@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.
- package/.medusa/server/src/admin/index.js +3739 -0
- package/.medusa/server/src/admin/index.mjs +3738 -0
- package/.medusa/server/src/api/admin/affiliate-applications/[id]/approve/route.js +28 -0
- package/.medusa/server/src/api/admin/affiliate-applications/[id]/reject/route.js +19 -0
- package/.medusa/server/src/api/admin/affiliate-applications/route.js +23 -0
- package/.medusa/server/src/api/admin/affiliate-distribution-reports/query.js +171 -0
- package/.medusa/server/src/api/admin/affiliate-distribution-reports/route.js +13 -0
- package/.medusa/server/src/api/admin/affiliate-program-settings/route.js +27 -0
- package/.medusa/server/src/api/admin/affiliate-reports/[id]/route.js +45 -0
- package/.medusa/server/src/api/admin/affiliate-reports/route.js +27 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/consignment-reminders/route.js +31 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/consignment-transfers/route.js +41 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/reconcile/route.js +34 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/revoke/route.js +36 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/rotate/route.js +40 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/route.js +56 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/distribution/route.js +45 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/inactive/route.js +20 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/route.js +50 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/slugs/[slug_id]/route.js +19 -0
- package/.medusa/server/src/api/admin/affiliates/[id]/slugs/route.js +26 -0
- package/.medusa/server/src/api/admin/affiliates/route.js +43 -0
- package/.medusa/server/src/api/admin/consignment-report-response.js +36 -0
- package/.medusa/server/src/api/admin/consignment-reports/[id]/approve/route.js +25 -0
- package/.medusa/server/src/api/admin/consignment-reports/[id]/correct/route.js +18 -0
- package/.medusa/server/src/api/admin/consignment-reports/[id]/reject/route.js +15 -0
- package/.medusa/server/src/api/admin/consignment-reports/[id]/route.js +11 -0
- package/.medusa/server/src/api/admin/consignment-reports/route.js +27 -0
- package/.medusa/server/src/api/admin/customers/[id]/affiliate/route.js +50 -0
- package/.medusa/server/src/api/admin/orders/[id]/affiliate-attribution/route.js +30 -0
- package/.medusa/server/src/api/affiliate-coupon-http.js +152 -0
- package/.medusa/server/src/api/affiliate-referral-cookie.js +34 -0
- package/.medusa/server/src/api/affiliate-self-service-http.js +37 -0
- package/.medusa/server/src/api/middlewares.js +786 -0
- package/.medusa/server/src/api/store/affiliate-referrals/apply-coupon/route.js +47 -0
- package/.medusa/server/src/api/store/affiliate-referrals/capture/route.js +76 -0
- package/.medusa/server/src/api/store/affiliate-referrals/carts/[cart_id]/route.js +20 -0
- package/.medusa/server/src/api/store/affiliates/consignment-inventory/route.js +53 -0
- package/.medusa/server/src/api/store/affiliates/consignment-report-response.js +31 -0
- package/.medusa/server/src/api/store/affiliates/consignment-reports/[id]/submit/route.js +40 -0
- package/.medusa/server/src/api/store/affiliates/consignment-reports/route.js +43 -0
- package/.medusa/server/src/api/store/affiliates/coupon-labels/route.js +14 -0
- package/.medusa/server/src/api/store/affiliates/me/commissions/route.js +35 -0
- package/.medusa/server/src/api/store/affiliates/me/coupon-codes/[coupon_id]/revoke/route.js +36 -0
- package/.medusa/server/src/api/store/affiliates/me/coupon-codes/[coupon_id]/rotate/route.js +40 -0
- package/.medusa/server/src/api/store/affiliates/me/coupon-codes/route.js +55 -0
- package/.medusa/server/src/api/store/affiliates/me/dashboard/route.js +15 -0
- package/.medusa/server/src/api/store/affiliates/me/route.js +85 -0
- package/.medusa/server/src/api/store/affiliates/me/slugs/[slug_id]/route.js +29 -0
- package/.medusa/server/src/api/store/affiliates/me/slugs/route.js +34 -0
- package/.medusa/server/src/api/store/affiliates/own-order-discount/route.js +22 -0
- package/.medusa/server/src/api/store/affiliates/own-order-promotion/route.js +30 -0
- package/.medusa/server/src/api/store/affiliates/register/route.js +27 -0
- package/.medusa/server/src/api/store/affiliates/resolve-referral/route.js +34 -0
- package/.medusa/server/src/api/validators.js +52 -0
- package/.medusa/server/src/api/wire-response.js +10 -0
- package/.medusa/server/src/integration/email-events.js +51 -0
- package/.medusa/server/src/integrations/inventory-transfer/batch-management-transfer-adapter.js +36 -0
- package/.medusa/server/src/integrations/inventory-transfer/native-inventory-transfer-adapter.js +30 -0
- package/.medusa/server/src/integrations/inventory-transfer/resolve-inventory-transfer-adapter.js +46 -0
- package/.medusa/server/src/integrations/inventory-transfer/types.js +3 -0
- package/.medusa/server/src/jobs/affiliate-attribution-expiry.js +20 -0
- package/.medusa/server/src/jobs/affiliate-consignment-report-reminders.js +15 -0
- package/.medusa/server/src/jobs/affiliate-promotion-freshness.js +24 -0
- package/.medusa/server/src/lib/query-string.js +15 -0
- package/.medusa/server/src/modules/affiliate/domain/affiliate-attribution-policy.js +81 -0
- package/.medusa/server/src/modules/affiliate/domain/affiliate-coupon-policy.js +61 -0
- package/.medusa/server/src/modules/affiliate/domain/commission-policy.js +33 -0
- package/.medusa/server/src/modules/affiliate/domain/consignment-reminder-rules.js +74 -0
- package/.medusa/server/src/modules/affiliate/domain/email-normalization.js +20 -0
- package/.medusa/server/src/modules/affiliate/domain/own-order-coupon-code.js +37 -0
- package/.medusa/server/src/modules/affiliate/domain/plugin-options.js +40 -0
- package/.medusa/server/src/modules/affiliate/index.js +13 -0
- package/.medusa/server/src/modules/affiliate/migrations/Migration20260827085154.js +423 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-application.js +38 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-cart-referral.js +65 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-code-redemption.js +41 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-coupon.js +55 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-distribution-settings.js +22 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-order-attribution.js +49 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-program-settings.js +28 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-referral-session.js +34 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate-slug.js +27 -0
- package/.medusa/server/src/modules/affiliate/models/affiliate.js +49 -0
- package/.medusa/server/src/modules/affiliate/models/commission-entry.js +62 -0
- package/.medusa/server/src/modules/affiliate/models/consignment-report-line.js +21 -0
- package/.medusa/server/src/modules/affiliate/models/consignment-report.js +31 -0
- package/.medusa/server/src/modules/affiliate/models/consignment-transfer-line.js +16 -0
- package/.medusa/server/src/modules/affiliate/models/consignment-transfer.js +20 -0
- package/.medusa/server/src/modules/affiliate/models/customer-affiliate-assignment.js +58 -0
- package/.medusa/server/src/modules/affiliate/service.js +2321 -0
- package/.medusa/server/src/modules/affiliate/services/affiliate-application-manager.js +171 -0
- package/.medusa/server/src/modules/affiliate/services/affiliate-coupon-manager.js +441 -0
- package/.medusa/server/src/modules/affiliate/services/affiliate-discount.service.js +55 -0
- package/.medusa/server/src/modules/affiliate/services/affiliate-manager.js +242 -0
- package/.medusa/server/src/modules/affiliate/services/affiliate-partner-portal.service.js +138 -0
- package/.medusa/server/src/modules/affiliate/services/affiliate-report.service.js +436 -0
- package/.medusa/server/src/modules/affiliate/services/affiliate-slug-manager.js +163 -0
- package/.medusa/server/src/modules/affiliate/services/commission-ledger.service.js +729 -0
- package/.medusa/server/src/modules/affiliate/services/customer-affiliate-assignment-manager.js +350 -0
- package/.medusa/server/src/modules/affiliate/services/order-attribution-manager.js +1051 -0
- package/.medusa/server/src/modules/affiliate/services/referral-lifecycle-manager.js +1420 -0
- package/.medusa/server/src/modules/affiliate/services/utils.js +49 -0
- package/.medusa/server/src/modules/affiliate/types/internal.js +3 -0
- package/.medusa/server/src/paths/affiliate.js +7 -0
- package/.medusa/server/src/paths/index.js +18 -0
- package/.medusa/server/src/schemas/index.js +18 -0
- package/.medusa/server/src/schemas/store.js +24 -0
- package/.medusa/server/src/subscribers/affiliate-cart-updated.js +92 -0
- package/.medusa/server/src/subscribers/affiliate-order-canceled.js +70 -0
- package/.medusa/server/src/subscribers/affiliate-order-placed.js +63 -0
- package/.medusa/server/src/subscribers/affiliate-order-return-received.js +67 -0
- package/.medusa/server/src/subscribers/affiliate-product-eligibility-updated.js +87 -0
- package/.medusa/server/src/types/admin-api.js +3 -0
- package/.medusa/server/src/types/enums.js +53 -0
- package/.medusa/server/src/types/index.js +32 -0
- package/.medusa/server/src/types/public.js +3 -0
- package/.medusa/server/src/types/store-api.js +3 -0
- package/.medusa/server/src/utils/affiliate-cart-operation-lock.js +316 -0
- package/.medusa/server/src/utils/affiliate-promotion-mutation-authorization.js +49 -0
- package/.medusa/server/src/utils/cart-promotions.js +9 -0
- package/.medusa/server/src/utils/money.js +79 -0
- package/.medusa/server/src/utils/promotion-code-availability.js +34 -0
- package/.medusa/server/src/utils/registered-email-checkout.js +101 -0
- package/.medusa/server/src/utils/resolve-services.js +7 -0
- package/.medusa/server/src/utils/settle-cart-promotions.js +44 -0
- package/.medusa/server/src/workflows/affiliate/affiliate-coupon-cart.js +215 -0
- package/.medusa/server/src/workflows/affiliate/affiliate-coupon-command-authorization.js +20 -0
- package/.medusa/server/src/workflows/affiliate/apply-affiliate-coupon.js +174 -0
- package/.medusa/server/src/workflows/affiliate/apply-own-order-promotion.js +89 -0
- package/.medusa/server/src/workflows/affiliate/approve-consignment-report.js +186 -0
- package/.medusa/server/src/workflows/affiliate/correct-approved-consignment-report.js +263 -0
- package/.medusa/server/src/workflows/affiliate/create-affiliate-coupon.js +35 -0
- package/.medusa/server/src/workflows/affiliate/create-commission-correction-for-cancellation.js +21 -0
- package/.medusa/server/src/workflows/affiliate/create-commission-correction-for-refund.js +24 -0
- package/.medusa/server/src/workflows/affiliate/create-commission-for-order.js +17 -0
- package/.medusa/server/src/workflows/affiliate/deactivate-affiliate.js +89 -0
- package/.medusa/server/src/workflows/affiliate/enable-distribution.js +120 -0
- package/.medusa/server/src/workflows/affiliate/enrich-affiliate-report.js +75 -0
- package/.medusa/server/src/workflows/affiliate/ensure-affiliate-coupon-promotion.js +410 -0
- package/.medusa/server/src/workflows/affiliate/ensure-affiliate-own-order-promotion.js +240 -0
- package/.medusa/server/src/workflows/affiliate/ensure-default-affiliate-coupon.js +32 -0
- package/.medusa/server/src/workflows/affiliate/expire-affiliate-attribution-state.js +131 -0
- package/.medusa/server/src/workflows/affiliate/finalize-affiliate-order-attribution.js +82 -0
- package/.medusa/server/src/workflows/affiliate/payment-authorization.js +33 -0
- package/.medusa/server/src/workflows/affiliate/promotion-eligibility.js +179 -0
- package/.medusa/server/src/workflows/affiliate/reconcile-affiliate-cart-referral.js +219 -0
- package/.medusa/server/src/workflows/affiliate/reconcile-affiliate-coupon.js +388 -0
- package/.medusa/server/src/workflows/affiliate/refresh-affiliate-promotions.js +114 -0
- package/.medusa/server/src/workflows/affiliate/resolve-coupon-labels.js +40 -0
- package/.medusa/server/src/workflows/affiliate/revoke-affiliate-coupon.js +29 -0
- package/.medusa/server/src/workflows/affiliate/rotate-affiliate-coupon.js +36 -0
- package/.medusa/server/src/workflows/affiliate/run-consignment-report-reminders.js +58 -0
- package/.medusa/server/src/workflows/affiliate/submit-consignment-report.js +279 -0
- package/.medusa/server/src/workflows/affiliate/transfer-batch-aware-inventory.js +172 -0
- package/.medusa/server/src/workflows/affiliate/transfer-consignment-stock.js +106 -0
- package/.medusa/server/src/workflows/affiliate/update-affiliate-coupon-discounts.js +129 -0
- package/.medusa/server/src/workflows/affiliate/utils.js +118 -0
- package/.medusa/server/src/workflows/hooks/complete-cart-affiliate-attribution.js +57 -0
- package/.medusa/server/src/workflows/hooks/complete-cart-order-created-composition.js +111 -0
- package/.medusa/server/src/workflows/hooks/complete-cart-own-order-discount.js +75 -0
- package/.medusa/server/src/workflows/hooks/enforce-unique-promotion-codes.js +33 -0
- package/.medusa/server/src/workflows/hooks/validate-affiliate-customer-code.js +239 -0
- package/.medusa/server/src/workflows/hooks/validate-complete-cart-affiliate-referral.js +137 -0
- package/LICENSE +21 -0
- package/README.md +799 -0
- package/dist/integration/email-events.d.ts +20 -0
- package/dist/integration/email-events.js +50 -0
- 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWZmaWxpYXRlLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9hZmZpbGlhdGUvc2VydmljZXMvYWZmaWxpYXRlLW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQXVEO0FBR3ZELDBDQU11QjtBQU92QixtQ0FBdUQ7QUFFdkQsNkVBQTZFO0FBQzdFLG9FQUFvRTtBQUNwRSwwRUFBMEU7QUFDMUUseUVBQXlFO0FBQ3pFLE1BQU0sOEJBQThCLEdBQUcseUJBQWlCLENBQUMsTUFBTSxDQUM3RCxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FDakMsQ0FBQTtBQUVELE1BQWEsZ0JBQWdCO0lBQzNCLFlBQ21CLEtBQTJCLEVBQzNCLFdBQWlDO1FBRGpDLFVBQUssR0FBTCxLQUFLLENBQXNCO1FBQzNCLGdCQUFXLEdBQVgsV0FBVyxDQUFzQjtJQUNqRCxDQUFDO0lBRUosS0FBSyxDQUFDLGVBQWUsQ0FDbkIsS0FBMkIsRUFDM0IsT0FBaUI7UUFFakIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxDQUFBO1FBQzlDLElBQUEsa0JBQVUsRUFBQyxLQUFLLENBQUMsZUFBZSxFQUFFLGlCQUFpQixDQUFDLENBQUE7UUFDcEQsSUFBQSxrQkFBVSxFQUFDLEtBQUssQ0FBQyx1QkFBdUIsRUFBRSx5QkFBeUIsQ0FBQyxDQUFBO1FBQ3BFLElBQUksS0FBSyxDQUFDLCtCQUErQixJQUFJLElBQUksRUFBRSxDQUFDO1lBQ2xELElBQUEsa0JBQVUsRUFDUixLQUFLLENBQUMsK0JBQStCLEVBQ3JDLGlDQUFpQyxDQUNsQyxDQUFBO1FBQ0gsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLHdCQUF3QixLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsd0JBQXdCLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDNUYs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
|
|
@@ -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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
|