@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,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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb25jaWxlLWFmZmlsaWF0ZS1jb3Vwb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2FmZmlsaWF0ZS9yZWNvbmNpbGUtYWZmaWxpYXRlLWNvdXBvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSxxRUFLMEM7QUFDMUMscURBSWtDO0FBQ2xDLDREQUEwRTtBQUcxRSw2RkFJa0Q7QUFDbEQsbUVBQXNFO0FBQ3RFLGlFQUFnRTtBQUNoRSwrRUFBeUU7QUFDekUsMkZBSTRDO0FBQzVDLG1FQUdnQztBQXVCaEMsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLEtBQWMsRUFBVSxFQUFFLENBQ3JELHlDQUNFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGVBQzNDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFBO0FBRXBCLE1BQU0sWUFBWSxHQUFHLEtBQUssRUFDeEIsU0FBMEIsRUFDMUIsTUFBYyxFQUNZLEVBQUU7SUFDNUIsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNoRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUNoQztRQUNFLE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxlQUFlLEVBQUUsaUJBQWlCLENBQUM7UUFDbEUsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRTtLQUN4QixFQUNELEVBQUUsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQzdCLENBQUE7SUFDRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUF5QixDQUFBO0lBQzVDLE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7QUFDakQsQ0FBQyxDQUFBO0FBRU0sTUFBTSwwQkFBMEIsR0FBRyxLQUFLLEVBQzdDLFNBQTBCLEVBQzFCLFdBQTBCLEVBQ1AsRUFBRTtJQUNyQixJQUFJLENBQUMsV0FBVztRQUFFLE9BQU8sRUFBRSxDQUFBO0lBRTNCLE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQ25DLGlDQUF5QixDQUFDLFlBQVksQ0FDaEIsQ0FBQTtJQUN4QixNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFBO0lBQ2pDLE1BQU0sUUFBUSxHQUFHLEdBQUcsQ0FBQTtJQUNwQixJQUFJLElBQUksR0FBRyxDQUFDLENBQUE7SUFFWixPQUFPLElBQUksRUFBRSxDQUFDO1FBQ1osTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sV0FBVyxDQUFDLEtBQUssQ0FDdEM7WUFDRSxNQUFNLEVBQUUsZ0JBQWdCO1lBQ3hCLE1BQU0sRUFBRSxDQUFDLFNBQVMsRUFBRSxtQkFBbUIsQ0FBQztZQUN4QyxPQUFPLEVBQUUsRUFBRSxZQUFZLEVBQUUsQ0FBQyxXQUFXLENBQUMsRUFBRTtZQUN4QyxVQUFVLEVBQUU7Z0JBQ1YsSUFBSTtnQkFDSixJQUFJLEVBQUUsUUFBUTtnQkFDZCxLQUFLLEVBQUUsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFO2FBQzFCO1NBQ0YsRUFDRCxFQUFFLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUM3QixDQUFBO1FBQ0QsTUFBTSxLQUFLLEdBQUcsSUFBaUMsQ0FBQTtRQUMvQyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFlBQVk7Z0JBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDekQsQ0FBQztRQUNELElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxRQUFRO1lBQUUsTUFBSztRQUNsQyxJQUFJLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQTtJQUN0QixDQUFDO0lBRUQsT0FBTyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUE7QUFDNUIsQ0FBQyxDQUFBO0FBcENZLFFBQUEsMEJBQTBCLDhCQW9DdEM7QUFFRCxNQUFNLDZCQUE2QixHQUFHLENBQUMsS0FBYyxFQUFXLEVBQUUsQ0FDaEUsS0FBSyxZQUFZLG1CQUFXO0lBQzVCLEtBQUssQ0FBQyxJQUFJLEtBQUssbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWTtJQUM3QyxLQUFLLENBQUMsT0FBTyxLQUFLLHVCQUF1QixDQUFBO0FBRTNDLE1BQU0sbUNBQW1DLEdBQUcsS0FBSyxFQUMvQyxTQUEwQixFQUMxQixNQUEwQixFQUMxQixNQUFjLEVBQ0MsRUFBRTtJQUNqQixJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVk7UUFBRSxPQUFNO0lBRWhDLE1BQU0sSUFBSSxHQUFHLE1BQU0sWUFBWSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUNsRCxJQUFJLENBQUMsSUFBSTtRQUFFLE9BQU07SUFDakIsTUFBTSxTQUFTLEdBQUcsSUFBQSxvQ0FBa0IsRUFBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUN4RCxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxNQUFNLENBQUMsWUFBWSxDQUN2QyxDQUFBO0lBQ0QsSUFBSSxDQUFDLFNBQVM7UUFBRSxPQUFNO0lBRXRCLE1BQU0sSUFBQSx5Q0FBNEIsRUFBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDaEQsS0FBSyxFQUFFO1lBQ0wsT0FBTyxFQUFFLE1BQU07WUFDZixXQUFXLEVBQUUsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDNUMsTUFBTSxFQUFFLHdCQUFnQixDQUFDLE1BQU07WUFDL0IsZ0NBQWdDLEVBQUUsSUFBSTtTQUN2QztLQUNGLENBQUMsQ0FBQTtJQUNGLDZEQUE2RDtJQUM3RCwrREFBK0Q7SUFDL0QseURBQXlEO0lBQ3pELE1BQU0sSUFBQSw2Q0FBb0IsRUFBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDN0MsTUFBTSxRQUFRLEdBQUcsTUFBTSxZQUFZLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBQ3RELElBQ0UsSUFBQSxvQ0FBa0IsRUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUMzQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxNQUFNLENBQUMsWUFBWSxDQUN2QyxFQUNELENBQUM7UUFDRCxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQ2xDLFNBQVMsTUFBTSxpREFBaUQsTUFBTSxDQUFDLFlBQVksSUFBSSxDQUN4RixDQUFBO0lBQ0gsQ0FBQztBQUNILENBQUMsQ0FBQTtBQUVELE1BQU0scUJBQXFCLEdBQUcsS0FBSyxFQUNqQyxTQUEwQixFQUMxQixNQUEwQixFQUMxQixLQUFjLEVBQ0UsRUFBRTtJQUNsQixNQUFNLGdCQUFnQixHQUFHLElBQUEsMENBQXVCLEVBQUMsU0FBUyxDQUFDLENBQUE7SUFDM0QsTUFBTSxRQUFRLEdBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNuQyxJQUFJLENBQUM7UUFDSCxNQUFNLElBQUEsMkRBQTJCLEVBQy9CLFNBQVMsRUFDVCxDQUFDLElBQUEsb0RBQW9CLEVBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLEVBQzNDLEtBQUssSUFBSSxFQUFFO1lBQ1QsTUFBTSxPQUFPLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyw2QkFBNkIsQ0FDbEUsTUFBTSxDQUFDLEVBQUUsRUFDVCxNQUFNLENBQUMsWUFBWSxDQUNwQixDQUFBO1lBQ0QsTUFBTSxnQkFBZ0IsQ0FBQyxtQ0FBbUMsQ0FBQztnQkFDekQsU0FBUyxFQUFFLE9BQU8sQ0FBQyxFQUFFO2dCQUNyQixHQUFHLENBQUMsT0FBTyxDQUFDLFlBQVk7b0JBQ3RCLENBQUMsQ0FBQyxFQUFFLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWSxFQUFFO29CQUN4QyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNQLG1CQUFtQixFQUFFLFFBQVE7Z0JBQzdCLHFCQUFxQixFQUFFLG1CQUFtQixDQUFDLEtBQUssQ0FBQzthQUNsRCxDQUFDLENBQUE7UUFDSixDQUFDLENBQ0YsQ0FBQTtJQUNILENBQUM7SUFBQyxPQUFPLFVBQVUsRUFBRSxDQUFDO1FBQ3BCLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDM0IsQ0FBQztJQUVELElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsTUFBTSxLQUFLLENBQUE7SUFDdEMsTUFBTSxJQUFJLGNBQWMsQ0FDdEIsUUFBUSxFQUNSLHlEQUF5RCxDQUMxRCxDQUFBO0FBQ0gsQ0FBQyxDQUFBO0FBRUQsTUFBTSw2QkFBNkIsR0FBRyxLQUFLLEVBQ3pDLFNBQTBCLEVBQzFCLFFBQWdCLEVBQytCLEVBQUU7SUFDakQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFBLDBDQUF1QixFQUFDLFNBQVMsQ0FBQyxDQUFBO0lBQzNELE1BQU0sTUFBTSxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsNkJBQTZCLENBQUMsUUFBUSxDQUFDLENBQUE7SUFFN0UsSUFBSSxDQUFDO1FBQ0gsTUFBTSxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDL0MsZ0JBQWdCLENBQUMsdUNBQXVDLENBQUM7Z0JBQ3ZELG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxFQUFFO2dCQUM5QixNQUFNLEVBQUUsZ0JBQWdCO2FBQ3pCLENBQUM7WUFDRixJQUFBLGtDQUEwQixFQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsWUFBWSxDQUFDO1NBQzNELENBQUMsQ0FBQTtRQUNGLE1BQU0sT0FBTyxHQUFHO1lBQ2QsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLGFBQWEsRUFBRSxHQUFHLGFBQWEsQ0FBQyxDQUFDO1NBQ3ZELENBQUMsSUFBSSxFQUFFLENBQUE7UUFDUixNQUFNLFFBQVEsR0FBYyxFQUFFLENBQUE7UUFDOUIsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxJQUFBLDhEQUE4QixFQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxJQUFJLEVBQUU7b0JBQ2pFLE1BQU0sbUNBQW1DLENBQUMsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQTtnQkFDdEUsQ0FBQyxDQUFDLENBQUE7WUFDSixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3RCLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDcEIsTUFBTSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUM7Z0JBQ3pCLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2dCQUNiLENBQUMsQ0FBQyxJQUFJLGNBQWMsQ0FDaEIsUUFBUSxFQUNSLHVEQUF1RCxDQUN4RCxDQUFBO1FBQ1AsQ0FBQztRQUVELE9BQU8sTUFBTSxJQUFBLHFFQUFpQyxFQUFDLFNBQVMsRUFBRTtZQUN4RCxTQUFTLEVBQUUsTUFBTSxDQUFDLEVBQUU7U0FDckIsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixPQUFPLE1BQU0scUJBQXFCLENBQUMsU0FBUyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQTtJQUM5RCxDQUFDO0FBQ0gsQ0FBQyxDQUFBO0FBRU0sTUFBTSwrQkFBK0IsR0FBRyxLQUFLLEVBQ2xELFNBQTBCLEVBQzFCLE1BQTBCLEVBQ1gsRUFBRTtJQUNqQixNQUFNLGdCQUFnQixHQUFHLElBQUEsMENBQXVCLEVBQUMsU0FBUyxDQUFDLENBQUE7SUFDM0QsTUFBTSxTQUFTLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyx1QkFBdUIsQ0FDOUQsTUFBTSxDQUFDLFlBQVksQ0FDcEIsQ0FBQTtJQUNELE1BQU0sQ0FBQyxZQUFZLEVBQUUsYUFBYSxFQUFFLFFBQVEsQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUNoRSxnQkFBZ0IsQ0FBQyxpQ0FBaUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzdELElBQUEsa0NBQTBCLEVBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUM7UUFDMUQsZ0JBQWdCLENBQUMsdUJBQXVCLEVBQUU7S0FDM0MsQ0FBQyxDQUFBO0lBQ0YsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUE7SUFDNUMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxZQUFZLEVBQUUsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUE7SUFDeEUsTUFBTSxRQUFRLEdBQWMsRUFBRSxDQUFBO0lBRTlCLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFBLDhEQUE4QixFQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ2pFLE1BQU0sSUFBSSxHQUFHLE1BQU0sWUFBWSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQTtnQkFDbEQsSUFBSSxDQUFDLElBQUk7b0JBQUUsT0FBTTtnQkFDakIsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsWUFBWTtvQkFDMUMsQ0FBQyxDQUFDLE1BQU0sZ0JBQWdCLENBQUMsMEJBQTBCLENBQy9DO3dCQUNFLE9BQU8sRUFBRSxNQUFNO3dCQUNmLE1BQU0sRUFBRSxRQUFRO3dCQUNoQiwyQkFBMkIsRUFBRSxNQUFNLENBQUMsRUFBRTt3QkFDdEMsb0JBQW9CLEVBQUUsTUFBTSxDQUFDLFlBQVk7cUJBQzFDLEVBQ0QsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQ3hEO29CQUNILENBQUMsQ0FBQyxFQUFFLENBQUE7Z0JBQ04sTUFBTSxnQkFBZ0IsR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLENBQzVDLENBQUMsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUNoRSxDQUFBO2dCQUVELG1FQUFtRTtnQkFDbkUsMkRBQTJEO2dCQUMzRCxJQUFJLGNBQWMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0I7b0JBQUUsT0FBTTtnQkFFM0QsSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLFFBQVEsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO29CQUN0RCxNQUFNLElBQUEsd0RBQWdDLEVBQUM7d0JBQ3JDLFNBQVM7d0JBQ1QsaUJBQWlCLEVBQUUsZ0JBQWdCO3dCQUNuQyxPQUFPLEVBQUUsTUFBTTt3QkFDZixhQUFhLEVBQUUsTUFBTTt3QkFDckIsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLGtCQUFrQjt3QkFDL0MsZUFBZSxFQUFFLElBQUEsb0NBQWtCLEVBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQzt3QkFDcEQsYUFBYSxFQUFFLElBQUk7cUJBQ3BCLENBQUMsQ0FBQTtvQkFDRixPQUFNO2dCQUNSLENBQUM7Z0JBRUQsTUFBTSxnQkFBZ0IsQ0FBQyxzQ0FBc0MsQ0FBQztvQkFDNUQsT0FBTyxFQUFFLE1BQU07b0JBQ2YsbUJBQW1CLEVBQUUsTUFBTSxDQUFDLEVBQUU7b0JBQzlCLE1BQU0sRUFDSixTQUFTLENBQUMsTUFBTSxLQUFLLFFBQVE7d0JBQzNCLENBQUMsQ0FBQyx3QkFBd0I7d0JBQzFCLENBQUMsQ0FBQyxvQkFBb0I7aUJBQzNCLENBQUMsQ0FBQTtnQkFDRixNQUFNLG1DQUFtQyxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7WUFDdEUsQ0FBQyxDQUFDLENBQUE7UUFDSixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sZUFBZSxHQUFjLDZCQUE2QixDQUFDLEtBQUssQ0FBQztnQkFDckUsQ0FBQyxDQUFDLEVBQUU7Z0JBQ0osQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDWCxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxJQUFBLDhEQUE4QixFQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxJQUFJLEVBQUU7b0JBQ2pFLE1BQU0sZ0JBQWdCLENBQUMsc0NBQXNDLENBQUM7d0JBQzVELE9BQU8sRUFBRSxNQUFNO3dCQUNmLG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxFQUFFO3dCQUM5QixNQUFNLEVBQUUsOEJBQThCO3FCQUN2QyxDQUFDLENBQUE7b0JBQ0YsTUFBTSxtQ0FBbUMsQ0FBQyxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFBO2dCQUN0RSxDQUFDLENBQUMsQ0FBQTtZQUNKLENBQUM7WUFBQyxPQUFPLFlBQVksRUFBRSxDQUFDO2dCQUN0QixlQUFlLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO1lBQ3BDLENBQUM7WUFDRCxJQUFJLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDM0IsUUFBUSxDQUFDLElBQUksQ0FDWCxlQUFlLENBQUMsTUFBTSxLQUFLLENBQUM7b0JBQzFCLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO29CQUNwQixDQUFDLENBQUMsSUFBSSxjQUFjLENBQ2hCLGVBQWUsRUFDZiw2Q0FBNkMsTUFBTSxHQUFHLENBQ3ZELENBQ04sQ0FBQTtZQUNILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3BCLE1BQU0sS0FBSyxHQUNULFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUNuQixDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztZQUNiLENBQUMsQ0FBQyxJQUFJLGNBQWMsQ0FDaEIsUUFBUSxFQUNSLDhEQUE4RCxDQUMvRCxDQUFBO1FBQ1AsTUFBTSxxQkFBcUIsQ0FBQyxTQUFTLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ3ZELENBQUM7QUFDSCxDQUFDLENBQUE7QUF2R1ksUUFBQSwrQkFBK0IsbUNBdUczQztBQUVNLE1BQU0sK0JBQStCLEdBQUcsS0FBSyxFQUNsRCxTQUEwQixFQUMxQixRQUFnQixFQUNoQixNQUFjLEVBQ0MsRUFBRTtJQUNqQixNQUFNLGdCQUFnQixHQUFHLElBQUEsMENBQXVCLEVBQUMsU0FBUyxDQUFDLENBQUE7SUFDM0QsSUFBSSxNQUFNLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyw2QkFBNkIsQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUUzRSxJQUFJLENBQUM7UUFDSCxJQUFJLE1BQU0sQ0FBQyxnQkFBZ0IsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMxQyxNQUFNLGdCQUFnQixDQUFDLHNDQUFzQyxDQUFDO2dCQUM1RCxPQUFPLEVBQUUsTUFBTTtnQkFDZixtQkFBbUIsRUFBRSxNQUFNLENBQUMsRUFBRTtnQkFDOUIsTUFBTSxFQUFFLGdCQUFnQjthQUN6QixDQUFDLENBQUE7WUFDRixNQUFNLG1DQUFtQyxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7WUFDcEUsT0FBTTtRQUNSLENBQUM7UUFFRCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEscUVBQWlDLEVBQUMsU0FBUyxFQUFFO1lBQ2hFLFNBQVMsRUFBRSxNQUFNLENBQUMsRUFBRTtTQUNyQixDQUFDLENBQUE7UUFDRixNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQTtRQUN0QixJQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUMxQixNQUFNLGdCQUFnQixDQUFDLHNDQUFzQyxDQUFDO2dCQUM1RCxPQUFPLEVBQUUsTUFBTTtnQkFDZixtQkFBbUIsRUFBRSxNQUFNLENBQUMsY0FBYyxDQUFDLEVBQUU7Z0JBQzdDLE1BQU0sRUFBRSxnQkFBZ0I7YUFDekIsQ0FBQyxDQUFBO1lBQ0YsTUFBTSxtQ0FBbUMsQ0FDdkMsU0FBUyxFQUNULE1BQU0sQ0FBQyxjQUFjLEVBQ3JCLE1BQU0sQ0FDUCxDQUFBO1FBQ0gsQ0FBQztRQUVELE1BQU0sU0FBUyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsdUJBQXVCLENBQzlELE1BQU0sQ0FBQyxZQUFZLENBQ3BCLENBQUE7UUFDRCxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FDMUIsTUFBTSxnQkFBZ0IsQ0FBQyxpQ0FBaUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQ3BFLENBQUE7UUFDRCxNQUFNLElBQUksR0FBRyxNQUFNLFlBQVksQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUE7UUFDbEQsSUFBSSxDQUFDLElBQUk7WUFBRSxPQUFNO1FBQ2pCLElBQUksU0FBUyxDQUFDLE1BQU0sS0FBSyxRQUFRLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDL0QsTUFBTSxnQkFBZ0IsQ0FBQyxzQ0FBc0MsQ0FBQztnQkFDNUQsT0FBTyxFQUFFLE1BQU07Z0JBQ2YsbUJBQW1CLEVBQUUsTUFBTSxDQUFDLEVBQUU7Z0JBQzlCLE1BQU0sRUFDSixTQUFTLENBQUMsTUFBTSxLQUFLLFFBQVE7b0JBQzNCLENBQUMsQ0FBQyx3QkFBd0I7b0JBQzFCLENBQUMsQ0FBQyxvQkFBb0I7YUFDM0IsQ0FBQyxDQUFBO1lBQ0YsTUFBTSxtQ0FBbUMsQ0FBQyxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBQ3BFLE9BQU07UUFDUixDQUFDO1FBRUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyx1QkFBdUIsRUFBRSxDQUFBO1FBQ2pFLE1BQU0sSUFBQSx3REFBZ0MsRUFBQztZQUNyQyxTQUFTO1lBQ1QsaUJBQWlCLEVBQUUsZ0JBQWdCO1lBQ25DLE9BQU8sRUFBRSxNQUFNO1lBQ2YsYUFBYSxFQUFFLE1BQU07WUFDckIsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLGtCQUFrQjtZQUMvQyxlQUFlLEVBQUUsSUFBQSxvQ0FBa0IsRUFBQyxJQUFJLENBQUMsVUFBVSxDQUFDO1lBQ3BELGFBQWEsRUFBRSxJQUFJO1NBQ3BCLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTyxNQUFNLHFCQUFxQixDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFDOUQsQ0FBQztBQUNILENBQUMsQ0FBQTtBQXRFWSxRQUFBLCtCQUErQixtQ0FzRTNDO0FBRU0sTUFBTSx3QkFBd0IsR0FBRyxLQUFLLEVBQzNDLFNBQTBCLEVBQzFCLEtBQW9DLEVBQ1csRUFBRTtJQUNqRCxNQUFNLGdCQUFnQixHQUFHLElBQUEsMENBQXVCLEVBQUMsU0FBUyxDQUFDLENBQUE7SUFDM0QsTUFBTSxRQUFRLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyw2QkFBNkIsQ0FDbkUsS0FBSyxDQUFDLFNBQVMsQ0FDaEIsQ0FBQTtJQUNELElBQUksUUFBUSxDQUFDLGdCQUFnQixLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzVDLE9BQU8sTUFBTSw2QkFBNkIsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQ3BFLENBQUM7SUFFRCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEscUVBQWlDLEVBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ3hFLE9BQU8sTUFBTSxJQUFBLDZDQUFxQyxFQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQTtBQUN2RSxDQUFDLENBQUE7QUFkWSxRQUFBLHdCQUF3Qiw0QkFjcEM7QUFFTSxNQUFNLHFDQUFxQyxHQUFHLEtBQUssRUFDeEQsU0FBMEIsRUFDMUIsTUFBNEMsRUFDRyxFQUFFO0lBQ2pELE1BQU0sZ0JBQWdCLEdBQUcsSUFBQSwwQ0FBdUIsRUFBQyxTQUFTLENBQUMsQ0FBQTtJQUMzRCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFBO0lBQzVCLElBQUksYUFBYSxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUE7SUFDekMsSUFBSSxNQUFNLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUM5QixNQUFNLFdBQVcsR0FBRyxNQUFNLGdCQUFnQixDQUFDLDZCQUE2QixDQUN0RSxNQUFNLENBQUMsa0JBQWtCLEVBQ3pCLE1BQU0sQ0FBQyxZQUFZLENBQ3BCLENBQUE7UUFDRCxJQUFJLFdBQVcsQ0FBQyxnQkFBZ0IsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMvQyxhQUFhLEdBQUcsQ0FDZCxNQUFNLDZCQUE2QixDQUFDLFNBQVMsRUFBRSxXQUFXLENBQUMsRUFBRSxDQUFDLENBQy9ELENBQUMsTUFBTSxDQUFBO1FBQ1YsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLElBQUEsdUNBQStCLEVBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBQ3hELE9BQU87UUFDTCxHQUFHLE1BQU07UUFDVCxjQUFjLEVBQUUsYUFBYTtLQUM5QixDQUFBO0FBQ0gsQ0FBQyxDQUFBO0FBeEJZLFFBQUEscUNBQXFDLHlDQXdCakQ7QUFFTSxNQUFNLHFDQUFxQyxHQUFHLEtBQUssRUFDeEQsU0FBMEIsRUFDMUIsV0FBbUIsRUFDWSxFQUFFO0lBQ2pDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBQSwwQ0FBdUIsRUFBQyxTQUFTLENBQUMsQ0FBQTtJQUMzRCxNQUFNLFVBQVUsR0FBeUIsRUFBRSxDQUFBO0lBQzNDLE1BQU0sUUFBUSxHQUFjLEVBQUUsQ0FBQTtJQUM5QixNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUE7SUFDcEIsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFBO0lBRWQsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUNaLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FDYixNQUFNLGdCQUFnQixDQUFDLG1DQUFtQyxDQUFDO1lBQ3pELFlBQVksRUFBRSxXQUFXO1lBQ3pCLGdCQUFnQixFQUFFLFNBQVM7WUFDM0IsS0FBSyxFQUFFLFFBQVE7WUFDZixNQUFNO1NBQ1AsQ0FBQyxDQUFBO1FBQ0osS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFBLGdDQUF3QixFQUFDLFNBQVMsRUFBRTtvQkFDdkQsU0FBUyxFQUFFLE1BQU0sQ0FBQyxFQUFFO2lCQUNyQixDQUFDLENBQUE7Z0JBQ0YsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7WUFDaEMsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUN0QixDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxRQUFRO1lBQUUsTUFBSztRQUNwQyxNQUFNLElBQUksUUFBUSxDQUFBO0lBQ3BCLENBQUM7SUFFRCxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE1BQU0sUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQzVDLElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3BCLE1BQU0sSUFBSSxjQUFjLENBQ3RCLFFBQVEsRUFDUix5REFBeUQsV0FBVyxHQUFHLENBQ3hFLENBQUE7SUFDSCxDQUFDO0lBQ0QsT0FBTyxVQUFVLENBQUE7QUFDbkIsQ0FBQyxDQUFBO0FBeENZLFFBQUEscUNBQXFDLHlDQXdDakQ7QUFFTSxNQUFNLG9DQUFvQyxHQUFHLEtBQUssRUFDdkQsU0FBMEIsRUFDa0IsRUFBRTtJQUM5QyxNQUFNLGdCQUFnQixHQUFHLElBQUEsMENBQXVCLEVBQUMsU0FBUyxDQUFDLENBQUE7SUFDM0QsTUFBTSxRQUFRLEdBQXNDLEVBQUUsQ0FBQTtJQUN0RCxNQUFNLFNBQVMsR0FBZ0QsRUFBRSxDQUFBO0lBQ2pFLE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxFQUd2QixDQUFBO0lBQ0gsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFBO0lBQ3BCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQTtJQUVkLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDWixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQ2IsTUFBTSxnQkFBZ0IsQ0FBQyxtQ0FBbUMsQ0FBQztZQUN6RCxnQkFBZ0IsRUFBRSxTQUFTO1lBQzNCLEtBQUssRUFBRSxRQUFRO1lBQ2YsTUFBTTtTQUNQLENBQUMsQ0FBQTtRQUNKLFNBQVMsQ0FBQyxJQUFJLENBQ1osR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUNqRSxDQUFBO1FBQ0QsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLFFBQVE7WUFBRSxNQUFLO1FBQ3BDLE1BQU0sSUFBSSxRQUFRLENBQUE7SUFDcEIsQ0FBQztJQUVELEtBQUssTUFBTSxNQUFNLElBQUksU0FBUyxFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDO1lBQ0gsSUFBSSxTQUFTLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUE7WUFDbkQsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNmLFNBQVMsR0FBRyxNQUFNLGdCQUFnQixDQUFDLHVCQUF1QixDQUN4RCxNQUFNLENBQUMsWUFBWSxDQUNwQixDQUFBO2dCQUNELFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsQ0FBQTtZQUNoRCxDQUFDO1lBQ0QsSUFBSSxTQUFTLENBQUMsK0JBQStCLElBQUksSUFBSTtnQkFBRSxTQUFRO1lBQy9ELE1BQU0sSUFBQSxnQ0FBd0IsRUFBQyxTQUFTLEVBQUUsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFDckUsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsU0FBUyxFQUFFLE1BQU0sQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtRQUNoRCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sUUFBUSxDQUFBO0FBQ2pCLENBQUMsQ0FBQTtBQTNDWSxRQUFBLG9DQUFvQyx3Q0EyQ2hEO0FBRUQsTUFBTSw0QkFBNEIsR0FBRyxJQUFBLDBCQUFVLEVBQzdDLDRCQUE0QixFQUM1QixLQUFLLEVBQ0gsS0FBb0MsRUFDcEMsRUFBRSxTQUFTLEVBQUUsRUFDZ0QsRUFBRSxDQUMvRCxJQUFJLDRCQUFZLENBQUMsTUFBTSxJQUFBLGdDQUF3QixFQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUNyRSxDQUFBO0FBRVksUUFBQSxnQ0FBZ0MsR0FBRyxJQUFBLDhCQUFjLEVBQzVELDRCQUE0QixFQUM1QixDQUFDLEtBQW9DLEVBQUUsRUFBRSxDQUN2QyxJQUFJLGdDQUFnQixDQUFDLDRCQUE0QixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQzVELENBQUE7QUFFRCxNQUFNLHlDQUF5QyxHQUFHLElBQUEsMEJBQVUsRUFDMUQsMkNBQTJDLEVBQzNDLEtBQUssRUFDSCxLQUErQixFQUMvQixFQUFFLFNBQVMsRUFBRSxFQUNnQyxFQUFFLENBQy9DLElBQUksNEJBQVksQ0FDZCxNQUFNLElBQUEsNkNBQXFDLEVBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FDM0UsQ0FDSixDQUFBO0FBRVksUUFBQSw2Q0FBNkMsR0FBRyxJQUFBLDhCQUFjLEVBQ3pFLDJDQUEyQyxFQUMzQyxDQUFDLEtBQStCLEVBQUUsRUFBRSxDQUNsQyxJQUFJLGdDQUFnQixDQUFDLHlDQUF5QyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQ3pFLENBQUEifQ==
|
|
@@ -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
|