@hartl-services/medusa-affiliate 0.3.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 (169) hide show
  1. package/.medusa/server/src/admin/index.js +3739 -0
  2. package/.medusa/server/src/admin/index.mjs +3738 -0
  3. package/.medusa/server/src/api/admin/affiliate-applications/[id]/approve/route.js +28 -0
  4. package/.medusa/server/src/api/admin/affiliate-applications/[id]/reject/route.js +19 -0
  5. package/.medusa/server/src/api/admin/affiliate-applications/route.js +23 -0
  6. package/.medusa/server/src/api/admin/affiliate-distribution-reports/query.js +171 -0
  7. package/.medusa/server/src/api/admin/affiliate-distribution-reports/route.js +13 -0
  8. package/.medusa/server/src/api/admin/affiliate-program-settings/route.js +27 -0
  9. package/.medusa/server/src/api/admin/affiliate-reports/[id]/route.js +45 -0
  10. package/.medusa/server/src/api/admin/affiliate-reports/route.js +27 -0
  11. package/.medusa/server/src/api/admin/affiliates/[id]/consignment-reminders/route.js +31 -0
  12. package/.medusa/server/src/api/admin/affiliates/[id]/consignment-transfers/route.js +41 -0
  13. package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/reconcile/route.js +34 -0
  14. package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/revoke/route.js +36 -0
  15. package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/rotate/route.js +40 -0
  16. package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/route.js +56 -0
  17. package/.medusa/server/src/api/admin/affiliates/[id]/distribution/route.js +45 -0
  18. package/.medusa/server/src/api/admin/affiliates/[id]/inactive/route.js +20 -0
  19. package/.medusa/server/src/api/admin/affiliates/[id]/route.js +50 -0
  20. package/.medusa/server/src/api/admin/affiliates/[id]/slugs/[slug_id]/route.js +19 -0
  21. package/.medusa/server/src/api/admin/affiliates/[id]/slugs/route.js +26 -0
  22. package/.medusa/server/src/api/admin/affiliates/route.js +43 -0
  23. package/.medusa/server/src/api/admin/consignment-report-response.js +36 -0
  24. package/.medusa/server/src/api/admin/consignment-reports/[id]/approve/route.js +25 -0
  25. package/.medusa/server/src/api/admin/consignment-reports/[id]/correct/route.js +18 -0
  26. package/.medusa/server/src/api/admin/consignment-reports/[id]/reject/route.js +15 -0
  27. package/.medusa/server/src/api/admin/consignment-reports/[id]/route.js +11 -0
  28. package/.medusa/server/src/api/admin/consignment-reports/route.js +27 -0
  29. package/.medusa/server/src/api/admin/customers/[id]/affiliate/route.js +50 -0
  30. package/.medusa/server/src/api/admin/orders/[id]/affiliate-attribution/route.js +30 -0
  31. package/.medusa/server/src/api/affiliate-coupon-http.js +152 -0
  32. package/.medusa/server/src/api/affiliate-referral-cookie.js +34 -0
  33. package/.medusa/server/src/api/affiliate-self-service-http.js +37 -0
  34. package/.medusa/server/src/api/middlewares.js +786 -0
  35. package/.medusa/server/src/api/store/affiliate-referrals/apply-coupon/route.js +47 -0
  36. package/.medusa/server/src/api/store/affiliate-referrals/capture/route.js +76 -0
  37. package/.medusa/server/src/api/store/affiliate-referrals/carts/[cart_id]/route.js +20 -0
  38. package/.medusa/server/src/api/store/affiliates/consignment-inventory/route.js +53 -0
  39. package/.medusa/server/src/api/store/affiliates/consignment-report-response.js +31 -0
  40. package/.medusa/server/src/api/store/affiliates/consignment-reports/[id]/submit/route.js +40 -0
  41. package/.medusa/server/src/api/store/affiliates/consignment-reports/route.js +43 -0
  42. package/.medusa/server/src/api/store/affiliates/coupon-labels/route.js +14 -0
  43. package/.medusa/server/src/api/store/affiliates/me/commissions/route.js +35 -0
  44. package/.medusa/server/src/api/store/affiliates/me/coupon-codes/[coupon_id]/revoke/route.js +36 -0
  45. package/.medusa/server/src/api/store/affiliates/me/coupon-codes/[coupon_id]/rotate/route.js +40 -0
  46. package/.medusa/server/src/api/store/affiliates/me/coupon-codes/route.js +55 -0
  47. package/.medusa/server/src/api/store/affiliates/me/dashboard/route.js +15 -0
  48. package/.medusa/server/src/api/store/affiliates/me/route.js +85 -0
  49. package/.medusa/server/src/api/store/affiliates/me/slugs/[slug_id]/route.js +29 -0
  50. package/.medusa/server/src/api/store/affiliates/me/slugs/route.js +34 -0
  51. package/.medusa/server/src/api/store/affiliates/own-order-discount/route.js +22 -0
  52. package/.medusa/server/src/api/store/affiliates/own-order-promotion/route.js +30 -0
  53. package/.medusa/server/src/api/store/affiliates/register/route.js +27 -0
  54. package/.medusa/server/src/api/store/affiliates/resolve-referral/route.js +34 -0
  55. package/.medusa/server/src/api/validators.js +52 -0
  56. package/.medusa/server/src/api/wire-response.js +10 -0
  57. package/.medusa/server/src/integration/email-events.js +51 -0
  58. package/.medusa/server/src/integrations/inventory-transfer/batch-management-transfer-adapter.js +36 -0
  59. package/.medusa/server/src/integrations/inventory-transfer/native-inventory-transfer-adapter.js +30 -0
  60. package/.medusa/server/src/integrations/inventory-transfer/resolve-inventory-transfer-adapter.js +46 -0
  61. package/.medusa/server/src/integrations/inventory-transfer/types.js +3 -0
  62. package/.medusa/server/src/jobs/affiliate-attribution-expiry.js +20 -0
  63. package/.medusa/server/src/jobs/affiliate-consignment-report-reminders.js +15 -0
  64. package/.medusa/server/src/jobs/affiliate-promotion-freshness.js +24 -0
  65. package/.medusa/server/src/lib/query-string.js +15 -0
  66. package/.medusa/server/src/modules/affiliate/domain/affiliate-attribution-policy.js +81 -0
  67. package/.medusa/server/src/modules/affiliate/domain/affiliate-coupon-policy.js +61 -0
  68. package/.medusa/server/src/modules/affiliate/domain/commission-policy.js +33 -0
  69. package/.medusa/server/src/modules/affiliate/domain/consignment-reminder-rules.js +74 -0
  70. package/.medusa/server/src/modules/affiliate/domain/email-normalization.js +20 -0
  71. package/.medusa/server/src/modules/affiliate/domain/own-order-coupon-code.js +37 -0
  72. package/.medusa/server/src/modules/affiliate/domain/plugin-options.js +40 -0
  73. package/.medusa/server/src/modules/affiliate/index.js +13 -0
  74. package/.medusa/server/src/modules/affiliate/migrations/Migration20260827085154.js +423 -0
  75. package/.medusa/server/src/modules/affiliate/models/affiliate-application.js +38 -0
  76. package/.medusa/server/src/modules/affiliate/models/affiliate-cart-referral.js +65 -0
  77. package/.medusa/server/src/modules/affiliate/models/affiliate-code-redemption.js +41 -0
  78. package/.medusa/server/src/modules/affiliate/models/affiliate-coupon.js +55 -0
  79. package/.medusa/server/src/modules/affiliate/models/affiliate-distribution-settings.js +22 -0
  80. package/.medusa/server/src/modules/affiliate/models/affiliate-order-attribution.js +49 -0
  81. package/.medusa/server/src/modules/affiliate/models/affiliate-program-settings.js +28 -0
  82. package/.medusa/server/src/modules/affiliate/models/affiliate-referral-session.js +34 -0
  83. package/.medusa/server/src/modules/affiliate/models/affiliate-slug.js +27 -0
  84. package/.medusa/server/src/modules/affiliate/models/affiliate.js +49 -0
  85. package/.medusa/server/src/modules/affiliate/models/commission-entry.js +62 -0
  86. package/.medusa/server/src/modules/affiliate/models/consignment-report-line.js +21 -0
  87. package/.medusa/server/src/modules/affiliate/models/consignment-report.js +31 -0
  88. package/.medusa/server/src/modules/affiliate/models/consignment-transfer-line.js +16 -0
  89. package/.medusa/server/src/modules/affiliate/models/consignment-transfer.js +20 -0
  90. package/.medusa/server/src/modules/affiliate/models/customer-affiliate-assignment.js +58 -0
  91. package/.medusa/server/src/modules/affiliate/service.js +2321 -0
  92. package/.medusa/server/src/modules/affiliate/services/affiliate-application-manager.js +171 -0
  93. package/.medusa/server/src/modules/affiliate/services/affiliate-coupon-manager.js +441 -0
  94. package/.medusa/server/src/modules/affiliate/services/affiliate-discount.service.js +55 -0
  95. package/.medusa/server/src/modules/affiliate/services/affiliate-manager.js +242 -0
  96. package/.medusa/server/src/modules/affiliate/services/affiliate-partner-portal.service.js +138 -0
  97. package/.medusa/server/src/modules/affiliate/services/affiliate-report.service.js +436 -0
  98. package/.medusa/server/src/modules/affiliate/services/affiliate-slug-manager.js +163 -0
  99. package/.medusa/server/src/modules/affiliate/services/commission-ledger.service.js +729 -0
  100. package/.medusa/server/src/modules/affiliate/services/customer-affiliate-assignment-manager.js +350 -0
  101. package/.medusa/server/src/modules/affiliate/services/order-attribution-manager.js +1051 -0
  102. package/.medusa/server/src/modules/affiliate/services/referral-lifecycle-manager.js +1420 -0
  103. package/.medusa/server/src/modules/affiliate/services/utils.js +49 -0
  104. package/.medusa/server/src/modules/affiliate/types/internal.js +3 -0
  105. package/.medusa/server/src/paths/affiliate.js +7 -0
  106. package/.medusa/server/src/paths/index.js +18 -0
  107. package/.medusa/server/src/schemas/index.js +18 -0
  108. package/.medusa/server/src/schemas/store.js +24 -0
  109. package/.medusa/server/src/subscribers/affiliate-cart-updated.js +92 -0
  110. package/.medusa/server/src/subscribers/affiliate-order-canceled.js +70 -0
  111. package/.medusa/server/src/subscribers/affiliate-order-placed.js +63 -0
  112. package/.medusa/server/src/subscribers/affiliate-order-return-received.js +67 -0
  113. package/.medusa/server/src/subscribers/affiliate-product-eligibility-updated.js +87 -0
  114. package/.medusa/server/src/types/admin-api.js +3 -0
  115. package/.medusa/server/src/types/enums.js +53 -0
  116. package/.medusa/server/src/types/index.js +32 -0
  117. package/.medusa/server/src/types/public.js +3 -0
  118. package/.medusa/server/src/types/store-api.js +3 -0
  119. package/.medusa/server/src/utils/affiliate-cart-operation-lock.js +316 -0
  120. package/.medusa/server/src/utils/affiliate-promotion-mutation-authorization.js +49 -0
  121. package/.medusa/server/src/utils/cart-promotions.js +9 -0
  122. package/.medusa/server/src/utils/money.js +79 -0
  123. package/.medusa/server/src/utils/promotion-code-availability.js +34 -0
  124. package/.medusa/server/src/utils/registered-email-checkout.js +101 -0
  125. package/.medusa/server/src/utils/resolve-services.js +7 -0
  126. package/.medusa/server/src/utils/settle-cart-promotions.js +44 -0
  127. package/.medusa/server/src/workflows/affiliate/affiliate-coupon-cart.js +215 -0
  128. package/.medusa/server/src/workflows/affiliate/affiliate-coupon-command-authorization.js +20 -0
  129. package/.medusa/server/src/workflows/affiliate/apply-affiliate-coupon.js +174 -0
  130. package/.medusa/server/src/workflows/affiliate/apply-own-order-promotion.js +89 -0
  131. package/.medusa/server/src/workflows/affiliate/approve-consignment-report.js +186 -0
  132. package/.medusa/server/src/workflows/affiliate/correct-approved-consignment-report.js +263 -0
  133. package/.medusa/server/src/workflows/affiliate/create-affiliate-coupon.js +35 -0
  134. package/.medusa/server/src/workflows/affiliate/create-commission-correction-for-cancellation.js +21 -0
  135. package/.medusa/server/src/workflows/affiliate/create-commission-correction-for-refund.js +24 -0
  136. package/.medusa/server/src/workflows/affiliate/create-commission-for-order.js +17 -0
  137. package/.medusa/server/src/workflows/affiliate/deactivate-affiliate.js +89 -0
  138. package/.medusa/server/src/workflows/affiliate/enable-distribution.js +120 -0
  139. package/.medusa/server/src/workflows/affiliate/enrich-affiliate-report.js +75 -0
  140. package/.medusa/server/src/workflows/affiliate/ensure-affiliate-coupon-promotion.js +410 -0
  141. package/.medusa/server/src/workflows/affiliate/ensure-affiliate-own-order-promotion.js +240 -0
  142. package/.medusa/server/src/workflows/affiliate/ensure-default-affiliate-coupon.js +32 -0
  143. package/.medusa/server/src/workflows/affiliate/expire-affiliate-attribution-state.js +131 -0
  144. package/.medusa/server/src/workflows/affiliate/finalize-affiliate-order-attribution.js +82 -0
  145. package/.medusa/server/src/workflows/affiliate/payment-authorization.js +33 -0
  146. package/.medusa/server/src/workflows/affiliate/promotion-eligibility.js +179 -0
  147. package/.medusa/server/src/workflows/affiliate/reconcile-affiliate-cart-referral.js +219 -0
  148. package/.medusa/server/src/workflows/affiliate/reconcile-affiliate-coupon.js +388 -0
  149. package/.medusa/server/src/workflows/affiliate/refresh-affiliate-promotions.js +114 -0
  150. package/.medusa/server/src/workflows/affiliate/resolve-coupon-labels.js +40 -0
  151. package/.medusa/server/src/workflows/affiliate/revoke-affiliate-coupon.js +29 -0
  152. package/.medusa/server/src/workflows/affiliate/rotate-affiliate-coupon.js +36 -0
  153. package/.medusa/server/src/workflows/affiliate/run-consignment-report-reminders.js +58 -0
  154. package/.medusa/server/src/workflows/affiliate/submit-consignment-report.js +279 -0
  155. package/.medusa/server/src/workflows/affiliate/transfer-batch-aware-inventory.js +172 -0
  156. package/.medusa/server/src/workflows/affiliate/transfer-consignment-stock.js +106 -0
  157. package/.medusa/server/src/workflows/affiliate/update-affiliate-coupon-discounts.js +129 -0
  158. package/.medusa/server/src/workflows/affiliate/utils.js +118 -0
  159. package/.medusa/server/src/workflows/hooks/complete-cart-affiliate-attribution.js +57 -0
  160. package/.medusa/server/src/workflows/hooks/complete-cart-order-created-composition.js +111 -0
  161. package/.medusa/server/src/workflows/hooks/complete-cart-own-order-discount.js +75 -0
  162. package/.medusa/server/src/workflows/hooks/enforce-unique-promotion-codes.js +33 -0
  163. package/.medusa/server/src/workflows/hooks/validate-affiliate-customer-code.js +239 -0
  164. package/.medusa/server/src/workflows/hooks/validate-complete-cart-affiliate-referral.js +137 -0
  165. package/LICENSE +21 -0
  166. package/README.md +799 -0
  167. package/dist/integration/email-events.d.ts +20 -0
  168. package/dist/integration/email-events.js +50 -0
  169. package/package.json +84 -0
@@ -0,0 +1,729 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CommissionLedgerService = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const money_1 = require("../../../utils/money");
6
+ const commission_policy_1 = require("../domain/commission-policy");
7
+ const utils_2 = require("./utils");
8
+ const correctionTypes = [
9
+ "refund_correction",
10
+ "cancellation_correction",
11
+ ];
12
+ class CommissionLedgerService {
13
+ constructor(store) {
14
+ this.store = store;
15
+ }
16
+ async createOrderCommission(input, context = {}, knownAttribution) {
17
+ const decimals = (0, money_1.getCurrencyDecimals)(input.order.currency_code);
18
+ if (input.order.eligibility_is_immutable === false) {
19
+ // Only checkout finalization may turn mutable Product eligibility into
20
+ // money. Event subscribers and correction workflows consume the base
21
+ // family persisted there and conservatively do nothing when it is absent.
22
+ return await this.store.listCommissionEntries({
23
+ order_id: input.order.id,
24
+ type: [
25
+ "order_commission",
26
+ "affiliate_referral_bonus",
27
+ "affiliate_own_order_referrer_bonus",
28
+ ],
29
+ }, { order: { id: "ASC" } }, context);
30
+ }
31
+ if (!knownAttribution) {
32
+ const ownOrderEntries = await this.createOwnOrderReferrerBonus(input, decimals, context);
33
+ if (ownOrderEntries !== null) {
34
+ return ownOrderEntries;
35
+ }
36
+ }
37
+ const attribution = knownAttribution ??
38
+ (await this.store.listAffiliateOrderAttributions({ order_id: input.order.id }, { take: 1 }, context))[0];
39
+ if (!attribution) {
40
+ return [];
41
+ }
42
+ if (attribution.order_id !== input.order.id) {
43
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Affiliate order attribution belongs to a different order.");
44
+ }
45
+ if (attribution.currency_code.trim().toLowerCase() !==
46
+ input.order.currency_code.trim().toLowerCase()) {
47
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Affiliate order attribution currency does not match the order.");
48
+ }
49
+ const existingStandaloneReferral = (await this.store.listCommissionEntries({ idempotency_key: `rab:${attribution.id}` }, undefined, context))[0];
50
+ if (existingStandaloneReferral) {
51
+ return [existingStandaloneReferral];
52
+ }
53
+ const existingCommission = (await this.store.listCommissionEntries({
54
+ order_id: input.order.id,
55
+ type: "order_commission",
56
+ }, undefined, context))[0] ?? null;
57
+ const bases = this.getEligibleNetItemSubtotals(input.order);
58
+ const breakdown = (0, commission_policy_1.calculateCommissionBreakdown)({
59
+ policy: {
60
+ version: attribution.policy_version,
61
+ commission_base: attribution.commission_base_strategy,
62
+ referrer_base: attribution.referrer_base_strategy,
63
+ },
64
+ currency_code: attribution.currency_code,
65
+ undiscounted_net_amount: bases.undiscounted,
66
+ discounted_net_amount: bases.discounted,
67
+ direct_rate: attribution.commission_rate,
68
+ referrer_rate: attribution.referrer_commission_rate ?? 0,
69
+ });
70
+ if (!existingCommission && breakdown.order_base <= 0) {
71
+ return [];
72
+ }
73
+ const hasDirectCommission = existingCommission?.commission_amount
74
+ ? existingCommission.commission_amount > 0
75
+ : attribution.commission_rate > 0 &&
76
+ breakdown.direct_commission_amount > 0;
77
+ const historicalReferralBase = existingCommission
78
+ ? existingCommission.referrer_base_amount_net ??
79
+ existingCommission.base_amount_net
80
+ : breakdown.referrer_base;
81
+ const hasHistoricalReferral = attribution.referrer_affiliate_id !== null &&
82
+ (attribution.referrer_commission_rate ?? 0) > 0 &&
83
+ (0, utils_2.calculateCommissionAmount)(historicalReferralBase, attribution.referrer_commission_rate ?? 0, decimals) > 0;
84
+ if (!hasDirectCommission && !hasHistoricalReferral) {
85
+ return [];
86
+ }
87
+ const occurredAt = input.order.created_at
88
+ ? (0, utils_2.toDate)(input.order.created_at)
89
+ : new Date();
90
+ const eligibleLinesSnapshot = this.createEligibleLinesSnapshot(input.order, decimals);
91
+ const attributionMetadata = {
92
+ order_attribution_id: attribution.id,
93
+ source: attribution.source,
94
+ attribution_source: attribution.source,
95
+ slug_or_code_snapshot: attribution.slug_or_code_snapshot,
96
+ assignment_id: attribution.customer_affiliate_assignment_id,
97
+ customer_affiliate_assignment_id: attribution.customer_affiliate_assignment_id,
98
+ referrer_affiliate_id_snapshot: attribution.referrer_affiliate_id,
99
+ referrer_commission_rate_snapshot: attribution.referrer_commission_rate,
100
+ eligible_lines_snapshot: eligibleLinesSnapshot,
101
+ };
102
+ if (!hasDirectCommission) {
103
+ const standaloneReferral = await this.createEntryIdempotent({
104
+ affiliate_id: attribution.referrer_affiliate_id,
105
+ customer_id: attribution.customer_id,
106
+ order_id: input.order.id,
107
+ refund_id: null,
108
+ base_commission_entry_id: null,
109
+ source_affiliate_id: attribution.affiliate_id,
110
+ type: "affiliate_referral_bonus",
111
+ policy_version: breakdown.policy_version,
112
+ commission_base_strategy: attribution.commission_base_strategy,
113
+ referrer_base_strategy: attribution.referrer_base_strategy,
114
+ undiscounted_base_amount_net: breakdown.undiscounted_net_amount,
115
+ discounted_base_amount_net: breakdown.discounted_net_amount,
116
+ discount_amount_net: breakdown.discount_amount,
117
+ base_amount_net: breakdown.referrer_base,
118
+ direct_commission_amount: 0,
119
+ referrer_base_amount_net: breakdown.referrer_base,
120
+ commission_rate: attribution.referrer_commission_rate,
121
+ commission_amount: breakdown.referrer_commission_amount,
122
+ currency_code: attribution.currency_code,
123
+ occurred_at: occurredAt,
124
+ idempotency_key: `rab:${attribution.id}`,
125
+ metadata: attributionMetadata,
126
+ }, context);
127
+ return [standaloneReferral];
128
+ }
129
+ const commission = existingCommission ??
130
+ (await this.createEntryIdempotent({
131
+ affiliate_id: attribution.affiliate_id,
132
+ customer_id: attribution.customer_id,
133
+ order_id: input.order.id,
134
+ refund_id: null,
135
+ base_commission_entry_id: null,
136
+ source_affiliate_id: null,
137
+ type: "order_commission",
138
+ policy_version: breakdown.policy_version,
139
+ commission_base_strategy: attribution.commission_base_strategy,
140
+ referrer_base_strategy: attribution.referrer_base_strategy,
141
+ undiscounted_base_amount_net: breakdown.undiscounted_net_amount,
142
+ discounted_base_amount_net: breakdown.discounted_net_amount,
143
+ discount_amount_net: breakdown.discount_amount,
144
+ base_amount_net: breakdown.order_base,
145
+ direct_commission_amount: breakdown.direct_commission_amount,
146
+ referrer_base_amount_net: breakdown.referrer_base,
147
+ commission_rate: attribution.commission_rate,
148
+ commission_amount: breakdown.direct_commission_amount,
149
+ currency_code: attribution.currency_code,
150
+ occurred_at: occurredAt,
151
+ idempotency_key: `oc:${input.order.id}`,
152
+ metadata: attributionMetadata,
153
+ }, context));
154
+ const entries = [commission];
155
+ if (!hasHistoricalReferral) {
156
+ return entries;
157
+ }
158
+ // The referral bonus is a separate write from the order commission above;
159
+ // check independently so a retry after a partial failure (commission
160
+ // written, bonus not) still creates the bonus instead of treating the order
161
+ // as fully processed.
162
+ const existingReferralBonus = await this.store.listCommissionEntries({
163
+ base_commission_entry_id: commission.id,
164
+ type: "affiliate_referral_bonus",
165
+ }, undefined, context);
166
+ if (existingReferralBonus.length) {
167
+ entries.push(...existingReferralBonus);
168
+ return entries;
169
+ }
170
+ const referralBonus = await this.createReferralBonusEntry({
171
+ sourceEntry: commission,
172
+ sourceAffiliateId: commission.affiliate_id,
173
+ referredByAffiliateId: attribution.referrer_affiliate_id,
174
+ referrerCommissionRate: attribution.referrer_commission_rate,
175
+ trustHistoricalEligibility: true,
176
+ baseAmountNet: commission.referrer_base_amount_net ?? commission.base_amount_net,
177
+ occurredAt: (0, utils_2.toDate)(commission.occurred_at),
178
+ decimals,
179
+ metadata: {
180
+ source: "order_commission",
181
+ order_attribution_id: attribution.id,
182
+ attribution_source: attribution.source,
183
+ slug_or_code_snapshot: attribution.slug_or_code_snapshot,
184
+ customer_affiliate_assignment_id: attribution.customer_affiliate_assignment_id,
185
+ },
186
+ context,
187
+ });
188
+ if (referralBonus) {
189
+ entries.push(referralBonus);
190
+ }
191
+ return entries;
192
+ }
193
+ /**
194
+ * Returns null when this is not an Affiliate's own order. An empty array is
195
+ * a handled own order without an eligible referrer, so it must never fall
196
+ * through to the ordinary customer-assignment commission branch.
197
+ */
198
+ async createOwnOrderReferrerBonus(input, decimals, context) {
199
+ // Resolve the immutable booking before consulting current Affiliate state:
200
+ // retries must return the historical bonus even if the buyer Affiliate was
201
+ // later deactivated, rebound, or otherwise changed.
202
+ const existing = (await this.store.listCommissionEntries({
203
+ idempotency_key: `aorb:${input.order.id}`,
204
+ order_id: input.order.id,
205
+ type: "affiliate_own_order_referrer_bonus",
206
+ }, undefined, context))[0];
207
+ if (existing) {
208
+ return [existing];
209
+ }
210
+ if (!input.order.customer_id ||
211
+ typeof this.store.listAffiliates !== "function") {
212
+ return null;
213
+ }
214
+ const affiliates = await this.store.listAffiliates({
215
+ customer_id: input.order.customer_id,
216
+ }, { take: 1 }, context);
217
+ const buyerAffiliate = affiliates[0];
218
+ if (!buyerAffiliate) {
219
+ return null;
220
+ }
221
+ if (buyerAffiliate.status !== "active") {
222
+ return [];
223
+ }
224
+ const referrerId = buyerAffiliate.referred_by_affiliate_id;
225
+ const referrerRate = buyerAffiliate.referrer_commission_rate ?? 0;
226
+ if (!referrerId || referrerRate <= 0) {
227
+ return [];
228
+ }
229
+ const referrer = await this.store.retrieveAffiliate(referrerId, context);
230
+ if (referrer.status !== "active") {
231
+ return [];
232
+ }
233
+ const settings = await this.store.retrieveProgramSettings(context);
234
+ const bases = this.getEligibleNetItemSubtotals(input.order);
235
+ const breakdown = (0, commission_policy_1.calculateCommissionBreakdown)({
236
+ policy: {
237
+ version: settings.policy_version,
238
+ commission_base: settings.commission_base,
239
+ referrer_base: settings.referrer_base,
240
+ },
241
+ currency_code: input.order.currency_code,
242
+ undiscounted_net_amount: bases.undiscounted,
243
+ discounted_net_amount: bases.discounted,
244
+ direct_rate: 0,
245
+ referrer_rate: referrerRate,
246
+ });
247
+ if (breakdown.order_base <= 0) {
248
+ return [];
249
+ }
250
+ const occurredAt = input.order.created_at
251
+ ? (0, utils_2.toDate)(input.order.created_at)
252
+ : new Date();
253
+ const entry = await this.createEntryIdempotent({
254
+ affiliate_id: referrer.id,
255
+ customer_id: input.order.customer_id,
256
+ order_id: input.order.id,
257
+ refund_id: null,
258
+ base_commission_entry_id: null,
259
+ source_affiliate_id: buyerAffiliate.id,
260
+ type: "affiliate_own_order_referrer_bonus",
261
+ policy_version: breakdown.policy_version,
262
+ commission_base_strategy: settings.commission_base,
263
+ referrer_base_strategy: settings.referrer_base,
264
+ undiscounted_base_amount_net: breakdown.undiscounted_net_amount,
265
+ discounted_base_amount_net: breakdown.discounted_net_amount,
266
+ discount_amount_net: breakdown.discount_amount,
267
+ base_amount_net: breakdown.order_base,
268
+ direct_commission_amount: 0,
269
+ referrer_base_amount_net: breakdown.order_base,
270
+ commission_rate: referrerRate,
271
+ commission_amount: breakdown.referrer_commission_amount,
272
+ currency_code: input.order.currency_code,
273
+ occurred_at: occurredAt,
274
+ idempotency_key: `aorb:${input.order.id}`,
275
+ metadata: {
276
+ buyer_affiliate_id_snapshot: buyerAffiliate.id,
277
+ referrer_affiliate_id_snapshot: referrer.id,
278
+ referrer_commission_rate_snapshot: referrerRate,
279
+ eligible_lines_snapshot: this.createEligibleLinesSnapshot(input.order, decimals),
280
+ },
281
+ }, context);
282
+ return [entry];
283
+ }
284
+ async createCorrection(input, context = {}) {
285
+ const orderCommissionEntries = await this.store.listCommissionEntries({
286
+ order_id: input.order.id,
287
+ type: "order_commission",
288
+ }, undefined, context);
289
+ const ownOrderReferrerBonusEntries = await this.store.listCommissionEntries({
290
+ order_id: input.order.id,
291
+ type: "affiliate_own_order_referrer_bonus",
292
+ }, undefined, context);
293
+ const allReferralBonusEntries = await this.store.listCommissionEntries({
294
+ order_id: input.order.id,
295
+ type: "affiliate_referral_bonus",
296
+ }, undefined, context);
297
+ const nestedReferralBonusEntries = new Map();
298
+ const standaloneReferralBonusEntries = [];
299
+ for (const referralEntry of allReferralBonusEntries) {
300
+ if (!referralEntry.base_commission_entry_id) {
301
+ standaloneReferralBonusEntries.push(referralEntry);
302
+ continue;
303
+ }
304
+ const nested = nestedReferralBonusEntries.get(referralEntry.base_commission_entry_id) ?? [];
305
+ nested.push(referralEntry);
306
+ nestedReferralBonusEntries.set(referralEntry.base_commission_entry_id, nested);
307
+ }
308
+ const originalEntries = [
309
+ ...orderCommissionEntries,
310
+ ...ownOrderReferrerBonusEntries,
311
+ ...standaloneReferralBonusEntries,
312
+ ];
313
+ const allBaseEntries = [
314
+ ...originalEntries,
315
+ ...allReferralBonusEntries.filter((entry) => entry.base_commission_entry_id !== null),
316
+ ];
317
+ if (!allBaseEntries.length) {
318
+ return [];
319
+ }
320
+ const currencyCodes = new Set(allBaseEntries.map((entry) => entry.currency_code));
321
+ if (currencyCodes.size !== 1 ||
322
+ allBaseEntries[0].currency_code !== input.order.currency_code) {
323
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Commission correction currency does not match the immutable ledger entries.");
324
+ }
325
+ const decimals = (0, money_1.getCurrencyDecimals)(allBaseEntries[0].currency_code);
326
+ const entries = [];
327
+ const refundRatios = new Map();
328
+ if (input.type === "refund_correction") {
329
+ for (const originalEntry of originalEntries) {
330
+ refundRatios.set(originalEntry.id, this.getHistoricalRefundRatio(input, originalEntry, decimals));
331
+ }
332
+ }
333
+ const occurredAt = input.occurred_at
334
+ ? (0, utils_2.toDate)(input.occurred_at)
335
+ : new Date();
336
+ for (const originalEntry of originalEntries) {
337
+ // Refund workflows provide cumulative pre- and post-discount returned
338
+ // bases. Select the historical denominator that belongs to the original
339
+ // policy, then apply that ratio independently to direct/referral bases.
340
+ // Hoisted here (out of bookCorrectionDelta) so the referral-bonus loop
341
+ // runs on every delivery, including a retry where the direct delta is 0.
342
+ // The module transaction makes the writes atomic; keeping both deltas
343
+ // independent also preserves recovery for historical partial writes.
344
+ const refundRatio = refundRatios.get(originalEntry.id);
345
+ if (input.type === "refund_correction" && !refundRatio) {
346
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Commission correction is missing its immutable refund ratio.");
347
+ }
348
+ const desiredCumulativeBase = input.type === "cancellation_correction"
349
+ ? (0, utils_2.roundCurrencyAmount)(originalEntry.base_amount_net, decimals)
350
+ : this.scaleHistoricalBaseForCorrection(refundRatio.returnedAmount, refundRatio.historicalReferenceAmount, originalEntry.base_amount_net, decimals);
351
+ const orderCorrection = await this.bookCorrectionDelta({
352
+ baseEntry: originalEntry,
353
+ desiredCumulativeBase,
354
+ input,
355
+ occurredAt,
356
+ decimals,
357
+ customerId: originalEntry.customer_id ?? null,
358
+ sourceAffiliateId: originalEntry.source_affiliate_id ?? null,
359
+ metadata: { correction_for: originalEntry.type },
360
+ context,
361
+ });
362
+ if (orderCorrection) {
363
+ entries.push(orderCorrection);
364
+ }
365
+ const referralBonusEntries = nestedReferralBonusEntries.get(originalEntry.id) ?? [];
366
+ for (const referralBonusEntry of referralBonusEntries) {
367
+ const desiredReferralCumulativeBase = input.type === "cancellation_correction"
368
+ ? (0, utils_2.roundCurrencyAmount)(referralBonusEntry.base_amount_net, decimals)
369
+ : this.scaleHistoricalBaseForCorrection(refundRatio.returnedAmount, refundRatio.historicalReferenceAmount, referralBonusEntry.base_amount_net, decimals);
370
+ const referralCorrection = await this.bookCorrectionDelta({
371
+ baseEntry: referralBonusEntry,
372
+ desiredCumulativeBase: desiredReferralCumulativeBase,
373
+ input,
374
+ occurredAt,
375
+ decimals,
376
+ customerId: referralBonusEntry.customer_id ?? null,
377
+ sourceAffiliateId: referralBonusEntry.source_affiliate_id ?? originalEntry.affiliate_id,
378
+ metadata: {
379
+ correction_for: referralBonusEntry.type,
380
+ original_order_commission_entry_id: originalEntry.id,
381
+ },
382
+ context,
383
+ });
384
+ if (referralCorrection) {
385
+ entries.push(referralCorrection);
386
+ }
387
+ }
388
+ }
389
+ return entries;
390
+ }
391
+ /**
392
+ * Scales a historical policy base by a cumulative discounted refund ratio.
393
+ * This is what makes a full 80 EUR refund reverse a before-discounts base of
394
+ * 100 EUR, while a 50% refund reverses 50 EUR direct and (for example) 45 EUR
395
+ * of a separate 90 EUR referrer base.
396
+ */
397
+ scaleHistoricalBaseForCorrection(requestedBaseAmount, discountedReferenceAmount, historicalBaseAmount, decimals) {
398
+ if (discountedReferenceAmount <= 0 || historicalBaseAmount <= 0) {
399
+ return 0;
400
+ }
401
+ const refundedRatio = money_1.Money.of(requestedBaseAmount)
402
+ .divide(discountedReferenceAmount)
403
+ .min(1)
404
+ .max(money_1.Money.zero());
405
+ return money_1.Money.of(historicalBaseAmount)
406
+ .multiply(refundedRatio)
407
+ .toRoundedNumber(decimals);
408
+ }
409
+ getHistoricalRefundRatio(input, originalEntry, decimals) {
410
+ const returnedFromSnapshot = this.getReturnedBasesFromSnapshot(originalEntry.metadata, input.returned_items, decimals);
411
+ if (originalEntry.commission_base_strategy === "before_discounts" &&
412
+ originalEntry.undiscounted_base_amount_net != null) {
413
+ return {
414
+ returnedAmount: returnedFromSnapshot.undiscounted,
415
+ historicalReferenceAmount: originalEntry.undiscounted_base_amount_net,
416
+ };
417
+ }
418
+ if (originalEntry.commission_base_strategy === "after_discounts" &&
419
+ originalEntry.discounted_base_amount_net != null) {
420
+ return {
421
+ returnedAmount: returnedFromSnapshot.discounted,
422
+ historicalReferenceAmount: originalEntry.discounted_base_amount_net,
423
+ };
424
+ }
425
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Commission correction requires immutable policy base snapshots.");
426
+ }
427
+ /**
428
+ * Ensures every immutable base entry expected for a correction exists before
429
+ * the caller acquires the per-base locks. A persisted customer attribution is
430
+ * passed straight into the booking path so historical materialization never
431
+ * consults current Affiliate or program state. An existing own-order base is
432
+ * terminal; an attributed direct/referrer family is completed idempotently.
433
+ */
434
+ async materializeMissingCorrectionBaseEntries(order, context = {}) {
435
+ const filters = {
436
+ order_id: order.id,
437
+ type: [
438
+ "order_commission",
439
+ "affiliate_referral_bonus",
440
+ "affiliate_own_order_referrer_bonus",
441
+ ],
442
+ };
443
+ const existingEntries = await this.store.listCommissionEntries(filters, { order: { id: "ASC" } }, context);
444
+ if (existingEntries.some((entry) => entry.type === "affiliate_own_order_referrer_bonus")) {
445
+ return existingEntries;
446
+ }
447
+ const attribution = (await this.store.listAffiliateOrderAttributions({ order_id: order.id }, { take: 1 }, context))[0];
448
+ if (attribution) {
449
+ await this.createOrderCommission({ order }, context, attribution);
450
+ }
451
+ else if (existingEntries.length) {
452
+ return existingEntries;
453
+ }
454
+ else {
455
+ await this.createOwnOrderReferrerBonus({ order }, (0, money_1.getCurrencyDecimals)(order.currency_code), context);
456
+ }
457
+ await this.store.flush(context);
458
+ return await this.store.listCommissionEntries(filters, { order: { id: "ASC" } }, context);
459
+ }
460
+ createEligibleLinesSnapshot(order, decimals) {
461
+ return (order.items ?? [])
462
+ .filter((item) => !item.is_giftcard && item.eligible !== false)
463
+ .map((item) => ({
464
+ item_id: item.id,
465
+ quantity: item.quantity,
466
+ undiscounted_net_subtotal: (0, utils_2.roundCurrencyAmount)(this.getUndiscountedLineItemSubtotal(item), decimals),
467
+ discounted_net_subtotal: (0, utils_2.roundCurrencyAmount)(this.getLineItemSubtotal(item), decimals),
468
+ }));
469
+ }
470
+ getReturnedBasesFromSnapshot(metadata, returnedItems, decimals) {
471
+ const rawSnapshot = metadata?.eligible_lines_snapshot;
472
+ if (!Array.isArray(rawSnapshot) ||
473
+ rawSnapshot.length === 0 ||
474
+ !Array.isArray(returnedItems) ||
475
+ returnedItems.length === 0) {
476
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Commission correction requires an immutable eligible-line snapshot.");
477
+ }
478
+ const lines = new Map();
479
+ for (const value of rawSnapshot) {
480
+ if (typeof value !== "object" ||
481
+ value === null ||
482
+ Array.isArray(value)) {
483
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Commission correction has a malformed eligible-line snapshot.");
484
+ }
485
+ const itemId = value.item_id;
486
+ const quantity = value.quantity;
487
+ const undiscounted = value.undiscounted_net_subtotal;
488
+ const discounted = value.discounted_net_subtotal;
489
+ if (typeof itemId !== "string" ||
490
+ lines.has(itemId) ||
491
+ typeof quantity !== "number" ||
492
+ !Number.isFinite(quantity) ||
493
+ quantity <= 0 ||
494
+ typeof undiscounted !== "number" ||
495
+ !Number.isFinite(undiscounted) ||
496
+ undiscounted < 0 ||
497
+ typeof discounted !== "number" ||
498
+ !Number.isFinite(discounted) ||
499
+ discounted < 0) {
500
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Commission correction has a malformed eligible-line snapshot.");
501
+ }
502
+ lines.set(itemId, { quantity, undiscounted, discounted });
503
+ }
504
+ let returnedUndiscounted = money_1.Money.zero();
505
+ let returnedDiscounted = money_1.Money.zero();
506
+ for (const returnedItem of returnedItems) {
507
+ const line = lines.get(returnedItem.item_id);
508
+ if (!line) {
509
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Returned line is absent from the immutable commission snapshot.");
510
+ }
511
+ const quantity = returnedItem.received_quantity ?? returnedItem.quantity ?? 0;
512
+ if (!Number.isFinite(quantity) || quantity < 0) {
513
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Returned line quantity is invalid for commission correction.");
514
+ }
515
+ returnedUndiscounted = returnedUndiscounted.add(money_1.Money.of(line.undiscounted).divide(line.quantity).multiply(quantity));
516
+ returnedDiscounted = returnedDiscounted.add(money_1.Money.of(line.discounted).divide(line.quantity).multiply(quantity));
517
+ }
518
+ return {
519
+ undiscounted: returnedUndiscounted.toRoundedNumber(decimals),
520
+ discounted: returnedDiscounted.toRoundedNumber(decimals),
521
+ };
522
+ }
523
+ getDiscountedNetItemSubtotal(order) {
524
+ return this.getEligibleNetItemSubtotals(order).discounted;
525
+ }
526
+ getEligibleNetItemSubtotals(order) {
527
+ const decimals = (0, money_1.getCurrencyDecimals)(order.currency_code);
528
+ const items = order.items ?? [];
529
+ if (!items.length) {
530
+ const discounted = (0, utils_2.roundCurrencyAmount)(order.item_discounted_net_subtotal ?? 0, decimals);
531
+ return {
532
+ undiscounted: discounted,
533
+ discounted,
534
+ };
535
+ }
536
+ const eligibleItems = items.filter((item) => !item.is_giftcard && item.eligible !== false);
537
+ const undiscounted = money_1.Money.sum(eligibleItems.map((item) => this.getUndiscountedLineItemSubtotal(item)));
538
+ const discounted = money_1.Money.sum(eligibleItems.map((item) => this.getLineItemSubtotal(item)));
539
+ return {
540
+ undiscounted: undiscounted.toRoundedNumber(decimals),
541
+ discounted: discounted.toRoundedNumber(decimals),
542
+ };
543
+ }
544
+ getRefundedDiscountedNetItemSubtotal(order, returnedItems) {
545
+ return this.getRefundedNetItemSubtotals(order, returnedItems).discounted;
546
+ }
547
+ getRefundedNetItemSubtotals(order, returnedItems) {
548
+ const decimals = (0, money_1.getCurrencyDecimals)(order.currency_code);
549
+ const orderItems = new Map((order.items ?? []).map((item) => [item.id, item]));
550
+ let undiscounted = money_1.Money.zero();
551
+ let discounted = money_1.Money.zero();
552
+ for (const returnedItem of returnedItems) {
553
+ const orderItem = orderItems.get(returnedItem.item_id);
554
+ if (!orderItem ||
555
+ orderItem.is_giftcard ||
556
+ orderItem.eligible === false ||
557
+ orderItem.quantity <= 0) {
558
+ continue;
559
+ }
560
+ const quantity = returnedItem.received_quantity ?? returnedItem.quantity ?? 0;
561
+ const undiscountedUnitSubtotal = money_1.Money.of(this.getUndiscountedLineItemSubtotal(orderItem)).divide(orderItem.quantity);
562
+ const discountedUnitSubtotal = money_1.Money.of(this.getLineItemSubtotal(orderItem)).divide(orderItem.quantity);
563
+ undiscounted = undiscounted.add(undiscountedUnitSubtotal.multiply(quantity));
564
+ discounted = discounted.add(discountedUnitSubtotal.multiply(quantity));
565
+ }
566
+ return {
567
+ undiscounted: undiscounted.toRoundedNumber(decimals),
568
+ discounted: discounted.toRoundedNumber(decimals),
569
+ };
570
+ }
571
+ getLineItemSubtotal(item) {
572
+ return Number.isFinite(item.discounted_net_subtotal)
573
+ ? item.discounted_net_subtotal
574
+ : 0;
575
+ }
576
+ getUndiscountedLineItemSubtotal(item) {
577
+ return Number.isFinite(item.undiscounted_net_subtotal)
578
+ ? item.undiscounted_net_subtotal
579
+ : this.getLineItemSubtotal(item);
580
+ }
581
+ async createReferralBonusEntry(input) {
582
+ if (!input.referredByAffiliateId || !input.referrerCommissionRate) {
583
+ return null;
584
+ }
585
+ if (!input.trustHistoricalEligibility) {
586
+ const referrer = await this.store.retrieveAffiliate(input.referredByAffiliateId, input.context);
587
+ if (referrer.status !== "active") {
588
+ return null;
589
+ }
590
+ }
591
+ const commissionAmount = (0, utils_2.calculateCommissionAmount)(input.baseAmountNet, input.referrerCommissionRate, input.decimals);
592
+ if (commissionAmount <= 0) {
593
+ return null;
594
+ }
595
+ return await this.createEntryIdempotent({
596
+ affiliate_id: input.referredByAffiliateId,
597
+ customer_id: input.sourceEntry.customer_id ?? null,
598
+ order_id: input.sourceEntry.order_id ?? null,
599
+ refund_id: null,
600
+ base_commission_entry_id: input.sourceEntry.id,
601
+ source_affiliate_id: input.sourceAffiliateId,
602
+ type: "affiliate_referral_bonus",
603
+ policy_version: input.sourceEntry.policy_version ?? null,
604
+ commission_base_strategy: input.sourceEntry.commission_base_strategy ?? null,
605
+ referrer_base_strategy: input.sourceEntry.referrer_base_strategy ?? null,
606
+ undiscounted_base_amount_net: input.sourceEntry.undiscounted_base_amount_net ?? null,
607
+ discounted_base_amount_net: input.sourceEntry.discounted_base_amount_net ?? null,
608
+ discount_amount_net: input.sourceEntry.discount_amount_net ?? null,
609
+ base_amount_net: input.baseAmountNet,
610
+ direct_commission_amount: input.sourceEntry.direct_commission_amount ?? null,
611
+ referrer_base_amount_net: input.sourceEntry.referrer_base_amount_net ?? input.baseAmountNet,
612
+ commission_rate: input.referrerCommissionRate,
613
+ commission_amount: commissionAmount,
614
+ currency_code: input.sourceEntry.currency_code,
615
+ occurred_at: input.occurredAt,
616
+ idempotency_key: `rb:${input.sourceEntry.id}`,
617
+ metadata: input.metadata ?? null,
618
+ }, input.context);
619
+ }
620
+ /**
621
+ * Books the missing correction delta for one base entry within one scope (a
622
+ * refund_id, or the single cancellation channel). Returns null when nothing
623
+ * is owed (already fully corrected, or a re-delivered event). The idempotency
624
+ * key encodes the scope's cumulative-after amount so a concurrent duplicate
625
+ * that computes the same delta collides on the unique index and is resolved
626
+ * to the existing row instead of double-booking.
627
+ */
628
+ async bookCorrectionDelta(input) {
629
+ const { baseEntry, decimals } = input;
630
+ const refundId = input.input.refund_id ?? null;
631
+ const type = input.input.type;
632
+ const existingCorrections = await this.store.listCommissionEntries({
633
+ base_commission_entry_id: baseEntry.id,
634
+ type: correctionTypes,
635
+ }, undefined, input.context);
636
+ const inScope = (entry) => refundId
637
+ ? entry.refund_id === refundId
638
+ : entry.type === "cancellation_correction";
639
+ const alreadyForScope = money_1.Money.sum(existingCorrections
640
+ .filter(inScope)
641
+ .map((entry) => money_1.Money.of(entry.base_amount_net).abs()));
642
+ const alreadyAll = money_1.Money.sum(existingCorrections.map((entry) => money_1.Money.of(entry.base_amount_net).abs()));
643
+ const alreadyCommissionForScope = money_1.Money.sum(existingCorrections
644
+ .filter(inScope)
645
+ .map((entry) => money_1.Money.of(entry.commission_amount).abs()));
646
+ const alreadyCommissionAll = money_1.Money.sum(existingCorrections.map((entry) => money_1.Money.of(entry.commission_amount).abs()));
647
+ const desired = money_1.Money.of(input.desiredCumulativeBase)
648
+ .min(baseEntry.base_amount_net)
649
+ .max(money_1.Money.zero());
650
+ const remainingOverall = money_1.Money.of(baseEntry.base_amount_net)
651
+ .subtract(alreadyAll)
652
+ .max(money_1.Money.zero());
653
+ const deltaBase = desired
654
+ .subtract(alreadyForScope)
655
+ .max(money_1.Money.zero())
656
+ .min(remainingOverall)
657
+ .toRoundedNumber(decimals);
658
+ if (deltaBase <= 0) {
659
+ return null;
660
+ }
661
+ const desiredCommission = baseEntry.base_amount_net > 0
662
+ ? money_1.Money.of(baseEntry.commission_amount)
663
+ .multiply(money_1.Money.of(desired).divide(baseEntry.base_amount_net))
664
+ .toRoundedNumber(decimals)
665
+ : 0;
666
+ const remainingCommission = money_1.Money.of(baseEntry.commission_amount)
667
+ .subtract(alreadyCommissionAll)
668
+ .max(money_1.Money.zero());
669
+ const deltaCommission = money_1.Money.of(desiredCommission)
670
+ .subtract(alreadyCommissionForScope)
671
+ .max(money_1.Money.zero())
672
+ .min(remainingCommission)
673
+ .toRoundedNumber(decimals);
674
+ const cumulativeAfter = (0, utils_2.roundCurrencyAmount)(money_1.Money.of(alreadyForScope).add(deltaBase).toRoundedNumber(decimals), decimals);
675
+ const idempotencyKey = refundId
676
+ ? `rc:${refundId}:${baseEntry.id}:${this.toMinorUnits(cumulativeAfter, decimals)}`
677
+ : `cc:${baseEntry.id}`;
678
+ const entry = await this.createEntryIdempotent({
679
+ affiliate_id: baseEntry.affiliate_id,
680
+ customer_id: input.customerId,
681
+ order_id: input.input.order.id,
682
+ refund_id: refundId,
683
+ base_commission_entry_id: baseEntry.id,
684
+ source_affiliate_id: input.sourceAffiliateId,
685
+ type,
686
+ policy_version: baseEntry.policy_version ?? null,
687
+ commission_base_strategy: baseEntry.commission_base_strategy ?? null,
688
+ referrer_base_strategy: baseEntry.referrer_base_strategy ?? null,
689
+ undiscounted_base_amount_net: baseEntry.undiscounted_base_amount_net ?? null,
690
+ discounted_base_amount_net: baseEntry.discounted_base_amount_net ?? null,
691
+ discount_amount_net: baseEntry.discount_amount_net ?? null,
692
+ base_amount_net: -deltaBase,
693
+ direct_commission_amount: baseEntry.direct_commission_amount ?? null,
694
+ referrer_base_amount_net: baseEntry.referrer_base_amount_net ?? null,
695
+ commission_rate: baseEntry.commission_rate,
696
+ commission_amount: -deltaCommission,
697
+ currency_code: baseEntry.currency_code,
698
+ occurred_at: input.occurredAt,
699
+ idempotency_key: idempotencyKey,
700
+ metadata: input.metadata,
701
+ }, input.context);
702
+ return entry;
703
+ }
704
+ toMinorUnits(amount, decimals) {
705
+ return money_1.Money.of(amount)
706
+ .multiply(Math.pow(10, decimals))
707
+ .toRoundedNumber(0);
708
+ }
709
+ /**
710
+ * Inserts a ledger entry and, if a concurrent duplicate already claimed the
711
+ * same deterministic idempotency_key (rejected by the partial unique index),
712
+ * returns that already-booked entry instead of surfacing the raw constraint
713
+ * violation. Mirrors the customer-assignment race handling.
714
+ */
715
+ async createEntryIdempotent(data, context) {
716
+ try {
717
+ return await this.store.createCommissionEntries(data, context);
718
+ }
719
+ catch (error) {
720
+ const existing = (await this.store.listCommissionEntries({ idempotency_key: data.idempotency_key }, { take: 1 }, context))[0];
721
+ if (existing) {
722
+ return existing;
723
+ }
724
+ throw error;
725
+ }
726
+ }
727
+ }
728
+ exports.CommissionLedgerService = CommissionLedgerService;
729
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWlzc2lvbi1sZWRnZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2FmZmlsaWF0ZS9zZXJ2aWNlcy9jb21taXNzaW9uLWxlZGdlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQVFBLHFEQUF1RDtBQVN2RCxnREFBaUU7QUFDakUsbUVBQTBFO0FBQzFFLG1DQUlnQjtBQUVoQixNQUFNLGVBQWUsR0FBMEI7SUFDN0MsbUJBQW1CO0lBQ25CLHlCQUF5QjtDQUMxQixDQUFBO0FBRUQsTUFBYSx1QkFBdUI7SUFDbEMsWUFBNkIsS0FBMkI7UUFBM0IsVUFBSyxHQUFMLEtBQUssQ0FBc0I7SUFBRyxDQUFDO0lBRTVELEtBQUssQ0FBQyxxQkFBcUIsQ0FDekIsS0FBaUMsRUFDakMsVUFBbUIsRUFBRSxFQUNyQixnQkFBK0M7UUFFL0MsTUFBTSxRQUFRLEdBQUcsSUFBQSwyQkFBbUIsRUFBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBRS9ELElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUNuRCx1RUFBdUU7WUFDdkUscUVBQXFFO1lBQ3JFLDBFQUEwRTtZQUMxRSxPQUFPLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsQ0FDM0M7Z0JBQ0UsUUFBUSxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDeEIsSUFBSSxFQUFFO29CQUNKLGtCQUFrQjtvQkFDbEIsMEJBQTBCO29CQUMxQixvQ0FBb0M7aUJBQ3JDO2FBQ0YsRUFDRCxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUN4QixPQUFPLENBQ1IsQ0FBQTtRQUNILENBQUM7UUFFRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUN0QixNQUFNLGVBQWUsR0FBRyxNQUFN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