@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,242 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AffiliateManager = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const types_1 = require("../../../types");
6
+ const utils_2 = require("./utils");
7
+ // The admin overview lists affiliate accounts, not review-queue applicants —
8
+ // a still-pending applicant only has an application row, not yet an
9
+ // affiliate one, so this excludes the (otherwise unreachable in practice)
10
+ // "pending" affiliate status by default to keep the overview free of it.
11
+ const NON_PENDING_AFFILIATE_STATUSES = types_1.affiliateStatuses.filter((status) => status !== "pending");
12
+ class AffiliateManager {
13
+ constructor(store, slugService) {
14
+ this.store = store;
15
+ this.slugService = slugService;
16
+ }
17
+ async createAffiliate(input, context) {
18
+ this.validateStatus(input.status ?? "pending");
19
+ (0, utils_2.assertRate)(input.commission_rate, "commission_rate");
20
+ (0, utils_2.assertRate)(input.own_order_discount_rate, "own_order_discount_rate");
21
+ if (input.customer_discount_rate_override != null) {
22
+ (0, utils_2.assertRate)(input.customer_discount_rate_override, "customer_discount_rate_override");
23
+ }
24
+ if (input.referrer_commission_rate !== undefined && input.referrer_commission_rate !== null) {
25
+ (0, utils_2.assertRate)(input.referrer_commission_rate, "referrer_commission_rate");
26
+ }
27
+ if (input.referred_by_affiliate_id) {
28
+ const referrer = await this.store.retrieveAffiliate(input.referred_by_affiliate_id, context);
29
+ this.assertAffiliateIsActive(referrer, "Referring affiliate must be active.");
30
+ }
31
+ // Check an explicitly requested slug is free before inserting the affiliate
32
+ // row, so the write pair can't leave an affiliate without its primary slug.
33
+ if (input.slug) {
34
+ await this.slugService.assertSlugAvailable(input.slug, context);
35
+ }
36
+ const customerAssignmentMode = input.customer_assignment_mode ?? "lifetime";
37
+ const assignmentDurationDays = input.assignment_duration_days ?? null;
38
+ this.assertAssignmentPolicy(customerAssignmentMode, assignmentDurationDays);
39
+ const status = input.status ?? "pending";
40
+ this.assertActivatableCommission(status, input.commission_rate);
41
+ const now = new Date();
42
+ const affiliate = await this.store.createAffiliates({
43
+ display_name: input.display_name.trim(),
44
+ customer_id: input.customer_id ?? null,
45
+ status,
46
+ commission_rate: input.commission_rate,
47
+ own_order_discount_rate: input.own_order_discount_rate,
48
+ customer_assignment_mode: customerAssignmentMode,
49
+ assignment_duration_days: assignmentDurationDays,
50
+ customer_discount_rate_override: input.customer_discount_rate_override ?? null,
51
+ own_order_promotion_id: null,
52
+ referred_by_affiliate_id: input.referred_by_affiliate_id ?? null,
53
+ referrer_commission_rate: input.referrer_commission_rate ?? null,
54
+ primary_slug_id: null,
55
+ internal_notes: (0, utils_2.parseOptionalText)(input.internal_notes),
56
+ activated_at: status === "active" ? now : null,
57
+ inactivated_at: status === "inactive" ? now : null,
58
+ metadata: input.metadata ?? null,
59
+ }, context);
60
+ const slugValue = input.slug ??
61
+ (await this.slugService.generateAvailableSlug(input.display_name, context));
62
+ await this.slugService.createSlug({
63
+ affiliate_id: affiliate.id,
64
+ slug: slugValue,
65
+ active: true,
66
+ is_primary: true,
67
+ }, context);
68
+ return await this.retrieveAffiliateWithSlugs(affiliate.id, context);
69
+ }
70
+ async updateAffiliate(input, context) {
71
+ const existing = await this.store.retrieveAffiliate(input.id, context);
72
+ const customerAssignmentMode = input.customer_assignment_mode ?? existing.customer_assignment_mode;
73
+ const assignmentDurationDays = input.assignment_duration_days !== undefined
74
+ ? input.assignment_duration_days
75
+ : existing.assignment_duration_days;
76
+ this.assertAssignmentPolicy(customerAssignmentMode, assignmentDurationDays);
77
+ if (input.status !== undefined) {
78
+ this.validateStatus(input.status);
79
+ }
80
+ if (input.commission_rate !== undefined) {
81
+ (0, utils_2.assertRate)(input.commission_rate, "commission_rate");
82
+ }
83
+ if (input.own_order_discount_rate !== undefined) {
84
+ (0, utils_2.assertRate)(input.own_order_discount_rate, "own_order_discount_rate");
85
+ }
86
+ if (input.customer_discount_rate_override != null) {
87
+ (0, utils_2.assertRate)(input.customer_discount_rate_override, "customer_discount_rate_override");
88
+ }
89
+ if (input.referrer_commission_rate !== undefined && input.referrer_commission_rate !== null) {
90
+ (0, utils_2.assertRate)(input.referrer_commission_rate, "referrer_commission_rate");
91
+ }
92
+ if (input.referred_by_affiliate_id) {
93
+ if (input.referred_by_affiliate_id === input.id) {
94
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "An affiliate cannot refer itself.");
95
+ }
96
+ const referrer = await this.store.retrieveAffiliate(input.referred_by_affiliate_id, context);
97
+ this.assertAffiliateIsActive(referrer, "Referring affiliate must be active.");
98
+ }
99
+ const nextStatus = input.status ?? existing.status;
100
+ const nextCommissionRate = input.commission_rate ?? existing.commission_rate;
101
+ this.assertActivatableCommission(nextStatus, nextCommissionRate);
102
+ const becameActive = existing.status !== "active" && nextStatus === "active";
103
+ const becameInactive = existing.status !== "inactive" && nextStatus === "inactive";
104
+ const updated = (await this.store.updateAffiliates({
105
+ id: input.id,
106
+ ...(input.display_name !== undefined
107
+ ? { display_name: input.display_name.trim() }
108
+ : {}),
109
+ ...(input.customer_id !== undefined
110
+ ? { customer_id: input.customer_id ?? null }
111
+ : {}),
112
+ ...(input.status !== undefined ? { status: input.status } : {}),
113
+ ...(input.commission_rate !== undefined
114
+ ? { commission_rate: input.commission_rate }
115
+ : {}),
116
+ ...(input.own_order_discount_rate !== undefined
117
+ ? { own_order_discount_rate: input.own_order_discount_rate }
118
+ : {}),
119
+ ...(input.customer_assignment_mode !== undefined
120
+ ? { customer_assignment_mode: input.customer_assignment_mode }
121
+ : {}),
122
+ ...(input.assignment_duration_days !== undefined
123
+ ? { assignment_duration_days: input.assignment_duration_days }
124
+ : {}),
125
+ ...(input.customer_discount_rate_override !== undefined
126
+ ? {
127
+ customer_discount_rate_override: input.customer_discount_rate_override ?? null,
128
+ }
129
+ : {}),
130
+ ...(input.referred_by_affiliate_id !== undefined
131
+ ? { referred_by_affiliate_id: input.referred_by_affiliate_id ?? null }
132
+ : {}),
133
+ ...(input.referrer_commission_rate !== undefined
134
+ ? { referrer_commission_rate: input.referrer_commission_rate ?? null }
135
+ : {}),
136
+ ...(input.internal_notes !== undefined
137
+ ? { internal_notes: (0, utils_2.parseOptionalText)(input.internal_notes) }
138
+ : {}),
139
+ ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),
140
+ ...(becameActive ? { activated_at: new Date(), inactivated_at: null } : {}),
141
+ ...(becameInactive ? { inactivated_at: new Date() } : {}),
142
+ }, context));
143
+ if (input.primary_slug_id !== undefined) {
144
+ if (input.primary_slug_id === null) {
145
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "An affiliate must have a primary slug.");
146
+ }
147
+ await this.slugService.setPrimarySlug({ affiliate_id: input.id, slug_id: input.primary_slug_id }, context);
148
+ }
149
+ return await this.retrieveAffiliateWithSlugs(updated.id, context);
150
+ }
151
+ async setInactive(affiliateId, context) {
152
+ return await this.updateAffiliate({
153
+ id: affiliateId,
154
+ status: "inactive",
155
+ }, context);
156
+ }
157
+ assertAssignmentPolicy(mode, durationDays) {
158
+ if (mode === "time_limited") {
159
+ if (!Number.isInteger(durationDays) || (durationDays ?? 0) <= 0) {
160
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "time_limited affiliates require a positive assignment_duration_days value.");
161
+ }
162
+ return;
163
+ }
164
+ if (durationDays !== null) {
165
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Only time_limited affiliates may set assignment_duration_days.");
166
+ }
167
+ }
168
+ async listAffiliates(input) {
169
+ const q = input.q?.trim();
170
+ const [affiliates, count] = await this.store.listAndCountAffiliates({
171
+ status: input.status ?? NON_PENDING_AFFILIATE_STATUSES,
172
+ ...(input.customer_id ? { customer_id: input.customer_id } : {}),
173
+ ...(q ? { display_name: { $ilike: `%${q}%` } } : {}),
174
+ }, {
175
+ skip: input.offset,
176
+ take: input.limit,
177
+ order: {
178
+ created_at: "DESC",
179
+ },
180
+ });
181
+ return [await this.attachSlugs(affiliates), count];
182
+ }
183
+ async retrieveAffiliateWithSlugs(id, context) {
184
+ // Read-back after writes in the same transaction: flush so the affiliate
185
+ // and its slugs (possibly just created/updated) are visible, and use a
186
+ // filtered `list` rather than `retrieve` (see AffiliateSlugManager.createSlug
187
+ // for why `retrieve` misses a row created earlier in the same transaction).
188
+ await this.store.flush(context);
189
+ const [affiliate] = await this.store.listAffiliates({ id }, { take: 1 }, context);
190
+ if (!affiliate) {
191
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Affiliate with id "${id}" was not found.`);
192
+ }
193
+ const slugs = await this.slugService.listSlugs(id, context);
194
+ return {
195
+ ...affiliate,
196
+ slugs,
197
+ };
198
+ }
199
+ async attachSlugs(affiliates) {
200
+ if (!affiliates.length) {
201
+ return affiliates;
202
+ }
203
+ const slugs = await this.store.listAffiliateSlugs({ affiliate_id: affiliates.map((affiliate) => affiliate.id) }, { order: { created_at: "ASC" } });
204
+ const slugsByAffiliateId = new Map();
205
+ for (const slug of slugs) {
206
+ const existing = slugsByAffiliateId.get(slug.affiliate_id);
207
+ if (existing) {
208
+ existing.push(slug);
209
+ }
210
+ else {
211
+ slugsByAffiliateId.set(slug.affiliate_id, [slug]);
212
+ }
213
+ }
214
+ return affiliates.map((affiliate) => ({
215
+ ...affiliate,
216
+ slugs: slugsByAffiliateId.get(affiliate.id) ?? [],
217
+ }));
218
+ }
219
+ assertAffiliateIsActive(affiliate, message) {
220
+ if (affiliate.status !== "active") {
221
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, message ?? "Affiliate must be active.");
222
+ }
223
+ }
224
+ validateStatus(status) {
225
+ if (!types_1.affiliateStatuses.includes(status)) {
226
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Invalid affiliate status "${status}".`);
227
+ }
228
+ }
229
+ // Medusa's promotion module rejects a percentage application_method value
230
+ // of 0 (see @medusajs/promotion's validateApplicationMethodAttributes), so
231
+ // an active affiliate with a 0% commission_rate would only fail later,
232
+ // *after* its status had already been persisted, when the route
233
+ // provisions its coupon. Rejecting it here keeps that write from ever
234
+ // happening instead of leaving the affiliate active with no working coupon.
235
+ assertActivatableCommission(status, commissionRate) {
236
+ if (status === "active" && commissionRate <= 0) {
237
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "An active affiliate needs a commission_rate greater than 0.");
238
+ }
239
+ }
240
+ }
241
+ exports.AffiliateManager = AffiliateManager;
242
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWZmaWxpYXRlLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9hZmZpbGlhdGUvc2VydmljZXMvYWZmaWxpYXRlLW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQXVEO0FBR3ZELDBDQU11QjtBQU92QixtQ0FBdUQ7QUFFdkQsNkVBQTZFO0FBQzdFLG9FQUFvRTtBQUNwRSwwRUFBMEU7QUFDMUUseUVBQXlFO0FBQ3pFLE1BQU0sOEJBQThCLEdBQUcseUJBQWlCLENBQUMsTUFBTSxDQUM3RCxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FDakMsQ0FBQTtBQUVELE1BQWEsZ0JBQWdCO0lBQzNCLFlBQ21CLEtBQTJCLEVBQzNCLFdBQWlDO1FBRGpDLFVBQUssR0FBTCxLQUFLLENBQXNCO1FBQzNCLGdCQUFXLEdBQVgsV0FBVyxDQUFzQjtJQUNqRCxDQUFDO0lBRUosS0FBSyxDQUFDLGVBQWUsQ0FDbkIsS0FBMkIsRUFDM0IsT0FBaUI7UUFFakIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxDQUFBO1FBQzlDLElBQUEsa0JBQVUsRUFBQyxLQUFLLENBQUMsZUFBZSxFQUFFLGlCQUFpQixDQUFDLENBQUE7UUFDcEQsSUFBQSxrQkFBVSxFQUFDLEtBQUssQ0FBQyx1QkFBdUIsRUFBRSx5QkFBeUIsQ0FBQyxDQUFBO1FBQ3BFLElBQUksS0FBSyxDQUFDLCtCQUErQixJQUFJLElBQUksRUFBRSxDQUFDO1lBQ2xELElBQUEsa0JBQVUsRUFDUixLQUFLLENBQUMsK0JBQStCLEVBQ3JDLGlDQUFpQyxDQUNsQyxDQUFBO1FBQ0gsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLHdCQUF3QixLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsd0JBQXdCLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDNUYsSUFBQSxrQkFBVSxFQUFDLEtBQUssQ0FBQyx3QkFBd0IsRUFBRSwwQkFBMEIsQ0FBQyxDQUFBO1FBQ3hFLENBQUM7UUFFRCxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1lBQ25DLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FDakQsS0FBSyxDQUFDLHdCQUF3QixFQUM5QixPQUFPLENBQ1IsQ0FBQTtZQUNELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxRQUFRLEVBQUUscUNBQXFDLENBQUMsQ0FBQTtRQUMvRSxDQUFDO1FBRUQsNEVBQTRFO1FBQzVFLDRFQUE0RTtRQUM1RSxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFBO1FBQ2pFLENBQUM7UUFFRCxNQUFNLHNCQUFzQixHQUFHLEtBQUssQ0FBQyx3QkFBd0IsSUFBSSxVQUFVLENBQUE7UUFDM0UsTUFBTSxzQkFBc0IsR0FBRyxLQUFLLENBQUMsd0JBQXdCLElBQUksSUFBSSxDQUFBO1FBQ3JFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxzQkFBc0IsRUFBRSxzQkFBc0IsQ0FBQyxDQUFBO1FBRTNFLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLElBQUksU0FBUyxDQUFBO1FBQ3hDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFBO1FBQy9ELE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUE7UUFDdEIsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUNqRDtZQUNFLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRTtZQUN2QyxXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVcsSUFBSSxJQUFJO1lBQ3RDLE1BQU07WUFDTixlQUFlLEVBQUUsS0FBSyxDQUFDLGVBQWU7WUFDdEMsdUJBQXVCLEVBQUUsS0FBSyxDQUFDLHVCQUF1QjtZQUN0RCx3QkFBd0IsRUFBRSxzQkFBc0I7WUFDaEQsd0JBQXdCLEVBQUUsc0JBQXNCO1lBQ2hELCtCQUErQixFQUM3QixLQUFLLENBQUMsK0JBQStCLElBQUksSUFBSTtZQUMvQyxzQkFBc0IsRUFBRSxJQUFJO1lBQzVCLHdCQUF3QixFQUFFLEtBQUssQ0FBQyx3QkFBd0IsSUFBSSxJQUFJO1lBQ2hFLHdCQUF3QixFQUFFLEtBQUssQ0FBQyx3QkFBd0IsSUFBSSxJQUFJO1lBQ2hFLGVBQWUsRUFBRSxJQUFJO1lBQ3JCLGNBQWMsRUFBRSxJQUFBLHlCQUFpQixFQUFDLEtBQUssQ0FBQyxjQUFjLENBQUM7WUFDdkQsWUFBWSxFQUFFLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSTtZQUM5QyxjQUFjLEVBQUUsTUFBTSxLQUFLLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJO1lBQ2xELFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUSxJQUFJLElBQUk7U0FDakMsRUFDRCxPQUFPLENBQ1IsQ0FBQTtRQUVELE1BQU0sU0FBUyxHQUNiLEtBQUssQ0FBQyxJQUFJO1lBQ1YsQ0FBQyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFBO1FBQzdFLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQy9CO1lBQ0UsWUFBWSxFQUFFLFNBQVMsQ0FBQyxFQUFFO1lBQzFCLElBQUksRUFBRSxTQUFTO1lBQ2YsTUFBTSxFQUFFLElBQUk7WUFDWixVQUFVLEVBQUUsSUFBSTtTQUNqQixFQUNELE9BQU8sQ0FDUixDQUFBO1FBRUQsT0FBTyxNQUFNLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ3JFLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZSxDQUNuQixLQUEyQixFQUMzQixPQUFpQjtRQUVqQixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUV0RSxNQUFNLHNCQUFzQixHQUMxQixLQUFLLENBQUMsd0JBQXdCLElBQUksUUFBUSxDQUFDLHdCQUF3QixDQUFBO1FBQ3JFLE1BQU0sc0JBQXNCLEdBQzFCLEtBQUssQ0FBQyx3QkFBd0IsS0FBSyxTQUFTO1lBQzFDLENBQUMsQ0FBQyxLQUFLLENBQUMsd0JBQXdCO1lBQ2hDLENBQUMsQ0FBQyxRQUFRLENBQUMsd0JBQXdCLENBQUE7UUFDdkMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLHNCQUFzQixFQUFFLHNCQUFzQixDQUFDLENBQUE7UUFFM0UsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ25DLENBQUM7UUFFRCxJQUFJLEtBQUssQ0FBQyxlQUFlLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDeEMsSUFBQSxrQkFBVSxFQUFDLEtBQUssQ0FBQyxlQUFlLEVBQUUsaUJBQWlCLENBQUMsQ0FBQTtRQUN0RCxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsdUJBQXVCLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDaEQsSUFBQSxrQkFBVSxFQUFDLEtBQUssQ0FBQyx1QkFBdUIsRUFBRSx5QkFBeUIsQ0FBQyxDQUFBO1FBQ3RFLENBQUM7UUFDRCxJQUFJLEtBQUssQ0FBQywrQkFBK0IsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNsRCxJQUFBLGtCQUFVLEVBQ1IsS0FBSyxDQUFDLCtCQUErQixFQUNyQyxpQ0FBaUMsQ0FDbEMsQ0FBQTtRQUNILENBQUM7UUFFRCxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsS0FBSyxTQUFTLElBQUksS0FBSyxDQUFDLHdCQUF3QixLQUFLLElBQUksRUFBRSxDQUFDO1lBQzVGLElBQUEsa0JBQVUsRUFBQyxLQUFLLENBQUMsd0JBQXdCLEVBQUUsMEJBQTBCLENBQUMsQ0FBQTtRQUN4RSxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztZQUNuQyxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsS0FBSyxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ2hELE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLG1DQUFtQyxDQUNwQyxDQUFBO1lBQ0gsQ0FBQztZQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FDakQsS0FBSyxDQUFDLHdCQUF3QixFQUM5QixPQUFPLENBQ1IsQ0FBQTtZQUNELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxRQUFRLEVBQUUscUNBQXFDLENBQUMsQ0FBQTtRQUMvRSxDQUFDO1FBRUQsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLE1BQU0sSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFBO1FBQ2xELE1BQU0sa0JBQWtCLEdBQUcsS0FBSyxDQUFDLGVBQWUsSUFBSSxRQUFRLENBQUMsZUFBZSxDQUFBO1FBQzVFLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxVQUFVLEVBQUUsa0JBQWtCLENBQUMsQ0FBQTtRQUNoRSxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsTUFBTSxLQUFLLFFBQVEsSUFBSSxVQUFVLEtBQUssUUFBUSxDQUFBO1FBQzVFLE1BQU0sY0FBYyxHQUNsQixRQUFRLENBQUMsTUFBTSxLQUFLLFVBQVUsSUFBSSxVQUFVLEtBQUssVUFBVSxDQUFBO1FBRTdELE1BQU0sT0FBTyxHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLGdCQUFnQixDQUNoRDtZQUNFLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTtZQUNaLEdBQUcsQ0FBQyxLQUFLLENBQUMsWUFBWSxLQUFLLFNBQVM7Z0JBQ2xDLENBQUMsQ0FBQyxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUM3QyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ1AsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLEtBQUssU0FBUztnQkFDakMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxXQUFXLElBQUksSUFBSSxFQUFFO2dCQUM1QyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ1AsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUMvRCxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsS0FBSyxTQUFTO2dCQUNyQyxDQUFDLENBQUMsRUFBRSxlQUFlLEVBQUUsS0FBSyxDQUFDLGVBQWUsRUFBRTtnQkFDNUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNQLEdBQUcsQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEtBQUssU0FBUztnQkFDN0MsQ0FBQyxDQUFDLEVBQUUsdUJBQXVCLEVBQUUsS0FBSyxDQUFDLHVCQUF1QixFQUFFO2dCQUM1RCxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ1AsR0FBRyxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsS0FBSyxTQUFTO2dCQUM5QyxDQUFDLENBQUMsRUFBRSx3QkFBd0IsRUFBRSxLQUFLLENBQUMsd0JBQXdCLEVBQUU7Z0JBQzlELENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDUCxHQUFHLENBQUMsS0FBSyxDQUFDLHdCQUF3QixLQUFLLFNBQVM7Z0JBQzlDLENBQUMsQ0FBQyxFQUFFLHdCQUF3QixFQUFFLEtBQUssQ0FBQyx3QkFBd0IsRUFBRTtnQkFDOUQsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNQLEdBQUcsQ0FBQyxLQUFLLENBQUMsK0JBQStCLEtBQUssU0FBUztnQkFDckQsQ0FBQyxDQUFDO29CQUNFLCtCQUErQixFQUM3QixLQUFLLENBQUMsK0JBQStCLElBQUksSUFBSTtpQkFDaEQ7Z0JBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNQLEdBQUcsQ0FBQyxLQUFLLENBQUMsd0JBQXdCLEtBQUssU0FBUztnQkFDOUMsQ0FBQyxDQUFDLEVBQUUsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLHdCQUF3QixJQUFJLElBQUksRUFBRTtnQkFDdEUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNQLEdBQUcsQ0FBQyxLQUFLLENBQUMsd0JBQXdCLEtBQUssU0FBUztnQkFDOUMsQ0FBQyxDQUFDLEVBQUUsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLHdCQUF3QixJQUFJLElBQUksRUFBRTtnQkFDdEUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNQLEdBQUcsQ0FBQyxLQUFLLENBQUMsY0FBYyxLQUFLLFNBQVM7Z0JBQ3BDLENBQUMsQ0FBQyxFQUFFLGNBQWMsRUFBRSxJQUFBLHlCQUFpQixFQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRTtnQkFDN0QsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNQLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDckUsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsRUFBRSxZQUFZLEVBQUUsSUFBSSxJQUFJLEVBQUUsRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUMzRSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxFQUFFLGNBQWMsRUFBRSxJQUFJLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUMxRCxFQUNELE9BQU8sQ0FDUixDQUFpQixDQUFBO1FBRWxCLElBQUksS0FBSyxDQUFDLGVBQWUsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN4QyxJQUFJLEtBQUssQ0FBQyxlQUFlLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQ25DLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHdDQUF3QyxDQUN6QyxDQUFBO1lBQ0gsQ0FBQztZQUVELE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQ25DLEVBQUUsWUFBWSxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxlQUFlLEVBQUUsRUFDMUQsT0FBTyxDQUNSLENBQUE7UUFDSCxDQUFDO1FBRUQsT0FBTyxNQUFNLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ25FLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxDQUNmLFdBQW1CLEVBQ25CLE9BQWlCO1FBRWpCLE9BQU8sTUFBTSxJQUFJLENBQUMsZUFBZSxDQUMvQjtZQUNFLEVBQUUsRUFBRSxXQUFXO1lBQ2YsTUFBTSxFQUFFLFVBQVU7U0FDbkIsRUFDRCxPQUFPLENBQ1IsQ0FBQTtJQUNILENBQUM7SUFFTyxzQkFBc0IsQ0FDNUIsSUFBcUMsRUFDckMsWUFBMkI7UUFFM0IsSUFBSSxJQUFJLEtBQUssY0FBYyxFQUFFLENBQUM7WUFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ2hFLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLDRFQUE0RSxDQUM3RSxDQUFBO1lBQ0gsQ0FBQztZQUNELE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxZQUFZLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDMUIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsZ0VBQWdFLENBQ2pFLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjLENBQUMsS0FNcEI7UUFDQyxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFBO1FBQ3pCLE1BQU0sQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUNqRTtZQUNFLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxJQUFJLDhCQUE4QjtZQUN0RCxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDaEUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxZQUFZLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUNyRCxFQUNEO1lBQ0UsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNO1lBQ2xCLElBQUksRUFBRSxLQUFLLENBQUMsS0FBSztZQUNqQixLQUFLLEVBQUU7Z0JBQ0wsVUFBVSxFQUFFLE1BQU07YUFDbkI7U0FDRixDQUNGLENBQUE7UUFFRCxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ3BELENBQUM7SUFFRCxLQUFLLENBQUMsMEJBQTBCLENBQzlCLEVBQVUsRUFDVixPQUFpQjtRQUVqQix5RUFBeUU7UUFDekUsdUVBQXVFO1FBQ3ZFLDhFQUE4RTtRQUM5RSw0RUFBNEU7UUFDNUUsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUMvQixNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FDakQsRUFBRSxFQUFFLEVBQUUsRUFDTixFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsRUFDWCxPQUFPLENBQ1IsQ0FBQTtRQUVELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQzNCLHNCQUFzQixFQUFFLGtCQUFrQixDQUMzQyxDQUFBO1FBQ0gsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFBO1FBRTNELE9BQU87WUFDTCxHQUFHLFNBQVM7WUFDWixLQUFLO1NBQ04sQ0FBQTtJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxDQUFDLFVBQTBCO1FBQzFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdkIsT0FBTyxVQUFVLENBQUE7UUFDbkIsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FDL0MsRUFBRSxZQUFZLEVBQUUsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQzdELEVBQUUsS0FBSyxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQ2pDLENBQUE7UUFDRCxNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxFQUE4QixDQUFBO1FBRWhFLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7WUFDekIsTUFBTSxRQUFRLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQTtZQUUxRCxJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUNiLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7WUFDckIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtZQUNuRCxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNwQyxHQUFHLFNBQVM7WUFDWixLQUFLLEVBQUUsa0JBQWtCLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFO1NBQ2xELENBQUMsQ0FBQyxDQUFBO0lBQ0wsQ0FBQztJQUVELHVCQUF1QixDQUFDLFNBQXVCLEVBQUUsT0FBZ0I7UUFDL0QsSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ2xDLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLE9BQU8sSUFBSSwyQkFBMkIsQ0FDdkMsQ0FBQTtRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsY0FBYyxDQUFDLE1BQXVCO1FBQ3BDLElBQUksQ0FBQyx5QkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUN4QyxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5Qiw2QkFBNkIsTUFBTSxJQUFJLENBQ3hDLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELDBFQUEwRTtJQUMxRSwyRUFBMkU7SUFDM0UsdUVBQXVFO0lBQ3ZFLGdFQUFnRTtJQUNoRSxzRUFBc0U7SUFDdEUsNEVBQTRFO0lBQ3BFLDJCQUEyQixDQUNqQyxNQUF1QixFQUN2QixjQUFzQjtRQUV0QixJQUFJLE1BQU0sS0FBSyxRQUFRLElBQUksY0FBYyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQy9DLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLDZEQUE2RCxDQUM5RCxDQUFBO1FBQ0gsQ0FBQztJQUNILENBQUM7Q0FDRjtBQXBXRCw0Q0FvV0MifQ==
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AffiliatePartnerPortalService = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const notAllowed = () => new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "This partner portal operation requires an active affiliate.");
6
+ /**
7
+ * Customer-scoped facade for the partner portal. It deliberately returns
8
+ * module DTOs, never Store wire DTOs: HTTP adapters own the final safe mapping.
9
+ */
10
+ class AffiliatePartnerPortalService {
11
+ constructor(store, affiliateManager, slugManager, reportService) {
12
+ this.store = store;
13
+ this.affiliateManager = affiliateManager;
14
+ this.slugManager = slugManager;
15
+ this.reportService = reportService;
16
+ }
17
+ async getPartnerPortalContext(customerId) {
18
+ const [affiliate] = await this.store.listAffiliates({ customer_id: customerId }, { take: 1 });
19
+ // A "rejected" affiliate row is an internal bookkeeping artifact kept by
20
+ // rejectApplication so the record stays reactivatable and visible in the
21
+ // Admin affiliates list; it is not a real inactive affiliate. Prefer the
22
+ // application below so the customer sees "rejected" (or a newer
23
+ // resubmitted application's state) instead of "inactive" - but only when
24
+ // a matching application actually exists. A "rejected" affiliate with no
25
+ // application (e.g. legacy data) still falls back to "inactive" below.
26
+ if (affiliate && affiliate.status !== "rejected") {
27
+ return {
28
+ portal_state: affiliate.status === "active" ? "active" : "inactive",
29
+ affiliate,
30
+ };
31
+ }
32
+ const [application] = await this.store.listAffiliateApplications({ customer_id: customerId }, { take: 1, order: { created_at: "DESC" } });
33
+ if (!application) {
34
+ return affiliate
35
+ ? { portal_state: "inactive", affiliate }
36
+ : { portal_state: "no_application" };
37
+ }
38
+ return {
39
+ portal_state: application.status === "pending" ? "pending" : "rejected",
40
+ application,
41
+ };
42
+ }
43
+ async getEffectiveCustomerDiscount(affiliate) {
44
+ if (affiliate.customer_discount_rate_override != null) {
45
+ return affiliate.customer_discount_rate_override;
46
+ }
47
+ const settings = await this.store.retrieveProgramSettings();
48
+ return settings.default_customer_discount_rate;
49
+ }
50
+ async updatePartnerPortalProfile(input, context) {
51
+ const affiliate = await this.requireActiveAffiliate(input.customer_id, context);
52
+ // Do not spread caller input: the only Store-writable Affiliate field is
53
+ // display_name, and the actor owns the affiliate resolution above.
54
+ return await this.affiliateManager.updateAffiliate({
55
+ id: affiliate.id,
56
+ display_name: input.display_name,
57
+ }, context);
58
+ }
59
+ async listPartnerPortalSlugs(customerId) {
60
+ const affiliate = await this.requireActiveAffiliate(customerId);
61
+ return await this.slugManager.listSlugs(affiliate.id);
62
+ }
63
+ async createPartnerPortalSlug(input, context) {
64
+ const affiliate = await this.requireActiveAffiliate(input.customer_id, context);
65
+ return await this.slugManager.createSlug({
66
+ affiliate_id: affiliate.id,
67
+ slug: input.slug,
68
+ }, context);
69
+ }
70
+ async updatePartnerPortalSlug(input, context) {
71
+ const affiliate = await this.requireActiveAffiliate(input.customer_id, context);
72
+ const [slug] = await this.store.listAffiliateSlugs({ id: input.slug_id, affiliate_id: affiliate.id }, { take: 1 }, context);
73
+ // A filtered lookup intentionally makes missing and foreign IDs identical.
74
+ if (!slug) {
75
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, "Affiliate slug was not found for this affiliate.");
76
+ }
77
+ if (input.active === false && input.is_primary === true) {
78
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "A primary affiliate slug must be active.");
79
+ }
80
+ if (input.is_primary === true) {
81
+ // `setPrimarySlug` contains the active/one-primary invariant and returns
82
+ // its just-written target, avoiding a deferred-transaction reread.
83
+ return await this.slugManager.setPrimarySlug({
84
+ affiliate_id: affiliate.id,
85
+ slug_id: slug.id,
86
+ }, context);
87
+ }
88
+ if (input.active !== undefined) {
89
+ return await this.slugManager.updateSlug({
90
+ id: slug.id,
91
+ affiliate_id: affiliate.id,
92
+ active: input.active,
93
+ }, context);
94
+ }
95
+ return await this.store.retrieveAffiliateSlug(slug.id, context);
96
+ }
97
+ async getPartnerPortalDashboard(input) {
98
+ const affiliate = await this.requireReadableAffiliate(input.customer_id);
99
+ return await this.reportService.getPortalLedgerTotals({
100
+ affiliate_id: affiliate.id,
101
+ from: input.from,
102
+ to: input.to,
103
+ });
104
+ }
105
+ async getPartnerPortalCommissions(input) {
106
+ const affiliate = await this.requireReadableAffiliate(input.customer_id);
107
+ return await this.reportService.getPortalLedgerPage({
108
+ affiliate_id: affiliate.id,
109
+ from: input.from,
110
+ to: input.to,
111
+ limit: input.limit,
112
+ offset: input.offset,
113
+ });
114
+ }
115
+ async requireActiveAffiliate(customerId, context) {
116
+ const affiliate = await this.findAffiliateByCustomer(customerId, context);
117
+ if (!affiliate || affiliate.status !== "active") {
118
+ throw notAllowed();
119
+ }
120
+ return affiliate;
121
+ }
122
+ async requireReadableAffiliate(customerId) {
123
+ const affiliate = await this.findAffiliateByCustomer(customerId);
124
+ // Context normalizes every persisted non-active affiliate to `inactive`.
125
+ // Keep historical reads aligned with that public state, while the active
126
+ // gate above remains the sole path for profile and slug mutations.
127
+ if (!affiliate) {
128
+ throw notAllowed();
129
+ }
130
+ return affiliate;
131
+ }
132
+ async findAffiliateByCustomer(customerId, context) {
133
+ const affiliates = await this.store.listAffiliates({ customer_id: customerId }, { take: 1 }, context);
134
+ return affiliates[0] ?? null;
135
+ }
136
+ }
137
+ exports.AffiliatePartnerPortalService = AffiliatePartnerPortalService;
138
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWZmaWxpYXRlLXBhcnRuZXItcG9ydGFsLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9hZmZpbGlhdGUvc2VydmljZXMvYWZmaWxpYXRlLXBhcnRuZXItcG9ydGFsLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQXVEO0FBbUJ2RCxNQUFNLFVBQVUsR0FBRyxHQUFnQixFQUFFLENBQ25DLElBQUksbUJBQVcsQ0FDYixtQkFBVyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQzdCLDZEQUE2RCxDQUM5RCxDQUFBO0FBRUg7OztHQUdHO0FBQ0gsTUFBYSw2QkFBNkI7SUFDeEMsWUFDbUIsS0FBMkIsRUFDM0IsZ0JBQWtDLEVBQ2xDLFdBQWlDLEVBQ2pDLGFBQXFDO1FBSHJDLFVBQUssR0FBTCxLQUFLLENBQXNCO1FBQzNCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFDbEMsZ0JBQVcsR0FBWCxXQUFXLENBQXNCO1FBQ2pDLGtCQUFhLEdBQWIsYUFBYSxDQUF3QjtJQUNyRCxDQUFDO0lBRUosS0FBSyxDQUFDLHVCQUF1QixDQUFDLFVBQWtCO1FBQzlDLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUNqRCxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsRUFDM0IsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQ1osQ0FBQTtRQUVELHlFQUF5RTtRQUN6RSx5RUFBeUU7UUFDekUseUVBQXlFO1FBQ3pFLGdFQUFnRTtRQUNoRSx5RUFBeUU7UUFDekUseUVBQXlFO1FBQ3pFLHVFQUF1RTtRQUN2RSxJQUFJLFNBQVMsSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQ2pELE9BQU87Z0JBQ0wsWUFBWSxFQUFFLFNBQVMsQ0FBQyxNQUFNLEtBQUssUUFBUSxDQUFDLENBQUMs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