@happyvertical/smrt-commerce 0.55.24 → 0.56.1
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 +11 -9
- package/README.md +114 -2
- package/agents/accounting-snapshot-mapper.md +111 -0
- package/agents/contract-money.md +18 -0
- package/agents/cost-billing.md +7 -2
- package/agents/document-money.md +126 -0
- package/agents/invoice-calculations.md +14 -2
- package/agents/line-amount-migration.md +50 -0
- package/agents/minor-unit-migration.md +20 -0
- package/agents/money-calculator.md +45 -0
- package/agents/money-model.md +113 -0
- package/agents/purchasing-ui.md +4 -3
- package/agents/quote-ui.md +3 -2
- package/agents/revenue-journal.md +23 -0
- package/agents/tax-codes.md +48 -0
- package/agents/tax-summary.md +126 -0
- package/dist/accounting-snapshot.d.ts +79 -0
- package/dist/accounting-snapshot.d.ts.map +1 -0
- package/dist/billing/runtime.d.ts +2 -0
- package/dist/billing/runtime.d.ts.map +1 -1
- package/dist/chunks/ContractLineItemCollection-DYjhj_pU.js +265 -0
- package/dist/chunks/ContractLineItemCollection-DYjhj_pU.js.map +1 -0
- package/dist/chunks/CustomerCollection-DQIujn4f.js +99 -0
- package/dist/chunks/CustomerCollection-DQIujn4f.js.map +1 -0
- package/dist/chunks/DocumentTaxCollection-BEpoqXAQ.js +1639 -0
- package/dist/chunks/DocumentTaxCollection-BEpoqXAQ.js.map +1 -0
- package/dist/chunks/InvoiceCollection-CKQflFjc.js +1047 -0
- package/dist/chunks/InvoiceCollection-CKQflFjc.js.map +1 -0
- package/dist/chunks/InvoiceLineItemCollection-CHm9zdqh.js +467 -0
- package/dist/chunks/InvoiceLineItemCollection-CHm9zdqh.js.map +1 -0
- package/dist/chunks/TaxCodeCollection-DOpzW4y8.js +149 -0
- package/dist/chunks/TaxCodeCollection-DOpzW4y8.js.map +1 -0
- package/dist/chunks/TaxComponentCollection-Cs2uXwEl.js +129 -0
- package/dist/chunks/TaxComponentCollection-Cs2uXwEl.js.map +1 -0
- package/dist/chunks/TaxSettingsCollection-BBTZDH1S.js +319 -0
- package/dist/chunks/TaxSettingsCollection-BBTZDH1S.js.map +1 -0
- package/dist/chunks/{money-DfrRxrel.js → allocation-integrity-DI3G16BN.js} +7 -12
- package/dist/chunks/allocation-integrity-DI3G16BN.js.map +1 -0
- package/dist/chunks/{calculations-Bz7RB3qK.js → calculations-DaHR17il.js} +134 -54
- package/dist/chunks/calculations-DaHR17il.js.map +1 -0
- package/dist/chunks/credit-allocation-yspz0Lab.js +121 -0
- package/dist/chunks/credit-allocation-yspz0Lab.js.map +1 -0
- package/dist/chunks/document-money-DNVhDJyC.js +860 -0
- package/dist/chunks/document-money-DNVhDJyC.js.map +1 -0
- package/dist/chunks/invoice-posting-BwV8g7z0.js +229 -0
- package/dist/chunks/invoice-posting-BwV8g7z0.js.map +1 -0
- package/dist/chunks/money-rational-CcW7gzG5.js +64 -0
- package/dist/chunks/money-rational-CcW7gzG5.js.map +1 -0
- package/dist/chunks/revenue-journal-DY9fro8E.js +140 -0
- package/dist/chunks/revenue-journal-DY9fro8E.js.map +1 -0
- package/dist/chunks/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/chunks/tenant-money-barrier-DjRXgMnX.js +135 -0
- package/dist/chunks/tenant-money-barrier-DjRXgMnX.js.map +1 -0
- package/dist/chunks/{types-zVnIjSOk.js → types-LDETvQ1C.js} +3 -14
- package/dist/chunks/types-LDETvQ1C.js.map +1 -0
- package/dist/chunks/{units-BpZ0_Dpk.js → units-CNcjH_eE.js} +2 -2
- package/dist/chunks/{units-BpZ0_Dpk.js.map → units-CNcjH_eE.js.map} +1 -1
- package/dist/collections/ContractCollection.d.ts +37 -1
- package/dist/collections/ContractCollection.d.ts.map +1 -1
- package/dist/collections/ContractLineItemCollection.d.ts +26 -1
- package/dist/collections/ContractLineItemCollection.d.ts.map +1 -1
- package/dist/collections/DocumentTaxCollection.d.ts +75 -0
- package/dist/collections/DocumentTaxCollection.d.ts.map +1 -0
- package/dist/collections/InvoiceCollection.d.ts +26 -1
- package/dist/collections/InvoiceCollection.d.ts.map +1 -1
- package/dist/collections/InvoiceLineItemCollection.d.ts +26 -1
- package/dist/collections/InvoiceLineItemCollection.d.ts.map +1 -1
- package/dist/collections/MoneyMigrationDocumentCollection.d.ts +12 -0
- package/dist/collections/MoneyMigrationDocumentCollection.d.ts.map +1 -0
- package/dist/collections/PaymentAllocationCollection.d.ts +2 -0
- package/dist/collections/PaymentAllocationCollection.d.ts.map +1 -1
- package/dist/collections/PurchaseContractCollection.d.ts +8 -0
- package/dist/collections/PurchaseContractCollection.d.ts.map +1 -0
- package/dist/collections/SalesContractCollection.d.ts +8 -0
- package/dist/collections/SalesContractCollection.d.ts.map +1 -0
- package/dist/collections/TaxCodeCollection.d.ts +7 -0
- package/dist/collections/TaxCodeCollection.d.ts.map +1 -0
- package/dist/collections/TaxComponentCollection.d.ts +6 -0
- package/dist/collections/TaxComponentCollection.d.ts.map +1 -0
- package/dist/collections/TaxSettingsCollection.d.ts +16 -0
- package/dist/collections/TaxSettingsCollection.d.ts.map +1 -0
- package/dist/collections/TaxSummaryReportCollection.d.ts +151 -0
- package/dist/collections/TaxSummaryReportCollection.d.ts.map +1 -0
- package/dist/collections/index.d.ts +8 -0
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/commerce-money-tools.d.ts +9 -0
- package/dist/commerce-money-tools.d.ts.map +1 -0
- package/dist/contract-money.d.ts +27 -0
- package/dist/contract-money.d.ts.map +1 -0
- package/dist/cost-billing.d.ts +0 -1
- package/dist/cost-billing.d.ts.map +1 -1
- package/dist/cost-billing.js +10 -15
- package/dist/cost-billing.js.map +1 -1
- package/dist/credit-allocation.d.ts +48 -0
- package/dist/credit-allocation.d.ts.map +1 -0
- package/dist/document-money-internal.d.ts +44 -0
- package/dist/document-money-internal.d.ts.map +1 -0
- package/dist/document-money.d.ts +85 -0
- package/dist/document-money.d.ts.map +1 -0
- package/dist/index.d.ts +16 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5563 -4243
- package/dist/index.js.map +1 -1
- package/dist/invoice-accounting-sync.d.ts +96 -0
- package/dist/invoice-accounting-sync.d.ts.map +1 -0
- package/dist/invoice-mcp.d.ts +16 -0
- package/dist/invoice-mcp.d.ts.map +1 -0
- package/dist/invoice-posting.d.ts +9 -0
- package/dist/invoice-posting.d.ts.map +1 -0
- package/dist/invoice-record-screen.d.ts +60 -0
- package/dist/invoice-record-screen.d.ts.map +1 -0
- package/dist/invoices.d.ts +2 -0
- package/dist/invoices.d.ts.map +1 -1
- package/dist/invoices.js +3 -2
- package/dist/manifest.json +11605 -4598
- package/dist/migrations/commerceLineAmounts.d.ts +84 -0
- package/dist/migrations/commerceLineAmounts.d.ts.map +1 -0
- package/dist/migrations/partyLinks.d.ts +39 -0
- package/dist/migrations/partyLinks.d.ts.map +1 -0
- package/dist/models/Contract.d.ts +61 -27
- package/dist/models/Contract.d.ts.map +1 -1
- package/dist/models/ContractLineItem.d.ts +30 -1
- package/dist/models/ContractLineItem.d.ts.map +1 -1
- package/dist/models/Customer.d.ts +7 -0
- package/dist/models/Customer.d.ts.map +1 -1
- package/dist/models/DocumentTax.d.ts +50 -0
- package/dist/models/DocumentTax.d.ts.map +1 -0
- package/dist/models/Invoice.d.ts +46 -2
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/InvoiceLineItem.d.ts +33 -2
- package/dist/models/InvoiceLineItem.d.ts.map +1 -1
- package/dist/models/MoneyMigrationDocument.d.ts +28 -0
- package/dist/models/MoneyMigrationDocument.d.ts.map +1 -0
- package/dist/models/Payment.d.ts +5 -1
- package/dist/models/Payment.d.ts.map +1 -1
- package/dist/models/PaymentAllocation.d.ts.map +1 -1
- package/dist/models/TaxCode.d.ts +22 -0
- package/dist/models/TaxCode.d.ts.map +1 -0
- package/dist/models/TaxComponent.d.ts +21 -0
- package/dist/models/TaxComponent.d.ts.map +1 -0
- package/dist/models/TaxSettings.d.ts +33 -0
- package/dist/models/TaxSettings.d.ts.map +1 -0
- package/dist/models/TaxSummaryReport.d.ts +35 -0
- package/dist/models/TaxSummaryReport.d.ts.map +1 -0
- package/dist/models/Vendor.d.ts +9 -0
- package/dist/models/Vendor.d.ts.map +1 -1
- package/dist/models/index.d.ts +7 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/money-rational.d.ts +15 -0
- package/dist/money-rational.d.ts.map +1 -0
- package/dist/money.d.ts +106 -25
- package/dist/money.d.ts.map +1 -1
- package/dist/money.js +274 -0
- package/dist/money.js.map +1 -0
- package/dist/recipes.d.ts +17 -47
- package/dist/recipes.d.ts.map +1 -1
- package/dist/revenue-journal.d.ts +61 -0
- package/dist/revenue-journal.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +6558 -1316
- package/dist/svelte/components/InvoiceActions.svelte +12 -0
- package/dist/svelte/components/InvoiceActions.svelte.d.ts +5 -0
- package/dist/svelte/components/InvoiceActions.svelte.d.ts.map +1 -1
- package/dist/svelte/components/InvoiceEditor.svelte +15 -1
- package/dist/svelte/components/InvoiceEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/InvoiceLineItems.svelte +3 -3
- package/dist/svelte/components/InvoiceRecordScreen.svelte +94 -0
- package/dist/svelte/components/InvoiceRecordScreen.svelte.d.ts +21 -0
- package/dist/svelte/components/InvoiceRecordScreen.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InvoiceTotals.svelte +2 -2
- package/dist/svelte/components/MoneyInvoiceEditor.svelte +282 -0
- package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts +31 -0
- package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts.map +1 -0
- package/dist/svelte/components/PurchaseOrderEditor.svelte +53 -1
- package/dist/svelte/components/PurchaseOrderEditor.svelte.d.ts +5 -0
- package/dist/svelte/components/PurchaseOrderEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/QuoteEditor.svelte +54 -1
- package/dist/svelte/components/QuoteEditor.svelte.d.ts +5 -0
- package/dist/svelte/components/QuoteEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/i18n.d.ts +16 -0
- package/dist/svelte/i18n.d.ts.map +1 -1
- package/dist/svelte/i18n.js +16 -0
- package/dist/svelte/index.d.ts +7 -2
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +4 -1
- package/dist/svelte/invoices/calculations.d.ts +7 -2
- package/dist/svelte/invoices/calculations.d.ts.map +1 -1
- package/dist/svelte/invoices/calculations.js +141 -47
- package/dist/svelte/invoices/money-editor.d.ts +123 -0
- package/dist/svelte/invoices/money-editor.d.ts.map +1 -0
- package/dist/svelte/invoices/money-editor.js +101 -0
- package/dist/svelte/invoices/types.d.ts +5 -1
- package/dist/svelte/invoices/types.d.ts.map +1 -1
- package/dist/svelte/purchasing-i18n.d.ts +5 -0
- package/dist/svelte/purchasing-i18n.d.ts.map +1 -1
- package/dist/svelte/purchasing-i18n.js +5 -0
- package/dist/svelte/quote-i18n.d.ts +5 -0
- package/dist/svelte/quote-i18n.d.ts.map +1 -1
- package/dist/svelte/quote-i18n.js +5 -0
- package/dist/tax/cookbook.d.ts +22 -0
- package/dist/tax/cookbook.d.ts.map +1 -0
- package/dist/tax/example-pack.d.ts +25 -0
- package/dist/tax/example-pack.d.ts.map +1 -0
- package/dist/tax/identity.d.ts +5 -0
- package/dist/tax/identity.d.ts.map +1 -0
- package/dist/tax/index.d.ts +4 -0
- package/dist/tax/index.d.ts.map +1 -0
- package/dist/tax/legacy.d.ts +48 -0
- package/dist/tax/legacy.d.ts.map +1 -0
- package/dist/tax-summary-report-adapter.d.ts +37 -0
- package/dist/tax-summary-report-adapter.d.ts.map +1 -0
- package/dist/tax-summary.d.ts +129 -0
- package/dist/tax-summary.d.ts.map +1 -0
- package/dist/tenant-money-barrier.d.ts +66 -0
- package/dist/tenant-money-barrier.d.ts.map +1 -0
- package/dist/types/index.d.ts +145 -5
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +19 -11
- package/dist/chunks/calculations-Bz7RB3qK.js.map +0 -1
- package/dist/chunks/money-DfrRxrel.js.map +0 -1
- package/dist/chunks/types-zVnIjSOk.js.map +0 -1
package/dist/money.js
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { n as roundSignedRational, t as allocateSignedRationals } from "./chunks/money-rational-CcW7gzG5.js";
|
|
2
|
+
import { ISO_4217_MINOR_UNITS } from "@happyvertical/smrt-ui/currency";
|
|
3
|
+
//#region src/money.ts
|
|
4
|
+
function assertIntegerMinorUnits(context, label, entries) {
|
|
5
|
+
for (const [field, value] of entries) if (!Number.isFinite(value) || !Number.isInteger(value)) throw new Error(`${context} ${label}: ${field} must be an integer number of minor units (cents, satoshis) \u2014 got ${value}. Money is exact: $19.99 is 1999, not 19.99.`);
|
|
6
|
+
}
|
|
7
|
+
var MoneyValidationError = class extends Error {
|
|
8
|
+
constructor(code, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.publicMessage = message;
|
|
12
|
+
}
|
|
13
|
+
code;
|
|
14
|
+
name = "MoneyValidationError";
|
|
15
|
+
/** Explicit marker consumed by public transports that preserve typed errors. */
|
|
16
|
+
publicMessage;
|
|
17
|
+
};
|
|
18
|
+
var PERCENT_SCALE = 1000000n;
|
|
19
|
+
var PERCENT_DENOMINATOR = 100n * PERCENT_SCALE;
|
|
20
|
+
var MAX_SAFE_MONEY = BigInt(Number.MAX_SAFE_INTEGER);
|
|
21
|
+
var IDENTIFIER = /^\S(?:.*\S)?$/;
|
|
22
|
+
function validationError(code, message) {
|
|
23
|
+
throw new MoneyValidationError(code, message);
|
|
24
|
+
}
|
|
25
|
+
function assertIdentifier(value, label) {
|
|
26
|
+
if (typeof value !== "string" || !IDENTIFIER.test(value)) validationError("INVALID_MONEY_INPUT", `${label} must be a nonempty string`);
|
|
27
|
+
}
|
|
28
|
+
function safeMoney(value) {
|
|
29
|
+
if (value > MAX_SAFE_MONEY || value < -MAX_SAFE_MONEY) validationError("UNSAFE_MONEY", "Money exceeds safe integer minor units");
|
|
30
|
+
return Number(value);
|
|
31
|
+
}
|
|
32
|
+
function money(value) {
|
|
33
|
+
if (!Number.isSafeInteger(value)) validationError("UNSAFE_MONEY", "Money must be safe integer minor units");
|
|
34
|
+
return BigInt(value);
|
|
35
|
+
}
|
|
36
|
+
function numberDecimal(value, precision) {
|
|
37
|
+
if (!Number.isFinite(value) || value < 0 || value > Number.MAX_SAFE_INTEGER) validationError("INVALID_MONEY_INPUT", "Quantity is outside the supported range");
|
|
38
|
+
const [mantissa, exponentText = "0"] = value.toString().split("e");
|
|
39
|
+
const [whole, fraction = ""] = mantissa.split(".");
|
|
40
|
+
const places = fraction.length - Number(exponentText);
|
|
41
|
+
if (places > precision) validationError("INVALID_MONEY_INPUT", "Quantity exceeds the supported decimal precision");
|
|
42
|
+
const coefficient = BigInt(whole + fraction);
|
|
43
|
+
return places < 0 ? {
|
|
44
|
+
coefficient: coefficient * 10n ** BigInt(-places),
|
|
45
|
+
scale: 1n
|
|
46
|
+
} : {
|
|
47
|
+
coefficient,
|
|
48
|
+
scale: 10n ** BigInt(places)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function percentUnits(value) {
|
|
52
|
+
if (typeof value !== "string" || !/^(?:0|[1-9]\d{0,2})(?:\.\d{1,6})?$/.test(value)) validationError("PERCENT_OUT_OF_RANGE", "Percent must be an exact decimal from 0 through 100 with at most six fractional digits");
|
|
53
|
+
const [whole, fraction = ""] = value.split(".");
|
|
54
|
+
const units = BigInt(whole) * PERCENT_SCALE + BigInt(fraction.padEnd(6, "0"));
|
|
55
|
+
if (units > PERCENT_DENOMINATOR) validationError("PERCENT_OUT_OF_RANGE", "Percent exceeds 100");
|
|
56
|
+
return units;
|
|
57
|
+
}
|
|
58
|
+
function validateTaxCode(code, rates) {
|
|
59
|
+
if (!code || typeof code !== "object") validationError("INVALID_MONEY_INPUT", "Tax code must be an object");
|
|
60
|
+
assertIdentifier(code.id, "Tax code ID");
|
|
61
|
+
if (code.kind !== "taxable" && code.kind !== "zero-rated" && code.kind !== "exempt" && code.kind !== "out-of-scope") validationError("TAX_CODE_KIND", "Unknown tax code kind");
|
|
62
|
+
if (!Array.isArray(code.components)) validationError("INVALID_MONEY_INPUT", "Tax code components must be an array");
|
|
63
|
+
if (code.kind === "taxable" && code.components.length === 0) validationError("TAX_CODE_TAXABLE_EMPTY", "Taxable codes require at least one component");
|
|
64
|
+
if (code.kind !== "taxable" && code.components.length !== 0) validationError("TAX_CODE_NON_TAXABLE_COMPONENTS", "Non-taxable codes cannot contain components");
|
|
65
|
+
const seen = /* @__PURE__ */ new Set();
|
|
66
|
+
return code.components.map((component) => {
|
|
67
|
+
if (!component || typeof component !== "object") validationError("INVALID_MONEY_INPUT", "Tax component must be an object");
|
|
68
|
+
assertIdentifier(component.taxComponentId, "Tax component ID");
|
|
69
|
+
if (seen.has(component.taxComponentId)) validationError("TAX_CODE_DUPLICATE_COMPONENT", "Duplicate tax component within code");
|
|
70
|
+
seen.add(component.taxComponentId);
|
|
71
|
+
if (typeof component.compound !== "boolean") validationError("INVALID_MONEY_INPUT", "Tax component compound must be boolean");
|
|
72
|
+
if (component.compound) validationError("COMPOUND_UNSUPPORTED", "Compound tax components are not supported");
|
|
73
|
+
const rate = percentUnits(component.percent);
|
|
74
|
+
const existing = rates.get(component.taxComponentId);
|
|
75
|
+
if (existing !== void 0 && existing !== rate) validationError("TAX_COMPONENT_RATE_CONFLICT", "Shared tax component has conflicting percentages");
|
|
76
|
+
rates.set(component.taxComponentId, rate);
|
|
77
|
+
return {
|
|
78
|
+
taxComponentId: component.taxComponentId,
|
|
79
|
+
rate
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function discountFor(gross, discount) {
|
|
84
|
+
if (!discount || typeof discount !== "object") validationError("INVALID_MONEY_INPUT", "Discount must be a tagged object");
|
|
85
|
+
const runtime = discount;
|
|
86
|
+
if (runtime.rate !== void 0 && runtime.minor !== void 0) validationError("DISCOUNT_BOTH_FORMS", "A discount cannot include both percent and amount forms");
|
|
87
|
+
let result;
|
|
88
|
+
if (discount.kind === "none") {
|
|
89
|
+
if (runtime.rate !== void 0 || runtime.minor !== void 0) validationError("DISCOUNT_BOTH_FORMS", "A none discount cannot include percent or amount values");
|
|
90
|
+
result = 0n;
|
|
91
|
+
} else if (discount.kind === "percent") result = roundSignedRational(gross * percentUnits(discount.rate), PERCENT_DENOMINATOR);
|
|
92
|
+
else if (discount.kind === "amount") result = money(discount.minor);
|
|
93
|
+
else validationError("INVALID_MONEY_INPUT", "Unknown discount kind");
|
|
94
|
+
if (result !== 0n && gross !== 0n && result < 0n !== gross < 0n) validationError("DISCOUNT_SIGN", "Discount amount must carry the sign of gross");
|
|
95
|
+
if (gross === 0n && result !== 0n) validationError("DISCOUNT_SIGN", "A zero gross cannot carry a discount");
|
|
96
|
+
const magnitude = (value) => value < 0n ? -value : value;
|
|
97
|
+
if (magnitude(result) > magnitude(gross)) validationError("DISCOUNT_EXCEEDS_GROSS", "Discount cannot exceed gross");
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
function validateDocumentInput(input) {
|
|
101
|
+
if (!input || typeof input !== "object") validationError("INVALID_MONEY_INPUT", "Money input must be an object");
|
|
102
|
+
if (typeof input.currency !== "string" || !/^[A-Z]{3}$/.test(input.currency) || !ISO_4217_MINOR_UNITS.has(input.currency) || ISO_4217_MINOR_UNITS.get(input.currency) === null) validationError("CURRENCY_MISMATCH", "Currency must be a supported uppercase ISO 4217 code with minor units");
|
|
103
|
+
if (input.lineAmountType !== "exclusive" && input.lineAmountType !== "inclusive" && input.lineAmountType !== "none") validationError("INVALID_MONEY_INPUT", "Unknown line amount type");
|
|
104
|
+
if (input.roundingScope !== "line" && input.roundingScope !== "document") validationError("INVALID_MONEY_INPUT", "Unknown tax rounding scope");
|
|
105
|
+
if (!Array.isArray(input.lines)) validationError("INVALID_MONEY_INPUT", "Lines must be an array");
|
|
106
|
+
}
|
|
107
|
+
function calculateMoneyDocument(input) {
|
|
108
|
+
validateDocumentInput(input);
|
|
109
|
+
const ids = /* @__PURE__ */ new Set();
|
|
110
|
+
const rates = /* @__PURE__ */ new Map();
|
|
111
|
+
const working = input.lines.map((line) => {
|
|
112
|
+
if (!line || typeof line !== "object") validationError("INVALID_MONEY_INPUT", "Money line must be an object");
|
|
113
|
+
assertIdentifier(line.id, "Line ID");
|
|
114
|
+
if (ids.has(line.id)) validationError("INVALID_MONEY_INPUT", "Duplicate money line ID");
|
|
115
|
+
ids.add(line.id);
|
|
116
|
+
const explicitNet = line.netAmountMinor === void 0 ? null : money(line.netAmountMinor);
|
|
117
|
+
const quantity = numberDecimal(line.quantity, 6);
|
|
118
|
+
const gross = explicitNet ?? roundSignedRational(quantity.coefficient * money(line.unitPrice), quantity.scale);
|
|
119
|
+
safeMoney(gross);
|
|
120
|
+
const discount = explicitNet === null ? discountFor(gross, line.discount) : 0n;
|
|
121
|
+
const amount = gross - discount;
|
|
122
|
+
safeMoney(amount);
|
|
123
|
+
if (input.lineAmountType === "none" && !line.taxCode) validationError("TAX_CODE_NOT_FOUND", "None pricing requires an out-of-scope tax code");
|
|
124
|
+
if (input.lineAmountType === "none" && line.taxCode?.kind !== "out-of-scope") validationError("TAX_CODE_KIND", "None pricing requires an out-of-scope tax code");
|
|
125
|
+
const components = line.taxCode ? validateTaxCode(line.taxCode, rates) : [];
|
|
126
|
+
const totalRate = components.reduce((sum, component) => sum + component.rate, 0n);
|
|
127
|
+
const denominator = explicitNet === null && input.lineAmountType === "inclusive" ? PERCENT_DENOMINATOR + totalRate : PERCENT_DENOMINATOR;
|
|
128
|
+
return {
|
|
129
|
+
input: line,
|
|
130
|
+
gross,
|
|
131
|
+
discount,
|
|
132
|
+
amount,
|
|
133
|
+
explicitNet,
|
|
134
|
+
exact: input.lineAmountType === "none" ? [] : components.map((component) => ({
|
|
135
|
+
taxComponentId: component.taxComponentId,
|
|
136
|
+
numerator: amount * component.rate,
|
|
137
|
+
denominator
|
|
138
|
+
})),
|
|
139
|
+
taxes: /* @__PURE__ */ new Map()
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
if (input.roundingScope === "line") for (const line of working) for (const component of line.exact) line.taxes.set(component.taxComponentId, roundSignedRational(component.numerator, component.denominator));
|
|
143
|
+
else for (const componentId of [...rates.keys()].sort()) {
|
|
144
|
+
const eligible = working.flatMap((line) => {
|
|
145
|
+
const exact = line.exact.find((component) => component.taxComponentId === componentId);
|
|
146
|
+
return exact ? [{
|
|
147
|
+
line,
|
|
148
|
+
exact
|
|
149
|
+
}] : [];
|
|
150
|
+
});
|
|
151
|
+
const allocated = allocateSignedRationals(eligible.map(({ line, exact }) => ({
|
|
152
|
+
id: line.input.id,
|
|
153
|
+
numerator: exact.numerator,
|
|
154
|
+
denominator: exact.denominator
|
|
155
|
+
})));
|
|
156
|
+
for (const allocation of allocated.allocations) eligible.find(({ line }) => line.input.id === allocation.id)?.line.taxes.set(componentId, allocation.value);
|
|
157
|
+
}
|
|
158
|
+
const lines = working.map((line) => {
|
|
159
|
+
const components = line.exact.map((component) => ({
|
|
160
|
+
taxComponentId: component.taxComponentId,
|
|
161
|
+
taxMinor: safeMoney(line.taxes.get(component.taxComponentId) ?? 0n)
|
|
162
|
+
}));
|
|
163
|
+
const tax2 = components.reduce((sum, component) => sum + BigInt(component.taxMinor), 0n);
|
|
164
|
+
const net = line.explicitNet ?? (input.lineAmountType === "inclusive" ? line.amount - tax2 : line.amount);
|
|
165
|
+
const amount = line.explicitNet !== null && input.lineAmountType === "inclusive" ? net + tax2 : line.amount;
|
|
166
|
+
return {
|
|
167
|
+
id: line.input.id,
|
|
168
|
+
grossMinor: safeMoney(line.gross),
|
|
169
|
+
discountMinor: safeMoney(line.discount),
|
|
170
|
+
amountMinor: safeMoney(amount),
|
|
171
|
+
components,
|
|
172
|
+
taxMinor: safeMoney(tax2),
|
|
173
|
+
netMinor: safeMoney(net)
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
const taxRows = /* @__PURE__ */ new Map();
|
|
177
|
+
for (let index = 0; index < working.length; index++) {
|
|
178
|
+
const source = working[index].input;
|
|
179
|
+
const result = lines[index];
|
|
180
|
+
if (!source.taxCode || source.taxCode.components.length === 0 || input.lineAmountType === "none") {
|
|
181
|
+
const key = `${source.taxCode?.id ?? ""}\0`;
|
|
182
|
+
const row = taxRows.get(key) ?? {
|
|
183
|
+
taxCodeId: source.taxCode?.id ?? null,
|
|
184
|
+
taxComponentId: null,
|
|
185
|
+
taxableMinor: 0,
|
|
186
|
+
taxMinor: 0
|
|
187
|
+
};
|
|
188
|
+
row.taxableMinor = safeMoney(BigInt(row.taxableMinor) + BigInt(result.netMinor));
|
|
189
|
+
taxRows.set(key, row);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
for (const component of result.components) {
|
|
193
|
+
if (!source.taxCode) validationError("INVALID_MONEY_INPUT", "Tax component requires a tax code");
|
|
194
|
+
const key = `${source.taxCode.id}\0${component.taxComponentId}`;
|
|
195
|
+
const row = taxRows.get(key) ?? {
|
|
196
|
+
taxCodeId: source.taxCode.id,
|
|
197
|
+
taxComponentId: component.taxComponentId,
|
|
198
|
+
taxableMinor: 0,
|
|
199
|
+
taxMinor: 0
|
|
200
|
+
};
|
|
201
|
+
row.taxableMinor = safeMoney(BigInt(row.taxableMinor) + BigInt(result.netMinor));
|
|
202
|
+
row.taxMinor = safeMoney(BigInt(row.taxMinor) + BigInt(component.taxMinor));
|
|
203
|
+
taxRows.set(key, row);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const taxes = [...taxRows.values()].sort((left, right) => {
|
|
207
|
+
const leftCode = left.taxCodeId ?? "";
|
|
208
|
+
const rightCode = right.taxCodeId ?? "";
|
|
209
|
+
if (leftCode !== rightCode) return leftCode < rightCode ? -1 : 1;
|
|
210
|
+
const leftComponent = left.taxComponentId ?? "";
|
|
211
|
+
const rightComponent = right.taxComponentId ?? "";
|
|
212
|
+
return leftComponent < rightComponent ? -1 : leftComponent > rightComponent ? 1 : 0;
|
|
213
|
+
});
|
|
214
|
+
const subtotal = lines.reduce((sum, line) => sum + BigInt(line.netMinor), 0n);
|
|
215
|
+
const discountTotal = lines.reduce((sum, line) => sum + BigInt(line.discountMinor), 0n);
|
|
216
|
+
const tax = lines.reduce((sum, line) => sum + BigInt(line.taxMinor), 0n);
|
|
217
|
+
return {
|
|
218
|
+
lines,
|
|
219
|
+
subtotalMinor: safeMoney(subtotal),
|
|
220
|
+
discountTotalMinor: safeMoney(discountTotal),
|
|
221
|
+
taxMinor: safeMoney(tax),
|
|
222
|
+
totalMinor: safeMoney(subtotal + tax),
|
|
223
|
+
taxes
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function selectedCode(id, source, context) {
|
|
227
|
+
if (!id) return null;
|
|
228
|
+
const taxCode = context.codes[id];
|
|
229
|
+
if (!taxCode) validationError("TAX_CODE_NOT_FOUND", `Unknown tax code: ${id}`);
|
|
230
|
+
if (typeof taxCode.active !== "boolean") validationError("INVALID_MONEY_INPUT", `Tax code ${id} has invalid state`);
|
|
231
|
+
if (!taxCode.active) validationError("TAX_CODE_INACTIVE", `Tax code ${id} is inactive`);
|
|
232
|
+
if (taxCode.appliesTo !== "sales" && taxCode.appliesTo !== "purchases" && taxCode.appliesTo !== "both") validationError("INVALID_MONEY_INPUT", `Tax code ${id} has invalid applicability`);
|
|
233
|
+
if (taxCode.appliesTo !== "both" && taxCode.appliesTo !== context.direction) validationError("TAX_CODE_SCOPE", `Tax code ${id} does not apply to ${context.direction}`);
|
|
234
|
+
return {
|
|
235
|
+
taxCode,
|
|
236
|
+
source
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function resolveLineTaxCode(line, context) {
|
|
240
|
+
if (!line || typeof line !== "object" || !context || typeof context !== "object") validationError("INVALID_MONEY_INPUT", "Tax-code resolution inputs must be objects");
|
|
241
|
+
if (!context.codes || typeof context.codes !== "object") validationError("INVALID_MONEY_INPUT", "Tax-code map must be an object");
|
|
242
|
+
if (line.lineAmountType !== "exclusive" && line.lineAmountType !== "inclusive" && line.lineAmountType !== "none") validationError("INVALID_MONEY_INPUT", "Unknown line amount type");
|
|
243
|
+
if (context.direction !== "sales" && context.direction !== "purchases") validationError("INVALID_MONEY_INPUT", "Unknown tax-code direction");
|
|
244
|
+
if (line.lineAmountType === "none") {
|
|
245
|
+
if (!context.outOfScopeCodeId) validationError("TAX_CODE_NOT_FOUND", "None mode requires an out-of-scope tax code");
|
|
246
|
+
const resolved = selectedCode(context.outOfScopeCodeId, "none", context);
|
|
247
|
+
if (resolved?.taxCode?.kind !== "out-of-scope") validationError("TAX_CODE_KIND", "None mode requires an out-of-scope tax code");
|
|
248
|
+
return resolved;
|
|
249
|
+
}
|
|
250
|
+
if (context.customerTaxExempt && !line.lineOverride) {
|
|
251
|
+
if (!context.exemptCodeId) validationError("TAX_CODE_NOT_FOUND", "An exempt customer requires an exempt tax code");
|
|
252
|
+
const exempt = selectedCode(context.exemptCodeId, "exempt-customer", context);
|
|
253
|
+
if (exempt?.taxCode?.kind !== "exempt") validationError("TAX_CODE_KIND", "Customer exemption requires an exempt tax code");
|
|
254
|
+
return exempt;
|
|
255
|
+
}
|
|
256
|
+
const candidates = [
|
|
257
|
+
[line.lineOverride, "line"],
|
|
258
|
+
[context.productCodeId, "product"],
|
|
259
|
+
[context.partyCodeId, "customer"],
|
|
260
|
+
[context.appDefaultCodeId, "app"]
|
|
261
|
+
];
|
|
262
|
+
for (const [id, source] of candidates) {
|
|
263
|
+
const resolved = selectedCode(id, source, context);
|
|
264
|
+
if (resolved) return resolved;
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
taxCode: null,
|
|
268
|
+
source: "none"
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
//#endregion
|
|
272
|
+
export { MoneyValidationError, assertIntegerMinorUnits, calculateMoneyDocument, resolveLineTaxCode };
|
|
273
|
+
|
|
274
|
+
//# sourceMappingURL=money.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"money.js","names":["tax"],"sources":["../src/money.ts"],"sourcesContent":["/** Exact, transport-neutral commercial document money calculation. */\n\nimport { ISO_4217_MINOR_UNITS } from '@happyvertical/smrt-ui/currency';\nimport {\n allocateSignedRationals,\n roundSignedRational,\n} from './money-rational.js';\n\n/** Throw unless every named model value is a finite integer minor-unit amount. */\nexport function assertIntegerMinorUnits(\n context: string,\n label: string,\n entries: ReadonlyArray<readonly [string, number]>,\n): void {\n for (const [field, value] of entries) {\n if (!Number.isFinite(value) || !Number.isInteger(value)) {\n throw new Error(\n `${context} ${label}: ${field} must be an integer number of minor ` +\n `units (cents, satoshis) — got ${value}. Money is exact: $19.99 is ` +\n '1999, not 19.99.',\n );\n }\n }\n}\n\nexport type LineAmountType = 'exclusive' | 'inclusive' | 'none';\nexport type TaxRoundingScope = 'line' | 'document';\nexport type TaxCodeKind = 'taxable' | 'zero-rated' | 'exempt' | 'out-of-scope';\nexport type TaxCodeAppliesTo = 'sales' | 'purchases' | 'both';\n\nexport type MoneyValidationCode =\n | 'DISCOUNT_BOTH_FORMS'\n | 'DISCOUNT_EXCEEDS_GROSS'\n | 'DISCOUNT_SIGN'\n | 'PERCENT_OUT_OF_RANGE'\n | 'COMPOUND_UNSUPPORTED'\n | 'INVALID_MONEY_INPUT'\n | 'TAX_CODE_DUPLICATE_COMPONENT'\n | 'TAX_CODE_KIND'\n | 'TAX_CODE_NON_TAXABLE_COMPONENTS'\n | 'TAX_CODE_NOT_FOUND'\n | 'TAX_CODE_TAXABLE_EMPTY'\n | 'TAX_COMPONENT_RATE_CONFLICT'\n | 'TAX_CODE_INACTIVE'\n | 'TAX_CODE_SCOPE'\n | 'UNSAFE_MONEY'\n | 'FROZEN_DOCUMENT'\n | 'CURRENCY_MISMATCH'\n | 'ACCOUNTING_SYNC_IN_PROGRESS'\n | 'ACCOUNTING_SYNC_RECONCILIATION_REQUIRED'\n | 'ACCOUNTING_SYNC_UNSUPPORTED'\n | 'CREDIT_EXCEEDS_LINE'\n | 'CREDIT_TARGET_NOT_ISSUED';\n\n/** Stable validation error shared by model, editor, and transport adapters. */\nexport class MoneyValidationError extends Error {\n override readonly name = 'MoneyValidationError';\n /** Explicit marker consumed by public transports that preserve typed errors. */\n readonly publicMessage: string;\n\n constructor(\n readonly code: MoneyValidationCode,\n message: string,\n ) {\n super(message);\n this.publicMessage = message;\n }\n}\n\nexport interface TaxComponentInput {\n taxComponentId: string;\n /** Exact percent: \"7\" means 7%; at most six fractional digits. */\n percent: string;\n compound: boolean;\n}\n\nexport interface MoneyTaxCodeInput {\n id: string;\n kind: TaxCodeKind;\n components: readonly TaxComponentInput[];\n}\n\nexport interface ResolvableTaxCodeInput extends MoneyTaxCodeInput {\n active: boolean;\n appliesTo: TaxCodeAppliesTo;\n}\n\nexport type MoneyDiscountInput =\n | { kind: 'none' }\n | { kind: 'percent'; rate: string }\n | { kind: 'amount'; minor: number };\n\nexport interface MoneyLineInput {\n id: string;\n /** Nonnegative decimal quantity with at most six fractional digits. */\n quantity: number;\n /** Signed safe integer minor units. */\n unitPrice: number;\n discount: MoneyDiscountInput;\n /** Explicit tax-exclusive basis for credit-note amount allocations. */\n netAmountMinor?: number;\n /** Null means no code resolved; `none` pricing requires an out-of-scope code. */\n taxCode: MoneyTaxCodeInput | null;\n}\n\nexport interface MoneyLineResult {\n id: string;\n grossMinor: number;\n discountMinor: number;\n amountMinor: number;\n components: { taxComponentId: string; taxMinor: number }[];\n taxMinor: number;\n netMinor: number;\n}\n\nexport interface MoneyDocumentTaxResult {\n /** Null records an unassigned line without inventing a persisted tax-code ID. */\n taxCodeId: string | null;\n taxComponentId: string | null;\n taxableMinor: number;\n taxMinor: number;\n}\n\nexport interface MoneyDocumentResult {\n lines: MoneyLineResult[];\n subtotalMinor: number;\n discountTotalMinor: number;\n taxMinor: number;\n totalMinor: number;\n taxes: MoneyDocumentTaxResult[];\n}\n\nexport type TaxCodeResolutionSource =\n | 'line'\n | 'exempt-customer'\n | 'product'\n | 'customer'\n | 'app'\n | 'none';\n\nexport interface ResolveLineTaxCodeInput {\n lineAmountType: LineAmountType;\n lineOverride?: string | null;\n}\n\nexport interface ResolveLineTaxCodeContext {\n direction: 'sales' | 'purchases';\n codes: Readonly<Record<string, ResolvableTaxCodeInput>>;\n customerTaxExempt: boolean;\n exemptCodeId?: string | null;\n productCodeId?: string | null;\n partyCodeId?: string | null;\n appDefaultCodeId?: string | null;\n outOfScopeCodeId?: string | null;\n}\n\nexport interface ResolvedLineTaxCode {\n taxCode: ResolvableTaxCodeInput | null;\n source: TaxCodeResolutionSource;\n}\n\nconst PERCENT_SCALE = 1_000_000n;\nconst PERCENT_DENOMINATOR = 100n * PERCENT_SCALE;\nconst MAX_SAFE_MONEY = BigInt(Number.MAX_SAFE_INTEGER);\nconst IDENTIFIER = /^\\S(?:.*\\S)?$/;\n\nfunction validationError(code: MoneyValidationCode, message: string): never {\n throw new MoneyValidationError(code, message);\n}\n\nfunction assertIdentifier(value: string, label: string): void {\n if (typeof value !== 'string' || !IDENTIFIER.test(value))\n validationError(\n 'INVALID_MONEY_INPUT',\n `${label} must be a nonempty string`,\n );\n}\n\nfunction safeMoney(value: bigint): number {\n if (value > MAX_SAFE_MONEY || value < -MAX_SAFE_MONEY)\n validationError('UNSAFE_MONEY', 'Money exceeds safe integer minor units');\n return Number(value);\n}\n\nfunction money(value: number): bigint {\n if (!Number.isSafeInteger(value))\n validationError('UNSAFE_MONEY', 'Money must be safe integer minor units');\n return BigInt(value);\n}\n\ninterface ExactDecimal {\n coefficient: bigint;\n scale: bigint;\n}\n\nfunction numberDecimal(value: number, precision: number): ExactDecimal {\n if (!Number.isFinite(value) || value < 0 || value > Number.MAX_SAFE_INTEGER)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Quantity is outside the supported range',\n );\n const [mantissa, exponentText = '0'] = value.toString().split('e');\n const [whole, fraction = ''] = mantissa.split('.');\n const places = fraction.length - Number(exponentText);\n if (places > precision)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Quantity exceeds the supported decimal precision',\n );\n const coefficient = BigInt(whole + fraction);\n return places < 0\n ? { coefficient: coefficient * 10n ** BigInt(-places), scale: 1n }\n : { coefficient, scale: 10n ** BigInt(places) };\n}\n\nfunction percentUnits(value: string): bigint {\n if (\n typeof value !== 'string' ||\n !/^(?:0|[1-9]\\d{0,2})(?:\\.\\d{1,6})?$/.test(value)\n )\n validationError(\n 'PERCENT_OUT_OF_RANGE',\n 'Percent must be an exact decimal from 0 through 100 with at most six fractional digits',\n );\n const [whole, fraction = ''] = value.split('.');\n const units = BigInt(whole) * PERCENT_SCALE + BigInt(fraction.padEnd(6, '0'));\n if (units > PERCENT_DENOMINATOR)\n validationError('PERCENT_OUT_OF_RANGE', 'Percent exceeds 100');\n return units;\n}\n\nfunction validateTaxCode(\n code: MoneyTaxCodeInput,\n rates: Map<string, bigint>,\n): { taxComponentId: string; rate: bigint }[] {\n if (!code || typeof code !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax code must be an object');\n assertIdentifier(code.id, 'Tax code ID');\n if (\n code.kind !== 'taxable' &&\n code.kind !== 'zero-rated' &&\n code.kind !== 'exempt' &&\n code.kind !== 'out-of-scope'\n )\n validationError('TAX_CODE_KIND', 'Unknown tax code kind');\n if (!Array.isArray(code.components))\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax code components must be an array',\n );\n if (code.kind === 'taxable' && code.components.length === 0)\n validationError(\n 'TAX_CODE_TAXABLE_EMPTY',\n 'Taxable codes require at least one component',\n );\n if (code.kind !== 'taxable' && code.components.length !== 0)\n validationError(\n 'TAX_CODE_NON_TAXABLE_COMPONENTS',\n 'Non-taxable codes cannot contain components',\n );\n const seen = new Set<string>();\n return code.components.map((component) => {\n if (!component || typeof component !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax component must be an object');\n assertIdentifier(component.taxComponentId, 'Tax component ID');\n if (seen.has(component.taxComponentId))\n validationError(\n 'TAX_CODE_DUPLICATE_COMPONENT',\n 'Duplicate tax component within code',\n );\n seen.add(component.taxComponentId);\n if (typeof component.compound !== 'boolean')\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax component compound must be boolean',\n );\n if (component.compound)\n validationError(\n 'COMPOUND_UNSUPPORTED',\n 'Compound tax components are not supported',\n );\n const rate = percentUnits(component.percent);\n const existing = rates.get(component.taxComponentId);\n if (existing !== undefined && existing !== rate)\n validationError(\n 'TAX_COMPONENT_RATE_CONFLICT',\n 'Shared tax component has conflicting percentages',\n );\n rates.set(component.taxComponentId, rate);\n return { taxComponentId: component.taxComponentId, rate };\n });\n}\n\nfunction discountFor(gross: bigint, discount: MoneyDiscountInput): bigint {\n if (!discount || typeof discount !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Discount must be a tagged object');\n const runtime = discount as MoneyDiscountInput & {\n rate?: unknown;\n minor?: unknown;\n };\n if (runtime.rate !== undefined && runtime.minor !== undefined)\n validationError(\n 'DISCOUNT_BOTH_FORMS',\n 'A discount cannot include both percent and amount forms',\n );\n let result: bigint;\n if (discount.kind === 'none') {\n if (runtime.rate !== undefined || runtime.minor !== undefined)\n validationError(\n 'DISCOUNT_BOTH_FORMS',\n 'A none discount cannot include percent or amount values',\n );\n result = 0n;\n } else if (discount.kind === 'percent') {\n result = roundSignedRational(\n gross * percentUnits(discount.rate),\n PERCENT_DENOMINATOR,\n );\n } else if (discount.kind === 'amount') {\n result = money(discount.minor);\n } else {\n validationError('INVALID_MONEY_INPUT', 'Unknown discount kind');\n }\n if (result !== 0n && gross !== 0n && result < 0n !== gross < 0n)\n validationError(\n 'DISCOUNT_SIGN',\n 'Discount amount must carry the sign of gross',\n );\n if (gross === 0n && result !== 0n)\n validationError('DISCOUNT_SIGN', 'A zero gross cannot carry a discount');\n const magnitude = (value: bigint) => (value < 0n ? -value : value);\n if (magnitude(result) > magnitude(gross))\n validationError('DISCOUNT_EXCEEDS_GROSS', 'Discount cannot exceed gross');\n return result;\n}\n\nfunction validateDocumentInput(input: {\n currency: string;\n lineAmountType: LineAmountType;\n roundingScope: TaxRoundingScope;\n lines: readonly MoneyLineInput[];\n}): void {\n if (!input || typeof input !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Money input must be an object');\n if (\n typeof input.currency !== 'string' ||\n !/^[A-Z]{3}$/.test(input.currency) ||\n !ISO_4217_MINOR_UNITS.has(input.currency) ||\n ISO_4217_MINOR_UNITS.get(input.currency) === null\n )\n validationError(\n 'CURRENCY_MISMATCH',\n 'Currency must be a supported uppercase ISO 4217 code with minor units',\n );\n if (\n input.lineAmountType !== 'exclusive' &&\n input.lineAmountType !== 'inclusive' &&\n input.lineAmountType !== 'none'\n )\n validationError('INVALID_MONEY_INPUT', 'Unknown line amount type');\n if (input.roundingScope !== 'line' && input.roundingScope !== 'document')\n validationError('INVALID_MONEY_INPUT', 'Unknown tax rounding scope');\n if (!Array.isArray(input.lines))\n validationError('INVALID_MONEY_INPUT', 'Lines must be an array');\n}\n\n/** Calculate exact line amounts, per-component tax, and document totals. */\nexport function calculateMoneyDocument(input: {\n currency: string;\n lineAmountType: LineAmountType;\n roundingScope: TaxRoundingScope;\n lines: readonly MoneyLineInput[];\n}): MoneyDocumentResult {\n validateDocumentInput(input);\n const ids = new Set<string>();\n const rates = new Map<string, bigint>();\n const working = input.lines.map((line) => {\n if (!line || typeof line !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Money line must be an object');\n assertIdentifier(line.id, 'Line ID');\n if (ids.has(line.id))\n validationError('INVALID_MONEY_INPUT', 'Duplicate money line ID');\n ids.add(line.id);\n const explicitNet =\n line.netAmountMinor === undefined ? null : money(line.netAmountMinor);\n const quantity = numberDecimal(line.quantity, 6);\n const gross =\n explicitNet ??\n roundSignedRational(\n quantity.coefficient * money(line.unitPrice),\n quantity.scale,\n );\n safeMoney(gross);\n const discount =\n explicitNet === null ? discountFor(gross, line.discount) : 0n;\n const amount = gross - discount;\n safeMoney(amount);\n if (input.lineAmountType === 'none' && !line.taxCode)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'None pricing requires an out-of-scope tax code',\n );\n if (\n input.lineAmountType === 'none' &&\n line.taxCode?.kind !== 'out-of-scope'\n )\n validationError(\n 'TAX_CODE_KIND',\n 'None pricing requires an out-of-scope tax code',\n );\n const components = line.taxCode ? validateTaxCode(line.taxCode, rates) : [];\n const totalRate = components.reduce(\n (sum, component) => sum + component.rate,\n 0n,\n );\n const denominator =\n explicitNet === null && input.lineAmountType === 'inclusive'\n ? PERCENT_DENOMINATOR + totalRate\n : PERCENT_DENOMINATOR;\n return {\n input: line,\n gross,\n discount,\n amount,\n explicitNet,\n exact:\n input.lineAmountType === 'none'\n ? []\n : components.map((component) => ({\n taxComponentId: component.taxComponentId,\n numerator: amount * component.rate,\n denominator,\n })),\n taxes: new Map<string, bigint>(),\n };\n });\n\n if (input.roundingScope === 'line') {\n for (const line of working)\n for (const component of line.exact)\n line.taxes.set(\n component.taxComponentId,\n roundSignedRational(component.numerator, component.denominator),\n );\n } else {\n for (const componentId of [...rates.keys()].sort()) {\n const eligible = working.flatMap((line) => {\n const exact = line.exact.find(\n (component) => component.taxComponentId === componentId,\n );\n return exact ? [{ line, exact }] : [];\n });\n const allocated = allocateSignedRationals(\n eligible.map(({ line, exact }) => ({\n id: line.input.id,\n numerator: exact.numerator,\n denominator: exact.denominator,\n })),\n );\n for (const allocation of allocated.allocations)\n eligible\n .find(({ line }) => line.input.id === allocation.id)\n ?.line.taxes.set(componentId, allocation.value);\n }\n }\n\n const lines = working.map((line): MoneyLineResult => {\n const components = line.exact.map((component) => ({\n taxComponentId: component.taxComponentId,\n taxMinor: safeMoney(line.taxes.get(component.taxComponentId) ?? 0n),\n }));\n const tax = components.reduce(\n (sum, component) => sum + BigInt(component.taxMinor),\n 0n,\n );\n const net =\n line.explicitNet ??\n (input.lineAmountType === 'inclusive' ? line.amount - tax : line.amount);\n const amount =\n line.explicitNet !== null && input.lineAmountType === 'inclusive'\n ? net + tax\n : line.amount;\n return {\n id: line.input.id,\n grossMinor: safeMoney(line.gross),\n discountMinor: safeMoney(line.discount),\n amountMinor: safeMoney(amount),\n components,\n taxMinor: safeMoney(tax),\n netMinor: safeMoney(net),\n };\n });\n\n const taxRows = new Map<string, MoneyDocumentTaxResult>();\n for (let index = 0; index < working.length; index++) {\n const source = working[index].input;\n const result = lines[index];\n if (\n !source.taxCode ||\n source.taxCode.components.length === 0 ||\n input.lineAmountType === 'none'\n ) {\n const key = `${source.taxCode?.id ?? ''}\\u0000`;\n const row = taxRows.get(key) ?? {\n taxCodeId: source.taxCode?.id ?? null,\n taxComponentId: null,\n taxableMinor: 0,\n taxMinor: 0,\n };\n row.taxableMinor = safeMoney(\n BigInt(row.taxableMinor) + BigInt(result.netMinor),\n );\n taxRows.set(key, row);\n continue;\n }\n for (const component of result.components) {\n if (!source.taxCode)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax component requires a tax code',\n );\n const key = `${source.taxCode.id}\\u0000${component.taxComponentId}`;\n const row = taxRows.get(key) ?? {\n taxCodeId: source.taxCode.id,\n taxComponentId: component.taxComponentId,\n taxableMinor: 0,\n taxMinor: 0,\n };\n row.taxableMinor = safeMoney(\n BigInt(row.taxableMinor) + BigInt(result.netMinor),\n );\n row.taxMinor = safeMoney(\n BigInt(row.taxMinor) + BigInt(component.taxMinor),\n );\n taxRows.set(key, row);\n }\n }\n const taxes = [...taxRows.values()].sort((left, right) => {\n const leftCode = left.taxCodeId ?? '';\n const rightCode = right.taxCodeId ?? '';\n if (leftCode !== rightCode) return leftCode < rightCode ? -1 : 1;\n const leftComponent = left.taxComponentId ?? '';\n const rightComponent = right.taxComponentId ?? '';\n return leftComponent < rightComponent\n ? -1\n : leftComponent > rightComponent\n ? 1\n : 0;\n });\n const subtotal = lines.reduce((sum, line) => sum + BigInt(line.netMinor), 0n);\n const discountTotal = lines.reduce(\n (sum, line) => sum + BigInt(line.discountMinor),\n 0n,\n );\n const tax = lines.reduce((sum, line) => sum + BigInt(line.taxMinor), 0n);\n return {\n lines,\n subtotalMinor: safeMoney(subtotal),\n discountTotalMinor: safeMoney(discountTotal),\n taxMinor: safeMoney(tax),\n totalMinor: safeMoney(subtotal + tax),\n taxes,\n };\n}\n\nfunction selectedCode(\n id: string | null | undefined,\n source: TaxCodeResolutionSource,\n context: ResolveLineTaxCodeContext,\n): ResolvedLineTaxCode | null {\n if (!id) return null;\n const taxCode = context.codes[id];\n if (!taxCode)\n validationError('TAX_CODE_NOT_FOUND', `Unknown tax code: ${id}`);\n if (typeof taxCode.active !== 'boolean')\n validationError('INVALID_MONEY_INPUT', `Tax code ${id} has invalid state`);\n if (!taxCode.active)\n validationError('TAX_CODE_INACTIVE', `Tax code ${id} is inactive`);\n if (\n taxCode.appliesTo !== 'sales' &&\n taxCode.appliesTo !== 'purchases' &&\n taxCode.appliesTo !== 'both'\n )\n validationError(\n 'INVALID_MONEY_INPUT',\n `Tax code ${id} has invalid applicability`,\n );\n if (taxCode.appliesTo !== 'both' && taxCode.appliesTo !== context.direction)\n validationError(\n 'TAX_CODE_SCOPE',\n `Tax code ${id} does not apply to ${context.direction}`,\n );\n return { taxCode, source };\n}\n\n/** Resolve a line tax code from already-loaded values, without model or I/O access. */\nexport function resolveLineTaxCode(\n line: ResolveLineTaxCodeInput,\n context: ResolveLineTaxCodeContext,\n): ResolvedLineTaxCode {\n if (\n !line ||\n typeof line !== 'object' ||\n !context ||\n typeof context !== 'object'\n )\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax-code resolution inputs must be objects',\n );\n if (!context.codes || typeof context.codes !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax-code map must be an object');\n if (\n line.lineAmountType !== 'exclusive' &&\n line.lineAmountType !== 'inclusive' &&\n line.lineAmountType !== 'none'\n )\n validationError('INVALID_MONEY_INPUT', 'Unknown line amount type');\n if (context.direction !== 'sales' && context.direction !== 'purchases')\n validationError('INVALID_MONEY_INPUT', 'Unknown tax-code direction');\n if (line.lineAmountType === 'none') {\n if (!context.outOfScopeCodeId)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'None mode requires an out-of-scope tax code',\n );\n const resolved = selectedCode(context.outOfScopeCodeId, 'none', context);\n if (resolved?.taxCode?.kind !== 'out-of-scope')\n validationError(\n 'TAX_CODE_KIND',\n 'None mode requires an out-of-scope tax code',\n );\n return resolved;\n }\n if (context.customerTaxExempt && !line.lineOverride) {\n if (!context.exemptCodeId)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'An exempt customer requires an exempt tax code',\n );\n const exempt = selectedCode(\n context.exemptCodeId,\n 'exempt-customer',\n context,\n );\n if (exempt?.taxCode?.kind !== 'exempt')\n validationError(\n 'TAX_CODE_KIND',\n 'Customer exemption requires an exempt tax code',\n );\n return exempt;\n }\n const candidates: readonly [\n string | null | undefined,\n TaxCodeResolutionSource,\n ][] = [\n [line.lineOverride, 'line'],\n [context.productCodeId, 'product'],\n [context.partyCodeId, 'customer'],\n [context.appDefaultCodeId, 'app'],\n ];\n for (const [id, source] of candidates) {\n const resolved = selectedCode(id, source, context);\n if (resolved) return resolved;\n }\n return { taxCode: null, source: 'none' };\n}\n"],"mappings":"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"}
|
package/dist/recipes.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
import { SmrtRecipe } from '@happyvertical/smrt-core';
|
|
10
|
-
import {
|
|
10
|
+
import { Contract, Estimate, Lease, LicenseSale, Order, PurchaseOrder, WholesaleOrder } from './models/Contract.js';
|
|
11
11
|
import { ContractLineItem } from './models/ContractLineItem.js';
|
|
12
12
|
import { Customer } from './models/Customer.js';
|
|
13
13
|
import { Fulfillment } from './models/Fulfillment.js';
|
|
@@ -61,7 +61,7 @@ export declare class PurchasesRecipe extends SmrtRecipe {
|
|
|
61
61
|
icon: string;
|
|
62
62
|
description: string;
|
|
63
63
|
};
|
|
64
|
-
static models: (typeof
|
|
64
|
+
static models: (typeof ContractLineItem | typeof PurchaseOrder)[];
|
|
65
65
|
static nav: {
|
|
66
66
|
label: string;
|
|
67
67
|
model: typeof PurchaseOrder;
|
|
@@ -77,10 +77,6 @@ export declare class PurchasesRecipe extends SmrtRecipe {
|
|
|
77
77
|
readonly visibility: "hidden";
|
|
78
78
|
readonly locked: true;
|
|
79
79
|
};
|
|
80
|
-
readonly customerId: {
|
|
81
|
-
readonly visibility: "hidden";
|
|
82
|
-
readonly locked: true;
|
|
83
|
-
};
|
|
84
80
|
readonly vendorId: {
|
|
85
81
|
readonly label: "Vendor";
|
|
86
82
|
readonly order: 1;
|
|
@@ -114,7 +110,7 @@ export declare class PurchasesRecipe extends SmrtRecipe {
|
|
|
114
110
|
readonly visibility: "hidden";
|
|
115
111
|
};
|
|
116
112
|
readonly taxRate: {
|
|
117
|
-
readonly help: "
|
|
113
|
+
readonly help: "Stored fraction: 0.05 means 5%.";
|
|
118
114
|
};
|
|
119
115
|
};
|
|
120
116
|
};
|
|
@@ -133,7 +129,7 @@ export declare class SalesRecipe extends SmrtRecipe {
|
|
|
133
129
|
icon: string;
|
|
134
130
|
description: string;
|
|
135
131
|
};
|
|
136
|
-
static models: (typeof
|
|
132
|
+
static models: (typeof ContractLineItem | typeof Order)[];
|
|
137
133
|
static nav: {
|
|
138
134
|
label: string;
|
|
139
135
|
model: typeof Order;
|
|
@@ -149,14 +145,9 @@ export declare class SalesRecipe extends SmrtRecipe {
|
|
|
149
145
|
readonly visibility: "hidden";
|
|
150
146
|
readonly locked: true;
|
|
151
147
|
};
|
|
152
|
-
readonly vendorId: {
|
|
153
|
-
readonly visibility: "hidden";
|
|
154
|
-
readonly locked: true;
|
|
155
|
-
};
|
|
156
148
|
readonly customerId: {
|
|
157
149
|
readonly label: "Customer";
|
|
158
150
|
readonly order: 1;
|
|
159
|
-
readonly required: true;
|
|
160
151
|
};
|
|
161
152
|
readonly channelId: {
|
|
162
153
|
readonly visibility: "hidden";
|
|
@@ -187,7 +178,7 @@ export declare class SalesRecipe extends SmrtRecipe {
|
|
|
187
178
|
readonly visibility: "hidden";
|
|
188
179
|
};
|
|
189
180
|
readonly taxRate: {
|
|
190
|
-
readonly help: "
|
|
181
|
+
readonly help: "Stored fraction: 0.05 means 5%.";
|
|
191
182
|
};
|
|
192
183
|
};
|
|
193
184
|
};
|
|
@@ -237,7 +228,7 @@ export declare class EstimatesRecipe extends SmrtRecipe {
|
|
|
237
228
|
icon: string;
|
|
238
229
|
description: string;
|
|
239
230
|
};
|
|
240
|
-
static models: (typeof
|
|
231
|
+
static models: (typeof ContractLineItem | typeof Estimate)[];
|
|
241
232
|
static nav: {
|
|
242
233
|
label: string;
|
|
243
234
|
model: typeof Estimate;
|
|
@@ -253,14 +244,9 @@ export declare class EstimatesRecipe extends SmrtRecipe {
|
|
|
253
244
|
readonly visibility: "hidden";
|
|
254
245
|
readonly locked: true;
|
|
255
246
|
};
|
|
256
|
-
readonly vendorId: {
|
|
257
|
-
readonly visibility: "hidden";
|
|
258
|
-
readonly locked: true;
|
|
259
|
-
};
|
|
260
247
|
readonly customerId: {
|
|
261
248
|
readonly label: "Customer";
|
|
262
249
|
readonly order: 1;
|
|
263
|
-
readonly required: true;
|
|
264
250
|
};
|
|
265
251
|
readonly channelId: {
|
|
266
252
|
readonly visibility: "hidden";
|
|
@@ -288,7 +274,7 @@ export declare class EstimatesRecipe extends SmrtRecipe {
|
|
|
288
274
|
readonly visibility: "hidden";
|
|
289
275
|
};
|
|
290
276
|
readonly taxRate: {
|
|
291
|
-
readonly help: "
|
|
277
|
+
readonly help: "Stored fraction: 0.05 means 5%.";
|
|
292
278
|
};
|
|
293
279
|
};
|
|
294
280
|
};
|
|
@@ -307,7 +293,7 @@ export declare class WholesaleRecipe extends SmrtRecipe {
|
|
|
307
293
|
icon: string;
|
|
308
294
|
description: string;
|
|
309
295
|
};
|
|
310
|
-
static models: (typeof
|
|
296
|
+
static models: (typeof ContractLineItem | typeof WholesaleOrder)[];
|
|
311
297
|
static nav: {
|
|
312
298
|
label: string;
|
|
313
299
|
model: typeof WholesaleOrder;
|
|
@@ -323,10 +309,6 @@ export declare class WholesaleRecipe extends SmrtRecipe {
|
|
|
323
309
|
readonly visibility: "hidden";
|
|
324
310
|
readonly locked: true;
|
|
325
311
|
};
|
|
326
|
-
readonly vendorId: {
|
|
327
|
-
readonly visibility: "hidden";
|
|
328
|
-
readonly locked: true;
|
|
329
|
-
};
|
|
330
312
|
readonly customerId: {
|
|
331
313
|
readonly label: "Customer";
|
|
332
314
|
readonly order: 1;
|
|
@@ -360,7 +342,7 @@ export declare class WholesaleRecipe extends SmrtRecipe {
|
|
|
360
342
|
readonly visibility: "hidden";
|
|
361
343
|
};
|
|
362
344
|
readonly taxRate: {
|
|
363
|
-
readonly help: "
|
|
345
|
+
readonly help: "Stored fraction: 0.05 means 5%.";
|
|
364
346
|
};
|
|
365
347
|
};
|
|
366
348
|
};
|
|
@@ -384,7 +366,7 @@ export declare class InvoicingRecipe extends SmrtRecipe {
|
|
|
384
366
|
icon: string;
|
|
385
367
|
description: string;
|
|
386
368
|
};
|
|
387
|
-
static models: (typeof
|
|
369
|
+
static models: (typeof Invoice | typeof InvoiceLineItem | typeof Payment | typeof PaymentAllocation)[];
|
|
388
370
|
static nav: ({
|
|
389
371
|
label: string;
|
|
390
372
|
model: typeof Invoice;
|
|
@@ -474,7 +456,7 @@ export declare class InvoicingRecipe extends SmrtRecipe {
|
|
|
474
456
|
readonly visibility: "hidden";
|
|
475
457
|
};
|
|
476
458
|
readonly taxRate: {
|
|
477
|
-
readonly help: "
|
|
459
|
+
readonly help: "Stored fraction: 0.05 means 5%.";
|
|
478
460
|
};
|
|
479
461
|
};
|
|
480
462
|
};
|
|
@@ -591,7 +573,7 @@ export declare class AgreementsRecipe extends SmrtRecipe {
|
|
|
591
573
|
static models: (typeof Contract | typeof ContractLineItem)[];
|
|
592
574
|
static nav: {
|
|
593
575
|
label: string;
|
|
594
|
-
model: typeof
|
|
576
|
+
model: typeof Contract;
|
|
595
577
|
icon: string;
|
|
596
578
|
description: string;
|
|
597
579
|
}[];
|
|
@@ -607,10 +589,6 @@ export declare class AgreementsRecipe extends SmrtRecipe {
|
|
|
607
589
|
readonly customerId: {
|
|
608
590
|
readonly label: "Customer";
|
|
609
591
|
readonly order: 1;
|
|
610
|
-
readonly required: true;
|
|
611
|
-
};
|
|
612
|
-
readonly vendorId: {
|
|
613
|
-
readonly visibility: "hidden";
|
|
614
592
|
};
|
|
615
593
|
readonly subtotal: {
|
|
616
594
|
readonly visibility: "hidden";
|
|
@@ -644,7 +622,7 @@ export declare class AgreementsRecipe extends SmrtRecipe {
|
|
|
644
622
|
readonly visibility: "hidden";
|
|
645
623
|
};
|
|
646
624
|
readonly taxRate: {
|
|
647
|
-
readonly help: "
|
|
625
|
+
readonly help: "Stored fraction: 0.05 means 5%.";
|
|
648
626
|
};
|
|
649
627
|
};
|
|
650
628
|
};
|
|
@@ -675,7 +653,7 @@ export declare class LeasesRecipe extends SmrtRecipe {
|
|
|
675
653
|
icon: string;
|
|
676
654
|
description: string;
|
|
677
655
|
};
|
|
678
|
-
static models: (typeof
|
|
656
|
+
static models: (typeof ContractLineItem | typeof Lease)[];
|
|
679
657
|
static nav: {
|
|
680
658
|
label: string;
|
|
681
659
|
model: typeof Lease;
|
|
@@ -694,10 +672,6 @@ export declare class LeasesRecipe extends SmrtRecipe {
|
|
|
694
672
|
readonly customerId: {
|
|
695
673
|
readonly label: "Customer";
|
|
696
674
|
readonly order: 1;
|
|
697
|
-
readonly required: true;
|
|
698
|
-
};
|
|
699
|
-
readonly vendorId: {
|
|
700
|
-
readonly visibility: "hidden";
|
|
701
675
|
};
|
|
702
676
|
readonly subtotal: {
|
|
703
677
|
readonly visibility: "hidden";
|
|
@@ -731,7 +705,7 @@ export declare class LeasesRecipe extends SmrtRecipe {
|
|
|
731
705
|
readonly visibility: "hidden";
|
|
732
706
|
};
|
|
733
707
|
readonly taxRate: {
|
|
734
|
-
readonly help: "
|
|
708
|
+
readonly help: "Stored fraction: 0.05 means 5%.";
|
|
735
709
|
};
|
|
736
710
|
};
|
|
737
711
|
};
|
|
@@ -755,7 +729,7 @@ export declare class LicensesRecipe extends SmrtRecipe {
|
|
|
755
729
|
icon: string;
|
|
756
730
|
description: string;
|
|
757
731
|
};
|
|
758
|
-
static models: (typeof
|
|
732
|
+
static models: (typeof ContractLineItem | typeof LicenseSale)[];
|
|
759
733
|
static nav: {
|
|
760
734
|
label: string;
|
|
761
735
|
model: typeof LicenseSale;
|
|
@@ -774,10 +748,6 @@ export declare class LicensesRecipe extends SmrtRecipe {
|
|
|
774
748
|
readonly customerId: {
|
|
775
749
|
readonly label: "Customer";
|
|
776
750
|
readonly order: 1;
|
|
777
|
-
readonly required: true;
|
|
778
|
-
};
|
|
779
|
-
readonly vendorId: {
|
|
780
|
-
readonly visibility: "hidden";
|
|
781
751
|
};
|
|
782
752
|
readonly subtotal: {
|
|
783
753
|
readonly visibility: "hidden";
|
|
@@ -811,7 +781,7 @@ export declare class LicensesRecipe extends SmrtRecipe {
|
|
|
811
781
|
readonly visibility: "hidden";
|
|
812
782
|
};
|
|
813
783
|
readonly taxRate: {
|
|
814
|
-
readonly help: "
|
|
784
|
+
readonly help: "Stored fraction: 0.05 means 5%.";
|
|
815
785
|
};
|
|
816
786
|
};
|
|
817
787
|
};
|
package/dist/recipes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,
|
|
1
|
+
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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"}
|