@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.
Files changed (220) hide show
  1. package/AGENTS.md +11 -9
  2. package/README.md +114 -2
  3. package/agents/accounting-snapshot-mapper.md +111 -0
  4. package/agents/contract-money.md +18 -0
  5. package/agents/cost-billing.md +7 -2
  6. package/agents/document-money.md +126 -0
  7. package/agents/invoice-calculations.md +14 -2
  8. package/agents/line-amount-migration.md +50 -0
  9. package/agents/minor-unit-migration.md +20 -0
  10. package/agents/money-calculator.md +45 -0
  11. package/agents/money-model.md +113 -0
  12. package/agents/purchasing-ui.md +4 -3
  13. package/agents/quote-ui.md +3 -2
  14. package/agents/revenue-journal.md +23 -0
  15. package/agents/tax-codes.md +48 -0
  16. package/agents/tax-summary.md +126 -0
  17. package/dist/accounting-snapshot.d.ts +79 -0
  18. package/dist/accounting-snapshot.d.ts.map +1 -0
  19. package/dist/billing/runtime.d.ts +2 -0
  20. package/dist/billing/runtime.d.ts.map +1 -1
  21. package/dist/chunks/ContractLineItemCollection-DYjhj_pU.js +265 -0
  22. package/dist/chunks/ContractLineItemCollection-DYjhj_pU.js.map +1 -0
  23. package/dist/chunks/CustomerCollection-DQIujn4f.js +99 -0
  24. package/dist/chunks/CustomerCollection-DQIujn4f.js.map +1 -0
  25. package/dist/chunks/DocumentTaxCollection-BEpoqXAQ.js +1639 -0
  26. package/dist/chunks/DocumentTaxCollection-BEpoqXAQ.js.map +1 -0
  27. package/dist/chunks/InvoiceCollection-CKQflFjc.js +1047 -0
  28. package/dist/chunks/InvoiceCollection-CKQflFjc.js.map +1 -0
  29. package/dist/chunks/InvoiceLineItemCollection-CHm9zdqh.js +467 -0
  30. package/dist/chunks/InvoiceLineItemCollection-CHm9zdqh.js.map +1 -0
  31. package/dist/chunks/TaxCodeCollection-DOpzW4y8.js +149 -0
  32. package/dist/chunks/TaxCodeCollection-DOpzW4y8.js.map +1 -0
  33. package/dist/chunks/TaxComponentCollection-Cs2uXwEl.js +129 -0
  34. package/dist/chunks/TaxComponentCollection-Cs2uXwEl.js.map +1 -0
  35. package/dist/chunks/TaxSettingsCollection-BBTZDH1S.js +319 -0
  36. package/dist/chunks/TaxSettingsCollection-BBTZDH1S.js.map +1 -0
  37. package/dist/chunks/{money-DfrRxrel.js → allocation-integrity-DI3G16BN.js} +7 -12
  38. package/dist/chunks/allocation-integrity-DI3G16BN.js.map +1 -0
  39. package/dist/chunks/{calculations-Bz7RB3qK.js → calculations-DaHR17il.js} +134 -54
  40. package/dist/chunks/calculations-DaHR17il.js.map +1 -0
  41. package/dist/chunks/credit-allocation-yspz0Lab.js +121 -0
  42. package/dist/chunks/credit-allocation-yspz0Lab.js.map +1 -0
  43. package/dist/chunks/document-money-DNVhDJyC.js +860 -0
  44. package/dist/chunks/document-money-DNVhDJyC.js.map +1 -0
  45. package/dist/chunks/invoice-posting-BwV8g7z0.js +229 -0
  46. package/dist/chunks/invoice-posting-BwV8g7z0.js.map +1 -0
  47. package/dist/chunks/money-rational-CcW7gzG5.js +64 -0
  48. package/dist/chunks/money-rational-CcW7gzG5.js.map +1 -0
  49. package/dist/chunks/revenue-journal-DY9fro8E.js +140 -0
  50. package/dist/chunks/revenue-journal-DY9fro8E.js.map +1 -0
  51. package/dist/chunks/rolldown-runtime-D7D4PA-g.js +13 -0
  52. package/dist/chunks/tenant-money-barrier-DjRXgMnX.js +135 -0
  53. package/dist/chunks/tenant-money-barrier-DjRXgMnX.js.map +1 -0
  54. package/dist/chunks/{types-zVnIjSOk.js → types-LDETvQ1C.js} +3 -14
  55. package/dist/chunks/types-LDETvQ1C.js.map +1 -0
  56. package/dist/chunks/{units-BpZ0_Dpk.js → units-CNcjH_eE.js} +2 -2
  57. package/dist/chunks/{units-BpZ0_Dpk.js.map → units-CNcjH_eE.js.map} +1 -1
  58. package/dist/collections/ContractCollection.d.ts +37 -1
  59. package/dist/collections/ContractCollection.d.ts.map +1 -1
  60. package/dist/collections/ContractLineItemCollection.d.ts +26 -1
  61. package/dist/collections/ContractLineItemCollection.d.ts.map +1 -1
  62. package/dist/collections/DocumentTaxCollection.d.ts +75 -0
  63. package/dist/collections/DocumentTaxCollection.d.ts.map +1 -0
  64. package/dist/collections/InvoiceCollection.d.ts +26 -1
  65. package/dist/collections/InvoiceCollection.d.ts.map +1 -1
  66. package/dist/collections/InvoiceLineItemCollection.d.ts +26 -1
  67. package/dist/collections/InvoiceLineItemCollection.d.ts.map +1 -1
  68. package/dist/collections/MoneyMigrationDocumentCollection.d.ts +12 -0
  69. package/dist/collections/MoneyMigrationDocumentCollection.d.ts.map +1 -0
  70. package/dist/collections/PaymentAllocationCollection.d.ts +2 -0
  71. package/dist/collections/PaymentAllocationCollection.d.ts.map +1 -1
  72. package/dist/collections/PurchaseContractCollection.d.ts +8 -0
  73. package/dist/collections/PurchaseContractCollection.d.ts.map +1 -0
  74. package/dist/collections/SalesContractCollection.d.ts +8 -0
  75. package/dist/collections/SalesContractCollection.d.ts.map +1 -0
  76. package/dist/collections/TaxCodeCollection.d.ts +7 -0
  77. package/dist/collections/TaxCodeCollection.d.ts.map +1 -0
  78. package/dist/collections/TaxComponentCollection.d.ts +6 -0
  79. package/dist/collections/TaxComponentCollection.d.ts.map +1 -0
  80. package/dist/collections/TaxSettingsCollection.d.ts +16 -0
  81. package/dist/collections/TaxSettingsCollection.d.ts.map +1 -0
  82. package/dist/collections/TaxSummaryReportCollection.d.ts +151 -0
  83. package/dist/collections/TaxSummaryReportCollection.d.ts.map +1 -0
  84. package/dist/collections/index.d.ts +8 -0
  85. package/dist/collections/index.d.ts.map +1 -1
  86. package/dist/commerce-money-tools.d.ts +9 -0
  87. package/dist/commerce-money-tools.d.ts.map +1 -0
  88. package/dist/contract-money.d.ts +27 -0
  89. package/dist/contract-money.d.ts.map +1 -0
  90. package/dist/cost-billing.d.ts +0 -1
  91. package/dist/cost-billing.d.ts.map +1 -1
  92. package/dist/cost-billing.js +10 -15
  93. package/dist/cost-billing.js.map +1 -1
  94. package/dist/credit-allocation.d.ts +48 -0
  95. package/dist/credit-allocation.d.ts.map +1 -0
  96. package/dist/document-money-internal.d.ts +44 -0
  97. package/dist/document-money-internal.d.ts.map +1 -0
  98. package/dist/document-money.d.ts +85 -0
  99. package/dist/document-money.d.ts.map +1 -0
  100. package/dist/index.d.ts +16 -4
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +5563 -4243
  103. package/dist/index.js.map +1 -1
  104. package/dist/invoice-accounting-sync.d.ts +96 -0
  105. package/dist/invoice-accounting-sync.d.ts.map +1 -0
  106. package/dist/invoice-mcp.d.ts +16 -0
  107. package/dist/invoice-mcp.d.ts.map +1 -0
  108. package/dist/invoice-posting.d.ts +9 -0
  109. package/dist/invoice-posting.d.ts.map +1 -0
  110. package/dist/invoice-record-screen.d.ts +60 -0
  111. package/dist/invoice-record-screen.d.ts.map +1 -0
  112. package/dist/invoices.d.ts +2 -0
  113. package/dist/invoices.d.ts.map +1 -1
  114. package/dist/invoices.js +3 -2
  115. package/dist/manifest.json +11605 -4598
  116. package/dist/migrations/commerceLineAmounts.d.ts +84 -0
  117. package/dist/migrations/commerceLineAmounts.d.ts.map +1 -0
  118. package/dist/migrations/partyLinks.d.ts +39 -0
  119. package/dist/migrations/partyLinks.d.ts.map +1 -0
  120. package/dist/models/Contract.d.ts +61 -27
  121. package/dist/models/Contract.d.ts.map +1 -1
  122. package/dist/models/ContractLineItem.d.ts +30 -1
  123. package/dist/models/ContractLineItem.d.ts.map +1 -1
  124. package/dist/models/Customer.d.ts +7 -0
  125. package/dist/models/Customer.d.ts.map +1 -1
  126. package/dist/models/DocumentTax.d.ts +50 -0
  127. package/dist/models/DocumentTax.d.ts.map +1 -0
  128. package/dist/models/Invoice.d.ts +46 -2
  129. package/dist/models/Invoice.d.ts.map +1 -1
  130. package/dist/models/InvoiceLineItem.d.ts +33 -2
  131. package/dist/models/InvoiceLineItem.d.ts.map +1 -1
  132. package/dist/models/MoneyMigrationDocument.d.ts +28 -0
  133. package/dist/models/MoneyMigrationDocument.d.ts.map +1 -0
  134. package/dist/models/Payment.d.ts +5 -1
  135. package/dist/models/Payment.d.ts.map +1 -1
  136. package/dist/models/PaymentAllocation.d.ts.map +1 -1
  137. package/dist/models/TaxCode.d.ts +22 -0
  138. package/dist/models/TaxCode.d.ts.map +1 -0
  139. package/dist/models/TaxComponent.d.ts +21 -0
  140. package/dist/models/TaxComponent.d.ts.map +1 -0
  141. package/dist/models/TaxSettings.d.ts +33 -0
  142. package/dist/models/TaxSettings.d.ts.map +1 -0
  143. package/dist/models/TaxSummaryReport.d.ts +35 -0
  144. package/dist/models/TaxSummaryReport.d.ts.map +1 -0
  145. package/dist/models/Vendor.d.ts +9 -0
  146. package/dist/models/Vendor.d.ts.map +1 -1
  147. package/dist/models/index.d.ts +7 -1
  148. package/dist/models/index.d.ts.map +1 -1
  149. package/dist/money-rational.d.ts +15 -0
  150. package/dist/money-rational.d.ts.map +1 -0
  151. package/dist/money.d.ts +106 -25
  152. package/dist/money.d.ts.map +1 -1
  153. package/dist/money.js +274 -0
  154. package/dist/money.js.map +1 -0
  155. package/dist/recipes.d.ts +17 -47
  156. package/dist/recipes.d.ts.map +1 -1
  157. package/dist/revenue-journal.d.ts +61 -0
  158. package/dist/revenue-journal.d.ts.map +1 -0
  159. package/dist/smrt-knowledge.json +6558 -1316
  160. package/dist/svelte/components/InvoiceActions.svelte +12 -0
  161. package/dist/svelte/components/InvoiceActions.svelte.d.ts +5 -0
  162. package/dist/svelte/components/InvoiceActions.svelte.d.ts.map +1 -1
  163. package/dist/svelte/components/InvoiceEditor.svelte +15 -1
  164. package/dist/svelte/components/InvoiceEditor.svelte.d.ts.map +1 -1
  165. package/dist/svelte/components/InvoiceLineItems.svelte +3 -3
  166. package/dist/svelte/components/InvoiceRecordScreen.svelte +94 -0
  167. package/dist/svelte/components/InvoiceRecordScreen.svelte.d.ts +21 -0
  168. package/dist/svelte/components/InvoiceRecordScreen.svelte.d.ts.map +1 -0
  169. package/dist/svelte/components/InvoiceTotals.svelte +2 -2
  170. package/dist/svelte/components/MoneyInvoiceEditor.svelte +282 -0
  171. package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts +31 -0
  172. package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts.map +1 -0
  173. package/dist/svelte/components/PurchaseOrderEditor.svelte +53 -1
  174. package/dist/svelte/components/PurchaseOrderEditor.svelte.d.ts +5 -0
  175. package/dist/svelte/components/PurchaseOrderEditor.svelte.d.ts.map +1 -1
  176. package/dist/svelte/components/QuoteEditor.svelte +54 -1
  177. package/dist/svelte/components/QuoteEditor.svelte.d.ts +5 -0
  178. package/dist/svelte/components/QuoteEditor.svelte.d.ts.map +1 -1
  179. package/dist/svelte/i18n.d.ts +16 -0
  180. package/dist/svelte/i18n.d.ts.map +1 -1
  181. package/dist/svelte/i18n.js +16 -0
  182. package/dist/svelte/index.d.ts +7 -2
  183. package/dist/svelte/index.d.ts.map +1 -1
  184. package/dist/svelte/index.js +4 -1
  185. package/dist/svelte/invoices/calculations.d.ts +7 -2
  186. package/dist/svelte/invoices/calculations.d.ts.map +1 -1
  187. package/dist/svelte/invoices/calculations.js +141 -47
  188. package/dist/svelte/invoices/money-editor.d.ts +123 -0
  189. package/dist/svelte/invoices/money-editor.d.ts.map +1 -0
  190. package/dist/svelte/invoices/money-editor.js +101 -0
  191. package/dist/svelte/invoices/types.d.ts +5 -1
  192. package/dist/svelte/invoices/types.d.ts.map +1 -1
  193. package/dist/svelte/purchasing-i18n.d.ts +5 -0
  194. package/dist/svelte/purchasing-i18n.d.ts.map +1 -1
  195. package/dist/svelte/purchasing-i18n.js +5 -0
  196. package/dist/svelte/quote-i18n.d.ts +5 -0
  197. package/dist/svelte/quote-i18n.d.ts.map +1 -1
  198. package/dist/svelte/quote-i18n.js +5 -0
  199. package/dist/tax/cookbook.d.ts +22 -0
  200. package/dist/tax/cookbook.d.ts.map +1 -0
  201. package/dist/tax/example-pack.d.ts +25 -0
  202. package/dist/tax/example-pack.d.ts.map +1 -0
  203. package/dist/tax/identity.d.ts +5 -0
  204. package/dist/tax/identity.d.ts.map +1 -0
  205. package/dist/tax/index.d.ts +4 -0
  206. package/dist/tax/index.d.ts.map +1 -0
  207. package/dist/tax/legacy.d.ts +48 -0
  208. package/dist/tax/legacy.d.ts.map +1 -0
  209. package/dist/tax-summary-report-adapter.d.ts +37 -0
  210. package/dist/tax-summary-report-adapter.d.ts.map +1 -0
  211. package/dist/tax-summary.d.ts +129 -0
  212. package/dist/tax-summary.d.ts.map +1 -0
  213. package/dist/tenant-money-barrier.d.ts +66 -0
  214. package/dist/tenant-money-barrier.d.ts.map +1 -0
  215. package/dist/types/index.d.ts +145 -5
  216. package/dist/types/index.d.ts.map +1 -1
  217. package/package.json +19 -11
  218. package/dist/chunks/calculations-Bz7RB3qK.js.map +0 -1
  219. package/dist/chunks/money-DfrRxrel.js.map +0 -1
  220. 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 { Agreement, Contract, Estimate, Lease, LicenseSale, Order, PurchaseOrder, WholesaleOrder } from './models/Contract.js';
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 PurchaseOrder | typeof ContractLineItem)[];
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: "Type a percentage: 5 means 5%.";
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 Order | typeof ContractLineItem)[];
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: "Type a percentage: 5 means 5%.";
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 Estimate | typeof ContractLineItem)[];
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: "Type a percentage: 5 means 5%.";
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 WholesaleOrder | typeof ContractLineItem)[];
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: "Type a percentage: 5 means 5%.";
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 InvoiceLineItem | typeof Payment | typeof Invoice | typeof PaymentAllocation)[];
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: "Type a percentage: 5 means 5%.";
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 Agreement;
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: "Type a percentage: 5 means 5%.";
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 Lease | typeof ContractLineItem)[];
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: "Type a percentage: 5 means 5%.";
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 LicenseSale | typeof ContractLineItem)[];
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: "Type a percentage: 5 means 5%.";
784
+ readonly help: "Stored fraction: 0.05 means 5%.";
815
785
  };
816
786
  };
817
787
  };
@@ -1 +1 @@
1
- {"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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"}