* feat(customers): carry contact person and invoice copy recipients through migration
Extends the arcim-migration entity mapper, Fortnox provider mapper, canonical
DTOs, customer APIs (web + v1) and invoice send flows so contact person and
customer-level invoice CC/BCC addresses survive provider migrations. NULL
means unconfigured and empty means an explicit clear, so re-syncs enrich
legacy gaps without resurrecting deliberately removed values. Fortnox fixed
assets are split into a dedicated follow-up issue.
Fixes#1345
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(db): bump customer metadata migration past pack-slug version
Main already contains 20260803230000; keep new versions strictly newest so
Supabase branching applies them in order.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(customers): complete Customer type consumers and make enrichment payload resolvable
The preview-pdf mock customer and the makeCustomer fixture now carry the
three new metadata fields, fixing the type-check failure in Build (zero
extensions) and Vercel.
The enrichment update in the migration orchestrator now spells its payload
as an object literal typed CustomerMetadataEnrichment (absent keys drop at
serialization), so the phantom-column guard resolves the columns instead of
counting another unresolvable dynamic payload past its ceiling. The cc/bcc
guards also verify element types instead of casting.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Implements #914 (kundnummer on customers, printed on the invoice PDF).
- Migration: nullable text column customers.customer_number, no unique
constraint in v1 so existing rows and imports keep working.
- API: CreateCustomerSchema/UpdateCustomerSchema accept an optional
customer_number (trimmed, max 32 chars, nullable-then-optional so the
OpenAPI registry sees it as not required); create/update routes
persist it and normalize empty string to null so it can be cleared.
- v1 public API: customers create/detail/update round-trip the field
(insert and update field lists, response projections, response
schemas), and the invoices :send route fetches customer_number in its
explicit customer join so the emailed PDF matches the downloaded one
(the pdf route already selects customers(*)).
- UI: optional Kundnummer field in CustomerForm (next-intl keys in both
sv and en), wired into the edit dialog's initialData; read-only
Kundnummer row on the customer detail page's business-details card.
- Invoice PDF: renders "Kundnr:" / "Customer no.:" in the customer box
when set; the PDF reads the live customers join, so no snapshot
column is needed.
- Tests: route tests cover 400 validation, trimming, clearing with
null/empty, and omit-leaves-untouched on POST and PATCH; v1 tests
cover the create/update round-trip (insert/update payload + response
projection) and the :send customer-join projection.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>