@devx-commerce/plugin-discounts-svaraa 0.0.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/.medusa/server/src/admin/index.js +20 -0
  2. package/.medusa/server/src/admin/index.mjs +21 -0
  3. package/.medusa/server/src/api/admin/discounts/freebie-rules/[id]/route.js +75 -0
  4. package/.medusa/server/src/api/admin/discounts/freebie-rules/route.js +73 -0
  5. package/.medusa/server/src/api/admin/discounts/middlewares.js +113 -0
  6. package/.medusa/server/src/api/admin/discounts/price-rules/[id]/codes/export/route.js +41 -0
  7. package/.medusa/server/src/api/admin/discounts/price-rules/[id]/codes/route.js +20 -0
  8. package/.medusa/server/src/api/admin/discounts/price-rules/[id]/route.js +50 -0
  9. package/.medusa/server/src/api/admin/discounts/price-rules/bulk/[id]/add-more-codes/route.js +34 -0
  10. package/.medusa/server/src/api/admin/discounts/price-rules/bulk/route.js +33 -0
  11. package/.medusa/server/src/api/admin/discounts/price-rules/route.js +47 -0
  12. package/.medusa/server/src/api/admin/discounts/validators.js +649 -0
  13. package/.medusa/server/src/api/admin/plugin/route.js +7 -0
  14. package/.medusa/server/src/api/middlewares.js +14 -0
  15. package/.medusa/server/src/api/store/discounts/apply/route.js +24 -0
  16. package/.medusa/server/src/api/store/discounts/apply-freebie/route.js +20 -0
  17. package/.medusa/server/src/api/store/discounts/auto-apply/route.js +125 -0
  18. package/.medusa/server/src/api/store/discounts/cart-eligible-coupons/[cart_id]/route.js +19 -0
  19. package/.medusa/server/src/api/store/discounts/middlewares.js +49 -0
  20. package/.medusa/server/src/api/store/discounts/offers-on-product/[variant_id]/route.js +19 -0
  21. package/.medusa/server/src/api/store/discounts/price-rules/route.js +20 -0
  22. package/.medusa/server/src/api/store/discounts/remove/route.js +21 -0
  23. package/.medusa/server/src/api/store/plugin/route.js +7 -0
  24. package/.medusa/server/src/index.js +18 -0
  25. package/.medusa/server/src/jobs/price-rule-status-updates.js +80 -0
  26. package/.medusa/server/src/lib/api-response.js +42 -0
  27. package/.medusa/server/src/lib/utils.js +10 -0
  28. package/.medusa/server/src/links/mtm-freebie-rule-with-customers.js +16 -0
  29. package/.medusa/server/src/links/mtm-freebie-rule-with-products-categories.js +16 -0
  30. package/.medusa/server/src/links/mtm-freebie-rule-with-products-variants.js +18 -0
  31. package/.medusa/server/src/links/mtm-price-rule-with-customers.js +16 -0
  32. package/.medusa/server/src/links/mtm-price-rule-with-products-categories.js +16 -0
  33. package/.medusa/server/src/links/mtm-price-rule-with-products-variants.js +16 -0
  34. package/.medusa/server/src/modules/discounts/index.js +13 -0
  35. package/.medusa/server/src/modules/discounts/migrations/Migration20250526174351.js +21 -0
  36. package/.medusa/server/src/modules/discounts/migrations/Migration20250527074936.js +14 -0
  37. package/.medusa/server/src/modules/discounts/migrations/Migration20250527104919.js +14 -0
  38. package/.medusa/server/src/modules/discounts/migrations/Migration20250527113947.js +14 -0
  39. package/.medusa/server/src/modules/discounts/migrations/Migration20250529123956.js +14 -0
  40. package/.medusa/server/src/modules/discounts/migrations/Migration20250602052234.js +14 -0
  41. package/.medusa/server/src/modules/discounts/migrations/Migration20250602052239.js +14 -0
  42. package/.medusa/server/src/modules/discounts/migrations/Migration20250602165037.js +16 -0
  43. package/.medusa/server/src/modules/discounts/migrations/Migration20250602194000.js +130 -0
  44. package/.medusa/server/src/modules/discounts/migrations/Migration20250603053221.js +16 -0
  45. package/.medusa/server/src/modules/discounts/migrations/Migration20250604162727.js +14 -0
  46. package/.medusa/server/src/modules/discounts/migrations/Migration20250604162741.js +14 -0
  47. package/.medusa/server/src/modules/discounts/migrations/Migration20250604175305.js +15 -0
  48. package/.medusa/server/src/modules/discounts/migrations/Migration20250605161922.js +14 -0
  49. package/.medusa/server/src/modules/discounts/migrations/Migration20250605162116.js +14 -0
  50. package/.medusa/server/src/modules/discounts/migrations/Migration20250605164908.js +14 -0
  51. package/.medusa/server/src/modules/discounts/migrations/Migration20250610063653.js +14 -0
  52. package/.medusa/server/src/modules/discounts/migrations/Migration20250611105345.js +14 -0
  53. package/.medusa/server/src/modules/discounts/migrations/Migration20250611105356.js +14 -0
  54. package/.medusa/server/src/modules/discounts/migrations/Migration20250617113007.js +14 -0
  55. package/.medusa/server/src/modules/discounts/models/discount-code.js +20 -0
  56. package/.medusa/server/src/modules/discounts/models/freebie-rule.js +27 -0
  57. package/.medusa/server/src/modules/discounts/models/price-rule.js +53 -0
  58. package/.medusa/server/src/modules/discounts/service.js +98 -0
  59. package/.medusa/server/src/workflows/discount/add-more-code-in-price-rule/index.js +28 -0
  60. package/.medusa/server/src/workflows/discount/apply-coupon/index.js +41 -0
  61. package/.medusa/server/src/workflows/discount/apply-coupon/steps/apply-coupon-step-backup.js +245 -0
  62. package/.medusa/server/src/workflows/discount/apply-coupon/steps/apply-coupon-step.js +244 -0
  63. package/.medusa/server/src/workflows/discount/apply-coupon/steps/generate-adjustment-line-item.js +28 -0
  64. package/.medusa/server/src/workflows/discount/apply-coupon/steps/validate-coupon-step.js +212 -0
  65. package/.medusa/server/src/workflows/discount/apply-freebie/index.js +31 -0
  66. package/.medusa/server/src/workflows/discount/apply-freebie/steps/add-freebie-items-to-cart.js +212 -0
  67. package/.medusa/server/src/workflows/discount/apply-freebie/steps/remove-freebie-from-cart.js +16 -0
  68. package/.medusa/server/src/workflows/discount/auto-apply-coupon/index.js +10 -0
  69. package/.medusa/server/src/workflows/discount/auto-apply-coupon/steps/auto-apply-coupon.js +81 -0
  70. package/.medusa/server/src/workflows/discount/calculate-coupon-discount/index.js +74 -0
  71. package/.medusa/server/src/workflows/discount/create-bulk-discount/index.js +46 -0
  72. package/.medusa/server/src/workflows/discount/create-bulk-discount/steps/add-bulk-codes-to-rule.js +84 -0
  73. package/.medusa/server/src/workflows/discount/create-discount-code/index.js +10 -0
  74. package/.medusa/server/src/workflows/discount/create-discount-code/steps/create-discount-code-step.js +20 -0
  75. package/.medusa/server/src/workflows/discount/create-discount-price-rule/index.js +56 -0
  76. package/.medusa/server/src/workflows/discount/create-discount-price-rule/steps/create-discount-price-rule-step.js +58 -0
  77. package/.medusa/server/src/workflows/discount/create-discount-price-rule/steps/validate-customer-exists.js +21 -0
  78. package/.medusa/server/src/workflows/discount/create-freebie-rule/index.js +44 -0
  79. package/.medusa/server/src/workflows/discount/create-freebie-rule/steps/create-freebie-rule-step.js +64 -0
  80. package/.medusa/server/src/workflows/discount/export-codes/index.js +14 -0
  81. package/.medusa/server/src/workflows/discount/export-codes/steps/export-codes-step.js +116 -0
  82. package/.medusa/server/src/workflows/discount/get-cart-eligible-coupons/index.js +15 -0
  83. package/.medusa/server/src/workflows/discount/get-cart-eligible-coupons/step/get-cart-eligible-coupon.js +39 -0
  84. package/.medusa/server/src/workflows/discount/get-product-offers/index.js +25 -0
  85. package/.medusa/server/src/workflows/discount/get-product-offers/step/calculate-product-offers.js +53 -0
  86. package/.medusa/server/src/workflows/discount/index.js +28 -0
  87. package/.medusa/server/src/workflows/discount/remove-coupon/index.js +18 -0
  88. package/.medusa/server/src/workflows/discount/remove-coupon/step/remove-coupon-step.js +32 -0
  89. package/.medusa/server/src/workflows/discount/steps/validate-cart-exists.js +22 -0
  90. package/.medusa/server/src/workflows/discount/steps/validate-discount-code-exists.js +20 -0
  91. package/.medusa/server/src/workflows/discount/steps/validate-freebie-code-exists.js +16 -0
  92. package/.medusa/server/src/workflows/discount/steps/validate-same-prefix-rule-exists.js +20 -0
  93. package/.medusa/server/src/workflows/discount/update-discount-price-rule/index.js +42 -0
  94. package/.medusa/server/src/workflows/discount/update-discount-price-rule/steps/update-discount-price-rule-step.js +160 -0
  95. package/.medusa/server/src/workflows/discount/update-discount-price-rule/steps/validate-discount-price-rule-update-step.js +175 -0
  96. package/.medusa/server/src/workflows/discount/update-freebie-price-rule/index.js +44 -0
  97. package/.medusa/server/src/workflows/discount/update-freebie-price-rule/steps/update-freebie-price-rule-step.js +201 -0
  98. package/.medusa/server/src/workflows/discount/update-freebie-price-rule/steps/validate-freebie-rule-update-step.js +44 -0
  99. package/.medusa/server/src/workflows/index.js +18 -0
  100. package/.medusa/server/src/workflows/product/steps/validate-product-category-exists.js +26 -0
  101. package/.medusa/server/src/workflows/product/steps/validate-product-exists.js +28 -0
  102. package/.medusa/server/src/workflows/product/steps/validate-product-variant-exists.js +26 -0
  103. package/.medusa/server/src/workflows/steps/throw-error-step.js +9 -0
  104. package/README.md +64 -0
  105. package/package.json +87 -0
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const utils_1 = require("@medusajs/framework/utils");
19
+ const discount_code_1 = __importDefault(require("./models/discount-code"));
20
+ const freebie_rule_1 = __importDefault(require("./models/freebie-rule"));
21
+ const price_rule_1 = __importDefault(require("./models/price-rule"));
22
+ class DiscountService extends (0, utils_1.MedusaService)({
23
+ DiscountPriceRule: price_rule_1.default,
24
+ DiscountCode: discount_code_1.default,
25
+ FreebieRule: freebie_rule_1.default,
26
+ }) {
27
+ /**
28
+ * Increments the code_count field of a price rule by the specified count
29
+ * @param priceRuleId - The ID of the price rule to update
30
+ * @param count - The number to increment the code_count by
31
+ */
32
+ async incrementCodeCount(priceRuleId, count, context = {}) {
33
+ if (!context?.manager) {
34
+ throw new Error("Transaction manager is required");
35
+ }
36
+ const em = context.manager;
37
+ // Use raw SQL to increment the code_count field
38
+ await em.getConnection().execute(`
39
+ UPDATE discount_price_rule
40
+ SET code_count = code_count + ?
41
+ WHERE id = ?
42
+ `, [count, priceRuleId]);
43
+ }
44
+ // @ts-ignore
45
+ async listDiscountPriceRules(filters, config, sharedContext) {
46
+ delete filters.context;
47
+ const priceRules = await super.listDiscountPriceRules(filters, config, sharedContext);
48
+ return await Promise.all(priceRules.map(async (priceRule) => {
49
+ if (priceRule.prefix)
50
+ return priceRule;
51
+ const [{ code }] = await this.listDiscountCodes({
52
+ price_rule_id: priceRule.id,
53
+ });
54
+ return {
55
+ ...priceRule,
56
+ discount_code: code,
57
+ };
58
+ }));
59
+ }
60
+ // @ts-ignore
61
+ async listAndCountDiscountPriceRules(filters, config, sharedContext) {
62
+ delete filters.context;
63
+ const [priceRules, metadata] = await super.listAndCountDiscountPriceRules(filters, config, sharedContext);
64
+ const updatedPriceRules = await Promise.all(priceRules.map(async (priceRule) => {
65
+ if (priceRule.prefix)
66
+ return priceRule;
67
+ const [{ code }] = await this.listDiscountCodes({
68
+ price_rule_id: priceRule.id,
69
+ });
70
+ return {
71
+ ...priceRule,
72
+ discount_code: code,
73
+ };
74
+ }));
75
+ return [updatedPriceRules, metadata];
76
+ }
77
+ }
78
+ __decorate([
79
+ (0, utils_1.InjectManager)(),
80
+ __param(2, (0, utils_1.MedusaContext)()),
81
+ __metadata("design:type", Function),
82
+ __metadata("design:paramtypes", [String, Number, Object]),
83
+ __metadata("design:returntype", Promise)
84
+ ], DiscountService.prototype, "incrementCodeCount", null);
85
+ __decorate([
86
+ __param(2, (0, utils_1.MedusaContext)()),
87
+ __metadata("design:type", Function),
88
+ __metadata("design:paramtypes", [Object, Object, Object]),
89
+ __metadata("design:returntype", Promise)
90
+ ], DiscountService.prototype, "listDiscountPriceRules", null);
91
+ __decorate([
92
+ __param(2, (0, utils_1.MedusaContext)()),
93
+ __metadata("design:type", Function),
94
+ __metadata("design:paramtypes", [Object, Object, Object]),
95
+ __metadata("design:returntype", Promise)
96
+ ], DiscountService.prototype, "listAndCountDiscountPriceRules", null);
97
+ exports.default = DiscountService;
98
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2Rpc2NvdW50cy9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQ0EscURBSW1DO0FBR25DLDJFQUFrRDtBQUNsRCx5RUFBZ0Q7QUFDaEQscUVBQStFO0FBRS9FLE1BQU0sZUFBZ0IsU0FBUSxJQUFBLHFCQUFhLEVBQUM7SUFDMUMsaUJBQWlCLEVBQWpCLG9CQUFpQjtJQUNqQixZQUFZLEVBQVosdUJBQVk7SUFDWixXQUFXLEVBQVgsc0JBQVc7Q0FDWixDQUFDO0lBQ0E7Ozs7T0FJRztJQUVHLEFBQU4sS0FBSyxDQUFDLGtCQUFrQixDQUN0QixXQUFtQixFQUNuQixLQUFhLEVBQ0ksVUFBa0MsRUFBRTtRQUVyRCxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDO1lBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBRUQsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUUzQixnREFBZ0Q7UUFDaEQsTUFBTSxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUMsT0FBTyxDQUM5Qjs7OztPQUlDLEVBQ0QsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQ3JCLENBQUM7SUFDSixDQUFDO0lBRUQsYUFBYTtJQUNQLEFBQU4sS0FBSyxDQUFDLHNCQUFzQixDQUMxQixPQUFhLEVBQ2IsTUFBb0MsRUFDbkIsYUFBbUM7UUFFcEQsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDO1FBRXZCLE1BQU0sVUFBVSxHQUFHLE1BQU0sS0FBSyxDQUFDLHNCQUFzQixDQUNuRCxPQUFPLEVBQ1AsTUFBTSxFQUNOLGFBQWEsQ0FDZCxDQUFDO1FBRUYsT0FBTyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQ3RCLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFO1lBQ2pDLElBQUksU0FBUyxDQUFDLE1BQU07Z0JBQUUsT0FBTyxTQUFTLENBQUM7WUFFdkMsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztnQkFDOUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxFQUFFO2FBQzVCLENBQUMsQ0FBQztZQUVILE9BQU87Z0JBQ0wsR0FBRyxTQUFTO2dCQUNaLGFBQWEsRUFBRSxJQUFJO2FBQ3BCLENBQUM7UUFDSixDQUFDLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQztJQUVELGFBQWE7SUFDUCxBQUFOLEtBQUssQ0FBQyw4QkFBOEIsQ0FDbEMsT0FBYSxFQUNiLE1BQW9DLEVBQ25CLGFBQW1DO1FBRXBELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUV2QixNQUFNLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxHQUFHLE1BQU0sS0FBSyxDQUFDLDhCQUE4QixDQUN2RSxPQUFPLEVBQ1AsTUFBTSxFQUNOLGFBQWEsQ0FDZCxDQUFDO1FBRUYsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQ3pDLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUFFO1lBQ2pDLElBQUksU0FBUyxDQUFDLE1BQU07Z0JBQUUsT0FBTyxTQUFTLENBQUM7WUFFdkMsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztnQkFDOUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxFQUFFO2FBQzVCLENBQUMsQ0FBQztZQUVILE9BQU87Z0JBQ0wsR0FBRyxTQUFTO2dCQUNaLGFBQWEsRUFBRSxJQUFJO2FBQ3BCLENBQUM7UUFDSixDQUFDLENBQUMsQ0FDSCxDQUFDO1FBRUYsT0FBTyxDQUFDLGlCQUFpQixFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7Q0FDRjtBQW5GTztJQURMLElBQUEscUJBQWEsR0FBRTtJQUliLFdBQUEsSUFBQSxxQkFBYSxHQUFFLENBQUE7Ozs7eURBaUJqQjtBQUdLO0lBR0gsV0FBQSxJQUFBLHFCQUFhLEdBQUUsQ0FBQTs7Ozs2REF3QmpCO0FBR0s7SUFHSCxXQUFBLElBQUEscUJBQWEsR0FBRSxDQUFBOzs7O3FFQTBCakI7QUFHSCxrQkFBZSxlQUFlLENBQUMifQ==
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addMoreCodesToPriceRuleWorkflow = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
6
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
7
+ const throw_error_step_1 = require("../../steps/throw-error-step");
8
+ const add_bulk_codes_to_rule_1 = require("../create-bulk-discount/steps/add-bulk-codes-to-rule");
9
+ exports.addMoreCodesToPriceRuleWorkflow = (0, workflows_sdk_1.createWorkflow)("add-more-codes-to-price-rule", (input) => {
10
+ const validate = (0, workflows_sdk_1.createHook)("validate", { input });
11
+ const { data: priceRules } = (0, core_flows_1.useQueryGraphStep)({
12
+ entity: "discount_price_rule",
13
+ fields: ["prefix", "id"],
14
+ filters: { id: input.price_rule_id },
15
+ options: { throwIfKeyNotFound: true },
16
+ });
17
+ (0, workflows_sdk_1.when)("throw-error-if-prefix-rule-does-not-exists", priceRules, (priceRules) => !(0, utils_1.isDefined)(priceRules?.[0]?.prefix)).then(() => {
18
+ (0, throw_error_step_1.throwErrorStep)({
19
+ errorMessage: priceRules[0].id,
20
+ });
21
+ });
22
+ (0, add_bulk_codes_to_rule_1.addBulkCodesToRuleStep)({
23
+ priceRuleId: priceRules[0].id,
24
+ codeCountToAdd: input.count,
25
+ });
26
+ return new workflows_sdk_1.WorkflowResponse({ message: "Codes addition to price rule started" }, { hooks: [validate] });
27
+ });
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2Rpc2NvdW50L2FkZC1tb3JlLWNvZGUtaW4tcHJpY2UtcnVsZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxREFBc0Q7QUFDdEQscUVBSzJDO0FBQzNDLDREQUFnRTtBQUdoRSxtRUFBOEQ7QUFDOUQsaUdBQThGO0FBRWpGLFFBQUEsK0JBQStCLEdBQUcsSUFBQSw4QkFBYyxFQUMzRCw4QkFBOEIsRUFDOUIsQ0FDRSxLQUVDLEVBQ0QsRUFBRTtJQUNGLE1BQU0sUUFBUSxHQUFHLElBQUEsMEJBQVUsRUFBQyxVQUFVLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBRW5ELE1BQU0sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEdBQUcsSUFBQSw4QkFBaUIsRUFBQztRQUM3QyxNQUFNLEVBQUUscUJBQXFCO1FBQzdCLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUM7UUFDeEIsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxhQUFhLEVBQUU7UUFDcEMsT0FBTyxFQUFFLEVBQUUsa0JBQWtCLEVBQUUsSUFBSSxFQUFFO0tBQ3RDLENBQUMsQ0FBQztJQUVILElBQUEsb0JBQUksRUFDRiw0Q0FBNEMsRUFDNUMsVUFBVSxFQUNWLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUEsaUJBQVMsRUFBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FDcEQsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO1FBQ1YsSUFBQSxpQ0FBYyxFQUFDO1lBQ2IsWUFBWSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1NBQy9CLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSwrQ0FBc0IsRUFBQztRQUNyQixXQUFXLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDN0IsY0FBYyxFQUFFLEtBQUssQ0FBQyxLQUFLO0tBQzVCLENBQUMsQ0FBQztJQUVILE9BQU8sSUFBSSxnQ0FBZ0IsQ0FDekIsRUFBRSxPQUFPLEVBQUUsc0NBQXNDLEVBQUUsRUFDbkQsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQVUsRUFBRSxDQUMvQixDQUFDO0FBQ0osQ0FBQyxDQUNGLENBQUMifQ==
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.applyCouponWorkflow = void 0;
7
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
8
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
9
+ const calculate_coupon_discount_1 = require("../calculate-coupon-discount");
10
+ const remove_coupon_step_1 = require("../remove-coupon/step/remove-coupon-step");
11
+ const generate_adjustment_line_item_1 = __importDefault(require("./steps/generate-adjustment-line-item"));
12
+ exports.applyCouponWorkflow = (0, workflows_sdk_1.createWorkflow)("apply-coupon", (input) => {
13
+ const response = calculate_coupon_discount_1.calculateCouponDiscountWorkflow.runAsStep({
14
+ input: {
15
+ code: input.code,
16
+ cart_id: input.cart_id,
17
+ customerId: input.customerId,
18
+ },
19
+ });
20
+ const { data: carts } = (0, core_flows_1.useQueryGraphStep)({
21
+ entity: "cart",
22
+ fields: [
23
+ "*",
24
+ "items.*",
25
+ "items.variant.*",
26
+ "items.variant.prices.*",
27
+ "items.variant.extended_product_variants.compare_at_price",
28
+ ],
29
+ filters: { id: input.cart_id },
30
+ options: { throwIfKeyNotFound: true },
31
+ }).config({ name: "get-cart" });
32
+ const cart = (0, workflows_sdk_1.transform)({ carts }, ({ carts }) => carts[0]);
33
+ (0, remove_coupon_step_1.removeCouponStep)({ cart });
34
+ (0, generate_adjustment_line_item_1.default)(response.adjustmentLineItems);
35
+ return new workflows_sdk_1.WorkflowResponse({
36
+ discount: response.discount,
37
+ isApplied: response.isApplied,
38
+ message: response.message,
39
+ });
40
+ });
41
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2Rpc2NvdW50L2FwcGx5LWNvdXBvbi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxxRUFJMkM7QUFDM0MsNERBQWdFO0FBR2hFLDRFQUErRTtBQUMvRSxpRkFBNEU7QUFDNUUsMEdBQStFO0FBRWxFLFFBQUEsbUJBQW1CLEdBQUcsSUFBQSw4QkFBYyxFQUMvQyxjQUFjLEVBQ2QsQ0FBQyxLQUE2QixFQUFFLEVBQUU7SUFDaEMsTUFBTSxRQUFRLEdBQUcsMkRBQStCLENBQUMsU0FBUyxDQUFDO1FBQ3pELEtBQUssRUFBRTtZQUNMLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtZQUNoQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87WUFDdEIsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO1NBQzdCO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFBLDhCQUFpQixFQUFDO1FBQ3hDLE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFO1lBQ04sR0FBRztZQUNILFNBQVM7WUFDVCxpQkFBaUI7WUFDakIsd0JBQXdCO1lBQ3hCLDBEQUEwRDtTQUMzRDtRQUNELE9BQU8sRUFBRSxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsT0FBTyxFQUFFO1FBQzlCLE9BQU8sRUFBRSxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRTtLQUN0QyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7SUFFaEMsTUFBTSxJQUFJLEdBQUcsSUFBQSx5QkFBUyxFQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUUzRCxJQUFBLHFDQUFnQixFQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUUzQixJQUFBLHVDQUEwQixFQUFDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBRXpELE9BQU8sSUFBSSxnQ0FBZ0IsQ0FBQztRQUMxQixRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVE7UUFDM0IsU0FBUyxFQUFFLFFBQVEsQ0FBQyxTQUFTO1FBQzdCLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTztLQUMxQixDQUFDLENBQUM7QUFDTCxDQUFDLENBQ0YsQ0FBQyJ9
@@ -0,0 +1,245 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyCouponStep = void 0;
4
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
5
+ const validators_1 = require("../../../../api/admin/discounts/validators");
6
+ exports.applyCouponStep = (0, workflows_sdk_1.createStep)("apply-coupon", async ({ priceRule, code, cart }, { container }) => {
7
+ const logger = container.resolve("logger");
8
+ logger.setLogLevel(process.env.LOG_LEVEL);
9
+ const { product_variants, product_categories } = priceRule;
10
+ let applicableCartLineItems = [...cart.items];
11
+ if (product_variants?.length) {
12
+ applicableCartLineItems = applicableCartLineItems.filter((item) => product_variants?.some((v) => v.id === item.variant_id));
13
+ }
14
+ if (product_categories?.length) {
15
+ applicableCartLineItems = applicableCartLineItems.filter((item) => product_categories?.some((v) => v.products?.some((p) => p.id === item.product_id)));
16
+ }
17
+ if (!priceRule.applicable_on_bundle) {
18
+ applicableCartLineItems = applicableCartLineItems.filter((item) => !item.metadata?.bundle_type);
19
+ }
20
+ const totalApplicableProductsQty = applicableCartLineItems.reduce((acc, item) => {
21
+ return acc + Number(item.quantity || 0);
22
+ }, 0);
23
+ let number_of_time_coupon_should_apply = Math.min(totalApplicableProductsQty, priceRule.usage_limit_per_cart_type ==
24
+ validators_1.DiscountUsageLimitPerCartType.Values.ONLY_ONCE
25
+ ? 1
26
+ : priceRule.usage_limit_per_cart_specific || Infinity);
27
+ const isMrp = priceRule.applies_on == validators_1.DiscountAppliesOn.Values.MRP;
28
+ const cartMrpTotal = applicableCartLineItems?.reduce((acc, item) => {
29
+ let variantListingPrice = item?.variant?.extended_product_variants?.compare_at_price;
30
+ const isBundle = !!item.metadata?.bundle_type;
31
+ return (acc +
32
+ Number(isBundle ? item.compare_at_unit_price : variantListingPrice) *
33
+ Number(item.quantity || 1));
34
+ }, 0);
35
+ const cartPriceTotal = applicableCartLineItems?.reduce((acc, item) => {
36
+ return acc + Number(item.unit_price) * Number(item.quantity || 1);
37
+ }, 0);
38
+ const cartTotal = isMrp ? cartMrpTotal : cartPriceTotal;
39
+ let totalDiscount = 0;
40
+ const cartService = container.resolve("cart");
41
+ switch (priceRule.type) {
42
+ case validators_1.DiscountType.Values.FIXED:
43
+ totalDiscount = Math.min(priceRule.get_flat_discount * number_of_time_coupon_should_apply, cartTotal);
44
+ await Promise.all(applicableCartLineItems?.map(async (item) => {
45
+ let variantListingPrice = item?.variant?.extended_product_variants?.compare_at_price;
46
+ const isBundle = !!item.metadata?.bundle_type;
47
+ let mrp = isBundle
48
+ ? item.compare_at_unit_price
49
+ : variantListingPrice;
50
+ const ratio = isMrp
51
+ ? Number((Number(mrp) / Number(cartMrpTotal)).toFixed(2))
52
+ : Number((Number(item.unit_price) / Number(cartPriceTotal)).toFixed(2));
53
+ const discount = ratio * totalDiscount;
54
+ await cartService.addLineItemAdjustments({
55
+ amount: discount,
56
+ code: code,
57
+ description: priceRule.title || priceRule.description || "Discount",
58
+ item_id: item.id,
59
+ promotion_id: priceRule.id,
60
+ });
61
+ }));
62
+ break;
63
+ case validators_1.DiscountType.Values.PERCENTAGE:
64
+ totalDiscount = Math.min((priceRule.get_percent * cartTotal) / 100, priceRule.max_discount || Infinity);
65
+ await Promise.all(applicableCartLineItems?.map(async (item) => {
66
+ let variantListingPrice = item?.variant?.extended_product_variants?.compare_at_price;
67
+ const isBundle = !!item.metadata?.bundle_type;
68
+ let mrp = isBundle
69
+ ? item.compare_at_unit_price
70
+ : variantListingPrice;
71
+ const ratio = isMrp
72
+ ? Number((Number(mrp) / Number(cartMrpTotal)).toFixed(2))
73
+ : Number((Number(item.unit_price) / Number(cartPriceTotal)).toFixed(2));
74
+ const discount = ratio * totalDiscount;
75
+ await cartService.addLineItemAdjustments({
76
+ amount: discount,
77
+ code: code,
78
+ description: priceRule.title || priceRule.description || "Discount",
79
+ item_id: item.id,
80
+ promotion_id: priceRule.id,
81
+ });
82
+ }));
83
+ break;
84
+ case validators_1.DiscountType.Values.BXGY:
85
+ // This is a “Buy X, Get Y Free” coupon.
86
+ // We first count how many items the customer has.
87
+ // For every (X + Y) items, they get Y items free.
88
+ // We always give the free items starting from the cheapest ones.
89
+ // Example 1: Buy 2, Get 1 free (B2G1), used once
90
+ // If the cart has 3 to 6 items, the customer gets 1 free item (the cheapest).
91
+ // Example 2: B2G1, used twice
92
+ // If the cart has 6 or 7 items, the customer gets 2 free items (the cheapest ones).
93
+ // Example 3: Buy 3, Get 2 free (B3G2), used once
94
+ // If the cart has 5 items, the customer gets 2 free items (the cheapest).
95
+ const totalEligibleQty = applicableCartLineItems.reduce((acc, item) => acc + Number(item.quantity || 0), 0);
96
+ const maxTimesCouponCanApply = Math.floor(totalEligibleQty / (priceRule.buy_x + priceRule.get_y));
97
+ const sortedByUnitPrice = applicableCartLineItems.sort((a, b) => {
98
+ const aPrice = isMrp
99
+ ? a.metadata?.bundle_type
100
+ ? Number(a.compare_at_unit_price)
101
+ : Number(a.variant.extended_product_variants.compare_at_price)
102
+ : Number(a.unit_price);
103
+ const bPrice = isMrp
104
+ ? b.metadata?.bundle_type
105
+ ? Number(b.compare_at_unit_price)
106
+ : Number(b.variant.extended_product_variants.compare_at_price)
107
+ : Number(b.unit_price);
108
+ return aPrice - bPrice;
109
+ });
110
+ const numberOfFreeItems = Math.min(priceRule.get_y * maxTimesCouponCanApply, totalEligibleQty);
111
+ let iterator = 0;
112
+ for (const item of sortedByUnitPrice) {
113
+ const t = Math.min(Number(item.quantity), numberOfFreeItems - iterator);
114
+ iterator += t;
115
+ totalDiscount += t * Number(item.unit_price);
116
+ await cartService.addLineItemAdjustments({
117
+ amount: t * Number(item.unit_price),
118
+ code,
119
+ description: priceRule.title || priceRule.description || "Discount",
120
+ item_id: item.id,
121
+ promotion_id: priceRule.id,
122
+ });
123
+ }
124
+ break;
125
+ case validators_1.DiscountType.Values.BXAY:
126
+ /* ────────────────────────────────────────────────────────────────────────────────────|
127
+ * Apply a “Buy X At Y” (BXAY) discount, which may fire multiple times per cart. |
128
+ * ────────────────────────────────────────────────────────────────────────────────────|
129
+ * Example A: limit = 1 (“only once”)
130
+ *
131
+ * Cart:
132
+ * - A: qty=1 @200 → units [200]
133
+ * - B: qty=4 @300 → units [300,300,300,300]
134
+ *
135
+ * buy_x = 2, at_y = 400, limit = 1
136
+ * totalQty = 5 → maxPossibleBundles = 2
137
+ * times = min(2,1) = 1
138
+ * unitsNeeded = 1 * 2 = 2
139
+ *
140
+ * Flatten & sort: [200,300,300,300,300] → select [200,300]
141
+ * sumPrices = 200 + 300 = 500
142
+ * bundleTotalPrice = 1 * 400 = 400
143
+ * totalBundleDiscount = 500 − 400 = 100
144
+ *
145
+ * Shares:
146
+ * - A: 200/500 = 0.4 → 0.4 * 100 = 40
147
+ * - B: 300/500 = 0.6 → 0.6 * 100 = 60
148
+ *
149
+ *
150
+ * Example B: limit = 2 (“twice”)
151
+ *
152
+ * Same cart & rule, but limit = 2
153
+ * totalQty = 5 → maxPossibleBundles = 2
154
+ * times = min(2,2) = 2
155
+ * unitsNeeded = 2 * 2 = 4
156
+ *
157
+ * Flatten & sort: [200,300,300,300,300] → select [200,300,300,300]
158
+ * sumPrices = 200 + 3*300 = 1100
159
+ * bundleTotalPrice = 2 * 400 = 800
160
+ * totalBundleDiscount = 1100 − 800 = 300
161
+ *
162
+ * Shares:
163
+ * - A: 200/1100 ≈ 0.1818 → ~300 * 0.1818 ≈ 54.55
164
+ * - B: 900/1100 ≈ 0.8182 → ~300 * 0.8182 ≈ 245.45
165
+ *
166
+ * You can extend this to any n by adjusting `limit`. The algorithm
167
+ * automatically picks the cheapest `n * buy_x` units and splits the
168
+ * discount proportionally.
169
+ */
170
+ // 1) Total times the bundle applies, and units per bundle
171
+ const unitsNeeded = number_of_time_coupon_should_apply;
172
+ logger.info("unitsNeeded: " + unitsNeeded);
173
+ const bxayTimes = Math.floor(number_of_time_coupon_should_apply / (priceRule.buy_x || 1));
174
+ logger.info("times: " + bxayTimes);
175
+ const units = [];
176
+ for (const item of applicableCartLineItems) {
177
+ const unitPrice = isMrp
178
+ ? item.metadata?.bundle_type
179
+ ? item.compare_at_unit_price
180
+ : item.variant.extended_product_variants.compare_at_price
181
+ : item.unit_price;
182
+ for (let i = 0; i < (Number(item.quantity) || 1); i++) {
183
+ units.push({ item, unitPrice: Number(unitPrice) });
184
+ }
185
+ }
186
+ // 3) Sort ascending by unitPrice
187
+ units.sort((a, b) => a.unitPrice - b.unitPrice);
188
+ // 4) Pick the cheapest `unitsNeeded` units
189
+ const selected = units.slice(0, unitsNeeded);
190
+ logger.info("selected: " + JSON.stringify(selected, null, 2));
191
+ // 5) Sum their original prices
192
+ const sumPrices = selected.reduce((sum, u) => sum + u.unitPrice, 0);
193
+ logger.info("sumPrices: " + sumPrices);
194
+ // 6) Compute total bundle price (you pay at_y per bundle)
195
+ const totalOfItemsAfterDiscount = priceRule.at_y * bxayTimes;
196
+ logger.info("totalOfItemsAfterDiscount: " + totalOfItemsAfterDiscount);
197
+ // 7) Total discount to allocate
198
+ const totalBundleDiscount = sumPrices - totalOfItemsAfterDiscount;
199
+ logger.info("totalBundleDiscount: " + totalBundleDiscount);
200
+ // 8) Group back by line-item to allocate proportionally
201
+ const lineBuckets = {};
202
+ for (const { item, unitPrice } of selected) {
203
+ if (!lineBuckets[item.id]) {
204
+ lineBuckets[item.id] = { sumPrices: 0 };
205
+ }
206
+ lineBuckets[item.id].sumPrices += unitPrice;
207
+ }
208
+ logger.info("lineBuckets: " + JSON.stringify(lineBuckets, null, 2));
209
+ // 9) For each line, compute its share and create one adjustment
210
+ let allocated = 0;
211
+ for (const [itemId, { sumPrices: lineSum }] of Object.entries(lineBuckets)) {
212
+ const share = lineSum / sumPrices;
213
+ const lineDiscount = Math.round(totalBundleDiscount * share * 100) / 100;
214
+ allocated += lineDiscount;
215
+ logger.info("line items: " +
216
+ {
217
+ amount: lineDiscount,
218
+ code,
219
+ description: priceRule.title || priceRule.description || "Discount",
220
+ item_id: itemId,
221
+ promotion_id: priceRule.id,
222
+ });
223
+ await cartService.addLineItemAdjustments({
224
+ amount: lineDiscount,
225
+ code,
226
+ description: priceRule.title || priceRule.description || "Discount",
227
+ item_id: itemId,
228
+ promotion_id: priceRule.id,
229
+ });
230
+ }
231
+ // 10) Track overall discount
232
+ totalDiscount += allocated;
233
+ break;
234
+ default:
235
+ logger.error("Discount type not supported", priceRule.type);
236
+ break;
237
+ }
238
+ return new workflows_sdk_1.StepResponse({
239
+ hasError: false,
240
+ isApplied: true,
241
+ discount: totalDiscount,
242
+ message: "Coupon Applied Successfully",
243
+ });
244
+ });
245
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbHktY291cG9uLXN0ZXAtYmFja3VwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9kaXNjb3VudC9hcHBseS1jb3Vwb24vc3RlcHMvYXBwbHktY291cG9uLXN0ZXAtYmFja3VwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQU9BLHFFQUE2RTtBQUU3RSwyRUFJb0Q7QUFxQnZDLFFBQUEsZUFBZSxHQUFHLElBQUEsMEJBQVUsRUFDdkMsY0FBYyxFQUNkLEtBQUssRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFhLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQzVELE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFM0MsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVUsQ0FBQyxDQUFDO0lBRTNDLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxrQkFBa0IsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUUzRCxJQUFJLHVCQUF1QixHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFOUMsSUFBSSxnQkFBZ0IsRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUM3Qix1QkFBdUIsR0FBRyx1QkFBdUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUNoRSxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUNuQyxDQUFDO0lBQ3pCLENBQUM7SUFFRCxJQUFJLGtCQUFrQixFQUFFLE1BQU0sRUFBRSxDQUFDO1FBQy9CLHVCQUF1QixHQUFHLHVCQUF1QixDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQ2hFLGtCQUFrQixF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