@happyvertical/smrt-commerce 0.40.70 → 0.41.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 +9 -2
- package/README.md +8 -8
- package/dist/chunks/money-WSMvSgWq.js +8 -0
- package/dist/chunks/money-WSMvSgWq.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +297 -115
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +613 -387
- package/dist/migrations/moneyMinorUnits.d.ts +86 -0
- package/dist/migrations/moneyMinorUnits.d.ts.map +1 -0
- package/dist/models/Contract.d.ts +19 -9
- package/dist/models/Contract.d.ts.map +1 -1
- package/dist/models/ContractLineItem.d.ts +21 -7
- package/dist/models/ContractLineItem.d.ts.map +1 -1
- package/dist/models/Customer.d.ts +7 -1
- package/dist/models/Customer.d.ts.map +1 -1
- package/dist/models/Invoice.d.ts +43 -37
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/InvoiceLineItem.d.ts +34 -10
- package/dist/models/InvoiceLineItem.d.ts.map +1 -1
- package/dist/models/Payment.d.ts +31 -11
- package/dist/models/Payment.d.ts.map +1 -1
- package/dist/models/PaymentAllocation.d.ts +9 -2
- package/dist/models/PaymentAllocation.d.ts.map +1 -1
- package/dist/models/PaymentIntent.d.ts +7 -2
- package/dist/models/PaymentIntent.d.ts.map +1 -1
- package/dist/models/Payout.d.ts +15 -10
- package/dist/models/Payout.d.ts.map +1 -1
- package/dist/models/Vendor.d.ts +3 -1
- package/dist/models/Vendor.d.ts.map +1 -1
- package/dist/money.d.ts +27 -0
- package/dist/money.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +155 -93
- package/package.json +8 -7
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { DatabaseInterface, MinorUnitsPreflightResult, MinorUnitsRescaleResult, MoneyColumnTarget } from '@happyvertical/smrt-core/migrations';
|
|
2
|
+
/** Marker recorded in `_smrt_backfills` once the column rescale has run. */
|
|
3
|
+
export declare const COMMERCE_MONEY_MINOR_UNITS_BACKFILL = "@happyvertical/smrt-commerce:money-minor-units:v1";
|
|
4
|
+
/**
|
|
5
|
+
* Every commerce money column denominated in the deployment's own currency,
|
|
6
|
+
* i.e. everything a single scale converts correctly.
|
|
7
|
+
*
|
|
8
|
+
* `invoices`, `invoice_line_items` and `payment_allocations` are absent on
|
|
9
|
+
* purpose: those were already INTEGER (#2361), so the preflight reports them as
|
|
10
|
+
* converted and there is nothing to rescale. Rate columns (`tax_rate`) are
|
|
11
|
+
* absent for the opposite reason — they are genuinely fractional and must stay
|
|
12
|
+
* DECIMAL. `payments.native_amount` is absent because its scale is per-asset;
|
|
13
|
+
* see {@link COMMERCE_NATIVE_UNIT_COLUMNS}.
|
|
14
|
+
*/
|
|
15
|
+
export declare const COMMERCE_MONEY_COLUMNS: MoneyColumnTarget[];
|
|
16
|
+
/**
|
|
17
|
+
* Columns whose minor-unit scale is a property of the **row's** asset, not of
|
|
18
|
+
* the deployment — so no single `scale` converts them and they are excluded
|
|
19
|
+
* from {@link migrateCommerceMoneyToMinorUnits}.
|
|
20
|
+
*
|
|
21
|
+
* `payments.native_amount` holds "the amount the backend actually moved, in the
|
|
22
|
+
* native currency's own minor units": satoshis for `BTC` (×1e8), cents for
|
|
23
|
+
* `USDC-base` or `USD-stripe` (×1e2). A blanket ×100 would store 1 satoshi-ish
|
|
24
|
+
* nonsense for a 0.00713 BTC payment whose correct value is 713 000 sats, and
|
|
25
|
+
* a round amount like 0.01 BTC would even pass the preflight's integrality
|
|
26
|
+
* check while being wrong by six orders of magnitude.
|
|
27
|
+
*
|
|
28
|
+
* Convert it in two deliberate steps, from one deploy process, while the column
|
|
29
|
+
* is still floating-point:
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* // 1. Normalise each row to its own asset's minor units, in the REAL column.
|
|
33
|
+
* for (const [currency, scale] of Object.entries({ BTC: 1e8, 'USDC-base': 100 })) {
|
|
34
|
+
* await db.query(
|
|
35
|
+
* 'UPDATE payments SET native_amount = round(native_amount * ?) WHERE native_currency = ?',
|
|
36
|
+
* scale,
|
|
37
|
+
* currency,
|
|
38
|
+
* );
|
|
39
|
+
* }
|
|
40
|
+
*
|
|
41
|
+
* // 2. Change the column type with no further scaling.
|
|
42
|
+
* await rescaleMoneyColumnsToMinorUnits(db, COMMERCE_NATIVE_UNIT_COLUMNS, {
|
|
43
|
+
* scale: 1,
|
|
44
|
+
* backfillName: '<your-app>:payments-native-amount-minor-units:v1',
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* Step 1 is deliberately yours to write: only the deployment knows which
|
|
49
|
+
* `native_currency` values it has used and what each one's exponent is.
|
|
50
|
+
*/
|
|
51
|
+
export declare const COMMERCE_NATIVE_UNIT_COLUMNS: MoneyColumnTarget[];
|
|
52
|
+
/**
|
|
53
|
+
* Report what {@link migrateCommerceMoneyToMinorUnits} would do, without
|
|
54
|
+
* writing anything.
|
|
55
|
+
*
|
|
56
|
+
* @param db - Root database handle.
|
|
57
|
+
* @param options - `scale` (default 100) and `engineHint`.
|
|
58
|
+
* @returns Per-column state plus the rows that would lose information.
|
|
59
|
+
*/
|
|
60
|
+
export declare function preflightCommerceMoneyMinorUnits(db: DatabaseInterface, options?: {
|
|
61
|
+
scale?: number;
|
|
62
|
+
engineHint?: string;
|
|
63
|
+
}): Promise<MinorUnitsPreflightResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Convert every single-scale commerce money column from floating-point major
|
|
66
|
+
* units to integer minor units.
|
|
67
|
+
*
|
|
68
|
+
* Idempotent: guarded by a `_smrt_backfills` marker, so re-running can never
|
|
69
|
+
* multiply a table by the scale twice.
|
|
70
|
+
*
|
|
71
|
+
* Does **not** touch `payments.native_amount` or the `paymentOptions` JSON —
|
|
72
|
+
* see this module's header and {@link COMMERCE_NATIVE_UNIT_COLUMNS}.
|
|
73
|
+
*
|
|
74
|
+
* @param db - Root database handle.
|
|
75
|
+
* @param options - `scale` (default 100 — cents), `engineHint`, and `force` to
|
|
76
|
+
* convert despite rows the preflight flagged as lossy.
|
|
77
|
+
* @throws `MinorUnitsPreflightError` when a row would be rounded or would
|
|
78
|
+
* overflow `int4` and `force` was not set. Print
|
|
79
|
+
* {@link preflightCommerceMoneyMinorUnits}'s summary, fix the data, retry.
|
|
80
|
+
*/
|
|
81
|
+
export declare function migrateCommerceMoneyToMinorUnits(db: DatabaseInterface, options?: {
|
|
82
|
+
scale?: number;
|
|
83
|
+
engineHint?: string;
|
|
84
|
+
force?: boolean;
|
|
85
|
+
}): Promise<MinorUnitsRescaleResult>;
|
|
86
|
+
//# sourceMappingURL=moneyMinorUnits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moneyMinorUnits.d.ts","sourceRoot":"","sources":["../../src/migrations/moneyMinorUnits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EAGvB,MAAM,qCAAqC,CAAC;AAE7C,4EAA4E;AAC5E,eAAO,MAAM,mCAAmC,sDACK,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBAAiB,EAiBrD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,4BAA4B,EAAE,iBAAiB,EAE3D,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,EAAE,EAAE,iBAAiB,EACrB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,OAAO,CAAC,yBAAyB,CAAC,CAEpC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gCAAgC,CAC9C,EAAE,EAAE,iBAAiB,EACrB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GACrE,OAAO,CAAC,uBAAuB,CAAC,CAMlC"}
|
|
@@ -16,7 +16,7 @@ import { ContractOptions, ContractStatus, ContractType, LicenseSaleOptions } fro
|
|
|
16
16
|
* const order = await contracts.create({
|
|
17
17
|
* _meta_type: 'Order',
|
|
18
18
|
* customerId: customer.id,
|
|
19
|
-
* totalAmount:
|
|
19
|
+
* totalAmount: 150000, // $1,500.00 in cents
|
|
20
20
|
* status: ContractStatus.DRAFT
|
|
21
21
|
* });
|
|
22
22
|
*
|
|
@@ -24,7 +24,7 @@ import { ContractOptions, ContractStatus, ContractType, LicenseSaleOptions } fro
|
|
|
24
24
|
* const po = await contracts.create({
|
|
25
25
|
* _meta_type: 'PurchaseOrder',
|
|
26
26
|
* vendorId: vendor.id,
|
|
27
|
-
* totalAmount:
|
|
27
|
+
* totalAmount: 500000, // $5,000.00 in cents
|
|
28
28
|
* reference: 'PO-2024-001'
|
|
29
29
|
* });
|
|
30
30
|
* ```
|
|
@@ -52,15 +52,20 @@ export declare class Contract extends SmrtObject {
|
|
|
52
52
|
*/
|
|
53
53
|
vendorId: string;
|
|
54
54
|
/**
|
|
55
|
-
* Subtotal before tax
|
|
55
|
+
* Subtotal before tax, in **integer minor units** (cents, satoshis).
|
|
56
|
+
*
|
|
57
|
+
* The `= 0` initializer is load-bearing: SMRT maps an integer literal to
|
|
58
|
+
* INTEGER and a decimal literal to DECIMAL. Money is exact, so it is stored
|
|
59
|
+
* as minor units and never as a float — `$19.99` is `1999`, not `19.99`
|
|
60
|
+
* (#2401).
|
|
56
61
|
*/
|
|
57
62
|
subtotal: number;
|
|
58
63
|
/**
|
|
59
|
-
* Tax amount
|
|
64
|
+
* Tax amount, in integer minor units (#2401).
|
|
60
65
|
*/
|
|
61
66
|
taxAmount: number;
|
|
62
67
|
/**
|
|
63
|
-
* Total amount including tax
|
|
68
|
+
* Total amount including tax, in integer minor units (#2401).
|
|
64
69
|
*/
|
|
65
70
|
totalAmount: number;
|
|
66
71
|
/**
|
|
@@ -136,10 +141,15 @@ export declare class Contract extends SmrtObject {
|
|
|
136
141
|
*/
|
|
137
142
|
initialize(): Promise<this>;
|
|
138
143
|
/**
|
|
139
|
-
* Validate the status transition before persisting, then
|
|
140
|
-
* every STI subtype (Estimate/Order/Lease/.../LicenseSale),
|
|
141
|
-
* `status` on any of them is caught here. LicenseSale layers its
|
|
142
|
-
* rights-immutability guard on top via `super.save()`. See S5 audit
|
|
144
|
+
* Validate the amounts and the status transition before persisting, then
|
|
145
|
+
* save. Inherited by every STI subtype (Estimate/Order/Lease/.../LicenseSale),
|
|
146
|
+
* so a forged `status` on any of them is caught here. LicenseSale layers its
|
|
147
|
+
* own rights-immutability guard on top via `super.save()`. See S5 audit
|
|
148
|
+
* #1390.
|
|
149
|
+
*
|
|
150
|
+
* `subtotal` / `taxAmount` / `totalAmount` are mass-assignable on the
|
|
151
|
+
* generated create/update routes, so the minor-units check runs on every
|
|
152
|
+
* write surface (#2401).
|
|
143
153
|
*/
|
|
144
154
|
save(): Promise<this>;
|
|
145
155
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Contract.d.ts","sourceRoot":"","sources":["../../src/models/Contract.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,KAAK,IAAI,EACT,UAAU,EAEX,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"Contract.d.ts","sourceRoot":"","sources":["../../src/models/Contract.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,KAAK,IAAI,EACT,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,KAAK,eAAe,EACpB,cAAc,EACd,YAAY,EACZ,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AA2C3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAOa,QAAS,SAAQ,UAAU;IACtC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IACH,YAAY,EAAE,YAAY,CAAsB;IAEhD;;OAEG;IACH,MAAM,EAAE,cAAc,CAAwB;IAE9C;;OAEG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IAEH,QAAQ,EAAE,MAAM,CAAM;IAEtB;;;;;;;OAOG;IACH,QAAQ,EAAE,MAAM,CAAK;IAErB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAK;IAEtB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAK;IAExB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAS;IAEzB;;OAEG;IACH,SAAS,EAAE,IAAI,CAAc;IAE7B;;OAEG;IACH,OAAO,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE5B;;OAEG;IACH,UAAU,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;IAEnB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;IAEnB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,kBAAkB;gBAE/B,OAAO,GAAE,eAAoB;IAsBzC;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,SAAS,IAAI,OAAO;IAKpB;;OAEG;IACH,SAAS,IAAI,OAAO;IAMpB;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxC;;;;;OAKG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;;;;;;;;OAUG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAapC;;;OAGG;IACH,SAAS,CAAC,8BAA8B,CACtC,KAAK,EAAE,cAAc,GAAG,SAAS,GAChC,IAAI;IAYP;;;;;;;;;;;;;;;OAeG;cACa,kBAAkB,IAAI,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;CAa1E;AAWD;;GAEG;AACH,qBAEa,QAAS,SAAQ,QAAQ;IAC3B,YAAY,eAAyB;CAC/C;AAED;;GAEG;AACH,qBAEa,KAAM,SAAQ,QAAQ;IACxB,YAAY,eAAsB;CAC5C;AAED;;GAEG;AACH,qBAEa,KAAM,SAAQ,QAAQ;IACxB,YAAY,eAAsB;CAC5C;AAED;;GAEG;AACH,qBAEa,SAAU,SAAQ,QAAQ;IAC5B,YAAY,eAA0B;CAChD;AAED;;GAEG;AACH,qBAEa,aAAc,SAAQ,QAAQ;IAChC,YAAY,eAA+B;CACrD;AAED;;;;;;GAMG;AACH,qBAEa,cAAe,SAAQ,QAAQ;IACjC,YAAY,eAAgC;CACtD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAEa,eAAgB,SAAQ,QAAQ;IAClC,YAAY,eAAiC;IAEtD;;;;OAIG;IACH,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAE7B;;;;;OAKG;IACH,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;CAC1B;AAED;;;;;;;;;;;;;GAaG;AACH,qBAEa,IAAK,SAAQ,QAAQ;IACvB,YAAY,eAAqB;CAC3C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB;AAeD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAEa,WAAY,SAAQ,QAAQ;IAC9B,YAAY,eAA6B;IAElD;;;;OAIG;IACH,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAEzB;;;;OAIG;IACH,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAE7B;;;;;OAKG;IACH,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAEjC;;;;OAIG;IACH,mBAAmB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAEvC;;;;OAIG;IACH,oBAAoB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAIxC,8DAA8D;IAC9D,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAEhC,uEAAuE;IACvE,uBAAuB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAE3C,oEAAoE;IACpE,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAErC,gEAAgE;IAChE,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAElC,gEAAgE;IAChE,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAEnC,sDAAsD;IACtD,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAS;IAE1C,wDAAwD;IACxD,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAS;IAIzC,oEAAoE;IACpE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAE1B;;;;OAIG;IACH,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;IAE3B;;;;;;OAMG;IACH,sBAAsB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAM;gBAE9B,OAAO,GAAE,kBAAuB;IA8B5C;;;;;;OAMG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;;;OAKG;IACH,iBAAiB,IAAI,qBAAqB;IAY1C;;;;;OAKG;IACH,MAAM,IAAI,IAAI;IASd;;;;;;;;;;;OAWG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcpC;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,uBAAuB;CAahC;AAED,eAAe,QAAQ,CAAC"}
|
|
@@ -12,7 +12,7 @@ import { ContractLineItemOptions } from '../types/index.js';
|
|
|
12
12
|
* contractId: order.id,
|
|
13
13
|
* description: 'Widget Pro',
|
|
14
14
|
* quantity: 10,
|
|
15
|
-
* unitPrice: 49.99
|
|
15
|
+
* unitPrice: 4999, // $49.99 in cents
|
|
16
16
|
* taxRate: 0.08
|
|
17
17
|
* });
|
|
18
18
|
* ```
|
|
@@ -32,23 +32,31 @@ export declare class ContractLineItem extends SmrtObject {
|
|
|
32
32
|
*/
|
|
33
33
|
description: string;
|
|
34
34
|
/**
|
|
35
|
-
* Quantity ordered
|
|
35
|
+
* Quantity ordered. Decimal on purpose — contracts price fractional
|
|
36
|
+
* quantities (hours, weight, bandwidth), unlike `InvoiceLineItem.quantity`.
|
|
36
37
|
*/
|
|
37
38
|
quantity: number;
|
|
38
39
|
/**
|
|
39
|
-
* Unit price before discount
|
|
40
|
+
* Unit price before discount, in **integer minor units** (cents, satoshis).
|
|
41
|
+
*
|
|
42
|
+
* The `= 0` initializer is load-bearing: SMRT maps an integer literal to
|
|
43
|
+
* INTEGER and a decimal literal to DECIMAL. Money is exact, so `$49.99` is
|
|
44
|
+
* `4999` (#2401).
|
|
40
45
|
*/
|
|
41
46
|
unitPrice: number;
|
|
42
47
|
/**
|
|
43
|
-
* Discount amount (flat, not percentage)
|
|
48
|
+
* Discount amount (flat, not percentage), in integer minor units (#2401).
|
|
44
49
|
*/
|
|
45
50
|
discount: number;
|
|
46
51
|
/**
|
|
47
|
-
* Tax rate as decimal (e.g., 0.08 for 8%)
|
|
52
|
+
* Tax rate as decimal (e.g., 0.08 for 8%). A rate is inherently fractional,
|
|
53
|
+
* so it stays DECIMAL — INTEGER would truncate every meaningful value.
|
|
48
54
|
*/
|
|
49
55
|
taxRate: number;
|
|
50
56
|
/**
|
|
51
|
-
* Calculated line amount (qty * price - discount + tax)
|
|
57
|
+
* Calculated line amount (qty * price - discount + tax), in integer minor
|
|
58
|
+
* units. Derived by {@link ContractLineItem.calculateAmount}, which rounds
|
|
59
|
+
* the fractional tax to a whole minor unit (#2401).
|
|
52
60
|
*/
|
|
53
61
|
amount: number;
|
|
54
62
|
/**
|
|
@@ -77,7 +85,13 @@ export declare class ContractLineItem extends SmrtObject {
|
|
|
77
85
|
sortOrder: number;
|
|
78
86
|
constructor(options?: ContractLineItemOptions);
|
|
79
87
|
/**
|
|
80
|
-
* Calculate the line amount
|
|
88
|
+
* Calculate the line amount, in integer minor units.
|
|
89
|
+
*
|
|
90
|
+
* `quantity` is decimal and `taxRate` is a fraction, so the product is not
|
|
91
|
+
* generally a whole number of minor units. Rounding happens here — at the
|
|
92
|
+
* one boundary where a rate meets money — so that every value that reaches a
|
|
93
|
+
* money column is already exact and every downstream comparison can be a
|
|
94
|
+
* plain `===` instead of an epsilon tolerance (#2401).
|
|
81
95
|
*/
|
|
82
96
|
calculateAmount(): number;
|
|
83
97
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContractLineItem.d.ts","sourceRoot":"","sources":["../../src/models/ContractLineItem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAEjE;;;;;;;;;;;;;;;;GAgBG;AACH,qBAOa,gBAAiB,SAAQ,UAAU;IAC9C;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB
|
|
1
|
+
{"version":3,"file":"ContractLineItem.d.ts","sourceRoot":"","sources":["../../src/models/ContractLineItem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAEjE;;;;;;;;;;;;;;;;GAgBG;AACH,qBAOa,gBAAiB,SAAQ,UAAU;IAC9C;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAO;IAEvB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAK;IAEtB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAK;IAErB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAO;IAEtB;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAK;IAEnB;;OAEG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAM;IAEjB;;OAEG;IACH,SAAS,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE9B;;OAEG;IACH,OAAO,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE5B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAM;IAE3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAK;gBAEV,OAAO,GAAE,uBAA4B;IAoBjD;;;;;;;;OAQG;IACH,eAAe,IAAI,MAAM;IAMzB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,oBAAoB,IAAI,OAAO;CAUhC;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -27,7 +27,13 @@ export declare class Customer extends SmrtObject {
|
|
|
27
27
|
*/
|
|
28
28
|
profileId: string;
|
|
29
29
|
/**
|
|
30
|
-
* Maximum credit extended to this customer
|
|
30
|
+
* Maximum credit extended to this customer, in **integer minor units**
|
|
31
|
+
* (cents, satoshis).
|
|
32
|
+
*
|
|
33
|
+
* Converts with the rest of commerce because
|
|
34
|
+
* {@link Customer.hasAvailableCredit} compares it directly against a money
|
|
35
|
+
* amount; a dollars-vs-cents split there would approve every request off by
|
|
36
|
+
* a factor of 100 (#2401).
|
|
31
37
|
*/
|
|
32
38
|
creditLimit: number;
|
|
33
39
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Customer.d.ts","sourceRoot":"","sources":["../../src/models/Customer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;GAcG;AACH,qBAMa,QAAS,SAAQ,UAAU;IACtC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;OAGG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB
|
|
1
|
+
{"version":3,"file":"Customer.d.ts","sourceRoot":"","sources":["../../src/models/Customer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,cAAc,EACd,YAAY,EACb,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;GAcG;AACH,qBAMa,QAAS,SAAQ,UAAU;IACtC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;OAGG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;;;;;;;OAQG;IACH,WAAW,EAAE,MAAM,CAAK;IAExB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAM;IAE1B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAS;IAE3B;;;;;OAKG;IAEH,KAAK,EAAE,MAAM,CAAM;IAEnB;;OAEG;IACH,sBAAsB,EAAE,OAAO,CAAM;IAErC;;OAEG;IACH,qBAAqB,EAAE,OAAO,CAAM;IAEpC;;OAEG;IACH,MAAM,EAAE,cAAc,CAAyB;IAE/C;;;;;OAKG;IACH,YAAY,EAAE,YAAY,CAAoB;IAE9C;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;gBAEP,OAAO,GAAE,eAAoB;IA4BzC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAK3C;;;;;;;;;;OAUG;IACH,YAAY,IAAI,MAAM;CAGvB;AAED,eAAe,QAAQ,CAAC"}
|
package/dist/models/Invoice.d.ts
CHANGED
|
@@ -69,19 +69,25 @@ export declare class Invoice extends SmrtObject {
|
|
|
69
69
|
*/
|
|
70
70
|
paidDate: Date | null;
|
|
71
71
|
/**
|
|
72
|
-
* Subtotal before tax
|
|
72
|
+
* Subtotal before tax, in **integer minor units** (cents, satoshis).
|
|
73
|
+
*
|
|
74
|
+
* The `= 0` initializer is load-bearing: SMRT maps an integer literal to
|
|
75
|
+
* INTEGER and a decimal literal to DECIMAL. Money is exact, so it is stored
|
|
76
|
+
* as minor units and never as a float — `$19.99` is `1999`, not `19.99`.
|
|
77
|
+
* Writing a fractional major-unit value here is the bug; PostgreSQL rejects
|
|
78
|
+
* it with `22P02` while SQLite's affinity silently stores it (#2361).
|
|
73
79
|
*/
|
|
74
80
|
subtotal: number;
|
|
75
81
|
/**
|
|
76
|
-
* Tax amount
|
|
82
|
+
* Tax amount, in integer minor units (#2361).
|
|
77
83
|
*/
|
|
78
84
|
taxAmount: number;
|
|
79
85
|
/**
|
|
80
|
-
* Total amount due (subtotal + tax)
|
|
86
|
+
* Total amount due (subtotal + tax), in integer minor units (#2361).
|
|
81
87
|
*/
|
|
82
88
|
totalAmount: number;
|
|
83
89
|
/**
|
|
84
|
-
* Amount paid (sum of PaymentAllocations)
|
|
90
|
+
* Amount paid (sum of PaymentAllocations), in integer minor units (#2361).
|
|
85
91
|
*/
|
|
86
92
|
amountPaid: number;
|
|
87
93
|
/**
|
|
@@ -169,8 +175,12 @@ export declare class Invoice extends SmrtObject {
|
|
|
169
175
|
* `totalAmount === subtotal + taxAmount` arithmetic invariant is enforced.
|
|
170
176
|
* - **amountPaid is derived/validated.** When persisted, it is recomputed
|
|
171
177
|
* from PaymentAllocations rather than trusted from the caller. It may
|
|
172
|
-
* never exceed `totalAmount
|
|
173
|
-
* - **
|
|
178
|
+
* never exceed `totalAmount`.
|
|
179
|
+
* - **Whole minor units and non-negativity** are enforced on all four
|
|
180
|
+
* amounts. The integer check runs FIRST (#2401), before the
|
|
181
|
+
* `totalAmount === subtotal + taxAmount` invariant, so a caller who wrote
|
|
182
|
+
* major units gets "money is minor units" rather than a confusing
|
|
183
|
+
* arithmetic-mismatch error from float addition.
|
|
174
184
|
* - **Status transitions** are validated against the prior persisted status.
|
|
175
185
|
*/
|
|
176
186
|
save(): Promise<this>;
|
|
@@ -192,23 +202,21 @@ export declare class Invoice extends SmrtObject {
|
|
|
192
202
|
*/
|
|
193
203
|
private recomputeAmountsForSave;
|
|
194
204
|
/**
|
|
195
|
-
* Whether `amountPaid` covers `totalAmount
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* from the epsilon-tolerant guard: a float-summed total paid exactly (e.g.
|
|
202
|
-
* `0.1 × 3` line items paid `0.3`) reads as "not covered" by `>=` but
|
|
203
|
-
* "covered" by the guard, so `updatePaymentStatus` would set PARTIAL and the
|
|
204
|
-
* save-time guard would then reject it — leaving a genuinely-paid invoice
|
|
205
|
-
* unsaveable (S5 audit #1390 follow-up).
|
|
205
|
+
* Whether `amountPaid` covers `totalAmount`. This is the SINGLE source of
|
|
206
|
+
* truth for the **PAID** decision — both {@link updatePaymentStatus} (which
|
|
207
|
+
* decides PAID) and {@link assertPaymentStatusConsistent} (which validates
|
|
208
|
+
* PAID on save) call it, so the PAID-deciding comparison and the
|
|
209
|
+
* PAID-validating comparison can never drift apart (S5 audit #1390
|
|
210
|
+
* follow-up).
|
|
206
211
|
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
+
* With integer minor units this is a plain `>=` (#2401). The float-era
|
|
213
|
+
* hazard it used to guard against — a total summed from `0.1 × 3` line items
|
|
214
|
+
* reading as "not covered" by `>=` but "covered" by an epsilon-tolerant
|
|
215
|
+
* guard, leaving a genuinely-paid invoice unsaveable — cannot arise when both
|
|
216
|
+
* sides are exact integers. That also removes the documented PAID/PARTIAL
|
|
217
|
+
* asymmetry: {@link updatePaymentStatus} and {@link isPartiallyPaid} now
|
|
218
|
+
* agree that any `amountPaid > 0` is a partial payment, because there is no
|
|
219
|
+
* such thing as sub-cent dust.
|
|
212
220
|
*/
|
|
213
221
|
private isFullyPaid;
|
|
214
222
|
/**
|
|
@@ -231,26 +239,24 @@ export declare class Invoice extends SmrtObject {
|
|
|
231
239
|
*/
|
|
232
240
|
private assertPaymentStatusConsistent;
|
|
233
241
|
/**
|
|
234
|
-
* Enforce `totalAmount === subtotal + taxAmount`
|
|
235
|
-
*
|
|
236
|
-
* no line items to recompute from.
|
|
242
|
+
* Enforce `totalAmount === subtotal + taxAmount` exactly. Used when the
|
|
243
|
+
* invoice has no line items to recompute from.
|
|
237
244
|
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
* `subtotal + taxAmount` here (after the tolerance check) means the persisted
|
|
246
|
-
* total and every journal built from it are always ledger-consistent.
|
|
245
|
+
* Exact because every term is integer minor units (#2401). The float era
|
|
246
|
+
* needed a `0.01` tolerance here and then had to SNAP `totalAmount` to the
|
|
247
|
+
* recomputed value afterwards, because a total that passed the invoice's
|
|
248
|
+
* loose tolerance could still fail smrt-ledgers' tighter `BALANCE_EPSILON`
|
|
249
|
+
* and void the journal `recognizeRevenue` builds from it. Integer arithmetic
|
|
250
|
+
* removes both halves of that workaround: what the caller supplied either is
|
|
251
|
+
* the sum or is rejected, and any journal built from it balances exactly.
|
|
247
252
|
*/
|
|
248
253
|
private assertTotalArithmetic;
|
|
249
254
|
/**
|
|
250
|
-
* Reject
|
|
251
|
-
*
|
|
252
|
-
* letting amountPaid float above the invoice total).
|
|
255
|
+
* Reject amounts that are not whole minor units, negative financial values,
|
|
256
|
+
* and an amountPaid that exceeds the total (overpayment is modelled
|
|
257
|
+
* elsewhere, not by letting amountPaid float above the invoice total).
|
|
253
258
|
*/
|
|
259
|
+
private assertAmountsAreMinorUnits;
|
|
254
260
|
private assertNonNegativeAmounts;
|
|
255
261
|
/**
|
|
256
262
|
* Reject an illegal status flip done via raw field assignment. Compares the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Invoice.d.ts","sourceRoot":"","sources":["../../src/models/Invoice.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,OAAO,EAAoB,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"Invoice.d.ts","sourceRoot":"","sources":["../../src/models/Invoice.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ import { AccountingLineItemInput, InvoiceLineItemOptions } from '../types/index.
|
|
|
12
12
|
* invoiceId: invoice.id,
|
|
13
13
|
* description: 'Display Advertising - Summer Campaign',
|
|
14
14
|
* quantity: 50000, // impressions
|
|
15
|
-
* unitPrice:
|
|
15
|
+
* unitPrice: 1, // 1 cent per impression (minor units)
|
|
16
16
|
* taxRate: 0.05,
|
|
17
17
|
* sourceType: 'campaign',
|
|
18
18
|
* sourceId: 'campaign-uuid',
|
|
@@ -40,23 +40,37 @@ export declare class InvoiceLineItem extends SmrtObject {
|
|
|
40
40
|
*/
|
|
41
41
|
sku: string;
|
|
42
42
|
/**
|
|
43
|
-
* Quantity (e.g., impressions, hours, units)
|
|
43
|
+
* Quantity (e.g., impressions, hours, units).
|
|
44
|
+
*
|
|
45
|
+
* Left INTEGER: this package's own example is `quantity: 50000` impressions,
|
|
46
|
+
* and nothing in it writes a fractional quantity, so whether fractional
|
|
47
|
+
* quantities are intended here is unresolved. `ContractLineItem.quantity` is
|
|
48
|
+
* decimal, which is the inconsistency to settle deliberately rather than by
|
|
49
|
+
* changing a column type in passing (#2361).
|
|
44
50
|
*/
|
|
45
51
|
quantity: number;
|
|
46
52
|
/**
|
|
47
|
-
* Unit price before discount
|
|
53
|
+
* Unit price before discount, in **integer minor units** (cents, satoshis).
|
|
54
|
+
*
|
|
55
|
+
* Money is exact, so it is stored as minor units and never as a float —
|
|
56
|
+
* `$19.99` is `1999`. An integer literal is what maps this to an INTEGER
|
|
57
|
+
* column (#2361).
|
|
48
58
|
*/
|
|
49
59
|
unitPrice: number;
|
|
50
60
|
/**
|
|
51
|
-
* Discount amount (flat, not percentage)
|
|
61
|
+
* Discount amount (flat, not percentage), in integer minor units (#2361).
|
|
52
62
|
*/
|
|
53
63
|
discount: number;
|
|
54
64
|
/**
|
|
55
|
-
* Tax rate as decimal (e.g., 0.05 for 5%)
|
|
65
|
+
* Tax rate as a decimal fraction (e.g., 0.05 for 5%).
|
|
66
|
+
*
|
|
67
|
+
* A genuine rate, not money: it is inherently fractional, so the `0.0`
|
|
68
|
+
* initializer is load-bearing and maps it to a DECIMAL column. INTEGER would
|
|
69
|
+
* truncate every rate to 0 (#2361).
|
|
56
70
|
*/
|
|
57
71
|
taxRate: number;
|
|
58
72
|
/**
|
|
59
|
-
* Calculated line amount
|
|
73
|
+
* Calculated line amount, in integer minor units (#2361).
|
|
60
74
|
*/
|
|
61
75
|
amount: number;
|
|
62
76
|
/**
|
|
@@ -86,9 +100,10 @@ export declare class InvoiceLineItem extends SmrtObject {
|
|
|
86
100
|
sortOrder: number;
|
|
87
101
|
constructor(options?: InvoiceLineItemOptions);
|
|
88
102
|
/**
|
|
89
|
-
* Calculate the line amount.
|
|
103
|
+
* Calculate the line amount, in integer minor units.
|
|
90
104
|
*
|
|
91
|
-
* Formula: (
|
|
105
|
+
* Formula: `getSubtotal() + getTaxAmount()`, i.e.
|
|
106
|
+
* `(quantity * unitPrice - discount) * (1 + taxRate)` with the tax rounded.
|
|
92
107
|
*
|
|
93
108
|
* Tax is calculated on the discounted subtotal. This follows the common
|
|
94
109
|
* "discount before tax" approach used in most North American jurisdictions.
|
|
@@ -97,11 +112,20 @@ export declare class InvoiceLineItem extends SmrtObject {
|
|
|
97
112
|
*/
|
|
98
113
|
calculateAmount(): number;
|
|
99
114
|
/**
|
|
100
|
-
* Get subtotal (before tax)
|
|
115
|
+
* Get subtotal (before tax), in integer minor units.
|
|
116
|
+
*
|
|
117
|
+
* `quantity` is an integer and `unitPrice` / `discount` are integer minor
|
|
118
|
+
* units, so this is exact with no rounding.
|
|
101
119
|
*/
|
|
102
120
|
getSubtotal(): number;
|
|
103
121
|
/**
|
|
104
|
-
* Get tax amount
|
|
122
|
+
* Get tax amount, in integer minor units.
|
|
123
|
+
*
|
|
124
|
+
* `taxRate` is a genuine fraction, so this product is where a rate meets
|
|
125
|
+
* money and the only place rounding is needed. Rounding here — rather than
|
|
126
|
+
* letting a fractional tax leak into `Invoice.taxAmount` — is what lets the
|
|
127
|
+
* invoice's guards compare integers exactly instead of tolerating an epsilon
|
|
128
|
+
* (#2401).
|
|
105
129
|
*/
|
|
106
130
|
getTaxAmount(): number;
|
|
107
131
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvoiceLineItem.d.ts","sourceRoot":"","sources":["../../src/models/InvoiceLineItem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAMa,eAAgB,SAAQ,UAAU;IAC7C;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAM;IAEjB
|
|
1
|
+
{"version":3,"file":"InvoiceLineItem.d.ts","sourceRoot":"","sources":["../../src/models/InvoiceLineItem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAMa,eAAgB,SAAQ,UAAU;IAC7C;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAM;IAEjB;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,CAAK;IAErB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAK;IAEtB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAK;IAErB;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,CAAO;IAEtB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAK;IAMnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAM;IAEtB;;OAEG;IACH,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEhC;;OAEG;IACH,SAAS,EAAE,IAAI,GAAG,IAAI,CAAQ;IAM9B;;;OAGG;IAEH,gBAAgB,EAAE,MAAM,CAAM;IAE9B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAK;gBAEV,OAAO,GAAE,sBAA2B;IAsBhD;;;;;;;;;;OAUG;IACH,eAAe,IAAI,MAAM;IAIzB;;;;;OAKG;IACH,WAAW,IAAI,MAAM;IAIrB;;;;;;;;OAQG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,oBAAoB,IAAI,uBAAuB;CAahD;AAED,eAAe,eAAe,CAAC"}
|
package/dist/models/Payment.d.ts
CHANGED
|
@@ -41,7 +41,12 @@ export declare class Payment extends SmrtObject {
|
|
|
41
41
|
*/
|
|
42
42
|
customerId: string;
|
|
43
43
|
/**
|
|
44
|
-
* Payment amount
|
|
44
|
+
* Payment amount, in **integer minor units** (cents, satoshis).
|
|
45
|
+
*
|
|
46
|
+
* The `= 0` initializer is load-bearing: SMRT maps an integer literal to
|
|
47
|
+
* INTEGER and a decimal literal to DECIMAL. This is the figure
|
|
48
|
+
* `PaymentAllocation.save()` caps allocations against and `Invoice.amountPaid`
|
|
49
|
+
* is summed from, so it must be in the same exact units as both (#2401).
|
|
45
50
|
*/
|
|
46
51
|
amount: number;
|
|
47
52
|
/**
|
|
@@ -110,10 +115,15 @@ export declare class Payment extends SmrtObject {
|
|
|
110
115
|
*/
|
|
111
116
|
backendTxRef: string;
|
|
112
117
|
/**
|
|
113
|
-
* The amount the backend actually moved, in
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* recorded, independent of any
|
|
118
|
+
* The amount the backend actually moved, in the native currency's own
|
|
119
|
+
* **integer minor units** — satoshis for BTC, cents for a fiat rail. For
|
|
120
|
+
* stablecoin rails this typically equals `amount`; for volatile-currency
|
|
121
|
+
* rails it's the satoshi/wei figure the chain recorded, independent of any
|
|
122
|
+
* USD valuation.
|
|
123
|
+
*
|
|
124
|
+
* Range note (#2401): INTEGER is `int4` on PostgreSQL, so this column tops
|
|
125
|
+
* out near 2.1e9 minor units — about 21 BTC in satoshis. Widening to BIGINT
|
|
126
|
+
* is the decision parked in #2373; INTEGER→BIGINT is a plain widening later.
|
|
117
127
|
*/
|
|
118
128
|
nativeAmount: number;
|
|
119
129
|
/**
|
|
@@ -126,18 +136,22 @@ export declare class Payment extends SmrtObject {
|
|
|
126
136
|
nativeCurrency: string;
|
|
127
137
|
/**
|
|
128
138
|
* USD valuation of the payment at the moment the price was quoted to
|
|
129
|
-
* the buyer (typically the moment a `PaymentIntent` was issued)
|
|
130
|
-
*
|
|
139
|
+
* the buyer (typically the moment a `PaymentIntent` was issued), in
|
|
140
|
+
* **integer minor units** (US cents). A default of `0` means no USD-quote
|
|
131
141
|
* snapshot was taken (the payment was already USD-denominated or the
|
|
132
142
|
* backend doesn't require drift accounting).
|
|
143
|
+
*
|
|
144
|
+
* This is money describing the same funds as {@link Payment.amount}, so it
|
|
145
|
+
* converts with it — a dollars-here / cents-there split would make
|
|
146
|
+
* {@link Payment.usdDrift} meaningless (#2401).
|
|
133
147
|
*/
|
|
134
148
|
usdAtQuote: number;
|
|
135
149
|
/**
|
|
136
150
|
* USD valuation of the payment at the moment it was confirmed on the
|
|
137
|
-
* backend (chain confirmation, gateway settlement, etc.)
|
|
138
|
-
* between {@link usdAtQuote} and
|
|
139
|
-
* the operator absorbs (positive or
|
|
140
|
-
* in a volatile native currency.
|
|
151
|
+
* backend (chain confirmation, gateway settlement, etc.), in integer minor
|
|
152
|
+
* units (US cents). The delta between {@link usdAtQuote} and
|
|
153
|
+
* `usdAtConfirmation` is the USD drift the operator absorbs (positive or
|
|
154
|
+
* negative) when accepting payment in a volatile native currency (#2401).
|
|
141
155
|
*/
|
|
142
156
|
usdAtConfirmation: number;
|
|
143
157
|
constructor(options?: PaymentOptions);
|
|
@@ -239,6 +253,12 @@ export declare class Payment extends SmrtObject {
|
|
|
239
253
|
* - Debit: Cash/Bank account (assets increase)
|
|
240
254
|
* - Credit: Accounts Receivable (receivables decrease)
|
|
241
255
|
*
|
|
256
|
+
* Both sides carry `this.amount`, so the journal posted from commerce is
|
|
257
|
+
* denominated in **integer minor units** like the rest of this package
|
|
258
|
+
* (#2401). smrt-ledgers is unit-agnostic — its `BALANCE_EPSILON` only checks
|
|
259
|
+
* that debits equal credits — and integer entries balance exactly, so this is
|
|
260
|
+
* strictly tighter than the major-unit journals commerce used to post.
|
|
261
|
+
*
|
|
242
262
|
* @param options - Ledger and account configuration
|
|
243
263
|
* @returns The created journal
|
|
244
264
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Payment.d.ts","sourceRoot":"","sources":["../../src/models/Payment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"Payment.d.ts","sourceRoot":"","sources":["../../src/models/Payment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAG3D,OAAO,EACL,aAAa,EACb,KAAK,cAAc,EACnB,aAAa,EACb,KAAK,oBAAoB,EAC1B,MAAM,mBAAmB,CAAC;AA6C3B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBA8Ca,OAAQ,SAAQ,UAAU;IACrC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB;;;;;;;OAOG;IACH,MAAM,EAAE,MAAM,CAAK;IAEnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAS;IAEzB;;OAEG;IACH,MAAM,EAAE,aAAa,CAA+B;IAEpD;;OAEG;IACH,MAAM,EAAE,aAAa,CAAyB;IAE9C;;OAEG;IACH,aAAa,EAAE,MAAM,CAAM;IAE3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,MAAM,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE3B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;IAMnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAM;IAE9B;;OAEG;IACH,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAQ;IAiB7B;;;;;;;;;;OAUG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAM;IAE1B;;;;;;;;;;OAUG;IACH,YAAY,EAAE,MAAM,CAAK;IAEzB;;;;;;OAMG;IACH,cAAc,EAAE,MAAM,CAAM;IAE5B;;;;;;;;;;OAUG;IACH,UAAU,EAAE,MAAM,CAAK;IAEvB;;;;;;OAMG;IACH,iBAAiB,EAAE,MAAM,CAAK;gBAElB,OAAO,GAAE,cAAmB;IA+BxC;;;;;OAKG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA6DpC;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAY9B;;;;;;;;;;;;;;;OAeG;YACW,gBAAgB;IAa9B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,6BAA6B;IA0CrC;;;;;;OAMG;IACH,QAAQ,IAAI,MAAM;IAKlB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4DpE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAa3C;;OAEG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAOjC;;OAEG;IACH,MAAM,IAAI,IAAI;CAMf;AAED,eAAe,OAAO,CAAC"}
|
|
@@ -20,7 +20,7 @@ import { PaymentAllocationOptions } from '../types/index.js';
|
|
|
20
20
|
* // Get the collection
|
|
21
21
|
* const allocations = await PaymentAllocationCollection.create(options);
|
|
22
22
|
*
|
|
23
|
-
* // Check available funds before allocating
|
|
23
|
+
* // Check available funds before allocating (all amounts are minor units)
|
|
24
24
|
* const available = await allocations.getUnallocatedFromPayment(
|
|
25
25
|
* payment.id,
|
|
26
26
|
* payment.amount
|
|
@@ -56,7 +56,14 @@ export declare class PaymentAllocation extends SmrtObject {
|
|
|
56
56
|
*/
|
|
57
57
|
invoiceId: string;
|
|
58
58
|
/**
|
|
59
|
-
* Amount allocated from payment to invoice
|
|
59
|
+
* Amount allocated from payment to invoice, in **integer minor units**
|
|
60
|
+
* (cents, satoshis).
|
|
61
|
+
*
|
|
62
|
+
* Matches `Invoice.amountPaid` (derived by summing these rows) and
|
|
63
|
+
* `Payment.amount` (which `save()` caps against). All three converted
|
|
64
|
+
* together in #2401 — the cap is a subtraction across the pair, so a
|
|
65
|
+
* dollars-vs-cents split there would reject every allocation as
|
|
66
|
+
* over-applying.
|
|
60
67
|
*/
|
|
61
68
|
amount: number;
|
|
62
69
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentAllocation.d.ts","sourceRoot":"","sources":["../../src/models/PaymentAllocation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAc,UAAU,EAAQ,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"PaymentAllocation.d.ts","sourceRoot":"","sources":["../../src/models/PaymentAllocation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAc,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAGxE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAYlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAoBa,iBAAkB,SAAQ,UAAU;IAC/C;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;;;;;;;;OASG;IACH,MAAM,EAAE,MAAM,CAAK;IAEnB;;OAEG;IACH,WAAW,EAAE,IAAI,CAAc;IAE/B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;gBAEP,OAAO,GAAE,wBAA6B;IAalD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAqFrC;AAED,eAAe,iBAAiB,CAAC"}
|