@mj-biz-apps/orders-core-entities-server 5.18.0 → 5.20.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/AdoptExternalInvoiceOperation.d.ts +33 -0
- package/dist/AdoptExternalInvoiceOperation.d.ts.map +1 -0
- package/dist/AdoptExternalInvoiceOperation.js +188 -0
- package/dist/AdoptExternalInvoiceOperation.js.map +1 -0
- package/dist/BaseInvoiceRail.d.ts +159 -0
- package/dist/BaseInvoiceRail.d.ts.map +1 -0
- package/dist/BaseInvoiceRail.js +41 -0
- package/dist/BaseInvoiceRail.js.map +1 -0
- package/dist/BasePaymentProvider.d.ts +10 -0
- package/dist/BasePaymentProvider.d.ts.map +1 -1
- package/dist/BasePaymentProvider.js +10 -0
- package/dist/BasePaymentProvider.js.map +1 -1
- package/dist/BillComGateway.d.ts +82 -0
- package/dist/BillComGateway.d.ts.map +1 -0
- package/dist/BillComGateway.js +164 -0
- package/dist/BillComGateway.js.map +1 -0
- package/dist/BillComInvoiceRail.d.ts +30 -0
- package/dist/BillComInvoiceRail.d.ts.map +1 -0
- package/dist/BillComInvoiceRail.js +248 -0
- package/dist/BillComInvoiceRail.js.map +1 -0
- package/dist/BillComPaymentProvider.d.ts +24 -0
- package/dist/BillComPaymentProvider.d.ts.map +1 -0
- package/dist/BillComPaymentProvider.js +82 -0
- package/dist/BillComPaymentProvider.js.map +1 -0
- package/dist/BillComWebhook.d.ts +54 -0
- package/dist/BillComWebhook.d.ts.map +1 -0
- package/dist/BillComWebhook.js +96 -0
- package/dist/BillComWebhook.js.map +1 -0
- package/dist/CancelExternalInvoiceOperation.d.ts +33 -0
- package/dist/CancelExternalInvoiceOperation.d.ts.map +1 -0
- package/dist/CancelExternalInvoiceOperation.js +130 -0
- package/dist/CancelExternalInvoiceOperation.js.map +1 -0
- package/dist/CancelSubscriptionOperation.d.ts.map +1 -1
- package/dist/CancelSubscriptionOperation.js +13 -0
- package/dist/CancelSubscriptionOperation.js.map +1 -1
- package/dist/CapturePaymentOperation.d.ts.map +1 -1
- package/dist/CapturePaymentOperation.js +2 -0
- package/dist/CapturePaymentOperation.js.map +1 -1
- package/dist/ContractBalance.d.ts +150 -0
- package/dist/ContractBalance.d.ts.map +1 -1
- package/dist/ContractBalance.js +156 -0
- package/dist/ContractBalance.js.map +1 -1
- package/dist/DeliveryBehavior.d.ts +7 -1
- package/dist/DeliveryBehavior.d.ts.map +1 -1
- package/dist/DeliveryBehavior.js +8 -0
- package/dist/DeliveryBehavior.js.map +1 -1
- package/dist/DeliveryRecipientResolver.d.ts +7 -0
- package/dist/DeliveryRecipientResolver.d.ts.map +1 -1
- package/dist/DeliveryRecipientResolver.js +25 -0
- package/dist/DeliveryRecipientResolver.js.map +1 -1
- package/dist/ExternalInvoiceBehavior.d.ts +156 -0
- package/dist/ExternalInvoiceBehavior.d.ts.map +1 -0
- package/dist/ExternalInvoiceBehavior.js +267 -0
- package/dist/ExternalInvoiceBehavior.js.map +1 -0
- package/dist/GLAccountResolver.d.ts +28 -0
- package/dist/GLAccountResolver.d.ts.map +1 -1
- package/dist/GLAccountResolver.js +44 -0
- package/dist/GLAccountResolver.js.map +1 -1
- package/dist/GetExternalInvoicingWorklistOperation.d.ts +27 -0
- package/dist/GetExternalInvoicingWorklistOperation.d.ts.map +1 -0
- package/dist/GetExternalInvoicingWorklistOperation.js +187 -0
- package/dist/GetExternalInvoicingWorklistOperation.js.map +1 -0
- package/dist/GetProgressWorklistOperation.d.ts +21 -0
- package/dist/GetProgressWorklistOperation.d.ts.map +1 -0
- package/dist/GetProgressWorklistOperation.js +132 -0
- package/dist/GetProgressWorklistOperation.js.map +1 -0
- package/dist/GiftCardEngine.d.ts +15 -0
- package/dist/GiftCardEngine.d.ts.map +1 -1
- package/dist/GiftCardEngine.js +58 -1
- package/dist/GiftCardEngine.js.map +1 -1
- package/dist/InstalmentInvoiceEntry.d.ts +44 -4
- package/dist/InstalmentInvoiceEntry.d.ts.map +1 -1
- package/dist/InstalmentInvoiceEntry.js +131 -66
- package/dist/InstalmentInvoiceEntry.js.map +1 -1
- package/dist/InvoiceBehavior.d.ts +30 -0
- package/dist/InvoiceBehavior.d.ts.map +1 -1
- package/dist/InvoiceBehavior.js +37 -1
- package/dist/InvoiceBehavior.js.map +1 -1
- package/dist/InvoiceBuilder.d.ts.map +1 -1
- package/dist/InvoiceBuilder.js +8 -3
- package/dist/InvoiceBuilder.js.map +1 -1
- package/dist/InvoiceRailResolver.d.ts +27 -0
- package/dist/InvoiceRailResolver.d.ts.map +1 -0
- package/dist/InvoiceRailResolver.js +114 -0
- package/dist/InvoiceRailResolver.js.map +1 -0
- package/dist/IssueExternalInvoiceOperation.d.ts +135 -0
- package/dist/IssueExternalInvoiceOperation.d.ts.map +1 -0
- package/dist/IssueExternalInvoiceOperation.js +580 -0
- package/dist/IssueExternalInvoiceOperation.js.map +1 -0
- package/dist/IssueInstalmentInvoiceOperation.d.ts.map +1 -1
- package/dist/IssueInstalmentInvoiceOperation.js +33 -4
- package/dist/IssueInstalmentInvoiceOperation.js.map +1 -1
- package/dist/OrderEntityServer.d.ts +76 -1
- package/dist/OrderEntityServer.d.ts.map +1 -1
- package/dist/OrderEntityServer.js +300 -32
- package/dist/OrderEntityServer.js.map +1 -1
- package/dist/OrderHeaderPaymentScheduleEntityServer.d.ts +19 -1
- package/dist/OrderHeaderPaymentScheduleEntityServer.d.ts.map +1 -1
- package/dist/OrderHeaderPaymentScheduleEntityServer.js +35 -2
- package/dist/OrderHeaderPaymentScheduleEntityServer.js.map +1 -1
- package/dist/OrderJournalEntryFactory.d.ts +72 -1
- package/dist/OrderJournalEntryFactory.d.ts.map +1 -1
- package/dist/OrderJournalEntryFactory.js +250 -38
- package/dist/OrderJournalEntryFactory.js.map +1 -1
- package/dist/OrderLineProgressMeasurementEntityServer.d.ts +47 -0
- package/dist/OrderLineProgressMeasurementEntityServer.d.ts.map +1 -0
- package/dist/OrderLineProgressMeasurementEntityServer.js +107 -0
- package/dist/OrderLineProgressMeasurementEntityServer.js.map +1 -0
- package/dist/PaymentAllocationFactory.d.ts +47 -0
- package/dist/PaymentAllocationFactory.d.ts.map +1 -1
- package/dist/PaymentAllocationFactory.js +112 -24
- package/dist/PaymentAllocationFactory.js.map +1 -1
- package/dist/PaymentAllocationInputs.d.ts +30 -1
- package/dist/PaymentAllocationInputs.d.ts.map +1 -1
- package/dist/PaymentAllocationInputs.js +96 -2
- package/dist/PaymentAllocationInputs.js.map +1 -1
- package/dist/PaymentHeaderEntityServer.d.ts +19 -0
- package/dist/PaymentHeaderEntityServer.d.ts.map +1 -1
- package/dist/PaymentHeaderEntityServer.js +119 -13
- package/dist/PaymentHeaderEntityServer.js.map +1 -1
- package/dist/PaymentLineEntityServer.d.ts.map +1 -1
- package/dist/PaymentLineEntityServer.js +22 -6
- package/dist/PaymentLineEntityServer.js.map +1 -1
- package/dist/PaymentReversalFactory.d.ts +12 -2
- package/dist/PaymentReversalFactory.d.ts.map +1 -1
- package/dist/PaymentReversalFactory.js +5 -2
- package/dist/PaymentReversalFactory.js.map +1 -1
- package/dist/PaymentScheduleBehavior.d.ts +138 -2
- package/dist/PaymentScheduleBehavior.d.ts.map +1 -1
- package/dist/PaymentScheduleBehavior.js +215 -2
- package/dist/PaymentScheduleBehavior.js.map +1 -1
- package/dist/PollExternalPaymentsOperation.d.ts +39 -0
- package/dist/PollExternalPaymentsOperation.d.ts.map +1 -0
- package/dist/PollExternalPaymentsOperation.js +478 -0
- package/dist/PollExternalPaymentsOperation.js.map +1 -0
- package/dist/RecordProgressOperation.d.ts +104 -0
- package/dist/RecordProgressOperation.d.ts.map +1 -0
- package/dist/RecordProgressOperation.js +348 -0
- package/dist/RecordProgressOperation.js.map +1 -0
- package/dist/RevenueRecognition.d.ts +67 -0
- package/dist/RevenueRecognition.d.ts.map +1 -1
- package/dist/RevenueRecognition.js +58 -1
- package/dist/RevenueRecognition.js.map +1 -1
- package/dist/ReversalBehavior.d.ts +17 -1
- package/dist/ReversalBehavior.d.ts.map +1 -1
- package/dist/ReversalBehavior.js +1 -1
- package/dist/ReversalBehavior.js.map +1 -1
- package/dist/ReversalResolver.d.ts +43 -0
- package/dist/ReversalResolver.d.ts.map +1 -1
- package/dist/ReversalResolver.js +87 -3
- package/dist/ReversalResolver.js.map +1 -1
- package/dist/SendExternalInvoicesOperation.d.ts +25 -0
- package/dist/SendExternalInvoicesOperation.d.ts.map +1 -0
- package/dist/SendExternalInvoicesOperation.js +110 -0
- package/dist/SendExternalInvoicesOperation.js.map +1 -0
- package/dist/SpawnRenewalsOperation.d.ts +11 -4
- package/dist/SpawnRenewalsOperation.d.ts.map +1 -1
- package/dist/SpawnRenewalsOperation.js +47 -7
- package/dist/SpawnRenewalsOperation.js.map +1 -1
- package/dist/entity-names.d.ts +21 -0
- package/dist/entity-names.d.ts.map +1 -1
- package/dist/entity-names.js +21 -0
- package/dist/entity-names.js.map +1 -1
- package/dist/index.d.ts +29 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -3
- package/dist/index.js.map +1 -1
- package/dist/instalmentIssueGuard.d.ts +27 -0
- package/dist/instalmentIssueGuard.d.ts.map +1 -0
- package/dist/instalmentIssueGuard.js +34 -0
- package/dist/instalmentIssueGuard.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Orders.AdoptExternalInvoice` — resolve a claimed unit by attaching the invoice the rail already holds.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS EXISTS. A send that times out leaves the unit claimed (`Sending`) deliberately: the rail
|
|
5
|
+
* may or may not have committed the invoice, and retrying blindly is how one billing unit becomes two
|
|
6
|
+
* invoices in a customer's inbox. Resolving that is a person's job and it has exactly two answers.
|
|
7
|
+
* The rail has nothing → re-issue with `AllowReissue`, which supersedes the claim. The rail HAS the
|
|
8
|
+
* invoice → bring its reference here.
|
|
9
|
+
*
|
|
10
|
+
* Until this operation existed only the first answer was implementable; the second was a hand edit in
|
|
11
|
+
* Explorer, which the claimed row's own message nonetheless told people to perform.
|
|
12
|
+
*
|
|
13
|
+
* IT READS THE INVOICE BACK AND REFUSES THREE WAYS, because a person is typing a reference off a
|
|
14
|
+
* screen and every one of these is a plausible slip:
|
|
15
|
+
* · ARCHIVED — an invoice the rail has withdrawn is not one the customer holds. This is the slip
|
|
16
|
+
* the total check cannot catch: a previously cancelled invoice for THIS unit ties exactly, by
|
|
17
|
+
* construction, so adopting it would mark the unit Sent for ever against a document nobody has.
|
|
18
|
+
* The unit would then be skipped by the sweep, refused by `CanSend`, and never billed.
|
|
19
|
+
* · A DIFFERENT DOCUMENT — the rail carries our own `DocumentNumber` as its invoice number (the
|
|
20
|
+
* send sets it), so a reference belonging to some other invoice is identifiable without guessing.
|
|
21
|
+
* Compared only when the rail reports one; a rail that does not is left to the total check.
|
|
22
|
+
* · A TOTAL THAT DOES NOT TIE — the same figure the send path proves, from the other direction.
|
|
23
|
+
*
|
|
24
|
+
* @module @mj-biz-apps/orders-core-entities-server
|
|
25
|
+
*/
|
|
26
|
+
import { type IMetadataProvider, type UserInfo } from '@memberjunction/core';
|
|
27
|
+
import { OrdersAdoptExternalInvoiceOperation as OrdersAdoptExternalInvoiceOperationBase, type OrdersAdoptExternalInvoiceInput, type OrdersAdoptExternalInvoiceOutput } from '@mj-biz-apps/orders-entities';
|
|
28
|
+
export declare class AdoptExternalInvoiceOperation extends OrdersAdoptExternalInvoiceOperationBase {
|
|
29
|
+
protected InternalExecute(input: OrdersAdoptExternalInvoiceInput, provider: IMetadataProvider, user: UserInfo): Promise<OrdersAdoptExternalInvoiceOutput>;
|
|
30
|
+
}
|
|
31
|
+
/** Registers {@link AdoptExternalInvoiceOperation}. Called from the server bootstrap. */
|
|
32
|
+
export declare function LoadAdoptExternalInvoiceOperation(): void;
|
|
33
|
+
//# sourceMappingURL=AdoptExternalInvoiceOperation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdoptExternalInvoiceOperation.d.ts","sourceRoot":"","sources":["../src/AdoptExternalInvoiceOperation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAA6C,KAAK,iBAAiB,EAAyB,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE/I,OAAO,EACH,mCAAmC,IAAI,uCAAuC,EAC9E,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,EACxC,MAAM,8BAA8B,CAAC;AActC,qBACa,6BAA8B,SAAQ,uCAAuC;cACtE,eAAe,CAC3B,KAAK,EAAE,+BAA+B,EACtC,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,QAAQ,GACf,OAAO,CAAC,gCAAgC,CAAC;CAqI/C;AAiBD,yFAAyF;AACzF,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* `Orders.AdoptExternalInvoice` — resolve a claimed unit by attaching the invoice the rail already holds.
|
|
9
|
+
*
|
|
10
|
+
* WHY THIS EXISTS. A send that times out leaves the unit claimed (`Sending`) deliberately: the rail
|
|
11
|
+
* may or may not have committed the invoice, and retrying blindly is how one billing unit becomes two
|
|
12
|
+
* invoices in a customer's inbox. Resolving that is a person's job and it has exactly two answers.
|
|
13
|
+
* The rail has nothing → re-issue with `AllowReissue`, which supersedes the claim. The rail HAS the
|
|
14
|
+
* invoice → bring its reference here.
|
|
15
|
+
*
|
|
16
|
+
* Until this operation existed only the first answer was implementable; the second was a hand edit in
|
|
17
|
+
* Explorer, which the claimed row's own message nonetheless told people to perform.
|
|
18
|
+
*
|
|
19
|
+
* IT READS THE INVOICE BACK AND REFUSES THREE WAYS, because a person is typing a reference off a
|
|
20
|
+
* screen and every one of these is a plausible slip:
|
|
21
|
+
* · ARCHIVED — an invoice the rail has withdrawn is not one the customer holds. This is the slip
|
|
22
|
+
* the total check cannot catch: a previously cancelled invoice for THIS unit ties exactly, by
|
|
23
|
+
* construction, so adopting it would mark the unit Sent for ever against a document nobody has.
|
|
24
|
+
* The unit would then be skipped by the sweep, refused by `CanSend`, and never billed.
|
|
25
|
+
* · A DIFFERENT DOCUMENT — the rail carries our own `DocumentNumber` as its invoice number (the
|
|
26
|
+
* send sets it), so a reference belonging to some other invoice is identifiable without guessing.
|
|
27
|
+
* Compared only when the rail reports one; a rail that does not is left to the total check.
|
|
28
|
+
* · A TOTAL THAT DOES NOT TIE — the same figure the send path proves, from the other direction.
|
|
29
|
+
*
|
|
30
|
+
* @module @mj-biz-apps/orders-core-entities-server
|
|
31
|
+
*/
|
|
32
|
+
import { BaseRemotableOperation, LogError, RunView } from '@memberjunction/core';
|
|
33
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
34
|
+
import { OrdersAdoptExternalInvoiceOperation as OrdersAdoptExternalInvoiceOperationBase, } from '@mj-biz-apps/orders-entities';
|
|
35
|
+
import { DecideAdoption, money } from './ExternalInvoiceBehavior.js';
|
|
36
|
+
import { ResolveInvoiceRail } from './InvoiceRailResolver.js';
|
|
37
|
+
import { ORDER_HEADER_ENTITY } from './entity-names.js';
|
|
38
|
+
import { LoadExternalInvoiceByID, stampHeaderDocumentNumber, stampScheduleRow, updateExternalInvoice, } from './IssueExternalInvoiceOperation.js';
|
|
39
|
+
import { RequireUUID } from './sql-guards.js';
|
|
40
|
+
let AdoptExternalInvoiceOperation = class AdoptExternalInvoiceOperation extends OrdersAdoptExternalInvoiceOperationBase {
|
|
41
|
+
async InternalExecute(input, provider, user) {
|
|
42
|
+
try {
|
|
43
|
+
const id = RequireUUID(input?.ExternalInvoiceID, 'ExternalInvoiceID');
|
|
44
|
+
const ref = (input?.ExternalInvoiceRef ?? '').trim();
|
|
45
|
+
const preview = !!input?.Preview;
|
|
46
|
+
if (!ref) {
|
|
47
|
+
return { Success: false, ResultCode: 'ERROR', Message: 'ExternalInvoiceRef is required: this operation exists to record the reference the rail already holds.' };
|
|
48
|
+
}
|
|
49
|
+
const row = await LoadExternalInvoiceByID(id, provider, user);
|
|
50
|
+
if (!row)
|
|
51
|
+
return { Success: false, ResultCode: 'ERROR', Message: `No external invoice with ID ${id}.` };
|
|
52
|
+
if (row.Status === 'Sent') {
|
|
53
|
+
return {
|
|
54
|
+
Success: row.ExternalInvoiceRef === ref,
|
|
55
|
+
ResultCode: 'ALREADY_ADOPTED',
|
|
56
|
+
Message: row.ExternalInvoiceRef === ref
|
|
57
|
+
? `${row.DocumentNumber} already carries ${ref}; nothing to do.`
|
|
58
|
+
: `${row.DocumentNumber} is already Sent as ${row.ExternalInvoiceRef}, not ${ref}. Refusing to repoint a live invoice — cancel it instead if it is wrong.`,
|
|
59
|
+
ExternalInvoiceID: row.ID,
|
|
60
|
+
ExternalInvoiceRef: row.ExternalInvoiceRef,
|
|
61
|
+
DocumentNumber: row.DocumentNumber,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (row.Status !== 'Sending') {
|
|
65
|
+
return {
|
|
66
|
+
Success: false,
|
|
67
|
+
ResultCode: 'NOT_CLAIMED',
|
|
68
|
+
Message: `${row.DocumentNumber} is ${row.Status}, not a claimed send. This operation resolves a send that was never confirmed; a ${row.Status.toLowerCase()} unit is issued again instead.`,
|
|
69
|
+
ExternalInvoiceID: row.ID,
|
|
70
|
+
DocumentNumber: row.DocumentNumber,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// The rail's own view decides this, not the person's typing.
|
|
74
|
+
const rail = await ResolveInvoiceRail(String(row.PaymentProviderID), provider, user);
|
|
75
|
+
const snap = await rail.GetInvoice(ref);
|
|
76
|
+
if (snap.Success === false) {
|
|
77
|
+
return { Success: false, ResultCode: 'ERROR', Message: `${rail.Config.Name} could not be read for ${ref}: ${snap.Reason}`, ExternalInvoiceID: row.ID, ExternalInvoiceRef: ref };
|
|
78
|
+
}
|
|
79
|
+
if (!snap.Value) {
|
|
80
|
+
return {
|
|
81
|
+
Success: false,
|
|
82
|
+
ResultCode: 'NOT_FOUND_ON_RAIL',
|
|
83
|
+
Message: `${rail.Config.Name} has no invoice ${ref}. If the rail really holds nothing for this unit, send it again with AllowReissue instead of adopting.`,
|
|
84
|
+
ExternalInvoiceID: row.ID,
|
|
85
|
+
ExternalInvoiceRef: ref,
|
|
86
|
+
DocumentNumber: row.DocumentNumber,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const total = money(snap.Value.Total);
|
|
90
|
+
const amount = money(Number(row.Amount ?? 0));
|
|
91
|
+
const verdict = DecideAdoption({
|
|
92
|
+
ExternalInvoiceRef: ref,
|
|
93
|
+
DocumentNumber: row.DocumentNumber,
|
|
94
|
+
UnitAmount: amount,
|
|
95
|
+
RailArchived: snap.Value.Archived,
|
|
96
|
+
RailInvoiceNumber: snap.Value.InvoiceNumber,
|
|
97
|
+
RailTotal: total,
|
|
98
|
+
RailName: rail.Config.Name,
|
|
99
|
+
});
|
|
100
|
+
if (!verdict.OK) {
|
|
101
|
+
return {
|
|
102
|
+
Success: false,
|
|
103
|
+
// An archived invoice is the rail holding nothing LIVE for this unit, which is the
|
|
104
|
+
// re-issue answer; the other two are the tie check refusing a mismatch.
|
|
105
|
+
ResultCode: verdict.Code === 'ARCHIVED' ? 'NOT_FOUND_ON_RAIL' : 'TIE_FAILED',
|
|
106
|
+
Message: verdict.Code === 'ARCHIVED' ? `${verdict.Reason} Send it again with AllowReissue.` : verdict.Reason,
|
|
107
|
+
ExternalInvoiceID: row.ID,
|
|
108
|
+
ExternalInvoiceRef: ref,
|
|
109
|
+
DocumentNumber: row.DocumentNumber,
|
|
110
|
+
ExternalTotal: total,
|
|
111
|
+
Amount: amount,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (preview) {
|
|
115
|
+
return {
|
|
116
|
+
Success: true,
|
|
117
|
+
ResultCode: 'PREVIEWED',
|
|
118
|
+
Message: `Would record ${ref} against ${row.DocumentNumber} for ${amount.toFixed(2)} and mark it Sent.`,
|
|
119
|
+
ExternalInvoiceID: row.ID,
|
|
120
|
+
ExternalInvoiceRef: ref,
|
|
121
|
+
DocumentNumber: row.DocumentNumber,
|
|
122
|
+
ExternalTotal: total,
|
|
123
|
+
Amount: amount,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const now = new Date();
|
|
127
|
+
await updateExternalInvoice(provider, user, String(row.ID), {
|
|
128
|
+
Status: 'Sent',
|
|
129
|
+
ExternalInvoiceRef: ref,
|
|
130
|
+
// The rail issued it at some unknown earlier moment; this is when we learned of it.
|
|
131
|
+
SentAt: row.SentAt ?? now,
|
|
132
|
+
ExternalTotal: total,
|
|
133
|
+
ExternalDueAmount: money(snap.Value.DueAmount),
|
|
134
|
+
ExternalStatus: snap.Value.Status,
|
|
135
|
+
LastSyncedAt: now,
|
|
136
|
+
LastError: null,
|
|
137
|
+
});
|
|
138
|
+
// THE SAME DENORMALISATION A SEND PERFORMS (step 9 of the issue path, the #239/#242
|
|
139
|
+
// contract). Without it an adopted instalment reads as never sent on its own row and on
|
|
140
|
+
// the order header, which is where a person looks — the worklist is unaffected either way
|
|
141
|
+
// because it keys off this table, so the inconsistency would have been silent.
|
|
142
|
+
if (row.OrderHeaderPaymentScheduleID) {
|
|
143
|
+
await stampScheduleRow(provider, user, String(row.OrderHeaderPaymentScheduleID), {
|
|
144
|
+
ExternalSystem: rail.Config.TypeCode,
|
|
145
|
+
ExternalInvoiceRef: ref,
|
|
146
|
+
SentAt: row.SentAt ? new Date(row.SentAt) : now,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const header = await loadHeaderStampTarget(String(row.OrderHeaderID), provider, user);
|
|
150
|
+
if (header)
|
|
151
|
+
await stampHeaderDocumentNumber(provider, user, header, rail.Config.PaymentProviderID, String(row.DocumentNumber));
|
|
152
|
+
return {
|
|
153
|
+
Success: true,
|
|
154
|
+
ResultCode: 'ADOPTED',
|
|
155
|
+
Message: `${row.DocumentNumber} now carries ${rail.Config.Name} invoice ${ref} for ${amount.toFixed(2)}.`,
|
|
156
|
+
ExternalInvoiceID: row.ID,
|
|
157
|
+
ExternalInvoiceRef: ref,
|
|
158
|
+
DocumentNumber: row.DocumentNumber,
|
|
159
|
+
ExternalTotal: total,
|
|
160
|
+
Amount: amount,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
LogError(`Orders.AdoptExternalInvoice failed: ${err}`);
|
|
165
|
+
return { Success: false, ResultCode: 'ERROR', Message: err instanceof Error ? err.message : String(err) };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
AdoptExternalInvoiceOperation = __decorate([
|
|
170
|
+
RegisterClass(BaseRemotableOperation, 'Orders.AdoptExternalInvoice')
|
|
171
|
+
], AdoptExternalInvoiceOperation);
|
|
172
|
+
export { AdoptExternalInvoiceOperation };
|
|
173
|
+
/** Just enough of the order for the display-only header stamp; a miss skips the stamp, never the adopt. */
|
|
174
|
+
async function loadHeaderStampTarget(orderID, provider, user) {
|
|
175
|
+
const rv = new RunView(provider);
|
|
176
|
+
const r = await rv.RunView({
|
|
177
|
+
EntityName: ORDER_HEADER_ENTITY,
|
|
178
|
+
ExtraFilter: `ID = '${RequireUUID(orderID, 'OrderHeaderID')}'`,
|
|
179
|
+
Fields: ['ID', 'OrderNumber', 'ExternalDocumentNumber'],
|
|
180
|
+
ResultType: 'simple',
|
|
181
|
+
}, user);
|
|
182
|
+
return r.Results?.[0] ?? null;
|
|
183
|
+
}
|
|
184
|
+
/** Registers {@link AdoptExternalInvoiceOperation}. Called from the server bootstrap. */
|
|
185
|
+
export function LoadAdoptExternalInvoiceOperation() {
|
|
186
|
+
void AdoptExternalInvoiceOperation;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=AdoptExternalInvoiceOperation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdoptExternalInvoiceOperation.js","sourceRoot":"","sources":["../src/AdoptExternalInvoiceOperation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The outbound invoice seam — `BaseInvoiceRail`.
|
|
3
|
+
*
|
|
4
|
+
* A RAIL is the system a customer actually holds our invoice in and pays through: Bill.com today,
|
|
5
|
+
* possibly Business Central later. Orders remains the receivable of record; the rail is delivery and
|
|
6
|
+
* collection. This base names the five things a rail has to do and nothing else:
|
|
7
|
+
*
|
|
8
|
+
* EnsureCustomer our bill-to party → the rail's customer id
|
|
9
|
+
* IssueInvoice one billing unit → the rail's invoice id
|
|
10
|
+
* GetInvoice the rail's view of an invoice we issued (total, due, status, archived)
|
|
11
|
+
* CancelInvoice withdraw an unpaid invoice on the rail
|
|
12
|
+
* FetchPaymentsSince every receivable payment the rail has changed since a watermark
|
|
13
|
+
*
|
|
14
|
+
* WHY NOT `BaseDeliveryChannel`. That seam carries a rendered HTML document and email recipients; a
|
|
15
|
+
* rail needs structured facts (amount, due date, lines, the frozen document number) and hands back a
|
|
16
|
+
* reference we must persist. Different inputs, different outputs, different idempotency — so a
|
|
17
|
+
* different base (design §3, D-B1).
|
|
18
|
+
*
|
|
19
|
+
* WHY NOT `BasePaymentProvider`. That seam is about taking money at a till: intents, capture, refund.
|
|
20
|
+
* A rail issues documents and reports money that arrived on its own. The two share a type code and a
|
|
21
|
+
* `PaymentProvider` row so that "which Bill.com organisation is this company" is configured once.
|
|
22
|
+
*
|
|
23
|
+
* THE BASE IS NOT DECORATED, on purpose — the resolver detects "nothing registered under this code"
|
|
24
|
+
* by seeing the base class come back (same trick as `BaseDeliveryChannel`).
|
|
25
|
+
*
|
|
26
|
+
* REFUSAL IS A RESULT, NOT AN EXCEPTION. `RailResult` carries `Transient`, which is what lets the
|
|
27
|
+
* sweep retry a timeout and never retry "this customer has no email address".
|
|
28
|
+
*
|
|
29
|
+
* @module @mj-biz-apps/orders-core-entities-server
|
|
30
|
+
*/
|
|
31
|
+
import type { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
32
|
+
/** The bill-to party, flattened to what a rail's customer record needs. */
|
|
33
|
+
export interface RailCustomerFacts {
|
|
34
|
+
PartyKind: 'Organization' | 'Person';
|
|
35
|
+
/** Our party id — sent as the rail's account number so the link is recoverable from the rail side. */
|
|
36
|
+
PartyID: string;
|
|
37
|
+
Name: string;
|
|
38
|
+
Email: string | null;
|
|
39
|
+
AddressLines: string[];
|
|
40
|
+
City: string | null;
|
|
41
|
+
State: string | null;
|
|
42
|
+
PostalCode: string | null;
|
|
43
|
+
Country: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface RailInvoiceLine {
|
|
46
|
+
Description: string;
|
|
47
|
+
Quantity: number;
|
|
48
|
+
UnitPrice: number;
|
|
49
|
+
}
|
|
50
|
+
/** One billing unit, ready to send. Built by `ExternalInvoiceBehavior.BuildExternalInvoicePayload`. */
|
|
51
|
+
export interface RailInvoiceFacts {
|
|
52
|
+
/** The frozen document number — `ORD-1234`, `ORD-1234-2`. Sent as the rail's invoice number. */
|
|
53
|
+
DocumentNumber: string;
|
|
54
|
+
/** `YYYY-MM-DD`. */
|
|
55
|
+
InvoiceDate: string;
|
|
56
|
+
/** `YYYY-MM-DD`, or null for "on receipt". */
|
|
57
|
+
DueDate: string | null;
|
|
58
|
+
/** What the lines must total, to the cent. */
|
|
59
|
+
Amount: number;
|
|
60
|
+
ExternalCustomerRef: string;
|
|
61
|
+
Lines: RailInvoiceLine[];
|
|
62
|
+
Memo: string | null;
|
|
63
|
+
}
|
|
64
|
+
/** The rail's own view of an invoice we issued. */
|
|
65
|
+
export interface RailInvoiceSnapshot {
|
|
66
|
+
ExternalInvoiceRef: string;
|
|
67
|
+
InvoiceNumber: string | null;
|
|
68
|
+
Total: number;
|
|
69
|
+
/** What is still owed on the rail's books, net of applied credits and payments (cleared or scheduled). */
|
|
70
|
+
DueAmount: number;
|
|
71
|
+
/** Payment promised but not yet cleared. */
|
|
72
|
+
ScheduledAmount: number;
|
|
73
|
+
Status: string | null;
|
|
74
|
+
Archived: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** One receivable payment as the rail reports it. `InvoicePayments` is the fan-out to our invoices. */
|
|
77
|
+
export interface RailPaymentRecord {
|
|
78
|
+
ExternalPaymentRef: string;
|
|
79
|
+
ExternalCustomerRef: string | null;
|
|
80
|
+
Amount: number;
|
|
81
|
+
UnappliedAmount: number;
|
|
82
|
+
/** `YYYY-MM-DD` when known. */
|
|
83
|
+
PaymentDate: string | null;
|
|
84
|
+
/** The rail's status string, verbatim — classified by `ExternalPaymentBehavior`, never here. */
|
|
85
|
+
Status: string | null;
|
|
86
|
+
/** True when the rail moved the money itself; false when a person recorded money that arrived elsewhere. */
|
|
87
|
+
OnlinePayment: boolean | null;
|
|
88
|
+
/**
|
|
89
|
+
* ISO-4217 as the rail reports it, or null when it reports none.
|
|
90
|
+
*
|
|
91
|
+
* Orders books a capture in the receiving company's functional currency and applies no rate, so a
|
|
92
|
+
* payment in anything else must be REFUSED rather than booked one-for-one. Null is treated as
|
|
93
|
+
* "the rail did not say", which the poller resolves against the company rather than assuming.
|
|
94
|
+
*/
|
|
95
|
+
CurrencyCode: string | null;
|
|
96
|
+
ReceivablesType: string | null;
|
|
97
|
+
/** The rail's updated-time, ISO — the watermark candidate. */
|
|
98
|
+
UpdatedAt: string | null;
|
|
99
|
+
InvoicePayments: Array<{
|
|
100
|
+
ExternalInvoiceRef: string;
|
|
101
|
+
Amount: number;
|
|
102
|
+
PaymentDate: string | null;
|
|
103
|
+
}>;
|
|
104
|
+
/** The record as received, for the audit trail. */
|
|
105
|
+
Raw: Record<string, unknown>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Success carries the value; refusal carries a reason and whether trying again could change the
|
|
109
|
+
* answer. `Transient: true` is a timeout, a 5xx, a lost session. `Transient: false` is "the customer
|
|
110
|
+
* has no email" — retrying that is noise.
|
|
111
|
+
*/
|
|
112
|
+
export type RailResult<T> = {
|
|
113
|
+
Success: true;
|
|
114
|
+
Value: T;
|
|
115
|
+
} | {
|
|
116
|
+
Success: false;
|
|
117
|
+
Reason: string;
|
|
118
|
+
Transient: boolean;
|
|
119
|
+
};
|
|
120
|
+
/** What the resolver reads off the `PaymentProvider` row and hands to the rail. */
|
|
121
|
+
export interface InvoiceRailConfig {
|
|
122
|
+
PaymentProviderID: string;
|
|
123
|
+
TypeCode: string;
|
|
124
|
+
CompanyID: string;
|
|
125
|
+
Name: string;
|
|
126
|
+
IsLiveMode: boolean;
|
|
127
|
+
/** The `MJ: Company Integrations` row the connector resolves credentials from. */
|
|
128
|
+
CompanyIntegrationID: string | null;
|
|
129
|
+
}
|
|
130
|
+
export declare class BaseInvoiceRail {
|
|
131
|
+
Config: InvoiceRailConfig;
|
|
132
|
+
Provider?: IMetadataProvider;
|
|
133
|
+
User?: UserInfo;
|
|
134
|
+
/**
|
|
135
|
+
* Is this rail configured well enough to be called at all? Resolves the integration row and the
|
|
136
|
+
* credential's environment; makes NO network call. A refusal here is a CONFIGURATION fault the
|
|
137
|
+
* operations raise as an error (no row written, nothing marked Failed), so a bad provider row
|
|
138
|
+
* cannot poison every unit in a sweep — and a preview run surfaces it before go-live.
|
|
139
|
+
*/
|
|
140
|
+
CheckConfiguration(): Promise<RailResult<true>>;
|
|
141
|
+
EnsureCustomer(_facts: RailCustomerFacts): Promise<RailResult<{
|
|
142
|
+
ExternalCustomerRef: string;
|
|
143
|
+
}>>;
|
|
144
|
+
IssueInvoice(_facts: RailInvoiceFacts): Promise<RailResult<{
|
|
145
|
+
ExternalInvoiceRef: string;
|
|
146
|
+
}>>;
|
|
147
|
+
GetInvoice(_externalInvoiceRef: string): Promise<RailResult<RailInvoiceSnapshot | null>>;
|
|
148
|
+
CancelInvoice(_externalInvoiceRef: string): Promise<RailResult<{
|
|
149
|
+
Archived: true;
|
|
150
|
+
}>>;
|
|
151
|
+
FetchPaymentsSince(_watermark: string | null): Promise<RailResult<{
|
|
152
|
+
Payments: RailPaymentRecord[];
|
|
153
|
+
NewWatermark: string | null;
|
|
154
|
+
}>>;
|
|
155
|
+
protected notImplemented<T>(what: string): RailResult<T>;
|
|
156
|
+
}
|
|
157
|
+
/** Tree-shaking anchor for the base — keeps the class reachable for the resolver's fallback check. */
|
|
158
|
+
export declare function LoadBaseInvoiceRail(): void;
|
|
159
|
+
//# sourceMappingURL=BaseInvoiceRail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseInvoiceRail.d.ts","sourceRoot":"","sources":["../src/BaseInvoiceRail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class BaseInvoiceRail {
|
|
2
|
+
/**
|
|
3
|
+
* Is this rail configured well enough to be called at all? Resolves the integration row and the
|
|
4
|
+
* credential's environment; makes NO network call. A refusal here is a CONFIGURATION fault the
|
|
5
|
+
* operations raise as an error (no row written, nothing marked Failed), so a bad provider row
|
|
6
|
+
* cannot poison every unit in a sweep — and a preview run surfaces it before go-live.
|
|
7
|
+
*/
|
|
8
|
+
async CheckConfiguration() {
|
|
9
|
+
return { Success: true, Value: true };
|
|
10
|
+
}
|
|
11
|
+
async EnsureCustomer(_facts) {
|
|
12
|
+
return this.notImplemented('ensuring a customer');
|
|
13
|
+
}
|
|
14
|
+
async IssueInvoice(_facts) {
|
|
15
|
+
return this.notImplemented('issuing an invoice');
|
|
16
|
+
}
|
|
17
|
+
async GetInvoice(_externalInvoiceRef) {
|
|
18
|
+
return this.notImplemented('reading an invoice');
|
|
19
|
+
}
|
|
20
|
+
async CancelInvoice(_externalInvoiceRef) {
|
|
21
|
+
return this.notImplemented('cancelling an invoice');
|
|
22
|
+
}
|
|
23
|
+
async FetchPaymentsSince(_watermark) {
|
|
24
|
+
return this.notImplemented('fetching payments');
|
|
25
|
+
}
|
|
26
|
+
notImplemented(what) {
|
|
27
|
+
const code = this.Config?.TypeCode ?? 'unknown';
|
|
28
|
+
return {
|
|
29
|
+
Success: false,
|
|
30
|
+
Transient: false,
|
|
31
|
+
Reason: `The '${code}' invoice rail does not implement ${what}. Register a subclass with ` +
|
|
32
|
+
`@RegisterClass(BaseInvoiceRail, '${code}') and call its Load* anchor from the server bootstrap — ` +
|
|
33
|
+
`without the anchor the decorator is tree-shaken away and the class is silently absent.`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Tree-shaking anchor for the base — keeps the class reachable for the resolver's fallback check. */
|
|
38
|
+
export function LoadBaseInvoiceRail() {
|
|
39
|
+
void BaseInvoiceRail;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=BaseInvoiceRail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseInvoiceRail.js","sourceRoot":"","sources":["../src/BaseInvoiceRail.ts"],"names":[],"mappings":"AA8HA,MAAM,OAAO,eAAe;IAKxB;;;;;OAKG;IACI,KAAK,CAAC,kBAAkB;QAC3B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC1C,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,MAAyB;QACjD,OAAO,IAAI,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC;IACtD,CAAC;IAEM,KAAK,CAAC,YAAY,CAAC,MAAwB;QAC9C,OAAO,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC;IACrD,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,mBAA2B;QAC/C,OAAO,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC;IACrD,CAAC;IAEM,KAAK,CAAC,aAAa,CAAC,mBAA2B;QAClD,OAAO,IAAI,CAAC,cAAc,CAAC,uBAAuB,CAAC,CAAC;IACxD,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC3B,UAAyB;QAEzB,OAAO,IAAI,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;IACpD,CAAC;IAES,cAAc,CAAI,IAAY;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,SAAS,CAAC;QAChD,OAAO;YACH,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,KAAK;YAChB,MAAM,EACF,QAAQ,IAAI,qCAAqC,IAAI,6BAA6B;gBAClF,oCAAoC,IAAI,2DAA2D;gBACnG,wFAAwF;SAC/F,CAAC;IACN,CAAC;CACJ;AAED,sGAAsG;AACtG,MAAM,UAAU,mBAAmB;IAC/B,KAAK,eAAe,CAAC;AACzB,CAAC"}
|
|
@@ -94,6 +94,8 @@ export interface CaptureRequest {
|
|
|
94
94
|
/** Omit for the full authorised amount. Major units. */
|
|
95
95
|
Amount?: number;
|
|
96
96
|
CurrencyCode: string;
|
|
97
|
+
/** The gift card being spent, when the tender is one. Only the stored-value driver reads it. */
|
|
98
|
+
StoredValueAccountID?: string | null;
|
|
97
99
|
}
|
|
98
100
|
export interface RetrieveIntentRequest {
|
|
99
101
|
ProviderIntentID: string;
|
|
@@ -207,6 +209,14 @@ export declare class BasePaymentProvider {
|
|
|
207
209
|
* switch would invite exactly that.
|
|
208
210
|
*/
|
|
209
211
|
get SettlesAsynchronously(): boolean;
|
|
212
|
+
/**
|
|
213
|
+
* Whether capturing a payment against this provider means asking the gateway to MOVE money.
|
|
214
|
+
* True for a till (Stripe): capture calls the gateway and needs an intent. False for a rail that
|
|
215
|
+
* collected the money on its own (Bill.com): the payment is RECORDED, not collected, so there is no
|
|
216
|
+
* intent and nothing to capture — `PaymentHeaderEntityServer` books it like a check, but keeps
|
|
217
|
+
* `PaymentProviderID` so the money stays attributed to the rail it arrived on.
|
|
218
|
+
*/
|
|
219
|
+
get CollectsAtCapture(): boolean;
|
|
210
220
|
CreateIntent(_request: CreateIntentRequest): Promise<CreateIntentResult>;
|
|
211
221
|
Capture(_request: CaptureRequest): Promise<CaptureResult>;
|
|
212
222
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BasePaymentProvider.d.ts","sourceRoot":"","sources":["../src/BasePaymentProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE;QACV,oBAAoB,EAAE,OAAO,CAAC;QAC9B,cAAc,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,OAAO,CAAC;KAC7B,CAAC;CACL;AAED,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IAC/B,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAChC,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,uEAAuE;IACvE,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,yFAAyF;IACzF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"BasePaymentProvider.d.ts","sourceRoot":"","sources":["../src/BasePaymentProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,6 +43,16 @@ export class BasePaymentProvider {
|
|
|
43
43
|
get SettlesAsynchronously() {
|
|
44
44
|
return false;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Whether capturing a payment against this provider means asking the gateway to MOVE money.
|
|
48
|
+
* True for a till (Stripe): capture calls the gateway and needs an intent. False for a rail that
|
|
49
|
+
* collected the money on its own (Bill.com): the payment is RECORDED, not collected, so there is no
|
|
50
|
+
* intent and nothing to capture — `PaymentHeaderEntityServer` books it like a check, but keeps
|
|
51
|
+
* `PaymentProviderID` so the money stays attributed to the rail it arrived on.
|
|
52
|
+
*/
|
|
53
|
+
get CollectsAtCapture() {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
46
56
|
async CreateIntent(_request) {
|
|
47
57
|
return { Success: false, Reason: this.notImplemented('creating a payment intent') };
|
|
48
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BasePaymentProvider.js","sourceRoot":"","sources":["../src/BasePaymentProvider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BasePaymentProvider.js","sourceRoot":"","sources":["../src/BasePaymentProvider.ts"],"names":[],"mappings":"AA6KA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,mBAAmB;IAW5B,gGAAgG;IAChG,IAAW,iBAAiB;QACxB,OAAO,EAAE,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAW,qBAAqB;QAC5B,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;;;;OAMG;IACH,IAAW,iBAAiB;QACxB,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,KAAK,CAAC,YAAY,CAAC,QAA6B;QACnD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,2BAA2B,CAAC,EAAE,CAAC;IACxF,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,QAAwB;QACzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAE,CAAC;IAClF,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,cAAc,CAAC,QAA+B;QACvD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,6BAA6B,CAAC,EAAE,CAAC;IAC1F,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,QAAuB;QACvC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,qBAAqB,CAAC,EAAE,CAAC;IAClF,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,aAAa,CACtB,QAAgB,EAChB,QAA4C;QAE5C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,eAAe,2BAA2B,EAAE,CAAC;IAC5G,CAAC;IAED,kGAAkG;IAC3F,iBAAiB,CAAC,QAAgB;QACrC,OAAO,IAAI,CAAC;IAChB,CAAC;IAES,cAAc,CAAC,IAAY;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,SAAS,CAAC;QAChD,OAAO,CACH,QAAQ,IAAI,uCAAuC,IAAI,kCAAkC;YACzF,oEAAoE;YACpE,iEAAiE,CACpE,CAAC;IACN,CAAC;CACJ;AAED,0FAA0F;AAC1F,MAAM,UAAU,uBAAuB;IACnC,sBAAsB;AAC1B,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The connector-facing seam for Bill.com.
|
|
3
|
+
*
|
|
4
|
+
* Everything that touches `@memberjunction/connector-bill-com` goes through here, for two reasons:
|
|
5
|
+
*
|
|
6
|
+
* 1. The rail can be unit-tested with the wire stubbed — `UseBillComGatewaySeams` swaps the whole
|
|
7
|
+
* surface, the same way `AccountingERPEngine.UseSeams` does for the ERP verbs. Standing up a
|
|
8
|
+
* fake Bill.com over HTTP and asserting against our own mock would prove less.
|
|
9
|
+
* 2. There is exactly one place that knows how an `MJ: Company Integrations` row becomes a live
|
|
10
|
+
* connector instance (`ConnectorFactory.Resolve` on the `MJ: Integrations` row behind it), and
|
|
11
|
+
* how the connector's generic verbs are spelled. The connector ships no domain methods — create
|
|
12
|
+
* customer, create invoice and read payments are all the engine's metadata-driven CRUD.
|
|
13
|
+
*
|
|
14
|
+
* CREDENTIALS NEVER PASS THROUGH HERE. The connector reads them itself from the Company Integration's
|
|
15
|
+
* `CredentialID`. The only credential fact this file reads is the `environment` flag, so the rail can
|
|
16
|
+
* refuse a live provider row pointed at a sandbox credential (design §7).
|
|
17
|
+
*
|
|
18
|
+
* PAGINATION IS DRAINED HERE. The engine's `FetchChanges` returns one page and a cursor; the poller
|
|
19
|
+
* wants "everything since the watermark", so the default gateway walks the pages. The hard stop of
|
|
20
|
+
* 200 pages (20,000 rows) is a fuse, not a target — a payments object that large in one pass means
|
|
21
|
+
* the watermark is wrong.
|
|
22
|
+
*
|
|
23
|
+
* @module @mj-biz-apps/orders-core-entities-server
|
|
24
|
+
*/
|
|
25
|
+
import type { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
26
|
+
import type { MJCompanyIntegrationEntity } from '@memberjunction/core-entities';
|
|
27
|
+
import { type CRUDResult, type ExternalRecord, type FetchBatchResult } from '@memberjunction/integration-engine';
|
|
28
|
+
export interface BillComGatewaySeams {
|
|
29
|
+
loadCompanyIntegration(companyIntegrationID: string, provider: IMetadataProvider, user: UserInfo): Promise<MJCompanyIntegrationEntity>;
|
|
30
|
+
/**
|
|
31
|
+
* Which BILL gateway this connection actually talks to.
|
|
32
|
+
*
|
|
33
|
+
* `Known` carries `'sandbox'` or `'production'`; `Unknown` carries why it could not be read. It is a
|
|
34
|
+
* discriminated result rather than a nullable string because the caller must REFUSE on Unknown —
|
|
35
|
+
* an environment nobody can read is exactly the case where sandbox money gets recorded as cash.
|
|
36
|
+
*/
|
|
37
|
+
loadCredentialEnvironment(ci: MJCompanyIntegrationEntity, provider: IMetadataProvider, user: UserInfo): Promise<RailEnvironment>;
|
|
38
|
+
createRecord(ci: MJCompanyIntegrationEntity, object: string, attrs: Record<string, unknown>, user: UserInfo): Promise<CRUDResult>;
|
|
39
|
+
updateRecord(ci: MJCompanyIntegrationEntity, object: string, externalID: string, attrs: Record<string, unknown>, user: UserInfo): Promise<CRUDResult>;
|
|
40
|
+
getRecord(ci: MJCompanyIntegrationEntity, object: string, externalID: string, user: UserInfo): Promise<ExternalRecord | null>;
|
|
41
|
+
/** Every record changed since the watermark, all pages drained. */
|
|
42
|
+
fetchChanges(ci: MJCompanyIntegrationEntity, object: string, watermark: string | null, user: UserInfo): Promise<FetchBatchResult>;
|
|
43
|
+
/**
|
|
44
|
+
* `POST /invoices/{id}/archive` — BILL's only way to archive an invoice. Verified live 2026-09-21
|
|
45
|
+
* (spike S1): `PUT {archived:true}` is refused with 400 because PUT is a full replace that demands
|
|
46
|
+
* `customer` and `invoiceLineItems`; the archive verb returns 200 with `archived: true`,
|
|
47
|
+
* `recordStatus: INACTIVE`, and is idempotent. Delegates to the connector's own `ArchiveInvoice`
|
|
48
|
+
* since 0.3.2 (Integrations #391); earlier builds have no such verb and this refuses with a
|
|
49
|
+
* sentence rather than failing obscurely.
|
|
50
|
+
*/
|
|
51
|
+
archiveInvoice(ci: MJCompanyIntegrationEntity, externalID: string, user: UserInfo): Promise<CRUDResult>;
|
|
52
|
+
}
|
|
53
|
+
/** Swap the wire for tests. Pass null to restore the real connector path. */
|
|
54
|
+
export declare function UseBillComGatewaySeams(s: BillComGatewaySeams | null): void;
|
|
55
|
+
export declare function CurrentBillComGatewaySeams(): BillComGatewaySeams | null;
|
|
56
|
+
/** `sandbox` or `production`, or the reason it could not be determined. Never a silent default. */
|
|
57
|
+
export type RailEnvironment = {
|
|
58
|
+
Known: true;
|
|
59
|
+
Environment: 'sandbox' | 'production';
|
|
60
|
+
} | {
|
|
61
|
+
Known: false;
|
|
62
|
+
Reason: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Read the effective environment out of a credential or Configuration blob.
|
|
66
|
+
*
|
|
67
|
+
* `apiUrl` OUTRANKS `environment`, because it outranks it in the connector: `ResolveBaseURL` uses an
|
|
68
|
+
* explicit apiUrl and only falls back to the environment string. Trusting `environment` alone let
|
|
69
|
+
* `{environment: 'production', apiUrl: '<stage>'}` pass a live provider's check and then talk to
|
|
70
|
+
* sandbox — and the reverse, which is the one that records play money as revenue.
|
|
71
|
+
*/
|
|
72
|
+
export declare function environmentFrom(blob: string | null | undefined, whereFrom: string): RailEnvironment;
|
|
73
|
+
/**
|
|
74
|
+
* BILL reports validation failures as an ARRAY of `{severity, message}` (seen live: PUT without a
|
|
75
|
+
* customer → `[{message: "customer: must not be null"}, …]`), which the engine's `ExtractErrorMessage`
|
|
76
|
+
* does not read. Joins those; falls back to `message`/`error` on an object; null when there is no text.
|
|
77
|
+
*/
|
|
78
|
+
export declare function billComErrorText(body: unknown): string | null;
|
|
79
|
+
export declare function DefaultBillComGateway(provider: IMetadataProvider): BillComGatewaySeams;
|
|
80
|
+
/** The gateway to use: the test seams when set, else the real connector path. */
|
|
81
|
+
export declare function BillComGateway(provider: IMetadataProvider): BillComGatewaySeams;
|
|
82
|
+
//# sourceMappingURL=BillComGateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BillComGateway.d.ts","sourceRoot":"","sources":["../src/BillComGateway.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,KAAK,EAAE,0BAA0B,EAA2C,MAAM,+BAA+B,CAAC;AACzH,OAAO,EAAoB,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGnI,MAAM,WAAW,mBAAmB;IAChC,sBAAsB,CAAC,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACvI;;;;;;OAMG;IACH,yBAAyB,CAAC,EAAE,EAAE,0BAA0B,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACjI,YAAY,CAAC,EAAE,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAClI,YAAY,CAAC,EAAE,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACtJ,SAAS,CAAC,EAAE,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC9H,mEAAmE;IACnE,YAAY,CAAC,EAAE,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClI;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,EAAE,0BAA0B,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC3G;AAaD,6EAA6E;AAC7E,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAE1E;AAED,wBAAgB,0BAA0B,IAAI,mBAAmB,GAAG,IAAI,CAEvE;AAED,mGAAmG;AACnG,MAAM,MAAM,eAAe,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,SAAS,GAAG,YAAY,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExH;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CAoBnG;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAW7D;AAeD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,mBAAmB,CAiFtF;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,GAAG,mBAAmB,CAE/E"}
|