@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,628 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const utils_1 = require("@medusajs/framework/utils");
16
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
17
+ const constants_1 = require("./constants");
18
+ const models_1 = require("./models");
19
+ const utils_2 = require("./utils");
20
+ const purchase_conditions_1 = require("./purchase-conditions");
21
+ const product_metadata_1 = require("./product-metadata");
22
+ class CouponModuleService extends (0, utils_1.MedusaService)({
23
+ CouponProductConfig: models_1.CouponProductConfig,
24
+ CouponProductVariantConfig: models_1.CouponProductVariantConfig,
25
+ CouponIssuance: models_1.CouponIssuance,
26
+ CouponEntitlementPromotion: models_1.CouponEntitlementPromotion,
27
+ CouponEntitlementSeller: models_1.CouponEntitlementSeller,
28
+ CustomerCouponEntitlement: models_1.CustomerCouponEntitlement,
29
+ CouponPromotionMirror: models_1.CouponPromotionMirror,
30
+ CouponMediaAsset: models_1.CouponMediaAsset,
31
+ }) {
32
+ constructor(container, options) {
33
+ super(container, options);
34
+ this.container_ = container;
35
+ }
36
+ async validateMediaSelection(selection, options = {}) {
37
+ const ids = Array.from(new Set([selection.thumbnail, ...(selection.images || [])].filter((id) => Boolean(id))));
38
+ if (!ids.length)
39
+ return {};
40
+ if (ids.length !==
41
+ [selection.thumbnail, ...(selection.images || [])].filter(Boolean).length) {
42
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "A managed coupon asset cannot be attached more than once");
43
+ }
44
+ const assets = (await this.listCouponMediaAssets({
45
+ id: ids,
46
+ }));
47
+ const byId = Object.fromEntries(assets.map((asset) => [asset.id, asset]));
48
+ for (const id of ids) {
49
+ const asset = byId[id];
50
+ if (!asset || asset.status === "pending_delete") {
51
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Coupon media asset with id: ${id} was not found`);
52
+ }
53
+ if (options.seller_id && asset.seller_id !== options.seller_id) {
54
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "A seller can only attach media uploaded by that seller");
55
+ }
56
+ if (asset.product_id && asset.product_id !== options.product_id) {
57
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "This coupon media asset is already attached to another product");
58
+ }
59
+ }
60
+ return byId;
61
+ }
62
+ async reconcileProductMedia(productId, selection, options = {}) {
63
+ await this.validateMediaSelection(selection, {
64
+ seller_id: options.seller_id,
65
+ product_id: productId,
66
+ });
67
+ const hasThumbnail = Object.prototype.hasOwnProperty.call(selection, "thumbnail");
68
+ const hasImages = Object.prototype.hasOwnProperty.call(selection, "images");
69
+ if (!hasThumbnail && !hasImages)
70
+ return;
71
+ const desired = [
72
+ ...(hasThumbnail && selection.thumbnail
73
+ ? [{ id: selection.thumbnail, role: "thumbnail", position: 0 }]
74
+ : []),
75
+ ...(hasImages
76
+ ? (selection.images || []).map((id, position) => ({
77
+ id,
78
+ role: "image",
79
+ position,
80
+ }))
81
+ : []),
82
+ ];
83
+ for (const assignment of desired) {
84
+ await this.updateCouponMediaAssets({
85
+ id: assignment.id,
86
+ product_id: productId,
87
+ role: assignment.role,
88
+ position: assignment.position,
89
+ status: "attached",
90
+ last_error: null,
91
+ });
92
+ }
93
+ const existing = (await this.listCouponMediaAssets({
94
+ product_id: productId,
95
+ status: "attached",
96
+ }));
97
+ const desiredIds = new Set(desired.map((assignment) => assignment.id));
98
+ const stale = existing.filter((asset) => !desiredIds.has(asset.id) &&
99
+ ((hasThumbnail && asset.role === "thumbnail") ||
100
+ (hasImages && asset.role === "image")));
101
+ for (const asset of stale) {
102
+ await this.updateCouponMediaAssets({
103
+ id: asset.id,
104
+ status: "pending_delete",
105
+ last_error: null,
106
+ });
107
+ await this.tryDeleteMediaAsset({ ...asset, status: "pending_delete" });
108
+ }
109
+ }
110
+ async retryPendingMediaDeletes() {
111
+ const pending = (await this.listCouponMediaAssets({
112
+ status: "pending_delete",
113
+ }));
114
+ for (const asset of pending) {
115
+ await this.tryDeleteMediaAsset(asset);
116
+ }
117
+ }
118
+ async tryDeleteMediaAsset(asset) {
119
+ try {
120
+ const fileService = this.container_.resolve(utils_1.Modules.FILE);
121
+ await fileService.deleteFiles(asset.file_id);
122
+ await this.deleteCouponMediaAssets(asset.id);
123
+ }
124
+ catch (error) {
125
+ await this.updateCouponMediaAssets({
126
+ id: asset.id,
127
+ status: "pending_delete",
128
+ delete_attempts: Number(asset.delete_attempts || 0) + 1,
129
+ last_error: error instanceof Error ? error.message : String(error),
130
+ });
131
+ }
132
+ }
133
+ async createProductConfig(input) {
134
+ const payload = (0, utils_2.normalizeConfigInput)({
135
+ enabled: input.enabled ?? true,
136
+ benefit_type: input.benefit_type ?? "fixed_amount",
137
+ code_strategy: input.code_strategy ?? "unique_code",
138
+ promotion_mirror_mode: input.promotion_mirror_mode ?? "none",
139
+ promotion_status: input.promotion_status ?? "draft",
140
+ campaign_mode: input.campaign_mode ?? "none",
141
+ max_issuance_per_order_item: input.max_issuance_per_order_item == null
142
+ ? 1
143
+ : (0, utils_2.normalizePositiveInteger)(input.max_issuance_per_order_item, 1),
144
+ ...input,
145
+ });
146
+ (0, utils_2.validateCouponConfig)(payload);
147
+ const existing = await this.listCouponProductConfigs({
148
+ product_id: payload.product_id,
149
+ });
150
+ if (existing.length) {
151
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.DUPLICATE_ERROR, "Coupon config already exists for this product");
152
+ }
153
+ const config = await this.createCouponProductConfigs({
154
+ ...payload,
155
+ item_type: "coupon",
156
+ fulfillment_type: "code_issuance",
157
+ config_version: 1,
158
+ });
159
+ await this.markProductMetadata(config.product_id, config.id);
160
+ await this.emit(constants_1.COUPON_EVENTS.CONFIG_CREATED, { id: config.id });
161
+ return config;
162
+ }
163
+ async updateProductConfig(id, input) {
164
+ const existing = await this.retrieveCouponProductConfig(id);
165
+ const payload = (0, utils_2.normalizeConfigInput)({
166
+ ...existing,
167
+ ...(input.amounts !== undefined
168
+ ? { amount: null, currency_code: null }
169
+ : {}),
170
+ ...input,
171
+ product_id: existing.product_id,
172
+ });
173
+ (0, utils_2.validateCouponConfig)(payload);
174
+ const config = await this.updateCouponProductConfigs({
175
+ id,
176
+ ...payload,
177
+ config_version: Number(existing.config_version || 1) + 1,
178
+ });
179
+ await this.markProductMetadata(config.product_id, config.id);
180
+ await this.emit(constants_1.COUPON_EVENTS.CONFIG_UPDATED, { id: config.id });
181
+ return config;
182
+ }
183
+ async deleteProductConfig(id) {
184
+ const existing = await this.retrieveCouponProductConfig(id);
185
+ await this.deleteCouponProductConfigs(id);
186
+ await this.markProductMetadata(existing.product_id, existing.id, false);
187
+ await this.emit(constants_1.COUPON_EVENTS.CONFIG_DELETED, {
188
+ id,
189
+ product_id: existing.product_id,
190
+ });
191
+ return existing;
192
+ }
193
+ async createVariantConfig(productConfigId, input) {
194
+ const productConfig = await this.retrieveCouponProductConfig(productConfigId);
195
+ const existing = await this.listCouponProductVariantConfigs({
196
+ variant_id: input.variant_id,
197
+ });
198
+ if (existing.length) {
199
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.DUPLICATE_ERROR, "Coupon config already exists for this variant");
200
+ }
201
+ const hasAmountOverride = input.amounts !== undefined ||
202
+ input.amount !== undefined ||
203
+ input.currency_code !== undefined;
204
+ const payload = (0, utils_2.normalizeConfigInput)(input);
205
+ if (!hasAmountOverride) {
206
+ payload.amounts = null;
207
+ payload.amount = null;
208
+ payload.currency_code = null;
209
+ }
210
+ (0, utils_2.mergeVariantConfig)(productConfig, payload);
211
+ return this.createCouponProductVariantConfigs({
212
+ ...payload,
213
+ product_config_id: productConfigId,
214
+ config_version: 1,
215
+ });
216
+ }
217
+ async updateVariantConfig(id, input) {
218
+ const existing = await this.retrieveCouponProductVariantConfig(id);
219
+ const hasAmountOverride = input.amounts !== undefined ||
220
+ input.amount !== undefined ||
221
+ input.currency_code !== undefined;
222
+ const payload = (0, utils_2.normalizeConfigInput)(hasAmountOverride
223
+ ? input
224
+ : {
225
+ ...input,
226
+ amounts: existing.amounts,
227
+ amount: existing.amount,
228
+ currency_code: existing.currency_code,
229
+ });
230
+ if (!hasAmountOverride && existing.amounts == null) {
231
+ payload.amounts = null;
232
+ payload.amount = existing.amount ?? null;
233
+ payload.currency_code = existing.currency_code ?? null;
234
+ }
235
+ const productConfig = await this.retrieveCouponProductConfig(existing.product_config_id);
236
+ (0, utils_2.mergeVariantConfig)(productConfig, { ...existing, ...payload });
237
+ return this.updateCouponProductVariantConfigs({
238
+ id,
239
+ ...payload,
240
+ config_version: Number(existing.config_version || 1) + 1,
241
+ });
242
+ }
243
+ async resolveConfigForLineItem(line) {
244
+ const productId = (0, utils_2.resolveLineProductId)(line);
245
+ if (!productId) {
246
+ return null;
247
+ }
248
+ const [productConfig] = await this.listCouponProductConfigs({
249
+ product_id: productId,
250
+ enabled: true,
251
+ });
252
+ if (!productConfig) {
253
+ return null;
254
+ }
255
+ const variantId = (0, utils_2.resolveLineVariantId)(line);
256
+ const [variantConfig] = variantId
257
+ ? await this.listCouponProductVariantConfigs({
258
+ product_config_id: productConfig.id,
259
+ variant_id: variantId,
260
+ enabled: true,
261
+ })
262
+ : [];
263
+ return (0, utils_2.mergeVariantConfig)(productConfig, variantConfig);
264
+ }
265
+ async issueFromOrder(order) {
266
+ const results = [];
267
+ for (const line of order.items || []) {
268
+ const issuance = await this.issueFromLineItem(order, line);
269
+ if (issuance) {
270
+ results.push(issuance);
271
+ }
272
+ }
273
+ return results;
274
+ }
275
+ async issueFromLineItem(order, line) {
276
+ if (!line.id) {
277
+ return null;
278
+ }
279
+ const [existing] = await this.listCouponIssuances({
280
+ line_item_id: line.id,
281
+ });
282
+ if (existing) {
283
+ return existing;
284
+ }
285
+ const config = await this.resolveConfigForLineItem(line);
286
+ if (!config) {
287
+ return null;
288
+ }
289
+ const quantity = (0, utils_2.normalizePositiveInteger)(line.quantity, 1);
290
+ const issueCount = quantity * config.max_issuance_per_order_item;
291
+ const customerId = order.customer_id || order.customer?.id || null;
292
+ const email = order.email || order.customer?.email || null;
293
+ const sourceVariantId = config.variant_id || (0, utils_2.resolveLineVariantId)(line) || null;
294
+ const now = new Date();
295
+ const expiresAt = (0, utils_2.computeExpirationDate)(config.expiration_policy, now, readCampaignEndsAt(config.campaign_snapshot));
296
+ const configSnapshot = {
297
+ ...(0, utils_2.buildBenefitSnapshot)(config),
298
+ purchase_conditions: structuredClone(config.purchase_conditions || []),
299
+ config_id: config.id,
300
+ variant_config_id: config.variant_config_id,
301
+ product_id: config.product_id,
302
+ variant_id: config.variant_id,
303
+ config_version: config.config_version,
304
+ campaign_id: config.campaign_id,
305
+ };
306
+ const issuance = await this.createCouponIssuances({
307
+ order_id: order.id,
308
+ line_item_id: line.id,
309
+ product_id: config.product_id,
310
+ variant_id: config.variant_id || null,
311
+ customer_id: customerId,
312
+ email,
313
+ quantity,
314
+ status: "pending",
315
+ config_id: config.id,
316
+ variant_config_id: config.variant_config_id || null,
317
+ config_version: config.config_version,
318
+ config_snapshot: configSnapshot,
319
+ issued_count: 0,
320
+ failed_count: 0,
321
+ metadata: {
322
+ line_item: {
323
+ title: line.title,
324
+ subtitle: line.subtitle,
325
+ unit_price: line.unit_price,
326
+ total: line.total,
327
+ subtotal: line.subtotal,
328
+ },
329
+ },
330
+ });
331
+ const entitlements = [];
332
+ for (let i = 0; i < issueCount; i++) {
333
+ entitlements.push({
334
+ origin: "purchase",
335
+ customer_id: customerId,
336
+ email,
337
+ code: (0, utils_2.createEntitlementCode)(config),
338
+ shared_code: config.code_strategy === "shared_code" ? config.shared_code : null,
339
+ status: "issued",
340
+ product_id: config.product_id,
341
+ variant_id: config.variant_id || null,
342
+ order_id: order.id,
343
+ line_item_id: line.id,
344
+ issuance_id: issuance.id,
345
+ config_id: config.id,
346
+ variant_config_id: config.variant_config_id || null,
347
+ benefit_snapshot: (0, utils_2.buildBenefitSnapshot)(config),
348
+ source_snapshot: {
349
+ order_id: order.id,
350
+ line_item_id: line.id,
351
+ product_id: config.product_id,
352
+ variant_id: sourceVariantId,
353
+ quantity,
354
+ title: line.title ?? null,
355
+ subtitle: line.subtitle ?? null,
356
+ unit_price: line.unit_price ?? null,
357
+ subtotal: line.subtotal ?? null,
358
+ total: line.total ?? null,
359
+ purchase_context: (0, purchase_conditions_1.buildCouponPurchaseContext)(order),
360
+ },
361
+ expires_at: expiresAt,
362
+ metadata: null,
363
+ });
364
+ }
365
+ const createdEntitlements = entitlements.length
366
+ ? (await this.createCustomerCouponEntitlements(entitlements))
367
+ : [];
368
+ const updatedIssuance = await this.updateCouponIssuances({
369
+ id: issuance.id,
370
+ status: "issued",
371
+ issued_count: createdEntitlements.length,
372
+ failed_count: Math.max(0, issueCount - createdEntitlements.length),
373
+ });
374
+ await this.emit(constants_1.COUPON_EVENTS.PRODUCT_PURCHASED, {
375
+ order_id: order.id,
376
+ line_item_id: line.id,
377
+ product_id: config.product_id,
378
+ variant_id: config.variant_id,
379
+ quantity,
380
+ });
381
+ await this.emit(constants_1.COUPON_EVENTS.ISSUANCE_CREATED, {
382
+ id: updatedIssuance.id,
383
+ order_id: order.id,
384
+ line_item_id: line.id,
385
+ });
386
+ for (const entitlement of createdEntitlements) {
387
+ await this.emit(constants_1.COUPON_EVENTS.ENTITLEMENT_ISSUED, {
388
+ id: entitlement.id,
389
+ order_id: order.id,
390
+ line_item_id: line.id,
391
+ customer_id: customerId,
392
+ });
393
+ }
394
+ return {
395
+ ...updatedIssuance,
396
+ entitlements: createdEntitlements,
397
+ };
398
+ }
399
+ async upsertExternalEntitlement(input) {
400
+ const externalReference = String(input.external_reference || "").trim();
401
+ const customerId = String(input.customer_id || "").trim();
402
+ if (!/^[a-z0-9][a-z0-9._-]*:/i.test(externalReference)) {
403
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "external_reference must be a namespaced reference");
404
+ }
405
+ if (!input.benefit_snapshot || typeof input.benefit_snapshot !== "object") {
406
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "benefit_snapshot is required for an external coupon entitlement");
407
+ }
408
+ const [existing] = await this.listCustomerCouponEntitlements({
409
+ external_reference: externalReference,
410
+ });
411
+ if (existing && existing.origin !== "external") {
412
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "external_reference belongs to a purchase-origin entitlement");
413
+ }
414
+ const payload = {
415
+ origin: "external",
416
+ external_reference: externalReference,
417
+ customer_id: customerId || null,
418
+ email: input.email ?? null,
419
+ code: input.code ?? null,
420
+ shared_code: input.shared_code ?? null,
421
+ status: input.status ?? "issued",
422
+ product_id: null,
423
+ variant_id: null,
424
+ order_id: null,
425
+ line_item_id: null,
426
+ issuance_id: null,
427
+ config_id: null,
428
+ variant_config_id: null,
429
+ benefit_snapshot: structuredClone(input.benefit_snapshot),
430
+ source_snapshot: input.source_snapshot
431
+ ? structuredClone(input.source_snapshot)
432
+ : null,
433
+ expires_at: input.expires_at ?? null,
434
+ redeemed_at: input.redeemed_at ?? null,
435
+ metadata: input.metadata ? structuredClone(input.metadata) : null,
436
+ };
437
+ if (existing) {
438
+ const entitlement = await this.updateCustomerCouponEntitlements({
439
+ id: existing.id,
440
+ ...payload,
441
+ metadata: {
442
+ ...(existing.metadata || {}),
443
+ ...(payload.metadata || {}),
444
+ },
445
+ });
446
+ const seller_targets = await this.replaceEntitlementSellerTargets(entitlement.id, input.seller_targets || []);
447
+ return { entitlement, created: false, updated: true, seller_targets };
448
+ }
449
+ try {
450
+ const entitlement = await this.createCustomerCouponEntitlements(payload);
451
+ const seller_targets = await this.replaceEntitlementSellerTargets(entitlement.id, input.seller_targets || []);
452
+ return { entitlement, created: true, updated: false, seller_targets };
453
+ }
454
+ catch (error) {
455
+ const duplicate = error?.type === utils_1.MedusaError.Types.DUPLICATE_ERROR ||
456
+ error?.code === "23505" ||
457
+ /duplicate|unique/i.test(String(error?.message || error));
458
+ if (!duplicate)
459
+ throw error;
460
+ const [concurrent] = await this.listCustomerCouponEntitlements({
461
+ external_reference: externalReference,
462
+ });
463
+ if (!concurrent)
464
+ throw error;
465
+ if (concurrent.origin !== "external") {
466
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "external_reference belongs to a purchase-origin entitlement");
467
+ }
468
+ const entitlement = await this.updateCustomerCouponEntitlements({
469
+ id: concurrent.id,
470
+ ...payload,
471
+ metadata: {
472
+ ...(concurrent.metadata || {}),
473
+ ...(payload.metadata || {}),
474
+ },
475
+ });
476
+ const seller_targets = await this.replaceEntitlementSellerTargets(entitlement.id, input.seller_targets || []);
477
+ return { entitlement, created: false, updated: true, seller_targets };
478
+ }
479
+ }
480
+ async replaceEntitlementSellerTargets(entitlementId, targets = [], sharedContext = {}) {
481
+ const normalized = new Map();
482
+ for (const target of targets || []) {
483
+ const sellerId = String(target?.seller_id || "").trim();
484
+ if (!sellerId) {
485
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "seller_targets[].seller_id is required");
486
+ }
487
+ normalized.set(sellerId, {
488
+ seller_id: sellerId,
489
+ seller_member_id: String(target?.seller_member_id || "").trim() || null,
490
+ metadata: target?.metadata ? structuredClone(target.metadata) : null,
491
+ });
492
+ }
493
+ const existing = await this.listCouponEntitlementSellers({
494
+ entitlement_id: entitlementId,
495
+ }, undefined, sharedContext);
496
+ const existingBySeller = new Map((existing || []).map((row) => [String(row.seller_id), row]));
497
+ for (const row of existing || []) {
498
+ if (!normalized.has(String(row.seller_id))) {
499
+ await this.deleteCouponEntitlementSellers(row.id, sharedContext);
500
+ }
501
+ }
502
+ for (const target of normalized.values()) {
503
+ const current = existingBySeller.get(target.seller_id);
504
+ if (current) {
505
+ await this.updateCouponEntitlementSellers({
506
+ id: current.id,
507
+ seller_member_id: target.seller_member_id,
508
+ metadata: target.metadata,
509
+ }, sharedContext);
510
+ }
511
+ else {
512
+ await this.createCouponEntitlementSellers({
513
+ entitlement_id: entitlementId,
514
+ ...target,
515
+ }, sharedContext);
516
+ }
517
+ }
518
+ return this.listCouponEntitlementSellers({
519
+ entitlement_id: entitlementId,
520
+ }, undefined, sharedContext);
521
+ }
522
+ async redeemEntitlement(id, metadata) {
523
+ const entitlement = await this.retrieveCustomerCouponEntitlement(id);
524
+ if (entitlement.status === "redeemed" &&
525
+ metadata?.redemption_order_id &&
526
+ entitlement.metadata?.redemption_order_id ===
527
+ metadata.redemption_order_id) {
528
+ return entitlement;
529
+ }
530
+ if (entitlement.status !== "issued") {
531
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Only issued coupon entitlements can be redeemed");
532
+ }
533
+ const updated = await this.updateCustomerCouponEntitlements({
534
+ id,
535
+ status: "redeemed",
536
+ redeemed_at: new Date(),
537
+ metadata: metadata ?? entitlement.metadata ?? null,
538
+ });
539
+ await this.emit(constants_1.COUPON_EVENTS.ENTITLEMENT_REDEEMED, { id });
540
+ return updated;
541
+ }
542
+ async cancelEntitlement(id, metadata) {
543
+ const entitlement = await this.retrieveCustomerCouponEntitlement(id);
544
+ if (entitlement.status === "redeemed") {
545
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Redeemed coupon entitlements cannot be canceled");
546
+ }
547
+ const updated = await this.updateCustomerCouponEntitlements({
548
+ id,
549
+ status: "canceled",
550
+ metadata: metadata ?? entitlement.metadata ?? null,
551
+ });
552
+ await this.emit(constants_1.COUPON_EVENTS.ENTITLEMENT_CANCELED, { id });
553
+ return updated;
554
+ }
555
+ async createPromotionMirror(input) {
556
+ const mirror = await this.createCouponPromotionMirrors({
557
+ status: "pending",
558
+ ...input,
559
+ mirrored_at: input.status === "created" || input.status === "updated"
560
+ ? new Date()
561
+ : null,
562
+ });
563
+ await this.emit(mirror.status === "failed"
564
+ ? constants_1.COUPON_EVENTS.PROMOTION_MIRROR_FAILED
565
+ : constants_1.COUPON_EVENTS.PROMOTION_MIRROR_CREATED, { id: mirror.id, config_id: mirror.config_id });
566
+ return mirror;
567
+ }
568
+ async markProductMetadata(productId, configId, enabled = true) {
569
+ try {
570
+ const productService = this.container_.resolve(utils_1.Modules.PRODUCT);
571
+ const product = await productService.retrieveProduct(productId, {
572
+ select: ["id", "metadata", "shipping_profile_id"],
573
+ });
574
+ const currentMarker = product.metadata?.[constants_1.COUPON_METADATA_KEY];
575
+ const markerIsCurrent = enabled
576
+ ? (0, product_metadata_1.hasCanonicalCouponProductMarker)(currentMarker, configId)
577
+ : currentMarker?.enabled === false;
578
+ const shippingIsCurrent = !enabled || product.shipping_profile_id == null;
579
+ if (markerIsCurrent && shippingIsCurrent) {
580
+ return false;
581
+ }
582
+ const metadata = {
583
+ ...(product.metadata || {}),
584
+ [constants_1.COUPON_METADATA_KEY]: (0, product_metadata_1.buildCouponProductMarker)(configId, enabled),
585
+ };
586
+ await (0, core_flows_1.updateProductsWorkflow)(this.container_).run({
587
+ input: {
588
+ products: [
589
+ {
590
+ id: productId,
591
+ metadata,
592
+ ...(enabled ? { shipping_profile_id: null } : {}),
593
+ },
594
+ ],
595
+ },
596
+ });
597
+ return true;
598
+ }
599
+ catch {
600
+ // Metadata is a convenience marker. The module config remains authoritative.
601
+ return false;
602
+ }
603
+ }
604
+ async emit(name, data) {
605
+ try {
606
+ const eventBus = this.container_.resolve(utils_1.Modules.EVENT_BUS);
607
+ if (typeof eventBus.emit === "function") {
608
+ await eventBus.emit({ name, data });
609
+ }
610
+ }
611
+ catch {
612
+ // Event emission should not make config persistence fail.
613
+ }
614
+ }
615
+ }
616
+ __decorate([
617
+ (0, utils_1.InjectTransactionManager)(),
618
+ __param(2, (0, utils_1.MedusaContext)()),
619
+ __metadata("design:type", Function),
620
+ __metadata("design:paramtypes", [String, Array, Object]),
621
+ __metadata("design:returntype", Promise)
622
+ ], CouponModuleService.prototype, "replaceEntitlementSellerTargets", null);
623
+ exports.default = CouponModuleService;
624
+ function readCampaignEndsAt(snapshot) {
625
+ const value = snapshot?.ends_at || snapshot?.endsAt;
626
+ return typeof value === "string" || value instanceof Date ? value : null;
627
+ }
628
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2NvdXBvbi9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7O0FBQ0EscURBTWtDO0FBQ2xDLDREQUFvRTtBQUNwRSwyQ0FBZ0U7QUFDaEUscUNBU2lCO0FBUWpCLG1DQVVnQjtBQUNoQiwrREFBa0U7QUFDbEUseURBRzJCO0FBd0IzQixNQUFNLG1CQUFvQixTQUFRLElBQUEscUJBQWEsRUFBQztJQUM5QyxtQkFBbUIsRUFBbkIsNEJBQW1CO0lBQ25CLDBCQUEwQixFQUExQixtQ0FBMEI7SUFDMUIsY0FBYyxFQUFkLHVCQUFjO0lBQ2QsMEJBQTBCLEVBQTFCLG1DQUEwQjtJQUMxQix1QkFBdUIsRUFBdkIsZ0NBQXVCO0lBQ3ZCLHlCQUF5QixFQUF6QixrQ0FBeUI7SUFDekIscUJBQXFCLEVBQXJCLDhCQUFxQjtJQUNyQixnQkFBZ0IsRUFBaEIseUJBQWdCO0NBQ2pCLENBQUM7SUFHQSxZQUFZLFNBQXdCLEVBQUUsT0FBaUM7UUFDckUsS0FBSyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUN6QixJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQTtJQUM3QixDQUFDO0lBRUQsS0FBSyxDQUFDLHNCQUFzQixDQUMxQixTQUErQixFQUMvQixVQUF1RCxFQUFFO1FBRXpELE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQ3BCLElBQUksR0FBRyxDQUNMLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FDdkQsQ0FBQyxFQUFFLEVBQWdCLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQ2xDLENBQ0YsQ0FDRixDQUFBO1FBQ0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNO1lBQUUs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