One asset per invoice from a registry (lib/crypto_asset.rb): BTC, LTC,
ETH, XMR, SOL, ALGO, USDT/USDC on ERC-20/TRC-20/BEP-20/Solana/Algorand.
Migration 003 generalizes the ltc_* columns to crypto_* + crypto_coin
(existing LTC invoices backfilled). QR payload adapts per asset: BIP21
amount URIs where supported, bare address for tokens with a network
hint on the PDF. Default addresses come from the CRYPTO_ADDRESSES
secret (JSON code=>address); LTC_ADDRESS still works as legacy.
Sequel guards primary keys against mass assignment, so passing uuid: to
Invoice.new raised MassAssignmentRestriction and turned every invoice
creation into a 500. Build the instance with the rest of the fields, then
set uuid as an attribute before returning.
Sequel::Model wrapper over the invoices table. Three responsibilities:
- Invoice.build takes form params (client, currency, GEL rate, items array)
and returns an unsaved Invoice with a freshly-allocated number, normalized
line items, and computed subtotal.
- Invoice.allocate_number scans for the highest INV-<year>-NNNN and
increments. Single-process deploy means no contention; if that changes
this needs a DB-side sequence per year.
- Instance methods: paid?, status, total, total_gel for the PDF renderer
and the public landing page.
Items are stored as JSONB; qty and unit_price are kept as strings on the
way in/out so BigDecimal arithmetic stays exact through the JSON round-trip.