@happyvertical/smrt-commerce 0.56.1 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +24 -11
- package/README.md +159 -93
- package/agents/accounting-snapshot-mapper.md +3 -3
- package/agents/commercial-ui.md +2 -2
- package/agents/contract-money.md +9 -6
- package/agents/cost-billing.md +3 -6
- package/agents/customer-vendor-ui.md +6 -1
- package/agents/document-money.md +59 -31
- package/agents/invoice-calculations.md +31 -56
- package/agents/invoice-preparation.md +62 -73
- package/agents/invoice-quantity.md +9 -21
- package/agents/minor-unit-migration.md +4 -4
- package/agents/money-calculator.md +7 -8
- package/agents/money-model.md +18 -22
- package/agents/money-upgrade.md +92 -0
- package/agents/revenue-journal.md +2 -2
- package/agents/tax-codes.md +17 -14
- package/agents/tax-summary.md +12 -8
- package/dist/billing/period-close.d.ts.map +1 -1
- package/dist/billing/runtime.d.ts +5 -2
- package/dist/billing/runtime.d.ts.map +1 -1
- package/dist/chunks/{ContractLineItemCollection-DYjhj_pU.js → ContractLineItemCollection-BZcrlrrY.js} +22 -27
- package/dist/chunks/ContractLineItemCollection-BZcrlrrY.js.map +1 -0
- package/dist/chunks/{CustomerCollection-DQIujn4f.js → CustomerCollection-BIPH2ZUx.js} +3 -3
- package/dist/chunks/{CustomerCollection-DQIujn4f.js.map → CustomerCollection-BIPH2ZUx.js.map} +1 -1
- package/dist/chunks/{DocumentTaxCollection-BEpoqXAQ.js → DocumentTaxCollection-DDzlywMW.js} +41 -14
- package/dist/chunks/DocumentTaxCollection-DDzlywMW.js.map +1 -0
- package/dist/chunks/{InvoiceCollection-CKQflFjc.js → InvoiceCollection-cinzAqt6.js} +53 -164
- package/dist/chunks/InvoiceCollection-cinzAqt6.js.map +1 -0
- package/dist/chunks/{TaxCodeCollection-DOpzW4y8.js → TaxCodeCollection-DaBOPG9c.js} +11 -4
- package/dist/chunks/{TaxCodeCollection-DOpzW4y8.js.map → TaxCodeCollection-DaBOPG9c.js.map} +1 -1
- package/dist/chunks/{TaxComponentCollection-Cs2uXwEl.js → TaxComponentCollection-C4zxnyVu.js} +3 -3
- package/dist/chunks/{TaxComponentCollection-Cs2uXwEl.js.map → TaxComponentCollection-C4zxnyVu.js.map} +1 -1
- package/dist/chunks/VendorCollection-D6ZcUYy8.js +100 -0
- package/dist/chunks/VendorCollection-D6ZcUYy8.js.map +1 -0
- package/dist/chunks/{allocation-integrity-DI3G16BN.js → allocation-integrity-WmWyXhtG.js} +6 -6
- package/dist/chunks/{allocation-integrity-DI3G16BN.js.map → allocation-integrity-WmWyXhtG.js.map} +1 -1
- package/dist/chunks/calculations-C9daQLsh.js +82 -0
- package/dist/chunks/calculations-C9daQLsh.js.map +1 -0
- package/dist/chunks/contract-money-EuToOghh.js +301 -0
- package/dist/chunks/contract-money-EuToOghh.js.map +1 -0
- package/dist/chunks/detect-CY9ufaFb.js +328 -0
- package/dist/chunks/detect-CY9ufaFb.js.map +1 -0
- package/dist/chunks/{document-money-DNVhDJyC.js → document-money-DV5t4vlK.js} +389 -63
- package/dist/chunks/document-money-DV5t4vlK.js.map +1 -0
- package/dist/chunks/{invoice-posting-BwV8g7z0.js → invoice-posting-C2i5dOVZ.js} +21 -23
- package/dist/chunks/invoice-posting-C2i5dOVZ.js.map +1 -0
- package/dist/chunks/{revenue-journal-DY9fro8E.js → revenue-journal-LLA9Kh_i.js} +3 -14
- package/dist/chunks/revenue-journal-LLA9Kh_i.js.map +1 -0
- package/dist/chunks/tenant-money-barrier-6TlqUeVj.js +255 -0
- package/dist/chunks/tenant-money-barrier-6TlqUeVj.js.map +1 -0
- package/dist/chunks/{types-LDETvQ1C.js → types-Bbm0Xflc.js} +2 -1
- package/dist/chunks/types-Bbm0Xflc.js.map +1 -0
- package/dist/chunks/{units-CNcjH_eE.js → units-8ElbjVZK.js} +18 -3
- package/dist/chunks/units-8ElbjVZK.js.map +1 -0
- package/dist/collections/ContractCollection.d.ts.map +1 -1
- package/dist/collections/ContractLineItemCollection.d.ts.map +1 -1
- package/dist/collections/InvoiceCollection.d.ts.map +1 -1
- package/dist/collections/InvoiceLineItemCollection.d.ts +0 -30
- package/dist/collections/InvoiceLineItemCollection.d.ts.map +1 -1
- package/dist/collections/TaxCodeCollection.d.ts +5 -1
- package/dist/collections/TaxCodeCollection.d.ts.map +1 -1
- package/dist/collections/TaxSettingsCollection.d.ts +15 -8
- package/dist/collections/TaxSettingsCollection.d.ts.map +1 -1
- package/dist/collections/TaxSummaryReportCollection.d.ts +3 -3
- package/dist/collections/TaxSummaryReportCollection.d.ts.map +1 -1
- package/dist/collections/index.d.ts +0 -1
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/commerce-money-tools.d.ts.map +1 -1
- package/dist/contract-money.d.ts +1 -13
- package/dist/contract-money.d.ts.map +1 -1
- package/dist/document-money-internal.d.ts +7 -3
- package/dist/document-money-internal.d.ts.map +1 -1
- package/dist/document-money.d.ts +1 -11
- package/dist/document-money.d.ts.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +686 -1656
- package/dist/index.js.map +1 -1
- package/dist/invoice-accounting-sync.d.ts.map +1 -1
- package/dist/invoice-mcp.d.ts +3 -3
- package/dist/invoice-mcp.d.ts.map +1 -1
- package/dist/invoice-posting.d.ts +11 -5
- package/dist/invoice-posting.d.ts.map +1 -1
- package/dist/invoice-record-screen.d.ts +1 -1
- package/dist/invoice-record-screen.d.ts.map +1 -1
- package/dist/invoices.d.ts +6 -1
- package/dist/invoices.d.ts.map +1 -1
- package/dist/invoices.js +2 -2
- package/dist/manifest.json +1041 -863
- package/dist/migrations/invoiceEditorStorage.d.ts +2 -4
- package/dist/migrations/invoiceEditorStorage.d.ts.map +1 -1
- package/dist/migrations/partyLinks.d.ts.map +1 -1
- package/dist/models/Contract.d.ts +10 -4
- package/dist/models/Contract.d.ts.map +1 -1
- package/dist/models/ContractLineItem.d.ts +9 -17
- package/dist/models/ContractLineItem.d.ts.map +1 -1
- package/dist/models/DocumentTax.d.ts.map +1 -1
- package/dist/models/Invoice.d.ts +18 -48
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/InvoiceLineItem.d.ts +13 -32
- package/dist/models/InvoiceLineItem.d.ts.map +1 -1
- package/dist/models/TaxSettings.d.ts +0 -10
- package/dist/models/TaxSettings.d.ts.map +1 -1
- package/dist/models/index.d.ts +1 -2
- package/dist/models/index.d.ts.map +1 -1
- package/dist/playground.js +1 -1
- package/dist/playground.js.map +1 -1
- package/dist/recipes.d.ts +8 -11
- package/dist/recipes.d.ts.map +1 -1
- package/dist/revenue-journal.d.ts +0 -8
- package/dist/revenue-journal.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +2886 -6121
- package/dist/svelte/components/InvoiceEditor.svelte +7 -148
- package/dist/svelte/components/InvoiceEditor.svelte.d.ts +4 -1
- package/dist/svelte/components/InvoiceEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/InvoiceTotals.svelte +14 -118
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts +4 -27
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts.map +1 -1
- package/dist/svelte/components/MoneyInvoiceEditor.svelte +3 -23
- package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts +3 -26
- package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/index.d.ts +2 -3
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +1 -2
- package/dist/svelte/invoices/calculations.d.ts +3 -108
- package/dist/svelte/invoices/calculations.d.ts.map +1 -1
- package/dist/svelte/invoices/calculations.js +12 -309
- package/dist/svelte/invoices/messages.d.ts +1 -37
- package/dist/svelte/invoices/messages.d.ts.map +1 -1
- package/dist/svelte/invoices/messages.js +1 -37
- package/dist/svelte/invoices/money-editor.d.ts +1 -1
- package/dist/svelte/invoices/money-editor.d.ts.map +1 -1
- package/dist/svelte/invoices/types.d.ts +14 -114
- package/dist/svelte/invoices/types.d.ts.map +1 -1
- package/dist/svelte/playground/InvoicePreparationPreview.svelte +85 -94
- package/dist/svelte/playground/InvoicePreparationPreview.svelte.d.ts.map +1 -1
- package/dist/svelte/playground.js +1 -1
- package/dist/tax/index.d.ts +2 -1
- package/dist/tax/index.d.ts.map +1 -1
- package/dist/tax/standard-codes.d.ts +12 -0
- package/dist/tax/standard-codes.d.ts.map +1 -0
- package/dist/tax/tenant-bootstrap.d.ts +29 -0
- package/dist/tax/tenant-bootstrap.d.ts.map +1 -0
- package/dist/tenant-money-barrier.d.ts +12 -44
- package/dist/tenant-money-barrier.d.ts.map +1 -1
- package/dist/types/index.d.ts +11 -23
- package/dist/types/index.d.ts.map +1 -1
- package/dist/ui.js +1 -1
- package/dist/ui.js.map +1 -1
- package/dist/upgrade/detect.d.ts +129 -0
- package/dist/upgrade/detect.d.ts.map +1 -0
- package/dist/upgrade/money-v2.d.ts +81 -0
- package/dist/upgrade/money-v2.d.ts.map +1 -0
- package/package.json +14 -13
- package/agents/line-amount-migration.md +0 -50
- package/dist/chunks/ContractLineItemCollection-DYjhj_pU.js.map +0 -1
- package/dist/chunks/DocumentTaxCollection-BEpoqXAQ.js.map +0 -1
- package/dist/chunks/InvoiceCollection-CKQflFjc.js.map +0 -1
- package/dist/chunks/InvoiceLineItemCollection-CHm9zdqh.js +0 -467
- package/dist/chunks/InvoiceLineItemCollection-CHm9zdqh.js.map +0 -1
- package/dist/chunks/TaxSettingsCollection-BBTZDH1S.js +0 -319
- package/dist/chunks/TaxSettingsCollection-BBTZDH1S.js.map +0 -1
- package/dist/chunks/calculations-DaHR17il.js +0 -333
- package/dist/chunks/calculations-DaHR17il.js.map +0 -1
- package/dist/chunks/document-money-DNVhDJyC.js.map +0 -1
- package/dist/chunks/invoice-posting-BwV8g7z0.js.map +0 -1
- package/dist/chunks/revenue-journal-DY9fro8E.js.map +0 -1
- package/dist/chunks/tenant-money-barrier-DjRXgMnX.js +0 -135
- package/dist/chunks/tenant-money-barrier-DjRXgMnX.js.map +0 -1
- package/dist/chunks/types-LDETvQ1C.js.map +0 -1
- package/dist/chunks/units-CNcjH_eE.js.map +0 -1
- package/dist/collections/MoneyMigrationDocumentCollection.d.ts +0 -12
- package/dist/collections/MoneyMigrationDocumentCollection.d.ts.map +0 -1
- package/dist/migrations/commerceLineAmounts.d.ts +0 -84
- package/dist/migrations/commerceLineAmounts.d.ts.map +0 -1
- package/dist/models/MoneyMigrationDocument.d.ts +0 -28
- package/dist/models/MoneyMigrationDocument.d.ts.map +0 -1
- package/dist/svelte/components/InvoiceLineEditor.svelte +0 -92
- package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts +0 -8
- package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts.map +0 -1
- package/dist/svelte/invoices/fields.d.ts +0 -6
- package/dist/svelte/invoices/fields.d.ts.map +0 -1
- package/dist/svelte/invoices/fields.js +0 -22
- package/dist/tax/legacy.d.ts +0 -48
- package/dist/tax/legacy.d.ts.map +0 -1
|
@@ -1,467 +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-BBTZDH1S.js";
|
|
6
|
-
import { i as withTenantMoneyCollectionRead } from "./tenant-money-barrier-DjRXgMnX.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-DNVhDJyC.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-DNVhDJyC.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 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({ nullable: true })], InvoiceLineItem.prototype, "legacyAmount", 2);
|
|
270
|
-
__decorateClass([field({
|
|
271
|
-
description: "The line total.",
|
|
272
|
-
ui: { format: "money" }
|
|
273
|
-
})], InvoiceLineItem.prototype, "amount", 2);
|
|
274
|
-
__decorateClass([crossPackageRef("@happyvertical/smrt-ledgers:Account", { nullable: true })], InvoiceLineItem.prototype, "revenueAccountId", 2);
|
|
275
|
-
InvoiceLineItem = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
276
|
-
api: {
|
|
277
|
-
include: [
|
|
278
|
-
"list",
|
|
279
|
-
"get",
|
|
280
|
-
"create",
|
|
281
|
-
"update",
|
|
282
|
-
"delete"
|
|
283
|
-
],
|
|
284
|
-
writable: [
|
|
285
|
-
"invoiceId",
|
|
286
|
-
"description",
|
|
287
|
-
"sku",
|
|
288
|
-
"productId",
|
|
289
|
-
"quantity",
|
|
290
|
-
"unitPrice",
|
|
291
|
-
"discount",
|
|
292
|
-
"discountType",
|
|
293
|
-
"discountRate",
|
|
294
|
-
"taxRate",
|
|
295
|
-
"taxMode",
|
|
296
|
-
"taxCodeId",
|
|
297
|
-
"sourceType",
|
|
298
|
-
"sourceId",
|
|
299
|
-
"periodStart",
|
|
300
|
-
"periodEnd",
|
|
301
|
-
"revenueAccountId",
|
|
302
|
-
"sortOrder"
|
|
303
|
-
]
|
|
304
|
-
},
|
|
305
|
-
mcp: { include: ["list", "get"] },
|
|
306
|
-
cli: { skipApiCheck: true }
|
|
307
|
-
})], InvoiceLineItem);
|
|
308
|
-
//#endregion
|
|
309
|
-
//#region src/collections/InvoiceLineItemCollection.ts
|
|
310
|
-
var InvoiceLineItemCollection_exports = /* @__PURE__ */ __exportAll({ InvoiceLineItemCollection: () => InvoiceLineItemCollection });
|
|
311
|
-
var InvoiceLineItemCollection = class extends SmrtCollection {
|
|
312
|
-
static _itemClass = InvoiceLineItem;
|
|
313
|
-
async withMoneyRead(operation) {
|
|
314
|
-
const rootDb = this.db;
|
|
315
|
-
const tenantId = getTenantId();
|
|
316
|
-
if (!tenantId) return operation();
|
|
317
|
-
const result = await withTenantMoneyCollectionRead(rootDb, tenantId, (boundDb) => this.withDatabase(boundDb, operation));
|
|
318
|
-
if (result instanceof InvoiceLineItem) result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);
|
|
319
|
-
else if (Array.isArray(result)) {
|
|
320
|
-
for (const item of result) if (item instanceof InvoiceLineItem) item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);
|
|
321
|
-
}
|
|
322
|
-
return result;
|
|
323
|
-
}
|
|
324
|
-
async get(filter, options = {}) {
|
|
325
|
-
return this.withMoneyRead(() => super.get(filter, options));
|
|
326
|
-
}
|
|
327
|
-
async list(options = {}) {
|
|
328
|
-
return this.withMoneyRead(() => super.list(options));
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Find line items by invoice
|
|
332
|
-
*
|
|
333
|
-
* @param invoiceId - Invoice ID
|
|
334
|
-
* @returns Array of line items, sorted by sortOrder
|
|
335
|
-
*/
|
|
336
|
-
async findByInvoice(invoiceId) {
|
|
337
|
-
return await this.list({
|
|
338
|
-
where: { invoiceId },
|
|
339
|
-
orderBy: "sortOrder ASC"
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Find line items by source
|
|
344
|
-
*
|
|
345
|
-
* @param sourceType - Source type (e.g., 'campaign', 'contract')
|
|
346
|
-
* @param sourceId - Source ID
|
|
347
|
-
* @returns Array of line items
|
|
348
|
-
*/
|
|
349
|
-
async findBySource(sourceType, sourceId) {
|
|
350
|
-
return await this.list({
|
|
351
|
-
where: {
|
|
352
|
-
sourceType,
|
|
353
|
-
sourceId
|
|
354
|
-
},
|
|
355
|
-
orderBy: "created_at DESC"
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Find line items by source type only
|
|
360
|
-
*
|
|
361
|
-
* @param sourceType - Source type (e.g., 'campaign')
|
|
362
|
-
* @returns Array of line items
|
|
363
|
-
*/
|
|
364
|
-
async findBySourceType(sourceType) {
|
|
365
|
-
return await this.list({
|
|
366
|
-
where: { sourceType },
|
|
367
|
-
orderBy: "created_at DESC"
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Calculate total amount for an invoice
|
|
372
|
-
*
|
|
373
|
-
* @param invoiceId - Invoice ID
|
|
374
|
-
* @returns Total amount
|
|
375
|
-
*/
|
|
376
|
-
async getTotalForInvoice(invoiceId) {
|
|
377
|
-
return (await this.findByInvoice(invoiceId)).reduce((sum, item) => sum + item.amount, 0);
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* Calculate subtotal (before tax) for an invoice
|
|
381
|
-
*
|
|
382
|
-
* @param invoiceId - Invoice ID
|
|
383
|
-
* @returns Subtotal
|
|
384
|
-
*/
|
|
385
|
-
async getSubtotalForInvoice(invoiceId) {
|
|
386
|
-
return (await this.findByInvoice(invoiceId)).reduce((sum, item) => sum + item.getSubtotal(), 0);
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Calculate tax amount for an invoice
|
|
390
|
-
*
|
|
391
|
-
* @param invoiceId - Invoice ID
|
|
392
|
-
* @returns Tax amount
|
|
393
|
-
*/
|
|
394
|
-
async getTaxForInvoice(invoiceId) {
|
|
395
|
-
return (await this.findByInvoice(invoiceId)).reduce((sum, item) => sum + item.getTaxAmount(), 0);
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Get the next sort order for an invoice
|
|
399
|
-
*
|
|
400
|
-
* @param invoiceId - Invoice ID
|
|
401
|
-
* @returns Next sort order number
|
|
402
|
-
*/
|
|
403
|
-
async getNextSortOrder(invoiceId) {
|
|
404
|
-
const lineItems = await this.findByInvoice(invoiceId);
|
|
405
|
-
if (lineItems.length === 0) return 0;
|
|
406
|
-
return Math.max(...lineItems.map((item) => item.sortOrder)) + 1;
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Recalculate all line item amounts for an invoice
|
|
410
|
-
*
|
|
411
|
-
* @param invoiceId - Invoice ID
|
|
412
|
-
* @returns Updated line items
|
|
413
|
-
*/
|
|
414
|
-
async recalculateAmounts(invoiceId) {
|
|
415
|
-
const lineItems = await this.findByInvoice(invoiceId);
|
|
416
|
-
for (const item of lineItems) item.amount = item.calculateAmount();
|
|
417
|
-
await Promise.all(lineItems.map((item) => item.save()));
|
|
418
|
-
return lineItems;
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* Convert line items to accounting format for SDK sync
|
|
422
|
-
*
|
|
423
|
-
* @param invoiceId - Invoice ID
|
|
424
|
-
* @returns Array of line items in accounting format, money in integer
|
|
425
|
-
* minor units (`Invoice.toAccountingInput()` converts to major units)
|
|
426
|
-
*/
|
|
427
|
-
async toAccountingLineItems(invoiceId) {
|
|
428
|
-
return (await this.findByInvoice(invoiceId)).map((item) => item.toAccountingLineItem());
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Find all invoice line items belonging to a specific tenant
|
|
432
|
-
*
|
|
433
|
-
* @param tenantId - Tenant ID
|
|
434
|
-
* @returns Array of invoice line items for the tenant
|
|
435
|
-
*/
|
|
436
|
-
async findByTenant(tenantId) {
|
|
437
|
-
return this.list({ where: { tenantId } });
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Find all global invoice line items (not associated with any tenant).
|
|
441
|
-
*
|
|
442
|
-
* Routes through the shared tenant-global helper so it does not throw under
|
|
443
|
-
* an active tenant context (an explicit `tenant_id IS NULL` filter would be
|
|
444
|
-
* flagged as an isolation violation). (#1600)
|
|
445
|
-
*
|
|
446
|
-
* @returns Array of global invoice line items
|
|
447
|
-
*/
|
|
448
|
-
async findGlobal() {
|
|
449
|
-
return queryGlobal(this);
|
|
450
|
-
}
|
|
451
|
-
/**
|
|
452
|
-
* Find invoice line items for a tenant including global line items.
|
|
453
|
-
*
|
|
454
|
-
* Fails closed if an active tenant context requests a different tenant's
|
|
455
|
-
* rows; the admin/system path keeps the cross-tenant capability. (#1600)
|
|
456
|
-
*
|
|
457
|
-
* @param tenantId - Tenant ID
|
|
458
|
-
* @returns Array of tenant-specific and global invoice line items
|
|
459
|
-
*/
|
|
460
|
-
async findWithGlobals(tenantId) {
|
|
461
|
-
return queryWithGlobals(this, tenantId, "InvoiceLineItem.findWithGlobals");
|
|
462
|
-
}
|
|
463
|
-
};
|
|
464
|
-
//#endregion
|
|
465
|
-
export { InvoiceLineItemCollection_exports as n, InvoiceLineItem as r, InvoiceLineItemCollection as t };
|
|
466
|
-
|
|
467
|
-
//# sourceMappingURL=InvoiceLineItemCollection-CHm9zdqh.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"InvoiceLineItemCollection-CHm9zdqh.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 *\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: 'The price of one, before 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 taxAmount = 0;\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).\n */\n @field({ description: 'The line total.', ui: { format: 'money' } })\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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"}
|