@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,23 +1,367 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { t as DocumentTaxCollection } from "./DocumentTaxCollection-KOkaQT2M.js";
2
+ import { t as DocumentTaxCollection } from "./DocumentTaxCollection-DDzlywMW.js";
3
3
  import { s as InvoiceStatus } from "./types-Bbm0Xflc.js";
4
- import { t as CustomerCollection } from "./CustomerCollection-CjGaZSpf.js";
4
+ import { t as CustomerCollection } from "./CustomerCollection-BIPH2ZUx.js";
5
5
  import { MoneyValidationError, calculateMoneyDocument, resolveLineTaxCode } from "../money.js";
6
6
  import { t as allocateFrozenCredit } from "./credit-allocation-yspz0Lab.js";
7
- import { c as lockDocumentMoneyParents, l as withDocumentMoneyObjectTransaction, o as DOCUMENT_MONEY_WRITE, u as withDocumentMoneyTransaction } from "./TaxSettingsCollection-DYYF-In-.js";
8
- import { t as InvoiceCollection } from "./InvoiceCollection-BUe_8FT1.js";
9
- import { n as lockTenantMoneyRuntime, o as withTenantMoneyRuntime, t as lockTenantMoneyMigrationOwner } from "./tenant-money-barrier-y6EAa6vY.js";
10
- import { r as InvoiceLineItem, t as InvoiceLineItemCollection } from "./InvoiceLineItemCollection-CPQGghyd.js";
11
- import { t as TaxCodeCollection } from "./TaxCodeCollection-DF2eaJed.js";
12
- import { t as TaxComponentCollection } from "./TaxComponentCollection-3x24xSNh.js";
13
- import { getTenantId } from "@happyvertical/smrt-tenancy";
7
+ import { a as assertCommerceMoneySchemaCurrent, f as DOCUMENT_MONEY_READ_REBIND, g as withDocumentMoneyTransaction, h as withDocumentMoneyObjectTransaction, m as lockDocumentMoneyParents, p as DOCUMENT_MONEY_WRITE } from "./detect-CY9ufaFb.js";
8
+ import { t as InvoiceCollection } from "./InvoiceCollection-cinzAqt6.js";
9
+ import { n as withTenantMoneyCollectionRead, r as withTenantMoneyRuntime, t as lockTenantMoneyRuntime } from "./tenant-money-barrier-6TlqUeVj.js";
10
+ import { t as TaxCodeCollection } from "./TaxCodeCollection-DaBOPG9c.js";
11
+ import { t as TaxComponentCollection } from "./TaxComponentCollection-C4zxnyVu.js";
12
+ import { SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
13
+ import { TenantScoped, getTenantId, queryGlobal, queryWithGlobals, tenantId } from "@happyvertical/smrt-tenancy";
14
+ //#region src/models/InvoiceLineItem.ts
15
+ var __defProp = Object.defineProperty;
16
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
17
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value
22
+ }) : obj[key] = value;
23
+ var __decorateClass = (decorators, target, key, kind) => {
24
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
25
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
26
+ if (kind && result) __defProp(target, key, result);
27
+ return result;
28
+ };
29
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
30
+ var InvoiceLineItem = class extends SmrtObject {
31
+ /** @internal Collection read guard returns this snapshot on its root DB. */
32
+ rebindMoneyRead(capability, db) {
33
+ if (capability !== DOCUMENT_MONEY_READ_REBIND) throw new MoneyValidationError("FROZEN_DOCUMENT", "Invoice line read rebinding requires the owning capability");
34
+ this._db = db;
35
+ this.options.db = db;
36
+ return this;
37
+ }
38
+ tenantId = null;
39
+ invoiceId = "";
40
+ creditedLineId = null;
41
+ creditCalculationBasisJson = "";
42
+ get creditCalculationBasis() {
43
+ try {
44
+ const value = JSON.parse(this.creditCalculationBasisJson);
45
+ if (!value || typeof value !== "object" || !("kind" in value)) return null;
46
+ const basis = value;
47
+ 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;
48
+ return basis;
49
+ } catch {
50
+ return null;
51
+ }
52
+ }
53
+ set creditCalculationBasis(value) {
54
+ this.creditCalculationBasisJson = value ? JSON.stringify(value) : "";
55
+ }
56
+ description = "";
57
+ /**
58
+ * SKU or item code
59
+ */
60
+ sku = "";
61
+ productId = null;
62
+ quantity = 1;
63
+ unitPrice = 0;
64
+ discount = 0;
65
+ discountType = "none";
66
+ discountRate = "0.0";
67
+ taxRate = 0;
68
+ taxMode = "inherit";
69
+ taxCodeId = null;
70
+ taxCodeCode = null;
71
+ taxCodeName = null;
72
+ taxComponentsJson = null;
73
+ get taxComponents() {
74
+ if (this.taxComponentsJson === null) return [];
75
+ try {
76
+ const value = JSON.parse(this.taxComponentsJson);
77
+ if (!Array.isArray(value)) return [];
78
+ return value.filter((entry) => !!entry && typeof entry === "object" && typeof entry.taxComponentId === "string" && typeof entry.name === "string" && typeof entry.percent === "string" && Number.isSafeInteger(entry.taxMinor));
79
+ } catch {
80
+ return [];
81
+ }
82
+ }
83
+ set taxComponents(value) {
84
+ this.taxComponentsJson = JSON.stringify(value);
85
+ }
86
+ taxAmount = 0;
87
+ /** Stable document snapshot identity; ordinary lifecycle saves do not change it. */
88
+ moneySnapshotId = "";
89
+ amount = 0;
90
+ /**
91
+ * Type of source ('campaign' | 'contract' | 'manual' | etc.)
92
+ */
93
+ sourceType = "";
94
+ /**
95
+ * ID of the source (e.g., campaign ID, contract ID)
96
+ */
97
+ sourceId = "";
98
+ /**
99
+ * Service period start (for time-based billing)
100
+ */
101
+ periodStart = null;
102
+ /**
103
+ * Service period end (for time-based billing)
104
+ */
105
+ periodEnd = null;
106
+ revenueAccountId = null;
107
+ /**
108
+ * Sort order within the invoice
109
+ */
110
+ sortOrder = 0;
111
+ constructor(options = {}) {
112
+ super(options);
113
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
114
+ if (options.invoiceId !== void 0) this.invoiceId = options.invoiceId;
115
+ if (options.creditedLineId !== void 0) this.creditedLineId = options.creditedLineId;
116
+ if (options.creditCalculationBasisJson !== void 0) this.creditCalculationBasisJson = options.creditCalculationBasisJson;
117
+ if (options.creditCalculationBasis !== void 0) this.creditCalculationBasis = structuredClone(options.creditCalculationBasis);
118
+ if (options.description !== void 0) this.description = options.description;
119
+ if (options.sku !== void 0) this.sku = options.sku;
120
+ if (options.productId !== void 0) this.productId = options.productId;
121
+ if (options.quantity !== void 0) this.quantity = options.quantity;
122
+ if (options.unitPrice !== void 0) this.unitPrice = options.unitPrice;
123
+ if (options.discount !== void 0) this.discount = options.discount;
124
+ if (options.discountType !== void 0) this.discountType = options.discountType;
125
+ if (options.discountRate !== void 0) this.discountRate = options.discountRate;
126
+ if (options.taxRate !== void 0) this.taxRate = options.taxRate;
127
+ if (options.taxMode !== void 0) this.taxMode = options.taxMode;
128
+ if (options.taxCodeId !== void 0) this.taxCodeId = options.taxCodeId;
129
+ if (options.taxCodeCode !== void 0) this.taxCodeCode = options.taxCodeCode;
130
+ if (options.taxCodeName !== void 0) this.taxCodeName = options.taxCodeName;
131
+ if (options.taxComponentsJson !== void 0) this.taxComponentsJson = options.taxComponentsJson;
132
+ if (options.taxComponents !== void 0) this.taxComponents = structuredClone(options.taxComponents);
133
+ if (options.taxAmount !== void 0) this.taxAmount = options.taxAmount;
134
+ if (options.moneySnapshotId !== void 0) this.moneySnapshotId = options.moneySnapshotId;
135
+ if (options.amount !== void 0) this.amount = options.amount;
136
+ if (options.sourceType !== void 0) this.sourceType = options.sourceType;
137
+ if (options.sourceId !== void 0) this.sourceId = options.sourceId;
138
+ if (options.periodStart !== void 0) this.periodStart = options.periodStart;
139
+ if (options.periodEnd !== void 0) this.periodEnd = options.periodEnd;
140
+ if (options.revenueAccountId !== void 0) this.revenueAccountId = options.revenueAccountId;
141
+ if (options.sortOrder !== void 0) this.sortOrder = options.sortOrder;
142
+ }
143
+ /** Refuse an old-format row read from the database. */
144
+ async initialize() {
145
+ await super.initialize();
146
+ if (this.isPersisted) {
147
+ const { assertHydratedMoneyRowCurrent } = await import("./detect-CY9ufaFb.js").then((n) => n.c);
148
+ await assertHydratedMoneyRowCurrent(this);
149
+ }
150
+ return this;
151
+ }
152
+ /** Persist through the invoice money aggregate. */
153
+ async save() {
154
+ const { saveInvoiceLineItem } = await Promise.resolve().then(() => document_money_exports);
155
+ return await saveInvoiceLineItem(this);
156
+ }
157
+ /** @internal Aggregate persistence only. */
158
+ async saveDerived(capability) {
159
+ if (capability !== DOCUMENT_MONEY_WRITE) throw new Error("Invoice line money write capability is required");
160
+ for (const [field2, value] of [["unitPrice", this.unitPrice], ["discount", this.discount]]) if (!Number.isSafeInteger(value)) throw new MoneyValidationError("UNSAFE_MONEY", `Invoice line ${field2} ${value} must be a safe integer number of minor units`);
161
+ return await super.save();
162
+ }
163
+ async delete(options = {}) {
164
+ const { deleteInvoiceLineItem } = await Promise.resolve().then(() => document_money_exports);
165
+ await deleteInvoiceLineItem(this, options);
166
+ }
167
+ /** @internal Aggregate persistence only. */
168
+ async deleteDerived(capability, options = {}) {
169
+ if (capability !== DOCUMENT_MONEY_WRITE) throw new Error("Invoice line money write capability is required");
170
+ await super.delete(options);
171
+ }
172
+ /**
173
+ * Check if line item has source tracking
174
+ */
175
+ hasSource() {
176
+ return !!this.sourceType && !!this.sourceId;
177
+ }
178
+ /**
179
+ * Check if line item has a service period
180
+ */
181
+ hasPeriod() {
182
+ return !!this.periodStart && !!this.periodEnd;
183
+ }
184
+ };
185
+ __publicField(InvoiceLineItem, "__smrtPackage__", "@happyvertical/smrt-commerce");
186
+ __decorateClass([tenantId({ nullable: true })], InvoiceLineItem.prototype, "tenantId", 2);
187
+ __decorateClass([field({ description: "The invoice this line belongs to." }), foreignKey("Invoice", { role: "items" })], InvoiceLineItem.prototype, "invoiceId", 2);
188
+ __decorateClass([foreignKey("InvoiceLineItem", { nullable: true })], InvoiceLineItem.prototype, "creditedLineId", 2);
189
+ __decorateClass([field({ description: "Frozen source basis used to cap and reproduce an issued credit line." })], InvoiceLineItem.prototype, "creditCalculationBasisJson", 2);
190
+ __decorateClass([field({ description: "What is being billed on this line." })], InvoiceLineItem.prototype, "description", 2);
191
+ __decorateClass([crossPackageRef("@happyvertical/smrt-products:Product", { nullable: true })], InvoiceLineItem.prototype, "productId", 2);
192
+ __decorateClass([field({ description: "How many." })], InvoiceLineItem.prototype, "quantity", 2);
193
+ __decorateClass([field({
194
+ description: "The price of one, before discount; includes tax when the document's prices include tax.",
195
+ ui: { format: "money" }
196
+ })], InvoiceLineItem.prototype, "unitPrice", 2);
197
+ __decorateClass([field({ ui: { format: "money" } })], InvoiceLineItem.prototype, "discount", 2);
198
+ __decorateClass([field({ type: "decimal" })], InvoiceLineItem.prototype, "discountRate", 2);
199
+ __decorateClass([field({ description: "The stored fractional tax rate for this line (0.05 means 5%)." })], InvoiceLineItem.prototype, "taxRate", 2);
200
+ __decorateClass([foreignKey("TaxCode", { nullable: true })], InvoiceLineItem.prototype, "taxCodeId", 2);
201
+ __decorateClass([field({ ui: { format: "money" } })], InvoiceLineItem.prototype, "taxAmount", 2);
202
+ __decorateClass([field({
203
+ description: "The line amount: net of discount, and including tax only when the document's prices include tax.",
204
+ ui: { format: "money" }
205
+ })], InvoiceLineItem.prototype, "amount", 2);
206
+ __decorateClass([crossPackageRef("@happyvertical/smrt-ledgers:Account", { nullable: true })], InvoiceLineItem.prototype, "revenueAccountId", 2);
207
+ InvoiceLineItem = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
208
+ api: {
209
+ include: [
210
+ "list",
211
+ "get",
212
+ "create",
213
+ "update",
214
+ "delete"
215
+ ],
216
+ writable: [
217
+ "invoiceId",
218
+ "description",
219
+ "sku",
220
+ "productId",
221
+ "quantity",
222
+ "unitPrice",
223
+ "discount",
224
+ "discountType",
225
+ "discountRate",
226
+ "taxRate",
227
+ "taxMode",
228
+ "taxCodeId",
229
+ "sourceType",
230
+ "sourceId",
231
+ "periodStart",
232
+ "periodEnd",
233
+ "revenueAccountId",
234
+ "sortOrder"
235
+ ]
236
+ },
237
+ mcp: { include: ["list", "get"] },
238
+ cli: { skipApiCheck: true }
239
+ })], InvoiceLineItem);
240
+ //#endregion
241
+ //#region src/collections/InvoiceLineItemCollection.ts
242
+ var InvoiceLineItemCollection = class extends SmrtCollection {
243
+ static _itemClass = InvoiceLineItem;
244
+ async withMoneyRead(operation) {
245
+ const rootDb = this.db;
246
+ const tenantId = getTenantId();
247
+ if (!tenantId) {
248
+ await assertCommerceMoneySchemaCurrent(rootDb);
249
+ return operation();
250
+ }
251
+ const result = await withTenantMoneyCollectionRead(rootDb, tenantId, (boundDb) => this.withDatabase(boundDb, operation));
252
+ if (result instanceof InvoiceLineItem) result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);
253
+ else if (Array.isArray(result)) {
254
+ for (const item of result) if (item instanceof InvoiceLineItem) item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);
255
+ }
256
+ return result;
257
+ }
258
+ async get(filter, options = {}) {
259
+ return this.withMoneyRead(() => super.get(filter, options));
260
+ }
261
+ async list(options = {}) {
262
+ return this.withMoneyRead(() => super.list(options));
263
+ }
264
+ /**
265
+ * Find line items by invoice
266
+ *
267
+ * @param invoiceId - Invoice ID
268
+ * @returns Array of line items, sorted by sortOrder
269
+ */
270
+ async findByInvoice(invoiceId) {
271
+ return await this.list({
272
+ where: { invoiceId },
273
+ orderBy: "sortOrder ASC"
274
+ });
275
+ }
276
+ /**
277
+ * Find line items by source
278
+ *
279
+ * @param sourceType - Source type (e.g., 'campaign', 'contract')
280
+ * @param sourceId - Source ID
281
+ * @returns Array of line items
282
+ */
283
+ async findBySource(sourceType, sourceId) {
284
+ return await this.list({
285
+ where: {
286
+ sourceType,
287
+ sourceId
288
+ },
289
+ orderBy: "created_at DESC"
290
+ });
291
+ }
292
+ /**
293
+ * Find line items by source type only
294
+ *
295
+ * @param sourceType - Source type (e.g., 'campaign')
296
+ * @returns Array of line items
297
+ */
298
+ async findBySourceType(sourceType) {
299
+ return await this.list({
300
+ where: { sourceType },
301
+ orderBy: "created_at DESC"
302
+ });
303
+ }
304
+ /**
305
+ * Calculate total amount for an invoice
306
+ *
307
+ * @param invoiceId - Invoice ID
308
+ * @returns Total amount
309
+ */
310
+ async getTotalForInvoice(invoiceId) {
311
+ return (await this.findByInvoice(invoiceId)).reduce((sum, item) => sum + item.amount, 0);
312
+ }
313
+ /**
314
+ * Get the next sort order for an invoice
315
+ *
316
+ * @param invoiceId - Invoice ID
317
+ * @returns Next sort order number
318
+ */
319
+ async getNextSortOrder(invoiceId) {
320
+ const lineItems = await this.findByInvoice(invoiceId);
321
+ if (lineItems.length === 0) return 0;
322
+ return Math.max(...lineItems.map((item) => item.sortOrder)) + 1;
323
+ }
324
+ /**
325
+ * Find all invoice line items belonging to a specific tenant
326
+ *
327
+ * @param tenantId - Tenant ID
328
+ * @returns Array of invoice line items for the tenant
329
+ */
330
+ async findByTenant(tenantId) {
331
+ return this.list({ where: { tenantId } });
332
+ }
333
+ /**
334
+ * Find all global invoice line items (not associated with any tenant).
335
+ *
336
+ * Routes through the shared tenant-global helper so it does not throw under
337
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
338
+ * flagged as an isolation violation). (#1600)
339
+ *
340
+ * @returns Array of global invoice line items
341
+ */
342
+ async findGlobal() {
343
+ return queryGlobal(this);
344
+ }
345
+ /**
346
+ * Find invoice line items for a tenant including global line items.
347
+ *
348
+ * Fails closed if an active tenant context requests a different tenant's
349
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
350
+ *
351
+ * @param tenantId - Tenant ID
352
+ * @returns Array of tenant-specific and global invoice line items
353
+ */
354
+ async findWithGlobals(tenantId) {
355
+ return queryWithGlobals(this, tenantId, "InvoiceLineItem.findWithGlobals");
356
+ }
357
+ };
358
+ //#endregion
14
359
  //#region src/document-money.ts
15
360
  var document_money_exports = /* @__PURE__ */ __exportAll({
16
361
  deleteInvoice: () => deleteInvoice,
17
362
  deleteInvoiceLineItem: () => deleteInvoiceLineItem,
18
363
  getInvoiceMoneyFacts: () => getInvoiceMoneyFacts,
19
364
  lockAndReloadInvoice: () => lockAndReloadInvoice,
20
- materializeInvoiceMoneyDraft: () => materializeInvoiceMoneyDraft,
21
365
  previewInvoiceMoney: () => previewInvoiceMoney,
22
366
  saveInvoice: () => saveInvoice,
23
367
  saveInvoiceLineItem: () => saveInvoiceLineItem
@@ -77,21 +421,22 @@ var FROZEN_LINE_FIELDS = [
77
421
  "moneySnapshotId"
78
422
  ];
79
423
  function comparable(value) {
80
- return value instanceof Date ? value.toISOString() : value ?? null;
424
+ if (value instanceof Date) return value.toISOString();
425
+ return value === "" || value === void 0 ? null : value;
81
426
  }
82
427
  function assertFieldsUnchanged(proposed, persisted, fields, label) {
83
428
  for (const field of fields) if (comparable(proposed[field]) !== comparable(persisted[field])) throw new MoneyValidationError("FROZEN_DOCUMENT", `${label} ${String(field)} is frozen`);
84
429
  }
85
430
  function assertTenantId(value) {
86
- if (!value || value.trim() !== value) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Money v2 requires a tenant-owned invoice");
431
+ if (!value || value.trim() !== value) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Invoice money requires a tenant-owned invoice");
87
432
  }
88
433
  function requireId(value, label) {
89
434
  if (!value) throw new MoneyValidationError("INVALID_MONEY_INPUT", `${label} requires a persisted ID`);
90
435
  return value;
91
436
  }
92
437
  async function lockRuntimeSettings(db, tenantId) {
93
- if (!tenantId) return null;
94
- return (await lockTenantMoneyRuntime(db, tenantId)).settings;
438
+ if (!tenantId) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Commerce money documents require a tenant");
439
+ return lockTenantMoneyRuntime(db, tenantId);
95
440
  }
96
441
  function isFrozen(invoice) {
97
442
  return invoice.status !== InvoiceStatus.DRAFT || !!invoice.arJournalId || !!invoice.moneySnapshotId;
@@ -186,12 +531,12 @@ async function refreshIssuedCreditBalance(db, source) {
186
531
  if (credit.creditedAmount !== applied) {
187
532
  credit.creditedAmount = applied;
188
533
  credit.updatePaymentStatus(credit.amountPaid);
189
- await credit.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: false });
534
+ await credit.saveDerived(DOCUMENT_MONEY_WRITE);
190
535
  }
191
536
  }
192
537
  source.creditedAmount = total;
193
538
  source.updatePaymentStatus(source.amountPaid);
194
- await source.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: false });
539
+ await source.saveDerived(DOCUMENT_MONEY_WRITE);
195
540
  }
196
541
  function lineNet(line, parent) {
197
542
  return parent.lineAmountType === "inclusive" ? line.amount - line.taxAmount : line.amount;
@@ -313,8 +658,8 @@ async function recomputeInvoiceAggregate(db, invoice, settings, freezeSnapshotId
313
658
  }))
314
659
  };
315
660
  }
316
- const exempt = await codesCollection.findByCode("exempt");
317
- const outOfScope = await codesCollection.findByCode("out-of-scope");
661
+ const exempt = await codesCollection.findByCode("exempt", tenantId);
662
+ const outOfScope = await codesCollection.findByCode("out-of-scope", tenantId);
318
663
  const customers = await CustomerCollection.create({ db });
319
664
  const customer = invoice.customerId ? await customers.get({ id: invoice.customerId }, { cache: false }) : null;
320
665
  if (customer && customer.tenantId !== tenantId) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Invoice customer must belong to its tenant");
@@ -511,7 +856,7 @@ async function recomputeInvoiceAggregate(db, invoice, settings, freezeSnapshotId
511
856
  });
512
857
  line.taxRate = code ? code.components.reduce((sum, part) => sum + Number(part.percent) / 100, 0) : 0;
513
858
  if (freezeSnapshotId) line.moneySnapshotId = freezeSnapshotId;
514
- if (persist) await line.saveDerived(DOCUMENT_MONEY_WRITE, false);
859
+ if (persist) await line.saveDerived(DOCUMENT_MONEY_WRITE);
515
860
  }
516
861
  const taxRows = calculated.taxes.map((tax) => {
517
862
  const code = tax.taxCodeId ? [...resolvedCodes.values()].find((candidate) => candidate?.id === tax.taxCodeId) ?? null : null;
@@ -619,10 +964,10 @@ async function previewInvoiceMoneyOnScope(input, settings) {
619
964
  };
620
965
  }
621
966
  async function previewInvoiceMoney(input) {
622
- return withTenantMoneyRuntime(input.db, input.tenantId, "v2", async (scope) => previewInvoiceMoneyOnScope({
967
+ return withTenantMoneyRuntime(input.db, input.tenantId, async (scope) => previewInvoiceMoneyOnScope({
623
968
  ...input,
624
969
  db: scope.db
625
- }, scope.barrier.settings));
970
+ }, scope.settings));
626
971
  }
627
972
  async function getInvoiceMoneyFactsOnScope(input) {
628
973
  if (!input.tenantId || getTenantId() !== input.tenantId) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Invoice money facts require their active principal tenant");
@@ -676,7 +1021,7 @@ async function getInvoiceMoneyFactsOnScope(input) {
676
1021
  };
677
1022
  }
678
1023
  async function getInvoiceMoneyFacts(input) {
679
- return withTenantMoneyRuntime(input.db, input.tenantId, "v2", async (scope) => getInvoiceMoneyFactsOnScope({
1024
+ return withTenantMoneyRuntime(input.db, input.tenantId, async (scope) => getInvoiceMoneyFactsOnScope({
680
1025
  ...input,
681
1026
  db: scope.db
682
1027
  }));
@@ -693,7 +1038,6 @@ async function saveInvoice(input) {
693
1038
  const existing = invoice.id ? await findInvoice(tx, invoice.id) : null;
694
1039
  const tenantId = existing?.tenantId ?? candidateTenantId;
695
1040
  if (candidateTenantId && existing?.tenantId && existing.tenantId !== candidateTenantId) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Invoice tenant does not match its active money barrier");
696
- if (settings?.moneyModel !== "v2") return invoice.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: true });
697
1041
  assertTenantId(tenantId);
698
1042
  if (!existing) {
699
1043
  invoice.tenantId = tenantId;
@@ -723,7 +1067,7 @@ async function saveInvoice(input) {
723
1067
  invoice.sellerTaxRegistrations = structuredClone(settings.taxRegistrations);
724
1068
  invoice.partyTaxId = customer?.taxId ?? "";
725
1069
  }
726
- return invoice.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: false });
1070
+ return invoice.saveDerived(DOCUMENT_MONEY_WRITE);
727
1071
  }
728
1072
  if (invoice.tenantId !== existing.tenantId) throw new MoneyValidationError("FROZEN_DOCUMENT", "Invoice tenant identity cannot change");
729
1073
  if (invoice.kind !== existing.kind || invoice.creditedInvoiceId !== existing.creditedInvoiceId) throw new MoneyValidationError("FROZEN_DOCUMENT", "Invoice kind and credited invoice identity are immutable");
@@ -734,9 +1078,9 @@ async function saveInvoice(input) {
734
1078
  if (locked.invoice.arJournalId && invoice.arJournalId !== locked.invoice.arJournalId) throw new MoneyValidationError("FROZEN_DOCUMENT", "Invoice revenue journal identity is frozen once assigned");
735
1079
  if (invoice.status === InvoiceStatus.CANCELLED && locked.invoice.status !== InvoiceStatus.CANCELLED && locked.invoice.kind === "invoice" && locked.invoice.isPaid()) throw new MoneyValidationError("FROZEN_DOCUMENT", "A paid invoice cannot be cancelled");
736
1080
  if (invoice.status === InvoiceStatus.CANCELLED && locked.invoice.status !== InvoiceStatus.CANCELLED && locked.invoice.kind === "credit_note" && locked.invoice.amountPaid > 0) throw new MoneyValidationError("FROZEN_DOCUMENT", "A refunded credit note cannot be cancelled");
737
- if (invoice.status === InvoiceStatus.CANCELLED && locked.invoice.status !== InvoiceStatus.CANCELLED && locked.invoice.arJournalId && !locked.invoice.arReversalJournalId) throw new MoneyValidationError("FROZEN_DOCUMENT", "A posted money-v2 invoice requires an atomic reversal before cancellation");
1081
+ if (invoice.status === InvoiceStatus.CANCELLED && locked.invoice.status !== InvoiceStatus.CANCELLED && locked.invoice.arJournalId && !locked.invoice.arReversalJournalId) throw new MoneyValidationError("FROZEN_DOCUMENT", "A posted invoice requires an atomic reversal before cancellation");
738
1082
  assertFieldsUnchanged(invoice, locked.invoice, FROZEN_INVOICE_FIELDS, "Invoice");
739
- const saved2 = await invoice.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: false });
1083
+ const saved2 = await invoice.saveDerived(DOCUMENT_MONEY_WRITE);
740
1084
  if (locked.source) await refreshIssuedCreditBalance(tx, locked.source);
741
1085
  return saved2;
742
1086
  }
@@ -750,7 +1094,7 @@ async function saveInvoice(input) {
750
1094
  invoice.partyTaxId = customer?.taxId ?? "";
751
1095
  invoice.moneySnapshotId = snapshotId;
752
1096
  }
753
- const saved = await invoice.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: false });
1097
+ const saved = await invoice.saveDerived(DOCUMENT_MONEY_WRITE);
754
1098
  if (locked.source) await refreshIssuedCreditBalance(tx, locked.source);
755
1099
  return saved;
756
1100
  }));
@@ -759,22 +1103,10 @@ async function saveInvoice(input) {
759
1103
  throw error;
760
1104
  }
761
1105
  }
762
- async function materializeInvoiceMoneyDraft(input) {
763
- const settings = await lockTenantMoneyMigrationOwner(input.db, input.tenantId, input.migrationId);
764
- const { invoice } = await lockAndReloadInvoice(input.db, input.invoiceId, input.tenantId);
765
- if (isFrozen(invoice)) throw new MoneyValidationError("FROZEN_DOCUMENT", "Only an unfrozen draft invoice can be migration-recomputed");
766
- const result = await recomputeInvoiceAggregate(input.db, invoice, settings);
767
- await invoice.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: false });
768
- return {
769
- invoiceId: input.invoiceId,
770
- taxRows: result.taxRows
771
- };
772
- }
773
1106
  async function saveInvoiceLineItem(input) {
774
1107
  return withDocumentMoneyObjectTransaction(input, async (line, tx) => {
775
1108
  const candidateTenantId = getTenantId() ?? line.tenantId ?? null;
776
1109
  const settings = await lockRuntimeSettings(tx, candidateTenantId);
777
- if (settings?.moneyModel !== "v2") return line.saveDerived(DOCUMENT_MONEY_WRITE, true);
778
1110
  const persisted = line.id ? await (await InvoiceLineItemCollection.create({ db: tx })).get({ id: line.id }, { cache: false }) : null;
779
1111
  const parentId = persisted?.invoiceId ?? line.invoiceId;
780
1112
  const first = await loadInvoice(tx, parentId);
@@ -789,12 +1121,12 @@ async function saveInvoiceLineItem(input) {
789
1121
  if (isFrozen(invoice)) {
790
1122
  if (!persisted) throw new MoneyValidationError("FROZEN_DOCUMENT", "Cannot add a line to a frozen invoice");
791
1123
  assertFieldsUnchanged(line, persisted, FROZEN_LINE_FIELDS, "Invoice line");
792
- return line.saveDerived(DOCUMENT_MONEY_WRITE, false);
1124
+ return line.saveDerived(DOCUMENT_MONEY_WRITE);
793
1125
  }
794
- await line.saveDerived(DOCUMENT_MONEY_WRITE, false);
1126
+ await line.saveDerived(DOCUMENT_MONEY_WRITE);
795
1127
  const priorAggregate = aggregateSignature(invoice);
796
1128
  await recomputeInvoiceAggregate(tx, invoice, settings);
797
- if (aggregateSignature(invoice) !== priorAggregate) await invoice.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: false });
1129
+ if (aggregateSignature(invoice) !== priorAggregate) await invoice.saveDerived(DOCUMENT_MONEY_WRITE);
798
1130
  const refreshed = await (await InvoiceLineItemCollection.create({ db: tx })).get({ id: requireId(line.id, "Invoice line") }, { cache: false });
799
1131
  if (refreshed) for (const field of [
800
1132
  "discount",
@@ -819,42 +1151,36 @@ async function deleteInvoiceLineItem(input, options) {
819
1151
  if (!persisted) return;
820
1152
  const first = await loadInvoice(tx, persisted.invoiceId);
821
1153
  if (candidateTenantId && first.invoice.tenantId !== candidateTenantId) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Invoice line tenant does not match its active money barrier");
822
- if (settings?.moneyModel !== "v2") {
823
- await line.deleteDerived(DOCUMENT_MONEY_WRITE, options);
824
- return;
825
- }
826
1154
  assertTenantId(first.invoice.tenantId);
827
1155
  const { invoice } = await lockAndReloadInvoice(tx, persisted.invoiceId, first.invoice.tenantId);
828
1156
  if (isFrozen(invoice)) throw new MoneyValidationError("FROZEN_DOCUMENT", "Cannot delete a line from a frozen invoice");
829
1157
  await line.deleteDerived(DOCUMENT_MONEY_WRITE, options);
830
1158
  const priorAggregate = aggregateSignature(invoice);
831
1159
  await recomputeInvoiceAggregate(tx, invoice, settings);
832
- if (aggregateSignature(invoice) !== priorAggregate) await invoice.saveDerived(DOCUMENT_MONEY_WRITE, { recomputeLegacy: false });
1160
+ if (aggregateSignature(invoice) !== priorAggregate) await invoice.saveDerived(DOCUMENT_MONEY_WRITE);
833
1161
  }));
834
1162
  }
835
1163
  async function deleteInvoice(input, options) {
836
1164
  await withDocumentMoneyTransaction(input.db, async (tx) => input.withDatabase(tx, async (invoice) => {
837
1165
  const candidateTenantId = getTenantId() ?? invoice.tenantId ?? null;
838
- const settings = await lockRuntimeSettings(tx, candidateTenantId);
1166
+ await lockRuntimeSettings(tx, candidateTenantId);
839
1167
  const persisted = invoice.id ? await findInvoice(tx, invoice.id) : null;
840
1168
  if (!persisted) return;
841
1169
  if (candidateTenantId && persisted.tenantId !== candidateTenantId) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Invoice tenant does not match its active money barrier");
842
- if (settings?.moneyModel === "v2" && isFrozen(persisted)) throw new MoneyValidationError("FROZEN_DOCUMENT", "Cannot delete a frozen invoice");
843
- if (settings?.moneyModel === "v2") {
844
- assertTenantId(persisted.tenantId);
845
- const persistedId = requireId(persisted.id, "Invoice");
846
- await lockAndReloadInvoice(tx, persistedId, persisted.tenantId);
847
- await (await DocumentTaxCollection.create({ db: tx })).replaceDerivedForDocument(DOCUMENT_MONEY_WRITE, {
848
- tenantId: persisted.tenantId,
849
- documentType: "invoice",
850
- documentId: persistedId,
851
- rows: []
852
- });
853
- }
1170
+ if (isFrozen(persisted)) throw new MoneyValidationError("FROZEN_DOCUMENT", "Cannot delete a frozen invoice");
1171
+ assertTenantId(persisted.tenantId);
1172
+ const persistedId = requireId(persisted.id, "Invoice");
1173
+ await lockAndReloadInvoice(tx, persistedId, persisted.tenantId);
1174
+ await (await DocumentTaxCollection.create({ db: tx })).replaceDerivedForDocument(DOCUMENT_MONEY_WRITE, {
1175
+ tenantId: persisted.tenantId,
1176
+ documentType: "invoice",
1177
+ documentId: persistedId,
1178
+ rows: []
1179
+ });
854
1180
  await invoice.deleteDerived(DOCUMENT_MONEY_WRITE, options);
855
1181
  }));
856
1182
  }
857
1183
  //#endregion
858
- export { previewInvoiceMoney as a, materializeInvoiceMoneyDraft as i, getInvoiceMoneyFacts as n, lockAndReloadInvoice as r, document_money_exports as t };
1184
+ export { InvoiceLineItemCollection as a, previewInvoiceMoney as i, getInvoiceMoneyFacts as n, InvoiceLineItem as o, lockAndReloadInvoice as r, document_money_exports as t };
859
1185
 
860
- //# sourceMappingURL=document-money-oUDvdjOf.js.map
1186
+ //# sourceMappingURL=document-money-DV5t4vlK.js.map