@happyvertical/smrt-commerce 0.30.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 +44 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +146 -0
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/collections/ContractCollection.d.ts +87 -0
- package/dist/collections/ContractCollection.d.ts.map +1 -0
- package/dist/collections/CustomerCollection.d.ts +58 -0
- package/dist/collections/CustomerCollection.d.ts.map +1 -0
- package/dist/collections/FulfillmentCollection.d.ts +75 -0
- package/dist/collections/FulfillmentCollection.d.ts.map +1 -0
- package/dist/collections/InvoiceCollection.d.ts +162 -0
- package/dist/collections/InvoiceCollection.d.ts.map +1 -0
- package/dist/collections/InvoiceLineItemCollection.d.ts +90 -0
- package/dist/collections/InvoiceLineItemCollection.d.ts.map +1 -0
- package/dist/collections/PaymentAllocationCollection.d.ts +86 -0
- package/dist/collections/PaymentAllocationCollection.d.ts.map +1 -0
- package/dist/collections/PaymentCollection.d.ts +96 -0
- package/dist/collections/PaymentCollection.d.ts.map +1 -0
- package/dist/collections/PaymentIntentCollection.d.ts +66 -0
- package/dist/collections/PaymentIntentCollection.d.ts.map +1 -0
- package/dist/collections/PayoutCollection.d.ts +47 -0
- package/dist/collections/PayoutCollection.d.ts.map +1 -0
- package/dist/collections/VendorCollection.d.ts +59 -0
- package/dist/collections/VendorCollection.d.ts.map +1 -0
- package/dist/collections/index.d.ts +15 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5308 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +13852 -0
- package/dist/models/Contract.d.ts +425 -0
- package/dist/models/Contract.d.ts.map +1 -0
- package/dist/models/ContractLineItem.d.ts +92 -0
- package/dist/models/ContractLineItem.d.ts.map +1 -0
- package/dist/models/Customer.d.ts +98 -0
- package/dist/models/Customer.d.ts.map +1 -0
- package/dist/models/Fulfillment.d.ts +99 -0
- package/dist/models/Fulfillment.d.ts.map +1 -0
- package/dist/models/FulfillmentLineItem.d.ts +42 -0
- package/dist/models/FulfillmentLineItem.d.ts.map +1 -0
- package/dist/models/Invoice.d.ts +326 -0
- package/dist/models/Invoice.d.ts.map +1 -0
- package/dist/models/InvoiceLineItem.d.ts +120 -0
- package/dist/models/InvoiceLineItem.d.ts.map +1 -0
- package/dist/models/Payment.d.ts +269 -0
- package/dist/models/Payment.d.ts.map +1 -0
- package/dist/models/PaymentAllocation.d.ts +93 -0
- package/dist/models/PaymentAllocation.d.ts.map +1 -0
- package/dist/models/PaymentIntent.d.ts +341 -0
- package/dist/models/PaymentIntent.d.ts.map +1 -0
- package/dist/models/Payout.d.ts +200 -0
- package/dist/models/Payout.d.ts.map +1 -0
- package/dist/models/Vendor.d.ts +153 -0
- package/dist/models/Vendor.d.ts.map +1 -0
- package/dist/models/index.d.ts +17 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/playground.d.ts +2 -0
- package/dist/playground.d.ts.map +1 -0
- package/dist/playground.js +108 -0
- package/dist/playground.js.map +1 -0
- package/dist/smrt-knowledge.json +5494 -0
- package/dist/svelte/components/InvoiceActions.svelte +191 -0
- package/dist/svelte/components/InvoiceActions.svelte.d.ts +26 -0
- package/dist/svelte/components/InvoiceActions.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InvoiceCard.svelte +233 -0
- package/dist/svelte/components/InvoiceCard.svelte.d.ts +16 -0
- package/dist/svelte/components/InvoiceCard.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InvoiceHeader.svelte +258 -0
- package/dist/svelte/components/InvoiceHeader.svelte.d.ts +26 -0
- package/dist/svelte/components/InvoiceHeader.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InvoiceLineItems.svelte +322 -0
- package/dist/svelte/components/InvoiceLineItems.svelte.d.ts +24 -0
- package/dist/svelte/components/InvoiceLineItems.svelte.d.ts.map +1 -0
- package/dist/svelte/components/InvoiceTotals.svelte +193 -0
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts +27 -0
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts.map +1 -0
- package/dist/svelte/components/UnbilledItems.svelte +355 -0
- package/dist/svelte/components/UnbilledItems.svelte.d.ts +18 -0
- package/dist/svelte/components/UnbilledItems.svelte.d.ts.map +1 -0
- package/dist/svelte/i18n.d.ts +19 -0
- package/dist/svelte/i18n.d.ts.map +1 -0
- package/dist/svelte/i18n.js +19 -0
- package/dist/svelte/index.d.ts +40 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +43 -0
- package/dist/svelte/playground.d.ts +103 -0
- package/dist/svelte/playground.d.ts.map +1 -0
- package/dist/svelte/playground.js +103 -0
- package/dist/svelte/types.d.ts +47 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +4 -0
- package/dist/types/index.d.ts +234 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/ui.d.ts +10 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +85 -0
- package/dist/ui.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { PaymentMethod, PaymentStatus, RecordPaymentOptions } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Payment represents a financial transaction against a contract.
|
|
5
|
+
*
|
|
6
|
+
* Payments can be integrated with smrt-ledgers to automatically
|
|
7
|
+
* create balanced journal entries for proper accounting.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // Create a payment
|
|
12
|
+
* const payment = await payments.create({
|
|
13
|
+
* contractId: order.id,
|
|
14
|
+
* customerId: customer.id,
|
|
15
|
+
* amount: 1500.00,
|
|
16
|
+
* method: PaymentMethod.CREDIT_CARD,
|
|
17
|
+
* transactionId: 'stripe_pi_123456'
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Record with ledger integration
|
|
21
|
+
* await payment.recordPayment({
|
|
22
|
+
* ledgerId: ledger.id,
|
|
23
|
+
* receivablesAccountId: arAccount.id,
|
|
24
|
+
* cashAccountId: bankAccount.id
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare class Payment extends SmrtObject {
|
|
29
|
+
/**
|
|
30
|
+
* Tenant ID for multi-tenant isolation
|
|
31
|
+
* Nullable to support both tenant-scoped and global payments
|
|
32
|
+
*/
|
|
33
|
+
tenantId: string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Contract this payment is for
|
|
36
|
+
*/
|
|
37
|
+
contractId: string;
|
|
38
|
+
/**
|
|
39
|
+
* Customer who made the payment
|
|
40
|
+
*/
|
|
41
|
+
customerId: string;
|
|
42
|
+
/**
|
|
43
|
+
* Payment amount
|
|
44
|
+
*/
|
|
45
|
+
amount: number;
|
|
46
|
+
/**
|
|
47
|
+
* Currency code (ISO 4217)
|
|
48
|
+
*/
|
|
49
|
+
currency: string;
|
|
50
|
+
/**
|
|
51
|
+
* Payment method used
|
|
52
|
+
*/
|
|
53
|
+
method: PaymentMethod;
|
|
54
|
+
/**
|
|
55
|
+
* Current payment status
|
|
56
|
+
*/
|
|
57
|
+
status: PaymentStatus;
|
|
58
|
+
/**
|
|
59
|
+
* External transaction ID (from payment processor)
|
|
60
|
+
*/
|
|
61
|
+
transactionId: string;
|
|
62
|
+
/**
|
|
63
|
+
* Internal reference number
|
|
64
|
+
*/
|
|
65
|
+
reference: string;
|
|
66
|
+
/**
|
|
67
|
+
* Link to smrt-ledgers Journal (created by recordPayment)
|
|
68
|
+
*/
|
|
69
|
+
journalId: string;
|
|
70
|
+
/**
|
|
71
|
+
* When the payment was completed
|
|
72
|
+
*/
|
|
73
|
+
paidAt: Date | null;
|
|
74
|
+
/**
|
|
75
|
+
* Notes about the payment
|
|
76
|
+
*/
|
|
77
|
+
notes: string;
|
|
78
|
+
/**
|
|
79
|
+
* External ID in accounting provider (e.g., QBO payment ID)
|
|
80
|
+
*/
|
|
81
|
+
externalId: string;
|
|
82
|
+
/**
|
|
83
|
+
* Accounting provider name ('quickbooks' | 'stripe' | 'paypal' | etc.)
|
|
84
|
+
*/
|
|
85
|
+
externalProvider: string;
|
|
86
|
+
/**
|
|
87
|
+
* When payment was last synced to provider
|
|
88
|
+
*/
|
|
89
|
+
syncedAt: Date | null;
|
|
90
|
+
/**
|
|
91
|
+
* Stable identifier of the `PaymentBackend` adapter that served this
|
|
92
|
+
* payment — e.g. `base-usdc`, `solana-usdc`, `btc`, `stripe`, `paypal`.
|
|
93
|
+
*
|
|
94
|
+
* Distinct from {@link externalProvider}: `backendId` names the SMRT
|
|
95
|
+
* payment-rail adapter, while `externalProvider` names a downstream
|
|
96
|
+
* accounting destination (QuickBooks, Stripe-the-accounting-source).
|
|
97
|
+
* The same Stripe payment will have `backendId: 'stripe'` AND
|
|
98
|
+
* `externalProvider: 'stripe'`; a crypto payment synced to QBO will
|
|
99
|
+
* have `backendId: 'base-usdc'` and `externalProvider: 'quickbooks'`.
|
|
100
|
+
*/
|
|
101
|
+
backendId: string;
|
|
102
|
+
/**
|
|
103
|
+
* Chain transaction hash or backend aggregator's reference id. For
|
|
104
|
+
* on-chain payments this is the tx hash (`0x...` on EVM, base58 sig on
|
|
105
|
+
* Solana, txid on Bitcoin); for fiat-rail backends it's the gateway's
|
|
106
|
+
* own reference. Kept distinct from {@link transactionId} so consumers
|
|
107
|
+
* that already populate `transactionId` with a provider-internal id
|
|
108
|
+
* don't have to overload it.
|
|
109
|
+
*/
|
|
110
|
+
backendTxRef: string;
|
|
111
|
+
/**
|
|
112
|
+
* The amount the backend actually moved, in its own native currency.
|
|
113
|
+
* For stablecoin rails this typically equals `amount`; for volatile-
|
|
114
|
+
* currency rails (BTC, ETH) it's the satoshi/wei figure that the chain
|
|
115
|
+
* recorded, independent of any USD valuation.
|
|
116
|
+
*/
|
|
117
|
+
nativeAmount: number;
|
|
118
|
+
/**
|
|
119
|
+
* Code identifying the native currency `nativeAmount` is denominated
|
|
120
|
+
* in. Mirrors the `backendId` namespacing convention — `USDC-base`,
|
|
121
|
+
* `BTC`, `ETH`, `USD-stripe`. Empty string means "use {@link currency}"
|
|
122
|
+
* (i.e. the payment was already quoted and settled in the same
|
|
123
|
+
* currency).
|
|
124
|
+
*/
|
|
125
|
+
nativeCurrency: string;
|
|
126
|
+
/**
|
|
127
|
+
* USD valuation of the payment at the moment the price was quoted to
|
|
128
|
+
* the buyer (typically the moment a `PaymentIntent` was issued).
|
|
129
|
+
* Stored at decimal precision; empty default `0.0` means no USD-quote
|
|
130
|
+
* snapshot was taken (the payment was already USD-denominated or the
|
|
131
|
+
* backend doesn't require drift accounting).
|
|
132
|
+
*/
|
|
133
|
+
usdAtQuote: number;
|
|
134
|
+
/**
|
|
135
|
+
* USD valuation of the payment at the moment it was confirmed on the
|
|
136
|
+
* backend (chain confirmation, gateway settlement, etc.). The delta
|
|
137
|
+
* between {@link usdAtQuote} and `usdAtConfirmation` is the USD drift
|
|
138
|
+
* the operator absorbs (positive or negative) when accepting payment
|
|
139
|
+
* in a volatile native currency.
|
|
140
|
+
*/
|
|
141
|
+
usdAtConfirmation: number;
|
|
142
|
+
constructor(options?: any);
|
|
143
|
+
/**
|
|
144
|
+
* Capture the persisted status the row was loaded with, so the save-time
|
|
145
|
+
* transition guard can reject illegal status flips made via raw field
|
|
146
|
+
* assignment (mass-assignment on the generated update route, a stale caller,
|
|
147
|
+
* etc.). Freshly-constructed (not-yet-saved) payments have no prior status.
|
|
148
|
+
*/
|
|
149
|
+
initialize(): Promise<this>;
|
|
150
|
+
/**
|
|
151
|
+
* Save-time state-machine guard (S5 audit #1390).
|
|
152
|
+
*
|
|
153
|
+
* `status` is mass-assignable on the generated update/create routes, and a
|
|
154
|
+
* COMPLETED Payment is treated as settlement proof downstream — e.g.
|
|
155
|
+
* {@link PaymentIntent}'s PAID verification trusts a COMPLETED Payment row.
|
|
156
|
+
* A forged `status: 'completed'` (with arbitrary amounts and no journal)
|
|
157
|
+
* would therefore satisfy that check without any money having moved.
|
|
158
|
+
*
|
|
159
|
+
* This guard enforces two things:
|
|
160
|
+
* - **Transitions must be legal** per {@link PAYMENT_STATUS_TRANSITIONS}.
|
|
161
|
+
* - **Reaching COMPLETED requires the verified settlement path — on
|
|
162
|
+
* creation AND on update.** Only `recordPayment()` (which posts a
|
|
163
|
+
* balanced journal and links `journalId`) may write a Payment into
|
|
164
|
+
* COMPLETED; it announces itself via {@link settlementInProgress}. A raw
|
|
165
|
+
* `status: 'completed'` is rejected whether the row is brand-new (a
|
|
166
|
+
* GENESIS `create({ status: 'completed' })`) or already persisted — that
|
|
167
|
+
* is the exact path a forged COMPLETED would take to satisfy
|
|
168
|
+
* PaymentIntent's PAID verification without any money having moved (codex
|
|
169
|
+
* HIGH#1, #1390 round 5). There is deliberately NO import/fixture
|
|
170
|
+
* carve-out: a COMPLETED Payment is settlement proof downstream, so it is
|
|
171
|
+
* only ever reachable through `recordPayment()`, on every surface
|
|
172
|
+
* (REST/MCP/CLI/direct). Fixtures/migrations that need a completed payment
|
|
173
|
+
* must drive it through `recordPayment()` (or start non-COMPLETED).
|
|
174
|
+
*/
|
|
175
|
+
save(): Promise<this>;
|
|
176
|
+
/**
|
|
177
|
+
* Reject an illegal status flip. Compares the about-to-be-written status
|
|
178
|
+
* against the status the row was loaded with. No-op transitions (status
|
|
179
|
+
* unchanged) and brand-new rows (no prior) are always allowed — the
|
|
180
|
+
* COMPLETED-specific settlement requirement is enforced separately in
|
|
181
|
+
* {@link save}.
|
|
182
|
+
*/
|
|
183
|
+
private assertStatusTransition;
|
|
184
|
+
/**
|
|
185
|
+
* Load the AUTHORITATIVE persisted row (S5 audit #1390 round 4, codex HIGH#1;
|
|
186
|
+
* extended round 6 to carry the full row, not just `status`). The WeakMap is
|
|
187
|
+
* only populated when {@link initialize} loaded the row from the DB; it is
|
|
188
|
+
* empty for an instance built via
|
|
189
|
+
* `collection.create({ id: <existing>, _skipLoad: true })` — the upsert path
|
|
190
|
+
* that lets a caller write onto an existing row without hydrating it. Trusting
|
|
191
|
+
* an empty WeakMap there would treat the write as a brand-new row and skip the
|
|
192
|
+
* transition guard entirely (a poisonable prior-state).
|
|
193
|
+
*
|
|
194
|
+
* So when this instance carries an `id`, read the persisted row straight from
|
|
195
|
+
* the database and use it as the prior — a create-onto-existing is an update.
|
|
196
|
+
* Returns `undefined` when no row exists (truly new), so callers fall back to
|
|
197
|
+
* the WeakMap (which is also empty then). Settled-amount columns are
|
|
198
|
+
* snake_case (`native_amount`, etc.); the `status` column is single-word.
|
|
199
|
+
*/
|
|
200
|
+
private loadPersistedRow;
|
|
201
|
+
/**
|
|
202
|
+
* Reject any change to the settled monetary fields of an already-COMPLETED
|
|
203
|
+
* Payment (S5 audit #1390 round 6 — codex ROOT INSIGHT). Mirrors the
|
|
204
|
+
* PaymentIntent PAID backing-field freeze. A COMPLETED Payment's economic
|
|
205
|
+
* identity is settled: the `amount` was posted into a balanced journal and is
|
|
206
|
+
* the figure PaymentIntent's PAID verification reconciles against, so it (and
|
|
207
|
+
* the native/USD valuation fields that describe the same money) must not
|
|
208
|
+
* drift. The only legal status move out of COMPLETED is REFUNDED, which
|
|
209
|
+
* reverses the funds without rewriting how much they were. Compared against
|
|
210
|
+
* the AUTHORITATIVE persisted row so the freeze holds on every surface, even
|
|
211
|
+
* for an un-hydrated create-onto-existing upsert.
|
|
212
|
+
*/
|
|
213
|
+
private assertSettledAmountsUnchanged;
|
|
214
|
+
/**
|
|
215
|
+
* USD drift between quote time and confirmation time — what the
|
|
216
|
+
* operator gained (positive) or lost (negative) by accepting a
|
|
217
|
+
* volatile-currency payment. Returns `0` when either side of the
|
|
218
|
+
* comparison is missing or zero, so callers don't have to special-case
|
|
219
|
+
* fiat-rail / stablecoin payments.
|
|
220
|
+
*/
|
|
221
|
+
usdDrift(): number;
|
|
222
|
+
/**
|
|
223
|
+
* Check if payment is pending
|
|
224
|
+
*/
|
|
225
|
+
isPending(): boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Check if payment is completed
|
|
228
|
+
*/
|
|
229
|
+
isCompleted(): boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Check if payment is refunded
|
|
232
|
+
*/
|
|
233
|
+
isRefunded(): boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Record the payment and create a balanced journal entry.
|
|
236
|
+
*
|
|
237
|
+
* Creates a journal entry in smrt-ledgers:
|
|
238
|
+
* - Debit: Cash/Bank account (assets increase)
|
|
239
|
+
* - Credit: Accounts Receivable (receivables decrease)
|
|
240
|
+
*
|
|
241
|
+
* @param options - Ledger and account configuration
|
|
242
|
+
* @returns The created journal
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```typescript
|
|
246
|
+
* const journal = await payment.recordPayment({
|
|
247
|
+
* ledgerId: ledger.id,
|
|
248
|
+
* receivablesAccountId: arAccount.id,
|
|
249
|
+
* cashAccountId: bankAccount.id
|
|
250
|
+
* });
|
|
251
|
+
* console.log(`Created journal: ${journal.number}`);
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
recordPayment(options: RecordPaymentOptions): Promise<any>;
|
|
255
|
+
/**
|
|
256
|
+
* Get the linked journal entry (if recorded)
|
|
257
|
+
*/
|
|
258
|
+
getJournal(): Promise<any | null>;
|
|
259
|
+
/**
|
|
260
|
+
* Mark payment as failed
|
|
261
|
+
*/
|
|
262
|
+
markFailed(reason?: string): void;
|
|
263
|
+
/**
|
|
264
|
+
* Cancel the payment
|
|
265
|
+
*/
|
|
266
|
+
cancel(): void;
|
|
267
|
+
}
|
|
268
|
+
export default Payment;
|
|
269
|
+
//# sourceMappingURL=Payment.d.ts.map
|
|
@@ -0,0 +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;AAElC,OAAO,EACL,aAAa,EACb,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;;OAEG;IACH,MAAM,EAAE,MAAM,CAAO;IAErB;;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;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAO;IAE3B;;;;;;OAMG;IACH,cAAc,EAAE,MAAM,CAAM;IAE5B;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,CAAO;IAEzB;;;;;;OAMG;IACH,iBAAiB,EAAE,MAAM,CAAO;gBAEpB,OAAO,GAAE,GAAQ;IA+B7B;;;;;OAKG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDpC;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAY9B;;;;;;;;;;;;;;;OAeG;YACW,gBAAgB;IAW9B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,6BAA6B;IAwCrC;;;;;;OAMG;IACH,QAAQ,IAAI,MAAM;IAKlB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;;;;;;;;;;;;;;;;;;OAmBG;IACG,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,GAAG,CAAC;IAwDhE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAavC;;OAEG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAOjC;;OAEG;IACH,MAAM,IAAI,IAAI;CAMf;AAED,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
/**
|
|
3
|
+
* PaymentAllocation tracks how payments are applied to invoices.
|
|
4
|
+
*
|
|
5
|
+
* This enables:
|
|
6
|
+
* - Partial payments (one payment partially covering an invoice)
|
|
7
|
+
* - Split payments (one payment split across multiple invoices)
|
|
8
|
+
* - Payment history per invoice
|
|
9
|
+
*
|
|
10
|
+
* **Note**: This model does not automatically validate that allocations
|
|
11
|
+
* don't exceed the payment amount or invoice amount due. Use
|
|
12
|
+
* `PaymentAllocationCollection.getUnallocatedFromPayment()` before creating
|
|
13
|
+
* allocations to ensure sufficient funds are available.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { PaymentAllocationCollection } from '@happyvertical/smrt-commerce';
|
|
18
|
+
*
|
|
19
|
+
* // Get the collection
|
|
20
|
+
* const allocations = await PaymentAllocationCollection.create(options);
|
|
21
|
+
*
|
|
22
|
+
* // Check available funds before allocating
|
|
23
|
+
* const available = await allocations.getUnallocatedFromPayment(
|
|
24
|
+
* payment.id,
|
|
25
|
+
* payment.amount
|
|
26
|
+
* );
|
|
27
|
+
*
|
|
28
|
+
* if (available >= amountToAllocate) {
|
|
29
|
+
* const allocation = await allocations.create({
|
|
30
|
+
* paymentId: payment.id,
|
|
31
|
+
* invoiceId: invoice.id,
|
|
32
|
+
* amount: amountToAllocate,
|
|
33
|
+
* allocatedBy: 'user-uuid'
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // Update invoice payment status
|
|
37
|
+
* const totalAllocated = await allocations.getTotalAllocatedToInvoice(invoice.id);
|
|
38
|
+
* invoice.updatePaymentStatus(totalAllocated);
|
|
39
|
+
* await invoice.save();
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare class PaymentAllocation extends SmrtObject {
|
|
44
|
+
/**
|
|
45
|
+
* Tenant ID for multi-tenant isolation
|
|
46
|
+
* Nullable to support both tenant-scoped and global payment allocations
|
|
47
|
+
*/
|
|
48
|
+
tenantId: string | null;
|
|
49
|
+
/**
|
|
50
|
+
* Payment being allocated
|
|
51
|
+
*/
|
|
52
|
+
paymentId: string;
|
|
53
|
+
/**
|
|
54
|
+
* Invoice receiving the allocation
|
|
55
|
+
*/
|
|
56
|
+
invoiceId: string;
|
|
57
|
+
/**
|
|
58
|
+
* Amount allocated from payment to invoice
|
|
59
|
+
*/
|
|
60
|
+
amount: number;
|
|
61
|
+
/**
|
|
62
|
+
* When the allocation was made
|
|
63
|
+
*/
|
|
64
|
+
allocatedAt: Date;
|
|
65
|
+
/**
|
|
66
|
+
* User/agent who made the allocation
|
|
67
|
+
*/
|
|
68
|
+
allocatedBy: string;
|
|
69
|
+
/**
|
|
70
|
+
* Notes about the allocation
|
|
71
|
+
*/
|
|
72
|
+
notes: string;
|
|
73
|
+
constructor(options?: any);
|
|
74
|
+
/**
|
|
75
|
+
* Save-time integrity guard (S5 audit #1390):
|
|
76
|
+
* - allocation `amount` must be a finite, positive number, and
|
|
77
|
+
* - the sum of all allocations against the referenced Payment (this row
|
|
78
|
+
* included) must not exceed the Payment's amount — over-applying a
|
|
79
|
+
* payment across invoices would falsify both payment and invoice
|
|
80
|
+
* balances.
|
|
81
|
+
*
|
|
82
|
+
* The Payment-amount cap is enforced against the persisted Payment row. An
|
|
83
|
+
* allocation always carries a `@foreignKey('Payment')` paymentId, so a
|
|
84
|
+
* `paymentId` that doesn't resolve to a real Payment is a **hard error** (S5
|
|
85
|
+
* audit #1390 round 2): previously a missing Payment silently skipped the cap
|
|
86
|
+
* entirely, letting a caller over-apply (or fabricate) funds simply by
|
|
87
|
+
* pointing at a non-existent payment. An empty `paymentId` is still rejected
|
|
88
|
+
* by the underlying FK requirement; the positivity check always applies.
|
|
89
|
+
*/
|
|
90
|
+
save(): Promise<this>;
|
|
91
|
+
}
|
|
92
|
+
export default PaymentAllocation;
|
|
93
|
+
//# sourceMappingURL=PaymentAllocation.d.ts.map
|
|
@@ -0,0 +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;AASxE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;;OAEG;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,GAAQ;IAa7B;;;;;;;;;;;;;;;OAeG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CA0CrC;AAED,eAAe,iBAAiB,CAAC"}
|