fix(invoices): accept USD/GBP payment accounts without an IBAN (#1649)

Payment accounts per currency required an IBAN for every non-SEK
currency. USD (ABA routing number) and GBP (sort code) accounts have no
IBAN, so a Wise US or UK receiving account could only be saved by
pasting an IBAN from another currency, which then printed on the invoice
and misrouted the payment.

- InvoicePaymentAccount gains bank_code (routing number / sort code) and
  foreign_account_number; JSONB column, no migration.
- Rule, shared by the Zod schema, the client validation and
  hasUsableInvoicePaymentAccount: a foreign account is usable with an
  IBAN, or, only for NON_IBAN_CURRENCIES (USD, GBP), with bank_code +
  foreign_account_number + BIC. EUR/NOK/DKK still require IBAN.
- Settings: the two fields appear only for USD/GBP with the identifier
  named per currency (Routing number (ABA) / Sort code), a hint that IBAN
  may be left empty, and IBAN no longer marked required there.
- Invoice PDF renders the routing row with the same per-currency label
  plus the foreign account number, in both sv and en.

Reported via gnubok_feedback 2026-08-03.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-17 22:23:36 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5
parent 76b8d5c100
commit 798a76ed7a
10 changed files with 323 additions and 13 deletions
+12
View File
@@ -217,6 +217,14 @@ export interface InvoicePaymentAccount {
swish: string | null
iban: string | null
bic: string | null
/**
* Foreign non-IBAN routing: ABA routing number (USD), sort code (GBP),
* BSB (AUD) or a comparable national bank code. Only meaningful together
* with foreign_account_number + bic on a non-SEK account.
*/
bank_code?: string | null
/** Foreign account number for non-IBAN countries (US/UK/AU/CA style). */
foreign_account_number?: string | null
}
// Profile (extends auth.users)
@@ -335,6 +343,10 @@ export interface CompanySettings {
swish: string | null
iban: string | null
bic: string | null
// Foreign non-IBAN routing, only ever populated on the render-time copy
// produced by companyWithInvoicePaymentAccount (never a DB column).
bank_code?: string | null
foreign_account_number?: string | null
// Invoice payment instructions keyed by the currency they can receive.
// Legacy bank fields above remain the SEK fallback for older companies.
invoice_payment_accounts?: Partial<Record<Currency, InvoicePaymentAccount>>