@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,260 @@
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
+ * OrderLineEntityServer — line-level invariants and engine-materialized totals.
9
+ *
10
+ * Two jobs, both of which must happen server-side because the journal entry is derived from them:
11
+ *
12
+ * 1. STAMP THE COMPANY (plan D6). `OrderLine.CompanyID` is a denormalized copy of the
13
+ * product's company, captured at save time so the line records who owned the product at
14
+ * transaction time even if product ownership later moves. It is derived, never authored —
15
+ * whatever a caller passes is overwritten.
16
+ *
17
+ * 2. COMPUTE THE TOTALS. `LineTotalNet` / `LineTotalGross` are engine-materialized and never
18
+ * user-entered:
19
+ * LineTotalNet = (Quantity × UnitPrice × (1 − DiscountPct)) − DiscountAmount
20
+ * LineTotalGross = LineTotalNet + LineTax + ChargeAmount
21
+ *
22
+ * DiscountPct and DiscountAmount are both applied, in that order, because they mean different
23
+ * things: a percentage is a negotiated concession on the line, an amount is an allocated share
24
+ * of a promotion (D70). The net is clamped TOWARD ZERO, in whichever direction the line runs —
25
+ * a discount larger than the line is a configuration mistake and must not turn a sale into a
26
+ * credit, but a reversal line (D16) is legitimately negative and must not be flattened to zero.
27
+ * The rule lives in `PricingBehavior.NetAfterDiscount`, shared with the charge/tax base, because
28
+ * it was written twice and both copies had the same bug.
29
+ * The journal entry is built from the same arithmetic, so a client-supplied total can never
30
+ * disagree with what was booked.
31
+ *
32
+ * The DB trigger (51003) freezes these columns once the parent order is Confirmed, so this runs
33
+ * meaningfully only while the order is still open.
34
+ *
35
+ * CONNECTS TO:
36
+ * FACTORY: OrderJournalEntryFactory (./OrderJournalEntryFactory.ts) — mirrors this arithmetic
37
+ */
38
+ import { BaseEntity, RunView, ValidationErrorInfo, ValidationErrorType, } from '@memberjunction/core';
39
+ import { RegisterClass } from '@memberjunction/global';
40
+ import { IsBooked, LineGross, NetAfterDiscount, OrderLineEntity } from '@mj-biz-apps/orders-entities';
41
+ import { ORDER_HEADER_ENTITY } from './entity-names.js';
42
+ import { RequireUUID } from './sql-guards.js';
43
+ const ORDER_LINE_ENTITY = 'MJ_BizApps_Orders: Order Lines';
44
+ const PRODUCT_ENTITY = 'MJ_BizApps_Orders: Products';
45
+ function money(value) {
46
+ return Math.round((value + Number.EPSILON) * 100) / 100;
47
+ }
48
+ let OrderLineEntityServer = class OrderLineEntityServer extends OrderLineEntity {
49
+ constructor() {
50
+ super(...arguments);
51
+ /**
52
+ * The exact extended amount the price rule computed, when a rule priced this line.
53
+ *
54
+ * TRANSIENT — not a column, and deliberately so. It is the pricing pass handing
55
+ * this line the figure it already computed exactly, rather than the line
56
+ * re-deriving it from a unit rate that cannot always represent it (see
57
+ * {@link LineGross}). Persisting it would add a column whose only job is to
58
+ * restate `LineTotalNet` before discount, and a second stored number that can
59
+ * disagree with the first is the thing worth avoiding.
60
+ *
61
+ * Null means "no rule priced this" — a hand-typed unit price, where the unit
62
+ * rate genuinely IS the authority — and the classic quantity × price applies.
63
+ */
64
+ this.ResolvedExtendedAmount = null;
65
+ /** Set by OrderEntityServer when saving lines as part of an order graph save/booking. */
66
+ this.BypassBookedCheck = false;
67
+ }
68
+ /**
69
+ * `BaseEntity` skips `ValidateAsync` unless a subclass opts in, so without this the checks
70
+ * below never run when a line is saved on its own. The order's own `ValidateAsync` loops over
71
+ * its lines and would have covered the confirm path — except that one was skipped for the same
72
+ * reason, so in practice nothing here was enforced anywhere. See the note on
73
+ * `OrderEntityServer.DefaultSkipAsyncValidation`.
74
+ */
75
+ get DefaultSkipAsyncValidation() {
76
+ return false;
77
+ }
78
+ async ValidateAsync() {
79
+ const result = await super.ValidateAsync();
80
+ // Quantity <> 0 is a DB CHECK; negative quantities are legal only as reversal slices
81
+ // (plan D16), which is a cross-field rule the database cannot express.
82
+ if (this.Quantity < 0 && !this.ReversesOrderLineID) {
83
+ result.Success = false;
84
+ result.Errors.push(new ValidationErrorInfo('Quantity', `A negative quantity is only valid on a reversal line. Set ReversesOrderLineID to the ` +
85
+ `line being reversed, or use a positive quantity.`, this.Quantity, ValidationErrorType.Failure));
86
+ }
87
+ await this.refuseNewLineOnBookedOrder(result);
88
+ return result;
89
+ }
90
+ /**
91
+ * A new line saved on its own (not through the order graph) still has to
92
+ * refuse a booked parent. Header.Validate covers the graph path; this
93
+ * covers the standalone path.
94
+ */
95
+ async refuseNewLineOnBookedOrder(result) {
96
+ if (this.IsSaved || !this.OrderHeaderID || this.BypassBookedCheck)
97
+ return;
98
+ const rv = new RunView(this.ProviderToUse);
99
+ const lookup = await rv.RunView({
100
+ EntityName: ORDER_HEADER_ENTITY,
101
+ ExtraFilter: `ID='${RequireUUID(this.OrderHeaderID, 'OrderHeaderID')}'`,
102
+ Fields: ['ID', 'Status'],
103
+ ResultType: 'simple',
104
+ }, this.ContextCurrentUser);
105
+ const status = lookup?.Results?.[0]?.Status;
106
+ if (!status || !IsBooked(status))
107
+ return;
108
+ result.Success = false;
109
+ result.Errors.push(new ValidationErrorInfo('OrderHeaderID', `Order line cannot be added — the order is booked. Corrections to booked orders go through reversal orders.`, this.OrderHeaderID, ValidationErrorType.Failure));
110
+ }
111
+ /**
112
+ * Populate the fields this line DERIVES rather than accepts, so it is valid before anything
113
+ * validates it.
114
+ *
115
+ * Public because the ORDER now has to call it. `Lines` is a related-record collection, and
116
+ * MJ validates every companion from the PARENT's save — deliberately, so a cross-record
117
+ * invariant sees the whole graph before the first row lands. But that runs before any child's
118
+ * own `Save()`, and `CompanyID` is stamped here, inside this class's `Save()`. The result was
119
+ * that every confirm failed with `Lines[0].CompanyID: Company cannot be null` — a NOT NULL
120
+ * column the line derives from its product and no caller ever authors.
121
+ *
122
+ * Idempotent, so the ordinary path (`Save()` calling it directly) is unaffected, and a line
123
+ * that was prepared by its order and then saved individually simply re-derives the same values.
124
+ */
125
+ async PrepareForSave() {
126
+ await this.stampCompanyFromProduct();
127
+ this.computeTotals();
128
+ }
129
+ async Save(options) {
130
+ await this.PrepareForSave();
131
+ const ok = await super.Save(options);
132
+ if (!ok) {
133
+ return false;
134
+ }
135
+ await this.persistExtension(options);
136
+ return true;
137
+ }
138
+ async persistExtension(options) {
139
+ if (!this.Extension.IsConfigured) {
140
+ return;
141
+ }
142
+ const ext = await this.Extension.EnsureEntity();
143
+ if (!ext) {
144
+ return;
145
+ }
146
+ if (this.ID && (!ext.Get('ID') || ext.Get('ID') !== this.ID)) {
147
+ ext.Set('ID', this.ID);
148
+ }
149
+ // If the extension is an IS-A child of this line, sync the saved parent state
150
+ // so the extension's inner save knows the parent row is already persisted in the database.
151
+ const parent = ext.ISAParent;
152
+ if (parent) {
153
+ await parent.LoadFromData(this.GetAll(), true);
154
+ }
155
+ // A persisted IS-A child with no leaf-owned dirt has nothing to write.
156
+ // Re-saving it re-enters BaseEntity's child-save path; after the parent
157
+ // row is already persisted, that path only re-hydrates from GetAll(),
158
+ // which includes parent virtuals the child does not own (e.g. OrderHeader).
159
+ if (parent && ext.IsSaved && !this.extensionHasLeafDirtyFields(ext)) {
160
+ return;
161
+ }
162
+ if (!ext.IsSaved || ext.Dirty) {
163
+ const saved = await ext.Save(options);
164
+ if (!saved) {
165
+ throw new Error(`Failed to save line extension '${this.Extension.EntityName}' for order line ${this.LineNumber}: ` +
166
+ (ext.LatestResult?.CompleteMessage ?? 'unknown error'));
167
+ }
168
+ }
169
+ }
170
+ extensionHasLeafDirtyFields(ext) {
171
+ const parentNames = ext.EntityInfo.ParentEntityFieldNames;
172
+ return ext.Fields.some((f) => f.Dirty && !parentNames.has(f.Name));
173
+ }
174
+ /** Derived from the product, always — plan D6. */
175
+ async stampCompanyFromProduct() {
176
+ if (!this.ProductID)
177
+ return;
178
+ const rv = new RunView(this.ProviderToUse);
179
+ const result = await rv.RunView({
180
+ EntityName: PRODUCT_ENTITY,
181
+ ExtraFilter: `ID='${this.ProductID}'`,
182
+ Fields: ['ID', 'CompanyID'],
183
+ ResultType: 'simple',
184
+ }, this.ContextCurrentUser);
185
+ const product = result?.Results?.[0];
186
+ if (product?.CompanyID) {
187
+ this.CompanyID = product.CompanyID;
188
+ }
189
+ }
190
+ computeTotals() {
191
+ // ROUND THE DISCOUNT TO ITS COLUMN'S SCALE FIRST, and store the rounded value.
192
+ //
193
+ // `DiscountPct` is `DECIMAL(7,4)`. Computing with an unrounded rate and storing a rounded one
194
+ // makes the application and the database disagree about the same line: a third off 900 is
195
+ // 600.00 by full precision and 600.03 by the stored 0.3333.
196
+ //
197
+ // That disagreement does not surface until the line is UPDATED — which happens when
198
+ // `JournalEntryID` is stamped after booking. `computeTotals` runs again, now reading 0.3333
199
+ // back from the row, produces 600.03, and the immutability trigger correctly refuses to let
200
+ // booked money change. The confirm then fails with 'Failed to stamp JournalEntryID', which
201
+ // names neither the discount nor the rounding, and any DiscountPct with more than four
202
+ // decimal places is simply un-bookable.
203
+ //
204
+ // `savePendingLines` already does exactly this for `Quantity` and for exactly this reason;
205
+ // the discount never got the same treatment. Assigning the rounded value here means the two
206
+ // can never diverge again, whichever path set it.
207
+ // A BOOKED LINE'S MONEY IS FROZEN — so do not recompute it.
208
+ //
209
+ // Trigger 51003 already enforces this at the database, and that is precisely
210
+ // the problem: the line is saved a SECOND time to stamp JournalEntryID after
211
+ // booking, computeTotals runs again, and any figure it cannot reproduce from
212
+ // stored state alone comes out different. The trigger then correctly refuses
213
+ // the change and the whole confirm rolls back, reported as a stamping failure
214
+ // that names neither the total nor the cause.
215
+ //
216
+ // That is not hypothetical — it is how a flat-priced line failed: the exact
217
+ // extended amount is known while pricing is in flight, but the reloaded line
218
+ // has only quantity and a derived unit rate, which for a Flat rule cannot
219
+ // reproduce the total (3 × 33.33 = 99.99, not 100.00). Rather than make the
220
+ // arithmetic reproducible from a rate that provably cannot represent every
221
+ // total, respect the rule the trigger already states: once booked, these
222
+ // columns are history, not a derivation.
223
+ if (this.JournalEntryID)
224
+ return;
225
+ const pct = Math.round((this.DiscountPct ?? 0) * 1e4) / 1e4;
226
+ if (pct !== (this.DiscountPct ?? 0))
227
+ this.DiscountPct = pct;
228
+ // A ROLLUP PARENT CONTRIBUTES NOTHING (D45).
229
+ //
230
+ // An expanded bundle's parent line is customer-facing: it keeps its UnitPrice so an invoice
231
+ // can print "Gold Package — 100", but the money lives on the children, which carry the
232
+ // allocated shares. Letting the parent compute a line total as well would DOUBLE the order —
233
+ // and do it invisibly, because the parent's own arithmetic is perfectly correct and every
234
+ // child's is too. The header rollup trigger sums LineTotalGross across all lines, so zero
235
+ // here is what keeps it honest without the trigger needing to know bundles exist.
236
+ //
237
+ // Deliberately after the DiscountPct rounding above, so the stored rate stays consistent
238
+ // whether or not the line happens to be a parent.
239
+ if (this.IsRollupParent) {
240
+ this.LineTotalNet = 0;
241
+ this.LineTotalGross = 0;
242
+ return;
243
+ }
244
+ // `NetAfterDiscount` is shared with the charge/tax base in OrderEntityServer. It used to be
245
+ // computed independently in both places, and both clamped a reversal line to zero — see
246
+ // PricingBehavior for what that cost.
247
+ const net = NetAfterDiscount(LineGross(this.Quantity, this.UnitPrice, this.ResolvedExtendedAmount), pct, this.DiscountAmount ?? 0);
248
+ this.LineTotalNet = net;
249
+ this.LineTotalGross = money(net + (this.LineTax ?? 0) + (this.ChargeAmount ?? 0));
250
+ }
251
+ };
252
+ OrderLineEntityServer = __decorate([
253
+ RegisterClass(BaseEntity, ORDER_LINE_ENTITY)
254
+ ], OrderLineEntityServer);
255
+ export { OrderLineEntityServer };
256
+ /** Tree-shaking anchor — call from the server bootstrap so @RegisterClass is retained. */
257
+ export function LoadOrderLineEntityServer() {
258
+ // intentionally empty
259
+ }
260
+ //# sourceMappingURL=OrderLineEntityServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrderLineEntityServer.js","sourceRoot":"","sources":["../src/OrderLineEntityServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { IMetadataProvider, UserInfo } from '@memberjunction/core';
2
+ /** Setting keys, in one place so a typo is a compile error rather than a silent default. */
3
+ export declare const ORDERS_SETTING: {
4
+ /**
5
+ * Whether confirming an order stamps the ship-to/bill-to organization from the named person's
6
+ * affiliation when the organization was left blank (D64).
7
+ */
8
+ readonly AutoPopulateOrganizationFromPerson: "AutoPopulateOrganizationFromPerson";
9
+ /**
10
+ * Comma-separated `RelationshipType` NAMES that count as an organizational affiliation for the
11
+ * rule above. Names rather than IDs because `RelationshipType` is a seeded lookup in
12
+ * bizapps-common — extensible data, so a deployment can add its own type and list it here
13
+ * without a schema change on either side.
14
+ */
15
+ readonly OrganizationAffiliationRelationshipTypes: "OrganizationAffiliationRelationshipTypes";
16
+ };
17
+ export declare class OrdersSettings {
18
+ private static _localOverrides;
19
+ /**
20
+ * Load the settings cache. Idempotent and cheap after the first call; the entity servers invoke
21
+ * it on the booking path so callers rarely need to.
22
+ */
23
+ static Load(provider: IMetadataProvider, user: UserInfo): Promise<void>;
24
+ /** Override a setting value for tests. Pass undefined to remove the override. */
25
+ static SetOverride(key: string, value: string | undefined): void;
26
+ /** Clear all test overrides. */
27
+ static ClearOverrides(): void;
28
+ /** The `__mj_BizAppsOrders` Application ID, or undefined when the app row is absent. */
29
+ private static applicationID;
30
+ private static raw;
31
+ /** Stamp the organization from the person's affiliation when it was left blank (D64). */
32
+ static get AutoPopulateOrganizationFromPerson(): boolean;
33
+ /** `RelationshipType` names that count as an organizational affiliation. */
34
+ static get OrganizationAffiliationRelationshipTypes(): string[];
35
+ }
36
+ //# sourceMappingURL=OrdersSettings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrdersSettings.d.ts","sourceRoot":"","sources":["../src/OrdersSettings.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,iBAAiB,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAM7E,4FAA4F;AAC5F,eAAO,MAAM,cAAc;IACvB;;;OAGG;;IAEH;;;;;OAKG;;CAEG,CAAC;AAiDX,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAC,eAAe,CAA6B;IAE3D;;;OAGG;WACiB,IAAI,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpF,iFAAiF;WACnE,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAqBvE,gCAAgC;WAClB,cAAc,IAAI,IAAI;IAKpC,wFAAwF;IACxF,OAAO,CAAC,MAAM,CAAC,aAAa;IAK5B,OAAO,CAAC,MAAM,CAAC,GAAG;IAYlB,yFAAyF;IACzF,WAAkB,kCAAkC,IAAI,OAAO,CAK9D;IAED,4EAA4E;IAC5E,WAAkB,wCAAwC,IAAI,MAAM,EAAE,CAKrE;CAEJ"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Typed access to this app's settings (plan D63).
3
+ *
4
+ * MJ already owns the mechanism: `__mj.ApplicationSetting` rows scoped to an `Application`, cached
5
+ * and auto-refreshed by `ApplicationSettingEngine` in `@memberjunction/core-entities`. This is NOT a
6
+ * second engine — it is a thin typed façade over that one, so callers read
7
+ * `OrdersSettings.AutoPopulateOrganizationFromPerson` (a real boolean, default applied) instead of
8
+ * parsing `"true"` at each call site and re-deciding the default every time.
9
+ *
10
+ * WHY A FAÇADE AT ALL
11
+ * `GetSetting` returns `string | undefined`. Every consumer would otherwise repeat the same three
12
+ * decisions — what the key is called, what the default is, and how to coerce — and they would drift.
13
+ * Naming the defaults in one place is what makes "the setting is off" and "the setting was never
14
+ * configured" behave identically on purpose rather than by accident.
15
+ *
16
+ * The engine is a BaseEngine, so `AutoRefresh` (default true) propagates a change made through the
17
+ * entity API without a restart. Callers must still have called `Config()` once — the entity servers
18
+ * do that on the booking path.
19
+ *
20
+ * CONNECTS TO:
21
+ * ENGINE: ApplicationSettingEngine (@memberjunction/core-entities)
22
+ * TABLE: __mj.ApplicationSetting, scoped to the '__mj_BizAppsOrders' Application row
23
+ */
24
+ import { ApplicationSettingEngine } from '@memberjunction/core-entities';
25
+ import { Metadata } from '@memberjunction/core';
26
+ /** The `MJ: Applications` row this app's settings hang off. */
27
+ const ORDERS_APPLICATION_NAME = '__mj_BizAppsOrders';
28
+ /** Setting keys, in one place so a typo is a compile error rather than a silent default. */
29
+ export const ORDERS_SETTING = {
30
+ /**
31
+ * Whether confirming an order stamps the ship-to/bill-to organization from the named person's
32
+ * affiliation when the organization was left blank (D64).
33
+ */
34
+ AutoPopulateOrganizationFromPerson: 'AutoPopulateOrganizationFromPerson',
35
+ /**
36
+ * Comma-separated `RelationshipType` NAMES that count as an organizational affiliation for the
37
+ * rule above. Names rather than IDs because `RelationshipType` is a seeded lookup in
38
+ * bizapps-common — extensible data, so a deployment can add its own type and list it here
39
+ * without a schema change on either side.
40
+ */
41
+ OrganizationAffiliationRelationshipTypes: 'OrganizationAffiliationRelationshipTypes',
42
+ };
43
+ /**
44
+ * Defaults, applied when a setting is absent.
45
+ *
46
+ * `Employee` only, deliberately. The seeded types include `Vendor`, `Customer` and `Friend`, and a
47
+ * person being a VENDOR to an organization must not make that organization their bill-to. Widening
48
+ * this is a data change, not a release — which is the whole point of it being a setting.
49
+ */
50
+ const DEFAULTS = {
51
+ AutoPopulateOrganizationFromPerson: true,
52
+ OrganizationAffiliationRelationshipTypes: ['Employee'],
53
+ };
54
+ /** Anything other than an explicit falsey string is true — an unparseable value should not disable a feature silently. */
55
+ function asBoolean(raw, fallback) {
56
+ if (raw == null)
57
+ return fallback;
58
+ const v = raw.trim().toLowerCase();
59
+ if (['false', '0', 'no', 'off'].includes(v))
60
+ return false;
61
+ if (['true', '1', 'yes', 'on'].includes(v))
62
+ return true;
63
+ return fallback;
64
+ }
65
+ function asList(raw, fallback) {
66
+ if (raw == null)
67
+ return [...fallback];
68
+ const parts = raw
69
+ .split(',')
70
+ .map((p) => p.trim())
71
+ .filter((p) => p.length > 0);
72
+ // An explicitly EMPTY list means "no type qualifies", which switches the feature off just as
73
+ // surely as the boolean does. That is a legitimate way to configure it, so it is honoured
74
+ // rather than being treated as "unset" and silently replaced by the default.
75
+ return parts;
76
+ }
77
+ const OVERRIDES_STORE_KEY = '__orders_settings_overrides__';
78
+ function getOverridesMap() {
79
+ const g = globalThis;
80
+ if (!g[OVERRIDES_STORE_KEY]) {
81
+ g[OVERRIDES_STORE_KEY] = new Map();
82
+ }
83
+ return g[OVERRIDES_STORE_KEY];
84
+ }
85
+ export class OrdersSettings {
86
+ static { this._localOverrides = new Map(); }
87
+ /**
88
+ * Load the settings cache. Idempotent and cheap after the first call; the entity servers invoke
89
+ * it on the booking path so callers rarely need to.
90
+ */
91
+ static async Load(provider, user) {
92
+ await ApplicationSettingEngine.Instance.Config(false, user, provider);
93
+ }
94
+ /** Override a setting value for tests. Pass undefined to remove the override. */
95
+ static SetOverride(key, value) {
96
+ const map = getOverridesMap();
97
+ if (value === undefined) {
98
+ map.delete(key);
99
+ this._localOverrides.delete(key);
100
+ }
101
+ else {
102
+ map.set(key, value);
103
+ this._localOverrides.set(key, value);
104
+ }
105
+ try {
106
+ const engine = ApplicationSettingEngine.Instance;
107
+ for (const s of engine.ApplicationSettings) {
108
+ if (s.Name === key) {
109
+ s.Value = value ?? '';
110
+ }
111
+ }
112
+ }
113
+ catch {
114
+ // ignore
115
+ }
116
+ }
117
+ /** Clear all test overrides. */
118
+ static ClearOverrides() {
119
+ this._localOverrides.clear();
120
+ getOverridesMap().clear();
121
+ }
122
+ /** The `__mj_BizAppsOrders` Application ID, or undefined when the app row is absent. */
123
+ static applicationID() {
124
+ const apps = new Metadata().Applications;
125
+ return apps?.find((a) => a.Name === ORDERS_APPLICATION_NAME || a.Name === 'MJ_BizApps_Orders' || a.Name === 'Orders')?.ID;
126
+ }
127
+ static raw(key) {
128
+ if (this._localOverrides.has(key)) {
129
+ return this._localOverrides.get(key);
130
+ }
131
+ const map = getOverridesMap();
132
+ if (map.has(key)) {
133
+ return map.get(key);
134
+ }
135
+ const appID = this.applicationID();
136
+ return ApplicationSettingEngine.Instance.GetSetting(key, appID);
137
+ }
138
+ /** Stamp the organization from the person's affiliation when it was left blank (D64). */
139
+ static get AutoPopulateOrganizationFromPerson() {
140
+ return asBoolean(this.raw(ORDERS_SETTING.AutoPopulateOrganizationFromPerson), DEFAULTS.AutoPopulateOrganizationFromPerson);
141
+ }
142
+ /** `RelationshipType` names that count as an organizational affiliation. */
143
+ static get OrganizationAffiliationRelationshipTypes() {
144
+ return asList(this.raw(ORDERS_SETTING.OrganizationAffiliationRelationshipTypes), DEFAULTS.OrganizationAffiliationRelationshipTypes);
145
+ }
146
+ }
147
+ //# sourceMappingURL=OrdersSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrdersSettings.js","sourceRoot":"","sources":["../src/OrdersSettings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Intercompany balancing on the payment side — the other half of D13.
3
+ *
4
+ * THE BUG THIS FIXES
5
+ * Capture booked `Dr Cash / Cr AR` against the RECEIVING company and nothing else. When company A
6
+ * collected cash settling a line owned by company B, A's receivable was credited for money A was
7
+ * never owed, and B's receivable stayed open forever. Both books misstated, nothing reconciling
8
+ * them, and no assertion anywhere would fail — the entry balanced perfectly. The `payment-ledger`
9
+ * suite missed it entirely because every check used a single-company order.
10
+ *
11
+ * THE SHAPE (plans/archive/intercompany-balancing.md §2)
12
+ * ONE JOURNAL ENTRY PER (PAYMENT LINE × COMPANY). This is the provenance rule booking already
13
+ * uses — an OrderLine produces a JE that points back at the line — extended to the payment side.
14
+ *
15
+ * Receiving company: Dr Cash the whole payment-line amount
16
+ * Cr AR its OWN share (omitted when it owns no line)
17
+ * Cr Due To <other> one line per other company, never netted
18
+ *
19
+ * Each other company: Dr Due From <receiving> its share
20
+ * Cr AR its share
21
+ *
22
+ * For a single-company order this collapses to exactly the previous behaviour — one entry,
23
+ * `Dr Cash / Cr AR`. Multi-company is the general case, not a special one.
24
+ *
25
+ * WHY EVERY ENTRY IS SINGLE-COMPANY: accounting derives an entry's company from its ACCOUNTS
26
+ * (their CH-2) and D6 hard-blocks cross-company mapping, so an entry spanning companies could not
27
+ * be booked at all. The shape is forced, not chosen.
28
+ *
29
+ * WHY THE DUE-TO CREDITS STAY SEPARATE: `Cr Due To B 200` and `Cr Due To C 300` are two lines, not
30
+ * one netted `Cr Due To 500`. Aggregation is recoverable downstream; the derivation is not.
31
+ *
32
+ * A MISSING PAIR IS FATAL. There is no fallback account, because a guessed intercompany account
33
+ * still balances — the misposting would be invisible until two entities' books disagree.
34
+ *
35
+ * CONNECTS TO:
36
+ * LOOKUP: AccountingEngineBase.ResolveIntercompanyAccounts (BA-D26, bizapps-accounting)
37
+ * RESOLVER: GLAccountResolver (./GLAccountResolver.ts)
38
+ * CALLER: PaymentLineEntityServer (./PaymentLineEntityServer.ts)
39
+ * DOC: plans/archive/intercompany-balancing.md
40
+ */
41
+ import { type GLAccountResolver } from './GLAccountResolver.js';
42
+ import type { PaymentJEDraft } from './PaymentJournalEntryFactory.js';
43
+ /** One order line's contribution, as far as allocation is concerned. */
44
+ export interface OrderLineShare {
45
+ OrderLineID: string;
46
+ /** The company that OWNS the line — the product's company (D6), already stamped on the line. */
47
+ CompanyID: string;
48
+ /** The line's gross amount. Used as the pro-rating weight. */
49
+ Amount: number;
50
+ }
51
+ /** What one company is owed out of a single payment line. */
52
+ export interface CompanyShare {
53
+ CompanyID: string;
54
+ Amount: number;
55
+ }
56
+ /** The intercompany account pair for an ordered company pair, or null when none is configured. */
57
+ export interface IntercompanyPair {
58
+ DueToGLAccountID: string;
59
+ DueFromGLAccountID: string;
60
+ }
61
+ /**
62
+ * Looks up the pair for (source collected on behalf of target), as of a date.
63
+ * Injected rather than imported so the allocation math is unit-testable without an engine.
64
+ */
65
+ export type IntercompanyLookup = (sourceCompanyID: string, targetCompanyID: string, asOf: Date) => IntercompanyPair | null;
66
+ export interface PaymentLineAllocationContext {
67
+ PaymentLineID: string;
68
+ PaymentNumber: string;
69
+ OrderNumber: string;
70
+ /** What this payment line applies to the order. Always positive; `IsReversal` sets direction. */
71
+ Amount: number;
72
+ /** Where the cash landed. */
73
+ ReceivingCompanyID: string;
74
+ /** Every line on the order this payment line settles. */
75
+ OrderLines: OrderLineShare[];
76
+ /**
77
+ * Set when the payment line targets ONE order line (`PaymentLine.OrderLineID`). Then the whole
78
+ * amount belongs to that line's company and no pro-rating happens — the simpler case, not the
79
+ * harder one, because one line means one company means no intercompany legs at all.
80
+ */
81
+ TargetOrderLineID?: string | null;
82
+ PaymentDate: Date;
83
+ /** True when un-applying (a refund or a negative allocation) — every entry mirrors. */
84
+ IsReversal: boolean;
85
+ }
86
+ export interface PaymentAllocationResult {
87
+ /** One draft per company. The receiving company's is always first. */
88
+ Drafts: PaymentJEDraft[];
89
+ /** The per-company split that produced them — surfaced for assertions and diagnostics. */
90
+ Shares: CompanyShare[];
91
+ }
92
+ export declare class IntercompanyPairMissingError extends Error {
93
+ readonly SourceCompanyID: string;
94
+ readonly TargetCompanyID: string;
95
+ constructor(SourceCompanyID: string, TargetCompanyID: string, message: string);
96
+ }
97
+ /**
98
+ * Split a payment-line amount across the companies owning the order's lines.
99
+ *
100
+ * Pure and exported for unit tests — this is where the money actually gets divided, and a rounding
101
+ * slip here would show up as an unbalanced entry or a cent stranded on the wrong company's books.
102
+ *
103
+ * Targeting one order line short-circuits the whole thing: the amount belongs to that line's
104
+ * company outright. Otherwise each company gets its proportional share of the order's total, and
105
+ * **the largest share absorbs the rounding residue** so the parts always sum to the whole.
106
+ */
107
+ export declare function AllocateByCompany(amount: number, orderLines: OrderLineShare[], targetOrderLineID?: string | null): CompanyShare[];
108
+ export declare class PaymentAllocationFactory {
109
+ private readonly _resolver;
110
+ private readonly _intercompany;
111
+ private readonly _paymentLineEntityID;
112
+ constructor(_resolver: GLAccountResolver, _intercompany: IntercompanyLookup, _paymentLineEntityID: string);
113
+ /**
114
+ * Build every journal entry a single payment line causes.
115
+ *
116
+ * The caller owns the transaction and the write; this computes only.
117
+ */
118
+ BuildAllocationDrafts(ctx: PaymentLineAllocationContext): Promise<PaymentAllocationResult>;
119
+ private toDraft;
120
+ /**
121
+ * Balance each entry before it leaves this class.
122
+ *
123
+ * Accounting validates too, but its rejection arrives as `MALFORMED_DRAFT` strings from inside
124
+ * a remote operation. Failing here names the payment, the order and the amounts.
125
+ */
126
+ private assertBalanced;
127
+ }
128
+ //# sourceMappingURL=PaymentAllocationFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaymentAllocationFactory.d.ts","sourceRoot":"","sources":["../src/PaymentAllocationFactory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,OAAO,EAAW,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,iCAAiC,CAAC;AAErF,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,kGAAkG;AAClG,MAAM,WAAW,gBAAgB;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC7B,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,IAAI,KACT,gBAAgB,GAAG,IAAI,CAAC;AAE7B,MAAM,WAAW,4BAA4B;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,IAAI,CAAC;IAClB,uFAAuF;IACvF,UAAU,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACpC,sEAAsE;IACtE,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,0FAA0F;IAC1F,MAAM,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,qBAAa,4BAA6B,SAAQ,KAAK;aAE/B,eAAe,EAAE,MAAM;aACvB,eAAe,EAAE,MAAM;gBADvB,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,EACvC,OAAO,EAAE,MAAM;CAKtB;AAiBD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,cAAc,EAAE,EAC5B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,GAClC,YAAY,EAAE,CAqDhB;AAED,qBAAa,wBAAwB;IAE7B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,oBAAoB;gBAFpB,SAAS,EAAE,iBAAiB,EAC5B,aAAa,EAAE,kBAAkB,EACjC,oBAAoB,EAAE,MAAM;IAGjD;;;;OAIG;IACU,qBAAqB,CAAC,GAAG,EAAE,4BAA4B,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAiGvG,OAAO,CAAC,OAAO;IAcf;;;;;OAKG;IACH,OAAO,CAAC,cAAc;CAUzB"}