@mj-biz-apps/orders-core-entities-server 0.0.1 → 5.2.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.
Files changed (267) hide show
  1. package/LICENSE +183 -0
  2. package/README.md +141 -2
  3. package/dist/AccountingBridge.d.ts +65 -0
  4. package/dist/AccountingBridge.d.ts.map +1 -0
  5. package/dist/AccountingBridge.js +102 -0
  6. package/dist/AccountingBridge.js.map +1 -0
  7. package/dist/AdvanceOrderStateOperation.d.ts +80 -0
  8. package/dist/AdvanceOrderStateOperation.d.ts.map +1 -0
  9. package/dist/AdvanceOrderStateOperation.js +267 -0
  10. package/dist/AdvanceOrderStateOperation.js.map +1 -0
  11. package/dist/ApplyAccountCreditOperation.d.ts +97 -0
  12. package/dist/ApplyAccountCreditOperation.d.ts.map +1 -0
  13. package/dist/ApplyAccountCreditOperation.js +275 -0
  14. package/dist/ApplyAccountCreditOperation.js.map +1 -0
  15. package/dist/BaseDeliveryChannel.d.ts +106 -0
  16. package/dist/BaseDeliveryChannel.d.ts.map +1 -0
  17. package/dist/BaseDeliveryChannel.js +36 -0
  18. package/dist/BaseDeliveryChannel.js.map +1 -0
  19. package/dist/BasePaymentProvider.d.ts +239 -0
  20. package/dist/BasePaymentProvider.d.ts.map +1 -0
  21. package/dist/BasePaymentProvider.js +91 -0
  22. package/dist/BasePaymentProvider.js.map +1 -0
  23. package/dist/BundleBehavior.d.ts +139 -0
  24. package/dist/BundleBehavior.d.ts.map +1 -0
  25. package/dist/BundleBehavior.js +173 -0
  26. package/dist/BundleBehavior.js.map +1 -0
  27. package/dist/BundleEngine.d.ts +60 -0
  28. package/dist/BundleEngine.d.ts.map +1 -0
  29. package/dist/BundleEngine.js +197 -0
  30. package/dist/BundleEngine.js.map +1 -0
  31. package/dist/CancelSubscriptionOperation.d.ts +98 -0
  32. package/dist/CancelSubscriptionOperation.d.ts.map +1 -0
  33. package/dist/CancelSubscriptionOperation.js +317 -0
  34. package/dist/CancelSubscriptionOperation.js.map +1 -0
  35. package/dist/CapturePaymentOperation.d.ts +62 -0
  36. package/dist/CapturePaymentOperation.d.ts.map +1 -0
  37. package/dist/CapturePaymentOperation.js +463 -0
  38. package/dist/CapturePaymentOperation.js.map +1 -0
  39. package/dist/CheckEntitlementOperation.d.ts +27 -0
  40. package/dist/CheckEntitlementOperation.d.ts.map +1 -0
  41. package/dist/CheckEntitlementOperation.js +45 -0
  42. package/dist/CheckEntitlementOperation.js.map +1 -0
  43. package/dist/CheckoutSessionService.d.ts +258 -0
  44. package/dist/CheckoutSessionService.d.ts.map +1 -0
  45. package/dist/CheckoutSessionService.js +1557 -0
  46. package/dist/CheckoutSessionService.js.map +1 -0
  47. package/dist/DeliveryBehavior.d.ts +121 -0
  48. package/dist/DeliveryBehavior.d.ts.map +1 -0
  49. package/dist/DeliveryBehavior.js +145 -0
  50. package/dist/DeliveryBehavior.js.map +1 -0
  51. package/dist/DeliveryRecipientResolver.d.ts +38 -0
  52. package/dist/DeliveryRecipientResolver.d.ts.map +1 -0
  53. package/dist/DeliveryRecipientResolver.js +93 -0
  54. package/dist/DeliveryRecipientResolver.js.map +1 -0
  55. package/dist/DeliveryResolver.d.ts +14 -0
  56. package/dist/DeliveryResolver.d.ts.map +1 -0
  57. package/dist/DeliveryResolver.js +45 -0
  58. package/dist/DeliveryResolver.js.map +1 -0
  59. package/dist/EmailDeliveryChannel.d.ts +31 -0
  60. package/dist/EmailDeliveryChannel.d.ts.map +1 -0
  61. package/dist/EmailDeliveryChannel.js +158 -0
  62. package/dist/EmailDeliveryChannel.js.map +1 -0
  63. package/dist/EntitlementBehavior.d.ts +235 -0
  64. package/dist/EntitlementBehavior.d.ts.map +1 -0
  65. package/dist/EntitlementBehavior.js +330 -0
  66. package/dist/EntitlementBehavior.js.map +1 -0
  67. package/dist/EntitlementEngine.d.ts +97 -0
  68. package/dist/EntitlementEngine.d.ts.map +1 -0
  69. package/dist/EntitlementEngine.js +338 -0
  70. package/dist/EntitlementEngine.js.map +1 -0
  71. package/dist/EntitlementGrantClaimDriver.d.ts +42 -0
  72. package/dist/EntitlementGrantClaimDriver.d.ts.map +1 -0
  73. package/dist/EntitlementGrantClaimDriver.js +158 -0
  74. package/dist/EntitlementGrantClaimDriver.js.map +1 -0
  75. package/dist/EntitlementRead.d.ts +82 -0
  76. package/dist/EntitlementRead.d.ts.map +1 -0
  77. package/dist/EntitlementRead.js +368 -0
  78. package/dist/EntitlementRead.js.map +1 -0
  79. package/dist/FulfillOrderLinesOperation.d.ts +34 -0
  80. package/dist/FulfillOrderLinesOperation.d.ts.map +1 -0
  81. package/dist/FulfillOrderLinesOperation.js +208 -0
  82. package/dist/FulfillOrderLinesOperation.js.map +1 -0
  83. package/dist/FulfillmentBehavior.d.ts +101 -0
  84. package/dist/FulfillmentBehavior.d.ts.map +1 -0
  85. package/dist/FulfillmentBehavior.js +145 -0
  86. package/dist/FulfillmentBehavior.js.map +1 -0
  87. package/dist/GLAccountResolver.d.ts +123 -0
  88. package/dist/GLAccountResolver.d.ts.map +1 -0
  89. package/dist/GLAccountResolver.js +175 -0
  90. package/dist/GLAccountResolver.js.map +1 -0
  91. package/dist/GetFulfillmentQueueOperation.d.ts +35 -0
  92. package/dist/GetFulfillmentQueueOperation.d.ts.map +1 -0
  93. package/dist/GetFulfillmentQueueOperation.js +221 -0
  94. package/dist/GetFulfillmentQueueOperation.js.map +1 -0
  95. package/dist/GetOverdueWorklistOperation.d.ts +41 -0
  96. package/dist/GetOverdueWorklistOperation.d.ts.map +1 -0
  97. package/dist/GetOverdueWorklistOperation.js +210 -0
  98. package/dist/GetOverdueWorklistOperation.js.map +1 -0
  99. package/dist/GiftCardBehavior.d.ts +97 -0
  100. package/dist/GiftCardBehavior.d.ts.map +1 -0
  101. package/dist/GiftCardBehavior.js +121 -0
  102. package/dist/GiftCardBehavior.js.map +1 -0
  103. package/dist/GiftCardEngine.d.ts +59 -0
  104. package/dist/GiftCardEngine.d.ts.map +1 -0
  105. package/dist/GiftCardEngine.js +197 -0
  106. package/dist/GiftCardEngine.js.map +1 -0
  107. package/dist/GuestOrderClaimDriver.d.ts +36 -0
  108. package/dist/GuestOrderClaimDriver.d.ts.map +1 -0
  109. package/dist/GuestOrderClaimDriver.js +161 -0
  110. package/dist/GuestOrderClaimDriver.js.map +1 -0
  111. package/dist/InvoiceBehavior.d.ts +394 -0
  112. package/dist/InvoiceBehavior.d.ts.map +1 -0
  113. package/dist/InvoiceBehavior.js +496 -0
  114. package/dist/InvoiceBehavior.js.map +1 -0
  115. package/dist/InvoiceBuilder.d.ts +48 -0
  116. package/dist/InvoiceBuilder.d.ts.map +1 -0
  117. package/dist/InvoiceBuilder.js +352 -0
  118. package/dist/InvoiceBuilder.js.map +1 -0
  119. package/dist/InvoiceDisplay.d.ts +96 -0
  120. package/dist/InvoiceDisplay.d.ts.map +1 -0
  121. package/dist/InvoiceDisplay.js +121 -0
  122. package/dist/InvoiceDisplay.js.map +1 -0
  123. package/dist/ListEntitlementsOperation.d.ts +21 -0
  124. package/dist/ListEntitlementsOperation.d.ts.map +1 -0
  125. package/dist/ListEntitlementsOperation.js +39 -0
  126. package/dist/ListEntitlementsOperation.js.map +1 -0
  127. package/dist/ManualPaymentProvider.d.ts +19 -0
  128. package/dist/ManualPaymentProvider.d.ts.map +1 -0
  129. package/dist/ManualPaymentProvider.js +92 -0
  130. package/dist/ManualPaymentProvider.js.map +1 -0
  131. package/dist/OrderEntityServer.d.ts +542 -0
  132. package/dist/OrderEntityServer.d.ts.map +1 -0
  133. package/dist/OrderEntityServer.js +2100 -0
  134. package/dist/OrderEntityServer.js.map +1 -0
  135. package/dist/OrderJournalEntryFactory.d.ts +140 -0
  136. package/dist/OrderJournalEntryFactory.d.ts.map +1 -0
  137. package/dist/OrderJournalEntryFactory.js +466 -0
  138. package/dist/OrderJournalEntryFactory.js.map +1 -0
  139. package/dist/OrderLineEntityServer.d.ts +90 -0
  140. package/dist/OrderLineEntityServer.d.ts.map +1 -0
  141. package/dist/OrderLineEntityServer.js +260 -0
  142. package/dist/OrderLineEntityServer.js.map +1 -0
  143. package/dist/OrdersSettings.d.ts +36 -0
  144. package/dist/OrdersSettings.d.ts.map +1 -0
  145. package/dist/OrdersSettings.js +147 -0
  146. package/dist/OrdersSettings.js.map +1 -0
  147. package/dist/PaymentAllocationFactory.d.ts +128 -0
  148. package/dist/PaymentAllocationFactory.d.ts.map +1 -0
  149. package/dist/PaymentAllocationFactory.js +235 -0
  150. package/dist/PaymentAllocationFactory.js.map +1 -0
  151. package/dist/PaymentHeaderEntityServer.d.ts +180 -0
  152. package/dist/PaymentHeaderEntityServer.d.ts.map +1 -0
  153. package/dist/PaymentHeaderEntityServer.js +656 -0
  154. package/dist/PaymentHeaderEntityServer.js.map +1 -0
  155. package/dist/PaymentIntentService.d.ts +101 -0
  156. package/dist/PaymentIntentService.d.ts.map +1 -0
  157. package/dist/PaymentIntentService.js +150 -0
  158. package/dist/PaymentIntentService.js.map +1 -0
  159. package/dist/PaymentJournalEntryFactory.d.ts +99 -0
  160. package/dist/PaymentJournalEntryFactory.d.ts.map +1 -0
  161. package/dist/PaymentJournalEntryFactory.js +127 -0
  162. package/dist/PaymentJournalEntryFactory.js.map +1 -0
  163. package/dist/PaymentLineEntityServer.d.ts +73 -0
  164. package/dist/PaymentLineEntityServer.d.ts.map +1 -0
  165. package/dist/PaymentLineEntityServer.js +303 -0
  166. package/dist/PaymentLineEntityServer.js.map +1 -0
  167. package/dist/PaymentProviderBehavior.d.ts +222 -0
  168. package/dist/PaymentProviderBehavior.d.ts.map +1 -0
  169. package/dist/PaymentProviderBehavior.js +368 -0
  170. package/dist/PaymentProviderBehavior.js.map +1 -0
  171. package/dist/PaymentProviderResolver.d.ts +84 -0
  172. package/dist/PaymentProviderResolver.d.ts.map +1 -0
  173. package/dist/PaymentProviderResolver.js +220 -0
  174. package/dist/PaymentProviderResolver.js.map +1 -0
  175. package/dist/PaymentReversalFactory.d.ts +107 -0
  176. package/dist/PaymentReversalFactory.d.ts.map +1 -0
  177. package/dist/PaymentReversalFactory.js +174 -0
  178. package/dist/PaymentReversalFactory.js.map +1 -0
  179. package/dist/PaymentSettlement.d.ts +56 -0
  180. package/dist/PaymentSettlement.d.ts.map +1 -0
  181. package/dist/PaymentSettlement.js +243 -0
  182. package/dist/PaymentSettlement.js.map +1 -0
  183. package/dist/PaymentTermsBehavior.d.ts +109 -0
  184. package/dist/PaymentTermsBehavior.d.ts.map +1 -0
  185. package/dist/PaymentTermsBehavior.js +172 -0
  186. package/dist/PaymentTermsBehavior.js.map +1 -0
  187. package/dist/PaymentWebhookHandler.d.ts +103 -0
  188. package/dist/PaymentWebhookHandler.d.ts.map +1 -0
  189. package/dist/PaymentWebhookHandler.js +246 -0
  190. package/dist/PaymentWebhookHandler.js.map +1 -0
  191. package/dist/PreviewPriceOperation.d.ts +62 -0
  192. package/dist/PreviewPriceOperation.d.ts.map +1 -0
  193. package/dist/PreviewPriceOperation.js +161 -0
  194. package/dist/PreviewPriceOperation.js.map +1 -0
  195. package/dist/PriceOrderOperation.d.ts +93 -0
  196. package/dist/PriceOrderOperation.d.ts.map +1 -0
  197. package/dist/PriceOrderOperation.js +146 -0
  198. package/dist/PriceOrderOperation.js.map +1 -0
  199. package/dist/ProductPriceEntityServer.d.ts +34 -0
  200. package/dist/ProductPriceEntityServer.d.ts.map +1 -0
  201. package/dist/ProductPriceEntityServer.js +97 -0
  202. package/dist/ProductPriceEntityServer.js.map +1 -0
  203. package/dist/RefundPaymentOperation.d.ts +61 -0
  204. package/dist/RefundPaymentOperation.d.ts.map +1 -0
  205. package/dist/RefundPaymentOperation.js +177 -0
  206. package/dist/RefundPaymentOperation.js.map +1 -0
  207. package/dist/RevenueRecognition.d.ts +76 -0
  208. package/dist/RevenueRecognition.d.ts.map +1 -0
  209. package/dist/RevenueRecognition.js +133 -0
  210. package/dist/RevenueRecognition.js.map +1 -0
  211. package/dist/ReversalBehavior.d.ts +82 -0
  212. package/dist/ReversalBehavior.d.ts.map +1 -0
  213. package/dist/ReversalBehavior.js +100 -0
  214. package/dist/ReversalBehavior.js.map +1 -0
  215. package/dist/ReversalResolver.d.ts +37 -0
  216. package/dist/ReversalResolver.d.ts.map +1 -0
  217. package/dist/ReversalResolver.js +96 -0
  218. package/dist/ReversalResolver.js.map +1 -0
  219. package/dist/SpawnRenewalsOperation.d.ts +109 -0
  220. package/dist/SpawnRenewalsOperation.d.ts.map +1 -0
  221. package/dist/SpawnRenewalsOperation.js +295 -0
  222. package/dist/SpawnRenewalsOperation.js.map +1 -0
  223. package/dist/StoredValuePaymentProvider.d.ts +52 -0
  224. package/dist/StoredValuePaymentProvider.d.ts.map +1 -0
  225. package/dist/StoredValuePaymentProvider.js +205 -0
  226. package/dist/StoredValuePaymentProvider.js.map +1 -0
  227. package/dist/StripeACHPaymentProvider.d.ts +50 -0
  228. package/dist/StripeACHPaymentProvider.d.ts.map +1 -0
  229. package/dist/StripeACHPaymentProvider.js +211 -0
  230. package/dist/StripeACHPaymentProvider.js.map +1 -0
  231. package/dist/StripePaymentProvider.d.ts +83 -0
  232. package/dist/StripePaymentProvider.d.ts.map +1 -0
  233. package/dist/StripePaymentProvider.js +442 -0
  234. package/dist/StripePaymentProvider.js.map +1 -0
  235. package/dist/SubscriptionBehavior.d.ts +197 -0
  236. package/dist/SubscriptionBehavior.d.ts.map +1 -0
  237. package/dist/SubscriptionBehavior.js +415 -0
  238. package/dist/SubscriptionBehavior.js.map +1 -0
  239. package/dist/checkoutCaptureAlert.d.ts +16 -0
  240. package/dist/checkoutCaptureAlert.d.ts.map +1 -0
  241. package/dist/checkoutCaptureAlert.js +55 -0
  242. package/dist/checkoutCaptureAlert.js.map +1 -0
  243. package/dist/checkoutCaptureRetry.d.ts +27 -0
  244. package/dist/checkoutCaptureRetry.d.ts.map +1 -0
  245. package/dist/checkoutCaptureRetry.js +50 -0
  246. package/dist/checkoutCaptureRetry.js.map +1 -0
  247. package/dist/claimDriverHelpers.d.ts +15 -0
  248. package/dist/claimDriverHelpers.d.ts.map +1 -0
  249. package/dist/claimDriverHelpers.js +34 -0
  250. package/dist/claimDriverHelpers.js.map +1 -0
  251. package/dist/entity-names.d.ts +15 -0
  252. package/dist/entity-names.d.ts.map +1 -0
  253. package/dist/entity-names.js +15 -0
  254. package/dist/entity-names.js.map +1 -0
  255. package/dist/identityClaimContracts.d.ts +118 -0
  256. package/dist/identityClaimContracts.d.ts.map +1 -0
  257. package/dist/identityClaimContracts.js +58 -0
  258. package/dist/identityClaimContracts.js.map +1 -0
  259. package/dist/index.d.ts +126 -0
  260. package/dist/index.d.ts.map +1 -0
  261. package/dist/index.js +115 -0
  262. package/dist/index.js.map +1 -0
  263. package/dist/sql-guards.d.ts +78 -0
  264. package/dist/sql-guards.d.ts.map +1 -0
  265. package/dist/sql-guards.js +115 -0
  266. package/dist/sql-guards.js.map +1 -0
  267. package/package.json +50 -5
@@ -0,0 +1,303 @@
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
+ * PaymentLine server subclass — the cash-application guard (plan D18/D41) AND the cash leg (D13).
9
+ *
10
+ * `PaymentLine` is the junction that says "this much of that payment settles this order". The only
11
+ * protection it had was `CHECK (Amount <> 0)`, so nothing stopped applying $500 against a $100
12
+ * order. The rollup triggers would dutifully compute `Balance = -400` and `PaymentStatus = 'Paid'`,
13
+ * and the customer would appear to be owed money the ledger has no record of.
14
+ *
15
+ * ONE RULE HERE (D68 revised the other away)
16
+ * A negative application (un-apply, or spending a credit) may not push the order's applied total
17
+ * BELOW zero. Un-applying more than was ever applied is always a mistake.
18
+ *
19
+ * THERE IS DELIBERATELY NO CEILING. An earlier version refused any application that pushed the
20
+ * order's applied total above its gross, on the reasoning that an over-payment should be recorded
21
+ * "deliberately" as a credit memo. That was wrong, and it made the honest case unrecordable: a
22
+ * customer who sends 1000 for a 900 order has done nothing unusual, and the money is in the bank
23
+ * whether or not the schema likes it. Over-applying now simply drives the order's balance negative,
24
+ * and a negative balance IS the credit — spendable on another order via the Account Credit tender.
25
+ *
26
+ * WHAT GUARDS THE PAYMENT INSTEAD: `PaymentHeaderEntityServer` requires a captured payment's Amount
27
+ * to equal the sum of its lines (D68). That is a payment-side sum, so it belongs on the payment —
28
+ * and being an equality rather than a ceiling, it makes over-allocating a payment impossible by
29
+ * construction rather than by a second check.
30
+ *
31
+ * ── THE CASH LEG MOVED HERE (2026-07-26, D13 payment half) ──────────────────────────────────
32
+ * It used to live on `PaymentHeader` capture, which booked `Dr Cash / Cr AR` against the RECEIVING
33
+ * company and nothing else. That was wrong the moment an order carried another company's product:
34
+ * the collector's receivable was credited for money it was never owed, and the owner's receivable
35
+ * stayed open forever — balanced, posted, and invisible.
36
+ *
37
+ * ALLOCATION is the earliest point the companies are even KNOWN. A capture says how much cash
38
+ * arrived; only the allocation says whose revenue it settles. So the entries belong here, one per
39
+ * company owning a line on the order (plans/archive/intercompany-balancing.md §2).
40
+ *
41
+ * `BookedAt` is the idempotency key rather than a `JournalEntryID`, because one allocation produces
42
+ * N entries. They are found the other way round, through accounting's D25 provenance pair.
43
+ *
44
+ * CONNECTS TO:
45
+ * FACTORY: PaymentAllocationFactory (./PaymentAllocationFactory.ts)
46
+ * LOOKUP: AccountingEngineBase.ResolveIntercompanyAccounts (BA-D26)
47
+ * TRIGGERS: trg_PaymentLine_RollupTotals → spRecalcOrderHeaderTotals (D41)
48
+ * TABLE: __mj_BizAppsOrders.PaymentLine
49
+ */
50
+ import { BaseEntity, BaseEntityResult, BaseRemotableOperation, LogError, RunView, ValidationErrorInfo, ValidationErrorType, } from '@memberjunction/core';
51
+ import { MJGlobal, RegisterClass } from '@memberjunction/global';
52
+ import { mjBizAppsOrdersPaymentLineEntity } from '@mj-biz-apps/orders-entities';
53
+ import { AccountingEngineBase } from '@mj-biz-apps/accounting-engine-base';
54
+ import { BuildGLAccountResolver, EntityIDFor } from './AccountingBridge.js';
55
+ import { PaymentAllocationFactory } from './PaymentAllocationFactory.js';
56
+ const PAYMENT_LINE_ENTITY = 'MJ_BizApps_Orders: Payment Lines';
57
+ const ORDER_HEADER_ENTITY = 'MJ_BizApps_Orders: Order Headers';
58
+ const ORDER_LINE_ENTITY = 'MJ_BizApps_Orders: Order Lines';
59
+ const PAYMENT_HEADER_ENTITY = 'MJ_BizApps_Orders: Payment Headers';
60
+ /** Payment statuses whose allocations belong in the ledger. */
61
+ const BOOKED_STATUSES = new Set(['Captured', 'Refunded']);
62
+ /** Cents of slack, so decimal rounding never trips the guard on an exact-payment case. */
63
+ const TOLERANCE = 0.005;
64
+ let PaymentLineEntityServer = class PaymentLineEntityServer extends mjBizAppsOrdersPaymentLineEntity {
65
+ /**
66
+ * The applied-total check runs in `Save`, not `Validate`, because it needs to read sibling rows
67
+ * — `Validate()` is synchronous by contract, and a guard that cannot see the other applications
68
+ * is not a guard.
69
+ */
70
+ async Save(options) {
71
+ const problem = await this.checkApplicationTotal();
72
+ if (problem) {
73
+ // Registered rather than thrown: a rejected application is a business outcome the
74
+ // caller inspects on LatestResult, the same contract every other save failure uses.
75
+ this.RegisterResultHistoryEntry(this.buildRejection(problem));
76
+ return false;
77
+ }
78
+ // `BookedAt` is the idempotency key: a re-saved allocation (a note edited, a user
79
+ // backfilled) must not credit AR a second time.
80
+ if (this.BookedAt)
81
+ return super.Save(options);
82
+ // When saved as part of a parent PaymentHeader save, the parent PaymentHeader
83
+ // coordinates the booking of all allocations in one atomic batch inside the parent transaction.
84
+ if (options?.IsParentEntitySave) {
85
+ return super.Save(options);
86
+ }
87
+ const payment = await this.loadPayment();
88
+ // Nothing to book yet for an allocation against a Pending payment — no cash has landed.
89
+ // It books when the payment reaches Captured, not here.
90
+ if (!payment || !BOOKED_STATUSES.has(payment.Status))
91
+ return super.Save(options);
92
+ const dbProvider = this.ProviderToUse;
93
+ await dbProvider.BeginTransaction();
94
+ try {
95
+ if (!(await super.Save(options))) {
96
+ throw new Error(`Failed to save the payment allocation: ${this.LatestResult?.CompleteMessage ?? 'unknown error'}`);
97
+ }
98
+ await this.bookAllocation(payment, options);
99
+ await dbProvider.CommitTransaction();
100
+ return true;
101
+ }
102
+ catch (err) {
103
+ LogError(`PaymentLineEntityServer.Save failed for allocation ${this.ID}: ${err}`);
104
+ try {
105
+ await dbProvider.RollbackTransaction();
106
+ }
107
+ catch (rollbackErr) {
108
+ LogError(`Rollback failed after allocation save error: ${rollbackErr}`);
109
+ }
110
+ // Same reasoning as OrderEntityServer (D50): a bare `false` leaves LatestResult holding
111
+ // the row's SUCCESSFUL save, so the caller sees no reason for the refusal.
112
+ this.RegisterResultHistoryEntry(this.buildRejection(err instanceof Error ? err.message : String(err)));
113
+ return false;
114
+ }
115
+ }
116
+ /**
117
+ * Book one journal entry per company owning a line on the order this allocation settles.
118
+ *
119
+ * Single-company orders produce exactly one entry — the shape the ledger had before — so this
120
+ * is a generalisation of the old behaviour rather than a parallel path.
121
+ */
122
+ async bookAllocation(payment, options) {
123
+ const provider = this.ProviderToUse;
124
+ const user = this.ContextCurrentUser;
125
+ const orderLines = await this.loadOrderLines();
126
+ if (orderLines.length === 0) {
127
+ throw new Error(`Cannot allocate ${this.Amount} to order ${this.OrderHeaderID}: the order has no lines, so ` +
128
+ `there is no basis for deciding whose revenue the cash settles.`);
129
+ }
130
+ const order = await this.loadOrderNumber();
131
+ // The intercompany lookup is accounting's (BA-D26), read from its cache. Config is cheap
132
+ // after the first call and keeps the pair current when one is added mid-session.
133
+ await AccountingEngineBase.Instance.Config(false, user, provider);
134
+ const factory = new PaymentAllocationFactory(await BuildGLAccountResolver(provider, user), (source, target, asOf) => {
135
+ const hit = AccountingEngineBase.Instance.ResolveIntercompanyAccounts(source, target, asOf);
136
+ return hit ? { DueToGLAccountID: hit.DueTo.GLAccountID, DueFromGLAccountID: hit.DueFrom.GLAccountID } : null;
137
+ }, EntityIDFor(PAYMENT_LINE_ENTITY));
138
+ const { Drafts } = await factory.BuildAllocationDrafts({
139
+ PaymentLineID: this.ID,
140
+ PaymentNumber: payment.PaymentNumber,
141
+ OrderNumber: order,
142
+ Amount: this.Amount ?? 0,
143
+ ReceivingCompanyID: payment.ReceivingCompanyID,
144
+ OrderLines: orderLines,
145
+ TargetOrderLineID: this.OrderLineID ?? null,
146
+ PaymentDate: payment.PaymentDate,
147
+ // A negative allocation un-applies cash, and a refunded payment reverses: both mirror.
148
+ IsReversal: payment.Status === 'Refunded' || (this.Amount ?? 0) < 0,
149
+ });
150
+ const result = await this.createJournalEntries(Drafts, provider, user);
151
+ if ((result.Results?.length ?? 0) !== Drafts.length) {
152
+ throw new Error(`Accounting returned ${result.Results?.length ?? 0} journal entries for an allocation that ` +
153
+ `produced ${Drafts.length} drafts. The cash leg is incomplete; refusing to commit.`);
154
+ }
155
+ this.BookedAt = new Date();
156
+ if (!(await super.Save(options))) {
157
+ throw new Error(`Failed to stamp BookedAt on the allocation: ${this.LatestResult?.CompleteMessage ?? 'unknown error'}`);
158
+ }
159
+ }
160
+ /** The payment this allocation belongs to, or null when it cannot be read. */
161
+ async loadPayment() {
162
+ if (!this.PaymentHeaderID)
163
+ return null;
164
+ const rv = new RunView(this.ProviderToUse);
165
+ const res = await rv.RunView({
166
+ EntityName: PAYMENT_HEADER_ENTITY,
167
+ ExtraFilter: `ID='${this.PaymentHeaderID}'`,
168
+ Fields: ['PaymentNumber', 'ReceivingCompanyID', 'Status', 'PaymentDate'],
169
+ ResultType: 'simple',
170
+ BypassCache: true,
171
+ }, this.ContextCurrentUser);
172
+ const row = res?.Results?.[0];
173
+ if (!row)
174
+ return null;
175
+ return {
176
+ PaymentNumber: row.PaymentNumber,
177
+ ReceivingCompanyID: row.ReceivingCompanyID,
178
+ Status: row.Status,
179
+ PaymentDate: row.PaymentDate ? new Date(row.PaymentDate) : new Date(),
180
+ };
181
+ }
182
+ /** Every line of the order, with the company that owns it — the pro-rating basis. */
183
+ async loadOrderLines() {
184
+ const rv = new RunView(this.ProviderToUse);
185
+ // LineTotalGross (= net + tax) is the basis on purpose: it is exactly what booking DEBITED
186
+ // to AR for the line, and what the order's TotalGross rolls up from. Allocating on any
187
+ // other basis would clear a different amount than was ever receivable.
188
+ const res = await rv.RunView({
189
+ EntityName: ORDER_LINE_ENTITY,
190
+ ExtraFilter: `OrderHeaderID='${this.OrderHeaderID}'`,
191
+ Fields: ['ID', 'CompanyID', 'LineTotalGross'],
192
+ ResultType: 'simple',
193
+ BypassCache: true,
194
+ }, this.ContextCurrentUser);
195
+ if (!res?.Success) {
196
+ throw new Error(`Could not read the order's lines to allocate the payment: ${res?.ErrorMessage ?? 'unknown error'}`);
197
+ }
198
+ return (res.Results ?? []).map((l) => ({
199
+ OrderLineID: l.ID,
200
+ CompanyID: l.CompanyID,
201
+ Amount: Number(l.LineTotalGross ?? 0),
202
+ }));
203
+ }
204
+ async loadOrderNumber() {
205
+ const rv = new RunView(this.ProviderToUse);
206
+ const res = await rv.RunView({
207
+ EntityName: ORDER_HEADER_ENTITY,
208
+ ExtraFilter: `ID='${this.OrderHeaderID}'`,
209
+ Fields: ['OrderNumber'],
210
+ ResultType: 'simple',
211
+ BypassCache: true,
212
+ }, this.ContextCurrentUser);
213
+ return res?.Results?.[0]?.OrderNumber ?? String(this.OrderHeaderID);
214
+ }
215
+ async createJournalEntries(drafts, provider, user) {
216
+ const op = MJGlobal.Instance.ClassFactory.CreateInstance(BaseRemotableOperation, 'Accounting.CreateJournalEntries');
217
+ if (!op) {
218
+ throw new Error(`The 'Accounting.CreateJournalEntries' operation is not registered. The BizApps ` +
219
+ `Accounting server package must be loaded before payments can book the cash leg.`);
220
+ }
221
+ const result = await op.Execute({ Drafts: drafts }, { provider, user });
222
+ if (!result.Success) {
223
+ throw new Error(`Accounting.CreateJournalEntries did not execute: ${result.ErrorMessage ?? result.ResultCode ?? 'unknown error'}`);
224
+ }
225
+ const payload = result.Output;
226
+ if (!payload)
227
+ throw new Error('Accounting.CreateJournalEntries returned no payload.');
228
+ if (!payload.Success) {
229
+ const detail = (payload.Errors ?? []).map((e) => `${e.Code ?? 'ERROR'}: ${e.Message ?? ''}`).join('; ');
230
+ throw new Error(`Journal entry booking failed for the payment allocation. ${detail}`);
231
+ }
232
+ return payload;
233
+ }
234
+ Validate() {
235
+ const result = super.Validate();
236
+ if (!this.OrderHeaderID) {
237
+ result.Success = false;
238
+ result.Errors.push(new ValidationErrorInfo('OrderHeaderID', 'A payment line must name the order it settles.', this.OrderHeaderID, ValidationErrorType.Failure));
239
+ }
240
+ return result;
241
+ }
242
+ /** Returns a message when this application would take the order out of range, else null. */
243
+ async checkApplicationTotal() {
244
+ if (!this.OrderHeaderID || !this.Amount)
245
+ return null;
246
+ const rv = new RunView(this.ProviderToUse);
247
+ const orders = await rv.RunView({
248
+ EntityName: ORDER_HEADER_ENTITY,
249
+ ExtraFilter: `ID='${this.OrderHeaderID}'`,
250
+ Fields: ['TotalGross', 'OrderNumber'],
251
+ ResultType: 'simple',
252
+ BypassCache: true,
253
+ }, this.ContextCurrentUser);
254
+ const order = orders?.Results?.[0];
255
+ // An order we cannot read is not this guard's problem to report — the FK will reject it.
256
+ if (!order)
257
+ return null;
258
+ const siblings = await rv.RunView({
259
+ EntityName: PAYMENT_LINE_ENTITY,
260
+ ExtraFilter: `OrderHeaderID='${this.OrderHeaderID}'`,
261
+ Fields: ['ID', 'Amount'],
262
+ ResultType: 'simple',
263
+ BypassCache: true,
264
+ }, this.ContextCurrentUser);
265
+ // Exclude this row when it is an UPDATE, so an edit is measured against its new value only.
266
+ const existing = (siblings?.Results ?? [])
267
+ .filter((l) => !this.ID || l.ID.toLowerCase() !== String(this.ID).toLowerCase())
268
+ .reduce((sum, l) => sum + Number(l.Amount ?? 0), 0);
269
+ const proposed = Math.round((existing + Number(this.Amount)) * 100) / 100;
270
+ // NO CEILING. Over-applying is deliberately permitted (D68): a customer paying more than an
271
+ // order is worth is an everyday event, and the resulting NEGATIVE balance is exactly how this
272
+ // system represents a customer credit — spendable on another order through the Account Credit
273
+ // tender. The ceiling that used to live here refused that, which is why a payment could not be
274
+ // recorded for what actually arrived. Consistency between a payment and its own allocations is
275
+ // enforced instead, on the payment side (PaymentHeaderEntityServer, D68).
276
+ if (proposed < -TOLERANCE) {
277
+ return (`Applying ${this.Amount} would take the total applied against order ${order.OrderNumber} ` +
278
+ `to ${proposed}. Only ${existing} has ever been applied, so there is nothing more to ` +
279
+ `un-apply.`);
280
+ }
281
+ return null;
282
+ }
283
+ buildRejection(message) {
284
+ const result = new BaseEntityResult();
285
+ result.Success = false;
286
+ result.Type = this.IsSaved ? 'update' : 'create';
287
+ result.Message = message;
288
+ result.OriginalValues = this.Fields.map((f) => ({ FieldName: f.Name, Value: f.OldValue }));
289
+ result.NewValues = this.Fields.map((f) => ({ FieldName: f.Name, Value: f.Value }));
290
+ result.StartedAt = new Date();
291
+ result.EndedAt = new Date();
292
+ return result;
293
+ }
294
+ };
295
+ PaymentLineEntityServer = __decorate([
296
+ RegisterClass(BaseEntity, PAYMENT_LINE_ENTITY)
297
+ ], PaymentLineEntityServer);
298
+ export { PaymentLineEntityServer };
299
+ /** Tree-shaking anchor — the guard lives in Save, reachable only via the registration. */
300
+ export function LoadPaymentLineEntityServer() {
301
+ // intentionally empty
302
+ }
303
+ //# sourceMappingURL=PaymentLineEntityServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaymentLineEntityServer.js","sourceRoot":"","sources":["../src/PaymentLineEntityServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * The parts of talking to a payment gateway that can be got wrong without a network — and therefore
3
+ * the parts worth proving without one.
4
+ *
5
+ * Three things live here, and each is here because its failure mode is silent:
6
+ *
7
+ * 1. MINOR-UNIT CONVERSION. Stripe and most gateways transact in the currency's smallest unit, so
8
+ * $12.34 is `1234`. Getting that wrong is a factor-of-100 error that looks like a plausible
9
+ * amount at both ends — charge 12 cents for a $12 order, or $1,234 for a $12.34 one. Worse, JPY
10
+ * has NO minor unit, so the "obvious" `× 100` overcharges a Japanese customer a hundredfold.
11
+ *
12
+ * 2. WEBHOOK SIGNATURE VERIFICATION. The webhook route is unauthenticated by necessity (D19) — the
13
+ * signature IS the authentication. A verifier that accepts anything is a public endpoint that
14
+ * marks orders paid, and it passes every test that only ever feeds it valid input.
15
+ *
16
+ * 3. IDEMPOTENCY. Gateways retry, and they retry on success too — a webhook that times out on our
17
+ * side is redelivered. Processing one twice books the cash twice.
18
+ *
19
+ * CONNECTS TO:
20
+ * SERVER: ./BasePaymentProvider.ts and the drivers under it
21
+ * ROUTE: ./PaymentWebhookHandler.ts
22
+ * DOC: plans/archive/bizapps-orders-master.md D19, D37
23
+ */
24
+ /** How many minor units make one major unit. */
25
+ export declare function CurrencyExponent(currencyCode: string): number;
26
+ /**
27
+ * Turn an amount we hold as a decimal into the integer the gateway wants.
28
+ *
29
+ * Rounds rather than truncates, and rounds the SCALED value: `Math.round(12.345 * 100)` is 1235 while
30
+ * `Math.round(12.345) * 100` is 1200. Both look like money.
31
+ *
32
+ * Throws on a non-finite amount instead of sending `NaN` to a gateway, which some accept as zero.
33
+ */
34
+ export declare function ToMinorUnits(amount: number, currencyCode: string): number;
35
+ /** And back, for reading what the gateway reported. */
36
+ export declare function FromMinorUnits(minor: number, currencyCode: string): number;
37
+ export interface SignatureVerification {
38
+ Valid: boolean;
39
+ /** Why not, when not. Logged, never returned to the caller — see PaymentWebhookHandler. */
40
+ Reason?: string;
41
+ }
42
+ /**
43
+ * Verify a Stripe-style `Stripe-Signature` header.
44
+ *
45
+ * The scheme: `t=<unix seconds>,v1=<hex hmac>[,v1=<another>]`, where the HMAC is SHA-256 over
46
+ * `${t}.${rawBody}` keyed with the endpoint secret. Multiple `v1` values appear during a secret
47
+ * rotation, and ANY match is a pass — a verifier that only reads the first one breaks silently
48
+ * halfway through a rotation, which is the worst possible moment.
49
+ *
50
+ * THE RAW BODY IS NOT NEGOTIABLE. The signature covers the exact bytes Stripe sent. Any JSON
51
+ * round-trip — key reordering, whitespace, unicode normalisation — changes them, and the signature
52
+ * then fails for a legitimate event. That is why the route captures the raw body before any parser
53
+ * touches it.
54
+ *
55
+ * TIMESTAMP TOLERANCE defends against replay: a valid old payload stays valid forever without it.
56
+ * Default five minutes, matching Stripe's own guidance. `nowSeconds` is a parameter so this is
57
+ * testable without waiting.
58
+ */
59
+ export declare function VerifyWebhookSignature(rawBody: string, signatureHeader: string | null | undefined, secret: string | null | undefined, opts?: {
60
+ NowSeconds?: number;
61
+ ToleranceSeconds?: number;
62
+ }): Promise<SignatureVerification>;
63
+ /** HMAC-SHA256 as lowercase hex, via Web Crypto. */
64
+ export declare function HmacSha256Hex(secret: string, payload: string): Promise<string>;
65
+ /**
66
+ * Constant-time hex comparison.
67
+ *
68
+ * `===` on a signature leaks how many leading characters were right through how long the comparison
69
+ * took. That is a real attack against a public endpoint, and the fix costs nothing. `timingSafeEqual`
70
+ * throws on a length mismatch, so the lengths are checked first — and a mismatched length is itself
71
+ * not secret, since the algorithm fixes it.
72
+ */
73
+ export declare function SignaturesMatch(expected: string, provided: string): boolean;
74
+ /** `PaymentIntent.Status` — the CHECK-constrained set our column allows. */
75
+ export type IntentStatus = 'RequiresPayment' | 'Processing' | 'Succeeded' | 'Canceled' | 'Failed';
76
+ /**
77
+ * Map a gateway's own status onto ours.
78
+ *
79
+ * UNKNOWN MAPS TO `Processing`, NOT to `Succeeded` or `Failed`. A status we do not recognise means the
80
+ * gateway has told us something this code was not written for, and both confident answers are
81
+ * dangerous: `Succeeded` books cash that may not exist, `Failed` abandons a payment that may be fine.
82
+ * `Processing` is the honest reading — something is happening and we do not yet know what — and it
83
+ * leaves the payment for a human or a later event to resolve.
84
+ */
85
+ export declare function MapStripeIntentStatus(providerStatus: string | null | undefined): IntentStatus;
86
+ /** What a webhook should cause, decided before anything is written. */
87
+ export type WebhookAction = 'Apply' | 'AlreadyApplied' | 'Ignore' | 'Reject';
88
+ export interface WebhookDecision {
89
+ Action: WebhookAction;
90
+ Reason: string;
91
+ }
92
+ /**
93
+ * Decide what to do with an event, given what we have already seen.
94
+ *
95
+ * `AlreadyApplied` IS A SUCCESS, and that distinction is the whole point. A gateway that does not get
96
+ * a 2xx retries, so returning an error for a duplicate guarantees it comes back — forever. The
97
+ * response must say "yes, we have this" without doing the work twice.
98
+ *
99
+ * `Ignore` is for events we are not interested in. Gateways send far more than any one integration
100
+ * consumes, and treating an unrecognised event as an error means a Stripe dashboard full of red for
101
+ * events we were never going to read.
102
+ */
103
+ export declare function DecideWebhookAction(input: {
104
+ EventID: string | null | undefined;
105
+ EventKind: string | null | undefined;
106
+ /** True when a `PaymentIntent` row already carries this `ProviderEventID`. */
107
+ AlreadySeen: boolean;
108
+ /** The kinds this integration acts on. */
109
+ HandledKinds: readonly string[];
110
+ /** False when the event names an intent we have no record of. */
111
+ IntentKnown: boolean;
112
+ }): WebhookDecision;
113
+ /**
114
+ * Split a captured amount into the cash actually received and the gateway's cut.
115
+ *
116
+ * The capture entry is `Dr Cash (net) / Dr Processing Fee / Cr A/R (gross)` (D18), so these three
117
+ * numbers must reconcile exactly or the entry will not balance. Deriving `net` by subtraction rather
118
+ * than trusting a reported net is deliberate: a gateway that rounds its own net differently would
119
+ * leave a penny with no home in the ledger.
120
+ *
121
+ * ALL THREE ARE EXACT AT 2DP, BUT `Net + Fee` IN JAVASCRIPT IS NOT. Adding two correctly-rounded
122
+ * decimals drifts in binary floating point — 32.06 + 1.27 is 33.330000000000005 — so a caller
123
+ * reconciling them must round the SUM before comparing, exactly as `Money()` does everywhere else in
124
+ * this package. This is the same hazard that made a balanced journal entry fail an exact-equality check
125
+ * in accounting; the numbers were never wrong, the comparison was.
126
+ */
127
+ export declare function SplitCapturedAmount(grossAmount: number, feeAmount: number): {
128
+ Gross: number;
129
+ Fee: number;
130
+ Net: number;
131
+ };
132
+ /**
133
+ * Stripe's published US bank-debit price: 0.8% of the amount, capped at $5.
134
+ *
135
+ * FOR THE STUB ONLY, and the name says so deliberately. The live path reads the fee off the charge's
136
+ * balance transaction like every other capture — what Stripe actually charged is a fact, and computing
137
+ * it here would be this file's opinion competing with the gateway's record. A stub that reported a
138
+ * ZERO fee would be worse still: it would make the fee leg of the capture entry (D18) unreachable in
139
+ * every test, so the arithmetic most worth exercising would be the arithmetic never exercised. That is
140
+ * the same reasoning behind the card stub's 2.9% + 30c, and the same reason this constant will drift
141
+ * from Stripe's price list one day without breaking anything real.
142
+ *
143
+ * The cap is a MAJOR-UNIT USD figure. A bank debit is a US rail, so the currency is USD in practice;
144
+ * a caller passing anything else gets the percentage without the cap rather than a cap converted at a
145
+ * rate this module has no business knowing.
146
+ */
147
+ export declare function AchFeeEstimate(grossAmount: number, currencyCode?: string): number;
148
+ /**
149
+ * What a settlement event should do to the payment we opened for it.
150
+ *
151
+ * `Hold` is the important one and the reason this is a decision table rather than an `if`. It means
152
+ * the event and the payment disagree in a way this code was not written for — a success against a
153
+ * refunded payment, a capture with no ledger entry behind it — and the honest response is to record
154
+ * nothing and say so. Both confident answers are worse: acting books or unbooks real money on a
155
+ * reading we have already admitted we do not understand.
156
+ */
157
+ export type SettlementAction = 'Promote' | 'Fail' | 'Reverse' | 'Hold' | 'None';
158
+ export interface SettlementDecision {
159
+ Action: SettlementAction;
160
+ Reason: string;
161
+ }
162
+ /**
163
+ * Decide what a bank-debit event does to its payment.
164
+ *
165
+ * THE ASYMMETRY IS THE WHOLE DESIGN. A card tells you at the till; a bank debit tells you up to four
166
+ * business days later, and it can tell you TWICE — "taken" and then, a week after that, "returned"
167
+ * (insufficient funds, account closed, unauthorised). So there is no single moment where the answer is
168
+ * known, and a payment has to be able to move forward AND backward:
169
+ *
170
+ * Pending + succeeded → `Promote` the payment becomes Captured, which is what books the cash
171
+ * Pending + failed → `Fail` nothing was ever booked, so nothing needs reversing
172
+ * Captured + failed → `Reverse` the money left again; a REVERSING payment says so in the ledger
173
+ *
174
+ * WHY `Reverse` AND NOT AN UPDATE. A returned debit is not "the payment never happened" — it happened,
175
+ * the ledger recorded it, a period may have closed over it. Editing the original would erase a true
176
+ * fact about a past date. A reversing payment is the same answer the rest of this application already
177
+ * gives (`ReversesPaymentHeaderID`, D53), and it leaves both facts standing.
178
+ *
179
+ * `None` covers the ordinary quiet cases — an event that changes nothing, a promotion that already
180
+ * happened — and is a SUCCESS. A gateway that does not get a 2xx retries forever.
181
+ */
182
+ export declare function DecideSettlement(input: {
183
+ /** How the driver read the intent after this event. */
184
+ EventStatus: IntentStatus | null | undefined;
185
+ /** `PaymentHeader.Status`, or null when no payment was opened for this intent. */
186
+ HeaderStatus: string | null | undefined;
187
+ /** True when the header carries a `JournalEntryID` — the cash is in the ledger. */
188
+ HeaderBooked: boolean;
189
+ /** True when a reversing payment already points at this one. */
190
+ AlreadyReversed: boolean;
191
+ }): SettlementDecision;
192
+ /** What the save path knows about a payment that is asking to become `Captured`. */
193
+ export interface CaptureTimingFacts {
194
+ /** The status the caller wrote. */
195
+ RequestedStatus: string;
196
+ /** The status already on disk, or undefined for a new payment. */
197
+ PersistedStatus?: string | null;
198
+ /** False for a payment being inserted. */
199
+ IsSaved: boolean;
200
+ /** False for a RECORDED payment — cheque, cash, wire — which has no gateway to wait for. */
201
+ HasProvider: boolean;
202
+ /** The driver's own declaration. See `BasePaymentProvider.SettlesAsynchronously`. */
203
+ SettlesAsynchronously: boolean;
204
+ }
205
+ /**
206
+ * Whether a payment asking to be `Captured` must be held at `Pending` because its rail settles on
207
+ * somebody else's schedule.
208
+ *
209
+ * WHY THIS IS A FUNCTION AND NOT AN `IF` IN THE SAVE PATH. The rule used to live only in
210
+ * `Orders.CapturePayment`, which made it a rule that ONE CALLER followed rather than one the system
211
+ * enforced — a workflow, a UI form or a test builder writing `Status: 'Captured'` went straight past
212
+ * it and booked `Dr Cash` for a bank debit that had not cleared. Balanced, posted, and undetectable
213
+ * downstream. Stating it here means the entity server and the operation ask the same question of the
214
+ * same code instead of both remembering.
215
+ *
216
+ * THE PROMOTION MUST PASS. When the webhook moves a `Pending` payment to `Captured`, that IS the
217
+ * bank answering; holding it again would mean a bank debit could never book at all. The persisted
218
+ * status is the signal — already `Pending` means promotion, anything else means a caller declaring
219
+ * cash that has not moved.
220
+ */
221
+ export declare function ShouldHoldForLateSettlement(facts: CaptureTimingFacts): boolean;
222
+ //# sourceMappingURL=PaymentProviderBehavior.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaymentProviderBehavior.d.ts","sourceRoot":"","sources":["../src/PaymentProviderBehavior.ts"],"names":[],"mappings":"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"}