@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,99 @@
|
|
|
1
|
+
import { SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { Address, FulfillmentStatus, FulfillmentType } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fulfillment tracks the delivery or completion of contract items.
|
|
5
|
+
*
|
|
6
|
+
* A contract can have multiple fulfillments (e.g., partial shipments).
|
|
7
|
+
* Each fulfillment tracks what was delivered and when.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const fulfillment = await fulfillments.create({
|
|
12
|
+
* contractId: order.id,
|
|
13
|
+
* fulfillmentType: FulfillmentType.SHIPMENT,
|
|
14
|
+
* trackingNumber: 'UPS-123456789',
|
|
15
|
+
* carrier: 'UPS',
|
|
16
|
+
* shippingAddress: {
|
|
17
|
+
* street1: '123 Main St',
|
|
18
|
+
* city: 'Anytown',
|
|
19
|
+
* state: 'CA',
|
|
20
|
+
* postalCode: '90210',
|
|
21
|
+
* country: 'US'
|
|
22
|
+
* }
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class Fulfillment extends SmrtObject {
|
|
27
|
+
/**
|
|
28
|
+
* Tenant ID for multi-tenant isolation
|
|
29
|
+
* Nullable to support both tenant-scoped and global fulfillments
|
|
30
|
+
*/
|
|
31
|
+
tenantId: string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Parent contract being fulfilled
|
|
34
|
+
*/
|
|
35
|
+
contractId: string;
|
|
36
|
+
/**
|
|
37
|
+
* Type of fulfillment
|
|
38
|
+
*/
|
|
39
|
+
fulfillmentType: FulfillmentType;
|
|
40
|
+
/**
|
|
41
|
+
* Current fulfillment status
|
|
42
|
+
*/
|
|
43
|
+
status: FulfillmentStatus;
|
|
44
|
+
/**
|
|
45
|
+
* Tracking number from carrier
|
|
46
|
+
*/
|
|
47
|
+
trackingNumber: string;
|
|
48
|
+
/**
|
|
49
|
+
* Shipping carrier name
|
|
50
|
+
*/
|
|
51
|
+
carrier: string;
|
|
52
|
+
/**
|
|
53
|
+
* Shipping destination address
|
|
54
|
+
*/
|
|
55
|
+
shippingAddress: Address;
|
|
56
|
+
/**
|
|
57
|
+
* When the shipment was sent
|
|
58
|
+
*/
|
|
59
|
+
shippedAt: Date | null;
|
|
60
|
+
/**
|
|
61
|
+
* When the shipment was delivered
|
|
62
|
+
*/
|
|
63
|
+
deliveredAt: Date | null;
|
|
64
|
+
/**
|
|
65
|
+
* Estimated delivery date
|
|
66
|
+
*/
|
|
67
|
+
estimatedDelivery: Date | null;
|
|
68
|
+
/**
|
|
69
|
+
* Notes about this fulfillment
|
|
70
|
+
*/
|
|
71
|
+
notes: string;
|
|
72
|
+
constructor(options?: any);
|
|
73
|
+
/**
|
|
74
|
+
* Check if fulfillment is complete
|
|
75
|
+
*/
|
|
76
|
+
isDelivered(): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Check if fulfillment is in transit
|
|
79
|
+
*/
|
|
80
|
+
isInTransit(): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Check if fulfillment is pending
|
|
83
|
+
*/
|
|
84
|
+
isPending(): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Mark as shipped
|
|
87
|
+
*/
|
|
88
|
+
markShipped(trackingNumber?: string, carrier?: string): void;
|
|
89
|
+
/**
|
|
90
|
+
* Mark as delivered
|
|
91
|
+
*/
|
|
92
|
+
markDelivered(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Cancel fulfillment
|
|
95
|
+
*/
|
|
96
|
+
cancel(): void;
|
|
97
|
+
}
|
|
98
|
+
export default Fulfillment;
|
|
99
|
+
//# sourceMappingURL=Fulfillment.d.ts.map
|
|
@@ -0,0 +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;AAE3B;;;;;;;;;;;;;;;;;;;;;;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;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,WAAW,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAO5D;;OAEG;IACH,aAAa,IAAI,IAAI;IAKrB;;OAEG;IACH,MAAM,IAAI,IAAI;CAGf;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
/**
|
|
3
|
+
* FulfillmentLineItem tracks which contract line items are included
|
|
4
|
+
* in a specific fulfillment and how much was fulfilled.
|
|
5
|
+
*
|
|
6
|
+
* This allows partial fulfillment - e.g., shipping 5 of 10 items ordered.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const fulfillmentItem = await fulfillmentItems.create({
|
|
11
|
+
* fulfillmentId: fulfillment.id,
|
|
12
|
+
* contractLineItemId: lineItem.id,
|
|
13
|
+
* quantityFulfilled: 5 // of 10 ordered
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare class FulfillmentLineItem extends SmrtObject {
|
|
18
|
+
/**
|
|
19
|
+
* Tenant ID for multi-tenant isolation
|
|
20
|
+
* Nullable to support both tenant-scoped and global fulfillment line items
|
|
21
|
+
*/
|
|
22
|
+
tenantId: string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Parent fulfillment
|
|
25
|
+
*/
|
|
26
|
+
fulfillmentId: string;
|
|
27
|
+
/**
|
|
28
|
+
* Contract line item being fulfilled
|
|
29
|
+
*/
|
|
30
|
+
contractLineItemId: string;
|
|
31
|
+
/**
|
|
32
|
+
* Quantity fulfilled in this fulfillment
|
|
33
|
+
*/
|
|
34
|
+
quantityFulfilled: number;
|
|
35
|
+
/**
|
|
36
|
+
* Notes about this line item
|
|
37
|
+
*/
|
|
38
|
+
notes: string;
|
|
39
|
+
constructor(options?: any);
|
|
40
|
+
}
|
|
41
|
+
export default FulfillmentLineItem;
|
|
42
|
+
//# sourceMappingURL=FulfillmentLineItem.d.ts.map
|
|
@@ -0,0 +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;AAGxE;;;;;;;;;;;;;;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;CAW9B;AAED,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { InvoiceStatus, RecognizeRevenueOptions } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Invoice represents a bill sent to a customer for goods or services.
|
|
5
|
+
*
|
|
6
|
+
* Invoices are distinct from Contracts - a Contract is an agreement,
|
|
7
|
+
* while an Invoice is the billing document requesting payment.
|
|
8
|
+
*
|
|
9
|
+
* Invoices integrate with:
|
|
10
|
+
* - `@happyvertical/smrt-ledgers` for revenue recognition (double-entry accounting)
|
|
11
|
+
* - `@happyvertical/accounting` SDK for syncing with external providers (QBO, Stripe)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Create an invoice
|
|
16
|
+
* const invoice = await invoices.create({
|
|
17
|
+
* customerId: customer.id,
|
|
18
|
+
* invoiceNumber: await invoices.generateInvoiceNumber(),
|
|
19
|
+
* issueDate: new Date(),
|
|
20
|
+
* dueDate: addDays(new Date(), 30),
|
|
21
|
+
* subtotal: 1000,
|
|
22
|
+
* taxAmount: 50,
|
|
23
|
+
* totalAmount: 1050,
|
|
24
|
+
* currency: 'CAD'
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* // Recognize revenue in ledger
|
|
28
|
+
* await invoice.recognizeRevenue({
|
|
29
|
+
* arAccountId: arAccount.id,
|
|
30
|
+
* revenueAccountId: revenueAccount.id,
|
|
31
|
+
* taxAccountId: taxAccount.id
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class Invoice extends SmrtObject {
|
|
36
|
+
/**
|
|
37
|
+
* Tenant ID for multi-tenant isolation
|
|
38
|
+
* Nullable to support both tenant-scoped and global invoices
|
|
39
|
+
*/
|
|
40
|
+
tenantId: string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Customer this invoice is for
|
|
43
|
+
*/
|
|
44
|
+
customerId: string;
|
|
45
|
+
/**
|
|
46
|
+
* Optional link to Contract (cross-package reference)
|
|
47
|
+
*/
|
|
48
|
+
contractId: string;
|
|
49
|
+
/**
|
|
50
|
+
* Invoice number (e.g., INV-2025-0001)
|
|
51
|
+
* Generated via InvoiceCollection.generateInvoiceNumber()
|
|
52
|
+
*/
|
|
53
|
+
invoiceNumber: string;
|
|
54
|
+
/**
|
|
55
|
+
* External reference (e.g., customer PO number)
|
|
56
|
+
*/
|
|
57
|
+
reference: string;
|
|
58
|
+
/**
|
|
59
|
+
* Date invoice was issued
|
|
60
|
+
*/
|
|
61
|
+
issueDate: Date;
|
|
62
|
+
/**
|
|
63
|
+
* Payment due date
|
|
64
|
+
*/
|
|
65
|
+
dueDate: Date;
|
|
66
|
+
/**
|
|
67
|
+
* Date invoice was fully paid
|
|
68
|
+
*/
|
|
69
|
+
paidDate: Date | null;
|
|
70
|
+
/**
|
|
71
|
+
* Subtotal before tax
|
|
72
|
+
*/
|
|
73
|
+
subtotal: number;
|
|
74
|
+
/**
|
|
75
|
+
* Tax amount
|
|
76
|
+
*/
|
|
77
|
+
taxAmount: number;
|
|
78
|
+
/**
|
|
79
|
+
* Total amount due (subtotal + tax)
|
|
80
|
+
*/
|
|
81
|
+
totalAmount: number;
|
|
82
|
+
/**
|
|
83
|
+
* Amount paid (sum of PaymentAllocations)
|
|
84
|
+
*/
|
|
85
|
+
amountPaid: number;
|
|
86
|
+
/**
|
|
87
|
+
* Currency code (ISO 4217)
|
|
88
|
+
*/
|
|
89
|
+
currency: string;
|
|
90
|
+
/**
|
|
91
|
+
* Current invoice status
|
|
92
|
+
*/
|
|
93
|
+
status: InvoiceStatus;
|
|
94
|
+
/**
|
|
95
|
+
* Journal ID for AR recognition (cross-package ref to smrt-ledgers)
|
|
96
|
+
*/
|
|
97
|
+
arJournalId: string;
|
|
98
|
+
/**
|
|
99
|
+
* Journal ID for revenue recognition (cross-package ref to smrt-ledgers)
|
|
100
|
+
*/
|
|
101
|
+
revenueJournalId: string;
|
|
102
|
+
/**
|
|
103
|
+
* External ID in accounting provider (e.g., QBO invoice ID)
|
|
104
|
+
*/
|
|
105
|
+
externalId: string;
|
|
106
|
+
/**
|
|
107
|
+
* Customer's external ID in accounting provider.
|
|
108
|
+
* Used to link invoice to customer in external system.
|
|
109
|
+
*/
|
|
110
|
+
customerExternalId: string;
|
|
111
|
+
/**
|
|
112
|
+
* Accounting provider name ('quickbooks' | 'stripe' | etc.)
|
|
113
|
+
*/
|
|
114
|
+
externalProvider: string;
|
|
115
|
+
/**
|
|
116
|
+
* When invoice was last synced to provider
|
|
117
|
+
*/
|
|
118
|
+
syncedAt: Date | null;
|
|
119
|
+
/**
|
|
120
|
+
* When invoice was sent to customer
|
|
121
|
+
*/
|
|
122
|
+
sentAt: Date | null;
|
|
123
|
+
/**
|
|
124
|
+
* When customer viewed the invoice
|
|
125
|
+
*/
|
|
126
|
+
viewedAt: Date | null;
|
|
127
|
+
/**
|
|
128
|
+
* Number of payment reminders sent
|
|
129
|
+
*/
|
|
130
|
+
remindersSent: number;
|
|
131
|
+
/**
|
|
132
|
+
* When last reminder was sent
|
|
133
|
+
*/
|
|
134
|
+
lastReminderAt: Date | null;
|
|
135
|
+
/**
|
|
136
|
+
* Internal notes (not shown to customer)
|
|
137
|
+
*/
|
|
138
|
+
notes: string;
|
|
139
|
+
/**
|
|
140
|
+
* Notes shown to customer on invoice
|
|
141
|
+
*/
|
|
142
|
+
customerNotes: string;
|
|
143
|
+
/**
|
|
144
|
+
* Payment terms text
|
|
145
|
+
*/
|
|
146
|
+
terms: string;
|
|
147
|
+
constructor(options?: any);
|
|
148
|
+
/**
|
|
149
|
+
* Capture the persisted status the row was loaded with, so the save-time
|
|
150
|
+
* transition guard can reject illegal status flips made via raw field
|
|
151
|
+
* assignment (mass-assignment on a generated update route, a stale caller,
|
|
152
|
+
* etc.). Only rows that already exist in the database carry a "prior"
|
|
153
|
+
* status — freshly-constructed (not-yet-saved) invoices have no prior and
|
|
154
|
+
* may start in any status.
|
|
155
|
+
*/
|
|
156
|
+
initialize(): Promise<this>;
|
|
157
|
+
/**
|
|
158
|
+
* Recompute and validate financial fields before every write so forged
|
|
159
|
+
* totals, negative amounts, and illegal status flips can't be persisted via
|
|
160
|
+
* raw mass-assignment on the generated CRUD routes.
|
|
161
|
+
*
|
|
162
|
+
* Behaviour:
|
|
163
|
+
* - **Totals are authoritative from line items.** When the invoice is
|
|
164
|
+
* persisted and has line items, `subtotal` / `taxAmount` / `totalAmount`
|
|
165
|
+
* are recomputed from those items, overriding whatever the caller sent.
|
|
166
|
+
* This blocks "create real line items but claim a tiny total" forgery.
|
|
167
|
+
* - **Without line items**, the caller-supplied totals are accepted but the
|
|
168
|
+
* `totalAmount === subtotal + taxAmount` arithmetic invariant is enforced.
|
|
169
|
+
* - **amountPaid is derived/validated.** When persisted, it is recomputed
|
|
170
|
+
* from PaymentAllocations rather than trusted from the caller. It may
|
|
171
|
+
* never exceed `totalAmount` (beyond rounding tolerance).
|
|
172
|
+
* - **Non-negativity** is enforced on all four amounts.
|
|
173
|
+
* - **Status transitions** are validated against the prior persisted status.
|
|
174
|
+
*/
|
|
175
|
+
save(): Promise<this>;
|
|
176
|
+
/**
|
|
177
|
+
* Resolve the AUTHORITATIVE prior status (S5 audit #1390 round 4). The
|
|
178
|
+
* {@link loadedInvoiceStatus} WeakMap is only populated when {@link initialize}
|
|
179
|
+
* hydrated the row, so a `create({ id: <existing>, _skipLoad: true })` upsert
|
|
180
|
+
* yields an instance whose WeakMap entry is missing — trusting it would treat
|
|
181
|
+
* the write as a brand-new row and skip the transition guard entirely. Read
|
|
182
|
+
* the persisted row's status directly so a create-onto-existing is correctly
|
|
183
|
+
* treated as an update. `undefined` means no row exists (genuinely new).
|
|
184
|
+
*/
|
|
185
|
+
private resolvePriorStatus;
|
|
186
|
+
/**
|
|
187
|
+
* Recompute subtotal/tax/total from line items (when present) and derive
|
|
188
|
+
* amountPaid from PaymentAllocations. Falls back to the arithmetic invariant
|
|
189
|
+
* when the invoice has no line items. Tolerant of smrt-ledgers being absent
|
|
190
|
+
* (the dynamic imports stay inside the package).
|
|
191
|
+
*/
|
|
192
|
+
private recomputeAmountsForSave;
|
|
193
|
+
/**
|
|
194
|
+
* After amounts are recomputed and amountPaid is re-derived from allocations,
|
|
195
|
+
* assert the persisted `status` is consistent with the derived
|
|
196
|
+
* amountPaid-vs-totalAmount relationship. This blocks the raw
|
|
197
|
+
* `SENT → PAID with amountPaid=0` flip (and its inverse, claiming PARTIAL/SENT
|
|
198
|
+
* while fully allocated) that the status-transition map alone permits because
|
|
199
|
+
* SENT → PAID is a structurally legal edge.
|
|
200
|
+
*
|
|
201
|
+
* Only enforced for the payment-derived statuses (PAID / PARTIAL and the
|
|
202
|
+
* unpaid open states SENT / VIEWED). Lifecycle statuses that aren't a
|
|
203
|
+
* function of amountPaid — DRAFT, OVERDUE, CANCELLED, WRITTEN_OFF — are left
|
|
204
|
+
* to their own transition rules.
|
|
205
|
+
*/
|
|
206
|
+
private assertPaymentStatusConsistent;
|
|
207
|
+
/**
|
|
208
|
+
* Enforce `totalAmount === subtotal + taxAmount` (within rounding tolerance).
|
|
209
|
+
* Used when the invoice has no line items to recompute from.
|
|
210
|
+
*/
|
|
211
|
+
private assertTotalArithmetic;
|
|
212
|
+
/**
|
|
213
|
+
* Reject negative financial values and an amountPaid that exceeds the total
|
|
214
|
+
* (beyond rounding tolerance — overpayment is modelled elsewhere, not by
|
|
215
|
+
* letting amountPaid float above the invoice total).
|
|
216
|
+
*/
|
|
217
|
+
private assertNonNegativeAmounts;
|
|
218
|
+
/**
|
|
219
|
+
* Reject an illegal status flip done via raw field assignment. Compares the
|
|
220
|
+
* about-to-be-written status against the status the row was loaded with.
|
|
221
|
+
* No-op transitions (status unchanged) and brand-new rows are always allowed.
|
|
222
|
+
*/
|
|
223
|
+
private assertStatusTransition;
|
|
224
|
+
/**
|
|
225
|
+
* Check if invoice is a draft
|
|
226
|
+
*/
|
|
227
|
+
isDraft(): boolean;
|
|
228
|
+
/**
|
|
229
|
+
* Check if invoice has been sent
|
|
230
|
+
*/
|
|
231
|
+
isSent(): boolean;
|
|
232
|
+
/**
|
|
233
|
+
* Check if invoice is fully paid
|
|
234
|
+
*/
|
|
235
|
+
isPaid(): boolean;
|
|
236
|
+
/**
|
|
237
|
+
* Check if invoice is partially paid
|
|
238
|
+
*/
|
|
239
|
+
isPartial(): boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Check if invoice is overdue
|
|
242
|
+
*/
|
|
243
|
+
isOverdue(): boolean;
|
|
244
|
+
/**
|
|
245
|
+
* Get remaining amount due
|
|
246
|
+
*/
|
|
247
|
+
getAmountDue(): number;
|
|
248
|
+
/**
|
|
249
|
+
* Mark invoice as sent
|
|
250
|
+
*/
|
|
251
|
+
markSent(): void;
|
|
252
|
+
/**
|
|
253
|
+
* Record that the invoice was viewed by the customer.
|
|
254
|
+
*
|
|
255
|
+
* This method is idempotent - calling it multiple times will only
|
|
256
|
+
* record the first view time. Status only transitions to VIEWED if
|
|
257
|
+
* the current status is SENT (other statuses like PARTIAL or PAID
|
|
258
|
+
* are preserved).
|
|
259
|
+
*/
|
|
260
|
+
markViewed(): void;
|
|
261
|
+
/**
|
|
262
|
+
* Update payment amount and status.
|
|
263
|
+
*
|
|
264
|
+
* Called when PaymentAllocations change. Handles both forward transitions
|
|
265
|
+
* (SENT → PARTIAL → PAID) and reversals (PAID → PARTIAL → original status).
|
|
266
|
+
*
|
|
267
|
+
* Terminal statuses (CANCELLED, WRITTEN_OFF) are not modified.
|
|
268
|
+
*/
|
|
269
|
+
updatePaymentStatus(amountPaid: number): void;
|
|
270
|
+
/**
|
|
271
|
+
* Cancel the invoice
|
|
272
|
+
*/
|
|
273
|
+
cancel(): void;
|
|
274
|
+
/**
|
|
275
|
+
* Write off the invoice (bad debt)
|
|
276
|
+
*/
|
|
277
|
+
writeOff(): void;
|
|
278
|
+
/**
|
|
279
|
+
* Recognize revenue and create AR journal entry.
|
|
280
|
+
*
|
|
281
|
+
* Creates a balanced journal entry in smrt-ledgers:
|
|
282
|
+
* - Debit: Accounts Receivable (assets increase)
|
|
283
|
+
* - Credit: Revenue (revenue increases)
|
|
284
|
+
* - Credit: Tax Payable (liability increases, if taxAmount > 0)
|
|
285
|
+
*
|
|
286
|
+
* **Note**: This method saves the invoice after setting arJournalId.
|
|
287
|
+
*
|
|
288
|
+
* @param options - Account IDs for the journal entry
|
|
289
|
+
* @returns The created journal
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```typescript
|
|
293
|
+
* const journal = await invoice.recognizeRevenue({
|
|
294
|
+
* arAccountId: '1120',
|
|
295
|
+
* revenueAccountId: '4100',
|
|
296
|
+
* taxAccountId: '2130'
|
|
297
|
+
* });
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
recognizeRevenue(options: RecognizeRevenueOptions): Promise<any>;
|
|
301
|
+
/**
|
|
302
|
+
* Get the AR journal entry (if revenue was recognized)
|
|
303
|
+
*/
|
|
304
|
+
getArJournal(): Promise<any | null>;
|
|
305
|
+
/**
|
|
306
|
+
* Convert to InvoiceInput for SDK accounting provider sync.
|
|
307
|
+
*
|
|
308
|
+
* Fetches line items and maps all fields to the format expected
|
|
309
|
+
* by @happyvertical/accounting providers.
|
|
310
|
+
*
|
|
311
|
+
* @returns InvoiceInput compatible with @happyvertical/accounting
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```typescript
|
|
315
|
+
* const provider = await getAccountingProvider({ type: 'quickbooks', ... });
|
|
316
|
+
* const input = await invoice.toAccountingInput();
|
|
317
|
+
* const result = await provider.invoices.push(input);
|
|
318
|
+
* invoice.externalId = result.externalId;
|
|
319
|
+
* invoice.syncedAt = result.syncedAt;
|
|
320
|
+
* await invoice.save();
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
toAccountingInput(): Promise<any>;
|
|
324
|
+
}
|
|
325
|
+
export default Invoice;
|
|
326
|
+
//# sourceMappingURL=Invoice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Invoice.d.ts","sourceRoot":"","sources":["../../src/models/Invoice.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
/**
|
|
3
|
+
* InvoiceLineItem represents a single line item on an invoice.
|
|
4
|
+
*
|
|
5
|
+
* Line items contain details of what is being billed, including
|
|
6
|
+
* quantity, pricing, and optional source tracking (e.g., from ad campaigns).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const lineItem = await lineItems.create({
|
|
11
|
+
* invoiceId: invoice.id,
|
|
12
|
+
* description: 'Display Advertising - Summer Campaign',
|
|
13
|
+
* quantity: 50000, // impressions
|
|
14
|
+
* unitPrice: 0.01, // per impression
|
|
15
|
+
* taxRate: 0.05,
|
|
16
|
+
* sourceType: 'campaign',
|
|
17
|
+
* sourceId: 'campaign-uuid',
|
|
18
|
+
* periodStart: new Date('2025-06-01'),
|
|
19
|
+
* periodEnd: new Date('2025-06-30')
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare class InvoiceLineItem extends SmrtObject {
|
|
24
|
+
/**
|
|
25
|
+
* Tenant ID for multi-tenant isolation
|
|
26
|
+
* Nullable to support both tenant-scoped and global invoice line items
|
|
27
|
+
*/
|
|
28
|
+
tenantId: string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Parent invoice
|
|
31
|
+
*/
|
|
32
|
+
invoiceId: string;
|
|
33
|
+
/**
|
|
34
|
+
* Item description
|
|
35
|
+
*/
|
|
36
|
+
description: string;
|
|
37
|
+
/**
|
|
38
|
+
* SKU or item code
|
|
39
|
+
*/
|
|
40
|
+
sku: string;
|
|
41
|
+
/**
|
|
42
|
+
* Quantity (e.g., impressions, hours, units)
|
|
43
|
+
*/
|
|
44
|
+
quantity: number;
|
|
45
|
+
/**
|
|
46
|
+
* Unit price before discount
|
|
47
|
+
*/
|
|
48
|
+
unitPrice: number;
|
|
49
|
+
/**
|
|
50
|
+
* Discount amount (flat, not percentage)
|
|
51
|
+
*/
|
|
52
|
+
discount: number;
|
|
53
|
+
/**
|
|
54
|
+
* Tax rate as decimal (e.g., 0.05 for 5%)
|
|
55
|
+
*/
|
|
56
|
+
taxRate: number;
|
|
57
|
+
/**
|
|
58
|
+
* Calculated line amount
|
|
59
|
+
*/
|
|
60
|
+
amount: number;
|
|
61
|
+
/**
|
|
62
|
+
* Type of source ('campaign' | 'contract' | 'manual' | etc.)
|
|
63
|
+
*/
|
|
64
|
+
sourceType: string;
|
|
65
|
+
/**
|
|
66
|
+
* ID of the source (e.g., campaign ID, contract ID)
|
|
67
|
+
*/
|
|
68
|
+
sourceId: string;
|
|
69
|
+
/**
|
|
70
|
+
* Service period start (for time-based billing)
|
|
71
|
+
*/
|
|
72
|
+
periodStart: Date | null;
|
|
73
|
+
/**
|
|
74
|
+
* Service period end (for time-based billing)
|
|
75
|
+
*/
|
|
76
|
+
periodEnd: Date | null;
|
|
77
|
+
/**
|
|
78
|
+
* Revenue account ID (cross-package ref to smrt-ledgers)
|
|
79
|
+
* Used for revenue recognition to specific accounts
|
|
80
|
+
*/
|
|
81
|
+
revenueAccountId: string;
|
|
82
|
+
/**
|
|
83
|
+
* Sort order within the invoice
|
|
84
|
+
*/
|
|
85
|
+
sortOrder: number;
|
|
86
|
+
constructor(options?: any);
|
|
87
|
+
/**
|
|
88
|
+
* Calculate the line amount.
|
|
89
|
+
*
|
|
90
|
+
* Formula: (quantity * unitPrice - discount) * (1 + taxRate)
|
|
91
|
+
*
|
|
92
|
+
* Tax is calculated on the discounted subtotal. This follows the common
|
|
93
|
+
* "discount before tax" approach used in most North American jurisdictions.
|
|
94
|
+
* For jurisdictions requiring different tax calculation methods, override
|
|
95
|
+
* this method or calculate amounts externally.
|
|
96
|
+
*/
|
|
97
|
+
calculateAmount(): number;
|
|
98
|
+
/**
|
|
99
|
+
* Get subtotal (before tax)
|
|
100
|
+
*/
|
|
101
|
+
getSubtotal(): number;
|
|
102
|
+
/**
|
|
103
|
+
* Get tax amount
|
|
104
|
+
*/
|
|
105
|
+
getTaxAmount(): number;
|
|
106
|
+
/**
|
|
107
|
+
* Check if line item has source tracking
|
|
108
|
+
*/
|
|
109
|
+
hasSource(): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Check if line item has a service period
|
|
112
|
+
*/
|
|
113
|
+
hasPeriod(): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Convert to line item format for SDK accounting provider
|
|
116
|
+
*/
|
|
117
|
+
toAccountingLineItem(): any;
|
|
118
|
+
}
|
|
119
|
+
export default InvoiceLineItem;
|
|
120
|
+
//# sourceMappingURL=InvoiceLineItem.d.ts.map
|
|
@@ -0,0 +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;AAGlC;;;;;;;;;;;;;;;;;;;;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;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAK;IAErB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAK;IAEtB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAK;IAErB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAK;IAEpB;;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,GAAQ;IAsB7B;;;;;;;;;OASG;IACH,eAAe,IAAI,MAAM;IAMzB;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,oBAAoB,IAAI,GAAG;CAa5B;AAED,eAAe,eAAe,CAAC"}
|