@lodashventure/medusa-campaign 1.5.18 → 1.5.19
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/subscribers/order-placed.js +1 -14
- package/.medusa/server/src/workflows/index.js +2 -4
- package/package.json +1 -1
- package/src/subscribers/order-placed.ts +0 -18
- package/src/workflows/index.ts +0 -1
- package/.medusa/server/src/workflows/buy-x-get-y/applyBuyXGetYToCartWorkflow.js +0 -176
- package/src/workflows/buy-x-get-y/applyBuyXGetYToCartWorkflow.ts +0 -266
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.config = void 0;
|
|
4
4
|
exports.default = updatePromotionUsage;
|
|
5
|
-
const updateBuyXGetYUsageWorkflow_1 = require("../workflows/custom-campaign/updateBuyXGetYUsageWorkflow");
|
|
6
5
|
const updatePromotionUsageWorkflow_1 = require("../workflows/custom-campaign/updatePromotionUsageWorkflow");
|
|
7
6
|
async function updatePromotionUsage({ event: { data }, }) {
|
|
8
7
|
try {
|
|
@@ -18,18 +17,6 @@ async function updatePromotionUsage({ event: { data }, }) {
|
|
|
18
17
|
console.error(`[Campaign] Error updating flash sale promotion usage for order ${data.id}:`, error);
|
|
19
18
|
console.error(`[Campaign] Error details:`, JSON.stringify(error, Object.getOwnPropertyNames(error)));
|
|
20
19
|
}
|
|
21
|
-
// update promotion usage for Buy X Get Y campaigns
|
|
22
|
-
try {
|
|
23
|
-
await updateBuyXGetYUsageWorkflow_1.updateBuyXGetYUsageWorkflow.run({
|
|
24
|
-
input: {
|
|
25
|
-
order_id: data.id,
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
console.error(`[Campaign] Error updating Buy X Get Y usage for order ${data.id}:`, error);
|
|
31
|
-
console.error(`[Campaign] Error details:`, JSON.stringify(error, Object.getOwnPropertyNames(error)));
|
|
32
|
-
}
|
|
33
20
|
}
|
|
34
21
|
catch (error) {
|
|
35
22
|
console.error(`[Campaign] Error in order.placed subscriber for order ${data.id}:`, error);
|
|
@@ -41,4 +28,4 @@ async function updatePromotionUsage({ event: { data }, }) {
|
|
|
41
28
|
exports.config = {
|
|
42
29
|
event: `order.placed`,
|
|
43
30
|
};
|
|
44
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JkZXItcGxhY2VkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3N1YnNjcmliZXJzL29yZGVyLXBsYWNlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSx1Q0FpQ0M7QUFuQ0QsNEdBQXlHO0FBRTFGLEtBQUssVUFBVSxvQkFBb0IsQ0FBQyxFQUNqRCxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FDZ0I7SUFDL0IsSUFBSSxDQUFDO1FBQ0gseUNBQXlDO1FBQ3pDLElBQUksQ0FBQztZQUNILE1BQU0sMkRBQTRCLENBQUMsR0FBRyxDQUFDO2dCQUNyQyxLQUFLLEVBQUU7b0JBQ0wsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFO2lCQUNsQjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLEtBQUssQ0FDWCxrRUFBa0UsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUM1RSxLQUFLLENBQ04sQ0FBQztZQUNGLE9BQU8sQ0FBQyxLQUFLLENBQ1gsMkJBQTJCLEVBQzNCLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUN6RCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTyxDQUFDLEtBQUssQ0FDWCx5REFBeUQsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUNuRSxLQUFLLENBQ04sQ0FBQztRQUNGLE9BQU8sQ0FBQyxLQUFLLENBQUMseUJBQXlCLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RELE9BQU8sQ0FBQyxLQUFLLENBQ1gsMkJBQTJCLEVBQzNCLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUN6RCxDQUFDO1FBQ0YsMkNBQTJDO0lBQzdDLENBQUM7QUFDSCxDQUFDO0FBRVksUUFBQSxNQUFNLEdBQXFCO0lBQ3RDLEtBQUssRUFBRSxjQUFjO0NBQ3RCLENBQUMifQ==
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.updateCouponCampaignWorkflow = exports.createCouponCampaignWorkflow = exports.
|
|
3
|
+
exports.updateCouponCampaignWorkflow = exports.createCouponCampaignWorkflow = exports.updatePromotionUsageWorkflow = exports.updateCustomFlashSaleWorkflow = exports.createCustomFlashSaleWorkflow = exports.createCustomCampaignWorkflow = void 0;
|
|
4
4
|
var createCustomCampaignWorkflow_1 = require("./custom-campaign/createCustomCampaignWorkflow");
|
|
5
5
|
Object.defineProperty(exports, "createCustomCampaignWorkflow", { enumerable: true, get: function () { return createCustomCampaignWorkflow_1.createCustomCampaignWorkflow; } });
|
|
6
6
|
Object.defineProperty(exports, "createCustomFlashSaleWorkflow", { enumerable: true, get: function () { return createCustomCampaignWorkflow_1.createCustomCampaignWorkflow; } });
|
|
@@ -8,10 +8,8 @@ var updateCustomFlashSaleWorkflow_1 = require("./custom-campaign/updateCustomFla
|
|
|
8
8
|
Object.defineProperty(exports, "updateCustomFlashSaleWorkflow", { enumerable: true, get: function () { return updateCustomFlashSaleWorkflow_1.updateCustomFlashSaleWorkflow; } });
|
|
9
9
|
var updatePromotionUsageWorkflow_1 = require("./custom-campaign/updatePromotionUsageWorkflow");
|
|
10
10
|
Object.defineProperty(exports, "updatePromotionUsageWorkflow", { enumerable: true, get: function () { return updatePromotionUsageWorkflow_1.updatePromotionUsageWorkflow; } });
|
|
11
|
-
var applyBuyXGetYToCartWorkflow_1 = require("./buy-x-get-y/applyBuyXGetYToCartWorkflow");
|
|
12
|
-
Object.defineProperty(exports, "applyBuyXGetYToCartWorkflow", { enumerable: true, get: function () { return applyBuyXGetYToCartWorkflow_1.applyBuyXGetYToCartWorkflow; } });
|
|
13
11
|
var createCouponCampaignWorkflow_1 = require("./custom-campaign/createCouponCampaignWorkflow");
|
|
14
12
|
Object.defineProperty(exports, "createCouponCampaignWorkflow", { enumerable: true, get: function () { return createCouponCampaignWorkflow_1.createCouponCampaignWorkflow; } });
|
|
15
13
|
var updateCouponCampaignWorkflow_1 = require("./custom-campaign/updateCouponCampaignWorkflow");
|
|
16
14
|
Object.defineProperty(exports, "updateCouponCampaignWorkflow", { enumerable: true, get: function () { return updateCouponCampaignWorkflow_1.updateCouponCampaignWorkflow; } });
|
|
17
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtGQUE2SjtBQUFwSiw0SUFBQSw0QkFBNEIsT0FBQTtBQUFFLDZJQUFBLDRCQUE0QixPQUFpQztBQUNwRyxpR0FBZ0c7QUFBdkYsOElBQUEsNkJBQTZCLE9BQUE7QUFDdEMsK0ZBQThGO0FBQXJGLDRJQUFBLDRCQUE0QixPQUFBO0FBQ3JDLCtGQUE4RjtBQUFyRiw0SUFBQSw0QkFBNEIsT0FBQTtBQUNyQywrRkFBOEY7QUFBckYsNElBQUEsNEJBQTRCLE9BQUEifQ==
|
package/package.json
CHANGED
|
@@ -23,24 +23,6 @@ export default async function updatePromotionUsage({
|
|
|
23
23
|
JSON.stringify(error, Object.getOwnPropertyNames(error)),
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
// update promotion usage for Buy X Get Y campaigns
|
|
28
|
-
try {
|
|
29
|
-
await updateBuyXGetYUsageWorkflow.run({
|
|
30
|
-
input: {
|
|
31
|
-
order_id: data.id,
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
} catch (error) {
|
|
35
|
-
console.error(
|
|
36
|
-
`[Campaign] Error updating Buy X Get Y usage for order ${data.id}:`,
|
|
37
|
-
error,
|
|
38
|
-
);
|
|
39
|
-
console.error(
|
|
40
|
-
`[Campaign] Error details:`,
|
|
41
|
-
JSON.stringify(error, Object.getOwnPropertyNames(error)),
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
26
|
} catch (error) {
|
|
45
27
|
console.error(
|
|
46
28
|
`[Campaign] Error in order.placed subscriber for order ${data.id}:`,
|
package/src/workflows/index.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { createCustomCampaignWorkflow, createCustomCampaignWorkflow as createCustomFlashSaleWorkflow } from "./custom-campaign/createCustomCampaignWorkflow";
|
|
2
2
|
export { updateCustomFlashSaleWorkflow } from "./custom-campaign/updateCustomFlashSaleWorkflow";
|
|
3
3
|
export { updatePromotionUsageWorkflow } from "./custom-campaign/updatePromotionUsageWorkflow";
|
|
4
|
-
export { applyBuyXGetYToCartWorkflow } from "./buy-x-get-y/applyBuyXGetYToCartWorkflow";
|
|
5
4
|
export { createCouponCampaignWorkflow } from "./custom-campaign/createCouponCampaignWorkflow";
|
|
6
5
|
export { updateCouponCampaignWorkflow } from "./custom-campaign/updateCouponCampaignWorkflow";
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.applyBuyXGetYToCartWorkflow = void 0;
|
|
4
|
-
const framework_1 = require("@medusajs/framework");
|
|
5
|
-
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
-
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
7
|
-
const custom_campaigns_1 = require("../../modules/custom-campaigns");
|
|
8
|
-
const campaign_type_enum_1 = require("../../modules/custom-campaigns/types/campaign-type.enum");
|
|
9
|
-
const resolveLinkModuleService = () => {
|
|
10
|
-
const legacyKey = "linkModuleService";
|
|
11
|
-
try {
|
|
12
|
-
return framework_1.container.resolve(utils_1.ContainerRegistrationKeys.LINK);
|
|
13
|
-
}
|
|
14
|
-
catch (err) {
|
|
15
|
-
const hasLegacy = typeof framework_1.container?.hasRegistration === "function" &&
|
|
16
|
-
framework_1.container.hasRegistration(legacyKey);
|
|
17
|
-
if (hasLegacy) {
|
|
18
|
-
return framework_1.container.resolve(legacyKey);
|
|
19
|
-
}
|
|
20
|
-
throw err;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
const applyBuyXGetYToCartStep = (0, workflows_sdk_1.createStep)("apply-buy-x-get-y-to-cart-step", async (data) => {
|
|
24
|
-
const customCampaignModuleService = framework_1.container.resolve(custom_campaigns_1.CUSTOM_CAMPAIGN_MODULE);
|
|
25
|
-
const cartService = framework_1.container.resolve(utils_1.Modules.CART);
|
|
26
|
-
const productService = framework_1.container.resolve(utils_1.Modules.PRODUCT);
|
|
27
|
-
const linkService = resolveLinkModuleService();
|
|
28
|
-
// Fetch the cart with items
|
|
29
|
-
const carts = await cartService.listCarts({
|
|
30
|
-
id: [data.cart_id],
|
|
31
|
-
}, {
|
|
32
|
-
relations: ["items", "items.variant", "items.product"],
|
|
33
|
-
});
|
|
34
|
-
const cart = carts[0];
|
|
35
|
-
if (!cart || !cart.items || cart.items.length === 0) {
|
|
36
|
-
return new workflows_sdk_1.StepResponse({ rewardItemsAdded: [] });
|
|
37
|
-
}
|
|
38
|
-
// Get all active Buy X Get Y campaigns
|
|
39
|
-
const now = new Date();
|
|
40
|
-
const campaignTypes = await customCampaignModuleService.listCustomCampaignTypes({
|
|
41
|
-
type: campaign_type_enum_1.CampaignTypeEnum.BuyXGetY,
|
|
42
|
-
});
|
|
43
|
-
if (campaignTypes.length === 0) {
|
|
44
|
-
return new workflows_sdk_1.StepResponse({ rewardItemsAdded: [] });
|
|
45
|
-
}
|
|
46
|
-
// Get campaigns through link service
|
|
47
|
-
const campaignLinks = await linkService.list({
|
|
48
|
-
[custom_campaigns_1.CUSTOM_CAMPAIGN_MODULE]: {
|
|
49
|
-
custom_campaign_type_id: campaignTypes.map((ct) => ct.id),
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
const campaignIds = campaignLinks.map((link) => link[utils_1.Modules.PROMOTION].campaign_id);
|
|
53
|
-
const promotionService = framework_1.container.resolve(utils_1.Modules.PROMOTION);
|
|
54
|
-
const campaigns = await promotionService.listCampaigns({
|
|
55
|
-
id: campaignIds,
|
|
56
|
-
});
|
|
57
|
-
// Filter active campaigns
|
|
58
|
-
const activeCampaigns = campaigns.filter((campaign) => new Date(campaign.starts_at) <= now &&
|
|
59
|
-
new Date(campaign.ends_at) >= now);
|
|
60
|
-
if (activeCampaigns.length === 0) {
|
|
61
|
-
return new workflows_sdk_1.StepResponse({ rewardItemsAdded: [] });
|
|
62
|
-
}
|
|
63
|
-
// Get BOGO configurations for active campaigns
|
|
64
|
-
const buyXGetYConfigs = await customCampaignModuleService.listBuyXGetYConfigs({
|
|
65
|
-
campaign_id: activeCampaigns.map((c) => c.id),
|
|
66
|
-
});
|
|
67
|
-
// Remove ALL existing BOGO reward items to recalculate from scratch
|
|
68
|
-
const existingBogoItems = cart.items.filter((item) => item.metadata?.is_bogo_reward === true);
|
|
69
|
-
const removedItemIds = [];
|
|
70
|
-
for (const bogoItem of existingBogoItems) {
|
|
71
|
-
try {
|
|
72
|
-
await cartService.deleteLineItems([bogoItem.id]);
|
|
73
|
-
removedItemIds.push(bogoItem.id);
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
console.error(`Failed to remove existing BOGO item:`, error);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// Group cart items by product (excluding BOGO items which are now removed)
|
|
80
|
-
const cartItemsByProduct = new Map();
|
|
81
|
-
cart.items.forEach((item) => {
|
|
82
|
-
if (item.metadata?.is_bogo_reward)
|
|
83
|
-
return; // Skip BOGO items (should be none now)
|
|
84
|
-
const productId = item.product_id;
|
|
85
|
-
if (!cartItemsByProduct.has(productId)) {
|
|
86
|
-
cartItemsByProduct.set(productId, []);
|
|
87
|
-
}
|
|
88
|
-
cartItemsByProduct.get(productId).push(item);
|
|
89
|
-
});
|
|
90
|
-
const rewardItemsToAdd = [];
|
|
91
|
-
// Check each BOGO configuration
|
|
92
|
-
for (const config of buyXGetYConfigs) {
|
|
93
|
-
// Check if usage limit reached
|
|
94
|
-
if (config.limit && config.used >= config.limit) {
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
// Get cart items for the trigger product
|
|
98
|
-
const triggerItems = cartItemsByProduct.get(config.trigger_product_id);
|
|
99
|
-
if (!triggerItems || triggerItems.length === 0) {
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
// Calculate total quantity of trigger product
|
|
103
|
-
const totalTriggerQuantity = triggerItems.reduce((sum, item) => sum + item.quantity, 0);
|
|
104
|
-
// Check if trigger quantity is met
|
|
105
|
-
if (totalTriggerQuantity >= config.trigger_quantity) {
|
|
106
|
-
// Calculate how many times the reward should be given
|
|
107
|
-
const rewardMultiplier = Math.floor(totalTriggerQuantity / config.trigger_quantity);
|
|
108
|
-
const totalRewardQuantity = config.reward_quantity * rewardMultiplier;
|
|
109
|
-
// Get the reward product's default variant
|
|
110
|
-
const rewardProduct = await productService.retrieveProduct(config.reward_product_id, {
|
|
111
|
-
relations: ["variants"],
|
|
112
|
-
});
|
|
113
|
-
if (!rewardProduct.variants || rewardProduct.variants.length === 0) {
|
|
114
|
-
console.warn(`No variants found for reward product ${config.reward_product_id}`);
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
const defaultVariant = rewardProduct.variants[0];
|
|
118
|
-
rewardItemsToAdd.push({
|
|
119
|
-
product_id: config.reward_product_id,
|
|
120
|
-
variant_id: defaultVariant.id,
|
|
121
|
-
quantity: totalRewardQuantity,
|
|
122
|
-
metadata: {
|
|
123
|
-
is_bogo_reward: true,
|
|
124
|
-
bogo_config_id: config.id,
|
|
125
|
-
reward_type: config.reward_type,
|
|
126
|
-
reward_value: config.reward_value ?? undefined,
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
// Add reward items to cart
|
|
132
|
-
const addedItems = [];
|
|
133
|
-
for (const rewardItem of rewardItemsToAdd) {
|
|
134
|
-
try {
|
|
135
|
-
const variants = await productService.listVariants({
|
|
136
|
-
id: [rewardItem.variant_id],
|
|
137
|
-
});
|
|
138
|
-
const products = await productService.listProducts({
|
|
139
|
-
id: [rewardItem.product_id],
|
|
140
|
-
});
|
|
141
|
-
const product = products[0];
|
|
142
|
-
const addedItem = await cartService.addLineItems(data.cart_id, [
|
|
143
|
-
{
|
|
144
|
-
variant_id: rewardItem.variant_id,
|
|
145
|
-
quantity: rewardItem.quantity,
|
|
146
|
-
title: product?.title || "Reward Item",
|
|
147
|
-
unit_price: 0,
|
|
148
|
-
metadata: rewardItem.metadata,
|
|
149
|
-
},
|
|
150
|
-
]);
|
|
151
|
-
addedItems.push(addedItem);
|
|
152
|
-
}
|
|
153
|
-
catch (error) {
|
|
154
|
-
console.error(`Failed to add reward item:`, error);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return new workflows_sdk_1.StepResponse({ rewardItemsAdded: addedItems }, { cart_id: data.cart_id, added_items: addedItems });
|
|
158
|
-
}, async (compensationData) => {
|
|
159
|
-
// Compensation: Remove added reward items if workflow fails
|
|
160
|
-
if (!compensationData || !compensationData.added_items)
|
|
161
|
-
return;
|
|
162
|
-
const cartService = framework_1.container.resolve(utils_1.Modules.CART);
|
|
163
|
-
for (const item of compensationData.added_items) {
|
|
164
|
-
try {
|
|
165
|
-
await cartService.deleteLineItems([item.id]);
|
|
166
|
-
}
|
|
167
|
-
catch (error) {
|
|
168
|
-
console.error(`Failed to remove reward item during compensation:`, error);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
exports.applyBuyXGetYToCartWorkflow = (0, workflows_sdk_1.createWorkflow)("apply-buy-x-get-y-to-cart", (data) => {
|
|
173
|
-
const result = applyBuyXGetYToCartStep(data);
|
|
174
|
-
return new workflows_sdk_1.WorkflowResponse(result);
|
|
175
|
-
});
|
|
176
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbHlCdXlYR2V0WVRvQ2FydFdvcmtmbG93LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9idXkteC1nZXQteS9hcHBseUJ1eVhHZXRZVG9DYXJ0V29ya2Zsb3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQWdEO0FBQ2hELHFEQUdtQztBQUNuQyxxRUFLMkM7QUFDM0MscUVBQXdFO0FBRXhFLGdHQUEyRjtBQWtCM0YsTUFBTSx3QkFBd0IsR0FBRyxHQUFRLEVBQUU7SUFDekMsTUFBTSxTQUFTLEdBQUcsbUJBQW1CLENBQUM7SUFFdEMsSUFBSSxDQUFDO1FBQ0gsT0FBTyxxQkFBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE1BQU0sU0FBUyxHQUNiLE9BQVEscUJBQWlCLEVBQUUsZUFBZSxLQUFLLFVBQVU7WUFDeEQscUJBQWlCLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRWhELElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxPQUFPLHFCQUFTLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7UUFFRCxNQUFNLEdBQUcsQ0FBQztJQUNaLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLHVCQUF1QixHQUFHLElBQUEsMEJBQVUsRUFLeEMsZ0NBQWdDLEVBQ2hDLEtBQUssRUFBRSxJQUF3QixFQUFFLEVBQUU7SUFDakMsTUFBTSwyQkFBMkIsR0FDL0IscUJBQVMsQ0FBQyxPQUFPLENBQThCLHlDQUFzQixDQUFDLENBQUM7SUFDekUsTUFBTSxXQUFXLEdBQUcscUJBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BELE1BQU0sY0FBYyxHQUFHLHFCQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxRCxNQUFNLFdBQVcsR0FBRyx3QkFBd0IsRUFBRSxDQUFDO0lBRS9DLDRCQUE0QjtJQUM1QixNQUFNLEtBQUssR0FBRyxNQUFNLFdBQVcsQ0FBQyxTQUFTLENBQ3ZDO1FBQ0UsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztLQUNuQixFQUNEO1FBQ0UsU0FBUyxFQUFFLENBQUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxlQUFlLENBQUM7S0FDdkQsQ0FDRixDQUFDO0lBQ0YsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXRCLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3BELE9BQU8sSUFBSSw0QkFBWSxDQUFDLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsdUNBQXVDO0lBQ3ZDLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7SUFDdkIsTUFBTSxhQUFhLEdBQ2pCLE1BQU0sMkJBQTJCLENBQUMsdUJBQXVCLENBQUM7UUFDeEQsSUFBSSxFQUFFLHFDQUFnQixDQUFDLFFBQVE7S0FDaEMsQ0FBQyxDQUFDO0lBRUwsSUFBSSxhQUFhLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQy9CLE9BQU8sSUFBSSw0QkFBWSxDQUFDLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQscUNBQXFDO0lBQ3JDLE1BQU0sYUFBYSxHQUFHLE1BQU0sV0FBVyxDQUFDLElBQUksQ0FBQztRQUMzQyxDQUFDLHlDQUFzQixDQUFDLEVBQUU7WUFDeEIsdUJBQXVCLEVBQUUsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztTQUMxRDtLQUNGLENBQUMsQ0FBQztJQUVILE1BQU0sV0FBVyxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQ25DLENBQUMsSUFBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsZUFBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFdBQVcsQ0FDbkQsQ0FBQztJQUVGLE1BQU0sZ0JBQWdCLEdBQUcscUJBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzlELE1BQU0sU0FBUyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsYUFBYSxDQUFDO1FBQ3JELEVBQUUsRUFBRSxXQUFXO0tBQ2hCLENBQUMsQ0FBQztJQUVILDBCQUEwQjtJQUMxQixNQUFNLGVBQWUsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUN0QyxDQUFDLFFBQWEsRUFBRSxFQUFFLENBQ2hCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxHQUFHO1FBQ25DLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLENBQ3BDLENBQUM7SUFFRixJQUFJLGVBQWUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDakMsT0FBTyxJQUFJLDRCQUFZLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFRCwrQ0FBK0M7SUFDL0MsTUFBTSxlQUFlLEdBQ25CLE1BQU0sMkJBQTJCLENBQUMsbUJBQW1CLENBQUM7UUFDcEQsV0FBVyxFQUFFLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7S0FDbkQsQ0FBQyxDQUFDO0lBRUwsb0VBQW9FO0lBQ3BFLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQ3pDLENBQUMsSUFBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLGNBQWMsS0FBSyxJQUFJLENBQ3RELENBQUM7SUFFRixNQUFNLGNBQWMsR0FBYSxFQUFFLENBQUM7SUFDcEMsS0FBSyxNQUFNLFFBQVEsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pDLElBQUksQ0FBQztZQUNILE1BQU0sV0FBVyxDQUFDLGVBQWUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2pELGNBQWMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ25DLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQyxzQ0FBc0MsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUMvRCxDQUFDO0lBQ0gsQ0FBQztJQUVELDJFQUEyRTtJQUMzRSxNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxFQUFpQixDQUFDO0lBQ3BELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBUyxFQUFFLEVBQUU7UUFDL0IsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLGNBQWM7WUFBRSxPQUFPLENBQUMsdUNBQXVDO1FBQ2xGLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDbEMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDeEMsQ0FBQztRQUNELGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDaEQsQ0FBQyxDQUFDLENBQUM7SUFFSCxNQUFNLGdCQUFnQixHQUFpQixFQUFFLENBQUM7SUFFMUMsZ0NBQWdDO0lBQ2hDLEtBQUssTUFBTSxNQUFNLElBQUksZUFBZSxFQUFFLENBQUM7UUFDckMsK0JBQStCO1FBQy9CLElBQUksTUFBTSxDQUFDLEtBQUssSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNoRCxTQUFTO1FBQ1gsQ0FBQztRQUVELHlDQUF5QztRQUN6QyxNQUFNLFlBQVksR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDdkUsSUFBSSxDQUFDLFlBQVksSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQy9DLFNBQVM7UUFDWCxDQUFDO1FBRUQsOENBQThDO1FBQzlDLE1BQU0sb0JBQW9CLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FDOUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFDbEMsQ0FBQyxDQUNGLENBQUM7UUFFRixtQ0FBbUM7UUFDbkMsSUFBSSxvQkFBb0IsSUFBSSxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUNwRCxzREFBc0Q7WUFDdEQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUNqQyxvQkFBb0IsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQy9DLENBQUM7WUFDRixNQUFNLG1CQUFtQixHQUFHLE1BQU0sQ0FBQyxlQUFlLEdBQUcsZ0JBQWdCLENBQUM7WUFFdEUsMkNBQTJDO1lBQzNDLE1BQU0sYUFBYSxHQUFHLE1BQU0sY0FBYyxDQUFDLGVBQWUsQ0FDeEQsTUFBTSxDQUFDLGlCQUFpQixFQUN4QjtnQkFDRSxTQUFTLEVBQUUsQ0FBQyxVQUFVLENBQUM7YUFDeEIsQ0FDRixDQUFDO1lBRUYsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLElBQUksYUFBYSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ25FLE9BQU8sQ0FBQyxJQUFJLENBQ1Ysd0NBQXdDLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxDQUNuRSxDQUFDO2dCQUNGLFNBQVM7WUFDWCxDQUFDO1lBRUQsTUFBTSxjQUFjLEdBQUcsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVqRCxnQkFBZ0IsQ0FBQyxJQUFJLENBQUM7Z0JBQ3BCLFVBQVUsRUFBRSxNQUFNLENBQUMsaUJBQWlCO2dCQUNwQyxVQUFVLEVBQUUsY0FBYyxDQUFDLEVBQUU7Z0JBQzdCLFFBQVEsRUFBRSxtQkFBbUI7Z0JBQzdCLFFBQVEsRUFBRTtvQkFDUixjQUFjLEVBQUUsSUFBSTtvQkFDcEIsY0FBYyxFQUFFLE1BQU0sQ0FBQyxFQUFFO29CQUN6QixXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVc7b0JBQy9CLFlBQVksRUFBRSxNQUFNLENBQUMsWUFBWSxJQUFJLFNBQVM7aUJBQy9DO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7SUFFRCwyQkFBMkI7SUFDM0IsTUFBTSxVQUFVLEdBQVUsRUFBRSxDQUFDO0lBQzdCLEtBQUssTUFBTSxVQUFVLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztRQUMxQyxJQUFJLENBQUM7WUFDSCxNQUFNLFFBQVEsR0FBRyxNQUFPLGNBQXNCLENBQUMsWUFBWSxDQUFDO2dCQUMxRCxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDO2FBQzVCLENBQUMsQ0FBQztZQUNILE1BQU0sUUFBUSxHQUFHLE1BQU0sY0FBYyxDQUFDLFlBQVksQ0FBQztnQkFDakQsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQzthQUM1QixDQUFDLENBQUM7WUFDSCxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFNUIsTUFBTSxTQUFTLEdBQUcsTUFBTSxXQUFXLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQzdEO29CQUNFLFVBQVUsRUFBRSxVQUFVLENBQUMsVUFBVTtvQkFDakMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxRQUFRO29CQUM3QixLQUFLLEVBQUUsT0FBTyxFQUFFLEtBQUssSUFBSSxhQUFhO29CQUN0QyxVQUFVLEVBQUUsQ0FBQztvQkFDYixRQUFRLEVBQUUsVUFBVSxDQUFDLFFBQVE7aUJBQzlCO2FBQ0YsQ0FBQyxDQUFDO1lBQ0gsVUFBVSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM3QixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsNEJBQTRCLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDckQsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLElBQUksNEJBQVksQ0FDckIsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsRUFDaEMsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLENBQ25ELENBQUM7QUFDSixDQUFDLEVBQ0QsS0FBSyxFQUFFLGdCQUFnQixFQUFFLEVBQUU7SUFDekIsNERBQTREO0lBQzVELElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVc7UUFBRSxPQUFPO0lBRS9ELE1BQU0sV0FBVyxHQUFHLHFCQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVwRCxLQUFLLE1BQU0sSUFBSSxJQUFJLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2hELElBQUksQ0FBQztZQUNILE1BQU0sV0FBVyxDQUFDLGVBQWUsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQy9DLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLEtBQUssQ0FDWCxtREFBbUQsRUFDbkQsS0FBSyxDQUNOLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMsQ0FDRixDQUFDO0FBRVcsUUFBQSwyQkFBMkIsR0FBRyxJQUFBLDhCQUFjLEVBQ3ZELDJCQUEyQixFQUMzQixDQUFDLElBQXdCLEVBQUUsRUFBRTtJQUMzQixNQUFNLE1BQU0sR0FBRyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU3QyxPQUFPLElBQUksZ0NBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdEMsQ0FBQyxDQUNGLENBQUMifQ==
|
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import { container } from "@medusajs/framework";
|
|
2
|
-
import {
|
|
3
|
-
ContainerRegistrationKeys,
|
|
4
|
-
Modules,
|
|
5
|
-
} from "@medusajs/framework/utils";
|
|
6
|
-
import {
|
|
7
|
-
createStep,
|
|
8
|
-
createWorkflow,
|
|
9
|
-
StepResponse,
|
|
10
|
-
WorkflowResponse,
|
|
11
|
-
} from "@medusajs/framework/workflows-sdk";
|
|
12
|
-
import { CUSTOM_CAMPAIGN_MODULE } from "../../modules/custom-campaigns";
|
|
13
|
-
import CustomCampaignModuleService from "../../modules/custom-campaigns/service";
|
|
14
|
-
import { CampaignTypeEnum } from "../../modules/custom-campaigns/types/campaign-type.enum";
|
|
15
|
-
|
|
16
|
-
interface ApplyBuyXGetYInput {
|
|
17
|
-
cart_id: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface RewardItem {
|
|
21
|
-
product_id: string;
|
|
22
|
-
variant_id: string;
|
|
23
|
-
quantity: number;
|
|
24
|
-
metadata?: {
|
|
25
|
-
is_bogo_reward?: boolean;
|
|
26
|
-
bogo_config_id?: string;
|
|
27
|
-
reward_type?: string;
|
|
28
|
-
reward_value?: number;
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const resolveLinkModuleService = (): any => {
|
|
33
|
-
const legacyKey = "linkModuleService";
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
return container.resolve(ContainerRegistrationKeys.LINK);
|
|
37
|
-
} catch (err) {
|
|
38
|
-
const hasLegacy =
|
|
39
|
-
typeof (container as any)?.hasRegistration === "function" &&
|
|
40
|
-
(container as any).hasRegistration(legacyKey);
|
|
41
|
-
|
|
42
|
-
if (hasLegacy) {
|
|
43
|
-
return container.resolve(legacyKey);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
throw err;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const applyBuyXGetYToCartStep = createStep<
|
|
51
|
-
ApplyBuyXGetYInput,
|
|
52
|
-
{ rewardItemsAdded: any[] },
|
|
53
|
-
{ cart_id: string; added_items: any[] }
|
|
54
|
-
>(
|
|
55
|
-
"apply-buy-x-get-y-to-cart-step",
|
|
56
|
-
async (data: ApplyBuyXGetYInput) => {
|
|
57
|
-
const customCampaignModuleService =
|
|
58
|
-
container.resolve<CustomCampaignModuleService>(CUSTOM_CAMPAIGN_MODULE);
|
|
59
|
-
const cartService = container.resolve(Modules.CART);
|
|
60
|
-
const productService = container.resolve(Modules.PRODUCT);
|
|
61
|
-
const linkService = resolveLinkModuleService();
|
|
62
|
-
|
|
63
|
-
// Fetch the cart with items
|
|
64
|
-
const carts = await cartService.listCarts(
|
|
65
|
-
{
|
|
66
|
-
id: [data.cart_id],
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
relations: ["items", "items.variant", "items.product"],
|
|
70
|
-
},
|
|
71
|
-
);
|
|
72
|
-
const cart = carts[0];
|
|
73
|
-
|
|
74
|
-
if (!cart || !cart.items || cart.items.length === 0) {
|
|
75
|
-
return new StepResponse({ rewardItemsAdded: [] });
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Get all active Buy X Get Y campaigns
|
|
79
|
-
const now = new Date();
|
|
80
|
-
const campaignTypes =
|
|
81
|
-
await customCampaignModuleService.listCustomCampaignTypes({
|
|
82
|
-
type: CampaignTypeEnum.BuyXGetY,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
if (campaignTypes.length === 0) {
|
|
86
|
-
return new StepResponse({ rewardItemsAdded: [] });
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Get campaigns through link service
|
|
90
|
-
const campaignLinks = await linkService.list({
|
|
91
|
-
[CUSTOM_CAMPAIGN_MODULE]: {
|
|
92
|
-
custom_campaign_type_id: campaignTypes.map((ct) => ct.id),
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const campaignIds = campaignLinks.map(
|
|
97
|
-
(link: any) => link[Modules.PROMOTION].campaign_id,
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const promotionService = container.resolve(Modules.PROMOTION);
|
|
101
|
-
const campaigns = await promotionService.listCampaigns({
|
|
102
|
-
id: campaignIds,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// Filter active campaigns
|
|
106
|
-
const activeCampaigns = campaigns.filter(
|
|
107
|
-
(campaign: any) =>
|
|
108
|
-
new Date(campaign.starts_at) <= now &&
|
|
109
|
-
new Date(campaign.ends_at) >= now,
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
if (activeCampaigns.length === 0) {
|
|
113
|
-
return new StepResponse({ rewardItemsAdded: [] });
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Get BOGO configurations for active campaigns
|
|
117
|
-
const buyXGetYConfigs =
|
|
118
|
-
await customCampaignModuleService.listBuyXGetYConfigs({
|
|
119
|
-
campaign_id: activeCampaigns.map((c: any) => c.id),
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// Remove ALL existing BOGO reward items to recalculate from scratch
|
|
123
|
-
const existingBogoItems = cart.items.filter(
|
|
124
|
-
(item: any) => item.metadata?.is_bogo_reward === true,
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
const removedItemIds: string[] = [];
|
|
128
|
-
for (const bogoItem of existingBogoItems) {
|
|
129
|
-
try {
|
|
130
|
-
await cartService.deleteLineItems([bogoItem.id]);
|
|
131
|
-
removedItemIds.push(bogoItem.id);
|
|
132
|
-
} catch (error) {
|
|
133
|
-
console.error(`Failed to remove existing BOGO item:`, error);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Group cart items by product (excluding BOGO items which are now removed)
|
|
138
|
-
const cartItemsByProduct = new Map<string, any[]>();
|
|
139
|
-
cart.items.forEach((item: any) => {
|
|
140
|
-
if (item.metadata?.is_bogo_reward) return; // Skip BOGO items (should be none now)
|
|
141
|
-
const productId = item.product_id;
|
|
142
|
-
if (!cartItemsByProduct.has(productId)) {
|
|
143
|
-
cartItemsByProduct.set(productId, []);
|
|
144
|
-
}
|
|
145
|
-
cartItemsByProduct.get(productId)!.push(item);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
const rewardItemsToAdd: RewardItem[] = [];
|
|
149
|
-
|
|
150
|
-
// Check each BOGO configuration
|
|
151
|
-
for (const config of buyXGetYConfigs) {
|
|
152
|
-
// Check if usage limit reached
|
|
153
|
-
if (config.limit && config.used >= config.limit) {
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Get cart items for the trigger product
|
|
158
|
-
const triggerItems = cartItemsByProduct.get(config.trigger_product_id);
|
|
159
|
-
if (!triggerItems || triggerItems.length === 0) {
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Calculate total quantity of trigger product
|
|
164
|
-
const totalTriggerQuantity = triggerItems.reduce(
|
|
165
|
-
(sum, item) => sum + item.quantity,
|
|
166
|
-
0,
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
// Check if trigger quantity is met
|
|
170
|
-
if (totalTriggerQuantity >= config.trigger_quantity) {
|
|
171
|
-
// Calculate how many times the reward should be given
|
|
172
|
-
const rewardMultiplier = Math.floor(
|
|
173
|
-
totalTriggerQuantity / config.trigger_quantity,
|
|
174
|
-
);
|
|
175
|
-
const totalRewardQuantity = config.reward_quantity * rewardMultiplier;
|
|
176
|
-
|
|
177
|
-
// Get the reward product's default variant
|
|
178
|
-
const rewardProduct = await productService.retrieveProduct(
|
|
179
|
-
config.reward_product_id,
|
|
180
|
-
{
|
|
181
|
-
relations: ["variants"],
|
|
182
|
-
},
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
if (!rewardProduct.variants || rewardProduct.variants.length === 0) {
|
|
186
|
-
console.warn(
|
|
187
|
-
`No variants found for reward product ${config.reward_product_id}`,
|
|
188
|
-
);
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const defaultVariant = rewardProduct.variants[0];
|
|
193
|
-
|
|
194
|
-
rewardItemsToAdd.push({
|
|
195
|
-
product_id: config.reward_product_id,
|
|
196
|
-
variant_id: defaultVariant.id,
|
|
197
|
-
quantity: totalRewardQuantity,
|
|
198
|
-
metadata: {
|
|
199
|
-
is_bogo_reward: true,
|
|
200
|
-
bogo_config_id: config.id,
|
|
201
|
-
reward_type: config.reward_type,
|
|
202
|
-
reward_value: config.reward_value ?? undefined,
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Add reward items to cart
|
|
209
|
-
const addedItems: any[] = [];
|
|
210
|
-
for (const rewardItem of rewardItemsToAdd) {
|
|
211
|
-
try {
|
|
212
|
-
const variants = await (productService as any).listVariants({
|
|
213
|
-
id: [rewardItem.variant_id],
|
|
214
|
-
});
|
|
215
|
-
const products = await productService.listProducts({
|
|
216
|
-
id: [rewardItem.product_id],
|
|
217
|
-
});
|
|
218
|
-
const product = products[0];
|
|
219
|
-
|
|
220
|
-
const addedItem = await cartService.addLineItems(data.cart_id, [
|
|
221
|
-
{
|
|
222
|
-
variant_id: rewardItem.variant_id,
|
|
223
|
-
quantity: rewardItem.quantity,
|
|
224
|
-
title: product?.title || "Reward Item",
|
|
225
|
-
unit_price: 0,
|
|
226
|
-
metadata: rewardItem.metadata,
|
|
227
|
-
},
|
|
228
|
-
]);
|
|
229
|
-
addedItems.push(addedItem);
|
|
230
|
-
} catch (error) {
|
|
231
|
-
console.error(`Failed to add reward item:`, error);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return new StepResponse(
|
|
236
|
-
{ rewardItemsAdded: addedItems },
|
|
237
|
-
{ cart_id: data.cart_id, added_items: addedItems },
|
|
238
|
-
);
|
|
239
|
-
},
|
|
240
|
-
async (compensationData) => {
|
|
241
|
-
// Compensation: Remove added reward items if workflow fails
|
|
242
|
-
if (!compensationData || !compensationData.added_items) return;
|
|
243
|
-
|
|
244
|
-
const cartService = container.resolve(Modules.CART);
|
|
245
|
-
|
|
246
|
-
for (const item of compensationData.added_items) {
|
|
247
|
-
try {
|
|
248
|
-
await cartService.deleteLineItems([item.id]);
|
|
249
|
-
} catch (error) {
|
|
250
|
-
console.error(
|
|
251
|
-
`Failed to remove reward item during compensation:`,
|
|
252
|
-
error,
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
export const applyBuyXGetYToCartWorkflow = createWorkflow(
|
|
260
|
-
"apply-buy-x-get-y-to-cart",
|
|
261
|
-
(data: ApplyBuyXGetYInput) => {
|
|
262
|
-
const result = applyBuyXGetYToCartStep(data);
|
|
263
|
-
|
|
264
|
-
return new WorkflowResponse(result);
|
|
265
|
-
},
|
|
266
|
-
);
|