@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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Exact, transport-neutral invoice draft validation shared by browser and server. */
|
|
2
|
-
import {
|
|
2
|
+
import { calculateMoneyDocument, MoneyValidationError, } from '../../money.js';
|
|
3
3
|
import { currencyMinorUnitExponent } from './currency.js';
|
|
4
4
|
const MAX_MINOR = BigInt(Number.MAX_SAFE_INTEGER);
|
|
5
5
|
const MAX_TEXT = 128;
|
|
@@ -50,38 +50,106 @@ function numberDecimal(value, precision) {
|
|
|
50
50
|
? { coefficient: coefficient * 10n ** BigInt(-places), scale: 1n }
|
|
51
51
|
: { coefficient, scale: 10n ** BigInt(places) };
|
|
52
52
|
}
|
|
53
|
-
function
|
|
54
|
-
// Preserve Math.round's existing credit-line ties toward positive infinity.
|
|
53
|
+
function roundSignedLegacy(numerator, denominator) {
|
|
55
54
|
return numerator >= 0n
|
|
56
55
|
? roundHalfUp(numerator, denominator)
|
|
57
56
|
: -((-numerator * 2n + denominator - 1n) / (denominator * 2n));
|
|
58
57
|
}
|
|
58
|
+
function decimalText(value) {
|
|
59
|
+
if (value.scale === 1n)
|
|
60
|
+
return value.coefficient.toString();
|
|
61
|
+
const places = value.scale.toString().length - 1;
|
|
62
|
+
const digits = value.coefficient.toString().padStart(places + 1, '0');
|
|
63
|
+
const split = digits.length - places;
|
|
64
|
+
return `${digits.slice(0, split)}.${digits.slice(split)}`
|
|
65
|
+
.replace(/0+$/, '')
|
|
66
|
+
.replace(/\.$/, '');
|
|
67
|
+
}
|
|
68
|
+
function legacyTaxCode(percent) {
|
|
69
|
+
const normalized = percent
|
|
70
|
+
.replace(/^0+(?=\d)/, '')
|
|
71
|
+
.replace(/(\.\d*?)0+$/, '$1')
|
|
72
|
+
.replace(/\.$/, '') || '0';
|
|
73
|
+
return normalized === '0'
|
|
74
|
+
? { id: 'legacy-zero', kind: 'zero-rated', components: [] }
|
|
75
|
+
: {
|
|
76
|
+
id: `legacy-${normalized}`,
|
|
77
|
+
kind: 'taxable',
|
|
78
|
+
components: [
|
|
79
|
+
{
|
|
80
|
+
taxComponentId: `legacy-${normalized}`,
|
|
81
|
+
percent: normalized,
|
|
82
|
+
compound: false,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
59
87
|
/**
|
|
60
88
|
* Exact model calculation, including existing negative-price credit lines.
|
|
61
89
|
* Throws before persistence for unsafe money, invalid quantity, or invalid tax.
|
|
62
90
|
*/
|
|
63
|
-
export function calculateInvoiceMinorLine(input) {
|
|
91
|
+
export function calculateInvoiceMinorLine(input, options = {}) {
|
|
64
92
|
for (const amount of [input.unitPrice, input.discount])
|
|
65
93
|
if (!Number.isSafeInteger(amount))
|
|
66
94
|
throw new RangeError('Invoice money must be safe integer minor units.');
|
|
67
|
-
|
|
95
|
+
const moneyModel = options.moneyModel ?? 'legacy';
|
|
96
|
+
if ((moneyModel === 'legacy' && input.discount < 0) || input.taxRate > 1)
|
|
68
97
|
throw new RangeError('Invoice discount or tax rate is outside the supported range.');
|
|
69
98
|
const quantity = numberDecimal(input.quantity, 6);
|
|
70
99
|
const tax = numberDecimal(input.taxRate, 8);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
100
|
+
if (moneyModel === 'legacy') {
|
|
101
|
+
const gross = roundSignedLegacy(quantity.coefficient * BigInt(input.unitPrice), quantity.scale);
|
|
102
|
+
const discount = BigInt(input.discount);
|
|
103
|
+
const subtotal = gross - discount;
|
|
104
|
+
const taxMinor = roundSignedLegacy(subtotal * tax.coefficient, tax.scale);
|
|
105
|
+
const total = subtotal + taxMinor;
|
|
106
|
+
for (const amount of [gross, subtotal, taxMinor, total])
|
|
107
|
+
if (amount > MAX_MINOR || amount < -MAX_MINOR)
|
|
108
|
+
throw new RangeError('Invoice line amount exceeds safe integer minor units.');
|
|
109
|
+
return {
|
|
110
|
+
grossMinor: Number(gross),
|
|
111
|
+
discountMinor: input.discount,
|
|
112
|
+
subtotalMinor: Number(subtotal),
|
|
113
|
+
taxMinor: Number(taxMinor),
|
|
114
|
+
totalMinor: Number(total),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (moneyModel !== 'v2')
|
|
118
|
+
throw new TypeError('Unknown invoice money model');
|
|
119
|
+
const percent = decimalText({
|
|
120
|
+
coefficient: tax.coefficient * 100n,
|
|
121
|
+
scale: tax.scale,
|
|
122
|
+
});
|
|
123
|
+
let result;
|
|
124
|
+
try {
|
|
125
|
+
result = calculateMoneyDocument({
|
|
126
|
+
currency: 'USD',
|
|
127
|
+
lineAmountType: 'exclusive',
|
|
128
|
+
roundingScope: 'line',
|
|
129
|
+
lines: [
|
|
130
|
+
{
|
|
131
|
+
id: 'legacy-line',
|
|
132
|
+
quantity: input.quantity,
|
|
133
|
+
unitPrice: input.unitPrice,
|
|
134
|
+
discount: input.discount === 0
|
|
135
|
+
? { kind: 'none' }
|
|
136
|
+
: { kind: 'amount', minor: input.discount },
|
|
137
|
+
taxCode: legacyTaxCode(percent),
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
}).lines[0];
|
|
141
|
+
}
|
|
142
|
+
catch (cause) {
|
|
143
|
+
if (cause instanceof MoneyValidationError)
|
|
144
|
+
throw new RangeError(cause.message, { cause });
|
|
145
|
+
throw cause;
|
|
146
|
+
}
|
|
79
147
|
return {
|
|
80
|
-
grossMinor:
|
|
81
|
-
discountMinor:
|
|
82
|
-
subtotalMinor:
|
|
83
|
-
taxMinor:
|
|
84
|
-
totalMinor:
|
|
148
|
+
grossMinor: result.grossMinor,
|
|
149
|
+
discountMinor: result.discountMinor,
|
|
150
|
+
subtotalMinor: result.netMinor,
|
|
151
|
+
taxMinor: result.taxMinor,
|
|
152
|
+
totalMinor: result.netMinor + result.taxMinor,
|
|
85
153
|
};
|
|
86
154
|
}
|
|
87
155
|
/**
|
|
@@ -177,30 +245,45 @@ export function calculateInvoiceLine(line, context) {
|
|
|
177
245
|
typeof discount === 'string' ||
|
|
178
246
|
typeof tax === 'string')
|
|
179
247
|
return { valid: false, errors };
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
248
|
+
let calculated;
|
|
249
|
+
try {
|
|
250
|
+
calculated = calculateMoneyDocument({
|
|
251
|
+
currency: context.currency,
|
|
252
|
+
lineAmountType: 'exclusive',
|
|
253
|
+
roundingScope: 'line',
|
|
254
|
+
lines: [
|
|
255
|
+
{
|
|
256
|
+
id: line.key,
|
|
257
|
+
quantity: Number(line.quantity),
|
|
258
|
+
unitPrice: Number(price),
|
|
259
|
+
discount: line.discountType === 'percent'
|
|
260
|
+
? { kind: 'percent', rate: line.discountValue }
|
|
261
|
+
: discount === 0n
|
|
262
|
+
? { kind: 'none' }
|
|
263
|
+
: { kind: 'amount', minor: Number(discount) },
|
|
264
|
+
taxCode: legacyTaxCode(effectiveTaxRate),
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
}).lines[0];
|
|
268
|
+
}
|
|
269
|
+
catch (cause) {
|
|
270
|
+
if (cause instanceof Error &&
|
|
271
|
+
'code' in cause &&
|
|
272
|
+
cause.code === 'DISCOUNT_EXCEEDS_GROSS')
|
|
273
|
+
return {
|
|
274
|
+
valid: false,
|
|
275
|
+
errors: { discountValue: 'discount-exceeds-gross' },
|
|
276
|
+
};
|
|
195
277
|
return { valid: false, errors: { taxRate: 'range' } };
|
|
278
|
+
}
|
|
196
279
|
return {
|
|
197
280
|
valid: true,
|
|
198
281
|
effectiveTaxRate,
|
|
199
|
-
grossMinor:
|
|
200
|
-
discountMinor:
|
|
201
|
-
subtotalMinor:
|
|
202
|
-
taxMinor:
|
|
203
|
-
totalMinor:
|
|
282
|
+
grossMinor: calculated.grossMinor,
|
|
283
|
+
discountMinor: calculated.discountMinor,
|
|
284
|
+
subtotalMinor: calculated.netMinor,
|
|
285
|
+
taxMinor: calculated.taxMinor,
|
|
286
|
+
totalMinor: calculated.netMinor + calculated.taxMinor,
|
|
204
287
|
};
|
|
205
288
|
}
|
|
206
289
|
function calendarDate(value) {
|
|
@@ -265,19 +348,30 @@ export function calculateInvoiceDraft(values, options = {}) {
|
|
|
265
348
|
};
|
|
266
349
|
});
|
|
267
350
|
try {
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
351
|
+
const calculated = calculateMoneyDocument({
|
|
352
|
+
currency: values.currency,
|
|
353
|
+
lineAmountType: 'exclusive',
|
|
354
|
+
roundingScope: 'document',
|
|
355
|
+
lines: taxable.map((row, index) => {
|
|
356
|
+
const result = lineResults[index];
|
|
357
|
+
if (!result.valid)
|
|
358
|
+
throw new Error('Validated invoice line expected');
|
|
359
|
+
return {
|
|
360
|
+
id: row.id,
|
|
361
|
+
quantity: 1,
|
|
362
|
+
unitPrice: result.grossMinor,
|
|
363
|
+
discount: result.discountMinor === 0
|
|
364
|
+
? { kind: 'none' }
|
|
365
|
+
: { kind: 'amount', minor: result.discountMinor },
|
|
366
|
+
taxCode: legacyTaxCode(row.category),
|
|
367
|
+
};
|
|
368
|
+
}),
|
|
275
369
|
});
|
|
276
|
-
sums.taxMinor = BigInt(
|
|
370
|
+
sums.taxMinor = BigInt(calculated.taxMinor);
|
|
277
371
|
sums.totalMinor = sums.subtotalMinor + sums.taxMinor;
|
|
278
372
|
}
|
|
279
373
|
catch (cause) {
|
|
280
|
-
if (!(cause instanceof RangeError))
|
|
374
|
+
if (!(cause instanceof RangeError || cause instanceof MoneyValidationError))
|
|
281
375
|
throw cause;
|
|
282
376
|
errors.total = 'range';
|
|
283
377
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/** Typed UI adapter for the v2 commercial-money editor. It never writes models. */
|
|
2
|
+
import { type LineAmountType, type MoneyDocumentResult, type MoneyTaxCodeInput, type MoneyValidationCode, type TaxRoundingScope } from '../../money.js';
|
|
3
|
+
export interface MoneyEditorTaxCode extends MoneyTaxCodeInput {
|
|
4
|
+
/** Stable label stored with the code supplied by the authorized adapter. */
|
|
5
|
+
code: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
/** Stored component labels; a component can be shared by more than one code. */
|
|
8
|
+
componentNames?: Readonly<Record<string, string>>;
|
|
9
|
+
}
|
|
10
|
+
export interface MoneyEditorLineDraft {
|
|
11
|
+
id: string;
|
|
12
|
+
description: string;
|
|
13
|
+
quantity: string;
|
|
14
|
+
/** Major-unit text, retained without coercion after an invalid submission. */
|
|
15
|
+
unitPrice: string;
|
|
16
|
+
discountType: 'none' | 'percent' | 'amount';
|
|
17
|
+
/** A non-negative magnitude; the calculator applies the line sign. */
|
|
18
|
+
discountValue: string;
|
|
19
|
+
taxMode: 'inherit' | 'override';
|
|
20
|
+
/** Blank is inherit. Historical rows may retain unknown code IDs. */
|
|
21
|
+
taxCodeId?: string | null;
|
|
22
|
+
/** Resolver result to use while the line remains inherited. */
|
|
23
|
+
inheritedTaxCodeId?: string | null;
|
|
24
|
+
inheritedTaxCodeSource?: 'product' | 'customer' | 'app' | 'exempt-customer' | 'none';
|
|
25
|
+
}
|
|
26
|
+
export interface MoneyEditorDraft {
|
|
27
|
+
currency: string;
|
|
28
|
+
lineAmountType: LineAmountType;
|
|
29
|
+
roundingScope: TaxRoundingScope;
|
|
30
|
+
lines: readonly MoneyEditorLineDraft[];
|
|
31
|
+
}
|
|
32
|
+
export interface MoneyStoredTax {
|
|
33
|
+
id: string;
|
|
34
|
+
/** Shared component identity: repeated tax codes with this ID aggregate. */
|
|
35
|
+
taxComponentId?: string | null;
|
|
36
|
+
name: string;
|
|
37
|
+
percent: string;
|
|
38
|
+
taxableMinor: number;
|
|
39
|
+
taxMinor: number;
|
|
40
|
+
}
|
|
41
|
+
/** A frozen document is rendered solely from this server-authoritative snapshot. */
|
|
42
|
+
export interface MoneyStoredDocument {
|
|
43
|
+
lineAmountType: LineAmountType;
|
|
44
|
+
roundingScope: TaxRoundingScope;
|
|
45
|
+
subtotalMinor: number;
|
|
46
|
+
discountTotalMinor: number;
|
|
47
|
+
taxMinor: number;
|
|
48
|
+
totalMinor: number;
|
|
49
|
+
taxes: readonly MoneyStoredTax[];
|
|
50
|
+
}
|
|
51
|
+
/** Stored money facts that header-only quote and purchase editors can display. */
|
|
52
|
+
export interface MoneyHeaderDisplay {
|
|
53
|
+
lineAmountType: LineAmountType;
|
|
54
|
+
taxMinor: number;
|
|
55
|
+
totalMinor: number;
|
|
56
|
+
minorUnitDigits: number;
|
|
57
|
+
}
|
|
58
|
+
export interface MoneyEditorFieldNames {
|
|
59
|
+
lineAmountType: string;
|
|
60
|
+
roundingScope: string;
|
|
61
|
+
lineId: string;
|
|
62
|
+
lineDescription: string;
|
|
63
|
+
lineQuantity: string;
|
|
64
|
+
lineUnitPrice: string;
|
|
65
|
+
lineDiscountType: string;
|
|
66
|
+
lineDiscountValue: string;
|
|
67
|
+
lineTaxMode: string;
|
|
68
|
+
lineTaxCodeId: string;
|
|
69
|
+
}
|
|
70
|
+
export declare const moneyEditorFieldNames: MoneyEditorFieldNames;
|
|
71
|
+
export interface MoneyEditorProps {
|
|
72
|
+
/** Explicit opt-in: existing invoice-editor consumers continue using legacy UI. */
|
|
73
|
+
mode: 'v2';
|
|
74
|
+
draft: MoneyEditorDraft;
|
|
75
|
+
taxCodes: readonly MoneyEditorTaxCode[];
|
|
76
|
+
/** Issued and posted documents must supply stored values and are read-only. */
|
|
77
|
+
frozen?: boolean;
|
|
78
|
+
/** A credit note cannot itself be credited. Defaults to an invoice for compatibility. */
|
|
79
|
+
kind?: 'invoice' | 'credit_note';
|
|
80
|
+
status?: string;
|
|
81
|
+
stored?: MoneyStoredDocument;
|
|
82
|
+
/**
|
|
83
|
+
* Host-authorized creation seam for an issued source invoice. The component
|
|
84
|
+
* never persists a credit note or chooses its route; the host supplies the
|
|
85
|
+
* action after its own authorization check.
|
|
86
|
+
*/
|
|
87
|
+
onCreateCreditNote?: () => void;
|
|
88
|
+
customerTaxExempt?: boolean;
|
|
89
|
+
sellerTaxRegistrations?: readonly string[];
|
|
90
|
+
partyTaxId?: string | null;
|
|
91
|
+
showNetSubtotal?: boolean;
|
|
92
|
+
names?: Partial<MoneyEditorFieldNames>;
|
|
93
|
+
}
|
|
94
|
+
export type MoneyEditorCalculation = {
|
|
95
|
+
valid: true;
|
|
96
|
+
result: MoneyDocumentResult;
|
|
97
|
+
} | {
|
|
98
|
+
valid: false;
|
|
99
|
+
code: MoneyValidationCode | 'INVALID_EDITOR_INPUT';
|
|
100
|
+
message: string;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Converts retained form text into the calculator's exact input. This is the
|
|
104
|
+
* only calculation boundary used by the v2 editor; server adapters still
|
|
105
|
+
* revalidate the resulting native form submission.
|
|
106
|
+
*/
|
|
107
|
+
export declare function calculateMoneyEditorDraft(draft: MoneyEditorDraft, taxCodes: readonly MoneyEditorTaxCode[]): MoneyEditorCalculation;
|
|
108
|
+
/** Typed, calculation-free shape represented by the v2 editor's native controls. */
|
|
109
|
+
export declare function moneyEditorSubmission(draft: MoneyEditorDraft): {
|
|
110
|
+
lineAmountType: LineAmountType;
|
|
111
|
+
taxRoundingScope: TaxRoundingScope;
|
|
112
|
+
lines: {
|
|
113
|
+
id: string;
|
|
114
|
+
description: string;
|
|
115
|
+
quantity: string;
|
|
116
|
+
unitPrice: string;
|
|
117
|
+
discountType: "none" | "percent" | "amount";
|
|
118
|
+
discountValue: string;
|
|
119
|
+
taxMode: "inherit" | "override";
|
|
120
|
+
taxCodeId: string;
|
|
121
|
+
}[];
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=money-editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"money-editor.d.ts","sourceRoot":"","sources":["../../../src/svelte/invoices/money-editor.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC5C,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,SAAS,GAAG,UAAU,CAAC;IAChC,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,+DAA+D;IAC/D,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,sBAAsB,CAAC,EACnB,SAAS,GACT,UAAU,GACV,KAAK,GACL,iBAAiB,GACjB,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,gBAAgB,CAAC;IAChC,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,oFAAoF;AACpF,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,gBAAgB,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;CAClC;AACD,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,qBAAqB,EAAE,qBAWnC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACxC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yFAAyF;IACzF,IAAI,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACxC;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,GAC5C;IACE,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,mBAAmB,GAAG,sBAAsB,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA8BN;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GACtC,sBAAsB,CA0CxB;AAED,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,gBAAgB;;;;;;;;;;;;;EAe5D"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/** Typed UI adapter for the v2 commercial-money editor. It never writes models. */
|
|
2
|
+
import { calculateMoneyDocument, } from '../../money.js';
|
|
3
|
+
import { currencyMinorUnitExponent } from './currency.js';
|
|
4
|
+
export const moneyEditorFieldNames = {
|
|
5
|
+
lineAmountType: 'lineAmountType',
|
|
6
|
+
roundingScope: 'taxRoundingScope',
|
|
7
|
+
lineId: 'lineId',
|
|
8
|
+
lineDescription: 'lineDescription',
|
|
9
|
+
lineQuantity: 'lineQuantity',
|
|
10
|
+
lineUnitPrice: 'lineUnitPrice',
|
|
11
|
+
lineDiscountType: 'lineDiscountType',
|
|
12
|
+
lineDiscountValue: 'lineDiscountValue',
|
|
13
|
+
lineTaxMode: 'lineTaxMode',
|
|
14
|
+
lineTaxCodeId: 'lineTaxCodeId',
|
|
15
|
+
};
|
|
16
|
+
function minor(text, exponent) {
|
|
17
|
+
if (!/^\d+(?:\.\d+)?$/u.test(text))
|
|
18
|
+
throw new Error('Amounts must be non-negative decimal text.');
|
|
19
|
+
const [whole, fraction = ''] = text.split('.');
|
|
20
|
+
if (fraction.length > exponent)
|
|
21
|
+
throw new Error('Amount exceeds the currency minor-unit precision.');
|
|
22
|
+
const value = BigInt(whole + fraction.padEnd(exponent, '0'));
|
|
23
|
+
if (value > BigInt(Number.MAX_SAFE_INTEGER))
|
|
24
|
+
throw new Error('Amount exceeds safe integer minor units.');
|
|
25
|
+
return Number(value);
|
|
26
|
+
}
|
|
27
|
+
function quantity(text) {
|
|
28
|
+
if (!/^\d+(?:\.\d+)?$/u.test(text))
|
|
29
|
+
throw new Error('Quantity must be a non-negative decimal.');
|
|
30
|
+
return Number(text);
|
|
31
|
+
}
|
|
32
|
+
function discount(line, exponent) {
|
|
33
|
+
if (line.discountType === 'none')
|
|
34
|
+
return { kind: 'none' };
|
|
35
|
+
if (line.discountType === 'percent')
|
|
36
|
+
return { kind: 'percent', rate: line.discountValue };
|
|
37
|
+
return { kind: 'amount', minor: minor(line.discountValue, exponent) };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Converts retained form text into the calculator's exact input. This is the
|
|
41
|
+
* only calculation boundary used by the v2 editor; server adapters still
|
|
42
|
+
* revalidate the resulting native form submission.
|
|
43
|
+
*/
|
|
44
|
+
export function calculateMoneyEditorDraft(draft, taxCodes) {
|
|
45
|
+
try {
|
|
46
|
+
const codes = new Map(taxCodes.map((code) => [code.id, code]));
|
|
47
|
+
const exponent = currencyMinorUnitExponent(draft.currency);
|
|
48
|
+
const lines = draft.lines.map((line) => {
|
|
49
|
+
const codeId = line.taxMode === 'override' ? line.taxCodeId : line.inheritedTaxCodeId;
|
|
50
|
+
const taxCode = codeId ? (codes.get(codeId) ?? null) : null;
|
|
51
|
+
if (codeId && !taxCode)
|
|
52
|
+
throw new Error('The selected tax code is no longer available.');
|
|
53
|
+
return {
|
|
54
|
+
id: line.id,
|
|
55
|
+
quantity: quantity(line.quantity),
|
|
56
|
+
unitPrice: minor(line.unitPrice, exponent),
|
|
57
|
+
discount: discount(line, exponent),
|
|
58
|
+
taxCode,
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
valid: true,
|
|
63
|
+
result: calculateMoneyDocument({
|
|
64
|
+
currency: draft.currency,
|
|
65
|
+
lineAmountType: draft.lineAmountType,
|
|
66
|
+
roundingScope: draft.roundingScope,
|
|
67
|
+
lines,
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (error && typeof error === 'object' && 'code' in error)
|
|
73
|
+
return {
|
|
74
|
+
valid: false,
|
|
75
|
+
code: error.code,
|
|
76
|
+
message: error instanceof Error ? error.message : 'Money validation failed.',
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
valid: false,
|
|
80
|
+
code: 'INVALID_EDITOR_INPUT',
|
|
81
|
+
message: error instanceof Error ? error.message : 'Money validation failed.',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Typed, calculation-free shape represented by the v2 editor's native controls. */
|
|
86
|
+
export function moneyEditorSubmission(draft) {
|
|
87
|
+
return {
|
|
88
|
+
lineAmountType: draft.lineAmountType,
|
|
89
|
+
taxRoundingScope: draft.roundingScope,
|
|
90
|
+
lines: draft.lines.map((line) => ({
|
|
91
|
+
id: line.id,
|
|
92
|
+
description: line.description,
|
|
93
|
+
quantity: line.quantity,
|
|
94
|
+
unitPrice: line.unitPrice,
|
|
95
|
+
discountType: line.discountType,
|
|
96
|
+
discountValue: line.discountValue,
|
|
97
|
+
taxMode: line.taxMode,
|
|
98
|
+
taxCodeId: line.taxCodeId ?? '',
|
|
99
|
+
})),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
@@ -2,6 +2,8 @@ import type { FormRetryStatus } from '@happyvertical/smrt-ui/form-retry';
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLFormAttributes } from 'svelte/elements';
|
|
4
4
|
import type { InvoiceDraftCalculationOptions } from './calculations.js';
|
|
5
|
+
import type { MoneyEditorProps } from './money-editor.js';
|
|
6
|
+
export type { MoneyEditorDraft, MoneyEditorFieldNames, MoneyEditorLineDraft, MoneyEditorProps, MoneyEditorTaxCode, MoneyStoredDocument, MoneyStoredTax, } from './money-editor.js';
|
|
5
7
|
/** Authorized source projection supplied by the application, not fetched by UI. */
|
|
6
8
|
export interface InvoicePreparationSource {
|
|
7
9
|
/** Opaque source reference submitted verbatim. */
|
|
@@ -153,7 +155,7 @@ export interface InvoiceEditorProps extends InvoiceDraftCalculationOptions {
|
|
|
153
155
|
/** Caller-localized title. */
|
|
154
156
|
title?: string;
|
|
155
157
|
/** Retained editable strings; never reconstructed from model numbers. */
|
|
156
|
-
values
|
|
158
|
+
values?: InvoiceDraftValues;
|
|
157
159
|
/** Authorized customer projections; retained unknown references stay visible. */
|
|
158
160
|
customers?: readonly {
|
|
159
161
|
id: string;
|
|
@@ -191,5 +193,7 @@ export interface InvoiceEditorProps extends InvoiceDraftCalculationOptions {
|
|
|
191
193
|
children?: Snippet<[InvoiceDraftValues]>;
|
|
192
194
|
/** Optional enhancement; native submission remains the default. */
|
|
193
195
|
onsubmit?: HTMLFormAttributes['onsubmit'];
|
|
196
|
+
/** Explicit v2 money surface. Omit to retain the legacy invoice editor API. */
|
|
197
|
+
money?: MoneyEditorProps;
|
|
194
198
|
}
|
|
195
199
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/svelte/invoices/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/svelte/invoices/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,11 @@ export declare const P: {
|
|
|
28
28
|
readonly 'commerce.purchase.unknown': "commerce.purchase.unknown";
|
|
29
29
|
readonly 'commerce.purchase.empty_allocations': "commerce.purchase.empty_allocations";
|
|
30
30
|
readonly 'commerce.purchase.tax': "commerce.purchase.tax";
|
|
31
|
+
readonly 'commerce.purchase.money_amounts_are': "commerce.purchase.money_amounts_are";
|
|
32
|
+
readonly 'commerce.purchase.money_includes_tax': "commerce.purchase.money_includes_tax";
|
|
33
|
+
readonly 'commerce.purchase.tax_inclusive': "commerce.purchase.tax_inclusive";
|
|
34
|
+
readonly 'commerce.purchase.tax_exclusive': "commerce.purchase.tax_exclusive";
|
|
35
|
+
readonly 'commerce.purchase.no_tax': "commerce.purchase.no_tax";
|
|
31
36
|
readonly 'commerce.purchase.scope': "commerce.purchase.scope";
|
|
32
37
|
readonly 'commerce.purchase.inclusions': "commerce.purchase.inclusions";
|
|
33
38
|
readonly 'commerce.purchase.exclusions': "commerce.purchase.exclusions";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"purchasing-i18n.d.ts","sourceRoot":"","sources":["../../src/svelte/purchasing-i18n.ts"],"names":[],"mappings":"AACA,6FAA6F;AAC7F,eAAO,MAAM,CAAC
|
|
1
|
+
{"version":3,"file":"purchasing-i18n.d.ts","sourceRoot":"","sources":["../../src/svelte/purchasing-i18n.ts"],"names":[],"mappings":"AACA,6FAA6F;AAC7F,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4EZ,CAAC"}
|
|
@@ -29,6 +29,11 @@ export const P = defineMessages({
|
|
|
29
29
|
'commerce.purchase.unknown': 'Unknown',
|
|
30
30
|
'commerce.purchase.empty_allocations': 'No allocations supplied.',
|
|
31
31
|
'commerce.purchase.tax': 'Included tax',
|
|
32
|
+
'commerce.purchase.money_amounts_are': 'Amounts are {amountType}.',
|
|
33
|
+
'commerce.purchase.money_includes_tax': 'Includes tax of {amount} {currency}.',
|
|
34
|
+
'commerce.purchase.tax_inclusive': 'tax inclusive',
|
|
35
|
+
'commerce.purchase.tax_exclusive': 'tax exclusive',
|
|
36
|
+
'commerce.purchase.no_tax': 'no tax',
|
|
32
37
|
'commerce.purchase.scope': 'Ordered or awarded scope',
|
|
33
38
|
'commerce.purchase.inclusions': 'Inclusions',
|
|
34
39
|
'commerce.purchase.exclusions': 'Exclusions',
|
|
@@ -11,6 +11,11 @@ export declare const Q: {
|
|
|
11
11
|
readonly 'commerce.quote.currency': "commerce.quote.currency";
|
|
12
12
|
readonly 'commerce.quote.total': "commerce.quote.total";
|
|
13
13
|
readonly 'commerce.quote.tax': "commerce.quote.tax";
|
|
14
|
+
readonly 'commerce.quote.money_amounts_are': "commerce.quote.money_amounts_are";
|
|
15
|
+
readonly 'commerce.quote.money_includes_tax': "commerce.quote.money_includes_tax";
|
|
16
|
+
readonly 'commerce.quote.tax_inclusive': "commerce.quote.tax_inclusive";
|
|
17
|
+
readonly 'commerce.quote.tax_exclusive': "commerce.quote.tax_exclusive";
|
|
18
|
+
readonly 'commerce.quote.no_tax': "commerce.quote.no_tax";
|
|
14
19
|
readonly 'commerce.quote.scope': "commerce.quote.scope";
|
|
15
20
|
readonly 'commerce.quote.inclusions': "commerce.quote.inclusions";
|
|
16
21
|
readonly 'commerce.quote.exclusions': "commerce.quote.exclusions";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quote-i18n.d.ts","sourceRoot":"","sources":["../../src/svelte/quote-i18n.ts"],"names":[],"mappings":"AAEA,gEAAgE;AAChE,eAAO,MAAM,CAAC
|
|
1
|
+
{"version":3,"file":"quote-i18n.d.ts","sourceRoot":"","sources":["../../src/svelte/quote-i18n.ts"],"names":[],"mappings":"AAEA,gEAAgE;AAChE,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDZ,CAAC"}
|
|
@@ -12,6 +12,11 @@ export const Q = defineMessages({
|
|
|
12
12
|
'commerce.quote.currency': 'Currency',
|
|
13
13
|
'commerce.quote.total': 'Total, including tax',
|
|
14
14
|
'commerce.quote.tax': 'Tax included in total',
|
|
15
|
+
'commerce.quote.money_amounts_are': 'Amounts are {amountType}.',
|
|
16
|
+
'commerce.quote.money_includes_tax': 'Includes tax of {amount}.',
|
|
17
|
+
'commerce.quote.tax_inclusive': 'tax inclusive',
|
|
18
|
+
'commerce.quote.tax_exclusive': 'tax exclusive',
|
|
19
|
+
'commerce.quote.no_tax': 'no tax',
|
|
15
20
|
'commerce.quote.scope': 'Scope',
|
|
16
21
|
'commerce.quote.inclusions': 'Inclusions',
|
|
17
22
|
'commerce.quote.exclusions': 'Exclusions',
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';
|
|
2
|
+
import type { Cookbook } from '@happyvertical/smrt-types';
|
|
3
|
+
/** The tax subset emitted by core's cookbook engine, expressed as a percent. */
|
|
4
|
+
export interface CookbookTaxSettingsInput {
|
|
5
|
+
taxRate: number;
|
|
6
|
+
pricesIncludeTax: boolean;
|
|
7
|
+
taxRounding: 'line' | 'document';
|
|
8
|
+
}
|
|
9
|
+
/** Read the validated cookbook's persisted commerce setting rows. */
|
|
10
|
+
export declare function cookbookTaxSettings(cookbook: Pick<Cookbook, 'policies'>): CookbookTaxSettingsInput;
|
|
11
|
+
/**
|
|
12
|
+
* Explicit server bootstrap boundary for a host that owns both the database
|
|
13
|
+
* and authoritative tenant context after schema setup.
|
|
14
|
+
*/
|
|
15
|
+
export declare function applyCommerceCookbookSettings(db: DatabaseInterface, tenantId: string, cookbook: Pick<Cookbook, 'policies'>): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Materialize core's legacy cookbook tax setting into commerce-owned records.
|
|
18
|
+
* Core deliberately stays unaware of these models to avoid a core → commerce
|
|
19
|
+
* dependency cycle.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyCookbookTaxSettings(db: DatabaseInterface, tenantId: string, input: CookbookTaxSettingsInput): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=cookbook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookbook.d.ts","sourceRoot":"","sources":["../../src/tax/cookbook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAE7E,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,2BAA2B,CAAC;AAO7E,gFAAgF;AAChF,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,UAAU,CAAC;CAClC;AAyBD,qEAAqE;AACrE,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,GACnC,wBAAwB,CAgC1B;AAED;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,EAAE,EAAE,iBAAiB,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,iBAAiB,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAiFf"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';
|
|
2
|
+
import type { TaxCodeAppliesTo } from '../models/TaxCode.js';
|
|
3
|
+
export interface TaxCodeExamplePack {
|
|
4
|
+
id: string;
|
|
5
|
+
components: readonly {
|
|
6
|
+
key: string;
|
|
7
|
+
name: string;
|
|
8
|
+
percent: string;
|
|
9
|
+
recoverable: boolean;
|
|
10
|
+
}[];
|
|
11
|
+
codes: readonly {
|
|
12
|
+
code: string;
|
|
13
|
+
name: string;
|
|
14
|
+
appliesTo: TaxCodeAppliesTo;
|
|
15
|
+
componentKeys: readonly string[];
|
|
16
|
+
}[];
|
|
17
|
+
}
|
|
18
|
+
/** Illustrative common rates; applications must confirm local applicability. */
|
|
19
|
+
export declare const COMMON_TAX_CODE_EXAMPLE_PACK: TaxCodeExamplePack;
|
|
20
|
+
/** Import a documented example pack without changing existing tenant rows. */
|
|
21
|
+
export declare function applyTaxCodeExamplePack(db: DatabaseInterface, tenantId: string, pack?: TaxCodeExamplePack): Promise<{
|
|
22
|
+
componentIds: Record<string, string>;
|
|
23
|
+
codeIds: Record<string, string>;
|
|
24
|
+
}>;
|
|
25
|
+
//# sourceMappingURL=example-pack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example-pack.d.ts","sourceRoot":"","sources":["../../src/tax/example-pack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAI7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,SAAS;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,OAAO,CAAC;KACtB,EAAE,CAAC;IACJ,KAAK,EAAE,SAAS;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,gBAAgB,CAAC;QAC5B,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;KAClC,EAAE,CAAC;CACL;AAED,gFAAgF;AAChF,eAAO,MAAM,4BAA4B,EAAE,kBA+D1C,CAAC;AAEF,8EAA8E;AAC9E,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,iBAAiB,EACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,kBAAiD,GACtD,OAAO,CAAC;IACT,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC,CAoED"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Stable UUID identities make tenant tax bootstrap retry and race safe. */
|
|
2
|
+
export declare function deterministicTaxId(tenantId: string, kind: 'code' | 'component' | 'settings' | 'report', key: string): Promise<string>;
|
|
3
|
+
/** A racing deterministic insert loses safely and reloads the committed row. */
|
|
4
|
+
export declare function createOrLoadTaxSeed<T>(create: () => Promise<T>, load: () => Promise<T | null | undefined>): Promise<T>;
|
|
5
|
+
//# sourceMappingURL=identity.d.ts.map
|