@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,388 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reconcileAffiliateCouponsForAffiliateWorkflow = exports.reconcileAffiliateCouponWorkflow = exports.reconcileCouponsUsingDefaultDiscount = exports.reconcileAffiliateCouponsForAffiliate = exports.completeAffiliateCouponReconciliation = exports.reconcileAffiliateCoupon = exports.reconcileAffiliateCouponForCart = exports.synchronizeAffiliateCouponCarts = exports.listNativePromotionCartIds = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
7
+ const affiliate_cart_operation_lock_1 = require("../../utils/affiliate-cart-operation-lock");
8
+ const resolve_services_1 = require("../../utils/resolve-services");
9
+ const cart_promotions_1 = require("../../utils/cart-promotions");
10
+ const settle_cart_promotions_1 = require("../../utils/settle-cart-promotions");
11
+ const ensure_affiliate_coupon_promotion_1 = require("./ensure-affiliate-coupon-promotion");
12
+ const affiliate_coupon_cart_1 = require("./affiliate-coupon-cart");
13
+ const cleanupErrorMessage = (error) => `Affiliate coupon cart cleanup failed: ${error instanceof Error ? error.message : "Unknown error"}`.slice(0, 2_000);
14
+ const loadOpenCart = async (container, cartId) => {
15
+ const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
16
+ const { data } = await query.graph({
17
+ entity: "cart",
18
+ fields: ["id", "completed_at", "promotions.id", "promotions.code"],
19
+ filters: { id: cartId }
20
+ }, { cache: { enable: false } });
21
+ const cart = data[0];
22
+ return cart && !cart.completed_at ? cart : null;
23
+ };
24
+ const listNativePromotionCartIds = async (container, promotionId) => {
25
+ if (!promotionId)
26
+ return [];
27
+ const remoteQuery = container.resolve(utils_1.ContainerRegistrationKeys.REMOTE_QUERY);
28
+ const cartIds = new Set();
29
+ const pageSize = 100;
30
+ let skip = 0;
31
+ while (true) {
32
+ const { data } = await remoteQuery.graph({
33
+ entity: "cart_promotion",
34
+ fields: ["cart_id", "cart.completed_at"],
35
+ filters: { promotion_id: [promotionId] },
36
+ pagination: {
37
+ skip,
38
+ take: pageSize,
39
+ order: { cart_id: "ASC" }
40
+ }
41
+ }, { cache: { enable: false } });
42
+ const links = data;
43
+ for (const link of links) {
44
+ if (!link.cart?.completed_at)
45
+ cartIds.add(link.cart_id);
46
+ }
47
+ if (links.length < pageSize)
48
+ break;
49
+ skip += links.length;
50
+ }
51
+ return [...cartIds].sort();
52
+ };
53
+ exports.listNativePromotionCartIds = listNativePromotionCartIds;
54
+ const isExpectedCouponIneligibility = (error) => error instanceof utils_1.MedusaError &&
55
+ error.type === utils_1.MedusaError.Types.INVALID_DATA &&
56
+ error.message === "coupon_not_applicable";
57
+ const removeNativeCouponPromotionFromCart = async (container, coupon, cartId) => {
58
+ if (!coupon.promotion_id)
59
+ return;
60
+ const cart = await loadOpenCart(container, cartId);
61
+ if (!cart)
62
+ return;
63
+ const promotion = (0, cart_promotions_1.readCartPromotions)(cart.promotions).find(({ id }) => id === coupon.promotion_id);
64
+ if (!promotion)
65
+ return;
66
+ await (0, core_flows_1.updateCartPromotionsWorkflow)(container).run({
67
+ input: {
68
+ cart_id: cartId,
69
+ promo_codes: [promotion.code || coupon.code],
70
+ action: utils_1.PromotionActions.REMOVE,
71
+ force_refresh_payment_collection: true
72
+ }
73
+ });
74
+ // Removing this code changes item_total; settle so any other
75
+ // total-dependent automatic promotion re-evaluates against the
76
+ // now-accurate cart instead of the pre-removal snapshot.
77
+ await (0, settle_cart_promotions_1.settleCartPromotions)(container, cartId);
78
+ const readback = await loadOpenCart(container, cartId);
79
+ if ((0, cart_promotions_1.readCartPromotions)(readback?.promotions).some(({ id }) => id === coupon.promotion_id)) {
80
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Cart "${cartId}" still contains revoked Affiliate promotion "${coupon.promotion_id}".`);
81
+ }
82
+ };
83
+ const persistCleanupFailure = async (container, coupon, error) => {
84
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
85
+ const failures = [error];
86
+ try {
87
+ await (0, affiliate_cart_operation_lock_1.withAffiliateOperationLocks)(container, [(0, affiliate_cart_operation_lock_1.affiliateSagaLockKey)(coupon.affiliate_id)], async () => {
88
+ const current = await affiliateService.retrieveAffiliateCouponRecord(coupon.id, coupon.affiliate_id);
89
+ await affiliateService.setAffiliateCouponProvisioningState({
90
+ coupon_id: current.id,
91
+ ...(current.promotion_id
92
+ ? { promotion_id: current.promotion_id }
93
+ : {}),
94
+ provisioning_status: "failed",
95
+ promotion_setup_error: cleanupErrorMessage(error)
96
+ });
97
+ });
98
+ }
99
+ catch (stateError) {
100
+ failures.push(stateError);
101
+ }
102
+ if (failures.length === 1)
103
+ throw error;
104
+ throw new AggregateError(failures, "Affiliate coupon cleanup and failure persistence failed");
105
+ };
106
+ const cleanupRevokedAffiliateCoupon = async (container, couponId) => {
107
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
108
+ const coupon = await affiliateService.retrieveAffiliateCouponRecord(couponId);
109
+ try {
110
+ const [local, nativeCartIds] = await Promise.all([
111
+ affiliateService.invalidateOpenAttributionStateForCoupon({
112
+ affiliate_coupon_id: coupon.id,
113
+ reason: "coupon_revoked"
114
+ }),
115
+ (0, exports.listNativePromotionCartIds)(container, coupon.promotion_id)
116
+ ]);
117
+ const cartIds = [
118
+ ...new Set([...local.open_cart_ids, ...nativeCartIds])
119
+ ].sort();
120
+ const failures = [];
121
+ for (const cartId of cartIds) {
122
+ try {
123
+ await (0, affiliate_cart_operation_lock_1.withAffiliateCartOperationLock)(container, cartId, async () => {
124
+ await removeNativeCouponPromotionFromCart(container, coupon, cartId);
125
+ });
126
+ }
127
+ catch (error) {
128
+ failures.push(error);
129
+ }
130
+ }
131
+ if (failures.length) {
132
+ throw failures.length === 1
133
+ ? failures[0]
134
+ : new AggregateError(failures, "Affiliate coupon cleanup failed for one or more carts");
135
+ }
136
+ return await (0, ensure_affiliate_coupon_promotion_1.provisionAffiliateCouponPromotion)(container, {
137
+ coupon_id: coupon.id
138
+ });
139
+ }
140
+ catch (error) {
141
+ return await persistCleanupFailure(container, coupon, error);
142
+ }
143
+ };
144
+ const synchronizeAffiliateCouponCarts = async (container, coupon) => {
145
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
146
+ const affiliate = await affiliateService.retrieveAffiliateRecord(coupon.affiliate_id);
147
+ const [localCartIds, nativeCartIds, settings] = await Promise.all([
148
+ affiliateService.listOpenCartIdsForAffiliateCoupon(coupon.id),
149
+ (0, exports.listNativePromotionCartIds)(container, coupon.promotion_id),
150
+ affiliateService.retrieveProgramSettings()
151
+ ]);
152
+ const locallyApplied = new Set(localCartIds);
153
+ const cartIds = [...new Set([...localCartIds, ...nativeCartIds])].sort();
154
+ const failures = [];
155
+ for (const cartId of cartIds) {
156
+ try {
157
+ await (0, affiliate_cart_operation_lock_1.withAffiliateCartOperationLock)(container, cartId, async () => {
158
+ const cart = await loadOpenCart(container, cartId);
159
+ if (!cart)
160
+ return;
161
+ const currentReferrals = coupon.promotion_id
162
+ ? await affiliateService.listAffiliateCartReferrals({
163
+ cart_id: cartId,
164
+ status: "active",
165
+ applied_affiliate_coupon_id: coupon.id,
166
+ applied_promotion_id: coupon.promotion_id
167
+ }, { take: 1, order: { captured_at: "DESC", id: "DESC" } })
168
+ : [];
169
+ const currentlyApplied = currentReferrals.some(({ expires_at }) => new Date(expires_at).getTime() > Date.now());
170
+ // A cart operation that won the lock may have replaced this coupon
171
+ // after discovery. Its mutation owns any required cleanup.
172
+ if (locallyApplied.has(cartId) && !currentlyApplied)
173
+ return;
174
+ if (affiliate.status === "active" && currentlyApplied) {
175
+ await (0, affiliate_coupon_cart_1.syncAffiliateCouponCartPromotion)({
176
+ container,
177
+ affiliate_service: affiliateService,
178
+ cart_id: cartId,
179
+ target_coupon: coupon,
180
+ promotion_stacking: settings.promotion_stacking,
181
+ base_promotions: (0, cart_promotions_1.readCartPromotions)(cart.promotions),
182
+ force_replace: true
183
+ });
184
+ return;
185
+ }
186
+ await affiliateService.removeAffiliateCouponFromCartReferrals({
187
+ cart_id: cartId,
188
+ affiliate_coupon_id: coupon.id,
189
+ reason: affiliate.status === "active"
190
+ ? "coupon_binding_missing"
191
+ : "affiliate_inactive"
192
+ });
193
+ await removeNativeCouponPromotionFromCart(container, coupon, cartId);
194
+ });
195
+ }
196
+ catch (error) {
197
+ const cleanupFailures = isExpectedCouponIneligibility(error)
198
+ ? []
199
+ : [error];
200
+ try {
201
+ await (0, affiliate_cart_operation_lock_1.withAffiliateCartOperationLock)(container, cartId, async () => {
202
+ await affiliateService.removeAffiliateCouponFromCartReferrals({
203
+ cart_id: cartId,
204
+ affiliate_coupon_id: coupon.id,
205
+ reason: "coupon_reconciliation_failed"
206
+ });
207
+ await removeNativeCouponPromotionFromCart(container, coupon, cartId);
208
+ });
209
+ }
210
+ catch (cleanupError) {
211
+ cleanupFailures.push(cleanupError);
212
+ }
213
+ if (cleanupFailures.length) {
214
+ failures.push(cleanupFailures.length === 1
215
+ ? cleanupFailures[0]
216
+ : new AggregateError(cleanupFailures, `Affiliate coupon cleanup failed for cart "${cartId}"`));
217
+ }
218
+ }
219
+ }
220
+ if (failures.length) {
221
+ const error = failures.length === 1
222
+ ? failures[0]
223
+ : new AggregateError(failures, "Affiliate coupon reconciliation failed for one or more carts");
224
+ await persistCleanupFailure(container, coupon, error);
225
+ }
226
+ };
227
+ exports.synchronizeAffiliateCouponCarts = synchronizeAffiliateCouponCarts;
228
+ const reconcileAffiliateCouponForCart = async (container, couponId, cartId) => {
229
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
230
+ let coupon = await affiliateService.retrieveAffiliateCouponRecord(couponId);
231
+ try {
232
+ if (coupon.lifecycle_status === "revoked") {
233
+ await affiliateService.removeAffiliateCouponFromCartReferrals({
234
+ cart_id: cartId,
235
+ affiliate_coupon_id: coupon.id,
236
+ reason: "coupon_revoked"
237
+ });
238
+ await removeNativeCouponPromotionFromCart(container, coupon, cartId);
239
+ return;
240
+ }
241
+ const result = await (0, ensure_affiliate_coupon_promotion_1.provisionAffiliateCouponPromotion)(container, {
242
+ coupon_id: coupon.id
243
+ });
244
+ coupon = result.coupon;
245
+ if (result.revoked_coupon) {
246
+ await affiliateService.removeAffiliateCouponFromCartReferrals({
247
+ cart_id: cartId,
248
+ affiliate_coupon_id: result.revoked_coupon.id,
249
+ reason: "coupon_revoked"
250
+ });
251
+ await removeNativeCouponPromotionFromCart(container, result.revoked_coupon, cartId);
252
+ }
253
+ const affiliate = await affiliateService.retrieveAffiliateRecord(coupon.affiliate_id);
254
+ const localCartIds = new Set(await affiliateService.listOpenCartIdsForAffiliateCoupon(coupon.id));
255
+ const cart = await loadOpenCart(container, cartId);
256
+ if (!cart)
257
+ return;
258
+ if (affiliate.status !== "active" || !localCartIds.has(cartId)) {
259
+ await affiliateService.removeAffiliateCouponFromCartReferrals({
260
+ cart_id: cartId,
261
+ affiliate_coupon_id: coupon.id,
262
+ reason: affiliate.status === "active"
263
+ ? "coupon_binding_missing"
264
+ : "affiliate_inactive"
265
+ });
266
+ await removeNativeCouponPromotionFromCart(container, coupon, cartId);
267
+ return;
268
+ }
269
+ const settings = await affiliateService.retrieveProgramSettings();
270
+ await (0, affiliate_coupon_cart_1.syncAffiliateCouponCartPromotion)({
271
+ container,
272
+ affiliate_service: affiliateService,
273
+ cart_id: cartId,
274
+ target_coupon: coupon,
275
+ promotion_stacking: settings.promotion_stacking,
276
+ base_promotions: (0, cart_promotions_1.readCartPromotions)(cart.promotions),
277
+ force_replace: true
278
+ });
279
+ }
280
+ catch (error) {
281
+ return await persistCleanupFailure(container, coupon, error);
282
+ }
283
+ };
284
+ exports.reconcileAffiliateCouponForCart = reconcileAffiliateCouponForCart;
285
+ const reconcileAffiliateCoupon = async (container, input) => {
286
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
287
+ const observed = await affiliateService.retrieveAffiliateCouponRecord(input.coupon_id);
288
+ if (observed.lifecycle_status === "revoked") {
289
+ return await cleanupRevokedAffiliateCoupon(container, observed.id);
290
+ }
291
+ const result = await (0, ensure_affiliate_coupon_promotion_1.provisionAffiliateCouponPromotion)(container, input);
292
+ return await (0, exports.completeAffiliateCouponReconciliation)(container, result);
293
+ };
294
+ exports.reconcileAffiliateCoupon = reconcileAffiliateCoupon;
295
+ const completeAffiliateCouponReconciliation = async (container, result) => {
296
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
297
+ const coupon = result.coupon;
298
+ let revokedCoupon = result.revoked_coupon;
299
+ if (coupon.replaces_coupon_id) {
300
+ const predecessor = await affiliateService.retrieveAffiliateCouponRecord(coupon.replaces_coupon_id, coupon.affiliate_id);
301
+ if (predecessor.lifecycle_status === "revoked") {
302
+ revokedCoupon = (await cleanupRevokedAffiliateCoupon(container, predecessor.id)).coupon;
303
+ }
304
+ }
305
+ await (0, exports.synchronizeAffiliateCouponCarts)(container, coupon);
306
+ return {
307
+ ...result,
308
+ revoked_coupon: revokedCoupon
309
+ };
310
+ };
311
+ exports.completeAffiliateCouponReconciliation = completeAffiliateCouponReconciliation;
312
+ const reconcileAffiliateCouponsForAffiliate = async (container, affiliateId) => {
313
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
314
+ const reconciled = [];
315
+ const failures = [];
316
+ const pageSize = 100;
317
+ let offset = 0;
318
+ while (true) {
319
+ const [coupons] = await affiliateService.listAffiliateCouponRecordsWithCount({
320
+ affiliate_id: affiliateId,
321
+ lifecycle_status: "enabled",
322
+ limit: pageSize,
323
+ offset
324
+ });
325
+ for (const coupon of coupons) {
326
+ try {
327
+ const result = await (0, exports.reconcileAffiliateCoupon)(container, {
328
+ coupon_id: coupon.id
329
+ });
330
+ reconciled.push(result.coupon);
331
+ }
332
+ catch (error) {
333
+ failures.push(error);
334
+ }
335
+ }
336
+ if (coupons.length < pageSize)
337
+ break;
338
+ offset += pageSize;
339
+ }
340
+ if (failures.length === 1)
341
+ throw failures[0];
342
+ if (failures.length) {
343
+ throw new AggregateError(failures, `Affiliate coupon reconciliation failed for affiliate "${affiliateId}"`);
344
+ }
345
+ return reconciled;
346
+ };
347
+ exports.reconcileAffiliateCouponsForAffiliate = reconcileAffiliateCouponsForAffiliate;
348
+ const reconcileCouponsUsingDefaultDiscount = async (container) => {
349
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
350
+ const failures = [];
351
+ const couponIds = [];
352
+ const affiliates = new Map();
353
+ const pageSize = 100;
354
+ let offset = 0;
355
+ while (true) {
356
+ const [coupons] = await affiliateService.listAffiliateCouponRecordsWithCount({
357
+ lifecycle_status: "enabled",
358
+ limit: pageSize,
359
+ offset
360
+ });
361
+ couponIds.push(...coupons.map(({ id, affiliate_id }) => ({ id, affiliate_id })));
362
+ if (coupons.length < pageSize)
363
+ break;
364
+ offset += pageSize;
365
+ }
366
+ for (const coupon of couponIds) {
367
+ try {
368
+ let affiliate = affiliates.get(coupon.affiliate_id);
369
+ if (!affiliate) {
370
+ affiliate = await affiliateService.retrieveAffiliateRecord(coupon.affiliate_id);
371
+ affiliates.set(coupon.affiliate_id, affiliate);
372
+ }
373
+ if (affiliate.customer_discount_rate_override != null)
374
+ continue;
375
+ await (0, exports.reconcileAffiliateCoupon)(container, { coupon_id: coupon.id });
376
+ }
377
+ catch (error) {
378
+ failures.push({ coupon_id: coupon.id, error });
379
+ }
380
+ }
381
+ return failures;
382
+ };
383
+ exports.reconcileCouponsUsingDefaultDiscount = reconcileCouponsUsingDefaultDiscount;
384
+ const reconcileAffiliateCouponStep = (0, workflows_sdk_1.createStep)("reconcile-affiliate-coupon", async (input, { container }) => new workflows_sdk_1.StepResponse(await (0, exports.reconcileAffiliateCoupon)(container, input)));
385
+ exports.reconcileAffiliateCouponWorkflow = (0, workflows_sdk_1.createWorkflow)("reconcile-affiliate-coupon", (input) => new workflows_sdk_1.WorkflowResponse(reconcileAffiliateCouponStep(input)));
386
+ const reconcileAffiliateCouponsForAffiliateStep = (0, workflows_sdk_1.createStep)("reconcile-affiliate-coupons-for-affiliate", async (input, { container }) => new workflows_sdk_1.StepResponse(await (0, exports.reconcileAffiliateCouponsForAffiliate)(container, input.affiliate_id)));
387
+ exports.reconcileAffiliateCouponsForAffiliateWorkflow = (0, workflows_sdk_1.createWorkflow)("reconcile-affiliate-coupons-for-affiliate", (input) => new workflows_sdk_1.WorkflowResponse(reconcileAffiliateCouponsForAffiliateStep(input)));
388
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb25jaWxlLWFmZmlsaWF0ZS1jb3Vwb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2FmZmlsaWF0ZS9yZWNvbmNpbGUtYWZmaWxpYXRlLWNvdXBvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSxxRUFLMEM7QUFDMUMscURBSWtDO0FBQ2xDLDREQUEwRTtBQUcxRSw2RkFJa0Q7QUFDbEQsbUVBQXNFO0FBQ3RFLGlFQUFnRTtBQUNoRSwrRUFBeUU7QUFDekUsMkZBSTRDO0FBQzVDLG1FQUdnQztBQXVCaEMsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLEtBQWMsRUFBVSxFQUFFLENBQ3JELHlDQUNFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGVBQzNDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFBO0FBRXBCLE1BQU0sWUFBWSxHQUFHLEtBQUssRUFDeEIsU0FBMEIsRUFDMUIsTUFBYyxFQUNZLEVBQUU7SUFDNUIsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNoRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUNoQztRQUNFLE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxlQUFlLEVBQUUsaUJBQWlCLENBQUM7UUFDbEUsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRTtLQUN4QixFQUNELEVBQUUsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQzdCLENBQUE7SUFDRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUF5QixDQUFBO0lBQzVDLE9BQU8sSUFBSSxJQUFJ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
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.refreshAffiliateOwnOrderPromotion = exports.refreshAffiliatePromotions = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const affiliate_cart_operation_lock_1 = require("../../utils/affiliate-cart-operation-lock");
6
+ const resolve_services_1 = require("../../utils/resolve-services");
7
+ const ensure_affiliate_coupon_promotion_1 = require("./ensure-affiliate-coupon-promotion");
8
+ const ensure_affiliate_own_order_promotion_1 = require("./ensure-affiliate-own-order-promotion");
9
+ const promotion_eligibility_1 = require("./promotion-eligibility");
10
+ const PAGE_SIZE = 100;
11
+ /**
12
+ * Brings every live Affiliate promotion back in line with the stored rates
13
+ * and the current variant allowlist. Cart and checkout only verify that a
14
+ * promotion is authentic, so this bounds how long a missed update (a catalogue
15
+ * change without an event, a transient provisioning failure, a manual edit in
16
+ * the Medusa promotion admin) can stay in effect.
17
+ *
18
+ * It never touches carts, and a run against current promotions only reads:
19
+ * ready coupons are provisioned in place (no "pending" window), and own-order
20
+ * promotions are rewritten only when they differ.
21
+ */
22
+ const refreshAffiliatePromotions = async (container) => {
23
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
24
+ const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
25
+ const eligibleVariantIds = await (0, promotion_eligibility_1.listAffiliateEligibleVariantIds)(query);
26
+ const failures = [];
27
+ // Only live coupons: repairing pending or failed ones (including rotations
28
+ // and revoked-coupon cart cleanup) stays with the Admin reconcile.
29
+ const couponIds = [];
30
+ for (let offset = 0;; offset += PAGE_SIZE) {
31
+ const [coupons] = await affiliateService.listAffiliateCouponRecordsWithCount({
32
+ lifecycle_status: "enabled",
33
+ provisioning_status: "ready",
34
+ limit: PAGE_SIZE,
35
+ offset,
36
+ });
37
+ couponIds.push(...coupons.map(({ id }) => id));
38
+ if (coupons.length < PAGE_SIZE)
39
+ break;
40
+ }
41
+ for (const couponId of couponIds) {
42
+ try {
43
+ await (0, ensure_affiliate_coupon_promotion_1.provisionAffiliateCouponPromotion)(container, {
44
+ coupon_id: couponId,
45
+ eligible_variant_ids: eligibleVariantIds,
46
+ });
47
+ }
48
+ catch (error) {
49
+ failures.push({ kind: "coupon", id: couponId, error });
50
+ }
51
+ }
52
+ const affiliateIds = [];
53
+ for (let offset = 0;; offset += PAGE_SIZE) {
54
+ const [affiliates] = await affiliateService.listAffiliateRecords({
55
+ limit: PAGE_SIZE,
56
+ offset,
57
+ });
58
+ affiliateIds.push(...affiliates.map(({ id }) => id));
59
+ if (affiliates.length < PAGE_SIZE)
60
+ break;
61
+ }
62
+ for (const affiliateId of affiliateIds) {
63
+ try {
64
+ await (0, exports.refreshAffiliateOwnOrderPromotion)(container, affiliateId, eligibleVariantIds);
65
+ }
66
+ catch (error) {
67
+ failures.push({ kind: "own_order", id: affiliateId, error });
68
+ }
69
+ }
70
+ return failures;
71
+ };
72
+ exports.refreshAffiliatePromotions = refreshAffiliatePromotions;
73
+ /**
74
+ * Runs under the Affiliate's saga lock, which status changes such as
75
+ * deactivation also hold, so the promotion is always derived from the
76
+ * Affiliate's final state.
77
+ */
78
+ const refreshAffiliateOwnOrderPromotion = async (container, affiliateId, eligibleVariantIds) => await (0, affiliate_cart_operation_lock_1.withAffiliateOperationLocks)(container, [(0, affiliate_cart_operation_lock_1.affiliateSagaLockKey)(affiliateId)], async () => {
79
+ const affiliate = await (0, resolve_services_1.resolveAffiliateService)(container).retrieveAffiliateRecord(affiliateId);
80
+ const promotionService = container.resolve(utils_1.Modules.PROMOTION);
81
+ const rate = affiliate.own_order_discount_rate;
82
+ const shouldBeActive = affiliate.status === "active" && Boolean(affiliate.customer_id) && rate > 0;
83
+ const [promotion] = affiliate.own_order_promotion_id
84
+ ? await promotionService.listPromotions({ id: [affiliate.own_order_promotion_id] }, { relations: ["rules", "rules.values", "application_method"], take: 1 })
85
+ : [];
86
+ if (!promotion) {
87
+ if (!affiliate.own_order_promotion_id && shouldBeActive) {
88
+ await (0, ensure_affiliate_own_order_promotion_1.ensureAffiliateOwnOrderPromotionWorkflow)(container).run({
89
+ input: { affiliate_id: affiliate.id },
90
+ });
91
+ }
92
+ return;
93
+ }
94
+ const boundToCustomer = (promotion.rules ?? []).some((rule) => rule.attribute === "customer.id" &&
95
+ (rule.values ?? []).some(({ value }) => value === affiliate.customer_id));
96
+ const current = shouldBeActive
97
+ ? promotion.status === "active" &&
98
+ promotion.is_automatic === true &&
99
+ boundToCustomer &&
100
+ promotion.application_method?.type === "percentage" &&
101
+ Number(promotion.application_method.value) === rate
102
+ : promotion.status === "inactive";
103
+ if (!current) {
104
+ await (0, ensure_affiliate_own_order_promotion_1.ensureAffiliateOwnOrderPromotionWorkflow)(container).run({
105
+ input: { affiliate_id: affiliate.id },
106
+ });
107
+ return;
108
+ }
109
+ if (shouldBeActive) {
110
+ await (0, promotion_eligibility_1.ensureAffiliateEligibleItemTargetRules)(promotionService, container.resolve(utils_1.ContainerRegistrationKeys.QUERY), promotion.id, eligibleVariantIds);
111
+ }
112
+ });
113
+ exports.refreshAffiliateOwnOrderPromotion = refreshAffiliateOwnOrderPromotion;
114
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVmcmVzaC1hZmZpbGlhdGUtcHJvbW90aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy93b3JrZmxvd3MvYWZmaWxpYXRlL3JlZnJlc2gtYWZmaWxpYXRlLXByb21vdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEscURBR2tDO0FBRWxDLDZGQUdrRDtBQUNsRCxtRUFBc0U7QUFDdEUsMkZBQXVGO0FBQ3ZGLGlHQUFpRztBQUNqRyxtRUFHZ0M7QUFFaEMsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFBO0FBUXJCOzs7Ozs7Ozs7O0dBVUc7QUFDSSxNQUFNLDBCQUEwQixHQUFHLEtBQUssRUFDN0MsU0FBMEIsRUFDbUIsRUFBRTtJQUMvQyxNQUFNLGdCQUFnQixHQUFHLElBQUEsMENBQXVCLEVBQUMsU0FBUyxDQUFDLENBQUE7SUFDM0QsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNoRSxNQUFNLGtCQUFrQixHQUFHLE1BQU0sSUFBQSx1REFBK0IsRUFBQyxLQUFLLENBQUMsQ0FBQTtJQUN2RSxNQUFNLFFBQVEsR0FBdUMsRUFBRSxDQUFBO0lBRXZELDJFQUEyRTtJQUMzRSxtRUFBbUU7SUFDbkUsTUFBTSxTQUFTLEdBQWEsRUFBRSxDQUFBO0lBQzlCLEtBQUssSUFBSSxNQUFNLEdBQUcsQ0FBQyxHQUFJLE1BQU0sSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUMzQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxtQ0FBbUMsQ0FDMUU7WUFDRSxnQkFBZ0IsRUFBRSxTQUFTO1lBQzNCLG1CQUFtQixFQUFFLE9BQU87WUFDNUIsS0FBSyxFQUFFLFNBQVM7WUFDaEIsTUFBTTtTQUNQLENBQ0YsQ0FBQTtRQUNELFNBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMs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
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveAffiliateCouponLabels = void 0;
4
+ const own_order_coupon_code_1 = require("../../modules/affiliate/domain/own-order-coupon-code");
5
+ const OWN_ORDER_COUPON_LABEL = "Wiederverkäuferrabatt";
6
+ /**
7
+ * Resolves a display label for whichever of the given codes are an
8
+ * affiliate's own-order discount coupon (see `own-order-coupon-code.ts`).
9
+ * Codes that don't match the pattern, or whose affiliate no longer exists,
10
+ * are silently omitted from the result - this is a best-effort display
11
+ * lookup, not a validation of the codes' eligibility on any cart.
12
+ */
13
+ const resolveAffiliateCouponLabels = async (affiliateService, codes) => {
14
+ const uniqueCodes = [...new Set(codes)];
15
+ const resolved = await Promise.all(uniqueCodes.map(async (code) => {
16
+ const parsed = (0, own_order_coupon_code_1.parseAffiliateOwnOrderCouponCode)(code);
17
+ if (!parsed) {
18
+ return null;
19
+ }
20
+ try {
21
+ const affiliate = await affiliateService.retrieveAffiliateRecord(parsed.affiliateId);
22
+ // The code encodes both ids together; only label it if they still
23
+ // agree with the affiliate record it resolved to.
24
+ if (affiliate.customer_id !== parsed.customerId) {
25
+ return null;
26
+ }
27
+ return {
28
+ code,
29
+ label: OWN_ORDER_COUPON_LABEL,
30
+ discount_percentage: affiliate.own_order_discount_rate,
31
+ };
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }));
37
+ return resolved.filter((label) => label !== null);
38
+ };
39
+ exports.resolveAffiliateCouponLabels = resolveAffiliateCouponLabels;
40
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb2x2ZS1jb3Vwb24tbGFiZWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9hZmZpbGlhdGUvcmVzb2x2ZS1jb3Vwb24tbGFiZWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGdHQUF1RztBQVN2RyxNQUFNLHNCQUFzQixHQUFHLHVCQUF1QixDQUFBO0FBRXREOzs7Ozs7R0FNRztBQUNJLE1BQU0sNEJBQTRCLEdBQUcsS0FBSyxFQUMvQyxnQkFBd0MsRUFDeEMsS0FBZSxFQUMwQixFQUFFO0lBQzNDLE1BQU0sV0FBVyxHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO0lBRXZDLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDaEMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDN0IsTUFBTSxNQUFNLEdBQUcsSUFBQSx3REFBZ0MsRUFBQyxJQUFJLENBQUMsQ0FBQTtRQUNyRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixPQUFPLElBQUksQ0FBQTtRQUNiLENBQUM7UUFFRCxJQUFJLENBQUM7WUFDSCxNQUFNLFNBQVMsR0FBRyxNQUFNLGdCQUFnQixDQUFDLHVCQUF1QixDQUM5RCxNQUFNLENBQUMsV0FBVyxDQUNuQixDQUFBO1lBQ0Qsa0VBQWtFO1lBQ2xFLGtEQUFrRDtZQUNsRCxJQUFJLFNBQVMsQ0FBQyxXQUFXLEtBQUssTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNoRCxPQUFPLElBQUksQ0FBQTtZQUNiLENBQUM7WUFFRCxPQUFPO2dCQUNMLElBQUk7Z0JBQ0osS0FBSyxFQUFFLHNCQUFzQjtnQkFDN0IsbUJBQW1CLEVBQUUsU0FBUyxDQUFDLHVCQUF1QjthQUN2RCxDQUFBO1FBQ0gsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU8sSUFBSSxDQUFBO1FBQ2IsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUNILENBQUE7SUFFRCxPQUFPLFFBQVEsQ0FBQyxNQUFNLENBQ3BCLENBQUMsS0FBSyxFQUF5QyxFQUFFLENBQUMsS0FBSyxLQUFLLElBQUksQ0FDakUsQ0FBQTtBQUNILENBQUMsQ0FBQTtBQXJDWSxRQUFBLDRCQUE0QixnQ0FxQ3hDIn0=
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.revokeAffiliateCouponWorkflow = exports.revokeAffiliateCoupon = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const affiliate_cart_operation_lock_1 = require("../../utils/affiliate-cart-operation-lock");
6
+ const resolve_services_1 = require("../../utils/resolve-services");
7
+ const reconcile_affiliate_coupon_1 = require("./reconcile-affiliate-coupon");
8
+ const affiliate_coupon_command_authorization_1 = require("./affiliate-coupon-command-authorization");
9
+ const revokeAffiliateCoupon = async (container, input) => {
10
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
11
+ const revoked = await (0, affiliate_coupon_command_authorization_1.withAuthorizedAffiliateCouponCommand)(container, [
12
+ (0, affiliate_cart_operation_lock_1.affiliateProgramSagaLockKey)(),
13
+ (0, affiliate_cart_operation_lock_1.affiliateSagaLockKey)(input.affiliate_id),
14
+ ], {
15
+ affiliate_id: input.affiliate_id,
16
+ actor_type: input.revoked_by_type,
17
+ actor_id: input.revoked_by_id,
18
+ }, async () => await affiliateService.revokeAffiliateCouponRecord({
19
+ ...input,
20
+ revoked_at: input.revoked_at ? new Date(input.revoked_at) : undefined,
21
+ }));
22
+ return (await (0, reconcile_affiliate_coupon_1.reconcileAffiliateCoupon)(container, {
23
+ coupon_id: revoked.id,
24
+ })).coupon;
25
+ };
26
+ exports.revokeAffiliateCoupon = revokeAffiliateCoupon;
27
+ const revokeAffiliateCouponStep = (0, workflows_sdk_1.createStep)("revoke-affiliate-coupon", async (input, { container }) => new workflows_sdk_1.StepResponse(await (0, exports.revokeAffiliateCoupon)(container, input)));
28
+ exports.revokeAffiliateCouponWorkflow = (0, workflows_sdk_1.createWorkflow)("revoke-affiliate-coupon", (input) => new workflows_sdk_1.WorkflowResponse(revokeAffiliateCouponStep(input)));
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV2b2tlLWFmZmlsaWF0ZS1jb3Vwb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2FmZmlsaWF0ZS9yZXZva2UtYWZmaWxpYXRlLWNvdXBvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFLMEM7QUFJMUMsNkZBR2tEO0FBQ2xELG1FQUFzRTtBQUN0RSw2RUFBdUU7QUFDdkUscUdBQStGO0FBVXhGLE1BQU0scUJBQXFCLEdBQUcsS0FBSyxFQUN4QyxTQUEwQixFQUMxQixLQUF5QyxFQUNaLEVBQUU7SUFDL0IsTUFBTSxnQkFBZ0IsR0FBRyxJQUFBLDBDQUF1QixFQUFDLFNBQVMsQ0FBQyxDQUFBO0lBQzNELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBQSw2RUFBb0MsRUFDeEQsU0FBUyxFQUNUO1FBQ0UsSUFBQSwyREFBMkIsR0FBRTtRQUM3QixJQUFBLG9EQUFvQixFQUFDLEtBQUssQ0FBQyxZQUFZLENBQUM7S0FDekMsRUFDRDtRQUNFLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTtRQUNoQyxVQUFVLEVBQUUsS0FBSyxDQUFDLGVBQWU7UUFDakMsUUFBUSxFQUFFLEtBQUssQ0FBQyxhQUFhO0tBQzlCLEVBQ0QsS0FBSyxJQUFJLEVBQUUsQ0FDVCxNQUFNLGdCQUFnQixDQUFDLDJCQUEyQixDQUFDO1FBQ2pELEdBQUcsS0FBSztRQUNSLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7S0FDdEUsQ0FBQyxDQUNMLENBQUE7SUFDRCxPQUFPLENBQ0wsTUFBTSxJQUFBLHFEQUF3QixFQUFDLFNBQVMsRUFBRTtRQUN4QyxTQUFTLEVBQUUsT0FBTyxDQUFDLEVBQUU7S0FDdEIsQ0FBQyxDQUNILENBQUMsTUFBTSxDQUFBO0FBQ1YsQ0FBQyxDQUFBO0FBM0JZLFFBQUEscUJBQXFCLHlCQTJCakM7QUFFRCxNQUFNLHlCQUF5QixHQUFHLElBQUEsMEJBQVUsRUFDMUMseUJBQXlCLEVBQ3pCLEtBQUssRUFDSCxLQUF5QyxFQUN6QyxFQUFFLFNBQVMsRUFBRSxFQUM4QixFQUFFLENBQzdDLElBQUksNEJBQVksQ0FBQyxNQUFNLElBQUEsNkJBQXFCLEVBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQ2xFLENBQUE7QUFFWSxRQUFBLDZCQUE2QixHQUFHLElBQUEsOEJBQWMsRUFDekQseUJBQXlCLEVBQ3pCLENBQUMsS0FBeUMsRUFBRSxFQUFFLENBQzVDLElBQUksZ0NBQWdCLENBQUMseUJBQXlCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDekQsQ0FBQSJ9