@happyvertical/smrt-commerce 0.56.1 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/AGENTS.md +24 -11
  2. package/README.md +159 -93
  3. package/agents/accounting-snapshot-mapper.md +3 -3
  4. package/agents/commercial-ui.md +2 -2
  5. package/agents/contract-money.md +9 -6
  6. package/agents/cost-billing.md +3 -6
  7. package/agents/customer-vendor-ui.md +6 -1
  8. package/agents/document-money.md +59 -31
  9. package/agents/invoice-calculations.md +31 -56
  10. package/agents/invoice-preparation.md +62 -73
  11. package/agents/invoice-quantity.md +9 -21
  12. package/agents/minor-unit-migration.md +4 -4
  13. package/agents/money-calculator.md +7 -8
  14. package/agents/money-model.md +18 -22
  15. package/agents/money-upgrade.md +92 -0
  16. package/agents/revenue-journal.md +2 -2
  17. package/agents/tax-codes.md +17 -14
  18. package/agents/tax-summary.md +12 -8
  19. package/dist/billing/period-close.d.ts.map +1 -1
  20. package/dist/billing/runtime.d.ts +5 -2
  21. package/dist/billing/runtime.d.ts.map +1 -1
  22. package/dist/chunks/{ContractLineItemCollection-DYjhj_pU.js → ContractLineItemCollection-BZcrlrrY.js} +22 -27
  23. package/dist/chunks/ContractLineItemCollection-BZcrlrrY.js.map +1 -0
  24. package/dist/chunks/{CustomerCollection-DQIujn4f.js → CustomerCollection-BIPH2ZUx.js} +3 -3
  25. package/dist/chunks/{CustomerCollection-DQIujn4f.js.map → CustomerCollection-BIPH2ZUx.js.map} +1 -1
  26. package/dist/chunks/{DocumentTaxCollection-BEpoqXAQ.js → DocumentTaxCollection-DDzlywMW.js} +41 -14
  27. package/dist/chunks/DocumentTaxCollection-DDzlywMW.js.map +1 -0
  28. package/dist/chunks/{InvoiceCollection-CKQflFjc.js → InvoiceCollection-cinzAqt6.js} +53 -164
  29. package/dist/chunks/InvoiceCollection-cinzAqt6.js.map +1 -0
  30. package/dist/chunks/{TaxCodeCollection-DOpzW4y8.js → TaxCodeCollection-DaBOPG9c.js} +11 -4
  31. package/dist/chunks/{TaxCodeCollection-DOpzW4y8.js.map → TaxCodeCollection-DaBOPG9c.js.map} +1 -1
  32. package/dist/chunks/{TaxComponentCollection-Cs2uXwEl.js → TaxComponentCollection-C4zxnyVu.js} +3 -3
  33. package/dist/chunks/{TaxComponentCollection-Cs2uXwEl.js.map → TaxComponentCollection-C4zxnyVu.js.map} +1 -1
  34. package/dist/chunks/VendorCollection-D6ZcUYy8.js +100 -0
  35. package/dist/chunks/VendorCollection-D6ZcUYy8.js.map +1 -0
  36. package/dist/chunks/{allocation-integrity-DI3G16BN.js → allocation-integrity-WmWyXhtG.js} +6 -6
  37. package/dist/chunks/{allocation-integrity-DI3G16BN.js.map → allocation-integrity-WmWyXhtG.js.map} +1 -1
  38. package/dist/chunks/calculations-C9daQLsh.js +82 -0
  39. package/dist/chunks/calculations-C9daQLsh.js.map +1 -0
  40. package/dist/chunks/contract-money-EuToOghh.js +301 -0
  41. package/dist/chunks/contract-money-EuToOghh.js.map +1 -0
  42. package/dist/chunks/detect-CY9ufaFb.js +328 -0
  43. package/dist/chunks/detect-CY9ufaFb.js.map +1 -0
  44. package/dist/chunks/{document-money-DNVhDJyC.js → document-money-DV5t4vlK.js} +389 -63
  45. package/dist/chunks/document-money-DV5t4vlK.js.map +1 -0
  46. package/dist/chunks/{invoice-posting-BwV8g7z0.js → invoice-posting-C2i5dOVZ.js} +21 -23
  47. package/dist/chunks/invoice-posting-C2i5dOVZ.js.map +1 -0
  48. package/dist/chunks/{revenue-journal-DY9fro8E.js → revenue-journal-LLA9Kh_i.js} +3 -14
  49. package/dist/chunks/revenue-journal-LLA9Kh_i.js.map +1 -0
  50. package/dist/chunks/tenant-money-barrier-6TlqUeVj.js +255 -0
  51. package/dist/chunks/tenant-money-barrier-6TlqUeVj.js.map +1 -0
  52. package/dist/chunks/{types-LDETvQ1C.js → types-Bbm0Xflc.js} +2 -1
  53. package/dist/chunks/types-Bbm0Xflc.js.map +1 -0
  54. package/dist/chunks/{units-CNcjH_eE.js → units-8ElbjVZK.js} +18 -3
  55. package/dist/chunks/units-8ElbjVZK.js.map +1 -0
  56. package/dist/collections/ContractCollection.d.ts.map +1 -1
  57. package/dist/collections/ContractLineItemCollection.d.ts.map +1 -1
  58. package/dist/collections/InvoiceCollection.d.ts.map +1 -1
  59. package/dist/collections/InvoiceLineItemCollection.d.ts +0 -30
  60. package/dist/collections/InvoiceLineItemCollection.d.ts.map +1 -1
  61. package/dist/collections/TaxCodeCollection.d.ts +5 -1
  62. package/dist/collections/TaxCodeCollection.d.ts.map +1 -1
  63. package/dist/collections/TaxSettingsCollection.d.ts +15 -8
  64. package/dist/collections/TaxSettingsCollection.d.ts.map +1 -1
  65. package/dist/collections/TaxSummaryReportCollection.d.ts +3 -3
  66. package/dist/collections/TaxSummaryReportCollection.d.ts.map +1 -1
  67. package/dist/collections/index.d.ts +0 -1
  68. package/dist/collections/index.d.ts.map +1 -1
  69. package/dist/commerce-money-tools.d.ts.map +1 -1
  70. package/dist/contract-money.d.ts +1 -13
  71. package/dist/contract-money.d.ts.map +1 -1
  72. package/dist/document-money-internal.d.ts +7 -3
  73. package/dist/document-money-internal.d.ts.map +1 -1
  74. package/dist/document-money.d.ts +1 -11
  75. package/dist/document-money.d.ts.map +1 -1
  76. package/dist/index.d.ts +6 -5
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +686 -1656
  79. package/dist/index.js.map +1 -1
  80. package/dist/invoice-accounting-sync.d.ts.map +1 -1
  81. package/dist/invoice-mcp.d.ts +3 -3
  82. package/dist/invoice-mcp.d.ts.map +1 -1
  83. package/dist/invoice-posting.d.ts +11 -5
  84. package/dist/invoice-posting.d.ts.map +1 -1
  85. package/dist/invoice-record-screen.d.ts +1 -1
  86. package/dist/invoice-record-screen.d.ts.map +1 -1
  87. package/dist/invoices.d.ts +6 -1
  88. package/dist/invoices.d.ts.map +1 -1
  89. package/dist/invoices.js +2 -2
  90. package/dist/manifest.json +1041 -863
  91. package/dist/migrations/invoiceEditorStorage.d.ts +2 -4
  92. package/dist/migrations/invoiceEditorStorage.d.ts.map +1 -1
  93. package/dist/migrations/partyLinks.d.ts.map +1 -1
  94. package/dist/models/Contract.d.ts +10 -4
  95. package/dist/models/Contract.d.ts.map +1 -1
  96. package/dist/models/ContractLineItem.d.ts +9 -17
  97. package/dist/models/ContractLineItem.d.ts.map +1 -1
  98. package/dist/models/DocumentTax.d.ts.map +1 -1
  99. package/dist/models/Invoice.d.ts +18 -48
  100. package/dist/models/Invoice.d.ts.map +1 -1
  101. package/dist/models/InvoiceLineItem.d.ts +13 -32
  102. package/dist/models/InvoiceLineItem.d.ts.map +1 -1
  103. package/dist/models/TaxSettings.d.ts +0 -10
  104. package/dist/models/TaxSettings.d.ts.map +1 -1
  105. package/dist/models/index.d.ts +1 -2
  106. package/dist/models/index.d.ts.map +1 -1
  107. package/dist/playground.js +1 -1
  108. package/dist/playground.js.map +1 -1
  109. package/dist/recipes.d.ts +8 -11
  110. package/dist/recipes.d.ts.map +1 -1
  111. package/dist/revenue-journal.d.ts +0 -8
  112. package/dist/revenue-journal.d.ts.map +1 -1
  113. package/dist/smrt-knowledge.json +2886 -6121
  114. package/dist/svelte/components/InvoiceEditor.svelte +7 -148
  115. package/dist/svelte/components/InvoiceEditor.svelte.d.ts +4 -1
  116. package/dist/svelte/components/InvoiceEditor.svelte.d.ts.map +1 -1
  117. package/dist/svelte/components/InvoiceTotals.svelte +14 -118
  118. package/dist/svelte/components/InvoiceTotals.svelte.d.ts +4 -27
  119. package/dist/svelte/components/InvoiceTotals.svelte.d.ts.map +1 -1
  120. package/dist/svelte/components/MoneyInvoiceEditor.svelte +3 -23
  121. package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts +3 -26
  122. package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts.map +1 -1
  123. package/dist/svelte/index.d.ts +2 -3
  124. package/dist/svelte/index.d.ts.map +1 -1
  125. package/dist/svelte/index.js +1 -2
  126. package/dist/svelte/invoices/calculations.d.ts +3 -108
  127. package/dist/svelte/invoices/calculations.d.ts.map +1 -1
  128. package/dist/svelte/invoices/calculations.js +12 -309
  129. package/dist/svelte/invoices/messages.d.ts +1 -37
  130. package/dist/svelte/invoices/messages.d.ts.map +1 -1
  131. package/dist/svelte/invoices/messages.js +1 -37
  132. package/dist/svelte/invoices/money-editor.d.ts +1 -1
  133. package/dist/svelte/invoices/money-editor.d.ts.map +1 -1
  134. package/dist/svelte/invoices/types.d.ts +14 -114
  135. package/dist/svelte/invoices/types.d.ts.map +1 -1
  136. package/dist/svelte/playground/InvoicePreparationPreview.svelte +85 -94
  137. package/dist/svelte/playground/InvoicePreparationPreview.svelte.d.ts.map +1 -1
  138. package/dist/svelte/playground.js +1 -1
  139. package/dist/tax/index.d.ts +2 -1
  140. package/dist/tax/index.d.ts.map +1 -1
  141. package/dist/tax/standard-codes.d.ts +12 -0
  142. package/dist/tax/standard-codes.d.ts.map +1 -0
  143. package/dist/tax/tenant-bootstrap.d.ts +29 -0
  144. package/dist/tax/tenant-bootstrap.d.ts.map +1 -0
  145. package/dist/tenant-money-barrier.d.ts +12 -44
  146. package/dist/tenant-money-barrier.d.ts.map +1 -1
  147. package/dist/types/index.d.ts +11 -23
  148. package/dist/types/index.d.ts.map +1 -1
  149. package/dist/ui.js +1 -1
  150. package/dist/ui.js.map +1 -1
  151. package/dist/upgrade/detect.d.ts +129 -0
  152. package/dist/upgrade/detect.d.ts.map +1 -0
  153. package/dist/upgrade/money-v2.d.ts +81 -0
  154. package/dist/upgrade/money-v2.d.ts.map +1 -0
  155. package/package.json +14 -13
  156. package/agents/line-amount-migration.md +0 -50
  157. package/dist/chunks/ContractLineItemCollection-DYjhj_pU.js.map +0 -1
  158. package/dist/chunks/DocumentTaxCollection-BEpoqXAQ.js.map +0 -1
  159. package/dist/chunks/InvoiceCollection-CKQflFjc.js.map +0 -1
  160. package/dist/chunks/InvoiceLineItemCollection-CHm9zdqh.js +0 -467
  161. package/dist/chunks/InvoiceLineItemCollection-CHm9zdqh.js.map +0 -1
  162. package/dist/chunks/TaxSettingsCollection-BBTZDH1S.js +0 -319
  163. package/dist/chunks/TaxSettingsCollection-BBTZDH1S.js.map +0 -1
  164. package/dist/chunks/calculations-DaHR17il.js +0 -333
  165. package/dist/chunks/calculations-DaHR17il.js.map +0 -1
  166. package/dist/chunks/document-money-DNVhDJyC.js.map +0 -1
  167. package/dist/chunks/invoice-posting-BwV8g7z0.js.map +0 -1
  168. package/dist/chunks/revenue-journal-DY9fro8E.js.map +0 -1
  169. package/dist/chunks/tenant-money-barrier-DjRXgMnX.js +0 -135
  170. package/dist/chunks/tenant-money-barrier-DjRXgMnX.js.map +0 -1
  171. package/dist/chunks/types-LDETvQ1C.js.map +0 -1
  172. package/dist/chunks/units-CNcjH_eE.js.map +0 -1
  173. package/dist/collections/MoneyMigrationDocumentCollection.d.ts +0 -12
  174. package/dist/collections/MoneyMigrationDocumentCollection.d.ts.map +0 -1
  175. package/dist/migrations/commerceLineAmounts.d.ts +0 -84
  176. package/dist/migrations/commerceLineAmounts.d.ts.map +0 -1
  177. package/dist/models/MoneyMigrationDocument.d.ts +0 -28
  178. package/dist/models/MoneyMigrationDocument.d.ts.map +0 -1
  179. package/dist/svelte/components/InvoiceLineEditor.svelte +0 -92
  180. package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts +0 -8
  181. package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts.map +0 -1
  182. package/dist/svelte/invoices/fields.d.ts +0 -6
  183. package/dist/svelte/invoices/fields.d.ts.map +0 -1
  184. package/dist/svelte/invoices/fields.js +0 -22
  185. package/dist/tax/legacy.d.ts +0 -48
  186. package/dist/tax/legacy.d.ts.map +0 -1
@@ -0,0 +1,92 @@
1
+ # Money data upgrade
2
+
3
+ Commerce has one money model. It does not read money data written by an
4
+ earlier version, and it does not convert that data on the fly. It refuses it
5
+ and names the upgrade command. The operator steps are in the CLI guide,
6
+ [commerce money upgrade command](../../cli/agents/commerce-money-upgrade.md).
7
+
8
+ ## Detection
9
+
10
+ `src/upgrade/detect.ts` owns detection. Four shapes count as old data:
11
+
12
+ - **Old schema.** The database still has `tax_settings.money_model`,
13
+ `tax_settings.money_migration_id`, `*_line_items.legacy_amount`, or the
14
+ `commerce_money_migration_documents` table. This refuses the whole database.
15
+ - **Documents without a tenant.** An Invoice or Contract row, header or line,
16
+ with no tenant. The current model writes none, and the upgrade cannot convert
17
+ one: assign it to a tenant or delete it. This refuses the whole database and
18
+ keeps the old schema in place until it is resolved.
19
+ - **Tenant without settings.** A tenant has Invoice or Contract rows but no
20
+ `tax_settings` row. This refuses that tenant only.
21
+ - **Old-format documents.** An issued Invoice or Contract without a money
22
+ snapshot, or a line with neither a tax code nor a component snapshot. The
23
+ current model never writes either, so these stay detectable after `db:migrate --drop-columns`
24
+ removed the old columns. This refuses that tenant only.
25
+
26
+ `assertCommerceMoneySchemaCurrent(db)` checks the schema.
27
+ `assertTenantMoneyCurrent(db, tenantId)` checks the schema, then the tenant.
28
+ On PostgreSQL every cross-tenant scan runs on a connection of its own (opened
29
+ from the database URL), in a transaction that raises `smrt.system_context`,
30
+ so the caller's connection and row policies are never touched; concurrent
31
+ checks for one database and tenant share a single scan. Both cache a passing
32
+ result per database (keyed by its connection URL, so
33
+ request executors share it) and tenant, so the check runs once per process.
34
+ Invoice, Contract and line models also run the check from `initialize()` on
35
+ every row hydrated from the database, which covers unscoped reads and every
36
+ collection class, including generated STI subtype collections. A
37
+ tenantless collection read still checks the schema, and a tenant's first
38
+ `TaxSettings` row is refused while that tenant holds old documents. Every runtime money read and write, the money MCP tools, the tax
39
+ summary, and `ensureCommerceTenant()` call them first.
40
+
41
+ A refusal is a `CommerceDataNeedsUpgradeError` with `code`
42
+ `COMMERCE_DATA_NEEDS_UPGRADE`. Its message ends with the command, for example
43
+ `Run smrt db:upgrade-commerce-money --tenant-id <id> to upgrade it.`
44
+ `commerceMoneyUpgradeCommand(tenantId?)` builds that command text.
45
+
46
+ `findCommerceMoneyUpgradeNeeds(db)` scans the whole database. It is
47
+ operator-only: it ignores the caller's row permissions, so never wire it into
48
+ a principal-facing surface. It returns `oldSchema`, `tenantlessDocuments`
49
+ (rows to assign or delete) and each tenant that needs the upgrade, with a
50
+ reason (`legacy-marker`, `interrupted-migration`, `missing-settings`, or
51
+ `old-format-documents`).
52
+ `smrt db:status` uses it to report the `commerce-money-upgrade` error
53
+ precondition, so `smrt app doctor` reports `migration-required`.
54
+
55
+ ## Upgrade
56
+
57
+ `upgradeCommerceMoney(db, { tenantId? })` in `src/upgrade/money-v2.ts` is the
58
+ one-shot conversion behind `smrt db:upgrade-commerce-money`. Run the normal
59
+ schema migration first. Each tenant converts in its own transaction:
60
+
61
+ 1. Its tax settings row and standard codes are seeded.
62
+ 2. Each stored fractional rate maps to a code. A zero rate becomes `exempt`
63
+ for an exempt customer, otherwise `out-of-scope`. Any other rate becomes a
64
+ one-component `rate-<percent>` code, created once.
65
+ 3. Issued documents are backfilled from their stored values: line net, line
66
+ tax, tax-code snapshot, `DocumentTax` rows, and a money snapshot. No stored
67
+ total changes.
68
+ 4. Drafts are recomputed through the runtime from their prices. Only
69
+ old-format lines (no tax code and no component snapshot) are mapped; a
70
+ draft header keeps its amount type and rounding. The result lists each
71
+ draft whose total changed.
72
+
73
+ An issued document whose stored lines do not add up exactly to its stored
74
+ header fails its tenant. So do an invalid stored rate, an invoice posted under
75
+ the earlier version (its revenue journal carries that version's provenance,
76
+ which current posting and reversal refuse; void it and clear the link, or reset
77
+ the data), an existing `rate-<percent>` code or component that does not
78
+ mean exactly that rate, and an edited standard `exempt` or `out-of-scope`
79
+ code. Nothing in that tenant changes, and the result lists
80
+ each failing document. A tenant whose earlier
81
+ migration never finished also fails; roll it back with the version that started
82
+ it, or reset its data. Converted tenants are skipped on a rerun.
83
+
84
+ Once no tenant needs the upgrade, the old columns and table are dropped. The
85
+ upgrade leaves no mode flag. Read `failures` and `remaining` on the result; the
86
+ CLI exits nonzero on either. New `rate-<percent>` components have no liability
87
+ account and are listed in `componentsWithoutLiabilityAccount`; posting falls
88
+ back to the caller's `taxAccountId` until one is assigned.
89
+
90
+ The runtime never imports `money-v2.ts`. Delete the `upgrade/` directory, the
91
+ CLI command, and the detection call sites together once no supported version
92
+ can have written old-format data.
@@ -13,8 +13,8 @@ debit receivables and credit revenue/tax; signed credits naturally swap sides, a
13
13
  For inclusive documents, stored line net is `amountMinor - taxMinor`; for exclusive
14
14
  and no-tax pricing it is `amountMinor`. Revenue is grouped by each line's stored
15
15
  account, falling back to the caller's revenue account. Component tax uses the
16
- stored liability account and falls back to `taxAccountId`. A `legacy-*` code that
17
- needs this fallback returns a structured warning. Provider tax is posted once as
16
+ stored liability account and falls back to `taxAccountId`. The result has only
17
+ `entries`; there are no warnings. Provider tax is posted once as
18
18
  its own entry to `taxAccountId`. Zero-tax and null-component reporting rows do not
19
19
  produce entries.
20
20
 
@@ -4,23 +4,22 @@
4
4
  change a rate, archive the old component, create a replacement and update the
5
5
  editable `TaxCode.components` list. Never edit a used component's percent.
6
6
 
7
- Every tenant seeds `exempt`, `zero-rated`, `out-of-scope`, and
8
- `legacy-unreconciled`. Those kinds have no components because they report
9
- differently. A legacy zero rate means out-of-scope unless the linked customer
10
- was explicitly exempt; malformed or out-of-range legacy rates stay visible
11
- through `legacy-unreconciled` and the mapping report.
7
+ Every tenant seeds `exempt`, `zero-rated`, and `out-of-scope`
8
+ (`STANDARD_TAX_CODES`, seeded by `ensureTenantTaxCodes(db, tenantId)` in
9
+ `src/tax/standard-codes.ts`). Those kinds have no components because they
10
+ report differently. They are reserved: billing lines and zero rates rely on
11
+ them never carrying tax, so `ensureTenantTaxCodes` (and through it the
12
+ bootstrap, billing period close and the upgrade) refuses a standard code
13
+ whose kind or components were changed. `TaxCodeCollection.findByCode(code, tenantId?)` finds a
14
+ code by its tenant-unique `code`, optionally for an explicit tenant.
15
+ The [money data upgrade](money-upgrade.md) adds a one-component
16
+ `rate-<percent>` code for each nonzero rate it finds in earlier-version data.
12
17
 
13
18
  `TaxSettings` owns tenant defaults, tax registrations, default line amount type
14
19
  and rounding scope. Cookbook policies adapt the portable settings document;
15
- they do not replace persisted tax settings. The per-tenant migration marker is
16
- owned by the money-snapshot migration. Ordinary saves and generated creates
17
- cannot change it: a new instance whose tenant natural key would upsert over a
18
- `migrating` or `v2` row is refused rather than resetting that tenant to legacy.
19
- The ordinary save transaction locks and re-reads the tenant marker before its
20
- natural-key upsert, serializing that check with migration claim and activation.
21
- If the tenant has no marker to lock, its first ordinary save is insert-only: a
22
- concurrent migration that creates the marker wins and the stale save is refused
23
- instead of adopting and overwriting the migration-owned row.
20
+ they do not replace persisted tax settings. There is one settings row per
21
+ tenant, created once under a tenant lock (see
22
+ [document money](document-money.md#tenant-settings-and-bootstrap-4009)).
24
23
 
25
24
  `applyCommerceCookbookSettings(db, tenantId, cookbook)` is the explicit
26
25
  server-side activation boundary for core's portable `taxRate`, inclusion, and
@@ -34,6 +33,10 @@ import cookbook from './smrt.cookbook.json' with { type: 'json' };
34
33
  await applyCommerceCookbookSettings(db, session.tenantId, cookbook);
35
34
  ```
36
35
 
36
+ `ensureCommerceTenant(db, tenantId, { cookbook })` wraps this call with the
37
+ settings row and standard code seed; prefer it for a newly created tenant
38
+ (#4009).
39
+
37
40
  `smrt cookbook apply` writes project files and does not have a database or
38
41
  tenant, so it deliberately performs no storage writes. Activation creates or
39
42
  reuses a component and default tax code, then updates tenant `TaxSettings` in
@@ -32,8 +32,9 @@ movement to every component.
32
32
  ## Materialized document report path
33
33
 
34
34
  `TaxSummaryReport` is a tenant-scoped, manual materialized report. Its owner,
35
- `TaxSummaryReportCollection.refreshTaxSummary()`, refuses tenants whose
36
- `TaxSettings.moneyModel` is not `v2`: legacy and migrating documents are not a
35
+ `TaxSummaryReportCollection.refreshTaxSummary()`, requires a tenant and refuses
36
+ one whose money data needs the upgrade (`COMMERCE_DATA_NEEDS_UPGRADE`, see
37
+ [money data upgrade](money-upgrade.md)): earlier-version documents are not a
37
38
  complete stored-tax source. The caller injects the public Expense and Journal
38
39
  source adapters because commerce cannot depend on expenses; omitting either
39
40
  adapter is a refusal, never a zero-ITC fallback.
@@ -47,8 +48,10 @@ The Contract branch gets a bounded, hydrated candidate set from
47
48
  owner's descendant classifier before joining only those purchase ids to
48
49
  `document_taxes` on document id and tenant id. This preserves custom
49
50
  `PurchaseContract` descendants without hard-coding contract enums or party
50
- display names. Contract rows include every non-draft, non-cancelled frozen
51
- snapshot, including `DECLINED`; their `issueDate`, reference (falling back to
51
+ display names. Contract rows include non-draft, non-cancelled frozen snapshots,
52
+ including `DECLINED`, except `SupplierQuote` and its descendants; exclusion uses
53
+ the hydrated STI subtype rather than the mutable `contractType` scalar. Their
54
+ `issueDate`, reference (falling back to
52
55
  the id), and vendor party id are read from the frozen Contract. The query only
53
56
  returns stored snapshots and never recalculates tax. A nullable tax-code kind
54
57
  becomes an unassigned-source warning; it never becomes out-of-scope by
@@ -66,13 +69,14 @@ matching `DocumentTax.documentType` pairs: `invoice`/`invoice` or
66
69
  `credit_note`/`credit_note`. Credit rows retain positive stored values and pass
67
70
  through the aggregation's single credit sign step.
68
71
 
69
- Refresh holds the tenant `TaxSettings` parent lock through the v2 gate, all
70
- source reads, aggregation, and replacement. Every source-adapter call receives
72
+ Refresh holds the tenant `TaxSettings` parent lock through the upgrade check,
73
+ all source reads, aggregation, and replacement. Every source-adapter call receives
71
74
  the same transaction-bound database executor. Replacement rows use a stable
72
75
  UUID derived from tenant, period, currency, row kind, and dimension, so retry
73
76
  and concurrent same-period refreshes converge to one row set. Materialized
74
- `list`, `get`, `count`, and Invoice drilldowns all recheck the tenant's marker;
75
- `legacy` and `migrating` refuse even existing report rows.
77
+ `list`, `get`, `count`, and Invoice drilldowns all require a tenant context and
78
+ recheck it; a tenant that needs the upgrade is refused even for existing report
79
+ rows.
76
80
 
77
81
  Each document drilldown fact carries its printed invoice number or Contract
78
82
  reference, tenant-scoped customer/vendor party id, issue date, stored taxable
@@ -1 +1 @@
1
- {"version":3,"file":"period-close.d.ts","sourceRoot":"","sources":["../../src/billing/period-close.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,WAAW,EAAE,IAAI,CAAC;IAClB,8DAA8D;IAC9D,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,iDAAiD;IACjD,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,OAAO,GACP,MAAM,GACN,iBAAiB,GACjB,QAAQ,CAAC;AAEb,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,WAAW,EAAE,IAAI,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC;AAED,yEAAyE;AACzE,qBAAa,uBAAwB,SAAQ,KAAK;IACpC,QAAQ,CAAC,MAAM,EAAE,iBAAiB;gBAAzB,MAAM,EAAE,iBAAiB;CAW/C;AAmDD,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,GAAG,OAAa,GAAG,aAAa,CAQrE;AAkCD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,GAAG,MAAM,CAAC,EACxD,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAsED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,gBAAqB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAwE5B"}
1
+ {"version":3,"file":"period-close.d.ts","sourceRoot":"","sources":["../../src/billing/period-close.ts"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,WAAW,EAAE,IAAI,CAAC;IAClB,8DAA8D;IAC9D,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,iDAAiD;IACjD,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,OAAO,GACP,MAAM,GACN,iBAAiB,GACjB,QAAQ,CAAC;AAEb,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,WAAW,EAAE,IAAI,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC;AAED,yEAAyE;AACzE,qBAAa,uBAAwB,SAAQ,KAAK;IACpC,QAAQ,CAAC,MAAM,EAAE,iBAAiB;gBAAzB,MAAM,EAAE,iBAAiB;CAW/C;AAmDD,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,GAAG,OAAa,GAAG,aAAa,CAQrE;AAkCD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,GAAG,MAAM,CAAC,EACxD,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAsED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,gBAAqB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAwE5B"}
@@ -24,8 +24,11 @@ import { type BillingProvider, type BillingProviderCheckoutSession } from './pro
24
24
  import { type AutoTopUpFailureHook, type AutoTopUpHookOptions } from './top-up.js';
25
25
  /** Ledger accounts billing posts to, in the seller's books. */
26
26
  export interface BillingLedgerAccounts {
27
- /** Explicit currency of this ledger book; required for money-v2 posting. */
28
- bookCurrency?: string;
27
+ /**
28
+ * ISO 4217 currency of this ledger book. Invoices post only in this
29
+ * currency, so it must equal the seller's billing currency.
30
+ */
31
+ bookCurrency: string;
29
32
  /** Accounts receivable (debited when an invoice is issued). */
30
33
  arAccountId: string;
31
34
  /** Revenue (credited with the invoice subtotal). */
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/billing/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/billing/runtime.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { a as DOCUMENT_MONEY_READ_REBIND, o as DOCUMENT_MONEY_WRITE } from "./TaxSettingsCollection-BBTZDH1S.js";
3
- import { i as withTenantMoneyCollectionRead } from "./tenant-money-barrier-DjRXgMnX.js";
2
+ import { MoneyValidationError } from "../money.js";
3
+ import { a as assertCommerceMoneySchemaCurrent, f as DOCUMENT_MONEY_READ_REBIND, p as DOCUMENT_MONEY_WRITE } from "./detect-CY9ufaFb.js";
4
+ import { n as withTenantMoneyCollectionRead } from "./tenant-money-barrier-6TlqUeVj.js";
4
5
  import { SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
5
6
  import { TenantScoped, getTenantId, queryGlobal, queryWithGlobals, tenantId } from "@happyvertical/smrt-tenancy";
6
7
  //#region src/models/ContractLineItem.ts
@@ -54,9 +55,7 @@ var ContractLineItem = class extends SmrtObject {
54
55
  set taxComponents(value) {
55
56
  this.taxComponentsJson = JSON.stringify(value);
56
57
  }
57
- /** Exact sum of frozen component taxes, in integer minor units. */
58
58
  taxAmount = 0;
59
- legacyAmount = null;
60
59
  /** Stable issue/freeze identity, independent of lifecycle updated_at. */
61
60
  moneySnapshotId = "";
62
61
  amount = 0;
@@ -99,7 +98,6 @@ var ContractLineItem = class extends SmrtObject {
99
98
  if (options.taxComponentsJson !== void 0) this.taxComponentsJson = options.taxComponentsJson;
100
99
  if (options.taxComponents !== void 0) this.taxComponents = structuredClone(options.taxComponents);
101
100
  if (options.taxAmount !== void 0) this.taxAmount = options.taxAmount;
102
- if (options.legacyAmount !== void 0) this.legacyAmount = options.legacyAmount;
103
101
  if (options.moneySnapshotId !== void 0) this.moneySnapshotId = options.moneySnapshotId;
104
102
  if (options.amount !== void 0) this.amount = options.amount;
105
103
  if (options.productId !== void 0) this.productId = options.productId;
@@ -109,32 +107,26 @@ var ContractLineItem = class extends SmrtObject {
109
107
  if (options.billingPeriod !== void 0) this.billingPeriod = options.billingPeriod;
110
108
  if (options.sortOrder !== void 0) this.sortOrder = options.sortOrder;
111
109
  }
112
- /**
113
- * Calculate the line amount, in integer minor units.
114
- *
115
- * `quantity` is decimal and `taxRate` is a fraction, so the product is not
116
- * generally a whole number of minor units. Rounding happens here — at the
117
- * one boundary where a rate meets money — so that every value that reaches a
118
- * money column is already exact and every downstream comparison can be a
119
- * plain `===` instead of an epsilon tolerance (#2401).
120
- */
121
- calculateAmount() {
122
- const subtotal = this.quantity * this.unitPrice - this.discount;
123
- const tax = subtotal * this.taxRate;
124
- return Math.round(subtotal + tax);
110
+ async initialize() {
111
+ await super.initialize();
112
+ if (this.isPersisted) {
113
+ const { assertHydratedMoneyRowCurrent } = await import("./detect-CY9ufaFb.js").then((n) => n.c);
114
+ await assertHydratedMoneyRowCurrent(this);
115
+ }
116
+ return this;
125
117
  }
126
118
  async save() {
127
- const { saveContractLineItem } = await import("../index.js").then((n) => n.t);
119
+ const { saveContractLineItem } = await import("./contract-money-EuToOghh.js");
128
120
  return await saveContractLineItem(this);
129
121
  }
130
122
  /** @internal Contract aggregate persistence only. */
131
- async saveDerived(capability, legacy) {
123
+ async saveDerived(capability) {
132
124
  if (capability !== DOCUMENT_MONEY_WRITE) throw new Error("Contract line money write capability is required");
133
- if (legacy) this.amount = this.calculateAmount();
125
+ for (const [field2, value] of [["unitPrice", this.unitPrice], ["discount", this.discount]]) if (!Number.isSafeInteger(value)) throw new MoneyValidationError("UNSAFE_MONEY", `Contract line ${field2} ${value} must be a safe integer number of minor units`);
134
126
  return await super.save();
135
127
  }
136
128
  async delete(options = {}) {
137
- const { deleteContractLineItem } = await import("../index.js").then((n) => n.t);
129
+ const { deleteContractLineItem } = await import("./contract-money-EuToOghh.js");
138
130
  await deleteContractLineItem(this, options);
139
131
  }
140
132
  /** @internal Contract aggregate persistence only. */
@@ -166,16 +158,16 @@ __decorateClass([field({ description: "The order, quote or agreement this line b
166
158
  __decorateClass([field({ description: "What is being sold or bought on this line." })], ContractLineItem.prototype, "description", 2);
167
159
  __decorateClass([field({ description: "How many." })], ContractLineItem.prototype, "quantity", 2);
168
160
  __decorateClass([field({
169
- description: "The price of one, before tax.",
161
+ description: "The price of one, before discount; includes tax when the document's prices include tax.",
170
162
  ui: { format: "money" }
171
163
  })], ContractLineItem.prototype, "unitPrice", 2);
172
164
  __decorateClass([field({ ui: { format: "money" } })], ContractLineItem.prototype, "discount", 2);
173
165
  __decorateClass([field({ type: "decimal" })], ContractLineItem.prototype, "discountRate", 2);
174
166
  __decorateClass([field({ description: "The stored fractional tax rate for this line (0.05 means 5%)." })], ContractLineItem.prototype, "taxRate", 2);
175
167
  __decorateClass([foreignKey("TaxCode", { nullable: true })], ContractLineItem.prototype, "taxCodeId", 2);
176
- __decorateClass([field({ nullable: true })], ContractLineItem.prototype, "legacyAmount", 2);
168
+ __decorateClass([field({ ui: { format: "money" } })], ContractLineItem.prototype, "taxAmount", 2);
177
169
  __decorateClass([field({
178
- description: "The line total.",
170
+ description: "The line amount: net of discount, and including tax only when the document's prices include tax.",
179
171
  ui: { format: "money" }
180
172
  })], ContractLineItem.prototype, "amount", 2);
181
173
  __decorateClass([field({ description: "The product this line is for, if it is one you list." }), crossPackageRef("@happyvertical/smrt-products:Product")], ContractLineItem.prototype, "productId", 2);
@@ -199,7 +191,10 @@ var ContractLineItemCollection = class extends SmrtCollection {
199
191
  async withMoneyRead(operation) {
200
192
  const rootDb = this.db;
201
193
  const tenantId = getTenantId();
202
- if (!tenantId) return operation();
194
+ if (!tenantId) {
195
+ await assertCommerceMoneySchemaCurrent(rootDb);
196
+ return operation();
197
+ }
203
198
  const result = await withTenantMoneyCollectionRead(rootDb, tenantId, (boundDb) => this.withDatabase(boundDb, operation));
204
199
  if (result instanceof ContractLineItem) result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);
205
200
  else if (Array.isArray(result)) {
@@ -262,4 +257,4 @@ var ContractLineItemCollection = class extends SmrtCollection {
262
257
  //#endregion
263
258
  export { ContractLineItemCollection_exports as n, ContractLineItem as r, ContractLineItemCollection as t };
264
259
 
265
- //# sourceMappingURL=ContractLineItemCollection-DYjhj_pU.js.map
260
+ //# sourceMappingURL=ContractLineItemCollection-BZcrlrrY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractLineItemCollection-BZcrlrrY.js","names":["field"],"sources":["../../src/models/ContractLineItem.ts","../../src/collections/ContractLineItemCollection.ts"],"sourcesContent":["/**\n * ContractLineItem model - individual items on a contract\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_READ_REBIND,\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyReadRebindCapability,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport { MoneyValidationError } from '../money.js';\nimport type {\n ContractLineItemOptions,\n ContractTaxComponentSnapshot,\n} from '../types/index.js';\n\n/**\n * ContractLineItem represents a single line item on a contract.\n *\n * Line items contain the details of what is being sold/purchased,\n * including quantity, pricing, and optional subscription details.\n *\n * @example\n * ```typescript\n * const lineItem = await lineItems.create({\n * contractId: order.id,\n * description: 'Widget Pro',\n * quantity: 10,\n * unitPrice: 4999, // $49.99 in cents\n * taxRate: 0.08\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ContractLineItem extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /** @internal Collection read guard returns this snapshot on its root DB. */\n rebindMoneyRead(\n capability: DocumentMoneyReadRebindCapability,\n db: DatabaseInterface,\n ): this {\n if (capability !== DOCUMENT_MONEY_READ_REBIND)\n throw new Error(\n 'Contract line read rebinding requires the owning capability',\n );\n this._db = db;\n this.options.db = db;\n return this;\n }\n\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global line items\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Parent contract\n */\n @field({ description: 'The order, quote or agreement this line belongs to.' })\n @foreignKey('Contract', { role: 'items' })\n contractId: string = '';\n\n /**\n * Item description\n */\n @field({ description: 'What is being sold or bought on this line.' })\n description: string = '';\n\n /**\n * Quantity ordered. Decimal on purpose — contracts price fractional\n * quantities (hours, weight, bandwidth), as do invoice line items.\n */\n @field({ description: 'How many.' })\n quantity: number = 1.0;\n\n /**\n * Unit price before discount, in **integer minor units** (cents, satoshis),\n * in the document's pricing mode: tax-inclusive when its `lineAmountType`\n * is `inclusive`.\n *\n * The `= 0` initializer is load-bearing: SMRT maps an integer literal to\n * INTEGER and a decimal literal to DECIMAL. Money is exact, so `$49.99` is\n * `4999` (#2401).\n */\n @field({\n description:\n \"The price of one, before discount; includes tax when the document's prices include tax.\",\n ui: { format: 'money' },\n })\n unitPrice: number = 0;\n\n /**\n * Discount amount (flat, not percentage), in integer minor units (#2401).\n */\n @field({ ui: { format: 'money' } })\n discount: number = 0;\n\n discountType: 'none' | 'percent' | 'amount' = 'none';\n\n @field({ type: 'decimal' })\n discountRate = '0.0';\n\n /**\n * Tax rate as decimal (e.g., 0.08 for 8%). A rate is inherently fractional,\n * so it stays DECIMAL — INTEGER would truncate every meaningful value.\n */\n @field({\n description:\n 'The stored fractional tax rate for this line (0.05 means 5%).',\n })\n taxRate: number = 0.0;\n\n taxMode: 'inherit' | 'override' = 'inherit';\n\n @foreignKey('TaxCode', { nullable: true })\n taxCodeId: string | null = null;\n\n taxCodeCode: string | null = null;\n\n taxCodeName: string | null = null;\n\n taxComponentsJson: string | null = null;\n\n get taxComponents(): ContractTaxComponentSnapshot[] {\n if (this.taxComponentsJson === null) return [];\n try {\n const value: unknown = JSON.parse(this.taxComponentsJson);\n if (!Array.isArray(value)) return [];\n return value.filter(\n (entry): entry is ContractTaxComponentSnapshot =>\n !!entry &&\n typeof entry === 'object' &&\n typeof (entry as ContractTaxComponentSnapshot).taxComponentId ===\n 'string' &&\n typeof (entry as ContractTaxComponentSnapshot).name === 'string' &&\n typeof (entry as ContractTaxComponentSnapshot).percent === 'string' &&\n Number.isSafeInteger(\n (entry as ContractTaxComponentSnapshot).taxMinor,\n ),\n );\n } catch {\n return [];\n }\n }\n\n set taxComponents(value: ContractTaxComponentSnapshot[]) {\n this.taxComponentsJson = JSON.stringify(value);\n }\n\n /** Exact sum of frozen component taxes, in integer minor units. */\n @field({ ui: { format: 'money' } })\n taxAmount = 0;\n\n /** Stable issue/freeze identity, independent of lifecycle updated_at. */\n moneySnapshotId = '';\n\n /**\n * Line amount in integer minor units: net of discount and before tax for\n * `exclusive` / `none` documents, and tax-inclusive for `inclusive` ones;\n * {@link taxAmount} holds the tax. Derived by the Contract money aggregate\n * on every save.\n */\n @field({\n description:\n \"The line amount: net of discount, and including tax only when the document's prices include tax.\",\n ui: { format: 'money' },\n })\n amount: number = 0;\n\n /**\n * Optional product reference (cross-package, plain string)\n */\n @field({\n description: 'The product this line is for, if it is one you list.',\n })\n @crossPackageRef('@happyvertical/smrt-products:Product')\n productId: string = '';\n\n /**\n * SKU or item code\n */\n sku: string = '';\n\n /**\n * Start date (for lease/subscription items)\n */\n startDate: Date | null = null;\n\n /**\n * End date (for lease/subscription items)\n */\n endDate: Date | null = null;\n\n /**\n * Billing period (for subscriptions: 'monthly', 'yearly', etc.)\n */\n billingPeriod: string = '';\n\n /**\n * Sort order within the contract\n */\n sortOrder: number = 0;\n\n constructor(options: ContractLineItemOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.contractId !== undefined) this.contractId = options.contractId;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.quantity !== undefined) this.quantity = options.quantity;\n if (options.unitPrice !== undefined) this.unitPrice = options.unitPrice;\n if (options.discount !== undefined) this.discount = options.discount;\n if (options.discountType !== undefined)\n this.discountType = options.discountType;\n if (options.discountRate !== undefined)\n this.discountRate = options.discountRate;\n if (options.taxRate !== undefined) this.taxRate = options.taxRate;\n if (options.taxMode !== undefined) this.taxMode = options.taxMode;\n if (options.taxCodeId !== undefined) this.taxCodeId = options.taxCodeId;\n if (options.taxCodeCode !== undefined)\n this.taxCodeCode = options.taxCodeCode;\n if (options.taxCodeName !== undefined)\n this.taxCodeName = options.taxCodeName;\n if (options.taxComponentsJson !== undefined)\n this.taxComponentsJson = options.taxComponentsJson;\n if (options.taxComponents !== undefined)\n this.taxComponents = structuredClone(options.taxComponents);\n if (options.taxAmount !== undefined) this.taxAmount = options.taxAmount;\n if (options.moneySnapshotId !== undefined)\n this.moneySnapshotId = options.moneySnapshotId;\n if (options.amount !== undefined) this.amount = options.amount;\n if (options.productId !== undefined) this.productId = options.productId;\n if (options.sku !== undefined) this.sku = options.sku;\n if (options.startDate !== undefined) this.startDate = options.startDate;\n if (options.endDate !== undefined) this.endDate = options.endDate;\n if (options.billingPeriod !== undefined)\n this.billingPeriod = options.billingPeriod;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n }\n\n override async initialize(): Promise<this> {\n await super.initialize();\n // A row read from the database must not be old-format money data.\n if (this.isPersisted) {\n const { assertHydratedMoneyRowCurrent } = await import(\n '../upgrade/detect.js'\n );\n await assertHydratedMoneyRowCurrent(this);\n }\n return this;\n }\n\n override async save(): Promise<this> {\n const { saveContractLineItem } = await import('../contract-money.js');\n return (await saveContractLineItem(this)) as this;\n }\n\n /** @internal Contract aggregate persistence only. */\n async saveDerived(capability: DocumentMoneyWriteCapability): Promise<this> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Contract line money write capability is required');\n // Money is integer minor units: refuse a major-unit price before it can\n // reach the database (#2401), ahead of the aggregate recompute.\n for (const [field, value] of [\n ['unitPrice', this.unitPrice],\n ['discount', this.discount],\n ] as const)\n if (!Number.isSafeInteger(value))\n throw new MoneyValidationError(\n 'UNSAFE_MONEY',\n `Contract line ${field} ${value} must be a safe integer number of minor units`,\n );\n return (await super.save()) as this;\n }\n\n override async delete(\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n const { deleteContractLineItem } = await import('../contract-money.js');\n await deleteContractLineItem(this, options);\n }\n\n /** @internal Contract aggregate persistence only. */\n async deleteDerived(\n capability: DocumentMoneyWriteCapability,\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Contract line money write capability is required');\n await super.delete(options);\n }\n\n /**\n * Check if this is a subscription/recurring item\n */\n isRecurring(): boolean {\n return !!this.billingPeriod && !!this.startDate;\n }\n\n /**\n * Check if subscription is active\n */\n isSubscriptionActive(): boolean {\n if (!this.isRecurring()) return false;\n if (!this.startDate) return false;\n\n const now = new Date();\n if (now < this.startDate) return false;\n if (this.endDate && now > this.endDate) return false;\n\n return true;\n }\n}\n\nexport default ContractLineItem;\n","/**\n * ContractLineItemCollection - Collection manager for ContractLineItem objects\n * @packageDocumentation\n */\n\nimport {\n SmrtCollection,\n type SmrtListOptions,\n type SmrtObject,\n type SmrtSelectedRow,\n type SmrtSelectField,\n type SmrtStiReadScope,\n type SmrtWhereClause,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n queryGlobal,\n queryWithGlobals,\n} from '@happyvertical/smrt-tenancy';\nimport { DOCUMENT_MONEY_READ_REBIND } from '../document-money-internal.js';\nimport { ContractLineItem } from '../models/ContractLineItem.js';\nimport { withTenantMoneyCollectionRead } from '../tenant-money-barrier.js';\nimport { assertCommerceMoneySchemaCurrent } from '../upgrade/detect.js';\n\nexport class ContractLineItemCollection extends SmrtCollection<ContractLineItem> {\n static readonly _itemClass = ContractLineItem;\n\n private async withMoneyRead<T>(operation: () => Promise<T>): Promise<T> {\n const rootDb = this.db;\n const tenantId = getTenantId();\n if (!tenantId) {\n // Without a tenant, still refuse a database with old money storage.\n await assertCommerceMoneySchemaCurrent(rootDb);\n return operation();\n }\n const result = await withTenantMoneyCollectionRead(\n rootDb,\n tenantId,\n (boundDb) => this.withDatabase(boundDb, operation),\n );\n if (result instanceof ContractLineItem)\n result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n else if (Array.isArray(result))\n for (const item of result)\n if (item instanceof ContractLineItem)\n item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n return result;\n }\n\n override async get(\n filter: string | SmrtWhereClause<ContractLineItem>,\n options: Parameters<SmrtCollection<ContractLineItem>['get']>[1] = {},\n ): Promise<ContractLineItem | null> {\n return this.withMoneyRead(() => super.get(filter, options));\n }\n\n override async list<\n const Select extends readonly SmrtSelectField<ContractLineItem>[],\n >(\n options: Omit<SmrtListOptions<ContractLineItem>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<Record<string, unknown>[]>;\n override async list<\n const Select extends readonly SmrtSelectField<ContractLineItem>[],\n >(\n options: Omit<SmrtListOptions<ContractLineItem>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope?: undefined;\n },\n ): Promise<SmrtSelectedRow<ContractLineItem, Select>[]>;\n override async list(\n options: Omit<SmrtListOptions<ContractLineItem>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<SmrtObject[]>;\n override async list(options?: undefined): Promise<ContractLineItem[]>;\n override async list(\n options: Omit<SmrtListOptions<ContractLineItem>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope?: undefined;\n },\n ): Promise<ContractLineItem[]>;\n override async list(\n options:\n | (Omit<SmrtListOptions<ContractLineItem>, 'select'> & {\n select?: undefined;\n })\n | undefined,\n ): Promise<SmrtObject[]>;\n override async list(\n options: SmrtListOptions<ContractLineItem> | undefined,\n ): Promise<SmrtObject[] | Record<string, unknown>[]>;\n override async list(\n options: SmrtListOptions<ContractLineItem> = {},\n ): Promise<SmrtObject[] | Record<string, unknown>[]> {\n return this.withMoneyRead(() => super.list(options));\n }\n\n /**\n * Find contract line items by their parent contract.\n *\n * @param contractId - Contract ID\n * @returns Array of contract line items, sorted by sortOrder\n */\n async findByContract(contractId: string): Promise<ContractLineItem[]> {\n return await this.list({\n where: { contractId },\n orderBy: 'sortOrder ASC',\n });\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all contract line items belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of contract line items for the tenant\n */\n async findByTenant(tenantId: string): Promise<ContractLineItem[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global contract line items (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global contract line items\n */\n async findGlobal(): Promise<ContractLineItem[]> {\n return queryGlobal<ContractLineItem>(this);\n }\n\n /**\n * Find contract line items for a tenant including global line items.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global contract line items\n */\n async findWithGlobals(tenantId: string): Promise<ContractLineItem[]> {\n return queryWithGlobals<ContractLineItem>(\n this,\n tenantId,\n 'ContractLineItem.findWithGlobals',\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAkDO,IAAM,mBAAN,cAA+B,WAAW;;CAE/C,gBACE,YACA,IACM;EACN,IAAI,eAAe,4BACjB,MAAM,IAAI,MACR,6DACF;EACF,KAAK,MAAM;EACX,KAAK,QAAQ,KAAK;EAClB,OAAO;CACT;CAOA,WAA0B;CAO1B,aAAqB;CAMrB,cAAsB;CAOtB,WAAmB;CAgBnB,YAAoB;CAMpB,WAAmB;CAEnB,eAA8C;CAG9C,eAAe;CAUf,UAAkB;CAElB,UAAkC;CAGlC,YAA2B;CAE3B,cAA6B;CAE7B,cAA6B;CAE7B,oBAAmC;CAEnC,IAAI,gBAAgD;EAClD,IAAI,KAAK,sBAAsB,MAAM,OAAO,CAAC;EAC7C,IAAI;GACF,MAAM,QAAiB,KAAK,MAAM,KAAK,iBAAiB;GACxD,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;GACnC,OAAO,MAAM,QACV,UACC,CAAC,CAAC,SACF,OAAO,UAAU,YACjB,OAAQ,MAAuC,mBAC7C,YACF,OAAQ,MAAuC,SAAS,YACxD,OAAQ,MAAuC,YAAY,YAC3D,OAAO,cACJ,MAAuC,QAC1C,CACJ;EACF,QAAQ;GACN,OAAO,CAAC;EACV;CACF;CAEA,IAAI,cAAc,OAAuC;EACvD,KAAK,oBAAoB,KAAK,UAAU,KAAK;CAC/C;CAIA,YAAY;;CAGZ,kBAAkB;CAalB,SAAiB;CASjB,YAAoB;;;;CAKpB,MAAc;;;;CAKd,YAAyB;;;;CAKzB,UAAuB;;;;CAKvB,gBAAwB;;;;CAKxB,YAAoB;CAEpB,YAAY,UAAmC,CAAC,GAAG;EACjD,MAAM,OAAO;EACb,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;EAC5D,IAAI,QAAQ,eAAe,KAAA,GAAW,KAAK,aAAa,QAAQ;EAChE,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;EAC7B,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;EAC5D,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;EAC5D,IAAI,QAAQ,iBAAiB,KAAA,GAC3B,KAAK,eAAe,QAAQ;EAC9B,IAAI,QAAQ,iBAAiB,KAAA,GAC3B,KAAK,eAAe,QAAQ;EAC9B,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;EAC1D,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;EAC1D,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;EAC7B,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;EAC7B,IAAI,QAAQ,sBAAsB,KAAA,GAChC,KAAK,oBAAoB,QAAQ;EACnC,IAAI,QAAQ,kBAAkB,KAAA,GAC5B,KAAK,gBAAgB,gBAAgB,QAAQ,aAAa;EAC5D,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,oBAAoB,KAAA,GAC9B,KAAK,kBAAkB,QAAQ;EACjC,IAAI,QAAQ,WAAW,KAAA,GAAW,KAAK,SAAS,QAAQ;EACxD,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,QAAQ,KAAA,GAAW,KAAK,MAAM,QAAQ;EAClD,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;EAC1D,IAAI,QAAQ,kBAAkB,KAAA,GAC5B,KAAK,gBAAgB,QAAQ;EAC/B,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;CAChE;CAEA,MAAe,aAA4B;EACzC,MAAM,MAAM,WAAW;EAEvB,IAAI,KAAK,aAAa;GACpB,MAAM,EAAE,kCAAkC,MAAM,OAC9C,uBAAA,CAAA,MAAA,MAAA,EAAA,CAAA;GAEF,MAAM,8BAA8B,IAAI;EAC1C;EACA,OAAO;CACT;CAEA,MAAe,OAAsB;EACnC,MAAM,EAAE,yBAAyB,MAAM,OAAO;EAC9C,OAAQ,MAAM,qBAAqB,IAAI;CACzC;;CAGA,MAAM,YAAY,YAAyD;EACzE,IAAI,eAAe,sBACjB,MAAM,IAAI,MAAM,kDAAkD;EAGpE,KAAA,MAAW,CAACA,QAAO,UAAU,CAC3B,CAAC,aAAa,KAAK,SAAS,GAC5B,CAAC,YAAY,KAAK,QAAQ,CAC5B,GACE,IAAI,CAAC,OAAO,cAAc,KAAK,GAC7B,MAAM,IAAI,qBACR,gBACA,iBAAiBA,OAAK,GAAI,MAAK,8CACjC;EACJ,OAAQ,MAAM,MAAM,KAAK;CAC3B;CAEA,MAAe,OACb,UAAiD,CAAC,GACnC;EACf,MAAM,EAAE,2BAA2B,MAAM,OAAO;EAChD,MAAM,uBAAuB,MAAM,OAAO;CAC5C;;CAGA,MAAM,cACJ,YACA,UAAiD,CAAC,GACnC;EACf,IAAI,eAAe,sBACjB,MAAM,IAAI,MAAM,kDAAkD;EACpE,MAAM,MAAM,OAAO,OAAO;CAC5B;;;;CAKA,cAAuB;EACrB,OAAO,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC,KAAK;CACxC;;;;CAKA,uBAAgC;EAC9B,IAAI,CAAC,KAAK,YAAY,GAAG,OAAO;EAChC,IAAI,CAAC,KAAK,WAAW,OAAO;EAE5B,MAAM,sBAAM,IAAI,KAAK;EACrB,IAAI,MAAM,KAAK,WAAW,OAAO;EACjC,IAAI,KAAK,WAAW,MAAM,KAAK,SAAS,OAAO;EAE/C,OAAO;CACT;AACF;AAvRmD,cAAtC,kBAA6C,mBAAkB,8BAAA;AAoB1E,gBAAA,CADC,SAAS,EAAE,UAAU,KAAK,CAAC,CAAA,GAnBjB,iBAoBX,WAAA,YAAA,CAAA;AAOA,gBAAA,CAFC,MAAM,EAAE,aAAa,sDAAsD,CAAC,GAC5E,WAAW,YAAY,EAAE,MAAM,QAAQ,CAAC,CAAA,GA1B9B,iBA2BX,WAAA,cAAA,CAAA;AAMA,gBAAA,CADC,MAAM,EAAE,aAAa,6CAA6C,CAAC,CAAA,GAhCzD,iBAiCX,WAAA,eAAA,CAAA;AAOA,gBAAA,CADC,MAAM,EAAE,aAAa,YAAY,CAAC,CAAA,GAvCxB,iBAwCX,WAAA,YAAA,CAAA;AAgBA,gBAAA,CALC,MAAM;CACL,aACE;CACF,IAAI,EAAE,QAAQ,QAAQ;AACxB,CAAC,CAAA,GAvDU,iBAwDX,WAAA,aAAA,CAAA;AAMA,gBAAA,CADC,MAAM,EAAE,IAAI,EAAE,QAAQ,QAAQ,EAAE,CAAC,CAAA,GA7DvB,iBA8DX,WAAA,YAAA,CAAA;AAKA,gBAAA,CADC,MAAM,EAAE,MAAM,UAAU,CAAC,CAAA,GAlEf,iBAmEX,WAAA,gBAAA,CAAA;AAUA,gBAAA,CAJC,MAAM,EACL,aACE,gEACJ,CAAC,CAAA,GA5EU,iBA6EX,WAAA,WAAA,CAAA;AAKA,gBAAA,CADC,WAAW,WAAW,EAAE,UAAU,KAAK,CAAC,CAAA,GAjF9B,iBAkFX,WAAA,aAAA,CAAA;AAoCA,gBAAA,CADC,MAAM,EAAE,IAAI,EAAE,QAAQ,QAAQ,EAAE,CAAC,CAAA,GArHvB,iBAsHX,WAAA,aAAA,CAAA;AAgBA,gBAAA,CALC,MAAM;CACL,aACE;CACF,IAAI,EAAE,QAAQ,QAAQ;AACxB,CAAC,CAAA,GArIU,iBAsIX,WAAA,UAAA,CAAA;AASA,gBAAA,CAJC,MAAM,EACL,aAAa,uDACf,CAAC,GACA,gBAAgB,sCAAsC,CAAA,GA9I5C,iBA+IX,WAAA,aAAA,CAAA;AA/IW,mBAAN,gBAAA,CAPN,aAAa,EAAE,MAAM,WAAW,CAAC,GACjC,KAAK;CACJ,eAAe;CACf,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;CAAQ,EAAE;CAC9D,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAE;CAChC,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,gBAAA;;;;AC1BN,IAAM,6BAAN,cAAyC,eAAiC;CAC/E,OAAgB,aAAa;CAE7B,MAAc,cAAiB,WAAyC;EACtE,MAAM,SAAS,KAAK;EACpB,MAAM,WAAW,YAAY;EAC7B,IAAI,CAAC,UAAU;GAEb,MAAM,iCAAiC,MAAM;GAC7C,OAAO,UAAU;EACnB;EACA,MAAM,SAAS,MAAM,8BACnB,QACA,WACC,YAAY,KAAK,aAAa,SAAS,SAAS,CACnD;EACA,IAAI,kBAAkB,kBACpB,OAAO,gBAAgB,4BAA4B,MAAM;OAAA,IAClD,MAAM,QAAQ,MAAM;QAC3B,MAAW,QAAQ,QACjB,IAAI,gBAAgB,kBAClB,KAAK,gBAAgB,4BAA4B,MAAM;EAAA;EAC7D,OAAO;CACT;CAEA,MAAe,IACb,QACA,UAAkE,CAAC,GACjC;EAClC,OAAO,KAAK,oBAAoB,MAAM,IAAI,QAAQ,OAAO,CAAC;CAC5D;CA2CA,MAAe,KACb,UAA6C,CAAC,GACK;EACnD,OAAO,KAAK,oBAAoB,MAAM,KAAK,OAAO,CAAC;CACrD;;;;;;;CAQA,MAAM,eAAe,YAAiD;EACpE,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,WAAW;GACpB,SAAS;EACX,CAAC;CACH;;;;;;;CAYA,MAAM,aAAa,UAA+C;EAChE,OAAO,KAAK,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;CAC1C;;;;;;;;;;CAWA,MAAM,aAA0C;EAC9C,OAAO,YAA8B,IAAI;CAC3C;;;;;;;;;;CAWA,MAAM,gBAAgB,UAA+C;EACnE,OAAO,iBACL,MACA,UACA,kCACF;CACF;AACF"}
@@ -1,5 +1,5 @@
1
- import { x as Customer } from "./DocumentTaxCollection-BEpoqXAQ.js";
2
- import { r as CustomerStatus } from "./types-LDETvQ1C.js";
1
+ import { C as Customer } from "./DocumentTaxCollection-DDzlywMW.js";
2
+ import { r as CustomerStatus } from "./types-Bbm0Xflc.js";
3
3
  import { SmrtCollection } from "@happyvertical/smrt-core";
4
4
  import { queryGlobal, queryWithGlobals } from "@happyvertical/smrt-tenancy";
5
5
  //#region src/collections/CustomerCollection.ts
@@ -96,4 +96,4 @@ var CustomerCollection = class extends SmrtCollection {
96
96
  //#endregion
97
97
  export { CustomerCollection as t };
98
98
 
99
- //# sourceMappingURL=CustomerCollection-DQIujn4f.js.map
99
+ //# sourceMappingURL=CustomerCollection-BIPH2ZUx.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CustomerCollection-DQIujn4f.js","names":[],"sources":["../../src/collections/CustomerCollection.ts"],"sourcesContent":["/**\n * CustomerCollection - Collection manager for Customer objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Customer } from '../models/Customer.js';\nimport { CustomerStatus } from '../types/index.js';\n\nexport class CustomerCollection extends SmrtCollection<Customer> {\n static readonly _itemClass = Customer;\n\n /**\n * Find customers by profile ID\n *\n * @param profileId - Profile ID from smrt-profiles\n * @returns Array of customers linked to this profile\n */\n async findByProfile(profileId: string): Promise<Customer[]> {\n return await this.list({\n where: { profileId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active customers\n *\n * @returns Array of active customers\n */\n async findActive(): Promise<Customer[]> {\n return await this.list({\n where: { status: CustomerStatus.ACTIVE },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find customers by status\n *\n * @param status - Customer status\n * @returns Array of customers\n */\n async findByStatus(status: CustomerStatus): Promise<Customer[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Get or create a customer for a profile\n *\n * @param profileId - Profile ID\n * @param defaults - Default values if creating\n * @returns Customer\n */\n async getOrCreateForProfile(\n profileId: string,\n defaults: Partial<{\n creditLimit: number;\n paymentTerms: string;\n }> = {},\n ): Promise<Customer> {\n const existing = await this.findByProfile(profileId);\n if (existing.length > 0) {\n return existing[0];\n }\n\n const customer = await this.create({\n profileId,\n creditLimit: defaults.creditLimit ?? 0,\n paymentTerms: defaults.paymentTerms ?? '',\n status: CustomerStatus.ACTIVE,\n });\n await customer.save();\n return customer;\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all customers belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of customers for the tenant\n */\n async findByTenant(tenantId: string): Promise<Customer[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global customers (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global customers\n */\n async findGlobal(): Promise<Customer[]> {\n return queryGlobal<Customer>(this);\n }\n\n /**\n * Find customers for a tenant including global customers.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global customers\n */\n async findWithGlobals(tenantId: string): Promise<Customer[]> {\n return queryWithGlobals<Customer>(\n this,\n tenantId,\n 'Customer.findWithGlobals',\n );\n }\n}\n"],"mappings":";;;;;AAUO,IAAM,qBAAN,cAAiC,eAAyB;CAC/D,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,cAAc,WAAwC;EAC1D,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,UAAU;GACnB,SAAS;EACX,CAAC;CACH;;;;;;CAOA,MAAM,aAAkC;EACtC,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,QAAQ,eAAe,OAAO;GACvC,SAAS;EACX,CAAC;CACH;;;;;;;CAQA,MAAM,aAAa,QAA6C;EAC9D,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,OAAO;GAChB,SAAS;EACX,CAAC;CACH;;;;;;;;CASA,MAAM,sBACJ,WACA,WAGK,CAAC,GACa;EACnB,MAAM,WAAW,MAAM,KAAK,cAAc,SAAS;EACnD,IAAI,SAAS,SAAS,GACpB,OAAO,SAAS;EAGlB,MAAM,WAAW,MAAM,KAAK,OAAO;GACjC;GACA,aAAa,SAAS,eAAe;GACrC,cAAc,SAAS,gBAAgB;GACvC,QAAQ,eAAe;EACzB,CAAC;EACD,MAAM,SAAS,KAAK;EACpB,OAAO;CACT;;;;;;;CAYA,MAAM,aAAa,UAAuC;EACxD,OAAO,KAAK,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;CAC1C;;;;;;;;;;CAWA,MAAM,aAAkC;EACtC,OAAO,YAAsB,IAAI;CACnC;;;;;;;;;;CAWA,MAAM,gBAAgB,UAAuC;EAC3D,OAAO,iBACL,MACA,UACA,0BACF;CACF;AACF"}
1
+ {"version":3,"file":"CustomerCollection-BIPH2ZUx.js","names":[],"sources":["../../src/collections/CustomerCollection.ts"],"sourcesContent":["/**\n * CustomerCollection - Collection manager for Customer objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Customer } from '../models/Customer.js';\nimport { CustomerStatus } from '../types/index.js';\n\nexport class CustomerCollection extends SmrtCollection<Customer> {\n static readonly _itemClass = Customer;\n\n /**\n * Find customers by profile ID\n *\n * @param profileId - Profile ID from smrt-profiles\n * @returns Array of customers linked to this profile\n */\n async findByProfile(profileId: string): Promise<Customer[]> {\n return await this.list({\n where: { profileId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active customers\n *\n * @returns Array of active customers\n */\n async findActive(): Promise<Customer[]> {\n return await this.list({\n where: { status: CustomerStatus.ACTIVE },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find customers by status\n *\n * @param status - Customer status\n * @returns Array of customers\n */\n async findByStatus(status: CustomerStatus): Promise<Customer[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Get or create a customer for a profile\n *\n * @param profileId - Profile ID\n * @param defaults - Default values if creating\n * @returns Customer\n */\n async getOrCreateForProfile(\n profileId: string,\n defaults: Partial<{\n creditLimit: number;\n paymentTerms: string;\n }> = {},\n ): Promise<Customer> {\n const existing = await this.findByProfile(profileId);\n if (existing.length > 0) {\n return existing[0];\n }\n\n const customer = await this.create({\n profileId,\n creditLimit: defaults.creditLimit ?? 0,\n paymentTerms: defaults.paymentTerms ?? '',\n status: CustomerStatus.ACTIVE,\n });\n await customer.save();\n return customer;\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all customers belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of customers for the tenant\n */\n async findByTenant(tenantId: string): Promise<Customer[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global customers (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global customers\n */\n async findGlobal(): Promise<Customer[]> {\n return queryGlobal<Customer>(this);\n }\n\n /**\n * Find customers for a tenant including global customers.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global customers\n */\n async findWithGlobals(tenantId: string): Promise<Customer[]> {\n return queryWithGlobals<Customer>(\n this,\n tenantId,\n 'Customer.findWithGlobals',\n );\n }\n}\n"],"mappings":";;;;;AAUO,IAAM,qBAAN,cAAiC,eAAyB;CAC/D,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,cAAc,WAAwC;EAC1D,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,UAAU;GACnB,SAAS;EACX,CAAC;CACH;;;;;;CAOA,MAAM,aAAkC;EACtC,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,QAAQ,eAAe,OAAO;GACvC,SAAS;EACX,CAAC;CACH;;;;;;;CAQA,MAAM,aAAa,QAA6C;EAC9D,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,OAAO;GAChB,SAAS;EACX,CAAC;CACH;;;;;;;;CASA,MAAM,sBACJ,WACA,WAGK,CAAC,GACa;EACnB,MAAM,WAAW,MAAM,KAAK,cAAc,SAAS;EACnD,IAAI,SAAS,SAAS,GACpB,OAAO,SAAS;EAGlB,MAAM,WAAW,MAAM,KAAK,OAAO;GACjC;GACA,aAAa,SAAS,eAAe;GACrC,cAAc,SAAS,gBAAgB;GACvC,QAAQ,eAAe;EACzB,CAAC;EACD,MAAM,SAAS,KAAK;EACpB,OAAO;CACT;;;;;;;CAYA,MAAM,aAAa,UAAuC;EACxD,OAAO,KAAK,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;CAC1C;;;;;;;;;;CAWA,MAAM,aAAkC;EACtC,OAAO,YAAsB,IAAI;CACnC;;;;;;;;;;CAWA,MAAM,gBAAgB,UAAuC;EAC3D,OAAO,iBACL,MACA,UACA,0BACF;CACF;AACF"}
@@ -1,8 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { i as CustomerType, n as ContractType, p as VendorStatus, r as CustomerStatus, t as ContractStatus } from "./types-LDETvQ1C.js";
2
+ import { i as CustomerType, n as ContractType, p as VendorStatus, r as CustomerStatus, t as ContractStatus } from "./types-Bbm0Xflc.js";
3
3
  import { MoneyValidationError, assertIntegerMinorUnits } from "../money.js";
4
- import { a as DOCUMENT_MONEY_READ_REBIND, o as DOCUMENT_MONEY_WRITE } from "./TaxSettingsCollection-BBTZDH1S.js";
5
- import { i as withTenantMoneyCollectionRead } from "./tenant-money-barrier-DjRXgMnX.js";
4
+ import { a as assertCommerceMoneySchemaCurrent, f as DOCUMENT_MONEY_READ_REBIND, p as DOCUMENT_MONEY_WRITE } from "./detect-CY9ufaFb.js";
5
+ import { n as withTenantMoneyCollectionRead } from "./tenant-money-barrier-6TlqUeVj.js";
6
6
  import { SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
7
7
  import { TenantScoped, getTenantId, queryGlobal, queryWithGlobals, tenantId, withTenant } from "@happyvertical/smrt-tenancy";
8
8
  //#region src/party-contacts.ts
@@ -563,7 +563,7 @@ function classifyContractPurchase(contract) {
563
563
  return "vendorId" in contract;
564
564
  }
565
565
  function isContractSnapshotReportEligible(contract) {
566
- return contract.status !== ContractStatus.DRAFT && contract.status !== ContractStatus.CANCELLED;
566
+ return !(contract instanceof SupplierQuote) && contract.status !== ContractStatus.DRAFT && contract.status !== ContractStatus.CANCELLED;
567
567
  }
568
568
  var Contract = class extends SmrtObject {
569
569
  /** @internal Collection read guard returns this snapshot on its root DB. */
@@ -577,7 +577,6 @@ var Contract = class extends SmrtObject {
577
577
  contractType = ContractType.ORDER;
578
578
  status = ContractStatus.DRAFT;
579
579
  subtotal = 0;
580
- /** Informational sum of resolved line discounts, in integer minor units. */
581
580
  discountTotal = 0;
582
581
  taxAmount = 0;
583
582
  totalAmount = 0;
@@ -672,7 +671,7 @@ var Contract = class extends SmrtObject {
672
671
  * Calculate and update totals from line items
673
672
  */
674
673
  async recalculateTotals() {
675
- const { recalculateContractTotals } = await import("../index.js").then((n) => n.t);
674
+ const { recalculateContractTotals } = await import("./contract-money-EuToOghh.js");
676
675
  await recalculateContractTotals(this);
677
676
  }
678
677
  /**
@@ -683,6 +682,10 @@ var Contract = class extends SmrtObject {
683
682
  */
684
683
  async initialize() {
685
684
  await super.initialize();
685
+ if (this.isPersisted) {
686
+ const { assertHydratedMoneyRowCurrent } = await import("./detect-CY9ufaFb.js").then((n) => n.c);
687
+ await assertHydratedMoneyRowCurrent(this);
688
+ }
686
689
  if (await this.isSaved()) loadedContractStatus.set(this, this.status);
687
690
  return this;
688
691
  }
@@ -698,7 +701,7 @@ var Contract = class extends SmrtObject {
698
701
  * write surface (#2401).
699
702
  */
700
703
  async save() {
701
- const { saveContract } = await import("../index.js").then((n) => n.t);
704
+ const { saveContract } = await import("./contract-money-EuToOghh.js");
702
705
  return await saveContract(this);
703
706
  }
704
707
  /** @internal Contract aggregate persistence only. */
@@ -761,6 +764,7 @@ __decorateClass$1([field({
761
764
  description: "The amount before tax.",
762
765
  ui: { format: "money" }
763
766
  })], Contract.prototype, "subtotal", 2);
767
+ __decorateClass$1([field({ ui: { format: "money" } })], Contract.prototype, "discountTotal", 2);
764
768
  __decorateClass$1([field({
765
769
  description: "The tax charged.",
766
770
  ui: { format: "money" }
@@ -815,7 +819,7 @@ var PurchaseContract = class extends Contract {
815
819
  }
816
820
  };
817
821
  __publicField$1(PurchaseContract, "__smrtPackage__", "@happyvertical/smrt-commerce");
818
- __decorateClass$1([foreignKey(Vendor, { description: "The vendor a purchase order is placed with." })], PurchaseContract.prototype, "vendorId", 2);
822
+ __decorateClass$1([foreignKey(Vendor, { description: "The vendor supplying this quote or purchase contract." })], PurchaseContract.prototype, "vendorId", 2);
819
823
  PurchaseContract = __decorateClass$1([TenantScoped({ mode: "optional" }), smrt({ abstract: true })], PurchaseContract);
820
824
  var Estimate = class extends SalesContract {
821
825
  customerId = null;
@@ -861,6 +865,17 @@ var Agreement = class extends SalesContract {
861
865
  __publicField$1(Agreement, "__smrtPackage__", "@happyvertical/smrt-commerce");
862
866
  __decorateClass$1([foreignKey(Customer, { required: true })], Agreement.prototype, "customerId", 2);
863
867
  Agreement = __decorateClass$1([TenantScoped({ mode: "optional" }), smrt()], Agreement);
868
+ var SupplierQuote = class extends PurchaseContract {
869
+ vendorId = null;
870
+ contractType = ContractType.SUPPLIER_QUOTE;
871
+ constructor(options = {}) {
872
+ super(options);
873
+ if (options.vendorId !== void 0) this.vendorId = options.vendorId;
874
+ }
875
+ };
876
+ __publicField$1(SupplierQuote, "__smrtPackage__", "@happyvertical/smrt-commerce");
877
+ __decorateClass$1([foreignKey(Vendor, { required: true })], SupplierQuote.prototype, "vendorId", 2);
878
+ SupplierQuote = __decorateClass$1([TenantScoped({ mode: "optional" }), smrt()], SupplierQuote);
864
879
  var PurchaseOrder = class extends PurchaseContract {
865
880
  vendorId = null;
866
881
  contractType = ContractType.PURCHASE_ORDER;
@@ -1105,7 +1120,10 @@ var ContractCollection = class extends SmrtCollection {
1105
1120
  async withMoneyRead(operation) {
1106
1121
  const rootDb = this.db;
1107
1122
  const tenantId = getTenantId();
1108
- if (!tenantId) return operation();
1123
+ if (!tenantId) {
1124
+ await assertCommerceMoneySchemaCurrent(rootDb);
1125
+ return operation();
1126
+ }
1109
1127
  const result = await withTenantMoneyCollectionRead(rootDb, tenantId, (boundDb) => this.withDatabase(boundDb, operation));
1110
1128
  if (result instanceof Contract) result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);
1111
1129
  else if (Array.isArray(result)) {
@@ -1386,9 +1404,18 @@ __decorateClass([field({
1386
1404
  nullable: true
1387
1405
  })], DocumentTax.prototype, "percent", 2);
1388
1406
  __decorateClass([field({ nullable: true })], DocumentTax.prototype, "liabilityAccountId", 2);
1389
- __decorateClass([field({ description: "Tax-exclusive base in integer minor units." })], DocumentTax.prototype, "taxableMinor", 2);
1390
- __decorateClass([field({ description: "Tax total in integer minor units." })], DocumentTax.prototype, "taxMinor", 2);
1391
- __decorateClass([field({ description: "Recoverable purchase tax in integer minor units." })], DocumentTax.prototype, "recoverableMinor", 2);
1407
+ __decorateClass([field({
1408
+ description: "Tax-exclusive base in integer minor units.",
1409
+ ui: { format: "money" }
1410
+ })], DocumentTax.prototype, "taxableMinor", 2);
1411
+ __decorateClass([field({
1412
+ description: "Tax total in integer minor units.",
1413
+ ui: { format: "money" }
1414
+ })], DocumentTax.prototype, "taxMinor", 2);
1415
+ __decorateClass([field({
1416
+ description: "Recoverable purchase tax in integer minor units.",
1417
+ ui: { format: "money" }
1418
+ })], DocumentTax.prototype, "recoverableMinor", 2);
1392
1419
  DocumentTax = __decorateClass([TenantScoped({ mode: "required" }), smrt({
1393
1420
  tableName: "document_taxes",
1394
1421
  conflictColumns: [
@@ -1634,6 +1661,6 @@ var DocumentTaxCollection = class extends SmrtCollection {
1634
1661
  }
1635
1662
  };
1636
1663
  //#endregion
1637
- export { savePartyContacts as A, PARTY_CONTACT_MAX_LENGTHS as C, applyPartyContactIntent as D, PartyContactValidationError as E, normalizePartyContacts as O, DEFAULT_PARTY_CONTACT_FIELD_NAMES as S, PartyContactPayloadError as T, SalesContract as _, SalesContractCollection as a, Vendor as b, Cart as c, Lease as d, LicenseSale as f, PurchaseOrder as g, PurchaseContract as h, ContractCollection as i, validatePartyContactRows as j, readPartyContactRows as k, Contract as l, ProductionOrder as m, DocumentTaxCollection_exports as n, PurchaseContractCollection as o, Order as p, DocumentTax as r, Agreement as s, DocumentTaxCollection as t, Estimate as u, WholesaleOrder as v, PartyContactPartyNotFoundError as w, Customer as x, classifyContractPurchase as y };
1664
+ export { normalizePartyContacts as A, Customer as C, PartyContactPayloadError as D, PartyContactPartyNotFoundError as E, savePartyContacts as M, validatePartyContactRows as N, PartyContactValidationError as O, Vendor as S, PARTY_CONTACT_MAX_LENGTHS as T, SalesContract as _, SalesContractCollection as a, classifyContractPurchase as b, Cart as c, Lease as d, LicenseSale as f, PurchaseOrder as g, PurchaseContract as h, ContractCollection as i, readPartyContactRows as j, applyPartyContactIntent as k, Contract as l, ProductionOrder as m, DocumentTaxCollection_exports as n, PurchaseContractCollection as o, Order as p, DocumentTax as r, Agreement as s, DocumentTaxCollection as t, Estimate as u, SupplierQuote as v, DEFAULT_PARTY_CONTACT_FIELD_NAMES as w, isContractSnapshotReportEligible as x, WholesaleOrder as y };
1638
1665
 
1639
- //# sourceMappingURL=DocumentTaxCollection-BEpoqXAQ.js.map
1666
+ //# sourceMappingURL=DocumentTaxCollection-DDzlywMW.js.map