fix: pending/paid invoices
This commit is contained in:
parent
d37f1d5dfe
commit
37a491cf79
4 changed files with 35 additions and 9 deletions
15
asxpio.rb
15
asxpio.rb
|
|
@ -202,10 +202,11 @@ class AsxpioWeb < Sinatra::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
invoice = Invoice.build(@form_values)
|
invoice = Invoice.build(@form_values)
|
||||||
pdf_bytes = InvoicePdf.render(invoice)
|
# Base key (no suffix); the two status variants get -pending/-paid appended.
|
||||||
pdf_key = "invoices/#{invoice.number}-#{invoice.uuid}.pdf"
|
invoice.pdf_key = "invoices/#{invoice.number}-#{invoice.uuid}.pdf"
|
||||||
S3.put(pdf_key, pdf_bytes)
|
%w[pending paid].each do |st|
|
||||||
invoice.pdf_key = pdf_key
|
S3.put(invoice.pdf_key_for(st), InvoicePdf.render(invoice, status: st))
|
||||||
|
end
|
||||||
invoice.save_changes
|
invoice.save_changes
|
||||||
|
|
||||||
redirect "/admin/invoices/#{invoice.uuid}"
|
redirect "/admin/invoices/#{invoice.uuid}"
|
||||||
|
|
@ -237,7 +238,11 @@ class AsxpioWeb < Sinatra::Base
|
||||||
|
|
||||||
get '/i/:uuid/pdf' do
|
get '/i/:uuid/pdf' do
|
||||||
invoice = Invoice[uuid: params[:uuid]] or halt 404
|
invoice = Invoice[uuid: params[:uuid]] or halt 404
|
||||||
url = S3.presigned_url(invoice.pdf_key,
|
# Prefer the status variant; fall back to the legacy single-PDF key for
|
||||||
|
# invoices created before the pending/paid split.
|
||||||
|
key = invoice.current_pdf_key
|
||||||
|
key = invoice.pdf_key unless S3.exists?(key)
|
||||||
|
url = S3.presigned_url(key,
|
||||||
expires_in: 300,
|
expires_in: 300,
|
||||||
filename: "#{invoice.number}.pdf")
|
filename: "#{invoice.number}.pdf")
|
||||||
redirect url, 302
|
redirect url, 302
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,17 @@ class Invoice < Sequel::Model(:invoices)
|
||||||
paid? ? 'paid' : 'pending'
|
paid? ? 'paid' : 'pending'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Both status variants are pre-rendered at creation; `pdf_key` is the base
|
||||||
|
# path (no suffix). The download route picks a variant by current status.
|
||||||
|
def pdf_key_for(status)
|
||||||
|
base = pdf_key.sub(/\.pdf\z/, '')
|
||||||
|
"#{base}-#{status}.pdf"
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_pdf_key
|
||||||
|
pdf_key_for(status)
|
||||||
|
end
|
||||||
|
|
||||||
def total
|
def total
|
||||||
BigDecimal(subtotal.to_s)
|
BigDecimal(subtotal.to_s)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,15 @@ class InvoicePdf
|
||||||
COLOR_RULE = 'DADADA'.freeze
|
COLOR_RULE = 'DADADA'.freeze
|
||||||
COLOR_ACCENT = '1A1A1A'.freeze
|
COLOR_ACCENT = '1A1A1A'.freeze
|
||||||
|
|
||||||
def self.render(invoice)
|
# `status` overrides the status shown in the PDF (e.g. to pre-render a "paid"
|
||||||
new(invoice).render
|
# copy before any payment date exists). Defaults to the invoice's live status.
|
||||||
|
def self.render(invoice, status: nil)
|
||||||
|
new(invoice, status: status).render
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(invoice)
|
def initialize(invoice, status: nil)
|
||||||
@invoice = invoice
|
@invoice = invoice
|
||||||
|
@status = status || invoice.status
|
||||||
end
|
end
|
||||||
|
|
||||||
def render
|
def render
|
||||||
|
|
@ -155,7 +158,7 @@ class InvoicePdf
|
||||||
['ISSUED', @invoice.issued_on.strftime('%Y-%m-%d')],
|
['ISSUED', @invoice.issued_on.strftime('%Y-%m-%d')],
|
||||||
['DUE', @invoice.due_on.strftime('%Y-%m-%d')],
|
['DUE', @invoice.due_on.strftime('%Y-%m-%d')],
|
||||||
['CURRENCY', @invoice.currency],
|
['CURRENCY', @invoice.currency],
|
||||||
['STATUS', @invoice.status.upcase]
|
['STATUS', @status.upcase]
|
||||||
]
|
]
|
||||||
col_w = pdf.bounds.width / cells.size.to_f
|
col_w = pdf.bounds.width / cells.size.to_f
|
||||||
top = pdf.cursor
|
top = pdf.cursor
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,13 @@ module S3
|
||||||
key
|
key
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def exists?(key)
|
||||||
|
client.head_object(bucket: bucket, key: key)
|
||||||
|
true
|
||||||
|
rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::NoSuchKey
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
def presigned_url(key, expires_in: 300, filename: nil)
|
def presigned_url(key, expires_in: 300, filename: nil)
|
||||||
params = { bucket: bucket, key: key }
|
params = { bucket: bucket, key: key }
|
||||||
if filename
|
if filename
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue