@happyvertical/smrt-commerce 0.56.2 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +24 -11
- package/README.md +137 -89
- package/agents/accounting-snapshot-mapper.md +3 -3
- package/agents/commercial-ui.md +2 -2
- package/agents/contract-money.md +9 -12
- package/agents/cost-billing.md +3 -6
- package/agents/customer-vendor-ui.md +1 -2
- package/agents/document-money.md +58 -31
- package/agents/invoice-calculations.md +31 -56
- package/agents/invoice-preparation.md +62 -73
- package/agents/invoice-quantity.md +9 -21
- package/agents/minor-unit-migration.md +4 -4
- package/agents/money-calculator.md +7 -8
- package/agents/money-model.md +18 -22
- package/agents/money-upgrade.md +92 -0
- package/agents/revenue-journal.md +2 -2
- package/agents/tax-codes.md +17 -14
- package/agents/tax-summary.md +8 -6
- package/dist/billing/period-close.d.ts.map +1 -1
- package/dist/billing/runtime.d.ts +5 -2
- package/dist/billing/runtime.d.ts.map +1 -1
- package/dist/chunks/{ContractLineItemCollection--BrGMtNz.js → ContractLineItemCollection-BZcrlrrY.js} +19 -24
- package/dist/chunks/ContractLineItemCollection-BZcrlrrY.js.map +1 -0
- package/dist/chunks/{CustomerCollection-CjGaZSpf.js → CustomerCollection-BIPH2ZUx.js} +2 -2
- package/dist/chunks/{CustomerCollection-CjGaZSpf.js.map → CustomerCollection-BIPH2ZUx.js.map} +1 -1
- package/dist/chunks/{DocumentTaxCollection-KOkaQT2M.js → DocumentTaxCollection-DDzlywMW.js} +14 -7
- package/dist/chunks/DocumentTaxCollection-DDzlywMW.js.map +1 -0
- package/dist/chunks/{InvoiceCollection-BUe_8FT1.js → InvoiceCollection-cinzAqt6.js} +50 -161
- package/dist/chunks/InvoiceCollection-cinzAqt6.js.map +1 -0
- package/dist/chunks/{TaxCodeCollection-DF2eaJed.js → TaxCodeCollection-DaBOPG9c.js} +11 -4
- package/dist/chunks/{TaxCodeCollection-DF2eaJed.js.map → TaxCodeCollection-DaBOPG9c.js.map} +1 -1
- package/dist/chunks/{TaxComponentCollection-3x24xSNh.js → TaxComponentCollection-C4zxnyVu.js} +3 -3
- package/dist/chunks/{TaxComponentCollection-3x24xSNh.js.map → TaxComponentCollection-C4zxnyVu.js.map} +1 -1
- package/dist/chunks/VendorCollection-D6ZcUYy8.js +100 -0
- package/dist/chunks/VendorCollection-D6ZcUYy8.js.map +1 -0
- package/dist/chunks/{allocation-integrity-Cq0g6CfO.js → allocation-integrity-WmWyXhtG.js} +6 -6
- package/dist/chunks/{allocation-integrity-Cq0g6CfO.js.map → allocation-integrity-WmWyXhtG.js.map} +1 -1
- package/dist/chunks/calculations-C9daQLsh.js +82 -0
- package/dist/chunks/calculations-C9daQLsh.js.map +1 -0
- package/dist/chunks/contract-money-EuToOghh.js +301 -0
- package/dist/chunks/contract-money-EuToOghh.js.map +1 -0
- package/dist/chunks/detect-CY9ufaFb.js +328 -0
- package/dist/chunks/detect-CY9ufaFb.js.map +1 -0
- package/dist/chunks/{document-money-oUDvdjOf.js → document-money-DV5t4vlK.js} +388 -62
- package/dist/chunks/document-money-DV5t4vlK.js.map +1 -0
- package/dist/chunks/{invoice-posting-CF3fE_Ec.js → invoice-posting-C2i5dOVZ.js} +20 -22
- package/dist/chunks/invoice-posting-C2i5dOVZ.js.map +1 -0
- package/dist/chunks/{revenue-journal-DY9fro8E.js → revenue-journal-LLA9Kh_i.js} +3 -14
- package/dist/chunks/revenue-journal-LLA9Kh_i.js.map +1 -0
- package/dist/chunks/tenant-money-barrier-6TlqUeVj.js +255 -0
- package/dist/chunks/tenant-money-barrier-6TlqUeVj.js.map +1 -0
- package/dist/chunks/types-Bbm0Xflc.js.map +1 -1
- package/dist/chunks/{units-CNcjH_eE.js → units-8ElbjVZK.js} +18 -3
- package/dist/chunks/units-8ElbjVZK.js.map +1 -0
- package/dist/collections/ContractCollection.d.ts.map +1 -1
- package/dist/collections/ContractLineItemCollection.d.ts.map +1 -1
- package/dist/collections/InvoiceCollection.d.ts.map +1 -1
- package/dist/collections/InvoiceLineItemCollection.d.ts +0 -30
- package/dist/collections/InvoiceLineItemCollection.d.ts.map +1 -1
- package/dist/collections/TaxCodeCollection.d.ts +5 -1
- package/dist/collections/TaxCodeCollection.d.ts.map +1 -1
- package/dist/collections/TaxSettingsCollection.d.ts +15 -8
- package/dist/collections/TaxSettingsCollection.d.ts.map +1 -1
- package/dist/collections/TaxSummaryReportCollection.d.ts +3 -3
- package/dist/collections/TaxSummaryReportCollection.d.ts.map +1 -1
- package/dist/collections/index.d.ts +0 -1
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/commerce-money-tools.d.ts.map +1 -1
- package/dist/contract-money.d.ts +1 -13
- package/dist/contract-money.d.ts.map +1 -1
- package/dist/document-money-internal.d.ts +7 -3
- package/dist/document-money-internal.d.ts.map +1 -1
- package/dist/document-money.d.ts +1 -11
- package/dist/document-money.d.ts.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +667 -1650
- package/dist/index.js.map +1 -1
- package/dist/invoice-accounting-sync.d.ts.map +1 -1
- package/dist/invoice-mcp.d.ts +3 -3
- package/dist/invoice-mcp.d.ts.map +1 -1
- package/dist/invoice-posting.d.ts +11 -5
- package/dist/invoice-posting.d.ts.map +1 -1
- package/dist/invoice-record-screen.d.ts +1 -1
- package/dist/invoice-record-screen.d.ts.map +1 -1
- package/dist/invoices.d.ts +6 -1
- package/dist/invoices.d.ts.map +1 -1
- package/dist/invoices.js +2 -2
- package/dist/manifest.json +37 -765
- package/dist/migrations/invoiceEditorStorage.d.ts +2 -4
- package/dist/migrations/invoiceEditorStorage.d.ts.map +1 -1
- package/dist/models/Contract.d.ts.map +1 -1
- package/dist/models/ContractLineItem.d.ts +6 -22
- package/dist/models/ContractLineItem.d.ts.map +1 -1
- package/dist/models/Invoice.d.ts +18 -48
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/InvoiceLineItem.d.ts +8 -37
- package/dist/models/InvoiceLineItem.d.ts.map +1 -1
- package/dist/models/TaxSettings.d.ts +0 -10
- package/dist/models/TaxSettings.d.ts.map +1 -1
- package/dist/models/index.d.ts +0 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/playground.js +1 -1
- package/dist/playground.js.map +1 -1
- package/dist/recipes.d.ts +8 -11
- package/dist/recipes.d.ts.map +1 -1
- package/dist/revenue-journal.d.ts +0 -8
- package/dist/revenue-journal.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +79 -661
- package/dist/svelte/components/InvoiceEditor.svelte +7 -148
- package/dist/svelte/components/InvoiceEditor.svelte.d.ts +4 -1
- package/dist/svelte/components/InvoiceEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/InvoiceTotals.svelte +14 -118
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts +4 -27
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts.map +1 -1
- package/dist/svelte/components/MoneyInvoiceEditor.svelte +3 -23
- package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts +3 -26
- package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/index.d.ts +2 -3
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +1 -2
- package/dist/svelte/invoices/calculations.d.ts +3 -108
- package/dist/svelte/invoices/calculations.d.ts.map +1 -1
- package/dist/svelte/invoices/calculations.js +12 -309
- package/dist/svelte/invoices/messages.d.ts +1 -37
- package/dist/svelte/invoices/messages.d.ts.map +1 -1
- package/dist/svelte/invoices/messages.js +1 -37
- package/dist/svelte/invoices/money-editor.d.ts +1 -1
- package/dist/svelte/invoices/money-editor.d.ts.map +1 -1
- package/dist/svelte/invoices/types.d.ts +14 -114
- package/dist/svelte/invoices/types.d.ts.map +1 -1
- package/dist/svelte/playground/InvoicePreparationPreview.svelte +85 -94
- package/dist/svelte/playground/InvoicePreparationPreview.svelte.d.ts.map +1 -1
- package/dist/svelte/playground.js +1 -1
- package/dist/tax/index.d.ts +2 -1
- package/dist/tax/index.d.ts.map +1 -1
- package/dist/tax/standard-codes.d.ts +12 -0
- package/dist/tax/standard-codes.d.ts.map +1 -0
- package/dist/tax/tenant-bootstrap.d.ts +29 -0
- package/dist/tax/tenant-bootstrap.d.ts.map +1 -0
- package/dist/tenant-money-barrier.d.ts +12 -44
- package/dist/tenant-money-barrier.d.ts.map +1 -1
- package/dist/types/index.d.ts +10 -23
- package/dist/types/index.d.ts.map +1 -1
- package/dist/ui.js +1 -1
- package/dist/ui.js.map +1 -1
- package/dist/upgrade/detect.d.ts +129 -0
- package/dist/upgrade/detect.d.ts.map +1 -0
- package/dist/upgrade/money-v2.d.ts +81 -0
- package/dist/upgrade/money-v2.d.ts.map +1 -0
- package/package.json +14 -13
- package/agents/line-amount-migration.md +0 -50
- package/dist/chunks/ContractLineItemCollection--BrGMtNz.js.map +0 -1
- package/dist/chunks/DocumentTaxCollection-KOkaQT2M.js.map +0 -1
- package/dist/chunks/InvoiceCollection-BUe_8FT1.js.map +0 -1
- package/dist/chunks/InvoiceLineItemCollection-CPQGghyd.js +0 -468
- package/dist/chunks/InvoiceLineItemCollection-CPQGghyd.js.map +0 -1
- package/dist/chunks/TaxSettingsCollection-DYYF-In-.js +0 -319
- package/dist/chunks/TaxSettingsCollection-DYYF-In-.js.map +0 -1
- package/dist/chunks/calculations-DaHR17il.js +0 -333
- package/dist/chunks/calculations-DaHR17il.js.map +0 -1
- package/dist/chunks/document-money-oUDvdjOf.js.map +0 -1
- package/dist/chunks/invoice-posting-CF3fE_Ec.js.map +0 -1
- package/dist/chunks/revenue-journal-DY9fro8E.js.map +0 -1
- package/dist/chunks/tenant-money-barrier-y6EAa6vY.js +0 -135
- package/dist/chunks/tenant-money-barrier-y6EAa6vY.js.map +0 -1
- package/dist/chunks/units-CNcjH_eE.js.map +0 -1
- package/dist/collections/MoneyMigrationDocumentCollection.d.ts +0 -12
- package/dist/collections/MoneyMigrationDocumentCollection.d.ts.map +0 -1
- package/dist/migrations/commerceLineAmounts.d.ts +0 -84
- package/dist/migrations/commerceLineAmounts.d.ts.map +0 -1
- package/dist/models/MoneyMigrationDocument.d.ts +0 -28
- package/dist/models/MoneyMigrationDocument.d.ts.map +0 -1
- package/dist/svelte/components/InvoiceLineEditor.svelte +0 -92
- package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts +0 -8
- package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts.map +0 -1
- package/dist/svelte/invoices/fields.d.ts +0 -6
- package/dist/svelte/invoices/fields.d.ts.map +0 -1
- package/dist/svelte/invoices/fields.js +0 -22
- package/dist/tax/legacy.d.ts +0 -48
- package/dist/tax/legacy.d.ts.map +0 -1
|
@@ -1,57 +1,8 @@
|
|
|
1
|
-
/** Unparsed editable invoice line; invalid values remain caller-owned. */
|
|
2
|
-
export interface InvoiceLineDraft {
|
|
3
|
-
/** Stable caller-owned row identity. */
|
|
4
|
-
key: string;
|
|
5
|
-
/** Human-readable item description. */
|
|
6
|
-
description: string;
|
|
7
|
-
/** Optional stock or service code. */
|
|
8
|
-
sku: string;
|
|
9
|
-
/** Nonnegative decimal quantity, at most six decimal places. */
|
|
10
|
-
quantity: string;
|
|
11
|
-
/** Unit price in currency major units. */
|
|
12
|
-
unitPrice: string;
|
|
13
|
-
/** Flat major-unit discount or percentage; unknown drafts remain representable. */
|
|
14
|
-
discountType: string;
|
|
15
|
-
/** Discount in major units or percent according to discountType. */
|
|
16
|
-
discountValue: string;
|
|
17
|
-
/** Inherit the authorized default or use an explicit override. */
|
|
18
|
-
taxMode: string;
|
|
19
|
-
/** Override percent; zero is an explicit exemption, not inheritance. */
|
|
20
|
-
taxRate: string;
|
|
21
|
-
}
|
|
22
|
-
/** Editable header and lines; clients never supply authoritative calculated totals. */
|
|
23
|
-
export interface InvoiceDraftValues {
|
|
24
|
-
/** Customer reference; authorization/existence must be checked by the server. */
|
|
25
|
-
customerId: string;
|
|
26
|
-
/** Calendar issue date, YYYY-MM-DD. */
|
|
27
|
-
issuedOn: string;
|
|
28
|
-
/** Calendar due date, YYYY-MM-DD. */
|
|
29
|
-
dueOn: string;
|
|
30
|
-
/** Uppercase three-letter currency, with Commerce's explicit minor-unit table. */
|
|
31
|
-
currency: string;
|
|
32
|
-
/** Free-form payment terms. */
|
|
33
|
-
paymentTerms: string;
|
|
34
|
-
/** Default tax percent; the server must substitute its authorized rate. */
|
|
35
|
-
taxRate: string;
|
|
36
|
-
/** Caller-owned ordered lines. */
|
|
37
|
-
lines: readonly InvoiceLineDraft[];
|
|
38
|
-
}
|
|
39
|
-
/** Fields on which line validation may report an error. */
|
|
40
|
-
export type InvoiceLineField = keyof InvoiceLineDraft;
|
|
41
|
-
/** Stable validation reasons for caller-localized error messages. */
|
|
42
|
-
export type InvoiceCalculationError = 'required' | 'invalid-decimal' | 'precision' | 'range' | 'invalid-mode' | 'discount-exceeds-gross' | 'invalid-date' | 'duplicate-key' | 'invalid-currency';
|
|
43
|
-
/** Currency and server-authorized inherited percentage for a line. */
|
|
44
|
-
export interface InvoiceCalculationContext {
|
|
45
|
-
/** Uppercase currency code. */
|
|
46
|
-
currency: string;
|
|
47
|
-
/** Default tax percent, for example "5". */
|
|
48
|
-
inheritedTaxRate: string;
|
|
49
|
-
}
|
|
50
1
|
/** All monetary outputs are safe integer minor units. */
|
|
51
2
|
export interface InvoiceCalculatedAmounts {
|
|
52
3
|
/** Rounded quantity times unit price before discounts. */
|
|
53
4
|
grossMinor: number;
|
|
54
|
-
/** Discount
|
|
5
|
+
/** Discount in minor units before tax; it carries the gross sign. */
|
|
55
6
|
discountMinor: number;
|
|
56
7
|
/** Gross less discount. */
|
|
57
8
|
subtotalMinor: number;
|
|
@@ -60,76 +11,20 @@ export interface InvoiceCalculatedAmounts {
|
|
|
60
11
|
/** Subtotal plus tax. */
|
|
61
12
|
totalMinor: number;
|
|
62
13
|
}
|
|
63
|
-
/** Success or field errors, with no plausible monetary output for an invalid line. */
|
|
64
|
-
export type InvoiceLineCalculation = ({
|
|
65
|
-
valid: true;
|
|
66
|
-
effectiveTaxRate: string;
|
|
67
|
-
} & InvoiceCalculatedAmounts) | {
|
|
68
|
-
valid: false;
|
|
69
|
-
errors: Partial<Record<InvoiceLineField, InvoiceCalculationError>>;
|
|
70
|
-
};
|
|
71
|
-
/** Header error keys include whole-invoice totals and line membership. */
|
|
72
|
-
export type InvoiceDraftField = Exclude<keyof InvoiceDraftValues, 'lines'> | 'lines' | 'total' | 'roundingScope';
|
|
73
|
-
/** Server-authorized tax rounding; absent means the historical per-line behavior. */
|
|
74
|
-
export interface InvoiceDraftCalculationOptions {
|
|
75
|
-
/** Invoice scope groups equal effective percentages and rounds each group once. */
|
|
76
|
-
roundingScope?: 'line' | 'invoice';
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Aggregate result retains standalone line calculations for validation/audit.
|
|
80
|
-
* With invoice rounding, line tax/total are estimates, NOT allocated invoice
|
|
81
|
-
* amounts, and must not be summed or persisted as authoritative invoice tax.
|
|
82
|
-
*/
|
|
83
|
-
export type InvoiceDraftCalculation = ({
|
|
84
|
-
valid: true;
|
|
85
|
-
lineResults: readonly InvoiceLineCalculation[];
|
|
86
|
-
} & InvoiceCalculatedAmounts) | {
|
|
87
|
-
valid: false;
|
|
88
|
-
errors: Partial<Record<InvoiceDraftField, InvoiceCalculationError>>;
|
|
89
|
-
lineResults: readonly InvoiceLineCalculation[];
|
|
90
|
-
};
|
|
91
14
|
/** Existing model monetary inputs, independent of currency display precision. */
|
|
92
15
|
export interface InvoiceMinorLineInput {
|
|
93
16
|
/** Nonnegative quantity with at most six fractional digits. */
|
|
94
17
|
quantity: number;
|
|
95
18
|
/** Signed integer minor units; negative prices support existing credit lines. */
|
|
96
19
|
unitPrice: number;
|
|
97
|
-
/**
|
|
20
|
+
/** Flat discount in signed integer minor units; it carries the gross sign. */
|
|
98
21
|
discount: number;
|
|
99
22
|
/** Resolved tax fraction, at most eight fractional digits, in [0, 1]. */
|
|
100
23
|
taxRate: number;
|
|
101
24
|
}
|
|
102
|
-
/** Explicit migration boundary for persisted legacy invoice-line arithmetic. */
|
|
103
|
-
export interface InvoiceMinorLineCalculationOptions {
|
|
104
|
-
/** Existing callers remain legacy until #3933's per-tenant marker selects v2. */
|
|
105
|
-
moneyModel?: 'legacy' | 'v2';
|
|
106
|
-
}
|
|
107
25
|
/**
|
|
108
26
|
* Exact model calculation, including existing negative-price credit lines.
|
|
109
27
|
* Throws before persistence for unsafe money, invalid quantity, or invalid tax.
|
|
110
28
|
*/
|
|
111
|
-
export declare function calculateInvoiceMinorLine(input: InvoiceMinorLineInput
|
|
112
|
-
/** Validated line fields suitable for the existing model's resolved money columns. */
|
|
113
|
-
export interface InvoiceResolvedLine extends InvoiceMinorLineInput {
|
|
114
|
-
/** Validated item description. */
|
|
115
|
-
description: string;
|
|
116
|
-
/** Caller stock code. */
|
|
117
|
-
sku: string;
|
|
118
|
-
/** Recomputed total; never copied from a browser total field. */
|
|
119
|
-
amount: number;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Resolve a validated editor draft to model fields. Percentage discounts become
|
|
123
|
-
* exact flat minor units; inherited tax becomes the authorized effective rate.
|
|
124
|
-
* Keep the raw draft alongside these fields when reopening its editing modes.
|
|
125
|
-
*/
|
|
126
|
-
export declare function resolveInvoiceLineDraft(line: InvoiceLineDraft, context: InvoiceCalculationContext): InvoiceResolvedLine;
|
|
127
|
-
/**
|
|
128
|
-
* Validate and calculate one line using decimal integer arithmetic. Round half
|
|
129
|
-
* up separately at gross, percentage discount, and tax boundaries. No rounding
|
|
130
|
-
* is permitted when parsing a price or flat discount into currency minor units.
|
|
131
|
-
*/
|
|
132
|
-
export declare function calculateInvoiceLine(line: InvoiceLineDraft, context: InvoiceCalculationContext): InvoiceLineCalculation;
|
|
133
|
-
/** Validate the header and sum validated lines without floating-point arithmetic. */
|
|
134
|
-
export declare function calculateInvoiceDraft(values: InvoiceDraftValues, options?: InvoiceDraftCalculationOptions): InvoiceDraftCalculation;
|
|
29
|
+
export declare function calculateInvoiceMinorLine(input: InvoiceMinorLineInput): InvoiceCalculatedAmounts;
|
|
135
30
|
//# sourceMappingURL=calculations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calculations.d.ts","sourceRoot":"","sources":["../../../src/svelte/invoices/calculations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"calculations.d.ts","sourceRoot":"","sources":["../../../src/svelte/invoices/calculations.ts"],"names":[],"mappings":"AAQA,yDAAyD;AACzD,MAAM,WAAW,wBAAwB;IACvC,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAOD,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;CACjB;AAsDD;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,qBAAqB,GAC3B,wBAAwB,CA2C1B"}
|
|
@@ -1,40 +1,5 @@
|
|
|
1
|
-
/** Exact, transport-neutral invoice
|
|
1
|
+
/** Exact, transport-neutral invoice line calculation shared by browser and server. */
|
|
2
2
|
import { calculateMoneyDocument, MoneyValidationError, } from '../../money.js';
|
|
3
|
-
import { currencyMinorUnitExponent } from './currency.js';
|
|
4
|
-
const MAX_MINOR = BigInt(Number.MAX_SAFE_INTEGER);
|
|
5
|
-
const MAX_TEXT = 128;
|
|
6
|
-
function decimal(value, precision) {
|
|
7
|
-
if (typeof value !== 'string' ||
|
|
8
|
-
value.length > MAX_TEXT ||
|
|
9
|
-
!/^\d+(?:\.\d+)?$/.test(value))
|
|
10
|
-
return 'invalid-decimal';
|
|
11
|
-
const [whole, fraction = ''] = value.split('.');
|
|
12
|
-
if (fraction.length > precision)
|
|
13
|
-
return 'precision';
|
|
14
|
-
return {
|
|
15
|
-
coefficient: BigInt(whole + fraction),
|
|
16
|
-
scale: 10n ** BigInt(fraction.length),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
function roundHalfUp(numerator, denominator) {
|
|
20
|
-
return (numerator * 2n + denominator) / (denominator * 2n);
|
|
21
|
-
}
|
|
22
|
-
function minor(value, digits) {
|
|
23
|
-
const parsed = decimal(value, MAX_TEXT);
|
|
24
|
-
if (typeof parsed === 'string')
|
|
25
|
-
return parsed;
|
|
26
|
-
const scaled = parsed.coefficient * 10n ** BigInt(digits);
|
|
27
|
-
if (scaled % parsed.scale !== 0n)
|
|
28
|
-
return 'precision';
|
|
29
|
-
const result = scaled / parsed.scale;
|
|
30
|
-
return result > MAX_MINOR ? 'range' : result;
|
|
31
|
-
}
|
|
32
|
-
function rate(value) {
|
|
33
|
-
const parsed = decimal(value, 6);
|
|
34
|
-
if (typeof parsed === 'string')
|
|
35
|
-
return parsed;
|
|
36
|
-
return parsed.coefficient > 100n * parsed.scale ? 'range' : parsed;
|
|
37
|
-
}
|
|
38
3
|
function numberDecimal(value, precision) {
|
|
39
4
|
if (!Number.isFinite(value) || value < 0 || value > Number.MAX_SAFE_INTEGER)
|
|
40
5
|
throw new RangeError('Invoice rate or quantity is outside the supported range.');
|
|
@@ -50,11 +15,6 @@ function numberDecimal(value, precision) {
|
|
|
50
15
|
? { coefficient: coefficient * 10n ** BigInt(-places), scale: 1n }
|
|
51
16
|
: { coefficient, scale: 10n ** BigInt(places) };
|
|
52
17
|
}
|
|
53
|
-
function roundSignedLegacy(numerator, denominator) {
|
|
54
|
-
return numerator >= 0n
|
|
55
|
-
? roundHalfUp(numerator, denominator)
|
|
56
|
-
: -((-numerator * 2n + denominator - 1n) / (denominator * 2n));
|
|
57
|
-
}
|
|
58
18
|
function decimalText(value) {
|
|
59
19
|
if (value.scale === 1n)
|
|
60
20
|
return value.coefficient.toString();
|
|
@@ -65,19 +25,20 @@ function decimalText(value) {
|
|
|
65
25
|
.replace(/0+$/, '')
|
|
66
26
|
.replace(/\.$/, '');
|
|
67
27
|
}
|
|
68
|
-
|
|
28
|
+
/** An in-memory single-rate tax code for editor previews of a percent rate. */
|
|
29
|
+
function rateTaxCode(percent) {
|
|
69
30
|
const normalized = percent
|
|
70
31
|
.replace(/^0+(?=\d)/, '')
|
|
71
32
|
.replace(/(\.\d*?)0+$/, '$1')
|
|
72
33
|
.replace(/\.$/, '') || '0';
|
|
73
34
|
return normalized === '0'
|
|
74
|
-
? { id: '
|
|
35
|
+
? { id: 'rate-zero', kind: 'zero-rated', components: [] }
|
|
75
36
|
: {
|
|
76
|
-
id: `
|
|
37
|
+
id: `rate-${normalized}`,
|
|
77
38
|
kind: 'taxable',
|
|
78
39
|
components: [
|
|
79
40
|
{
|
|
80
|
-
taxComponentId: `
|
|
41
|
+
taxComponentId: `rate-${normalized}`,
|
|
81
42
|
percent: normalized,
|
|
82
43
|
compound: false,
|
|
83
44
|
},
|
|
@@ -88,34 +49,14 @@ function legacyTaxCode(percent) {
|
|
|
88
49
|
* Exact model calculation, including existing negative-price credit lines.
|
|
89
50
|
* Throws before persistence for unsafe money, invalid quantity, or invalid tax.
|
|
90
51
|
*/
|
|
91
|
-
export function calculateInvoiceMinorLine(input
|
|
52
|
+
export function calculateInvoiceMinorLine(input) {
|
|
92
53
|
for (const amount of [input.unitPrice, input.discount])
|
|
93
54
|
if (!Number.isSafeInteger(amount))
|
|
94
55
|
throw new RangeError('Invoice money must be safe integer minor units.');
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const quantity = numberDecimal(input.quantity, 6);
|
|
56
|
+
if (input.taxRate > 1)
|
|
57
|
+
throw new RangeError('Invoice tax rate is outside the supported range.');
|
|
58
|
+
numberDecimal(input.quantity, 6);
|
|
99
59
|
const tax = numberDecimal(input.taxRate, 8);
|
|
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
60
|
const percent = decimalText({
|
|
120
61
|
coefficient: tax.coefficient * 100n,
|
|
121
62
|
scale: tax.scale,
|
|
@@ -128,13 +69,13 @@ export function calculateInvoiceMinorLine(input, options = {}) {
|
|
|
128
69
|
roundingScope: 'line',
|
|
129
70
|
lines: [
|
|
130
71
|
{
|
|
131
|
-
id: '
|
|
72
|
+
id: 'line',
|
|
132
73
|
quantity: input.quantity,
|
|
133
74
|
unitPrice: input.unitPrice,
|
|
134
75
|
discount: input.discount === 0
|
|
135
76
|
? { kind: 'none' }
|
|
136
77
|
: { kind: 'amount', minor: input.discount },
|
|
137
|
-
taxCode:
|
|
78
|
+
taxCode: rateTaxCode(percent),
|
|
138
79
|
},
|
|
139
80
|
],
|
|
140
81
|
}).lines[0];
|
|
@@ -152,241 +93,3 @@ export function calculateInvoiceMinorLine(input, options = {}) {
|
|
|
152
93
|
totalMinor: result.netMinor + result.taxMinor,
|
|
153
94
|
};
|
|
154
95
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Resolve a validated editor draft to model fields. Percentage discounts become
|
|
157
|
-
* exact flat minor units; inherited tax becomes the authorized effective rate.
|
|
158
|
-
* Keep the raw draft alongside these fields when reopening its editing modes.
|
|
159
|
-
*/
|
|
160
|
-
export function resolveInvoiceLineDraft(line, context) {
|
|
161
|
-
const result = calculateInvoiceLine(line, context);
|
|
162
|
-
if (!result.valid)
|
|
163
|
-
throw new RangeError(`Invalid invoice line: ${JSON.stringify(result.errors)}`);
|
|
164
|
-
const quantity = Number(line.quantity);
|
|
165
|
-
const sourceQuantity = decimal(line.quantity, 6);
|
|
166
|
-
const storedQuantity = numberDecimal(quantity, 6);
|
|
167
|
-
if (typeof sourceQuantity === 'string' ||
|
|
168
|
-
sourceQuantity.coefficient * storedQuantity.scale !==
|
|
169
|
-
storedQuantity.coefficient * sourceQuantity.scale)
|
|
170
|
-
throw new RangeError('Invoice quantity cannot round-trip through numeric persistence.');
|
|
171
|
-
const [whole, fraction = ''] = result.effectiveTaxRate.split('.');
|
|
172
|
-
const rateDigits = BigInt(whole + fraction)
|
|
173
|
-
.toString()
|
|
174
|
-
.padStart(fraction.length + 3, '0');
|
|
175
|
-
const split = rateDigits.length - fraction.length - 2;
|
|
176
|
-
const taxRate = Number(`${rateDigits.slice(0, split)}.${rateDigits.slice(split)}`);
|
|
177
|
-
const unitPrice = minor(line.unitPrice, currencyMinorUnitExponent(context.currency));
|
|
178
|
-
if (typeof unitPrice !== 'bigint')
|
|
179
|
-
throw new RangeError('Invalid invoice unit price.');
|
|
180
|
-
const resolved = {
|
|
181
|
-
description: line.description,
|
|
182
|
-
sku: line.sku,
|
|
183
|
-
quantity,
|
|
184
|
-
unitPrice: Number(unitPrice),
|
|
185
|
-
discount: result.discountMinor,
|
|
186
|
-
taxRate,
|
|
187
|
-
amount: result.totalMinor,
|
|
188
|
-
};
|
|
189
|
-
const model = calculateInvoiceMinorLine(resolved);
|
|
190
|
-
if (model.totalMinor !== result.totalMinor ||
|
|
191
|
-
model.subtotalMinor !== result.subtotalMinor ||
|
|
192
|
-
model.taxMinor !== result.taxMinor)
|
|
193
|
-
throw new RangeError('Invoice draft and persisted calculation disagree.');
|
|
194
|
-
return resolved;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Validate and calculate one line using decimal integer arithmetic. Round half
|
|
198
|
-
* up separately at gross, percentage discount, and tax boundaries. No rounding
|
|
199
|
-
* is permitted when parsing a price or flat discount into currency minor units.
|
|
200
|
-
*/
|
|
201
|
-
export function calculateInvoiceLine(line, context) {
|
|
202
|
-
const errors = {};
|
|
203
|
-
if (!line.key?.trim())
|
|
204
|
-
errors.key = 'required';
|
|
205
|
-
if (!line.description?.trim())
|
|
206
|
-
errors.description = 'required';
|
|
207
|
-
if (!/^[A-Z]{3}$/.test(context.currency))
|
|
208
|
-
return { valid: false, errors: { unitPrice: 'invalid-currency' } };
|
|
209
|
-
const digits = currencyMinorUnitExponent(context.currency);
|
|
210
|
-
const quantity = decimal(line.quantity, 6);
|
|
211
|
-
const price = minor(line.unitPrice, digits);
|
|
212
|
-
if (typeof quantity === 'string')
|
|
213
|
-
errors.quantity = quantity;
|
|
214
|
-
else if (quantity.coefficient > MAX_MINOR * quantity.scale)
|
|
215
|
-
errors.quantity = 'range';
|
|
216
|
-
else {
|
|
217
|
-
try {
|
|
218
|
-
const persisted = numberDecimal(Number(line.quantity), 6);
|
|
219
|
-
if (quantity.coefficient * persisted.scale !==
|
|
220
|
-
persisted.coefficient * quantity.scale)
|
|
221
|
-
errors.quantity = 'precision';
|
|
222
|
-
}
|
|
223
|
-
catch {
|
|
224
|
-
errors.quantity = 'precision';
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
if (typeof price === 'string')
|
|
228
|
-
errors.unitPrice = price;
|
|
229
|
-
if (line.discountType !== 'flat' && line.discountType !== 'percent')
|
|
230
|
-
errors.discountType = 'invalid-mode';
|
|
231
|
-
if (line.taxMode !== 'inherit' && line.taxMode !== 'override')
|
|
232
|
-
errors.taxMode = 'invalid-mode';
|
|
233
|
-
const discount = line.discountType === 'percent'
|
|
234
|
-
? rate(line.discountValue)
|
|
235
|
-
: minor(line.discountValue, digits);
|
|
236
|
-
if (typeof discount === 'string')
|
|
237
|
-
errors.discountValue = discount;
|
|
238
|
-
const effectiveTaxRate = line.taxMode === 'inherit' ? context.inheritedTaxRate : line.taxRate;
|
|
239
|
-
const tax = rate(effectiveTaxRate);
|
|
240
|
-
if (typeof tax === 'string')
|
|
241
|
-
errors.taxRate = tax;
|
|
242
|
-
if (Object.keys(errors).length ||
|
|
243
|
-
typeof quantity === 'string' ||
|
|
244
|
-
typeof price === 'string' ||
|
|
245
|
-
typeof discount === 'string' ||
|
|
246
|
-
typeof tax === 'string')
|
|
247
|
-
return { valid: false, errors };
|
|
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
|
-
};
|
|
277
|
-
return { valid: false, errors: { taxRate: 'range' } };
|
|
278
|
-
}
|
|
279
|
-
return {
|
|
280
|
-
valid: true,
|
|
281
|
-
effectiveTaxRate,
|
|
282
|
-
grossMinor: calculated.grossMinor,
|
|
283
|
-
discountMinor: calculated.discountMinor,
|
|
284
|
-
subtotalMinor: calculated.netMinor,
|
|
285
|
-
taxMinor: calculated.taxMinor,
|
|
286
|
-
totalMinor: calculated.netMinor + calculated.taxMinor,
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
function calendarDate(value) {
|
|
290
|
-
if (!/^\d{4}-\d{2}-\d{2}$/.test(value) || value.startsWith('0000'))
|
|
291
|
-
return false;
|
|
292
|
-
const date = new Date(`${value}T00:00:00.000Z`);
|
|
293
|
-
return (Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === value);
|
|
294
|
-
}
|
|
295
|
-
/** Validate the header and sum validated lines without floating-point arithmetic. */
|
|
296
|
-
export function calculateInvoiceDraft(values, options = {}) {
|
|
297
|
-
const errors = {};
|
|
298
|
-
const roundingScope = options.roundingScope === undefined ? 'line' : options.roundingScope;
|
|
299
|
-
if (roundingScope !== 'line' && roundingScope !== 'invoice')
|
|
300
|
-
errors.roundingScope = 'invalid-mode';
|
|
301
|
-
if (!values.customerId?.trim())
|
|
302
|
-
errors.customerId = 'required';
|
|
303
|
-
if (!calendarDate(values.issuedOn))
|
|
304
|
-
errors.issuedOn = 'invalid-date';
|
|
305
|
-
if (!calendarDate(values.dueOn) || values.dueOn < values.issuedOn)
|
|
306
|
-
errors.dueOn = 'invalid-date';
|
|
307
|
-
if (!/^[A-Z]{3}$/.test(values.currency))
|
|
308
|
-
errors.currency = 'invalid-currency';
|
|
309
|
-
const inheritedRate = rate(values.taxRate);
|
|
310
|
-
if (typeof inheritedRate === 'string')
|
|
311
|
-
errors.taxRate = inheritedRate;
|
|
312
|
-
if (values.lines.length === 0)
|
|
313
|
-
errors.lines = 'required';
|
|
314
|
-
if (new Set(values.lines.map((line) => line.key)).size !== values.lines.length)
|
|
315
|
-
errors.lines = 'duplicate-key';
|
|
316
|
-
const lineResults = values.lines.map((line) => calculateInvoiceLine(line, {
|
|
317
|
-
currency: values.currency,
|
|
318
|
-
inheritedTaxRate: values.taxRate,
|
|
319
|
-
}));
|
|
320
|
-
const sums = {
|
|
321
|
-
grossMinor: 0n,
|
|
322
|
-
discountMinor: 0n,
|
|
323
|
-
subtotalMinor: 0n,
|
|
324
|
-
taxMinor: 0n,
|
|
325
|
-
totalMinor: 0n,
|
|
326
|
-
};
|
|
327
|
-
for (const result of lineResults) {
|
|
328
|
-
if (!result.valid)
|
|
329
|
-
continue;
|
|
330
|
-
for (const key of Object.keys(sums))
|
|
331
|
-
sums[key] += BigInt(result[key]);
|
|
332
|
-
}
|
|
333
|
-
if (roundingScope === 'invoice' &&
|
|
334
|
-
!Object.keys(errors).length &&
|
|
335
|
-
lineResults.every((result) => result.valid)) {
|
|
336
|
-
// Rates have already passed exact decimal validation. Normalize textual
|
|
337
|
-
// equivalents without numeric conversion before assigning component IDs.
|
|
338
|
-
const taxable = lineResults.map((result, index) => {
|
|
339
|
-
if (!result.valid)
|
|
340
|
-
throw new Error('Validated invoice line expected');
|
|
341
|
-
const [whole, fraction = ''] = result.effectiveTaxRate.split('.');
|
|
342
|
-
const digits = fraction.replace(/0+$/, '');
|
|
343
|
-
const percent = `${BigInt(whole)}${digits ? `.${digits}` : ''}`;
|
|
344
|
-
return {
|
|
345
|
-
id: values.lines[index].key,
|
|
346
|
-
amountMinor: result.subtotalMinor,
|
|
347
|
-
category: percent,
|
|
348
|
-
};
|
|
349
|
-
});
|
|
350
|
-
try {
|
|
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
|
-
}),
|
|
369
|
-
});
|
|
370
|
-
sums.taxMinor = BigInt(calculated.taxMinor);
|
|
371
|
-
sums.totalMinor = sums.subtotalMinor + sums.taxMinor;
|
|
372
|
-
}
|
|
373
|
-
catch (cause) {
|
|
374
|
-
if (!(cause instanceof RangeError || cause instanceof MoneyValidationError))
|
|
375
|
-
throw cause;
|
|
376
|
-
errors.total = 'range';
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
if (Object.values(sums).some((value) => value > MAX_MINOR))
|
|
380
|
-
errors.total = 'range';
|
|
381
|
-
if (Object.keys(errors).length || lineResults.some((result) => !result.valid))
|
|
382
|
-
return { valid: false, errors, lineResults };
|
|
383
|
-
return {
|
|
384
|
-
valid: true,
|
|
385
|
-
lineResults,
|
|
386
|
-
grossMinor: Number(sums.grossMinor),
|
|
387
|
-
discountMinor: Number(sums.discountMinor),
|
|
388
|
-
subtotalMinor: Number(sums.subtotalMinor),
|
|
389
|
-
taxMinor: Number(sums.taxMinor),
|
|
390
|
-
totalMinor: Number(sums.totalMinor),
|
|
391
|
-
};
|
|
392
|
-
}
|
|
@@ -1,37 +1,5 @@
|
|
|
1
|
+
/** Messages for the invoice allocation fields and review presentation. */
|
|
1
2
|
export declare const invoicePreparationMessages: {
|
|
2
|
-
readonly 'commerce.preparation.title': "commerce.preparation.title";
|
|
3
|
-
readonly 'commerce.invoice.customer': "commerce.invoice.customer";
|
|
4
|
-
readonly 'commerce.invoice.chooseCustomer': "commerce.invoice.chooseCustomer";
|
|
5
|
-
readonly 'commerce.invoice.issued': "commerce.invoice.issued";
|
|
6
|
-
readonly 'commerce.invoice.due': "commerce.invoice.due";
|
|
7
|
-
readonly 'commerce.invoice.currency': "commerce.invoice.currency";
|
|
8
|
-
readonly 'commerce.invoice.terms': "commerce.invoice.terms";
|
|
9
|
-
readonly 'commerce.invoice.defaultTax': "commerce.invoice.defaultTax";
|
|
10
|
-
readonly 'commerce.invoice.line': "commerce.invoice.line";
|
|
11
|
-
readonly 'commerce.invoice.description': "commerce.invoice.description";
|
|
12
|
-
readonly 'commerce.invoice.sku': "commerce.invoice.sku";
|
|
13
|
-
readonly 'commerce.invoice.quantity': "commerce.invoice.quantity";
|
|
14
|
-
readonly 'commerce.invoice.unitPrice': "commerce.invoice.unitPrice";
|
|
15
|
-
readonly 'commerce.invoice.discountType': "commerce.invoice.discountType";
|
|
16
|
-
readonly 'commerce.invoice.flat': "commerce.invoice.flat";
|
|
17
|
-
readonly 'commerce.invoice.percent': "commerce.invoice.percent";
|
|
18
|
-
readonly 'commerce.invoice.discountValue': "commerce.invoice.discountValue";
|
|
19
|
-
readonly 'commerce.invoice.taxMode': "commerce.invoice.taxMode";
|
|
20
|
-
readonly 'commerce.invoice.inherit': "commerce.invoice.inherit";
|
|
21
|
-
readonly 'commerce.invoice.override': "commerce.invoice.override";
|
|
22
|
-
readonly 'commerce.invoice.taxRate': "commerce.invoice.taxRate";
|
|
23
|
-
readonly 'commerce.invoice.remove': "commerce.invoice.remove";
|
|
24
|
-
readonly 'commerce.invoice.add': "commerce.invoice.add";
|
|
25
|
-
readonly 'commerce.invoice.empty': "commerce.invoice.empty";
|
|
26
|
-
readonly 'commerce.invoice.gross': "commerce.invoice.gross";
|
|
27
|
-
readonly 'commerce.invoice.discount': "commerce.invoice.discount";
|
|
28
|
-
readonly 'commerce.invoice.subtotal': "commerce.invoice.subtotal";
|
|
29
|
-
readonly 'commerce.invoice.tax': "commerce.invoice.tax";
|
|
30
|
-
readonly 'commerce.invoice.total': "commerce.invoice.total";
|
|
31
|
-
readonly 'commerce.invoice.invalid': "commerce.invoice.invalid";
|
|
32
|
-
readonly 'commerce.invoice.invoiceRounding': "commerce.invoice.invoiceRounding";
|
|
33
|
-
readonly 'commerce.invoice.preview': "commerce.invoice.preview";
|
|
34
|
-
readonly 'commerce.invoice.retained': "commerce.invoice.retained";
|
|
35
3
|
readonly 'commerce.preparation.allocation': "commerce.preparation.allocation";
|
|
36
4
|
readonly 'commerce.preparation.source': "commerce.preparation.source";
|
|
37
5
|
readonly 'commerce.preparation.reference': "commerce.preparation.reference";
|
|
@@ -42,13 +10,9 @@ export declare const invoicePreparationMessages: {
|
|
|
42
10
|
readonly 'commerce.preparation.help': "commerce.preparation.help";
|
|
43
11
|
readonly 'commerce.preparation.remove': "commerce.preparation.remove";
|
|
44
12
|
readonly 'commerce.preparation.add': "commerce.preparation.add";
|
|
45
|
-
readonly 'commerce.preparation.save': "commerce.preparation.save";
|
|
46
|
-
readonly 'commerce.preparation.cancel': "commerce.preparation.cancel";
|
|
47
13
|
readonly 'commerce.preparation.restricted': "commerce.preparation.restricted";
|
|
48
14
|
readonly 'commerce.preparation.empty': "commerce.preparation.empty";
|
|
49
15
|
readonly 'commerce.preparation.no_rows': "commerce.preparation.no_rows";
|
|
50
|
-
readonly 'commerce.preparation.readonly': "commerce.preparation.readonly";
|
|
51
|
-
readonly 'commerce.preparation.uncertain': "commerce.preparation.uncertain";
|
|
52
16
|
readonly 'commerce.preparation.review': "commerce.preparation.review";
|
|
53
17
|
};
|
|
54
18
|
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/svelte/invoices/messages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,0BAA0B
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/svelte/invoices/messages.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;CAoBrC,CAAC"}
|
|
@@ -1,38 +1,6 @@
|
|
|
1
1
|
import { defineMessages } from '@happyvertical/smrt-ui/i18n';
|
|
2
|
+
/** Messages for the invoice allocation fields and review presentation. */
|
|
2
3
|
export const invoicePreparationMessages = defineMessages({
|
|
3
|
-
'commerce.preparation.title': 'Prepare invoice',
|
|
4
|
-
'commerce.invoice.customer': 'Customer',
|
|
5
|
-
'commerce.invoice.chooseCustomer': 'Choose a customer',
|
|
6
|
-
'commerce.invoice.issued': 'Invoice date',
|
|
7
|
-
'commerce.invoice.due': 'Due date',
|
|
8
|
-
'commerce.invoice.currency': 'Currency',
|
|
9
|
-
'commerce.invoice.terms': 'Payment terms',
|
|
10
|
-
'commerce.invoice.defaultTax': 'Default tax (%)',
|
|
11
|
-
'commerce.invoice.line': 'Invoice line {number}',
|
|
12
|
-
'commerce.invoice.description': 'Description',
|
|
13
|
-
'commerce.invoice.sku': 'SKU',
|
|
14
|
-
'commerce.invoice.quantity': 'Quantity',
|
|
15
|
-
'commerce.invoice.unitPrice': 'Unit price ({currency})',
|
|
16
|
-
'commerce.invoice.discountType': 'Discount type',
|
|
17
|
-
'commerce.invoice.flat': 'Flat amount',
|
|
18
|
-
'commerce.invoice.percent': 'Percentage',
|
|
19
|
-
'commerce.invoice.discountValue': 'Discount value',
|
|
20
|
-
'commerce.invoice.taxMode': 'Tax mode',
|
|
21
|
-
'commerce.invoice.inherit': 'Inherit default tax',
|
|
22
|
-
'commerce.invoice.override': 'Override tax',
|
|
23
|
-
'commerce.invoice.taxRate': 'Line tax (%)',
|
|
24
|
-
'commerce.invoice.remove': 'Remove line',
|
|
25
|
-
'commerce.invoice.add': 'Add line',
|
|
26
|
-
'commerce.invoice.empty': 'No invoice lines. Add a line to begin.',
|
|
27
|
-
'commerce.invoice.gross': 'Gross',
|
|
28
|
-
'commerce.invoice.discount': 'Discount',
|
|
29
|
-
'commerce.invoice.subtotal': 'Subtotal',
|
|
30
|
-
'commerce.invoice.tax': 'Tax',
|
|
31
|
-
'commerce.invoice.total': 'Total',
|
|
32
|
-
'commerce.invoice.invalid': 'Totals unavailable until quantity, price, discount, tax and currency are valid.',
|
|
33
|
-
'commerce.invoice.invoiceRounding': 'Tax is rounded across the invoice for each effective rate; see the invoice totals.',
|
|
34
|
-
'commerce.invoice.preview': 'Calculated preview; the server revalidates prices, tax and totals.',
|
|
35
|
-
'commerce.invoice.retained': 'Retained reference: {reference}',
|
|
36
4
|
'commerce.preparation.allocation': 'Allocation {number}',
|
|
37
5
|
'commerce.preparation.source': 'Reviewed source',
|
|
38
6
|
'commerce.preparation.reference': 'Source reference',
|
|
@@ -43,12 +11,8 @@ export const invoicePreparationMessages = defineMessages({
|
|
|
43
11
|
'commerce.preparation.help': 'Enter currency amounts, for example 125.00 for CAD. The server validates currency precision and source availability.',
|
|
44
12
|
'commerce.preparation.remove': 'Remove this allocation',
|
|
45
13
|
'commerce.preparation.add': 'Add allocation row',
|
|
46
|
-
'commerce.preparation.save': 'Save invoice draft',
|
|
47
|
-
'commerce.preparation.cancel': 'Cancel',
|
|
48
14
|
'commerce.preparation.restricted': 'Source details are restricted. Enter references supplied through your authorized workflow.',
|
|
49
15
|
'commerce.preparation.empty': 'No reviewed sources are available. Retained references remain visible for review.',
|
|
50
16
|
'commerce.preparation.no_rows': 'No allocations. Add a row to prepare this draft.',
|
|
51
|
-
'commerce.preparation.readonly': 'This draft is read-only.',
|
|
52
|
-
'commerce.preparation.uncertain': 'The outcome is uncertain. Your values and request identity are retained; follow your application’s retry guidance.',
|
|
53
17
|
'commerce.preparation.review': 'Invoice review',
|
|
54
18
|
});
|
|
@@ -69,7 +69,7 @@ export interface MoneyEditorFieldNames {
|
|
|
69
69
|
}
|
|
70
70
|
export declare const moneyEditorFieldNames: MoneyEditorFieldNames;
|
|
71
71
|
export interface MoneyEditorProps {
|
|
72
|
-
/**
|
|
72
|
+
/** Money model discriminator; v2 is the only invoice money model. */
|
|
73
73
|
mode: 'v2';
|
|
74
74
|
draft: MoneyEditorDraft;
|
|
75
75
|
taxCodes: readonly MoneyEditorTaxCode[];
|
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"money-editor.d.ts","sourceRoot":"","sources":["../../../src/svelte/invoices/money-editor.ts"],"names":[],"mappings":"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"}
|