@lodashventure/medusa-campaign 1.5.18 → 1.5.20

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.
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.config = void 0;
4
- exports.default = handleCartUpdated;
5
- async function handleCartUpdated({ event: { data }, }) {
6
- console.info(`[Campaign] Buy X Get Y workflow disabled. Skipping reward calculation for cart ${data.id}`);
7
- }
8
4
  exports.config = {
9
5
  event: [
10
6
  "cart.updated",
@@ -14,4 +10,4 @@ exports.config = {
14
10
  "cart-line-item.deleted",
15
11
  ],
16
12
  };
17
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FydC11cGRhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3N1YnNjcmliZXJzL2NhcnQtdXBkYXRlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxvQ0FNQztBQU5jLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxFQUM5QyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FDZ0I7SUFDL0IsT0FBTyxDQUFDLElBQUksQ0FDVixrRkFBa0YsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUM1RixDQUFDO0FBQ0osQ0FBQztBQUVZLFFBQUEsTUFBTSxHQUFxQjtJQUN0QyxLQUFLLEVBQUU7UUFDTCxjQUFjO1FBQ2QsY0FBYztRQUNkLHdCQUF3QjtRQUN4Qix3QkFBd0I7UUFDeEIsd0JBQXdCO0tBQ3pCO0NBQ0YsQ0FBQyJ9
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FydC11cGRhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3N1YnNjcmliZXJzL2NhcnQtdXBkYXRlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFYSxRQUFBLE1BQU0sR0FBcUI7SUFDdEMsS0FBSyxFQUFFO1FBQ0wsY0FBYztRQUNkLGNBQWM7UUFDZCx3QkFBd0I7UUFDeEIsd0JBQXdCO1FBQ3hCLHdCQUF3QjtLQUN6QjtDQUNGLENBQUMifQ==
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JkZXItcGxhY2VkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3N1YnNjcmliZXJzL29yZGVyLXBsYWNlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSx1Q0FtREM7QUF0REQsMEdBQXVHO0FBQ3ZHLDRHQUF5RztBQUUxRixLQUFLLFVBQVUsb0JBQW9CLENBQUMsRUFDakQsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLEdBQ2dCO0lBQy9CLElBQUksQ0FBQztRQUNILHlDQUF5QztRQUN6QyxJQUFJLENBQUM7WUFDSCxNQUFNLDJEQUE0QixDQUFDLEdBQUcsQ0FBQztnQkFDckMsS0FBSyxFQUFFO29CQUNMLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRTtpQkFDbEI7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQ1gsa0VBQWtFLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFDNUUsS0FBSyxDQUNOLENBQUM7WUFDRixPQUFPLENBQUMsS0FBSyxDQUNYLDJCQUEyQixFQUMzQixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDekQsQ0FBQztRQUNKLENBQUM7UUFFRCxtREFBbUQ7UUFDbkQsSUFBSSxDQUFDO1lBQ0gsTUFBTSx5REFBMkIsQ0FBQyxHQUFHLENBQUM7Z0JBQ3BDLEtBQUssRUFBRTtvQkFDTCxRQUFRLEVBQUUsSUFBSSxDQUFDLEVBQUU7aUJBQ2xCO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsS0FBSyxDQUNYLHlEQUF5RCxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQ25FLEtBQUssQ0FDTixDQUFDO1lBQ0YsT0FBTyxDQUFDLEtBQUssQ0FDWCwyQkFBMkIsRUFDM0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQ3pELENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixPQUFPLENBQUMsS0FBSyxDQUNYLHlEQUF5RCxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQ25FLEtBQUssQ0FDTixDQUFDO1FBQ0YsT0FBTyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEQsT0FBTyxDQUFDLEtBQUssQ0FDWCwyQkFBMkIsRUFDM0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQ3pELENBQUM7UUFDRiwyQ0FBMkM7SUFDN0MsQ0FBQztBQUNILENBQUM7QUFFWSxRQUFBLE1BQU0sR0FBcUI7SUFDdEMsS0FBSyxFQUFFLGNBQWM7Q0FDdEIsQ0FBQyJ9
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.applyBuyXGetYToCartWorkflow = exports.updatePromotionUsageWorkflow = exports.updateCustomFlashSaleWorkflow = exports.createCustomFlashSaleWorkflow = exports.createCustomCampaignWorkflow = void 0;
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtGQUE2SjtBQUFwSiw0SUFBQSw0QkFBNEIsT0FBQTtBQUFFLDZJQUFBLDRCQUE0QixPQUFpQztBQUNwRyxpR0FBZ0c7QUFBdkYsOElBQUEsNkJBQTZCLE9BQUE7QUFDdEMsK0ZBQThGO0FBQXJGLDRJQUFBLDRCQUE0QixPQUFBO0FBQ3JDLHlGQUF3RjtBQUEvRSwwSUFBQSwyQkFBMkIsT0FBQTtBQUNwQywrRkFBOEY7QUFBckYsNElBQUEsNEJBQTRCLE9BQUE7QUFDckMsK0ZBQThGO0FBQXJGLDRJQUFBLDRCQUE0QixPQUFBIn0=
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtGQUE2SjtBQUFwSiw0SUFBQSw0QkFBNEIsT0FBQTtBQUFFLDZJQUFBLDRCQUE0QixPQUFpQztBQUNwRyxpR0FBZ0c7QUFBdkYsOElBQUEsNkJBQTZCLE9BQUE7QUFDdEMsK0ZBQThGO0FBQXJGLDRJQUFBLDRCQUE0QixPQUFBO0FBQ3JDLCtGQUE4RjtBQUFyRiw0SUFBQSw0QkFBNEIsT0FBQTtBQUNyQywrRkFBOEY7QUFBckYsNElBQUEsNEJBQTRCLE9BQUEifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodashventure/medusa-campaign",
3
- "version": "1.5.18",
3
+ "version": "1.5.20",
4
4
  "description": "A starter for Medusa plugins.",
5
5
  "author": "Medusa (https://medusajs.com)",
6
6
  "license": "MIT",
@@ -1,12 +1,4 @@
1
- import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework";
2
-
3
- export default async function handleCartUpdated({
4
- event: { data },
5
- }: SubscriberArgs<{ id: string }>) {
6
- console.info(
7
- `[Campaign] Buy X Get Y workflow disabled. Skipping reward calculation for cart ${data.id}`,
8
- );
9
- }
1
+ import type { SubscriberConfig } from "@medusajs/framework";
10
2
 
11
3
  export const config: SubscriberConfig = {
12
4
  event: [
@@ -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}:`,
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbHlCdXlYR2V0WVRvQ2FydFdvcmtmbG93LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9idXkteC1nZXQteS9hcHBseUJ1eVhHZXRZVG9DYXJ0V29ya2Zsb3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQWdEO0FBQ2hELHFEQUdtQztBQUNuQyxxRUFLMkM7QUFDM0MscUVBQXdFO0FBRXhFLGdHQUEyRjtBQWtCM0YsTUFBTSx3QkFBd0IsR0FBRyxHQUFRLEVBQUU7SUFDekMsTUFBTSxTQUFTLEdBQUcsbUJBQW1CLENBQUM7SUFFdEMsSUFBSSxDQUFDO1FBQ0gsT0FBTyxxQkFBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE1BQU0sU0FBUyxHQUNiLE9BQVEscUJBQWlCLEVBQUUsZUFBZSxLQUFLLFVBQVU7WUFDeEQscUJBQWlCLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRWhELElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxPQUFPLHFCQUFTLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7UUFFRCxNQUFNLEdBQUcsQ0FBQztJQUNaLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLHVCQUF1QixHQUFHLElBQUEsMEJBQVUsRUFLeEMsZ0NBQWdDLEVBQ2hDLEtBQUssRUFBRSxJQUF3QixFQUFFLEVBQUU7SUFDakMsTUFBTSwyQkFBMkIsR0FDL0IscUJBQVMsQ0FBQyxPQUFPLENBQThCLHlDQUFzQixDQUFDLENBQUM7SUFDekUsTUFBTSxXQUFXLEdBQUcscUJBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BELE1BQU0sY0FBYyxHQUFHLHFCQUFTLENBQUMsT0FBTyxDQUFDLGVBQU8s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
@@ -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
- );