@happyvertical/smrt-commerce 0.31.0 → 0.32.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/dist/collections/ContractLineItemCollection.d.ts +33 -0
- package/dist/collections/ContractLineItemCollection.d.ts.map +1 -0
- package/dist/collections/FulfillmentLineItemCollection.d.ts +50 -0
- package/dist/collections/FulfillmentLineItemCollection.d.ts.map +1 -0
- package/dist/collections/index.d.ts +2 -0
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +636 -248
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +284 -3
- package/dist/models/Fulfillment.d.ts +40 -3
- package/dist/models/Fulfillment.d.ts.map +1 -1
- package/dist/models/FulfillmentLineItem.d.ts +24 -0
- package/dist/models/FulfillmentLineItem.d.ts.map +1 -1
- package/dist/models/Invoice.d.ts +38 -2
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/PaymentAllocation.d.ts +15 -3
- package/dist/models/PaymentAllocation.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +57 -7
- package/dist/svelte/components/InvoiceCard.svelte +4 -3
- package/dist/svelte/components/InvoiceCard.svelte.d.ts.map +1 -1
- package/dist/svelte/components/InvoiceLineItems.svelte +4 -3
- package/dist/svelte/components/InvoiceLineItems.svelte.d.ts.map +1 -1
- package/dist/svelte/components/InvoiceTotals.svelte +12 -11
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts +4 -4
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts.map +1 -1
- package/dist/svelte/components/UnbilledItems.svelte +4 -3
- package/dist/svelte/components/UnbilledItems.svelte.d.ts.map +1 -1
- package/dist/svelte/types.d.ts +3 -3
- package/dist/svelte/types.d.ts.map +1 -1
- package/package.json +7 -7
package/dist/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.0.0",
|
|
3
|
-
"timestamp":
|
|
3
|
+
"timestamp": 1782198546055,
|
|
4
4
|
"packageName": "@happyvertical/smrt-commerce",
|
|
5
|
-
"packageVersion": "0.
|
|
5
|
+
"packageVersion": "0.32.0",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-commerce:ContractCollection": {
|
|
8
8
|
"name": "contractcollection",
|
|
@@ -211,6 +211,120 @@
|
|
|
211
211
|
"version": "c2abc9f0"
|
|
212
212
|
}
|
|
213
213
|
},
|
|
214
|
+
"@happyvertical/smrt-commerce:ContractLineItemCollection": {
|
|
215
|
+
"name": "contractlineitemcollection",
|
|
216
|
+
"className": "ContractLineItemCollection",
|
|
217
|
+
"qualifiedName": "@happyvertical/smrt-commerce:ContractLineItemCollection",
|
|
218
|
+
"collection": "contractlineitems",
|
|
219
|
+
"filePath": "/home/runner/_work/smrt/smrt/packages/commerce/src/collections/ContractLineItemCollection.ts",
|
|
220
|
+
"packageName": "@happyvertical/smrt-commerce",
|
|
221
|
+
"fields": {},
|
|
222
|
+
"methods": {
|
|
223
|
+
"findByContract": {
|
|
224
|
+
"name": "findByContract",
|
|
225
|
+
"async": true,
|
|
226
|
+
"parameters": [
|
|
227
|
+
{
|
|
228
|
+
"name": "contractId",
|
|
229
|
+
"type": "string",
|
|
230
|
+
"optional": false
|
|
231
|
+
}
|
|
232
|
+
],
|
|
233
|
+
"returnType": "Promise<ContractLineItem[]>",
|
|
234
|
+
"isStatic": false,
|
|
235
|
+
"isPublic": true
|
|
236
|
+
},
|
|
237
|
+
"findByTenant": {
|
|
238
|
+
"name": "findByTenant",
|
|
239
|
+
"async": true,
|
|
240
|
+
"parameters": [
|
|
241
|
+
{
|
|
242
|
+
"name": "tenantId",
|
|
243
|
+
"type": "string",
|
|
244
|
+
"optional": false
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
"returnType": "Promise<ContractLineItem[]>",
|
|
248
|
+
"isStatic": false,
|
|
249
|
+
"isPublic": true
|
|
250
|
+
},
|
|
251
|
+
"findGlobal": {
|
|
252
|
+
"name": "findGlobal",
|
|
253
|
+
"async": true,
|
|
254
|
+
"parameters": [],
|
|
255
|
+
"returnType": "Promise<ContractLineItem[]>",
|
|
256
|
+
"isStatic": false,
|
|
257
|
+
"isPublic": true
|
|
258
|
+
},
|
|
259
|
+
"findWithGlobals": {
|
|
260
|
+
"name": "findWithGlobals",
|
|
261
|
+
"async": true,
|
|
262
|
+
"parameters": [
|
|
263
|
+
{
|
|
264
|
+
"name": "tenantId",
|
|
265
|
+
"type": "string",
|
|
266
|
+
"optional": false
|
|
267
|
+
}
|
|
268
|
+
],
|
|
269
|
+
"returnType": "Promise<ContractLineItem[]>",
|
|
270
|
+
"isStatic": false,
|
|
271
|
+
"isPublic": true
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
"decoratorConfig": {},
|
|
275
|
+
"extends": "SmrtCollection",
|
|
276
|
+
"extendsTypeArg": "ContractLineItem",
|
|
277
|
+
"exportName": "ContractLineItemCollection",
|
|
278
|
+
"collectionExportName": "ContractLineItemCollectionCollection",
|
|
279
|
+
"schema": {
|
|
280
|
+
"tableName": "contract_line_item_collections",
|
|
281
|
+
"ddl": "CREATE TABLE IF NOT EXISTS \"contract_line_item_collections\" (\n \"id\" UUID PRIMARY KEY NOT NULL,\n \"slug\" TEXT NOT NULL,\n \"context\" TEXT NOT NULL DEFAULT '',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp\n);",
|
|
282
|
+
"columns": {
|
|
283
|
+
"id": {
|
|
284
|
+
"type": "UUID",
|
|
285
|
+
"primaryKey": true,
|
|
286
|
+
"referenceKind": "id",
|
|
287
|
+
"notNull": true
|
|
288
|
+
},
|
|
289
|
+
"slug": {
|
|
290
|
+
"type": "TEXT",
|
|
291
|
+
"notNull": true
|
|
292
|
+
},
|
|
293
|
+
"context": {
|
|
294
|
+
"type": "TEXT",
|
|
295
|
+
"notNull": true,
|
|
296
|
+
"default": ""
|
|
297
|
+
},
|
|
298
|
+
"created_at": {
|
|
299
|
+
"type": "TIMESTAMP",
|
|
300
|
+
"notNull": true,
|
|
301
|
+
"default": "current_timestamp"
|
|
302
|
+
},
|
|
303
|
+
"updated_at": {
|
|
304
|
+
"type": "TIMESTAMP",
|
|
305
|
+
"notNull": true,
|
|
306
|
+
"default": "current_timestamp"
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
"indexes": [
|
|
310
|
+
{
|
|
311
|
+
"name": "contract_line_item_collections_id_idx",
|
|
312
|
+
"columns": [
|
|
313
|
+
"id"
|
|
314
|
+
]
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"name": "contract_line_item_collections_slug_context_idx",
|
|
318
|
+
"columns": [
|
|
319
|
+
"slug",
|
|
320
|
+
"context"
|
|
321
|
+
],
|
|
322
|
+
"unique": true
|
|
323
|
+
}
|
|
324
|
+
],
|
|
325
|
+
"version": "410887d1"
|
|
326
|
+
}
|
|
327
|
+
},
|
|
214
328
|
"@happyvertical/smrt-commerce:CustomerCollection": {
|
|
215
329
|
"name": "customercollection",
|
|
216
330
|
"className": "CustomerCollection",
|
|
@@ -557,6 +671,148 @@
|
|
|
557
671
|
"version": "0cb8f9e1"
|
|
558
672
|
}
|
|
559
673
|
},
|
|
674
|
+
"@happyvertical/smrt-commerce:FulfillmentLineItemCollection": {
|
|
675
|
+
"name": "fulfillmentlineitemcollection",
|
|
676
|
+
"className": "FulfillmentLineItemCollection",
|
|
677
|
+
"qualifiedName": "@happyvertical/smrt-commerce:FulfillmentLineItemCollection",
|
|
678
|
+
"collection": "fulfillmentlineitems",
|
|
679
|
+
"filePath": "/home/runner/_work/smrt/smrt/packages/commerce/src/collections/FulfillmentLineItemCollection.ts",
|
|
680
|
+
"packageName": "@happyvertical/smrt-commerce",
|
|
681
|
+
"fields": {},
|
|
682
|
+
"methods": {
|
|
683
|
+
"findByFulfillment": {
|
|
684
|
+
"name": "findByFulfillment",
|
|
685
|
+
"async": true,
|
|
686
|
+
"parameters": [
|
|
687
|
+
{
|
|
688
|
+
"name": "fulfillmentId",
|
|
689
|
+
"type": "string",
|
|
690
|
+
"optional": false
|
|
691
|
+
}
|
|
692
|
+
],
|
|
693
|
+
"returnType": "Promise<FulfillmentLineItem[]>",
|
|
694
|
+
"isStatic": false,
|
|
695
|
+
"isPublic": true
|
|
696
|
+
},
|
|
697
|
+
"findByContractLineItem": {
|
|
698
|
+
"name": "findByContractLineItem",
|
|
699
|
+
"async": true,
|
|
700
|
+
"parameters": [
|
|
701
|
+
{
|
|
702
|
+
"name": "contractLineItemId",
|
|
703
|
+
"type": "string",
|
|
704
|
+
"optional": false
|
|
705
|
+
}
|
|
706
|
+
],
|
|
707
|
+
"returnType": "Promise<FulfillmentLineItem[]>",
|
|
708
|
+
"isStatic": false,
|
|
709
|
+
"isPublic": true
|
|
710
|
+
},
|
|
711
|
+
"getTotalFulfilledForContractLine": {
|
|
712
|
+
"name": "getTotalFulfilledForContractLine",
|
|
713
|
+
"async": true,
|
|
714
|
+
"parameters": [
|
|
715
|
+
{
|
|
716
|
+
"name": "contractLineItemId",
|
|
717
|
+
"type": "string",
|
|
718
|
+
"optional": false
|
|
719
|
+
}
|
|
720
|
+
],
|
|
721
|
+
"returnType": "Promise<number>",
|
|
722
|
+
"isStatic": false,
|
|
723
|
+
"isPublic": true
|
|
724
|
+
},
|
|
725
|
+
"findByTenant": {
|
|
726
|
+
"name": "findByTenant",
|
|
727
|
+
"async": true,
|
|
728
|
+
"parameters": [
|
|
729
|
+
{
|
|
730
|
+
"name": "tenantId",
|
|
731
|
+
"type": "string",
|
|
732
|
+
"optional": false
|
|
733
|
+
}
|
|
734
|
+
],
|
|
735
|
+
"returnType": "Promise<FulfillmentLineItem[]>",
|
|
736
|
+
"isStatic": false,
|
|
737
|
+
"isPublic": true
|
|
738
|
+
},
|
|
739
|
+
"findGlobal": {
|
|
740
|
+
"name": "findGlobal",
|
|
741
|
+
"async": true,
|
|
742
|
+
"parameters": [],
|
|
743
|
+
"returnType": "Promise<FulfillmentLineItem[]>",
|
|
744
|
+
"isStatic": false,
|
|
745
|
+
"isPublic": true
|
|
746
|
+
},
|
|
747
|
+
"findWithGlobals": {
|
|
748
|
+
"name": "findWithGlobals",
|
|
749
|
+
"async": true,
|
|
750
|
+
"parameters": [
|
|
751
|
+
{
|
|
752
|
+
"name": "tenantId",
|
|
753
|
+
"type": "string",
|
|
754
|
+
"optional": false
|
|
755
|
+
}
|
|
756
|
+
],
|
|
757
|
+
"returnType": "Promise<FulfillmentLineItem[]>",
|
|
758
|
+
"isStatic": false,
|
|
759
|
+
"isPublic": true
|
|
760
|
+
}
|
|
761
|
+
},
|
|
762
|
+
"decoratorConfig": {},
|
|
763
|
+
"extends": "SmrtCollection",
|
|
764
|
+
"extendsTypeArg": "FulfillmentLineItem",
|
|
765
|
+
"exportName": "FulfillmentLineItemCollection",
|
|
766
|
+
"collectionExportName": "FulfillmentLineItemCollectionCollection",
|
|
767
|
+
"schema": {
|
|
768
|
+
"tableName": "fulfillment_line_item_collections",
|
|
769
|
+
"ddl": "CREATE TABLE IF NOT EXISTS \"fulfillment_line_item_collections\" (\n \"id\" UUID PRIMARY KEY NOT NULL,\n \"slug\" TEXT NOT NULL,\n \"context\" TEXT NOT NULL DEFAULT '',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp\n);",
|
|
770
|
+
"columns": {
|
|
771
|
+
"id": {
|
|
772
|
+
"type": "UUID",
|
|
773
|
+
"primaryKey": true,
|
|
774
|
+
"referenceKind": "id",
|
|
775
|
+
"notNull": true
|
|
776
|
+
},
|
|
777
|
+
"slug": {
|
|
778
|
+
"type": "TEXT",
|
|
779
|
+
"notNull": true
|
|
780
|
+
},
|
|
781
|
+
"context": {
|
|
782
|
+
"type": "TEXT",
|
|
783
|
+
"notNull": true,
|
|
784
|
+
"default": ""
|
|
785
|
+
},
|
|
786
|
+
"created_at": {
|
|
787
|
+
"type": "TIMESTAMP",
|
|
788
|
+
"notNull": true,
|
|
789
|
+
"default": "current_timestamp"
|
|
790
|
+
},
|
|
791
|
+
"updated_at": {
|
|
792
|
+
"type": "TIMESTAMP",
|
|
793
|
+
"notNull": true,
|
|
794
|
+
"default": "current_timestamp"
|
|
795
|
+
}
|
|
796
|
+
},
|
|
797
|
+
"indexes": [
|
|
798
|
+
{
|
|
799
|
+
"name": "fulfillment_line_item_collections_id_idx",
|
|
800
|
+
"columns": [
|
|
801
|
+
"id"
|
|
802
|
+
]
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
"name": "fulfillment_line_item_collections_slug_context_idx",
|
|
806
|
+
"columns": [
|
|
807
|
+
"slug",
|
|
808
|
+
"context"
|
|
809
|
+
],
|
|
810
|
+
"unique": true
|
|
811
|
+
}
|
|
812
|
+
],
|
|
813
|
+
"version": "88e7502e"
|
|
814
|
+
}
|
|
815
|
+
},
|
|
560
816
|
"@happyvertical/smrt-commerce:InvoiceCollection": {
|
|
561
817
|
"name": "invoicecollection",
|
|
562
818
|
"className": "InvoiceCollection",
|
|
@@ -10894,6 +11150,22 @@
|
|
|
10894
11150
|
}
|
|
10895
11151
|
},
|
|
10896
11152
|
"methods": {
|
|
11153
|
+
"initialize": {
|
|
11154
|
+
"name": "initialize",
|
|
11155
|
+
"async": true,
|
|
11156
|
+
"parameters": [],
|
|
11157
|
+
"returnType": "Promise",
|
|
11158
|
+
"isStatic": false,
|
|
11159
|
+
"isPublic": true
|
|
11160
|
+
},
|
|
11161
|
+
"save": {
|
|
11162
|
+
"name": "save",
|
|
11163
|
+
"async": true,
|
|
11164
|
+
"parameters": [],
|
|
11165
|
+
"returnType": "Promise",
|
|
11166
|
+
"isStatic": false,
|
|
11167
|
+
"isPublic": true
|
|
11168
|
+
},
|
|
10897
11169
|
"isDelivered": {
|
|
10898
11170
|
"name": "isDelivered",
|
|
10899
11171
|
"async": false,
|
|
@@ -11133,7 +11405,16 @@
|
|
|
11133
11405
|
"default": ""
|
|
11134
11406
|
}
|
|
11135
11407
|
},
|
|
11136
|
-
"methods": {
|
|
11408
|
+
"methods": {
|
|
11409
|
+
"save": {
|
|
11410
|
+
"name": "save",
|
|
11411
|
+
"async": true,
|
|
11412
|
+
"parameters": [],
|
|
11413
|
+
"returnType": "Promise",
|
|
11414
|
+
"isStatic": false,
|
|
11415
|
+
"isPublic": true
|
|
11416
|
+
}
|
|
11417
|
+
},
|
|
11137
11418
|
"decoratorConfig": {
|
|
11138
11419
|
"api": {
|
|
11139
11420
|
"include": [
|
|
@@ -70,6 +70,35 @@ export declare class Fulfillment extends SmrtObject {
|
|
|
70
70
|
*/
|
|
71
71
|
notes: string;
|
|
72
72
|
constructor(options?: any);
|
|
73
|
+
/**
|
|
74
|
+
* Capture the status the row was loaded with so the save-time transition
|
|
75
|
+
* guard can reject illegal status flips made via raw field assignment
|
|
76
|
+
* (mass-assignment on the generated update route, a stale caller, etc.).
|
|
77
|
+
* Only persisted rows carry a prior status.
|
|
78
|
+
*/
|
|
79
|
+
initialize(): Promise<this>;
|
|
80
|
+
/**
|
|
81
|
+
* Validate the status transition before persisting, then save. Blocks a
|
|
82
|
+
* forged `status` written via raw mass-assignment on the open
|
|
83
|
+
* `api:{create,update}` surface. See S5 audit #1390 follow-up.
|
|
84
|
+
*/
|
|
85
|
+
save(): Promise<this>;
|
|
86
|
+
/**
|
|
87
|
+
* Reject an illegal status flip done via raw assignment. No-op transitions
|
|
88
|
+
* and brand-new rows are always allowed.
|
|
89
|
+
*/
|
|
90
|
+
private assertStatusTransition;
|
|
91
|
+
/**
|
|
92
|
+
* Resolve the AUTHORITATIVE prior status. The WeakMap is only populated when
|
|
93
|
+
* {@link initialize} loaded the row; it is empty for an instance built via
|
|
94
|
+
* `collection.create({ id: <existing>, _skipLoad: true })` (the upsert path
|
|
95
|
+
* that writes onto an existing row without hydrating it). Trusting an empty
|
|
96
|
+
* WeakMap there would treat the write as a brand-new row and skip the guard.
|
|
97
|
+
* So when this instance carries an `id`, read the persisted row straight from
|
|
98
|
+
* the DB and treat its `status` as the prior. `undefined` = genuinely new.
|
|
99
|
+
* Mirrors the authoritative-prior-load on Contract/Payment/Invoice/Payout.
|
|
100
|
+
*/
|
|
101
|
+
private resolvePriorStatus;
|
|
73
102
|
/**
|
|
74
103
|
* Check if fulfillment is complete
|
|
75
104
|
*/
|
|
@@ -83,15 +112,23 @@ export declare class Fulfillment extends SmrtObject {
|
|
|
83
112
|
*/
|
|
84
113
|
isPending(): boolean;
|
|
85
114
|
/**
|
|
86
|
-
*
|
|
115
|
+
* Assert the current in-memory status may legally transition to `next`,
|
|
116
|
+
* surfacing the illegal-transition error at the mutation call site rather
|
|
117
|
+
* than deferring it to save(). A no-op (already in `next`) is allowed.
|
|
118
|
+
*/
|
|
119
|
+
private assertCanTransitionTo;
|
|
120
|
+
/**
|
|
121
|
+
* Mark as shipped. Rejected from a terminal state (DELIVERED / CANCELLED).
|
|
87
122
|
*/
|
|
88
123
|
markShipped(trackingNumber?: string, carrier?: string): void;
|
|
89
124
|
/**
|
|
90
|
-
* Mark as delivered
|
|
125
|
+
* Mark as delivered. Rejected from CANCELLED (a cancelled shipment can't be
|
|
126
|
+
* delivered).
|
|
91
127
|
*/
|
|
92
128
|
markDelivered(): void;
|
|
93
129
|
/**
|
|
94
|
-
* Cancel fulfillment
|
|
130
|
+
* Cancel fulfillment. Rejected once DELIVERED (a delivered shipment can't be
|
|
131
|
+
* cancelled — model a return/refund elsewhere instead).
|
|
95
132
|
*/
|
|
96
133
|
cancel(): void;
|
|
97
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Fulfillment.d.ts","sourceRoot":"","sources":["../../src/models/Fulfillment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAc,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAExE,OAAO,EACL,KAAK,OAAO,EACZ,iBAAiB,EACjB,eAAe,EAChB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"Fulfillment.d.ts","sourceRoot":"","sources":["../../src/models/Fulfillment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAc,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAExE,OAAO,EACL,KAAK,OAAO,EACZ,iBAAiB,EACjB,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAiD3B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAMa,WAAY,SAAQ,UAAU;IACzC;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB;;OAEG;IACH,eAAe,EAAE,eAAe,CAA4B;IAE5D;;OAEG;IACH,MAAM,EAAE,iBAAiB,CAA6B;IAEtD;;OAEG;IACH,cAAc,EAAE,MAAM,CAAM;IAE5B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAM;IAErB;;OAEG;IACH,eAAe,EAAE,OAAO,CAAM;IAE9B;;OAEG;IACH,SAAS,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE9B;;OAEG;IACH,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEhC;;OAEG;IACH,iBAAiB,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEtC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;gBAEP,OAAO,GAAE,GAAQ;IAoB7B;;;;;OAKG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ1C;;;;OAIG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQpC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAa9B;;;;;;;;;OASG;YACW,kBAAkB;IAchC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;IACH,WAAW,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ5D;;;OAGG;IACH,aAAa,IAAI,IAAI;IAMrB;;;OAGG;IACH,MAAM,IAAI,IAAI;CAIf;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -37,6 +37,30 @@ export declare class FulfillmentLineItem extends SmrtObject {
|
|
|
37
37
|
*/
|
|
38
38
|
notes: string;
|
|
39
39
|
constructor(options?: any);
|
|
40
|
+
/**
|
|
41
|
+
* Save-time over-fulfillment guard (S5 audit #1390 follow-up, round 2):
|
|
42
|
+
* - `quantityFulfilled` must be a finite, positive number,
|
|
43
|
+
* - the referenced `ContractLineItem` must resolve **within the caller's
|
|
44
|
+
* tenant scope** AND belong to the same contract as the parent
|
|
45
|
+
* Fulfillment, and
|
|
46
|
+
* - the sum of all FulfillmentLineItems against that ContractLineItem
|
|
47
|
+
* (this row included) must not exceed the ordered `ContractLineItem.quantity`.
|
|
48
|
+
*
|
|
49
|
+
* Without this, a caller could ship 50 of 10 ordered — the direct parallel
|
|
50
|
+
* to the PaymentAllocation over-allocation hole #1390 closed.
|
|
51
|
+
*
|
|
52
|
+
* Tenant isolation (round 2): the ContractLineItem is loaded through
|
|
53
|
+
* `ContractLineItemCollection`, so it goes through the tenancy
|
|
54
|
+
* auto-filtering interceptors. A cross-tenant `contractLineItemId` therefore
|
|
55
|
+
* fails closed — it resolves to `null` and trips the existing "does not
|
|
56
|
+
* exist" error rather than leaking a foreign-tenant ordered quantity. The
|
|
57
|
+
* raw `this.db.get('contract_line_items', …)` it replaced bypassed those
|
|
58
|
+
* filters. We additionally load the parent Fulfillment (also tenant-scoped)
|
|
59
|
+
* and reject when the line item belongs to a *different* contract than the
|
|
60
|
+
* Fulfillment is fulfilling, so a valid-but-unrelated line id can't be
|
|
61
|
+
* used to fulfill against the wrong order.
|
|
62
|
+
*/
|
|
63
|
+
save(): Promise<this>;
|
|
40
64
|
}
|
|
41
65
|
export default FulfillmentLineItem;
|
|
42
66
|
//# sourceMappingURL=FulfillmentLineItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FulfillmentLineItem.d.ts","sourceRoot":"","sources":["../../src/models/FulfillmentLineItem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAc,UAAU,EAAQ,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"FulfillmentLineItem.d.ts","sourceRoot":"","sources":["../../src/models/FulfillmentLineItem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAc,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAUxE;;;;;;;;;;;;;;GAcG;AACH,qBAMa,mBAAoB,SAAQ,UAAU;IACjD;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,aAAa,EAAE,MAAM,CAAM;IAE3B;;OAEG;IAEH,kBAAkB,EAAE,MAAM,CAAM;IAEhC;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAO;IAEhC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAM;gBAEP,OAAO,GAAE,GAAQ;IAY7B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAwFrC;AAED,eAAe,mBAAmB,CAAC"}
|
package/dist/models/Invoice.d.ts
CHANGED
|
@@ -190,6 +190,31 @@ export declare class Invoice extends SmrtObject {
|
|
|
190
190
|
* (the dynamic imports stay inside the package).
|
|
191
191
|
*/
|
|
192
192
|
private recomputeAmountsForSave;
|
|
193
|
+
/**
|
|
194
|
+
* Whether `amountPaid` covers `totalAmount` within the sub-cent rounding
|
|
195
|
+
* tolerance. This is the SINGLE source of truth for the **PAID** decision —
|
|
196
|
+
* both {@link updatePaymentStatus} (which decides PAID) and
|
|
197
|
+
* {@link assertPaymentStatusConsistent} (which validates PAID on save) call
|
|
198
|
+
* it, so the PAID-deciding comparison and the PAID-validating comparison can
|
|
199
|
+
* never drift apart. A strict `amountPaid >= totalAmount` here would diverge
|
|
200
|
+
* from the epsilon-tolerant guard: a float-summed total paid exactly (e.g.
|
|
201
|
+
* `0.1 × 3` line items paid `0.3`) reads as "not covered" by `>=` but
|
|
202
|
+
* "covered" by the guard, so `updatePaymentStatus` would set PARTIAL and the
|
|
203
|
+
* save-time guard would then reject it — leaving a genuinely-paid invoice
|
|
204
|
+
* unsaveable (S5 audit #1390 follow-up).
|
|
205
|
+
*
|
|
206
|
+
* NOTE: the claim is scoped to PAID. The PARTIAL branch is NOT unified the
|
|
207
|
+
* same way — {@link updatePaymentStatus} treats any `amountPaid > 0` as
|
|
208
|
+
* PARTIAL, whereas {@link isPartiallyPaid} (used by the save-time guard)
|
|
209
|
+
* requires `amountPaid > INVOICE_EPSILON`. That pre-existing asymmetry only
|
|
210
|
+
* matters for a sub-cent dust payment and is intentionally left as-is.
|
|
211
|
+
*/
|
|
212
|
+
private isFullyPaid;
|
|
213
|
+
/**
|
|
214
|
+
* Whether `amountPaid` is a non-trivial partial payment of `totalAmount`.
|
|
215
|
+
* Derived from {@link isFullyPaid} so the two stay mutually exclusive.
|
|
216
|
+
*/
|
|
217
|
+
private isPartiallyPaid;
|
|
193
218
|
/**
|
|
194
219
|
* After amounts are recomputed and amountPaid is re-derived from allocations,
|
|
195
220
|
* assert the persisted `status` is consistent with the derived
|
|
@@ -205,8 +230,19 @@ export declare class Invoice extends SmrtObject {
|
|
|
205
230
|
*/
|
|
206
231
|
private assertPaymentStatusConsistent;
|
|
207
232
|
/**
|
|
208
|
-
* Enforce `totalAmount === subtotal + taxAmount` (within rounding tolerance)
|
|
209
|
-
*
|
|
233
|
+
* Enforce `totalAmount === subtotal + taxAmount` (within rounding tolerance),
|
|
234
|
+
* then SNAP `totalAmount` to the exact arithmetic. Used when the invoice has
|
|
235
|
+
* no line items to recompute from.
|
|
236
|
+
*
|
|
237
|
+
* The snap closes the invoice-vs-ledger epsilon gap (S5 audit #1390
|
|
238
|
+
* follow-up): the invoice guard tolerates `INVOICE_EPSILON` (0.01) but the
|
|
239
|
+
* smrt-ledgers balance check uses a tighter `BALANCE_EPSILON` (0.001). A
|
|
240
|
+
* no-line-item invoice with, say, subtotal 100.00 / total 100.005 passes this
|
|
241
|
+
* guard, yet `recognizeRevenue` would build DR 100.005 / CR 100.00 and
|
|
242
|
+
* `journal.post()` would reject it as unbalanced — voiding the journal and
|
|
243
|
+
* permanently blocking revenue recognition. Snapping `totalAmount` to
|
|
244
|
+
* `subtotal + taxAmount` here (after the tolerance check) means the persisted
|
|
245
|
+
* total and every journal built from it are always ledger-consistent.
|
|
210
246
|
*/
|
|
211
247
|
private assertTotalArithmetic;
|
|
212
248
|
/**
|
|
@@ -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;AAElC,OAAO,EAAE,aAAa,EAAE,KAAK,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"Invoice.d.ts","sourceRoot":"","sources":["../../src/models/Invoice.ts"],"names":[],"mappings":"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"}
|
|
@@ -72,12 +72,14 @@ export declare class PaymentAllocation extends SmrtObject {
|
|
|
72
72
|
notes: string;
|
|
73
73
|
constructor(options?: any);
|
|
74
74
|
/**
|
|
75
|
-
* Save-time integrity guard (S5 audit #1390):
|
|
76
|
-
* - allocation `amount` must be a finite, positive number,
|
|
75
|
+
* Save-time integrity guard (S5 audit #1390 + follow-up):
|
|
76
|
+
* - allocation `amount` must be a finite, positive number,
|
|
77
77
|
* - the sum of all allocations against the referenced Payment (this row
|
|
78
78
|
* included) must not exceed the Payment's amount — over-applying a
|
|
79
79
|
* payment across invoices would falsify both payment and invoice
|
|
80
|
-
* balances
|
|
80
|
+
* balances, and
|
|
81
|
+
* - the sum of all allocations against the referenced Invoice (this row
|
|
82
|
+
* included) must not exceed the Invoice's `totalAmount`.
|
|
81
83
|
*
|
|
82
84
|
* The Payment-amount cap is enforced against the persisted Payment row. An
|
|
83
85
|
* allocation always carries a `@foreignKey('Payment')` paymentId, so a
|
|
@@ -86,6 +88,16 @@ export declare class PaymentAllocation extends SmrtObject {
|
|
|
86
88
|
* entirely, letting a caller over-apply (or fabricate) funds simply by
|
|
87
89
|
* pointing at a non-existent payment. An empty `paymentId` is still rejected
|
|
88
90
|
* by the underlying FK requirement; the positivity check always applies.
|
|
91
|
+
*
|
|
92
|
+
* The Invoice-total cap (follow-up) closes a complementary hole: the
|
|
93
|
+
* per-Payment cap lets allocations from *different* payments each pass their
|
|
94
|
+
* own check while jointly summing above the invoice total. The next
|
|
95
|
+
* `Invoice.save()` would then recompute `amountPaid` from these allocations,
|
|
96
|
+
* trip `assertNonNegativeAmounts` (amountPaid > totalAmount), and leave the
|
|
97
|
+
* invoice permanently unsaveable while the over-allocations persist. Capping
|
|
98
|
+
* here keeps allocations from ever exceeding what the invoice owes. The cap
|
|
99
|
+
* is skipped only when the invoice row can't be resolved (e.g. ledger-less /
|
|
100
|
+
* not-yet-persisted) so it never blocks an otherwise-valid allocation.
|
|
89
101
|
*/
|
|
90
102
|
save(): Promise<this>;
|
|
91
103
|
}
|
|
@@ -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;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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACY,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAmFrC;AAED,eAAe,iBAAiB,CAAC"}
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"generatedAt": "2026-06-23T07:09:06.841Z",
|
|
4
4
|
"packageName": "@happyvertical/smrt-commerce",
|
|
5
|
-
"packageVersion": "0.
|
|
5
|
+
"packageVersion": "0.32.0",
|
|
6
6
|
"sourceManifestPath": "dist/manifest.json",
|
|
7
7
|
"agentDocPath": "AGENTS.md",
|
|
8
8
|
"sourceHashes": {
|
|
9
|
-
"manifest": "
|
|
10
|
-
"packageJson": "
|
|
9
|
+
"manifest": "84f8fdc2826f300da47a9ab3762a862193a80a2dcb3e347c4ab578e5b40a81ef",
|
|
10
|
+
"packageJson": "941964662329b4dd0a86529d6edfa8f2f11e0adf215f3ba4d55e74009aec8d99",
|
|
11
11
|
"agents": "f544ac9cece5c94aaead6013316709fcd044944b993110fc7218c0db7c998a63"
|
|
12
12
|
},
|
|
13
13
|
"exports": [
|
|
@@ -76,6 +76,28 @@
|
|
|
76
76
|
"tags": [],
|
|
77
77
|
"risks": []
|
|
78
78
|
},
|
|
79
|
+
{
|
|
80
|
+
"name": "ContractLineItemCollection",
|
|
81
|
+
"qualifiedName": "@happyvertical/smrt-commerce:ContractLineItemCollection",
|
|
82
|
+
"collection": "contractlineitems",
|
|
83
|
+
"tableName": "contract_line_item_collections",
|
|
84
|
+
"packageName": "@happyvertical/smrt-commerce",
|
|
85
|
+
"extends": "SmrtCollection",
|
|
86
|
+
"fields": [],
|
|
87
|
+
"relationships": [],
|
|
88
|
+
"methods": [
|
|
89
|
+
"findByContract",
|
|
90
|
+
"findByTenant",
|
|
91
|
+
"findGlobal",
|
|
92
|
+
"findWithGlobals"
|
|
93
|
+
],
|
|
94
|
+
"surfaces": [],
|
|
95
|
+
"relationshipFeatures": [
|
|
96
|
+
"uuidColumns"
|
|
97
|
+
],
|
|
98
|
+
"tags": [],
|
|
99
|
+
"risks": []
|
|
100
|
+
},
|
|
79
101
|
{
|
|
80
102
|
"name": "CustomerCollection",
|
|
81
103
|
"qualifiedName": "@happyvertical/smrt-commerce:CustomerCollection",
|
|
@@ -129,6 +151,30 @@
|
|
|
129
151
|
"tags": [],
|
|
130
152
|
"risks": []
|
|
131
153
|
},
|
|
154
|
+
{
|
|
155
|
+
"name": "FulfillmentLineItemCollection",
|
|
156
|
+
"qualifiedName": "@happyvertical/smrt-commerce:FulfillmentLineItemCollection",
|
|
157
|
+
"collection": "fulfillmentlineitems",
|
|
158
|
+
"tableName": "fulfillment_line_item_collections",
|
|
159
|
+
"packageName": "@happyvertical/smrt-commerce",
|
|
160
|
+
"extends": "SmrtCollection",
|
|
161
|
+
"fields": [],
|
|
162
|
+
"relationships": [],
|
|
163
|
+
"methods": [
|
|
164
|
+
"findByContractLineItem",
|
|
165
|
+
"findByFulfillment",
|
|
166
|
+
"findByTenant",
|
|
167
|
+
"findGlobal",
|
|
168
|
+
"findWithGlobals",
|
|
169
|
+
"getTotalFulfilledForContractLine"
|
|
170
|
+
],
|
|
171
|
+
"surfaces": [],
|
|
172
|
+
"relationshipFeatures": [
|
|
173
|
+
"uuidColumns"
|
|
174
|
+
],
|
|
175
|
+
"tags": [],
|
|
176
|
+
"risks": []
|
|
177
|
+
},
|
|
132
178
|
{
|
|
133
179
|
"name": "InvoiceCollection",
|
|
134
180
|
"qualifiedName": "@happyvertical/smrt-commerce:InvoiceCollection",
|
|
@@ -2919,11 +2965,13 @@
|
|
|
2919
2965
|
],
|
|
2920
2966
|
"methods": [
|
|
2921
2967
|
"cancel",
|
|
2968
|
+
"initialize",
|
|
2922
2969
|
"isDelivered",
|
|
2923
2970
|
"isInTransit",
|
|
2924
2971
|
"isPending",
|
|
2925
2972
|
"markDelivered",
|
|
2926
|
-
"markShipped"
|
|
2973
|
+
"markShipped",
|
|
2974
|
+
"save"
|
|
2927
2975
|
],
|
|
2928
2976
|
"surfaces": [
|
|
2929
2977
|
{
|
|
@@ -3065,7 +3113,9 @@
|
|
|
3065
3113
|
"columnType": "UUID"
|
|
3066
3114
|
}
|
|
3067
3115
|
],
|
|
3068
|
-
"methods": [
|
|
3116
|
+
"methods": [
|
|
3117
|
+
"save"
|
|
3118
|
+
],
|
|
3069
3119
|
"surfaces": [
|
|
3070
3120
|
{
|
|
3071
3121
|
"kind": "api",
|
|
@@ -5488,7 +5538,7 @@
|
|
|
5488
5538
|
"junctionCollections": 0,
|
|
5489
5539
|
"hierarchicalObjects": 0,
|
|
5490
5540
|
"polymorphicAssociations": 0,
|
|
5491
|
-
"uuidColumns":
|
|
5541
|
+
"uuidColumns": 93
|
|
5492
5542
|
},
|
|
5493
5543
|
"agentDoc": "# @happyvertical/smrt-commerce\n\nE-commerce with Contract STI hierarchy, invoice lifecycle, payment tracking, payout remittance, and optional ledger integration.\n\n## Models\n\n- **Customer** / **Vendor**: linked to Profile via string ID (not FK). Customer has creditLimit, paymentTerms, customerType (DTC / WHOLESALE / RETAIL). Vendor has leadTimeDays, minimumOrder, and `payoutAddresses: Record<string, string>` — a flat map from payout-rail-qualified currency code (`USDC-base`, `BTC`, `USD-stripe`, ...) to destination string (EVM address, BTC address, Stripe Connect account id, IBAN). Use `getPayoutAddress(currency)` for a `Map.get`-style lookup; missing entries return `undefined` (caller decides skip-vs-error).\n- **Contract** (STI base → Estimate, Order, Lease, Agreement, PurchaseOrder, WholesaleOrder, ProductionOrder, Cart, LicenseSale): 9 contract types sharing one table. Carries `channelId` (open-ended string — `dtc-web`, `wholesale-b2b`, `pos-store-N`, etc.) so the same model serves DTC checkout, B2B portals, and POS.\n- **WholesaleOrder**: B2B order. Conventional pairing — customer has `customerType: 'wholesale'`, NET-30/60 terms, delivered via wholesale-portal channel.\n- **ProductionOrder**: manufacturing equivalent of a PurchaseOrder — commission your factory to make finished goods. Consumes raw materials per BOM (`@happyvertical/smrt-manufacturing`) and produces SKU stock (`@happyvertical/smrt-inventory`).\n- **Cart**: transient order-in-progress. Same shape as Order; the application promotes the row from `_meta_type: Cart` to `_meta_type: Order` at checkout instead of copying data between tables.\n- **LicenseSale**: industry-neutral licensing primitive. Carries an *immutable* rights snapshot (`rightsMedium`, `rightsDistributionScope`, `rightsExclusivity`, `rightsDuration`, `rightsTerritory`, `rightsSublicensing`, `rightsDerivatives` — typed `Meta<T>` fields), licensee identity (`licenseeEmail`, optional `licenseeLegalEntity` / `licenseeJurisdiction`), and a signed-PDF reference (`pdfUrl`, `pdfHash`, optional `onChainHashRegistryRef`). Once saved at `ContractStatus.ACCEPTED`, the rights snapshot is frozen — mutating any of the seven rights fields and re-saving throws. The only legal transition out of ACCEPTED is `revoke()` (moves to CANCELLED without touching rights). Useful for stock media, music licensing, code-asset marketplaces, license keys, anywhere rights are sold for a fee.\n- **ContractLineItem**: items on contracts.\n- **Invoice**: status machine `DRAFT → SENT → VIEWED → PARTIAL → PAID` (also OVERDUE, CANCELLED, WRITTEN_OFF). `recognizeRevenue()` creates balanced AR journal entry (DR: Accounts Receivable, CR: Revenue, CR: Tax Payable).\n- **InvoiceLineItem**: line items on invoices.\n- **Payment** / **PaymentAllocation**: tracks payments against invoices. Status controlled by `Invoice.updatePaymentStatus()`, not Payment model. Carries optional backend-adapter fields for PaymentBackend-routed flows: `backendId` (rail adapter id — `base-usdc`, `btc`, `stripe`, distinct from `externalProvider` which names an accounting sync destination), `backendTxRef` (chain tx hash or gateway settlement id), `nativeAmount` / `nativeCurrency` (what actually arrived), `usdAtQuote` / `usdAtConfirmation` (drift accounting for volatile-currency rails). `Payment.usdDrift()` returns the confirmation - quote delta, or `0` when either side is unset.\n- **PaymentIntent**: short-lived pre-payment commitment with multi-option semantics. Locks a USD price for a fixed window (default 15 minutes) and lists one or more `PaymentOption`s describing different rails (`backendId`, `currency`, `payTo`, `nativeAmount`, optional `chain` / `memo` / `x402Capable` / `expiresAt`). First option to receive payment wins; the others are implicitly retired. State machine `awaiting_payment → paid → (issued | retired)` plus `expired` and `cancelled`. Mutate via dedicated `markPaid` / `markIssued` / `expire` / `cancel` / `retire` helpers — direct status assignment bypasses the invariant checks. Idempotency via natural key `(tenant_id, offering_ref, licensee_email, idempotency_key)` and `PaymentIntentCollection.getOrCreateByIdempotencyKey()`.\n- **Payout**: operator-to-supplier remittance. Distinct from Payment because direction, status machine, and chain semantics differ. Status machine `pending → sent → confirmed → failed` (failed is terminal but resettable via `resetFromFailed()` after fixing the underlying problem). References source `paymentId` (plain string) and destination `vendorId` (foreign key). Amount invariant `supplierNet === grossAmount - operatorFee` (1¢ rounding tolerance) enforced on save. `PayoutCollection.createFromPayment()` is the typical entry point; it pulls native amount / currency from the source Payment.\n- **Fulfillment** / **FulfillmentLineItem**: shipment/delivery tracking.\n\n## Ledger Integration\n\n`@happyvertical/smrt-ledgers` is a regular dependency, loaded lazily via dynamic `import()` so the coupling stays runtime-only (no hard static import; the package graph stays a DAG — see #1582). Invoice stores `arJournalId` and `revenueJournalId` as string references. `recognizeRevenue()` creates a balanced AR journal entry; `getArJournal()` returns null when no journal has been recognized yet.\n\n## Cross-Package References\n\n- `customerId` → `@foreignKey('Customer')` (hard reference within package)\n- `profileId` → plain string to smrt-profiles\n- `arJournalId`, `revenueJournalId` → plain string to smrt-ledgers\n- `skuId` (on `PaymentIntent`, `LicenseSale`) → plain string to smrt-products\n- `paymentId` (on `PaymentIntent`, `Payout`, `LicenseSale`) → plain string to `Payment` (same package, but kept as plain string for cross-model consistency)\n- `vendorId` on `Payout` → `@foreignKey(Vendor)` (hard reference within package)\n\n## Gotchas\n\n- **Optional tenancy**: all models `@TenantScoped({ mode: 'optional' })` + nullable tenantId\n- **Currency in decimal fields**: price, taxAmount, totalAmount (not integer cents like affiliates)\n- **Invoice controls payment status**: not the Payment model — use `Invoice.updatePaymentStatus()`\n- **Tax rate is external**: no tax rate field on Invoice — rate must be calculated externally\n- **Profile linking**: separate `ProfileCollection.create()` needed to fetch actual Profile object\n- **PaymentIntent natural key**: `conflictColumns: ['tenant_id', 'offering_ref', 'licensee_email', 'idempotency_key']` — a retried `create` with the same tuple upserts the existing row. Use `getOrCreateByIdempotencyKey()` to branch on `{ intent, created }`. Empty natural-key inputs (e.g. blank `idempotencyKey`) disable dedup by design.\n- **Payout state-machine guards**: `markSent` requires a non-empty `backendTxRef`; `markConfirmed` only valid from `SENT`; `markFailed` only valid from `PENDING` / `SENT` (a confirmed payout can't fail — that path is a refund). `resetFromFailed()` is the dedicated escape hatch from `FAILED` back to `PENDING` after an operator fixes the underlying problem; it clears `backendTxRef` so the next attempt picks up a fresh one.\n- **LicenseSale immutability**: rights snapshot freezes on save-with-status-ACCEPTED. The captured snapshot lives in a module-scoped `WeakMap<LicenseSale, string>` so it doesn't interact with the schema or round-trip through `_meta_data`. Drafts (status != ACCEPTED) remain mutable. To \"change\" an issued license: `revoke()` it, then issue a new `LicenseSale` row.\n- **Vendor.payoutAddresses normalization**: the constructor accepts either a `Record<string, string>` or a pre-serialized JSON string. `initialize()` re-normalizes after the framework's option-override pass; `save()` re-normalizes defensively against direct field assignment. Non-string values inside the input map are silently dropped to preserve the typed invariant downstream.\n"
|
|
5494
5544
|
}
|