@xbstracts/medusa-coupons 0.0.1

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 (84) hide show
  1. package/.medusa/server/src/admin/index.js +3207 -0
  2. package/.medusa/server/src/admin/index.mjs +3253 -0
  3. package/.medusa/server/src/api/admin/coupon-products/[product_id]/entitlements/route.js +9 -0
  4. package/.medusa/server/src/api/admin/coupon-products/[product_id]/mirror-promotion/route.js +132 -0
  5. package/.medusa/server/src/api/admin/coupon-products/[product_id]/preview/route.js +28 -0
  6. package/.medusa/server/src/api/admin/coupon-products/[product_id]/route.js +18 -0
  7. package/.medusa/server/src/api/admin/coupon-products/[product_id]/variants/[variant_config_id]/route.js +14 -0
  8. package/.medusa/server/src/api/admin/coupon-products/[product_id]/variants/route.js +14 -0
  9. package/.medusa/server/src/api/admin/coupon-products/configs/[id]/route.js +53 -0
  10. package/.medusa/server/src/api/admin/coupon-products/configs/[id]/variants/[variant_config_id]/route.js +26 -0
  11. package/.medusa/server/src/api/admin/coupon-products/configs/[id]/variants/route.js +27 -0
  12. package/.medusa/server/src/api/admin/coupon-products/configs/route.js +36 -0
  13. package/.medusa/server/src/api/admin/coupon-products/entitlements/[id]/cancel/route.js +15 -0
  14. package/.medusa/server/src/api/admin/coupon-products/entitlements/[id]/redeem/route.js +15 -0
  15. package/.medusa/server/src/api/admin/coupon-products/entitlements/[id]/route.js +16 -0
  16. package/.medusa/server/src/api/admin/coupon-products/entitlements/route.js +22 -0
  17. package/.medusa/server/src/api/admin/coupon-products/options/route.js +9 -0
  18. package/.medusa/server/src/api/admin/coupon-products/products/route.js +16 -0
  19. package/.medusa/server/src/api/admin/coupon-products/route.js +13 -0
  20. package/.medusa/server/src/api/admin/coupon-products/uploads/route.js +7 -0
  21. package/.medusa/server/src/api/coupon-product-routes.js +546 -0
  22. package/.medusa/server/src/api/entitlement-utils.js +90 -0
  23. package/.medusa/server/src/api/media-upload.js +57 -0
  24. package/.medusa/server/src/api/middlewares.js +92 -0
  25. package/.medusa/server/src/api/product-utils.js +304 -0
  26. package/.medusa/server/src/api/promotion-code-resolver.js +225 -0
  27. package/.medusa/server/src/api/seller-utils.js +101 -0
  28. package/.medusa/server/src/api/utils.js +25 -0
  29. package/.medusa/server/src/api/validators.js +199 -0
  30. package/.medusa/server/src/api/vendor/coupon-products/[product_id]/entitlements/route.js +9 -0
  31. package/.medusa/server/src/api/vendor/coupon-products/[product_id]/route.js +18 -0
  32. package/.medusa/server/src/api/vendor/coupon-products/[product_id]/variants/[variant_config_id]/route.js +14 -0
  33. package/.medusa/server/src/api/vendor/coupon-products/[product_id]/variants/route.js +14 -0
  34. package/.medusa/server/src/api/vendor/coupon-products/configs/[id]/route.js +60 -0
  35. package/.medusa/server/src/api/vendor/coupon-products/configs/[id]/variants/[variant_config_id]/route.js +41 -0
  36. package/.medusa/server/src/api/vendor/coupon-products/configs/[id]/variants/route.js +45 -0
  37. package/.medusa/server/src/api/vendor/coupon-products/configs/route.js +51 -0
  38. package/.medusa/server/src/api/vendor/coupon-products/entitlements/[id]/route.js +25 -0
  39. package/.medusa/server/src/api/vendor/coupon-products/entitlements/route.js +45 -0
  40. package/.medusa/server/src/api/vendor/coupon-products/options/route.js +9 -0
  41. package/.medusa/server/src/api/vendor/coupon-products/products/route.js +19 -0
  42. package/.medusa/server/src/api/vendor/coupon-products/route.js +13 -0
  43. package/.medusa/server/src/api/vendor/coupon-products/uploads/route.js +7 -0
  44. package/.medusa/server/src/jobs/retry-coupon-media-deletes.js +14 -0
  45. package/.medusa/server/src/links/coupon-issuance-order-line-item.js +17 -0
  46. package/.medusa/server/src/links/coupon-issuance-order.js +15 -0
  47. package/.medusa/server/src/links/coupon-product-config-product.js +17 -0
  48. package/.medusa/server/src/links/coupon-product-variant-config-variant.js +17 -0
  49. package/.medusa/server/src/links/coupon-promotion-mirror-promotion.js +17 -0
  50. package/.medusa/server/src/links/customer-coupon-entitlement-customer.js +15 -0
  51. package/.medusa/server/src/modules/coupon/constants.js +46 -0
  52. package/.medusa/server/src/modules/coupon/index.js +16 -0
  53. package/.medusa/server/src/modules/coupon/loaders/reconcile-coupon-products.js +65 -0
  54. package/.medusa/server/src/modules/coupon/migrations/Migration20260709000000.js +40 -0
  55. package/.medusa/server/src/modules/coupon/migrations/Migration20260710000000.js +22 -0
  56. package/.medusa/server/src/modules/coupon/migrations/Migration20260711000000.js +25 -0
  57. package/.medusa/server/src/modules/coupon/migrations/Migration20260712000000.js +78 -0
  58. package/.medusa/server/src/modules/coupon/migrations/Migration20260719000000.js +19 -0
  59. package/.medusa/server/src/modules/coupon/migrations/Migration20260722000000.js +17 -0
  60. package/.medusa/server/src/modules/coupon/migrations/Migration20260723000000.js +18 -0
  61. package/.medusa/server/src/modules/coupon/models/coupon-entitlement-promotion.js +31 -0
  62. package/.medusa/server/src/modules/coupon/models/coupon-entitlement-seller.js +28 -0
  63. package/.medusa/server/src/modules/coupon/models/coupon-issuance.js +35 -0
  64. package/.medusa/server/src/modules/coupon/models/coupon-media-asset.js +41 -0
  65. package/.medusa/server/src/modules/coupon/models/coupon-product-config.js +45 -0
  66. package/.medusa/server/src/modules/coupon/models/coupon-product-variant-config.js +36 -0
  67. package/.medusa/server/src/modules/coupon/models/coupon-promotion-mirror.js +27 -0
  68. package/.medusa/server/src/modules/coupon/models/customer-coupon-entitlement.js +56 -0
  69. package/.medusa/server/src/modules/coupon/models/index.js +23 -0
  70. package/.medusa/server/src/modules/coupon/payment-order-utils.js +76 -0
  71. package/.medusa/server/src/modules/coupon/product-metadata.js +24 -0
  72. package/.medusa/server/src/modules/coupon/purchase-conditions.js +138 -0
  73. package/.medusa/server/src/modules/coupon/service.js +628 -0
  74. package/.medusa/server/src/modules/coupon/types.js +3 -0
  75. package/.medusa/server/src/modules/coupon/utils.js +302 -0
  76. package/.medusa/server/src/subscribers/issue-coupons-from-order.js +88 -0
  77. package/.medusa/server/src/vendor/index.mjs +3237 -0
  78. package/.medusa/server/src/workflows/hooks/validate-coupon-add-to-cart.js +13 -0
  79. package/.medusa/server/src/workflows/hooks/validate-coupon-complete-cart.js +8 -0
  80. package/.medusa/server/src/workflows/index.js +21 -0
  81. package/.medusa/server/src/workflows/steps.js +27 -0
  82. package/.medusa/server/src/workflows/validate-coupon-purchase.js +85 -0
  83. package/README.md +84 -0
  84. package/package.json +102 -0
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9jb3Vwb24vdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeCurrencyCode = normalizeCurrencyCode;
4
+ exports.normalizeCode = normalizeCode;
5
+ exports.normalizePrefix = normalizePrefix;
6
+ exports.normalizePositiveInteger = normalizePositiveInteger;
7
+ exports.normalizeCouponAmounts = normalizeCouponAmounts;
8
+ exports.resolveAmountForCurrency = resolveAmountForCurrency;
9
+ exports.assertExpirationPolicy = assertExpirationPolicy;
10
+ exports.validateCouponConfig = validateCouponConfig;
11
+ exports.computeExpirationDate = computeExpirationDate;
12
+ exports.resolvePromotionAllocation = resolvePromotionAllocation;
13
+ exports.mergeVariantConfig = mergeVariantConfig;
14
+ exports.resolveLineProductId = resolveLineProductId;
15
+ exports.resolveLineVariantId = resolveLineVariantId;
16
+ exports.createEntitlementCode = createEntitlementCode;
17
+ exports.buildBenefitSnapshot = buildBenefitSnapshot;
18
+ exports.normalizeConfigInput = normalizeConfigInput;
19
+ const utils_1 = require("@medusajs/framework/utils");
20
+ const purchase_conditions_1 = require("./purchase-conditions");
21
+ const CURRENCY_RE = /^[a-z]{3}$/i;
22
+ function normalizeCurrencyCode(value) {
23
+ return value ? value.trim().toLowerCase() : null;
24
+ }
25
+ function normalizeCode(value) {
26
+ return value ? value.trim().toUpperCase() : null;
27
+ }
28
+ function normalizePrefix(value) {
29
+ return value ? value.trim().toUpperCase() : null;
30
+ }
31
+ function normalizePositiveInteger(value, fallback) {
32
+ const parsed = Number(value);
33
+ if (!Number.isFinite(parsed) || parsed <= 0) {
34
+ return fallback;
35
+ }
36
+ return Math.floor(parsed);
37
+ }
38
+ function assertPositiveNumber(value, field) {
39
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
40
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `${field} must be greater than 0`);
41
+ }
42
+ }
43
+ function couponAmountRows(data) {
44
+ if (Array.isArray(data.amounts)) {
45
+ return data.amounts.map((row) => ({
46
+ currency_code: normalizeCurrencyCode(row?.currency_code) || "",
47
+ amount: Number(row?.amount),
48
+ }));
49
+ }
50
+ if (data.amount != null || data.currency_code) {
51
+ return [
52
+ {
53
+ currency_code: normalizeCurrencyCode(data.currency_code) || "",
54
+ amount: Number(data.amount),
55
+ },
56
+ ];
57
+ }
58
+ return [];
59
+ }
60
+ function normalizeCouponAmounts(value) {
61
+ if (!Array.isArray(value))
62
+ return [];
63
+ return value.map((row) => ({
64
+ currency_code: normalizeCurrencyCode(row?.currency_code) || "",
65
+ amount: Number(row?.amount),
66
+ }));
67
+ }
68
+ function assertLegacyAmountCompatibility(input, amounts) {
69
+ if (!Array.isArray(input.amounts))
70
+ return;
71
+ if (input.amount == null && !input.currency_code)
72
+ return;
73
+ const legacyCurrency = normalizeCurrencyCode(input.currency_code);
74
+ const first = amounts[0];
75
+ if (!first ||
76
+ Number(input.amount) !== first.amount ||
77
+ legacyCurrency !== first.currency_code) {
78
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "amount and currency_code must match the first amounts entry");
79
+ }
80
+ }
81
+ function resolveAmountForCurrency(value, currencyCode) {
82
+ const normalizedCurrency = normalizeCurrencyCode(currencyCode);
83
+ const amounts = couponAmountRows(value);
84
+ const match = amounts.find((row) => row.currency_code === normalizedCurrency);
85
+ if (!match) {
86
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, `Coupon does not have a value for ${(normalizedCurrency || currencyCode).toUpperCase()}`);
87
+ }
88
+ return match;
89
+ }
90
+ function assertExpirationPolicy(value) {
91
+ if (!value || typeof value !== "object") {
92
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "expiration_policy is required");
93
+ }
94
+ const policy = value;
95
+ if (policy.type === "none") {
96
+ return;
97
+ }
98
+ if (policy.type === "duration") {
99
+ const days = Number(policy.duration_days);
100
+ if (Number.isFinite(days) && days > 0) {
101
+ if (policy.cap_at && Number.isNaN(Date.parse(String(policy.cap_at)))) {
102
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "expiration_policy.cap_at must be a valid date");
103
+ }
104
+ return;
105
+ }
106
+ }
107
+ if (policy.type === "fixed") {
108
+ const expiresAt = String(policy.expires_at || "");
109
+ if (expiresAt && !Number.isNaN(Date.parse(expiresAt))) {
110
+ if (policy.cap_at && Number.isNaN(Date.parse(String(policy.cap_at)))) {
111
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "expiration_policy.cap_at must be a valid date");
112
+ }
113
+ return;
114
+ }
115
+ }
116
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "expiration_policy must be { type: 'none' }, { type: 'duration', duration_days }, or { type: 'fixed', expires_at }");
117
+ }
118
+ function validateCouponConfig(data) {
119
+ const benefitType = data.benefit_type;
120
+ const codeStrategy = data.code_strategy;
121
+ assertExpirationPolicy(data.expiration_policy);
122
+ const purchaseConditions = (0, purchase_conditions_1.normalizePurchaseConditions)(data.purchase_conditions || []);
123
+ if (benefitType === "fixed_amount") {
124
+ const amounts = couponAmountRows(data);
125
+ if (!amounts.length) {
126
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "amounts must include at least one currency amount for fixed amount coupons");
127
+ }
128
+ const seen = new Set();
129
+ for (const row of amounts) {
130
+ assertPositiveNumber(row.amount, "amounts.amount");
131
+ if (!row.currency_code || !CURRENCY_RE.test(row.currency_code)) {
132
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "amounts.currency_code must be a 3-letter currency code for fixed amount coupons");
133
+ }
134
+ if (seen.has(row.currency_code)) {
135
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `amounts currency_code ${row.currency_code.toUpperCase()} cannot be duplicated`);
136
+ }
137
+ seen.add(row.currency_code);
138
+ }
139
+ const currencyCondition = (0, purchase_conditions_1.findPurchaseCondition)(purchaseConditions, "currency_code");
140
+ if (!currencyCondition) {
141
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "A Currency Code purchase condition is required for fixed amount coupons");
142
+ }
143
+ if (currencyCondition.operator !== "ne") {
144
+ const expected = [...currencyCondition.values].sort();
145
+ const configured = Array.from(seen).sort();
146
+ if (expected.length !== configured.length ||
147
+ expected.some((value, index) => value !== configured[index])) {
148
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Fixed coupon amounts must match the Currency Code purchase condition");
149
+ }
150
+ }
151
+ else if (amounts.some((row) => currencyCondition.values.includes(row.currency_code))) {
152
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Fixed coupon amounts cannot include a currency excluded by the Currency Code condition");
153
+ }
154
+ }
155
+ if (benefitType === "percentage") {
156
+ assertPositiveNumber(data.percentage, "percentage");
157
+ if ((data.percentage || 0) > 100) {
158
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "percentage must be less than or equal to 100");
159
+ }
160
+ }
161
+ if (codeStrategy === "shared_code" && !normalizeCode(data.shared_code)) {
162
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "shared_code is required when code_strategy is shared_code");
163
+ }
164
+ if (data.max_issuance_per_order_item != null &&
165
+ normalizePositiveInteger(data.max_issuance_per_order_item, 0) <= 0) {
166
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "max_issuance_per_order_item must be greater than 0");
167
+ }
168
+ }
169
+ function computeExpirationDate(policy, now = new Date(), campaignEndsAt) {
170
+ if (policy.type === "none") {
171
+ return null;
172
+ }
173
+ let expiresAt;
174
+ if (policy.type === "fixed") {
175
+ expiresAt = new Date(policy.expires_at);
176
+ }
177
+ else {
178
+ expiresAt = new Date(now);
179
+ expiresAt.setUTCDate(expiresAt.getUTCDate() + policy.duration_days);
180
+ }
181
+ const capValue = policy.cap_at || campaignEndsAt;
182
+ if (policy.cap_by_campaign !== false && capValue) {
183
+ const capAt = new Date(capValue);
184
+ if (!Number.isNaN(capAt.getTime()) &&
185
+ capAt.getTime() < expiresAt.getTime()) {
186
+ return capAt;
187
+ }
188
+ }
189
+ return expiresAt;
190
+ }
191
+ function resolvePromotionAllocation(promotionTemplate, targetType) {
192
+ if (targetType === "order")
193
+ return "across";
194
+ const configured = promotionTemplate?.application_method?.allocation;
195
+ return configured === "once" ? "once" : "each";
196
+ }
197
+ function mergeVariantConfig(productConfig, variantConfig) {
198
+ const merged = {
199
+ ...productConfig,
200
+ variant_id: variantConfig?.variant_id ?? null,
201
+ variant_config_id: variantConfig?.id ?? null,
202
+ };
203
+ if (variantConfig) {
204
+ for (const key of [
205
+ "benefit_type",
206
+ "amounts",
207
+ "amount",
208
+ "percentage",
209
+ "currency_code",
210
+ "code_strategy",
211
+ "code_prefix",
212
+ "shared_code",
213
+ "expiration_policy",
214
+ "max_issuance_per_order_item",
215
+ "promotion_mirror_mode",
216
+ "promotion_status",
217
+ "promotion_template",
218
+ "campaign_mode",
219
+ "campaign_id",
220
+ "campaign_snapshot",
221
+ "metadata",
222
+ ]) {
223
+ if (variantConfig[key] !== undefined && variantConfig[key] !== null) {
224
+ merged[key] = variantConfig[key];
225
+ }
226
+ }
227
+ merged.config_version = Math.max(Number(productConfig.config_version || 1), Number(variantConfig.config_version || 1));
228
+ }
229
+ merged.enabled = merged.enabled ?? true;
230
+ merged.benefit_type = merged.benefit_type ?? "fixed_amount";
231
+ merged.code_strategy = merged.code_strategy ?? "unique_code";
232
+ merged.promotion_mirror_mode = merged.promotion_mirror_mode ?? "none";
233
+ merged.promotion_status = merged.promotion_status ?? "draft";
234
+ merged.promotion_template = merged.promotion_template ?? null;
235
+ merged.campaign_mode = merged.campaign_mode ?? "none";
236
+ merged.campaign_id = merged.campaign_id ?? null;
237
+ merged.campaign_snapshot = merged.campaign_snapshot ?? null;
238
+ merged.purchase_conditions = (0, purchase_conditions_1.normalizePurchaseConditions)(merged.purchase_conditions || []);
239
+ merged.max_issuance_per_order_item = normalizePositiveInteger(merged.max_issuance_per_order_item, 1);
240
+ const normalized = normalizeConfigInput(merged);
241
+ merged.amounts = normalized.amounts;
242
+ merged.amount = normalized.amount;
243
+ merged.currency_code = normalized.currency_code;
244
+ merged.code_prefix = normalizePrefix(merged.code_prefix);
245
+ merged.shared_code = normalizeCode(merged.shared_code);
246
+ validateCouponConfig(merged);
247
+ return merged;
248
+ }
249
+ function resolveLineProductId(line) {
250
+ return line.product_id || line.product?.id || "";
251
+ }
252
+ function resolveLineVariantId(line) {
253
+ return line.variant_id || line.variant?.id || "";
254
+ }
255
+ function createEntitlementCode(config) {
256
+ if (config.code_strategy === "shared_code") {
257
+ return normalizeCode(config.shared_code);
258
+ }
259
+ const prefix = normalizePrefix(config.code_prefix) || "COUPON";
260
+ const random = Math.random().toString(36).slice(2, 10).toUpperCase();
261
+ const timestamp = Date.now().toString(36).toUpperCase();
262
+ return `${prefix}-${timestamp}-${random}`;
263
+ }
264
+ function buildBenefitSnapshot(config) {
265
+ return {
266
+ benefit_type: config.benefit_type,
267
+ amounts: config.amounts.map((row) => ({ ...row })),
268
+ amount: config.amount,
269
+ percentage: config.percentage,
270
+ currency_code: config.currency_code,
271
+ code_strategy: config.code_strategy,
272
+ shared_code: config.shared_code,
273
+ expiration_policy: { ...config.expiration_policy },
274
+ max_issuance_per_order_item: config.max_issuance_per_order_item,
275
+ promotion_status: config.promotion_status,
276
+ promotion_template: config.promotion_template
277
+ ? structuredClone(config.promotion_template)
278
+ : null,
279
+ campaign_mode: config.campaign_mode,
280
+ campaign_id: config.campaign_id,
281
+ campaign_snapshot: config.campaign_snapshot
282
+ ? structuredClone(config.campaign_snapshot)
283
+ : null,
284
+ };
285
+ }
286
+ function normalizeConfigInput(input) {
287
+ const amounts = Array.isArray(input.amounts)
288
+ ? normalizeCouponAmounts(input.amounts)
289
+ : couponAmountRows(input);
290
+ assertLegacyAmountCompatibility(input, amounts);
291
+ const first = amounts[0];
292
+ return {
293
+ ...input,
294
+ purchase_conditions: (0, purchase_conditions_1.normalizePurchaseConditions)(input.purchase_conditions || []),
295
+ amounts,
296
+ amount: first?.amount ?? null,
297
+ currency_code: first?.currency_code ?? null,
298
+ code_prefix: normalizePrefix(input.code_prefix),
299
+ shared_code: normalizeCode(input.shared_code),
300
+ };
301
+ }
302
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9jb3Vwb24vdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFpQkEsc0RBRUM7QUFFRCxzQ0FFQztBQUVELDBDQUVDO0FBRUQsNERBT0M7QUFrQ0Qsd0RBUUM7QUF1QkQsNERBa0JDO0FBRUQsd0RBNkNDO0FBRUQsb0RBK0ZDO0FBRUQsc0RBNkJDO0FBRUQsZ0VBUUM7QUFFRCxnREFrRUM7QUFFRCxvREFFQztBQUVELG9EQUVDO0FBRUQsc0RBU0M7QUFFRCxvREFxQkM7QUFFRCxvREFrQkM7QUFsYkQscURBQXVEO0FBVXZELCtEQUc4QjtBQUU5QixNQUFNLFdBQVcsR0FBRyxhQUFhLENBQUE7QUFFakMsU0FBZ0IscUJBQXFCLENBQUMsS0FBcUI7SUFDekQsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO0FBQ2xELENBQUM7QUFFRCxTQUFnQixhQUFhLENBQUMsS0FBcUI7SUFDakQsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO0FBQ2xELENBQUM7QUFFRCxTQUFnQixlQUFlLENBQUMsS0FBcUI7SUFDbkQsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO0FBQ2xELENBQUM7QUFFRCxTQUFnQix3QkFBd0IsQ0FBQyxLQUFjLEVBQUUsUUFBZ0I7SUFDdkUsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQzVCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLE1B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
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.config = void 0;
4
+ exports.default = issueCouponsFromOrderHandler;
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ const coupon_1 = require("../modules/coupon");
7
+ const payment_order_utils_1 = require("../modules/coupon/payment-order-utils");
8
+ async function issueCouponsFromOrderHandler({ event: { data }, container, }) {
9
+ const orderId = await (0, payment_order_utils_1.resolveOrderIdFromPaymentEvent)(data, container);
10
+ if (!orderId) {
11
+ return;
12
+ }
13
+ const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
14
+ const { data: [order], } = await query.graph({
15
+ entity: "order",
16
+ filters: { id: orderId },
17
+ fields: [
18
+ "id",
19
+ "customer_id",
20
+ "email",
21
+ "currency_code",
22
+ "region_id",
23
+ "sales_channel_id",
24
+ "metadata",
25
+ "customer.id",
26
+ "customer.email",
27
+ "customer.groups.id",
28
+ "region.id",
29
+ "sales_channel.id",
30
+ "shipping_address.country_code",
31
+ "items.id",
32
+ "items.product_id",
33
+ "items.variant_id",
34
+ "items.quantity",
35
+ "items.title",
36
+ "items.subtitle",
37
+ "items.unit_price",
38
+ "items.total",
39
+ "items.subtotal",
40
+ "items.metadata",
41
+ "items.product.id",
42
+ "items.product.metadata",
43
+ "items.variant.id",
44
+ "items.variant.metadata",
45
+ "promotions.id",
46
+ "promotions.code",
47
+ "promotions.metadata",
48
+ ],
49
+ });
50
+ if (!order) {
51
+ return;
52
+ }
53
+ const service = container.resolve(coupon_1.COUPON_MODULE);
54
+ await service.issueFromOrder(order);
55
+ for (const promotion of order.promotions || []) {
56
+ const [mapping] = await service.listCouponEntitlementPromotions({
57
+ promotion_id: promotion.id,
58
+ });
59
+ if (!mapping)
60
+ continue;
61
+ const entitlement = await service.retrieveCustomerCouponEntitlement(mapping.entitlement_id);
62
+ if (entitlement.status === "redeemed" &&
63
+ entitlement.metadata?.redemption_order_id === order.id) {
64
+ continue;
65
+ }
66
+ const mappingMetadata = (mapping.metadata || {});
67
+ const applicationMethod = (mappingMetadata.application_method || {});
68
+ const isPercentage = mappingMetadata.benefit_type === "percentage" ||
69
+ applicationMethod.type === "percentage";
70
+ await service.redeemEntitlement(entitlement.id, {
71
+ ...(entitlement.metadata || {}),
72
+ redemption_order_id: order.id,
73
+ redemption_currency_code: mapping.currency_code,
74
+ ...(isPercentage
75
+ ? {
76
+ redemption_percentage: Number(applicationMethod.value) || mapping.amount,
77
+ }
78
+ : { redemption_amount: mapping.amount }),
79
+ redemption_target_type: applicationMethod.target_type || null,
80
+ redemption_allocation: applicationMethod.allocation || null,
81
+ promotion_id: mapping.promotion_id,
82
+ });
83
+ }
84
+ }
85
+ exports.config = {
86
+ event: "payment.captured",
87
+ };
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXNzdWUtY291cG9ucy1mcm9tLW9yZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3N1YnNjcmliZXJzL2lzc3VlLWNvdXBvbnMtZnJvbS1vcmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFZQSwrQ0FpR0M7QUE1R0QscURBRWtDO0FBQ2xDLDhDQUFpRDtBQUdqRCwrRUFHOEM7QUFFL0IsS0FBSyxVQUFVLDRCQUE0QixDQUFDLEVBQ3pELEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxFQUNmLFNBQVMsR0FDNEI7SUFDckMsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFBLG9EQUE4QixFQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQTtJQUNyRSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFNO0lBQ1IsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDaEUsTUFBTSxFQUNKLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUNkLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3BCLE1BQU0sRUFBRSxPQUFPO1FBQ2YsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRTtRQUN4QixNQUFNLEVBQUU7WUFDTixJQUFJO1lBQ0osYUFBYTtZQUNiLE9BQU87WUFDUCxlQUFlO1lBQ2YsV0FBVztZQUNYLGtCQUFrQjtZQUNsQixVQUFVO1lBQ1YsYUFBYTtZQUNiLGdCQUFnQjtZQUNoQixvQkFBb0I7WUFDcEIsV0FBVztZQUNYLGtCQUFrQjtZQUNsQiwrQkFBK0I7WUFDL0IsVUFBVTtZQUNWLGtCQUFrQjtZQUNsQixrQkFBa0I7WUFDbEIsZ0JBQWdCO1lBQ2hCLGFBQWE7WUFDYixnQkFBZ0I7WUFDaEIsa0JBQWtCO1lBQ2xCLGFBQWE7WUFDYixnQkFBZ0I7WUFDaEIsZ0JBQWdCO1lBQ2hCLGtCQUFrQjtZQUNsQix3QkFBd0I7WUFDeEIsa0JBQWtCO1lBQ2xCLHdCQUF3QjtZQUN4QixlQUFlO1lBQ2YsaUJBQWlCO1lBQ2pCLHFCQUFxQjtTQUN0QjtLQUNGLENBQUMsQ0FBQTtJQUVGLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLE9BQU07SUFDUixDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQXdCLFNBQVMsQ0FBQyxPQUFPLENBQUMsc0JBQWEsQ0FBQyxDQUFBO0lBQ3JFLE1BQU0sT0FBTyxDQUFDLGNBQWMsQ0FBQyxLQUFvQixDQUFDLENBQUE7SUFFbEQsS0FBSyxNQUFNLFNBQVMsSUFBSyxLQUFhLENBQUMsVUFBVSxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ3hELE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQywrQkFBK0IsQ0FBQztZQUM5RCxZQUFZLEVBQUUsU0FBUyxDQUFDLEVBQUU7U0FDcEIsQ0FBQyxDQUFBO1FBQ1QsSUFBSSxDQUFDLE9BQU87WUFBRSxTQUFRO1FBRXRCLE1BQU0sV0FBVyxHQUFHLE1BQU0sT0FBTyxDQUFDLGlDQUFpQyxDQUNqRSxPQUFPLENBQUMsY0FBYyxDQUN2QixDQUFBO1FBQ0QsSUFDRSxXQUFXLENBQUMsTUFBTSxLQUFLLFVBQVU7WUFDaEMsV0FBVyxDQUFDLFFBQWdCLEVBQUUsbUJBQW1CLEtBQUssS0FBSyxDQUFDLEVBQUUsRUFDL0QsQ0FBQztZQUNELFNBQVE7UUFDVixDQUFDO1FBQ0QsTUFBTSxlQUFlLEdBQUcsQ0FBRSxPQUFPLENBQUMsUUFBZ0IsSUFBSSxFQUFFLENBR3ZELENBQUE7UUFDRCxNQUFNLGlCQUFpQixHQUFHLENBQUMsZUFBZSxDQUFDLGtCQUFrQixJQUFJLEVBQUUsQ0FHbEUsQ0FBQTtRQUNELE1BQU0sWUFBWSxHQUNoQixlQUFlLENBQUMsWUFBWSxLQUFLLFlBQVk7WUFDN0MsaUJBQWlCLENBQUMsSUFBSSxLQUFLLFlBQVksQ0FBQTtRQUN6QyxNQUFNLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFO1lBQzlDLEdBQUcsQ0FBRSxXQUFXLENBQUMsUUFBZ0IsSUFBSSxFQUFFLENBQUM7WUFDeEMsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLEVBQUU7WUFDN0Isd0JBQXdCLEVBQUUsT0FBTyxDQUFDLGFBQWE7WUFDL0MsR0FBRyxDQUFDLFlBQVk7Z0JBQ2QsQ0FBQyxDQUFDO29CQUNFLHFCQUFxQixFQUNuQixNQUFNLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLElBQUksT0FBTyxDQUFDLE1BQU07aUJBQ3BEO2dCQUNILENBQUMsQ0FBQyxFQUFFLGlCQUFpQixFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMxQyxzQkFBc0IsRUFBRSxpQkFBaUIsQ0FBQyxXQUFXLElBQUksSUFBSTtZQUM3RCxxQkFBcUIsRUFBRSxpQkFBaUIsQ0FBQyxVQUFVLElBQUksSUFBSTtZQUMzRCxZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVk7U0FDbkMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztBQUNILENBQUM7QUFFWSxRQUFBLE1BQU0sR0FBcUI7SUFDdEMsS0FBSyxFQUFFLGtCQUFrQjtDQUMxQixDQUFBIn0=