@happyvertical/smrt-commerce 0.56.2 → 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 (181) hide show
  1. package/AGENTS.md +24 -11
  2. package/README.md +137 -89
  3. package/agents/accounting-snapshot-mapper.md +3 -3
  4. package/agents/commercial-ui.md +2 -2
  5. package/agents/contract-money.md +9 -12
  6. package/agents/cost-billing.md +3 -6
  7. package/agents/customer-vendor-ui.md +1 -2
  8. package/agents/document-money.md +58 -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 +8 -6
  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--BrGMtNz.js → ContractLineItemCollection-BZcrlrrY.js} +19 -24
  23. package/dist/chunks/ContractLineItemCollection-BZcrlrrY.js.map +1 -0
  24. package/dist/chunks/{CustomerCollection-CjGaZSpf.js → CustomerCollection-BIPH2ZUx.js} +2 -2
  25. package/dist/chunks/{CustomerCollection-CjGaZSpf.js.map → CustomerCollection-BIPH2ZUx.js.map} +1 -1
  26. package/dist/chunks/{DocumentTaxCollection-KOkaQT2M.js → DocumentTaxCollection-DDzlywMW.js} +14 -7
  27. package/dist/chunks/DocumentTaxCollection-DDzlywMW.js.map +1 -0
  28. package/dist/chunks/{InvoiceCollection-BUe_8FT1.js → InvoiceCollection-cinzAqt6.js} +50 -161
  29. package/dist/chunks/InvoiceCollection-cinzAqt6.js.map +1 -0
  30. package/dist/chunks/{TaxCodeCollection-DF2eaJed.js → TaxCodeCollection-DaBOPG9c.js} +11 -4
  31. package/dist/chunks/{TaxCodeCollection-DF2eaJed.js.map → TaxCodeCollection-DaBOPG9c.js.map} +1 -1
  32. package/dist/chunks/{TaxComponentCollection-3x24xSNh.js → TaxComponentCollection-C4zxnyVu.js} +3 -3
  33. package/dist/chunks/{TaxComponentCollection-3x24xSNh.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-Cq0g6CfO.js → allocation-integrity-WmWyXhtG.js} +6 -6
  37. package/dist/chunks/{allocation-integrity-Cq0g6CfO.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-oUDvdjOf.js → document-money-DV5t4vlK.js} +388 -62
  45. package/dist/chunks/document-money-DV5t4vlK.js.map +1 -0
  46. package/dist/chunks/{invoice-posting-CF3fE_Ec.js → invoice-posting-C2i5dOVZ.js} +20 -22
  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-Bbm0Xflc.js.map +1 -1
  53. package/dist/chunks/{units-CNcjH_eE.js → units-8ElbjVZK.js} +18 -3
  54. package/dist/chunks/units-8ElbjVZK.js.map +1 -0
  55. package/dist/collections/ContractCollection.d.ts.map +1 -1
  56. package/dist/collections/ContractLineItemCollection.d.ts.map +1 -1
  57. package/dist/collections/InvoiceCollection.d.ts.map +1 -1
  58. package/dist/collections/InvoiceLineItemCollection.d.ts +0 -30
  59. package/dist/collections/InvoiceLineItemCollection.d.ts.map +1 -1
  60. package/dist/collections/TaxCodeCollection.d.ts +5 -1
  61. package/dist/collections/TaxCodeCollection.d.ts.map +1 -1
  62. package/dist/collections/TaxSettingsCollection.d.ts +15 -8
  63. package/dist/collections/TaxSettingsCollection.d.ts.map +1 -1
  64. package/dist/collections/TaxSummaryReportCollection.d.ts +3 -3
  65. package/dist/collections/TaxSummaryReportCollection.d.ts.map +1 -1
  66. package/dist/collections/index.d.ts +0 -1
  67. package/dist/collections/index.d.ts.map +1 -1
  68. package/dist/commerce-money-tools.d.ts.map +1 -1
  69. package/dist/contract-money.d.ts +1 -13
  70. package/dist/contract-money.d.ts.map +1 -1
  71. package/dist/document-money-internal.d.ts +7 -3
  72. package/dist/document-money-internal.d.ts.map +1 -1
  73. package/dist/document-money.d.ts +1 -11
  74. package/dist/document-money.d.ts.map +1 -1
  75. package/dist/index.d.ts +6 -5
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +667 -1650
  78. package/dist/index.js.map +1 -1
  79. package/dist/invoice-accounting-sync.d.ts.map +1 -1
  80. package/dist/invoice-mcp.d.ts +3 -3
  81. package/dist/invoice-mcp.d.ts.map +1 -1
  82. package/dist/invoice-posting.d.ts +11 -5
  83. package/dist/invoice-posting.d.ts.map +1 -1
  84. package/dist/invoice-record-screen.d.ts +1 -1
  85. package/dist/invoice-record-screen.d.ts.map +1 -1
  86. package/dist/invoices.d.ts +6 -1
  87. package/dist/invoices.d.ts.map +1 -1
  88. package/dist/invoices.js +2 -2
  89. package/dist/manifest.json +37 -765
  90. package/dist/migrations/invoiceEditorStorage.d.ts +2 -4
  91. package/dist/migrations/invoiceEditorStorage.d.ts.map +1 -1
  92. package/dist/models/Contract.d.ts.map +1 -1
  93. package/dist/models/ContractLineItem.d.ts +6 -22
  94. package/dist/models/ContractLineItem.d.ts.map +1 -1
  95. package/dist/models/Invoice.d.ts +18 -48
  96. package/dist/models/Invoice.d.ts.map +1 -1
  97. package/dist/models/InvoiceLineItem.d.ts +8 -37
  98. package/dist/models/InvoiceLineItem.d.ts.map +1 -1
  99. package/dist/models/TaxSettings.d.ts +0 -10
  100. package/dist/models/TaxSettings.d.ts.map +1 -1
  101. package/dist/models/index.d.ts +0 -1
  102. package/dist/models/index.d.ts.map +1 -1
  103. package/dist/playground.js +1 -1
  104. package/dist/playground.js.map +1 -1
  105. package/dist/recipes.d.ts +8 -11
  106. package/dist/recipes.d.ts.map +1 -1
  107. package/dist/revenue-journal.d.ts +0 -8
  108. package/dist/revenue-journal.d.ts.map +1 -1
  109. package/dist/smrt-knowledge.json +79 -661
  110. package/dist/svelte/components/InvoiceEditor.svelte +7 -148
  111. package/dist/svelte/components/InvoiceEditor.svelte.d.ts +4 -1
  112. package/dist/svelte/components/InvoiceEditor.svelte.d.ts.map +1 -1
  113. package/dist/svelte/components/InvoiceTotals.svelte +14 -118
  114. package/dist/svelte/components/InvoiceTotals.svelte.d.ts +4 -27
  115. package/dist/svelte/components/InvoiceTotals.svelte.d.ts.map +1 -1
  116. package/dist/svelte/components/MoneyInvoiceEditor.svelte +3 -23
  117. package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts +3 -26
  118. package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts.map +1 -1
  119. package/dist/svelte/index.d.ts +2 -3
  120. package/dist/svelte/index.d.ts.map +1 -1
  121. package/dist/svelte/index.js +1 -2
  122. package/dist/svelte/invoices/calculations.d.ts +3 -108
  123. package/dist/svelte/invoices/calculations.d.ts.map +1 -1
  124. package/dist/svelte/invoices/calculations.js +12 -309
  125. package/dist/svelte/invoices/messages.d.ts +1 -37
  126. package/dist/svelte/invoices/messages.d.ts.map +1 -1
  127. package/dist/svelte/invoices/messages.js +1 -37
  128. package/dist/svelte/invoices/money-editor.d.ts +1 -1
  129. package/dist/svelte/invoices/money-editor.d.ts.map +1 -1
  130. package/dist/svelte/invoices/types.d.ts +14 -114
  131. package/dist/svelte/invoices/types.d.ts.map +1 -1
  132. package/dist/svelte/playground/InvoicePreparationPreview.svelte +85 -94
  133. package/dist/svelte/playground/InvoicePreparationPreview.svelte.d.ts.map +1 -1
  134. package/dist/svelte/playground.js +1 -1
  135. package/dist/tax/index.d.ts +2 -1
  136. package/dist/tax/index.d.ts.map +1 -1
  137. package/dist/tax/standard-codes.d.ts +12 -0
  138. package/dist/tax/standard-codes.d.ts.map +1 -0
  139. package/dist/tax/tenant-bootstrap.d.ts +29 -0
  140. package/dist/tax/tenant-bootstrap.d.ts.map +1 -0
  141. package/dist/tenant-money-barrier.d.ts +12 -44
  142. package/dist/tenant-money-barrier.d.ts.map +1 -1
  143. package/dist/types/index.d.ts +10 -23
  144. package/dist/types/index.d.ts.map +1 -1
  145. package/dist/ui.js +1 -1
  146. package/dist/ui.js.map +1 -1
  147. package/dist/upgrade/detect.d.ts +129 -0
  148. package/dist/upgrade/detect.d.ts.map +1 -0
  149. package/dist/upgrade/money-v2.d.ts +81 -0
  150. package/dist/upgrade/money-v2.d.ts.map +1 -0
  151. package/package.json +14 -13
  152. package/agents/line-amount-migration.md +0 -50
  153. package/dist/chunks/ContractLineItemCollection--BrGMtNz.js.map +0 -1
  154. package/dist/chunks/DocumentTaxCollection-KOkaQT2M.js.map +0 -1
  155. package/dist/chunks/InvoiceCollection-BUe_8FT1.js.map +0 -1
  156. package/dist/chunks/InvoiceLineItemCollection-CPQGghyd.js +0 -468
  157. package/dist/chunks/InvoiceLineItemCollection-CPQGghyd.js.map +0 -1
  158. package/dist/chunks/TaxSettingsCollection-DYYF-In-.js +0 -319
  159. package/dist/chunks/TaxSettingsCollection-DYYF-In-.js.map +0 -1
  160. package/dist/chunks/calculations-DaHR17il.js +0 -333
  161. package/dist/chunks/calculations-DaHR17il.js.map +0 -1
  162. package/dist/chunks/document-money-oUDvdjOf.js.map +0 -1
  163. package/dist/chunks/invoice-posting-CF3fE_Ec.js.map +0 -1
  164. package/dist/chunks/revenue-journal-DY9fro8E.js.map +0 -1
  165. package/dist/chunks/tenant-money-barrier-y6EAa6vY.js +0 -135
  166. package/dist/chunks/tenant-money-barrier-y6EAa6vY.js.map +0 -1
  167. package/dist/chunks/units-CNcjH_eE.js.map +0 -1
  168. package/dist/collections/MoneyMigrationDocumentCollection.d.ts +0 -12
  169. package/dist/collections/MoneyMigrationDocumentCollection.d.ts.map +0 -1
  170. package/dist/migrations/commerceLineAmounts.d.ts +0 -84
  171. package/dist/migrations/commerceLineAmounts.d.ts.map +0 -1
  172. package/dist/models/MoneyMigrationDocument.d.ts +0 -28
  173. package/dist/models/MoneyMigrationDocument.d.ts.map +0 -1
  174. package/dist/svelte/components/InvoiceLineEditor.svelte +0 -92
  175. package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts +0 -8
  176. package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts.map +0 -1
  177. package/dist/svelte/invoices/fields.d.ts +0 -6
  178. package/dist/svelte/invoices/fields.d.ts.map +0 -1
  179. package/dist/svelte/invoices/fields.js +0 -22
  180. package/dist/tax/legacy.d.ts +0 -48
  181. package/dist/tax/legacy.d.ts.map +0 -1
@@ -1,468 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { i as resolveInvoiceLineDraft, r as calculateInvoiceMinorLine } from "./calculations-DaHR17il.js";
3
- import { o as minorToMajorUnits } from "./units-CNcjH_eE.js";
4
- import { MoneyValidationError } from "../money.js";
5
- import { a as DOCUMENT_MONEY_READ_REBIND, o as DOCUMENT_MONEY_WRITE } from "./TaxSettingsCollection-DYYF-In-.js";
6
- import { i as withTenantMoneyCollectionRead } from "./tenant-money-barrier-y6EAa6vY.js";
7
- import { SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
8
- import { TenantScoped, getTenantId, queryGlobal, queryWithGlobals, tenantId } from "@happyvertical/smrt-tenancy";
9
- //#region src/models/InvoiceLineItem.ts
10
- var __defProp = Object.defineProperty;
11
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
13
- enumerable: true,
14
- configurable: true,
15
- writable: true,
16
- value
17
- }) : obj[key] = value;
18
- var __decorateClass = (decorators, target, key, kind) => {
19
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
20
- for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
21
- if (kind && result) __defProp(target, key, result);
22
- return result;
23
- };
24
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
25
- var InvoiceLineItem = class extends SmrtObject {
26
- /** @internal Collection read guard returns this snapshot on its root DB. */
27
- rebindMoneyRead(capability, db) {
28
- if (capability !== DOCUMENT_MONEY_READ_REBIND) throw new MoneyValidationError("FROZEN_DOCUMENT", "Invoice line read rebinding requires the owning capability");
29
- this._db = db;
30
- this.options.db = db;
31
- return this;
32
- }
33
- tenantId = null;
34
- invoiceId = "";
35
- creditedLineId = null;
36
- creditCalculationBasisJson = "";
37
- get creditCalculationBasis() {
38
- try {
39
- const value = JSON.parse(this.creditCalculationBasisJson);
40
- if (!value || typeof value !== "object" || !("kind" in value)) return null;
41
- const basis = value;
42
- if (basis.kind !== "quantity" && basis.kind !== "net_amount" || typeof basis.sourceQuantity !== "string" || !Number.isSafeInteger(basis.sourceUnitPrice) || basis.sourceDiscountType !== "none" && basis.sourceDiscountType !== "percent" && basis.sourceDiscountType !== "amount" || typeof basis.sourceDiscountRate !== "string" || !Number.isSafeInteger(basis.sourceDiscountMinor) || basis.kind === "quantity" && typeof basis.quantity !== "string" || basis.kind === "net_amount" && !Number.isSafeInteger(basis.netMinor)) return null;
43
- return basis;
44
- } catch {
45
- return null;
46
- }
47
- }
48
- set creditCalculationBasis(value) {
49
- this.creditCalculationBasisJson = value ? JSON.stringify(value) : "";
50
- }
51
- description = "";
52
- /**
53
- * SKU or item code
54
- */
55
- sku = "";
56
- productId = null;
57
- quantity = 1;
58
- /** Raw editor modes retained only while they resolve to the authoritative model fields. */
59
- invoiceEditorStateJson = "";
60
- /** Guarded editor metadata view; malformed stored JSON is treated as absent. */
61
- get invoiceEditorState() {
62
- try {
63
- const value = JSON.parse(this.invoiceEditorStateJson);
64
- if (!value || typeof value !== "object" || !("draft" in value) || !("context" in value) || !value.draft || typeof value.draft !== "object" || !value.context || typeof value.context !== "object") return null;
65
- return value;
66
- } catch {
67
- return null;
68
- }
69
- }
70
- /** Store only this model's editor state, preserving unrelated metadata. */
71
- set invoiceEditorState(value) {
72
- this.invoiceEditorStateJson = value ? JSON.stringify(value) : "";
73
- }
74
- unitPrice = 0;
75
- discount = 0;
76
- discountType = "none";
77
- discountRate = "0.0";
78
- taxRate = 0;
79
- taxMode = "inherit";
80
- taxCodeId = null;
81
- taxCodeCode = null;
82
- taxCodeName = null;
83
- taxComponentsJson = null;
84
- get taxComponents() {
85
- if (this.taxComponentsJson === null) return [];
86
- try {
87
- const value = JSON.parse(this.taxComponentsJson);
88
- if (!Array.isArray(value)) return [];
89
- return value.filter((entry) => !!entry && typeof entry === "object" && typeof entry.taxComponentId === "string" && typeof entry.name === "string" && typeof entry.percent === "string" && Number.isSafeInteger(entry.taxMinor));
90
- } catch {
91
- return [];
92
- }
93
- }
94
- set taxComponents(value) {
95
- this.taxComponentsJson = JSON.stringify(value);
96
- }
97
- taxAmount = 0;
98
- legacyAmount = null;
99
- /** Stable document snapshot identity; ordinary lifecycle saves do not change it. */
100
- moneySnapshotId = "";
101
- amount = 0;
102
- /**
103
- * Type of source ('campaign' | 'contract' | 'manual' | etc.)
104
- */
105
- sourceType = "";
106
- /**
107
- * ID of the source (e.g., campaign ID, contract ID)
108
- */
109
- sourceId = "";
110
- /**
111
- * Service period start (for time-based billing)
112
- */
113
- periodStart = null;
114
- /**
115
- * Service period end (for time-based billing)
116
- */
117
- periodEnd = null;
118
- revenueAccountId = null;
119
- /**
120
- * Sort order within the invoice
121
- */
122
- sortOrder = 0;
123
- constructor(options = {}) {
124
- super(options);
125
- if (options.invoiceEditorStateJson !== void 0) this.invoiceEditorStateJson = options.invoiceEditorStateJson;
126
- if (options.invoiceEditorState !== void 0) this.invoiceEditorState = structuredClone(options.invoiceEditorState);
127
- if (options.tenantId !== void 0) this.tenantId = options.tenantId;
128
- if (options.invoiceId !== void 0) this.invoiceId = options.invoiceId;
129
- if (options.creditedLineId !== void 0) this.creditedLineId = options.creditedLineId;
130
- if (options.creditCalculationBasisJson !== void 0) this.creditCalculationBasisJson = options.creditCalculationBasisJson;
131
- if (options.creditCalculationBasis !== void 0) this.creditCalculationBasis = structuredClone(options.creditCalculationBasis);
132
- if (options.description !== void 0) this.description = options.description;
133
- if (options.sku !== void 0) this.sku = options.sku;
134
- if (options.productId !== void 0) this.productId = options.productId;
135
- if (options.quantity !== void 0) this.quantity = options.quantity;
136
- if (options.unitPrice !== void 0) this.unitPrice = options.unitPrice;
137
- if (options.discount !== void 0) this.discount = options.discount;
138
- if (options.discountType !== void 0) this.discountType = options.discountType;
139
- if (options.discountRate !== void 0) this.discountRate = options.discountRate;
140
- if (options.taxRate !== void 0) this.taxRate = options.taxRate;
141
- if (options.taxMode !== void 0) this.taxMode = options.taxMode;
142
- if (options.taxCodeId !== void 0) this.taxCodeId = options.taxCodeId;
143
- if (options.taxCodeCode !== void 0) this.taxCodeCode = options.taxCodeCode;
144
- if (options.taxCodeName !== void 0) this.taxCodeName = options.taxCodeName;
145
- if (options.taxComponentsJson !== void 0) this.taxComponentsJson = options.taxComponentsJson;
146
- if (options.taxComponents !== void 0) this.taxComponents = structuredClone(options.taxComponents);
147
- if (options.taxAmount !== void 0) this.taxAmount = options.taxAmount;
148
- if (options.legacyAmount !== void 0) this.legacyAmount = options.legacyAmount;
149
- if (options.moneySnapshotId !== void 0) this.moneySnapshotId = options.moneySnapshotId;
150
- if (options.amount !== void 0) this.amount = options.amount;
151
- if (options.sourceType !== void 0) this.sourceType = options.sourceType;
152
- if (options.sourceId !== void 0) this.sourceId = options.sourceId;
153
- if (options.periodStart !== void 0) this.periodStart = options.periodStart;
154
- if (options.periodEnd !== void 0) this.periodEnd = options.periodEnd;
155
- if (options.revenueAccountId !== void 0) this.revenueAccountId = options.revenueAccountId;
156
- if (options.sortOrder !== void 0) this.sortOrder = options.sortOrder;
157
- }
158
- /** Calculate exact safe integer-minor totals, rounding gross and tax ties toward positive infinity. */
159
- calculateAmount() {
160
- return calculateInvoiceMinorLine(this).totalMinor;
161
- }
162
- /** Rounded quantity times price, less the resolved flat minor-unit discount. */
163
- getSubtotal() {
164
- return calculateInvoiceMinorLine(this).subtotalMinor;
165
- }
166
- /** Tax on the rounded discounted subtotal, in safe integer minor units. */
167
- getTaxAmount() {
168
- return calculateInvoiceMinorLine(this).taxMinor;
169
- }
170
- /** Apply a server-validated draft without saving; authorization and transaction stay caller-owned. */
171
- applyEditorDraft(draft, context) {
172
- const resolved = resolveInvoiceLineDraft(draft, context);
173
- Object.assign(this, resolved);
174
- this.invoiceEditorState = structuredClone({
175
- draft,
176
- context
177
- });
178
- }
179
- /** Recover original editing modes only when current authority and resolved model fields agree. */
180
- getEditorDraft(authorizedContext) {
181
- const state = this.invoiceEditorState;
182
- if (!state || !authorizedContext || state.context?.currency !== authorizedContext.currency || state.context?.inheritedTaxRate !== authorizedContext.inheritedTaxRate) return null;
183
- try {
184
- const resolved = resolveInvoiceLineDraft(state.draft, authorizedContext);
185
- if (resolved.description !== this.description || resolved.sku !== this.sku || resolved.quantity !== this.quantity || resolved.unitPrice !== this.unitPrice || resolved.discount !== this.discount || resolved.taxRate !== this.taxRate) return null;
186
- return structuredClone(state.draft);
187
- } catch {
188
- return null;
189
- }
190
- }
191
- /** Validate resolved fields and recompute amount before persistence; editor metadata never determines money. */
192
- async save() {
193
- try {
194
- this.db;
195
- } catch (error) {
196
- this.calculateAmount();
197
- throw error;
198
- }
199
- const { saveInvoiceLineItem } = await import("./document-money-oUDvdjOf.js").then((n) => n.t);
200
- return await saveInvoiceLineItem(this);
201
- }
202
- /** @internal Aggregate persistence only. */
203
- async saveDerived(capability, legacy) {
204
- if (capability !== DOCUMENT_MONEY_WRITE) throw new Error("Invoice line money write capability is required");
205
- if (legacy) this.amount = this.calculateAmount();
206
- const state = this.invoiceEditorState;
207
- if (this.invoiceEditorStateJson && (!state || !this.getEditorDraft(state.context))) this.invoiceEditorState = null;
208
- return await super.save();
209
- }
210
- async delete(options = {}) {
211
- const { deleteInvoiceLineItem } = await import("./document-money-oUDvdjOf.js").then((n) => n.t);
212
- await deleteInvoiceLineItem(this, options);
213
- }
214
- /** @internal Aggregate persistence only. */
215
- async deleteDerived(capability, options = {}) {
216
- if (capability !== DOCUMENT_MONEY_WRITE) throw new Error("Invoice line money write capability is required");
217
- await super.delete(options);
218
- }
219
- /**
220
- * Check if line item has source tracking
221
- */
222
- hasSource() {
223
- return !!this.sourceType && !!this.sourceId;
224
- }
225
- /**
226
- * Check if line item has a service period
227
- */
228
- hasPeriod() {
229
- return !!this.periodStart && !!this.periodEnd;
230
- }
231
- /**
232
- * Convert to line item format for SDK accounting provider.
233
- *
234
- * `@happyvertical/accounting` takes currency **major** units. Pass the
235
- * invoice currency to convert (as {@link Invoice.toAccountingInput} does);
236
- * without it, money stays in this package's integer minor units.
237
- */
238
- toAccountingLineItem(currency) {
239
- const money = (value) => currency ? minorToMajorUnits(value, currency) : value;
240
- return {
241
- description: this.description,
242
- sku: this.sku || void 0,
243
- quantity: this.quantity,
244
- unitPrice: money(this.unitPrice),
245
- discount: this.discount ? money(this.discount) : void 0,
246
- taxRate: this.taxRate,
247
- amount: money(this.amount),
248
- periodStart: this.periodStart || void 0,
249
- periodEnd: this.periodEnd || void 0
250
- };
251
- }
252
- };
253
- __publicField(InvoiceLineItem, "__smrtPackage__", "@happyvertical/smrt-commerce");
254
- __decorateClass([tenantId({ nullable: true })], InvoiceLineItem.prototype, "tenantId", 2);
255
- __decorateClass([field({ description: "The invoice this line belongs to." }), foreignKey("Invoice", { role: "items" })], InvoiceLineItem.prototype, "invoiceId", 2);
256
- __decorateClass([foreignKey("InvoiceLineItem", { nullable: true })], InvoiceLineItem.prototype, "creditedLineId", 2);
257
- __decorateClass([field({ description: "Frozen source basis used to cap and reproduce an issued credit line." })], InvoiceLineItem.prototype, "creditCalculationBasisJson", 2);
258
- __decorateClass([field({ description: "What is being billed on this line." })], InvoiceLineItem.prototype, "description", 2);
259
- __decorateClass([crossPackageRef("@happyvertical/smrt-products:Product", { nullable: true })], InvoiceLineItem.prototype, "productId", 2);
260
- __decorateClass([field({ description: "How many." })], InvoiceLineItem.prototype, "quantity", 2);
261
- __decorateClass([field({
262
- description: "The price of one, before discount; includes tax when the document's prices include tax.",
263
- ui: { format: "money" }
264
- })], InvoiceLineItem.prototype, "unitPrice", 2);
265
- __decorateClass([field({ ui: { format: "money" } })], InvoiceLineItem.prototype, "discount", 2);
266
- __decorateClass([field({ type: "decimal" })], InvoiceLineItem.prototype, "discountRate", 2);
267
- __decorateClass([field({ description: "The stored fractional tax rate for this line (0.05 means 5%)." })], InvoiceLineItem.prototype, "taxRate", 2);
268
- __decorateClass([foreignKey("TaxCode", { nullable: true })], InvoiceLineItem.prototype, "taxCodeId", 2);
269
- __decorateClass([field({ ui: { format: "money" } })], InvoiceLineItem.prototype, "taxAmount", 2);
270
- __decorateClass([field({ nullable: true })], InvoiceLineItem.prototype, "legacyAmount", 2);
271
- __decorateClass([field({
272
- description: "The line amount: net of discount, and including tax only when the document's prices include tax.",
273
- ui: { format: "money" }
274
- })], InvoiceLineItem.prototype, "amount", 2);
275
- __decorateClass([crossPackageRef("@happyvertical/smrt-ledgers:Account", { nullable: true })], InvoiceLineItem.prototype, "revenueAccountId", 2);
276
- InvoiceLineItem = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
277
- api: {
278
- include: [
279
- "list",
280
- "get",
281
- "create",
282
- "update",
283
- "delete"
284
- ],
285
- writable: [
286
- "invoiceId",
287
- "description",
288
- "sku",
289
- "productId",
290
- "quantity",
291
- "unitPrice",
292
- "discount",
293
- "discountType",
294
- "discountRate",
295
- "taxRate",
296
- "taxMode",
297
- "taxCodeId",
298
- "sourceType",
299
- "sourceId",
300
- "periodStart",
301
- "periodEnd",
302
- "revenueAccountId",
303
- "sortOrder"
304
- ]
305
- },
306
- mcp: { include: ["list", "get"] },
307
- cli: { skipApiCheck: true }
308
- })], InvoiceLineItem);
309
- //#endregion
310
- //#region src/collections/InvoiceLineItemCollection.ts
311
- var InvoiceLineItemCollection_exports = /* @__PURE__ */ __exportAll({ InvoiceLineItemCollection: () => InvoiceLineItemCollection });
312
- var InvoiceLineItemCollection = class extends SmrtCollection {
313
- static _itemClass = InvoiceLineItem;
314
- async withMoneyRead(operation) {
315
- const rootDb = this.db;
316
- const tenantId = getTenantId();
317
- if (!tenantId) return operation();
318
- const result = await withTenantMoneyCollectionRead(rootDb, tenantId, (boundDb) => this.withDatabase(boundDb, operation));
319
- if (result instanceof InvoiceLineItem) result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);
320
- else if (Array.isArray(result)) {
321
- for (const item of result) if (item instanceof InvoiceLineItem) item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);
322
- }
323
- return result;
324
- }
325
- async get(filter, options = {}) {
326
- return this.withMoneyRead(() => super.get(filter, options));
327
- }
328
- async list(options = {}) {
329
- return this.withMoneyRead(() => super.list(options));
330
- }
331
- /**
332
- * Find line items by invoice
333
- *
334
- * @param invoiceId - Invoice ID
335
- * @returns Array of line items, sorted by sortOrder
336
- */
337
- async findByInvoice(invoiceId) {
338
- return await this.list({
339
- where: { invoiceId },
340
- orderBy: "sortOrder ASC"
341
- });
342
- }
343
- /**
344
- * Find line items by source
345
- *
346
- * @param sourceType - Source type (e.g., 'campaign', 'contract')
347
- * @param sourceId - Source ID
348
- * @returns Array of line items
349
- */
350
- async findBySource(sourceType, sourceId) {
351
- return await this.list({
352
- where: {
353
- sourceType,
354
- sourceId
355
- },
356
- orderBy: "created_at DESC"
357
- });
358
- }
359
- /**
360
- * Find line items by source type only
361
- *
362
- * @param sourceType - Source type (e.g., 'campaign')
363
- * @returns Array of line items
364
- */
365
- async findBySourceType(sourceType) {
366
- return await this.list({
367
- where: { sourceType },
368
- orderBy: "created_at DESC"
369
- });
370
- }
371
- /**
372
- * Calculate total amount for an invoice
373
- *
374
- * @param invoiceId - Invoice ID
375
- * @returns Total amount
376
- */
377
- async getTotalForInvoice(invoiceId) {
378
- return (await this.findByInvoice(invoiceId)).reduce((sum, item) => sum + item.amount, 0);
379
- }
380
- /**
381
- * Calculate subtotal (before tax) for an invoice
382
- *
383
- * @param invoiceId - Invoice ID
384
- * @returns Subtotal
385
- */
386
- async getSubtotalForInvoice(invoiceId) {
387
- return (await this.findByInvoice(invoiceId)).reduce((sum, item) => sum + item.getSubtotal(), 0);
388
- }
389
- /**
390
- * Calculate tax amount for an invoice
391
- *
392
- * @param invoiceId - Invoice ID
393
- * @returns Tax amount
394
- */
395
- async getTaxForInvoice(invoiceId) {
396
- return (await this.findByInvoice(invoiceId)).reduce((sum, item) => sum + item.getTaxAmount(), 0);
397
- }
398
- /**
399
- * Get the next sort order for an invoice
400
- *
401
- * @param invoiceId - Invoice ID
402
- * @returns Next sort order number
403
- */
404
- async getNextSortOrder(invoiceId) {
405
- const lineItems = await this.findByInvoice(invoiceId);
406
- if (lineItems.length === 0) return 0;
407
- return Math.max(...lineItems.map((item) => item.sortOrder)) + 1;
408
- }
409
- /**
410
- * Recalculate all line item amounts for an invoice
411
- *
412
- * @param invoiceId - Invoice ID
413
- * @returns Updated line items
414
- */
415
- async recalculateAmounts(invoiceId) {
416
- const lineItems = await this.findByInvoice(invoiceId);
417
- for (const item of lineItems) item.amount = item.calculateAmount();
418
- await Promise.all(lineItems.map((item) => item.save()));
419
- return lineItems;
420
- }
421
- /**
422
- * Convert line items to accounting format for SDK sync
423
- *
424
- * @param invoiceId - Invoice ID
425
- * @returns Array of line items in accounting format, money in integer
426
- * minor units (`Invoice.toAccountingInput()` converts to major units)
427
- */
428
- async toAccountingLineItems(invoiceId) {
429
- return (await this.findByInvoice(invoiceId)).map((item) => item.toAccountingLineItem());
430
- }
431
- /**
432
- * Find all invoice line items belonging to a specific tenant
433
- *
434
- * @param tenantId - Tenant ID
435
- * @returns Array of invoice line items for the tenant
436
- */
437
- async findByTenant(tenantId) {
438
- return this.list({ where: { tenantId } });
439
- }
440
- /**
441
- * Find all global invoice line items (not associated with any tenant).
442
- *
443
- * Routes through the shared tenant-global helper so it does not throw under
444
- * an active tenant context (an explicit `tenant_id IS NULL` filter would be
445
- * flagged as an isolation violation). (#1600)
446
- *
447
- * @returns Array of global invoice line items
448
- */
449
- async findGlobal() {
450
- return queryGlobal(this);
451
- }
452
- /**
453
- * Find invoice line items for a tenant including global line items.
454
- *
455
- * Fails closed if an active tenant context requests a different tenant's
456
- * rows; the admin/system path keeps the cross-tenant capability. (#1600)
457
- *
458
- * @param tenantId - Tenant ID
459
- * @returns Array of tenant-specific and global invoice line items
460
- */
461
- async findWithGlobals(tenantId) {
462
- return queryWithGlobals(this, tenantId, "InvoiceLineItem.findWithGlobals");
463
- }
464
- };
465
- //#endregion
466
- export { InvoiceLineItemCollection_exports as n, InvoiceLineItem as r, InvoiceLineItemCollection as t };
467
-
468
- //# sourceMappingURL=InvoiceLineItemCollection-CPQGghyd.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"InvoiceLineItemCollection-CPQGghyd.js","names":[],"sources":["../../src/models/InvoiceLineItem.ts","../../src/collections/InvoiceLineItemCollection.ts"],"sourcesContent":["/**\n * InvoiceLineItem model - individual items on an invoice\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 { minorToMajorUnits } from '../billing/units.js';\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 {\n calculateInvoiceMinorLine,\n type InvoiceCalculationContext,\n type InvoiceLineDraft,\n resolveInvoiceLineDraft,\n} from '../svelte/invoices/calculations.js';\nimport type {\n AccountingLineItemInput,\n InvoiceCreditCalculationBasis,\n InvoiceLineEditorState,\n InvoiceLineItemOptions,\n InvoiceTaxComponentSnapshot,\n} from '../types/index.js';\n\n/**\n * InvoiceLineItem represents a single line item on an invoice.\n *\n * Line items contain details of what is being billed, including\n * quantity, pricing, and optional source tracking (e.g., from ad campaigns).\n *\n * @example\n * ```typescript\n * const lineItem = await lineItems.create({\n * invoiceId: invoice.id,\n * description: 'Display Advertising - Summer Campaign',\n * quantity: 50000, // impressions\n * unitPrice: 1, // 1 cent per impression (minor units)\n * taxRate: 0.05,\n * sourceType: 'campaign',\n * sourceId: 'campaign-uuid',\n * periodStart: new Date('2025-06-01'),\n * periodEnd: new Date('2025-06-30')\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n writable: [\n 'invoiceId',\n 'description',\n 'sku',\n 'productId',\n 'quantity',\n 'unitPrice',\n 'discount',\n 'discountType',\n 'discountRate',\n 'taxRate',\n 'taxMode',\n 'taxCodeId',\n 'sourceType',\n 'sourceId',\n 'periodStart',\n 'periodEnd',\n 'revenueAccountId',\n 'sortOrder',\n ],\n },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class InvoiceLineItem 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 MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice 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 invoice line items\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Parent invoice\n */\n @field({ description: 'The invoice this line belongs to.' })\n @foreignKey('Invoice', { role: 'items' })\n invoiceId: string = '';\n\n @foreignKey('InvoiceLineItem', { nullable: true })\n creditedLineId: string | null = null;\n\n @field({\n description:\n 'Frozen source basis used to cap and reproduce an issued credit line.',\n })\n creditCalculationBasisJson = '';\n\n get creditCalculationBasis(): InvoiceCreditCalculationBasis | null {\n try {\n const value: unknown = JSON.parse(this.creditCalculationBasisJson);\n if (!value || typeof value !== 'object' || !('kind' in value))\n return null;\n const basis = value as Record<string, unknown>;\n if (\n (basis.kind !== 'quantity' && basis.kind !== 'net_amount') ||\n typeof basis.sourceQuantity !== 'string' ||\n !Number.isSafeInteger(basis.sourceUnitPrice) ||\n (basis.sourceDiscountType !== 'none' &&\n basis.sourceDiscountType !== 'percent' &&\n basis.sourceDiscountType !== 'amount') ||\n typeof basis.sourceDiscountRate !== 'string' ||\n !Number.isSafeInteger(basis.sourceDiscountMinor) ||\n (basis.kind === 'quantity' && typeof basis.quantity !== 'string') ||\n (basis.kind === 'net_amount' && !Number.isSafeInteger(basis.netMinor))\n )\n return null;\n return basis as unknown as InvoiceCreditCalculationBasis;\n } catch {\n return null;\n }\n }\n\n set creditCalculationBasis(value: InvoiceCreditCalculationBasis | null) {\n this.creditCalculationBasisJson = value ? JSON.stringify(value) : '';\n }\n\n /**\n * Item description\n */\n @field({ description: 'What is being billed on this line.' })\n description: string = '';\n\n /**\n * SKU or item code\n */\n sku: string = '';\n\n @crossPackageRef('@happyvertical/smrt-products:Product', { nullable: true })\n productId: string | null = null;\n\n /** Nonnegative decimal quantity (hours, weight, units), up to six fractional digits. */\n @field({ description: 'How many.' })\n quantity: number = 1.0;\n\n /** Raw editor modes retained only while they resolve to the authoritative model fields. */\n invoiceEditorStateJson: string = '';\n\n /** Guarded editor metadata view; malformed stored JSON is treated as absent. */\n get invoiceEditorState(): InvoiceLineEditorState | null {\n try {\n const value: unknown = JSON.parse(this.invoiceEditorStateJson);\n if (\n !value ||\n typeof value !== 'object' ||\n !('draft' in value) ||\n !('context' in value) ||\n !value.draft ||\n typeof value.draft !== 'object' ||\n !value.context ||\n typeof value.context !== 'object'\n )\n return null;\n return value as InvoiceLineEditorState;\n } catch {\n return null;\n }\n }\n\n /** Store only this model's editor state, preserving unrelated metadata. */\n set invoiceEditorState(value: InvoiceLineEditorState | null) {\n this.invoiceEditorStateJson = value ? JSON.stringify(value) : '';\n }\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 * Money is exact, so it is stored as minor units and never as a float —\n * `$19.99` is `1999`. An integer literal is what maps this to an INTEGER\n * column (#2361).\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 (#2361).\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 a decimal fraction (e.g., 0.05 for 5%).\n *\n * A genuine rate, not money: it is inherently fractional, so the `0.0`\n * initializer is load-bearing and maps it to a DECIMAL column. INTEGER would\n * truncate every rate to 0 (#2361).\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(): InvoiceTaxComponentSnapshot[] {\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 InvoiceTaxComponentSnapshot =>\n !!entry &&\n typeof entry === 'object' &&\n typeof (entry as InvoiceTaxComponentSnapshot).taxComponentId ===\n 'string' &&\n typeof (entry as InvoiceTaxComponentSnapshot).name === 'string' &&\n typeof (entry as InvoiceTaxComponentSnapshot).percent === 'string' &&\n Number.isSafeInteger((entry as InvoiceTaxComponentSnapshot).taxMinor),\n );\n } catch {\n return [];\n }\n }\n\n set taxComponents(value: InvoiceTaxComponentSnapshot[]) {\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 /**\n * @internal Pre-v2 line amount preserved only by the line-amount migration\n * for rollback; not a user-facing amount, so it carries no money hint.\n */\n @field({ nullable: true })\n legacyAmount: number | null = null;\n\n /** Stable document snapshot identity; ordinary lifecycle saves do not change it. */\n moneySnapshotId = '';\n\n /**\n * Calculated line amount, in integer minor units (#2361). Under money v2 it\n * is net of discount and before tax for `exclusive` / `none` documents, and\n * tax-inclusive for `inclusive` ones; {@link taxAmount} holds the tax. A\n * legacy-model tenant still stores qty * price - discount + tax.\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 // Source Tracking\n // ============================================================================\n\n /**\n * Type of source ('campaign' | 'contract' | 'manual' | etc.)\n */\n sourceType: string = '';\n\n /**\n * ID of the source (e.g., campaign ID, contract ID)\n */\n sourceId: string = '';\n\n /**\n * Service period start (for time-based billing)\n */\n periodStart: Date | null = null;\n\n /**\n * Service period end (for time-based billing)\n */\n periodEnd: Date | null = null;\n\n // ============================================================================\n // Accounting\n // ============================================================================\n\n /**\n * Revenue account ID (cross-package ref to smrt-ledgers)\n * Used for revenue recognition to specific accounts\n */\n @crossPackageRef('@happyvertical/smrt-ledgers:Account', { nullable: true })\n revenueAccountId: string | null = null;\n\n /**\n * Sort order within the invoice\n */\n sortOrder: number = 0;\n\n constructor(options: InvoiceLineItemOptions = {}) {\n super(options);\n if (options.invoiceEditorStateJson !== undefined)\n this.invoiceEditorStateJson = options.invoiceEditorStateJson;\n if (options.invoiceEditorState !== undefined)\n this.invoiceEditorState = structuredClone(options.invoiceEditorState);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.invoiceId !== undefined) this.invoiceId = options.invoiceId;\n if (options.creditedLineId !== undefined)\n this.creditedLineId = options.creditedLineId;\n if (options.creditCalculationBasisJson !== undefined)\n this.creditCalculationBasisJson = options.creditCalculationBasisJson;\n if (options.creditCalculationBasis !== undefined)\n this.creditCalculationBasis = structuredClone(\n options.creditCalculationBasis,\n );\n if (options.description !== undefined)\n this.description = options.description;\n if (options.sku !== undefined) this.sku = options.sku;\n if (options.productId !== undefined) this.productId = options.productId;\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.legacyAmount !== undefined)\n this.legacyAmount = options.legacyAmount;\n if (options.moneySnapshotId !== undefined)\n this.moneySnapshotId = options.moneySnapshotId;\n if (options.amount !== undefined) this.amount = options.amount;\n if (options.sourceType !== undefined) this.sourceType = options.sourceType;\n if (options.sourceId !== undefined) this.sourceId = options.sourceId;\n if (options.periodStart !== undefined)\n this.periodStart = options.periodStart;\n if (options.periodEnd !== undefined) this.periodEnd = options.periodEnd;\n if (options.revenueAccountId !== undefined)\n this.revenueAccountId = options.revenueAccountId;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n }\n\n /** Calculate exact safe integer-minor totals, rounding gross and tax ties toward positive infinity. */\n calculateAmount(): number {\n return calculateInvoiceMinorLine(this).totalMinor;\n }\n\n /** Rounded quantity times price, less the resolved flat minor-unit discount. */\n getSubtotal(): number {\n return calculateInvoiceMinorLine(this).subtotalMinor;\n }\n\n /** Tax on the rounded discounted subtotal, in safe integer minor units. */\n getTaxAmount(): number {\n return calculateInvoiceMinorLine(this).taxMinor;\n }\n\n /** Apply a server-validated draft without saving; authorization and transaction stay caller-owned. */\n applyEditorDraft(\n draft: InvoiceLineDraft,\n context: InvoiceCalculationContext,\n ): void {\n const resolved = resolveInvoiceLineDraft(draft, context);\n Object.assign(this, resolved);\n this.invoiceEditorState = structuredClone({ draft, context });\n }\n\n /** Recover original editing modes only when current authority and resolved model fields agree. */\n getEditorDraft(\n authorizedContext: InvoiceCalculationContext,\n ): InvoiceLineDraft | null {\n const state = this.invoiceEditorState;\n if (\n !state ||\n !authorizedContext ||\n state.context?.currency !== authorizedContext.currency ||\n state.context?.inheritedTaxRate !== authorizedContext.inheritedTaxRate\n )\n return null;\n try {\n const resolved = resolveInvoiceLineDraft(state.draft, authorizedContext);\n if (\n resolved.description !== this.description ||\n resolved.sku !== this.sku ||\n resolved.quantity !== this.quantity ||\n resolved.unitPrice !== this.unitPrice ||\n resolved.discount !== this.discount ||\n resolved.taxRate !== this.taxRate\n )\n return null;\n return structuredClone(state.draft);\n } catch {\n return null;\n }\n }\n\n /** Validate resolved fields and recompute amount before persistence; editor metadata never determines money. */\n override async save(): Promise<this> {\n try {\n void this.db;\n } catch (error) {\n // Preserve the legacy validation contract for detached model instances:\n // invalid arithmetic is reported before the ordinary initialization error.\n this.calculateAmount();\n throw error;\n }\n const { saveInvoiceLineItem } = await import('../document-money.js');\n return (await saveInvoiceLineItem(this)) as this;\n }\n\n /** @internal Aggregate persistence only. */\n async saveDerived(\n capability: DocumentMoneyWriteCapability,\n legacy: boolean,\n ): Promise<this> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Invoice line money write capability is required');\n if (legacy) this.amount = this.calculateAmount();\n const state = this.invoiceEditorState;\n if (\n this.invoiceEditorStateJson &&\n (!state || !this.getEditorDraft(state.context))\n )\n this.invoiceEditorState = null;\n return (await super.save()) as this;\n }\n\n override async delete(\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n const { deleteInvoiceLineItem } = await import('../document-money.js');\n await deleteInvoiceLineItem(this, options);\n }\n\n /** @internal 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('Invoice line money write capability is required');\n await super.delete(options);\n }\n\n /**\n * Check if line item has source tracking\n */\n hasSource(): boolean {\n return !!this.sourceType && !!this.sourceId;\n }\n\n /**\n * Check if line item has a service period\n */\n hasPeriod(): boolean {\n return !!this.periodStart && !!this.periodEnd;\n }\n\n /**\n * Convert to line item format for SDK accounting provider.\n *\n * `@happyvertical/accounting` takes currency **major** units. Pass the\n * invoice currency to convert (as {@link Invoice.toAccountingInput} does);\n * without it, money stays in this package's integer minor units.\n */\n toAccountingLineItem(currency?: string): AccountingLineItemInput {\n const money = (value: number) =>\n currency ? minorToMajorUnits(value, currency) : value;\n return {\n description: this.description,\n sku: this.sku || undefined,\n quantity: this.quantity,\n unitPrice: money(this.unitPrice),\n discount: this.discount ? money(this.discount) : undefined,\n taxRate: this.taxRate,\n amount: money(this.amount),\n periodStart: this.periodStart || undefined,\n periodEnd: this.periodEnd || undefined,\n };\n }\n}\n\nexport default InvoiceLineItem;\n","/**\n * InvoiceLineItemCollection - Collection manager for InvoiceLineItem 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 { InvoiceLineItem } from '../models/InvoiceLineItem.js';\nimport { withTenantMoneyCollectionRead } from '../tenant-money-barrier.js';\nimport type { AccountingLineItemInput } from '../types/index.js';\n\nexport class InvoiceLineItemCollection extends SmrtCollection<InvoiceLineItem> {\n static readonly _itemClass = InvoiceLineItem;\n\n private async withMoneyRead<T>(operation: () => Promise<T>): Promise<T> {\n const rootDb = this.db;\n const tenantId = getTenantId();\n if (!tenantId) return operation();\n const result = await withTenantMoneyCollectionRead(\n rootDb,\n tenantId,\n (boundDb) => this.withDatabase(boundDb, operation),\n );\n if (result instanceof InvoiceLineItem)\n result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n else if (Array.isArray(result))\n for (const item of result)\n if (item instanceof InvoiceLineItem)\n item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n return result;\n }\n\n override async get(\n filter: string | SmrtWhereClause<InvoiceLineItem>,\n options: Parameters<SmrtCollection<InvoiceLineItem>['get']>[1] = {},\n ): Promise<InvoiceLineItem | null> {\n return this.withMoneyRead(() => super.get(filter, options));\n }\n\n override async list<\n const Select extends readonly SmrtSelectField<InvoiceLineItem>[],\n >(\n options: Omit<SmrtListOptions<InvoiceLineItem>, '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<InvoiceLineItem>[],\n >(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope?: undefined;\n },\n ): Promise<SmrtSelectedRow<InvoiceLineItem, Select>[]>;\n override async list(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<SmrtObject[]>;\n override async list(options?: undefined): Promise<InvoiceLineItem[]>;\n override async list(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope?: undefined;\n },\n ): Promise<InvoiceLineItem[]>;\n override async list(\n options:\n | (Omit<SmrtListOptions<InvoiceLineItem>, 'select'> & {\n select?: undefined;\n })\n | undefined,\n ): Promise<SmrtObject[]>;\n override async list(\n options: SmrtListOptions<InvoiceLineItem> | undefined,\n ): Promise<SmrtObject[] | Record<string, unknown>[]>;\n override async list(\n options: SmrtListOptions<InvoiceLineItem> = {},\n ): Promise<SmrtObject[] | Record<string, unknown>[]> {\n return this.withMoneyRead(() => super.list(options));\n }\n\n /**\n * Find line items by invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Array of line items, sorted by sortOrder\n */\n async findByInvoice(invoiceId: string): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { invoiceId },\n orderBy: 'sortOrder ASC',\n });\n }\n\n /**\n * Find line items by source\n *\n * @param sourceType - Source type (e.g., 'campaign', 'contract')\n * @param sourceId - Source ID\n * @returns Array of line items\n */\n async findBySource(\n sourceType: string,\n sourceId: string,\n ): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { sourceType, sourceId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find line items by source type only\n *\n * @param sourceType - Source type (e.g., 'campaign')\n * @returns Array of line items\n */\n async findBySourceType(sourceType: string): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { sourceType },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Calculate total amount for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Total amount\n */\n async getTotalForInvoice(invoiceId: string): Promise<number> {\n const lineItems = await this.findByInvoice(invoiceId);\n return lineItems.reduce((sum, item) => sum + item.amount, 0);\n }\n\n /**\n * Calculate subtotal (before tax) for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Subtotal\n */\n async getSubtotalForInvoice(invoiceId: string): Promise<number> {\n const lineItems = await this.findByInvoice(invoiceId);\n return lineItems.reduce((sum, item) => sum + item.getSubtotal(), 0);\n }\n\n /**\n * Calculate tax amount for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Tax amount\n */\n async getTaxForInvoice(invoiceId: string): Promise<number> {\n const lineItems = await this.findByInvoice(invoiceId);\n return lineItems.reduce((sum, item) => sum + item.getTaxAmount(), 0);\n }\n\n /**\n * Get the next sort order for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Next sort order number\n */\n async getNextSortOrder(invoiceId: string): Promise<number> {\n const lineItems = await this.findByInvoice(invoiceId);\n if (lineItems.length === 0) return 0;\n\n const maxSortOrder = Math.max(...lineItems.map((item) => item.sortOrder));\n return maxSortOrder + 1;\n }\n\n /**\n * Recalculate all line item amounts for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Updated line items\n */\n async recalculateAmounts(invoiceId: string): Promise<InvoiceLineItem[]> {\n const lineItems = await this.findByInvoice(invoiceId);\n\n for (const item of lineItems) {\n item.amount = item.calculateAmount();\n }\n\n await Promise.all(lineItems.map((item) => item.save()));\n\n return lineItems;\n }\n\n /**\n * Convert line items to accounting format for SDK sync\n *\n * @param invoiceId - Invoice ID\n * @returns Array of line items in accounting format, money in integer\n * minor units (`Invoice.toAccountingInput()` converts to major units)\n */\n async toAccountingLineItems(\n invoiceId: string,\n ): Promise<AccountingLineItemInput[]> {\n const lineItems = await this.findByInvoice(invoiceId);\n return lineItems.map((item) => item.toAccountingLineItem());\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all invoice line items belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of invoice line items for the tenant\n */\n async findByTenant(tenantId: string): Promise<InvoiceLineItem[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global invoice 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 invoice line items\n */\n async findGlobal(): Promise<InvoiceLineItem[]> {\n return queryGlobal<InvoiceLineItem>(this);\n }\n\n /**\n * Find invoice 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 invoice line items\n */\n async findWithGlobals(tenantId: string): Promise<InvoiceLineItem[]> {\n return queryWithGlobals<InvoiceLineItem>(\n this,\n tenantId,\n 'InvoiceLineItem.findWithGlobals',\n );\n }\n}\n"],"mappings":"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"}