@lyxa.ai/marketing 1.0.30 → 1.0.32

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 (163) hide show
  1. package/dist/lib/event/event-initializations.d.ts +2 -0
  2. package/dist/lib/event/event-initializations.d.ts.map +1 -0
  3. package/dist/lib/event/event-initializations.js +8 -0
  4. package/dist/lib/event/event-initializations.js.map +1 -0
  5. package/dist/lib/event/event-listeners/event-listeners.d.ts +2 -0
  6. package/dist/lib/event/event-listeners/event-listeners.d.ts.map +1 -0
  7. package/dist/lib/event/event-listeners/event-listeners.js +12 -0
  8. package/dist/lib/event/event-listeners/event-listeners.js.map +1 -0
  9. package/dist/lib/index.d.ts +86 -58
  10. package/dist/lib/index.d.ts.map +1 -1
  11. package/dist/lib/index.js +17 -17
  12. package/dist/lib/index.js.map +1 -1
  13. package/dist/lib/modules/coupon/routers/coupon.router.d.ts +55 -55
  14. package/dist/lib/modules/coupon/routers/coupon.router.d.ts.map +1 -1
  15. package/dist/lib/modules/coupon/routers/coupon.router.js +9 -6
  16. package/dist/lib/modules/coupon/routers/coupon.router.js.map +1 -1
  17. package/dist/lib/modules/coupon/services/coupon.service.d.ts +2 -1
  18. package/dist/lib/modules/coupon/services/coupon.service.d.ts.map +1 -1
  19. package/dist/lib/modules/coupon/services/coupon.service.js +90 -49
  20. package/dist/lib/modules/coupon/services/coupon.service.js.map +1 -1
  21. package/dist/lib/modules/coupon/services/helper.service.d.ts +1 -0
  22. package/dist/lib/modules/coupon/services/helper.service.d.ts.map +1 -1
  23. package/dist/lib/modules/coupon/services/helper.service.js +21 -2
  24. package/dist/lib/modules/coupon/services/helper.service.js.map +1 -1
  25. package/dist/lib/modules/coupon/services/individual-store-coupon.service.js +1 -1
  26. package/dist/lib/modules/coupon/services/individual-store-coupon.service.js.map +1 -1
  27. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.d.ts +1 -0
  28. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.d.ts.map +1 -1
  29. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.js +134 -12
  30. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.js.map +1 -1
  31. package/dist/lib/modules/coupon/services/referral-code-coupon.service.d.ts +1 -1
  32. package/dist/lib/modules/coupon/services/referral-code-coupon.service.d.ts.map +1 -1
  33. package/dist/lib/modules/coupon/services/referral-code-coupon.service.js +9 -3
  34. package/dist/lib/modules/coupon/services/referral-code-coupon.service.js.map +1 -1
  35. package/dist/lib/modules/coupon/services/referral-reward-coupon.service.d.ts.map +1 -1
  36. package/dist/lib/modules/coupon/services/referral-reward-coupon.service.js +10 -2
  37. package/dist/lib/modules/coupon/services/referral-reward-coupon.service.js.map +1 -1
  38. package/dist/lib/modules/coupon/services/shops-categories-coupon.service.js +1 -1
  39. package/dist/lib/modules/coupon/services/shops-categories-coupon.service.js.map +1 -1
  40. package/dist/lib/modules/coupon/validations/all-coupons.validation.d.ts +153 -153
  41. package/dist/lib/modules/coupon/validations/coupon.validation.d.ts +12 -12
  42. package/dist/lib/modules/coupon/validations/coupon.validation.d.ts.map +1 -1
  43. package/dist/lib/modules/coupon/validations/coupon.validation.js +2 -1
  44. package/dist/lib/modules/coupon/validations/coupon.validation.js.map +1 -1
  45. package/dist/lib/modules/coupon/validations/custom-coupon.validation.d.ts +8 -8
  46. package/dist/lib/modules/coupon/validations/global-coupon.validation.d.ts +8 -8
  47. package/dist/lib/modules/coupon/validations/individual-store-coupon.validation.d.ts +10 -10
  48. package/dist/lib/modules/coupon/validations/individual-user-coupon.validation.d.ts +8 -8
  49. package/dist/lib/modules/coupon/validations/referral-reward-coupon.validation.d.ts +9 -9
  50. package/dist/lib/modules/coupon/validations/shops-categories-coupon.validation.d.ts +8 -8
  51. package/dist/lib/modules/deal-setting/validations/deal-setting.validation.d.ts +1 -1
  52. package/dist/lib/modules/marketing/routers/marketing.router.d.ts +28 -0
  53. package/dist/lib/modules/marketing/routers/marketing.router.d.ts.map +1 -1
  54. package/dist/lib/modules/marketing/routers/marketing.router.js +19 -0
  55. package/dist/lib/modules/marketing/routers/marketing.router.js.map +1 -1
  56. package/dist/lib/modules/marketing/services/buy1-get1-marketing.service.d.ts +2 -1
  57. package/dist/lib/modules/marketing/services/buy1-get1-marketing.service.d.ts.map +1 -1
  58. package/dist/lib/modules/marketing/services/buy1-get1-marketing.service.js +45 -110
  59. package/dist/lib/modules/marketing/services/buy1-get1-marketing.service.js.map +1 -1
  60. package/dist/lib/modules/marketing/services/discount-marketing.service.d.ts +2 -1
  61. package/dist/lib/modules/marketing/services/discount-marketing.service.d.ts.map +1 -1
  62. package/dist/lib/modules/marketing/services/discount-marketing.service.js +54 -171
  63. package/dist/lib/modules/marketing/services/discount-marketing.service.js.map +1 -1
  64. package/dist/lib/modules/marketing/services/featured-marketing.service.d.ts +2 -0
  65. package/dist/lib/modules/marketing/services/featured-marketing.service.d.ts.map +1 -1
  66. package/dist/lib/modules/marketing/services/featured-marketing.service.js +30 -2
  67. package/dist/lib/modules/marketing/services/featured-marketing.service.js.map +1 -1
  68. package/dist/lib/modules/marketing/services/free-delivery-marketing.service.d.ts.map +1 -1
  69. package/dist/lib/modules/marketing/services/free-delivery-marketing.service.js +6 -1
  70. package/dist/lib/modules/marketing/services/free-delivery-marketing.service.js.map +1 -1
  71. package/dist/lib/modules/marketing/services/index.d.ts +1 -0
  72. package/dist/lib/modules/marketing/services/index.d.ts.map +1 -1
  73. package/dist/lib/modules/marketing/services/index.js +1 -0
  74. package/dist/lib/modules/marketing/services/index.js.map +1 -1
  75. package/dist/lib/modules/marketing/services/marketing.service.d.ts +5 -0
  76. package/dist/lib/modules/marketing/services/marketing.service.d.ts.map +1 -1
  77. package/dist/lib/modules/marketing/services/marketing.service.js +210 -5
  78. package/dist/lib/modules/marketing/services/marketing.service.js.map +1 -1
  79. package/dist/lib/modules/marketing/services/product-marketing.service.d.ts +2 -0
  80. package/dist/lib/modules/marketing/services/product-marketing.service.d.ts.map +1 -1
  81. package/dist/lib/modules/marketing/services/product-marketing.service.js +27 -3
  82. package/dist/lib/modules/marketing/services/product-marketing.service.js.map +1 -1
  83. package/dist/lib/modules/marketing/services/punch-marketing.service.d.ts.map +1 -1
  84. package/dist/lib/modules/marketing/services/punch-marketing.service.js +6 -1
  85. package/dist/lib/modules/marketing/services/punch-marketing.service.js.map +1 -1
  86. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.d.ts +15 -0
  87. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.d.ts.map +1 -0
  88. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.js +250 -0
  89. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.js.map +1 -0
  90. package/dist/lib/modules/marketing/transformers/buy1-get1-marketing.transformer.d.ts +2 -2
  91. package/dist/lib/modules/marketing/transformers/discount-marketing.transformer.d.ts +2 -2
  92. package/dist/lib/modules/marketing/validations/buy1-get1-marketing.validation.d.ts +55 -55
  93. package/dist/lib/modules/marketing/validations/discount-marketing.validation.d.ts +65 -65
  94. package/dist/lib/modules/marketing/validations/featured-marketing.validation.d.ts +21 -21
  95. package/dist/lib/modules/marketing/validations/free-delivery-marketing.validation.d.ts +18 -18
  96. package/dist/lib/modules/marketing/validations/marketing.validation.d.ts +21 -7
  97. package/dist/lib/modules/marketing/validations/marketing.validation.d.ts.map +1 -1
  98. package/dist/lib/modules/marketing/validations/marketing.validation.js +7 -1
  99. package/dist/lib/modules/marketing/validations/marketing.validation.js.map +1 -1
  100. package/dist/lib/modules/marketing/validations/product-marketing.validation.d.ts +4 -4
  101. package/dist/lib/modules/marketing/validations/punch-marketing.validation.d.ts +22 -22
  102. package/dist/lib/modules/punch-marketing-history/routers/punch-marketing-history.router.d.ts +3 -3
  103. package/dist/lib/modules/punch-marketing-history/services/punch-marketing-history.service.js +2 -2
  104. package/dist/lib/modules/punch-marketing-history/services/punch-marketing-history.service.js.map +1 -1
  105. package/dist/lib/modules/punch-marketing-history/validations/punch-marketing-history.validation.d.ts +6 -6
  106. package/dist/types/event/event-initializations.d.ts +2 -0
  107. package/dist/types/event/event-initializations.d.ts.map +1 -0
  108. package/dist/types/event/event-listeners/event-listeners.d.ts +2 -0
  109. package/dist/types/event/event-listeners/event-listeners.d.ts.map +1 -0
  110. package/dist/types/index.d.ts +86 -58
  111. package/dist/types/index.d.ts.map +1 -1
  112. package/dist/types/modules/coupon/routers/coupon.router.d.ts +55 -55
  113. package/dist/types/modules/coupon/routers/coupon.router.d.ts.map +1 -1
  114. package/dist/types/modules/coupon/services/coupon.service.d.ts +2 -1
  115. package/dist/types/modules/coupon/services/coupon.service.d.ts.map +1 -1
  116. package/dist/types/modules/coupon/services/helper.service.d.ts +1 -0
  117. package/dist/types/modules/coupon/services/helper.service.d.ts.map +1 -1
  118. package/dist/types/modules/coupon/services/patterns/repository/CouponRepository.d.ts +1 -0
  119. package/dist/types/modules/coupon/services/patterns/repository/CouponRepository.d.ts.map +1 -1
  120. package/dist/types/modules/coupon/services/referral-code-coupon.service.d.ts +1 -1
  121. package/dist/types/modules/coupon/services/referral-code-coupon.service.d.ts.map +1 -1
  122. package/dist/types/modules/coupon/services/referral-reward-coupon.service.d.ts.map +1 -1
  123. package/dist/types/modules/coupon/validations/all-coupons.validation.d.ts +153 -153
  124. package/dist/types/modules/coupon/validations/coupon.validation.d.ts +12 -12
  125. package/dist/types/modules/coupon/validations/coupon.validation.d.ts.map +1 -1
  126. package/dist/types/modules/coupon/validations/custom-coupon.validation.d.ts +8 -8
  127. package/dist/types/modules/coupon/validations/global-coupon.validation.d.ts +8 -8
  128. package/dist/types/modules/coupon/validations/individual-store-coupon.validation.d.ts +10 -10
  129. package/dist/types/modules/coupon/validations/individual-user-coupon.validation.d.ts +8 -8
  130. package/dist/types/modules/coupon/validations/referral-reward-coupon.validation.d.ts +9 -9
  131. package/dist/types/modules/coupon/validations/shops-categories-coupon.validation.d.ts +8 -8
  132. package/dist/types/modules/deal-setting/validations/deal-setting.validation.d.ts +1 -1
  133. package/dist/types/modules/marketing/routers/marketing.router.d.ts +28 -0
  134. package/dist/types/modules/marketing/routers/marketing.router.d.ts.map +1 -1
  135. package/dist/types/modules/marketing/services/buy1-get1-marketing.service.d.ts +2 -1
  136. package/dist/types/modules/marketing/services/buy1-get1-marketing.service.d.ts.map +1 -1
  137. package/dist/types/modules/marketing/services/discount-marketing.service.d.ts +2 -1
  138. package/dist/types/modules/marketing/services/discount-marketing.service.d.ts.map +1 -1
  139. package/dist/types/modules/marketing/services/featured-marketing.service.d.ts +2 -0
  140. package/dist/types/modules/marketing/services/featured-marketing.service.d.ts.map +1 -1
  141. package/dist/types/modules/marketing/services/free-delivery-marketing.service.d.ts.map +1 -1
  142. package/dist/types/modules/marketing/services/index.d.ts +1 -0
  143. package/dist/types/modules/marketing/services/index.d.ts.map +1 -1
  144. package/dist/types/modules/marketing/services/marketing.service.d.ts +5 -0
  145. package/dist/types/modules/marketing/services/marketing.service.d.ts.map +1 -1
  146. package/dist/types/modules/marketing/services/product-marketing.service.d.ts +2 -0
  147. package/dist/types/modules/marketing/services/product-marketing.service.d.ts.map +1 -1
  148. package/dist/types/modules/marketing/services/punch-marketing.service.d.ts.map +1 -1
  149. package/dist/types/modules/marketing/services/synchronize-product-marketing.service.d.ts +15 -0
  150. package/dist/types/modules/marketing/services/synchronize-product-marketing.service.d.ts.map +1 -0
  151. package/dist/types/modules/marketing/transformers/buy1-get1-marketing.transformer.d.ts +2 -2
  152. package/dist/types/modules/marketing/transformers/discount-marketing.transformer.d.ts +2 -2
  153. package/dist/types/modules/marketing/validations/buy1-get1-marketing.validation.d.ts +55 -55
  154. package/dist/types/modules/marketing/validations/discount-marketing.validation.d.ts +65 -65
  155. package/dist/types/modules/marketing/validations/featured-marketing.validation.d.ts +21 -21
  156. package/dist/types/modules/marketing/validations/free-delivery-marketing.validation.d.ts +18 -18
  157. package/dist/types/modules/marketing/validations/marketing.validation.d.ts +21 -7
  158. package/dist/types/modules/marketing/validations/marketing.validation.d.ts.map +1 -1
  159. package/dist/types/modules/marketing/validations/product-marketing.validation.d.ts +4 -4
  160. package/dist/types/modules/marketing/validations/punch-marketing.validation.d.ts +22 -22
  161. package/dist/types/modules/punch-marketing-history/routers/punch-marketing-history.router.d.ts +3 -3
  162. package/dist/types/modules/punch-marketing-history/validations/punch-marketing-history.validation.d.ts +6 -6
  163. package/package.json +2 -2
@@ -263,7 +263,7 @@ let CouponService = class CouponService {
263
263
  async update(id, data) {
264
264
  let coupon;
265
265
  const [oldCoupon, oldOrders, checkCouponCode] = await Promise.all([
266
- this.model.findById(id),
266
+ this.baseCouponModel.findById(id),
267
267
  this.orderModel
268
268
  .find({
269
269
  'finance.coupon.coupon': id,
@@ -296,9 +296,6 @@ let CouponService = class CouponService {
296
296
  if (!globalCoupon.forNewUserOnly) {
297
297
  await this.exchangeCouponForMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id, coupon._id);
298
298
  }
299
- else {
300
- await this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);
301
- }
302
299
  }
303
300
  break;
304
301
  }
@@ -307,10 +304,7 @@ let CouponService = class CouponService {
307
304
  if (coupon) {
308
305
  const shopsCategoriesCoupon = coupon;
309
306
  if (!shopsCategoriesCoupon.forNewUserOnly) {
310
- await this.exchangeCouponForMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id, coupon._id);
311
- }
312
- else {
313
- await this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);
307
+ await this.exchangeCouponForMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id, shopsCategoriesCoupon._id);
314
308
  }
315
309
  }
316
310
  break;
@@ -320,10 +314,7 @@ let CouponService = class CouponService {
320
314
  if (coupon) {
321
315
  const individualStoreCoupon = coupon;
322
316
  if (!individualStoreCoupon.forNewUserOnly) {
323
- await this.exchangeCouponForMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id, coupon._id);
324
- }
325
- else {
326
- await this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);
317
+ await this.exchangeCouponForMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id, individualStoreCoupon._id);
327
318
  }
328
319
  }
329
320
  break;
@@ -333,9 +324,7 @@ let CouponService = class CouponService {
333
324
  if (coupon) {
334
325
  const individualUserCoupon = coupon;
335
326
  await this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);
336
- if (!individualUserCoupon.forNewUserOnly) {
337
- await this.assignCouponToMultipleUser({ _id: { $in: individualUserCoupon.users } }, oldCoupon._id);
338
- }
327
+ await this.assignCouponToMultipleUser({ _id: { $in: individualUserCoupon.users } }, individualUserCoupon._id);
339
328
  }
340
329
  break;
341
330
  }
@@ -358,7 +347,7 @@ let CouponService = class CouponService {
358
347
  }
359
348
  const previousVersions = oldCoupon?.previousVersions || [];
360
349
  previousVersions.push(oldCoupon._id);
361
- const updatedCoupon = await this.model.findByIdAndUpdate(coupon._id, {
350
+ const updatedCoupon = await this.baseCouponModel.findByIdAndUpdate(coupon._id, {
362
351
  $set: {
363
352
  previousVersions,
364
353
  },
@@ -372,9 +361,10 @@ let CouponService = class CouponService {
372
361
  message: `Could not set previous versions of coupon`,
373
362
  });
374
363
  }
375
- const updatedOldCoupon = await this.model.findByIdAndUpdate(oldCoupon._id, {
364
+ const updatedOldCoupon = await this.baseCouponModel.findByIdAndUpdate(oldCoupon._id, {
376
365
  $set: {
377
366
  updatedVersion: coupon._id,
367
+ 'duration.end': coupon.duration.end,
378
368
  },
379
369
  }, {
380
370
  new: true,
@@ -395,10 +385,20 @@ let CouponService = class CouponService {
395
385
  message: 'Coupon not found',
396
386
  });
397
387
  }
388
+ const previousVersions = coupon.previousVersions;
389
+ if (previousVersions && previousVersions.length > 0) {
390
+ await this.baseCouponModel.updateMany({ _id: { $in: previousVersions } }, {
391
+ $set: { status },
392
+ });
393
+ }
398
394
  return coupon;
399
395
  }
400
396
  async deleteById(data) {
401
397
  const { _id, softDelete } = data;
398
+ const coupon = await this.model.findById(_id);
399
+ if (!coupon) {
400
+ (0, error_common_1.notFoundError)('Coupon not found');
401
+ }
402
402
  const result = await this.model.deleteRecord({ _id, deletedAt: null }, softDelete);
403
403
  if (!result) {
404
404
  throw new server_1.TRPCError({
@@ -407,6 +407,10 @@ let CouponService = class CouponService {
407
407
  });
408
408
  }
409
409
  this.removeCouponFromMultipleUser({}, _id);
410
+ const previousVersions = coupon.previousVersions;
411
+ if (previousVersions && previousVersions.length > 0) {
412
+ await this.model.deleteRecord({ _id: { $in: previousVersions }, deletedAt: null }, softDelete);
413
+ }
410
414
  return 'Record deleted successfully';
411
415
  }
412
416
  async getUserCoupons(user, shop, page = 0, size = 0) {
@@ -429,16 +433,27 @@ let CouponService = class CouponService {
429
433
  if (data.coupon === 'punch') {
430
434
  return await services_1.punchMarketingHistoryService.getPunchDiscount(data);
431
435
  }
432
- const [user, coupon] = await Promise.all([
433
- this.userModel.findById(data.user),
434
- this.model.findOne({ code: data.coupon, updatedVersion: { $exists: false } }),
435
- ]);
436
+ const user = await this.userModel.findById(data.user);
436
437
  if (!user)
437
438
  (0, error_common_1.notFoundError)('User not found');
438
- if (!coupon)
439
- (0, error_common_1.notFoundError)('Coupon not found');
439
+ let coupon = await this.model.findOne({
440
+ code: data.coupon,
441
+ _id: { $in: user.coupons ?? [] },
442
+ status: { $in: [enum_1.Status.ACTIVE, null] },
443
+ });
444
+ if (!coupon) {
445
+ coupon = await this.model.findOne({
446
+ code: data.coupon,
447
+ status: { $in: [enum_1.Status.ACTIVE, null] },
448
+ couponType: { $in: [enum_1.CouponType.REFERRAL_CODE, enum_1.CouponType.CUSTOM_COUPON] },
449
+ updatedVersion: { $exists: false },
450
+ });
451
+ if (!coupon) {
452
+ (0, error_common_1.notFoundError)('Coupon not found');
453
+ }
454
+ }
440
455
  if (coupon.couponType == enum_1.CouponType.REFERRAL_CODE) {
441
- return await _1.referralCodeCouponService.validateCoupon(data);
456
+ return await _1.referralCodeCouponService.validateCoupon(data, coupon);
442
457
  }
443
458
  const baseCoupon = coupon;
444
459
  const { isValid, invalidMessage } = await this.validateBaseCoupon(baseCoupon, user._id, data.amountBeforeCoupon);
@@ -474,9 +489,9 @@ let CouponService = class CouponService {
474
489
  async validateBaseCoupon(coupon, user, orderAmount) {
475
490
  const invalidConditions = [
476
491
  this.isCouponExpired(coupon),
477
- coupon.duration.start > new Date(),
492
+ coupon.duration.start > (0, dayjs_1.dayjs)().toDate(),
478
493
  coupon.isMinOrderValueEnabled && coupon.minOrderValue && orderAmount < coupon.minOrderValue,
479
- coupon.forNewUserOnly && !(await helper_service_1.couponHelperService.isNewUser(user)),
494
+ coupon.forNewUserOnly && !(await this.verifyNewUserConditions(coupon, user)),
480
495
  coupon.isOrderLimitPerUserEnabled &&
481
496
  coupon.orderLimitPerUser &&
482
497
  (await this.getCouponOrdersForUser(user, coupon.code)) >= coupon.orderLimitPerUser,
@@ -492,6 +507,19 @@ let CouponService = class CouponService {
492
507
  const invalidMessage = invalidMessages.filter((_, index) => invalidConditions[index])?.[0];
493
508
  return { isValid, invalidMessage };
494
509
  }
510
+ async verifyNewUserConditions(coupon, user) {
511
+ const forNewUserOnly = coupon.forNewUserOnly;
512
+ const isOrderLimitPerUserEnabled = coupon.isOrderLimitPerUserEnabled;
513
+ const orderLimitPerUser = coupon.orderLimitPerUser;
514
+ if (forNewUserOnly) {
515
+ if (isOrderLimitPerUserEnabled && orderLimitPerUser) {
516
+ const orderCount = await helper_service_1.couponHelperService.getSameDeviceOrders(user);
517
+ return orderLimitPerUser > orderCount;
518
+ }
519
+ return await helper_service_1.couponHelperService.isNewUser(user);
520
+ }
521
+ return true;
522
+ }
495
523
  async getCouponOrdersForUser(user, couponCode) {
496
524
  const orders = (await this.orderModel
497
525
  .find({
@@ -503,11 +531,9 @@ let CouponService = class CouponService {
503
531
  const count = orders.filter(order => order.cart.couponCode == couponCode).length;
504
532
  return count;
505
533
  }
506
- async handleCouponExpiry(couponCode) {
507
- const coupon = await this.model.findOne({ code: couponCode, updatedVersion: { $exists: false } });
508
- if (!coupon ||
509
- coupon.couponType == enum_1.CouponType.REFERRAL_CODE ||
510
- coupon.couponType == enum_1.CouponType.REFERRAL_REWARD) {
534
+ async handleCouponExpiry(couponId) {
535
+ const coupon = await this.model.findById(couponId);
536
+ if (!coupon || coupon.couponType == enum_1.CouponType.REFERRAL_CODE) {
511
537
  return;
512
538
  }
513
539
  const typedCoupon = coupon;
@@ -562,7 +588,7 @@ let CouponService = class CouponService {
562
588
  });
563
589
  }
564
590
  async findCouponByCode(code) {
565
- const coupon = await this.model.findOne({ code: code });
591
+ const coupon = await this.model.findOne({ code: code, updatedVersion: { $exists: false } });
566
592
  if (!coupon) {
567
593
  throw new server_1.TRPCError({
568
594
  code: 'NOT_FOUND',
@@ -680,6 +706,11 @@ let CouponService = class CouponService {
680
706
  if (coupon.couponType == enum_1.CouponType.REFERRAL_CODE && !isNewUser) {
681
707
  this.throwBadRequest('This coupon is valid for new users only');
682
708
  }
709
+ if (coupon.couponType == enum_1.CouponType.REFERRAL_CODE) {
710
+ if (coupon.referralUser.toString() == user) {
711
+ this.throwBadRequest('You cannot add your own referral code');
712
+ }
713
+ }
683
714
  const typedCoupon = coupon;
684
715
  if (this.isCouponExpired(typedCoupon)) {
685
716
  this.throwBadRequest('This coupon has expired and cannot be added');
@@ -687,7 +718,7 @@ let CouponService = class CouponService {
687
718
  if (typedCoupon.forNewUserOnly && !isNewUser) {
688
719
  this.throwBadRequest('This coupon is valid for new users only');
689
720
  }
690
- const alreadyApplied = await this.hasUserAlreadyAppliedCoupon(user, typedCoupon._id);
721
+ const alreadyApplied = await this.hasUserAlreadyAppliedCoupon(user, typedCoupon);
691
722
  if (alreadyApplied) {
692
723
  this.throwBadRequest('Coupon already applied to user');
693
724
  }
@@ -699,18 +730,13 @@ let CouponService = class CouponService {
699
730
  await this.userModel.findByIdAndUpdate(user, { $push: { coupons: typedCoupon._id } }, { new: true, runValidators: true });
700
731
  return coupon;
701
732
  }
702
- async hasUserAlreadyAppliedCoupon(userId, couponId) {
703
- const user = await this.userModel.findById(userId).select('coupons');
704
- if (!user) {
705
- throw new server_1.TRPCError({
706
- code: 'NOT_FOUND',
707
- message: 'User not found',
708
- });
709
- }
710
- return (user.coupons?.some((c) => {
711
- const id = (c?._id ?? c)?.toString();
712
- return id === couponId.toString();
713
- }) ?? false);
733
+ async hasUserAlreadyAppliedCoupon(userId, coupon) {
734
+ const couponIds = [coupon._id, ...(coupon.previousVersions ?? []).map(v => v._id)];
735
+ const user = await this.userModel.exists({
736
+ _id: userId,
737
+ coupons: { $in: couponIds },
738
+ });
739
+ return !!user;
714
740
  }
715
741
  async exchangeCouponForMultipleUser(query, oldCoupon, newCoupon) {
716
742
  await this.removeCouponFromMultipleUser(query, oldCoupon);
@@ -738,6 +764,7 @@ let CouponService = class CouponService {
738
764
  code: 1,
739
765
  status: 1,
740
766
  createdAt: 1,
767
+ couponType: 1,
741
768
  };
742
769
  let isExpiredField = null;
743
770
  if (query.status) {
@@ -779,7 +806,15 @@ let CouponService = class CouponService {
779
806
  isExpired: {
780
807
  $cond: {
781
808
  if: {
782
- $or: [{ $lt: ['$duration.end', new Date()] }, { $ifNull: ['$expirationReason', false] }],
809
+ $or: [
810
+ {
811
+ $and: [
812
+ { $ifNull: ['$duration.end', false] },
813
+ { $lt: ['$duration.end', (0, dayjs_1.dayjs)().toDate()] },
814
+ ],
815
+ },
816
+ { $ifNull: ['$expirationReason', false] },
817
+ ],
783
818
  },
784
819
  then: true,
785
820
  else: false,
@@ -830,17 +865,22 @@ let CouponService = class CouponService {
830
865
  }
831
866
  }
832
867
  async addExistingCouponsToNewUser(userId) {
833
- const coupons = await this.baseCouponModel.find({
868
+ const isNewUser = await helper_service_1.couponHelperService.isNewUser(userId);
869
+ const query = {
834
870
  couponType: { $in: [enum_1.CouponType.GLOBAL, enum_1.CouponType.INDIVIDUAL_STORE, enum_1.CouponType.SHOPS_CATEGORIES] },
835
871
  deletedAt: null,
836
872
  expirationReason: null,
837
873
  $or: [
838
- { 'duration.end': { $gt: new Date() } },
874
+ { 'duration.end': { $gt: (0, dayjs_1.dayjs)().toDate() } },
839
875
  { 'duration.end': { $exists: false } },
840
876
  { 'duration.end': null },
841
877
  ],
842
878
  updatedVersion: { $exists: false },
843
- });
879
+ };
880
+ if (!isNewUser) {
881
+ query.forNewUserOnly = { $ne: true };
882
+ }
883
+ const coupons = await this.baseCouponModel.find(query);
844
884
  const couponIds = coupons.map(coupon => coupon._id);
845
885
  await this.userModel.findByIdAndUpdate(userId, {
846
886
  $addToSet: {
@@ -866,6 +906,7 @@ let CouponService = class CouponService {
866
906
  },
867
907
  ],
868
908
  'duration.end': { $gte: currentDate },
909
+ updatedVersion: { $exists: false },
869
910
  });
870
911
  if (alreadyActiveForNewUserCoupon) {
871
912
  return { exists: true };
@@ -1 +1 @@
1
- {"version":3,"file":"coupon.service.js","sourceRoot":"/","sources":["modules/coupon/services/coupon.service.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { TRPCError } from '@trpc/server';\nimport { DocumentType, mongoose, queryMethod, ReturnModelType } from '@typegoose/typegoose';\nimport {\n\tCart,\n\tCouponModel,\n\tCustomCoupon,\n\tgetCoreUserModel,\n\tGlobalCoupon,\n\tIndividualStoreCoupon,\n\tIndividualUserCoupon,\n\tCoupon as Model,\n\tReferralRewardCoupon,\n\tReferralRewardCouponModel,\n\tRegularOrder,\n\tRegularOrderModel,\n\tShopModel,\n\tShop,\n\tShopsCategoriesCoupon,\n\tUser,\n\tUserModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {\n\tAllCouponsValidationDTO,\n\tCouponValidationOutputDTO,\n\tValidateCouponDTO,\n\tAllCouponsDTO,\n\tCheckExistingNewUserCouponOutputDTO,\n} from '@modules/coupon/validations';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport {\n\tFilterDTO,\n\tPaginatedResponse,\n\tDeleteDTO,\n\tShareableLinkDTO,\n} from '@lyxa.ai/core/dist/utilities/validation';\nimport {\n\tcreateRawDocumentPaginatorObject,\n\tpaginateAggregation,\n\tPaginatorOptions,\n} from '@lyxa.ai/core/dist/utilities/pagination';\nimport { ModelType } from '@typegoose/typegoose/lib/types';\nimport {\n\tcustomCouponService,\n\tglobalCouponService,\n\tindividualStoreCouponService,\n\tindividualUserCouponService,\n\treferralCodeCouponService,\n\treferralRewardCouponService,\n} from '.';\nimport {\n\tCouponExpirationReason,\n\tCouponType,\n\tItemType,\n\tOrderType,\n\tRegularOrderStatus,\n\tStatus,\n} from '@lyxa.ai/core/dist/utilities/enum';\nimport { BaseCoupon, BaseCouponModel } from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {\n\tPunchMarketingHistoryService,\n\tpunchMarketingHistoryService,\n} from '@modules/punch-marketing-history/services';\nimport { getLibraries } from '@lyxa.ai/core';\nimport { NotificationMicroserviceRouter } from '@lyxa.ai/notification';\nimport { CouponRepository } from './patterns/repository/CouponRepository';\nimport {\n\tbadRequestError,\n\tconflictError,\n\tinternalServerError,\n\tnotFoundError,\n\tnotImplementedError,\n} from '@lyxa.ai/core/dist/utilities/error-common';\nimport { shopsCategoriesCouponService } from './shops-categories-coupon.service';\nimport { couponHelperService } from './helper.service';\nimport { dayjs } from '@lyxa.ai/core/dist/utilities/dayjs';\n\n@Service()\nexport class CouponService {\n\tprivate model: typeof CouponModel & SoftDeleteModel<Model>;\n\tprivate baseCouponModel: typeof BaseCouponModel & SoftDeleteModel<BaseCoupon>;\n\tprivate userModel: typeof UserModel & SoftDeleteModel<User>;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\tprivate shopModel: typeof ShopModel & SoftDeleteModel<Shop>;\n\tprivate referralRewardModel: typeof ReferralRewardCouponModel & SoftDeleteModel<ReferralRewardCoupon>;\n\tprivate punchHistoryService: PunchMarketingHistoryService;\n\tprivate _coreUserModel: ReturnType<typeof getCoreUserModel> | null = null;\n\n\tconstructor() {\n\t\tthis.model = CouponModel as typeof CouponModel & SoftDeleteModel<Model>;\n\t\tthis.baseCouponModel = BaseCouponModel as typeof BaseCouponModel & SoftDeleteModel<BaseCoupon>;\n\t\tthis.userModel = UserModel as typeof UserModel & SoftDeleteModel<User>;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\t\tthis.shopModel = ShopModel as typeof ShopModel & SoftDeleteModel<Shop>;\n\t\tthis.referralRewardModel = ReferralRewardCouponModel as typeof ReferralRewardCouponModel &\n\t\t\tSoftDeleteModel<ReferralRewardCoupon>;\n\t\tthis.punchHistoryService = punchMarketingHistoryService;\n\t}\n\n\tprivate get coreUserModel() {\n\t\tif (!this._coreUserModel) {\n\t\t\tthis._coreUserModel = getCoreUserModel();\n\t\t}\n\t\treturn this._coreUserModel;\n\t}\n\n\t/**\n\t * Create a new record\n\t * @param data Data for the new record\n\t */\n\tpublic async create(data: AllCouponsValidationDTO): Promise<DocumentType<Model>> {\n\t\tlet coupon: DocumentType<Model>;\n\n\t\tconst checkCoupon = await this.model.findOne({\n\t\t\tcode: data.code,\n\t\t\tdeletedAt: null,\n\t\t});\n\n\t\tif (checkCoupon) conflictError('Coupon code already exists');\n\n\t\tswitch (data.couponType) {\n\t\t\tcase CouponType.GLOBAL: {\n\t\t\t\tcoupon = await globalCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst globalCoupon = coupon as DocumentType<GlobalCoupon>;\n\t\t\t\t\tif (!globalCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.assignCouponToMultipleUser({}, coupon._id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.assignCouponToNewUsers(coupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.REFERRAL_CODE: {\n\t\t\t\tcoupon = await referralCodeCouponService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.REFERRAL_REWARD: {\n\t\t\t\tcoupon = await referralRewardCouponService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.SHOPS_CATEGORIES: {\n\t\t\t\tcoupon = await shopsCategoriesCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst shopsCategoriesCoupon = coupon as DocumentType<ShopsCategoriesCoupon>;\n\t\t\t\t\tif (!shopsCategoriesCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.assignCouponToMultipleUser({}, coupon._id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.assignCouponToNewUsers(coupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.INDIVIDUAL_STORE: {\n\t\t\t\tcoupon = await individualStoreCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst individualStoreCoupon = coupon as DocumentType<IndividualStoreCoupon>;\n\t\t\t\t\tif (!individualStoreCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.assignCouponToMultipleUser({}, coupon._id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.assignCouponToNewUsers(coupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.INDIVIDUAL_USER: {\n\t\t\t\tcoupon = await individualUserCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst individualUserCoupon = coupon as DocumentType<IndividualUserCoupon>;\n\t\t\t\t\tconst users = individualUserCoupon.users;\n\t\t\t\t\tawait this.assignCouponToMultipleUser({ _id: { $in: users } }, coupon._id);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.CUSTOM_COUPON: {\n\t\t\t\tcoupon = await customCouponService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tbadRequestError('Coupon type is not valid');\n\t\t\t}\n\t\t}\n\n\t\tif (!coupon) internalServerError('Could not create coupon');\n\n\t\t// Send Notification\n\t\tconst dispatcher = getLibraries().getMicroServiceDispatcher();\n\t\tconst notificationRouter =\n\t\t\tawait dispatcher.getMicroService<NotificationMicroserviceRouter>('notification');\n\n\t\tawait notificationRouter.notificationRouter.sendPushNotificationForCoupon.mutate(coupon._id);\n\n\t\treturn coupon;\n\t}\n\n\t/**\n\t * Get record by ID\n\t * @param id ID of the record\n\t */\n\tpublic async findById(id: string | mongoose.Types.ObjectId): Promise<DocumentType<Model>> {\n\t\tconst result = await this.model\n\t\t\t.findOne({\n\t\t\t\t_id: id,\n\t\t\t\tdeletedAt: null,\n\t\t\t})\n\t\t\t.populate([\n\t\t\t\t{\n\t\t\t\t\tpath: 'previousVersions',\n\t\t\t\t},\n\t\t\t]);\n\t\tif (!result) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Record not found',\n\t\t\t});\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get records\n\t * @param query Query to find records\n\t */\n\tpublic async find(data?: Partial<FilterDTO>): Promise<PaginatedResponse<DocumentType<ModelType<Model>>>> {\n\t\ttry {\n\t\t\tconst populate = [\n\t\t\t\t...data?.populate,\n\t\t\t\t{\n\t\t\t\t\tpath: 'users',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpath: 'influencer',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpath: 'referralUser',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpath: 'user',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpath: 'referralCodeUsedBy',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t];\n\n\t\t\tconst paginate = createRawDocumentPaginatorObject(this.model as ReturnModelType<typeof this.model>);\n\t\t\tconst options: PaginatorOptions<typeof Model> = {\n\t\t\t\tpage: data?.page,\n\t\t\t\tsize: data?.size,\n\t\t\t\tsort: data?.sort,\n\t\t\t\tquery: { ...data?.query, updatedVersion: { $exists: false } },\n\t\t\t\tselect: data?.select,\n\t\t\t\tpopulate: populate,\n\t\t\t};\n\t\t\tconst paginatedResult = await paginate(options);\n\t\t\treturn paginatedResult;\n\t\t} catch (err) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: `err: ${err}`,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Update record\n\t * @param id ID of the old coupon\n\t * @param data Data of the updated coupon\n\t */\n\tpublic async update(id: string, data: AllCouponsValidationDTO): Promise<DocumentType<Model>> {\n\t\tlet coupon: DocumentType<Model> | null;\n\n\t\tconst [oldCoupon, oldOrders, checkCouponCode] = await Promise.all([\n\t\t\tthis.model.findById(id),\n\t\t\tthis.orderModel\n\t\t\t\t.find({\n\t\t\t\t\t'finance.coupon.coupon': id,\n\t\t\t\t})\n\t\t\t\t.select(['user', 'finance']),\n\t\t\tthis.model.findOne({\n\t\t\t\tcode: data.code,\n\t\t\t\t_id: { $ne: id },\n\t\t\t\tupdatedVersion: { $exists: false },\n\t\t\t}),\n\t\t]);\n\n\t\tif (!oldCoupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: `Coupon not found`,\n\t\t\t});\n\t\t}\n\n\t\tif (checkCouponCode) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'CONFLICT',\n\t\t\t\tmessage: `Coupon code already exists`,\n\t\t\t});\n\t\t}\n\n\t\tconst oldCouponUsers = oldOrders.map(order => order.user);\n\n\t\tswitch (data.couponType) {\n\t\t\tcase CouponType.GLOBAL: {\n\t\t\t\tcoupon = await globalCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst globalCoupon = coupon as DocumentType<GlobalCoupon>;\n\t\t\t\t\tif (!globalCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.exchangeCouponForMultipleUser(\n\t\t\t\t\t\t\t{ _id: { $nin: oldCouponUsers } },\n\t\t\t\t\t\t\toldCoupon._id,\n\t\t\t\t\t\t\tcoupon._id\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CouponType.SHOPS_CATEGORIES: {\n\t\t\t\tcoupon = await shopsCategoriesCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst shopsCategoriesCoupon = coupon as DocumentType<ShopsCategoriesCoupon>;\n\t\t\t\t\tif (!shopsCategoriesCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.exchangeCouponForMultipleUser(\n\t\t\t\t\t\t\t{ _id: { $nin: oldCouponUsers } },\n\t\t\t\t\t\t\toldCoupon._id,\n\t\t\t\t\t\t\tcoupon._id\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CouponType.INDIVIDUAL_STORE: {\n\t\t\t\tcoupon = await individualStoreCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst individualStoreCoupon = coupon as DocumentType<IndividualStoreCoupon>;\n\t\t\t\t\tif (!individualStoreCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.exchangeCouponForMultipleUser(\n\t\t\t\t\t\t\t{ _id: { $nin: oldCouponUsers } },\n\t\t\t\t\t\t\toldCoupon._id,\n\t\t\t\t\t\t\tcoupon._id\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CouponType.INDIVIDUAL_USER: {\n\t\t\t\tcoupon = await individualUserCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst individualUserCoupon = coupon as DocumentType<IndividualUserCoupon>;\n\t\t\t\t\tawait this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);\n\t\t\t\t\tif (!individualUserCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.assignCouponToMultipleUser(\n\t\t\t\t\t\t\t{ _id: { $in: individualUserCoupon.users } },\n\t\t\t\t\t\t\toldCoupon._id\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CouponType.CUSTOM_COUPON: {\n\t\t\t\tcoupon = await customCouponService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: 'BAD_REQUEST',\n\t\t\t\t\tmessage: `Invalid coupon type`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (!coupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'BAD_REQUEST',\n\t\t\t\tmessage: `Could create updated coupon`,\n\t\t\t});\n\t\t}\n\n\t\t// add previous version to new coupon\n\t\tconst previousVersions = oldCoupon?.previousVersions || [];\n\t\tpreviousVersions.push(oldCoupon._id);\n\n\t\tconst updatedCoupon = await this.model.findByIdAndUpdate(\n\t\t\tcoupon._id,\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\tpreviousVersions,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\n\t\tif (!updatedCoupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: `Could not set previous versions of coupon`,\n\t\t\t});\n\t\t}\n\t\t// update old coupon\n\t\tconst updatedOldCoupon = await this.model.findByIdAndUpdate(\n\t\t\toldCoupon._id,\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\tupdatedVersion: coupon._id,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\n\t\treturn updatedCoupon;\n\t}\n\n\tpublic async updateStatus(id: string, status: Status): Promise<DocumentType<Model>> {\n\t\tconst coupon = await this.baseCouponModel.findByIdAndUpdate(\n\t\t\tid,\n\t\t\t{\n\t\t\t\t$set: { status },\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\n\t\tif (!coupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Coupon not found',\n\t\t\t});\n\t\t}\n\n\t\treturn coupon;\n\t}\n\n\t/**\n\t * Delete record\n\t * @param data Data for delete\n\t */\n\tpublic async deleteById(data: DeleteDTO): Promise<string> {\n\t\tconst { _id, softDelete } = data;\n\n\t\tconst result = await this.model.deleteRecord({ _id, deletedAt: null }, softDelete);\n\t\tif (!result) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Record not found',\n\t\t\t});\n\t\t}\n\n\t\t// remove coupons from users' coupon lists\n\t\tthis.removeCouponFromMultipleUser({}, _id);\n\n\t\treturn 'Record deleted successfully';\n\t}\n\n\t/**\n\t * Get User Coupons\n\t * @param data User and pagination data\n\t */\n\tpublic async getUserCoupons(\n\t\tuser: mongoose.Types.ObjectId | undefined,\n\t\tshop: mongoose.Types.ObjectId | undefined,\n\t\tpage: number = 0,\n\t\tsize: number = 0\n\t): Promise<{\n\t\tavailable: Array<DocumentType<Model>>;\n\t\tused: Array<DocumentType<Model>>;\n\t\texpired: Array<DocumentType<Model>>;\n\t}> {\n\t\tconst couponRepository = new CouponRepository();\n\t\tlet itemType: ItemType | undefined = undefined;\n\t\tif (shop) {\n\t\t\tconst shopDocument = await this.shopModel.findOne({ _id: shop }).select('itemType');\n\t\t\titemType = shopDocument?.itemType;\n\t\t}\n\t\tconst coupons = await couponRepository.getUserCoupons(user, shop, itemType);\n\n\t\tif (shop && user) {\n\t\t\tconst punch = await this.punchHistoryService.getPunchCoupon(user, shop);\n\t\t\tif (punch) {\n\t\t\t\tcoupons.available.unshift(punch);\n\t\t\t}\n\t\t}\n\n\t\treturn couponRepository.addLabelsToAllCoupons(coupons);\n\t}\n\n\tpublic async validateCoupon(data: ValidateCouponDTO): Promise<CouponValidationOutputDTO> {\n\t\tif (data.coupon === 'punch') {\n\t\t\treturn await punchMarketingHistoryService.getPunchDiscount(data);\n\t\t}\n\n\t\tconst [user, coupon] = await Promise.all([\n\t\t\tthis.userModel.findById(data.user),\n\t\t\tthis.model.findOne({ code: data.coupon, updatedVersion: { $exists: false } }),\n\t\t]);\n\n\t\tif (!user) notFoundError('User not found');\n\t\tif (!coupon) notFoundError('Coupon not found');\n\n\t\tif (coupon.couponType == CouponType.REFERRAL_CODE) {\n\t\t\treturn await referralCodeCouponService.validateCoupon(data);\n\t\t}\n\n\t\tconst baseCoupon = coupon as DocumentType<BaseCoupon>;\n\n\t\tconst { isValid, invalidMessage } = await this.validateBaseCoupon(\n\t\t\tbaseCoupon,\n\t\t\tuser._id,\n\t\t\tdata.amountBeforeCoupon\n\t\t);\n\n\t\tif (!isValid) {\n\t\t\treturn {\n\t\t\t\tisValid,\n\t\t\t\tmessage: invalidMessage,\n\t\t\t};\n\t\t}\n\n\t\tswitch (coupon.couponType) {\n\t\t\tcase CouponType.REFERRAL_REWARD:\n\t\t\t\treturn await referralRewardCouponService.validateCoupon(\n\t\t\t\t\tdata,\n\t\t\t\t\tcoupon as DocumentType<ReferralRewardCoupon>\n\t\t\t\t);\n\t\t\tcase CouponType.GLOBAL:\n\t\t\t\treturn await globalCouponService.validateCoupon(data, coupon as DocumentType<GlobalCoupon>);\n\t\t\tcase CouponType.SHOPS_CATEGORIES:\n\t\t\t\treturn await shopsCategoriesCouponService.validateCoupon(\n\t\t\t\t\tdata,\n\t\t\t\t\tcoupon as DocumentType<ShopsCategoriesCoupon>\n\t\t\t\t);\n\t\t\tcase CouponType.INDIVIDUAL_STORE:\n\t\t\t\treturn await individualStoreCouponService.validateCoupon(\n\t\t\t\t\tdata,\n\t\t\t\t\tcoupon as DocumentType<IndividualStoreCoupon>\n\t\t\t\t);\n\t\t\tcase CouponType.INDIVIDUAL_USER:\n\t\t\t\treturn await individualUserCouponService.validateCoupon(\n\t\t\t\t\tdata,\n\t\t\t\t\tcoupon as DocumentType<IndividualUserCoupon>\n\t\t\t\t);\n\t\t\tcase CouponType.CUSTOM_COUPON:\n\t\t\t\treturn await customCouponService.validateCoupon(data, coupon as DocumentType<CustomCoupon>);\n\t\t\tdefault:\n\t\t\t\tnotImplementedError(`Validation not implemented for ${coupon.couponType} coupons`);\n\t\t}\n\t}\n\n\tprivate isCouponExpired(coupon: DocumentType<BaseCoupon>): Boolean {\n\t\tif (coupon.expirationReason || (coupon?.duration?.end && new Date(coupon?.duration?.end) < new Date())) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t *\n\t * @param coupon Base coupon document\n\t * @param user ID of the user trying to user the coupon\n\t * @param orderAmount Order subtotal\n\t * @returns True if coupon is valid\n\t */\n\tprivate async validateBaseCoupon(\n\t\tcoupon: DocumentType<BaseCoupon>,\n\t\tuser: mongoose.Types.ObjectId,\n\t\torderAmount: number\n\t): Promise<{ isValid: boolean; invalidMessage?: string }> {\n\t\tconst invalidConditions = [\n\t\t\tthis.isCouponExpired(coupon), // check coupon expired\n\t\t\tcoupon.duration.start > new Date(), // check coupon start\n\t\t\tcoupon.isMinOrderValueEnabled && coupon.minOrderValue && orderAmount < coupon.minOrderValue, // check minimum order value\n\t\t\tcoupon.forNewUserOnly && !(await couponHelperService.isNewUser(user)), // check if new user\n\t\t\tcoupon.isOrderLimitPerUserEnabled &&\n\t\t\t\tcoupon.orderLimitPerUser &&\n\t\t\t\t(await this.getCouponOrdersForUser(user, coupon.code)) >= coupon.orderLimitPerUser, // check order limit for user\n\t\t];\n\n\t\tconst invalidMessages = [\n\t\t\t'This coupon is expired',\n\t\t\t'This coupon is not available yet',\n\t\t\t'The minimum order amount for this coupon is not met',\n\t\t\t'This coupon is for new users only',\n\t\t\t'You have reached the order limit for this coupon',\n\t\t];\n\n\t\tconst isValid = invalidConditions.every(value => Boolean(value) == false);\n\t\tconst invalidMessage = invalidMessages.filter((_, index) => invalidConditions[index])?.[0];\n\n\t\treturn { isValid, invalidMessage };\n\t}\n\n\tprivate async getCouponOrdersForUser(user: mongoose.Types.ObjectId, couponCode: string): Promise<number> {\n\t\tconst orders = (await this.orderModel\n\t\t\t.find({\n\t\t\t\tuser: user,\n\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\torderType: OrderType.REGULAR,\n\t\t\t})\n\t\t\t.populate([{ path: 'cart' }])) as Array<DocumentType<RegularOrder> & { cart: DocumentType<Cart> }>;\n\n\t\tconst count = orders.filter(order => order.cart.couponCode == couponCode).length;\n\n\t\treturn count;\n\t}\n\n\tpublic async handleCouponExpiry(couponCode: string) {\n\t\tconst coupon = await this.model.findOne({ code: couponCode, updatedVersion: { $exists: false } });\n\t\tif (\n\t\t\t!coupon ||\n\t\t\tcoupon.couponType == CouponType.REFERRAL_CODE ||\n\t\t\tcoupon.couponType == CouponType.REFERRAL_REWARD\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst typedCoupon = coupon as DocumentType<BaseCoupon>;\n\n\t\tlet expirationReason: string | null = null;\n\n\t\tif (typedCoupon.isTotalOrderLimitEnabled && typedCoupon.totalOrderLimit) {\n\t\t\t// find the order count by aggregating the order collection,\n\t\t\t// checking orders that have adjustedFinance.pricing.couponDiscount > 0,\n\t\t\t// populating cart collection to match coupon code\n\n\t\t\tconst pipeline = [\n\t\t\t\t{\n\t\t\t\t\t$match: {\n\t\t\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\t\t\t'adjustedFinance.pricing.couponDiscount': { $gt: 0 },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$lookup: {\n\t\t\t\t\t\tfrom: 'carts',\n\t\t\t\t\t\tlocalField: 'cart',\n\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\tas: 'cart',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$unwind: '$cart',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$match: {\n\t\t\t\t\t\t'cart.couponCode': typedCoupon.code,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$count: 'orderCount',\n\t\t\t\t},\n\t\t\t];\n\t\t\tconst result = await this.orderModel.aggregate(pipeline);\n\t\t\tconst orderCount = result[0]?.orderCount ?? 0;\n\n\t\t\tif (orderCount > typedCoupon.totalOrderLimit) {\n\t\t\t\texpirationReason = CouponExpirationReason.TOTAL_ORDER_LIMIT;\n\t\t\t}\n\t\t}\n\t\tif (typedCoupon.isSpendLimitEnabled && typedCoupon.spendLimit) {\n\t\t\t// spend limit\n\n\t\t\tconst { totalCouponDiscount, totalSecondaryCouponDiscount } = await this.getCouponDiscountTotals(\n\t\t\t\ttypedCoupon.code\n\t\t\t);\n\n\t\t\tif (totalCouponDiscount >= typedCoupon.spendLimit) {\n\t\t\t\texpirationReason = CouponExpirationReason.SPEND_LIMIT;\n\t\t\t}\n\t\t}\n\n\t\tawait this.baseCouponModel.findByIdAndUpdate(\n\t\t\ttypedCoupon._id,\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\texpirationReason,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\t}\n\tprivate async findCouponByCode(code: string): Promise<DocumentType<Model> | null> {\n\t\tconst coupon = await this.model.findOne({ code: code });\n\t\tif (!coupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Coupon not found',\n\t\t\t});\n\t\t}\n\t\treturn coupon;\n\t}\n\n\tprivate async getCouponDiscountTotals(couponCode: string) {\n\t\tconst pipeline = [\n\t\t\t{\n\t\t\t\t$match: {\n\t\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\t\t'adjustedFinance.pricing.couponDiscount': { $gt: 0 },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'carts',\n\t\t\t\t\tlocalField: 'cart',\n\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\tas: 'cart',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$unwind: '$cart',\n\t\t\t},\n\t\t\t{\n\t\t\t\t$match: {\n\t\t\t\t\t'cart.couponCode': couponCode,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalCouponDiscount: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$toDouble: {\n\t\t\t\t\t\t\t\t$ifNull: ['$finance.pricing.couponDiscount', 0],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\ttotalSecondaryCouponDiscount: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$toDouble: {\n\t\t\t\t\t\t\t\t$ifNull: ['$finance.pricing.secondaryCouponDiscount', 0],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tconst result = await this.orderModel.aggregate(pipeline);\n\n\t\treturn {\n\t\t\ttotalCouponDiscount: result[0]?.totalCouponDiscount ?? 0,\n\t\t\ttotalSecondaryCouponDiscount: result[0]?.totalSecondaryCouponDiscount ?? 0,\n\t\t};\n\t}\n\n\tprivate async assignCouponToUser(user: mongoose.Types.ObjectId, coupon: mongoose.Types.ObjectId) {\n\t\tconst updatedUser = await this.userModel.findByIdAndUpdate(\n\t\t\tuser,\n\t\t\t{\n\t\t\t\t$push: {\n\t\t\t\t\tcoupons: coupon,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\t}\n\n\tprivate async assignCouponToMultipleUser(\n\t\tquery: mongoose.FilterQuery<User>,\n\t\tcoupon: mongoose.Types.ObjectId\n\t) {\n\t\tconsole.log('Assigning coupon to multiple users with coupon:', coupon);\n\t\tconst updatedUsers = await this.userModel.updateMany(query, {\n\t\t\t$push: {\n\t\t\t\tcoupons: coupon,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async assignCouponToNewUsers(coupon: mongoose.Types.ObjectId) {\n\t\tconsole.log('Assigning coupon to new users', coupon);\n\n\t\tconst newUsers = await couponHelperService.getNewUsers();\n\t\tconst updatedUsers = await this.userModel.updateMany(\n\t\t\t{ _id: { $in: newUsers.map(user => user._id) } },\n\t\t\t{\n\t\t\t\t$push: {\n\t\t\t\t\tcoupons: coupon,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tprivate async removeCouponFromUser(user: mongoose.Types.ObjectId, coupon: mongoose.Types.ObjectId) {\n\t\tconst updatedUser = await this.userModel.findByIdAndUpdate(\n\t\t\tuser,\n\t\t\t{\n\t\t\t\t$pull: {\n\t\t\t\t\tcoupons: coupon,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\t}\n\n\tprivate async removeCouponFromMultipleUser(\n\t\tquery: mongoose.FilterQuery<User>,\n\t\tcoupon: mongoose.Types.ObjectId\n\t) {\n\t\tconst updatedUsers = await this.userModel.updateMany(query, {\n\t\t\t$pull: {\n\t\t\t\tcoupons: coupon,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate throwBadRequest(message: string): never {\n\t\tthrow new TRPCError({\n\t\t\tcode: 'BAD_REQUEST',\n\t\t\tmessage,\n\t\t});\n\t}\n\n\tpublic async addCouponToUser(user: any, couponCode: string): Promise<DocumentType<Model>> {\n\t\tconst coupon = await this.findCouponByCode(couponCode);\n\t\tif (!coupon) {\n\t\t\tthis.throwBadRequest('Coupon not found');\n\t\t}\n\t\tconst isNewUser = await couponHelperService.isNewUser(new mongoose.Types.ObjectId(user));\n\n\t\tif (coupon.couponType == CouponType.REFERRAL_CODE && !isNewUser) {\n\t\t\tthis.throwBadRequest('This coupon is valid for new users only');\n\t\t}\n\n\t\tconst typedCoupon = coupon as DocumentType<BaseCoupon>;\n\n\t\tif (this.isCouponExpired(typedCoupon)) {\n\t\t\tthis.throwBadRequest('This coupon has expired and cannot be added');\n\t\t}\n\n\t\tif (typedCoupon.forNewUserOnly && !isNewUser) {\n\t\t\tthis.throwBadRequest('This coupon is valid for new users only');\n\t\t}\n\n\t\tconst alreadyApplied = await this.hasUserAlreadyAppliedCoupon(user, typedCoupon._id);\n\t\tif (alreadyApplied) {\n\t\t\tthis.throwBadRequest('Coupon already applied to user');\n\t\t}\n\n\t\tif (typedCoupon.couponType == CouponType.INDIVIDUAL_USER) {\n\t\t\tif (!(typedCoupon as DocumentType<IndividualUserCoupon>).users?.includes(user)) {\n\t\t\t\tthis.throwBadRequest('This coupon is not assigned to this user');\n\t\t\t}\n\t\t}\n\n\t\tawait this.userModel.findByIdAndUpdate(\n\t\t\tuser,\n\t\t\t{ $push: { coupons: typedCoupon._id } },\n\t\t\t{ new: true, runValidators: true }\n\t\t);\n\n\t\treturn coupon;\n\t}\n\n\tprivate async hasUserAlreadyAppliedCoupon(\n\t\tuserId: mongoose.Types.ObjectId,\n\t\tcouponId: mongoose.Types.ObjectId\n\t): Promise<boolean> {\n\t\tconst user = await this.userModel.findById(userId).select('coupons');\n\t\tif (!user) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'User not found',\n\t\t\t});\n\t\t}\n\n\t\treturn (\n\t\t\tuser.coupons?.some((c: any) => {\n\t\t\t\tconst id = (c?._id ?? c)?.toString();\n\t\t\t\treturn id === couponId.toString();\n\t\t\t}) ?? false\n\t\t);\n\t}\n\n\tprivate async exchangeCouponForMultipleUser(\n\t\tquery: mongoose.FilterQuery<User>,\n\t\toldCoupon: mongoose.Types.ObjectId,\n\t\tnewCoupon: mongoose.Types.ObjectId\n\t) {\n\t\tawait this.removeCouponFromMultipleUser(query, oldCoupon);\n\t\tawait this.assignCouponToMultipleUser(query, newCoupon);\n\t}\n\n\tpublic getShareableLink = async (code: string): Promise<ShareableLinkDTO> => {\n\t\tconst secretsService = getLibraries().getSecretsService();\n\t\tconst deepLinkUrl = (await secretsService.getKey('DEEP_LINK_URL')) ?? 'https://link.lyxa.ai';\n\n\t\tconst link = `${deepLinkUrl}/invite/${code}`;\n\n\t\tconst message = `Download Lyxa and explore the wide variety of offerings and benefits! Use my code at checkout to claim a special coupon : ${code}.\n\t\t${link}`;\n\n\t\treturn { link, message };\n\t};\n\n\tpublic async getUserCouponList(data?: Partial<FilterDTO>): Promise<PaginatedResponse<AllCouponsDTO>> {\n\t\ttry {\n\t\t\tlet query = data?.query || {};\n\n\t\t\tif (!query.user) {\n\t\t\t\tbadRequestError('User ID is required in query');\n\t\t\t}\n\n\t\t\tconst select = data?.select || {\n\t\t\t\t_id: 1,\n\t\t\t\t'createdBy.name': 1,\n\t\t\t\t'duration.start': 1,\n\t\t\t\t'duration.end': 1,\n\t\t\t\tcode: 1,\n\t\t\t\tstatus: 1,\n\t\t\t\tcreatedAt: 1,\n\t\t\t};\n\n\t\t\tlet isExpiredField = null;\n\n\t\t\tif (query.status) {\n\t\t\t\tif (query.status === 'expired') {\n\t\t\t\t\tisExpiredField = true;\n\t\t\t\t\tdelete query.status;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (query.createdAt) {\n\t\t\t\t// convert to date range\n\t\t\t\tif ('$gte' in query.createdAt) {\n\t\t\t\t\tquery.createdAt.$gte = new Date(query.createdAt.$gte);\n\t\t\t\t}\n\t\t\t\tif ('$lte' in query.createdAt) {\n\t\t\t\t\tquery.createdAt.$lte = new Date(query.createdAt.$lte);\n\t\t\t\t}\n\t\t\t\tif ('$gt' in query.createdAt) {\n\t\t\t\t\tquery.createdAt.$gt = new Date(query.createdAt.$gt);\n\t\t\t\t}\n\t\t\t\tif ('$lt' in query.createdAt) {\n\t\t\t\t\tquery.createdAt.$lt = new Date(query.createdAt.$lt);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst user = await this.userModel.findById(query.user).select('coupons');\n\t\t\tquery._id = { $in: user?.coupons ?? [] };\n\t\t\tdelete query.user; // remove user from query to avoid issues in aggregation match stage\n\n\t\t\tconst pipeline: any[] = [\n\t\t\t\t{ $match: { ...query, deletedAt: null } }, // Filter by search query\n\t\t\t\t{\n\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t// INNER JOIN on categories\n\t\t\t\t\t\tfrom: 'admins', // Mongoose auto-pluralizes collection names\n\t\t\t\t\t\tlocalField: 'createdBy',\n\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\tas: 'createdBy',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $unwind: { path: '$createdBy', preserveNullAndEmptyArrays: true } }, // Flatten the array\n\t\t\t\t{\n\t\t\t\t\t$addFields: {\n\t\t\t\t\t\tisExpired: {\n\t\t\t\t\t\t\t$cond: {\n\t\t\t\t\t\t\t\tif: {\n\t\t\t\t\t\t\t\t\t$or: [{ $lt: ['$duration.end', new Date()] }, { $ifNull: ['$expirationReason', false] }],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tthen: true,\n\t\t\t\t\t\t\t\telse: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$match: isExpiredField\n\t\t\t\t\t\t? { isExpired: true }\n\t\t\t\t\t\t: query.status === 'active'\n\t\t\t\t\t\t\t? { isExpired: false }\n\t\t\t\t\t\t\t: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$addFields: {\n\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t$cond: {\n\t\t\t\t\t\t\t\tif: { $eq: ['$isExpired', true] },\n\t\t\t\t\t\t\t\tthen: 'expired',\n\t\t\t\t\t\t\t\telse: '$status',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$project: select,\n\t\t\t\t},\n\t\t\t];\n\n\t\t\tif (data?.search?.searchKey) {\n\t\t\t\tconst searchKey = data.search.searchKey;\n\t\t\t\tconst regex = new RegExp(searchKey, 'i'); // case-insensitive search\n\t\t\t\tconst fields = data.search.searchFields?.length ? data.search.searchFields : ['code']; // default field(s) to search in\n\n\t\t\t\tpipeline.push({\n\t\t\t\t\t$match: {\n\t\t\t\t\t\t$or: fields.map(field => ({ [field]: { $regex: regex } })),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Execute the aggregation with pagination and sorting\n\t\t\tconst results = await paginateAggregation(this.model, pipeline, data?.page, data?.size, data?.sort);\n\n\t\t\treturn results as unknown as PaginatedResponse<AllCouponsDTO>;\n\t\t} catch (err) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: `err: ${err}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic async addExistingCouponsToNewUser(userId: mongoose.Types.ObjectId) {\n\t\t// assign all coupons that are not expired\n\t\tconst coupons = await this.baseCouponModel.find({\n\t\t\tcouponType: { $in: [CouponType.GLOBAL, CouponType.INDIVIDUAL_STORE, CouponType.SHOPS_CATEGORIES] },\n\t\t\tdeletedAt: null,\n\t\t\texpirationReason: null,\n\t\t\t$or: [\n\t\t\t\t{ 'duration.end': { $gt: new Date() } },\n\t\t\t\t{ 'duration.end': { $exists: false } },\n\t\t\t\t{ 'duration.end': null },\n\t\t\t],\n\t\t\tupdatedVersion: { $exists: false },\n\t\t});\n\n\t\tconst couponIds = coupons.map(coupon => coupon._id);\n\n\t\tawait this.userModel.findByIdAndUpdate(\n\t\t\tuserId,\n\t\t\t{\n\t\t\t\t$addToSet: {\n\t\t\t\t\tcoupons: { $each: couponIds },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic async checkExistingNewUserCoupon(): Promise<CheckExistingNewUserCouponOutputDTO> {\n\t\tconst currentDate = dayjs().toDate();\n\t\tconst alreadyActiveForNewUserCoupon = await this.baseCouponModel.findOne({\n\t\t\tcouponType: CouponType.GLOBAL,\n\t\t\tforNewUserOnly: true,\n\t\t\tdeletedAt: null,\n\t\t\t$or: [\n\t\t\t\t{\n\t\t\t\t\texpirationReason: { $exists: false },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\texpirationReason: null,\n\t\t\t\t},\n\t\t\t],\n\t\t\t'duration.end': { $gte: currentDate },\n\t\t});\n\n\t\tif (alreadyActiveForNewUserCoupon) {\n\t\t\treturn { exists: true };\n\t\t}\n\t\treturn { exists: false };\n\t}\n}\n\nexport const couponService = Container.get(CouponService);\n"]}
1
+ {"version":3,"file":"coupon.service.js","sourceRoot":"/","sources":["modules/coupon/services/coupon.service.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { TRPCError } from '@trpc/server';\nimport { DocumentType, mongoose, queryMethod, ReturnModelType } from '@typegoose/typegoose';\nimport {\n\tCart,\n\tCouponModel,\n\tCustomCoupon,\n\tgetCoreUserModel,\n\tGlobalCoupon,\n\tIndividualStoreCoupon,\n\tIndividualUserCoupon,\n\tCoupon as Model,\n\tReferralRewardCoupon,\n\tReferralRewardCouponModel,\n\tRegularOrder,\n\tRegularOrderModel,\n\tShopModel,\n\tShop,\n\tShopsCategoriesCoupon,\n\tUser,\n\tUserModel,\n\tReferralCodeCoupon,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {\n\tAllCouponsValidationDTO,\n\tCouponValidationOutputDTO,\n\tValidateCouponDTO,\n\tAllCouponsDTO,\n\tCheckExistingNewUserCouponOutputDTO,\n} from '@modules/coupon/validations';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport {\n\tFilterDTO,\n\tPaginatedResponse,\n\tDeleteDTO,\n\tShareableLinkDTO,\n} from '@lyxa.ai/core/dist/utilities/validation';\nimport {\n\tcreateRawDocumentPaginatorObject,\n\tpaginateAggregation,\n\tPaginatorOptions,\n} from '@lyxa.ai/core/dist/utilities/pagination';\nimport { ModelType } from '@typegoose/typegoose/lib/types';\nimport {\n\tcustomCouponService,\n\tglobalCouponService,\n\tindividualStoreCouponService,\n\tindividualUserCouponService,\n\treferralCodeCouponService,\n\treferralRewardCouponService,\n} from '.';\nimport {\n\tCouponExpirationReason,\n\tCouponType,\n\tItemType,\n\tOrderType,\n\tRegularOrderStatus,\n\tStatus,\n} from '@lyxa.ai/core/dist/utilities/enum';\nimport { BaseCoupon, BaseCouponModel } from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {\n\tPunchMarketingHistoryService,\n\tpunchMarketingHistoryService,\n} from '@modules/punch-marketing-history/services';\nimport { getLibraries } from '@lyxa.ai/core';\nimport { NotificationMicroserviceRouter } from '@lyxa.ai/notification';\nimport { CouponRepository } from './patterns/repository/CouponRepository';\nimport {\n\tbadRequestError,\n\tconflictError,\n\tinternalServerError,\n\tnotFoundError,\n\tnotImplementedError,\n} from '@lyxa.ai/core/dist/utilities/error-common';\nimport { shopsCategoriesCouponService } from './shops-categories-coupon.service';\nimport { couponHelperService } from './helper.service';\nimport { dayjs } from '@lyxa.ai/core/dist/utilities/dayjs';\n\n@Service()\nexport class CouponService {\n\tprivate model: typeof CouponModel & SoftDeleteModel<Model>;\n\tprivate baseCouponModel: typeof BaseCouponModel & SoftDeleteModel<BaseCoupon>;\n\tprivate userModel: typeof UserModel & SoftDeleteModel<User>;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\tprivate shopModel: typeof ShopModel & SoftDeleteModel<Shop>;\n\tprivate referralRewardModel: typeof ReferralRewardCouponModel & SoftDeleteModel<ReferralRewardCoupon>;\n\tprivate punchHistoryService: PunchMarketingHistoryService;\n\tprivate _coreUserModel: ReturnType<typeof getCoreUserModel> | null = null;\n\n\tconstructor() {\n\t\tthis.model = CouponModel as typeof CouponModel & SoftDeleteModel<Model>;\n\t\tthis.baseCouponModel = BaseCouponModel as typeof BaseCouponModel & SoftDeleteModel<BaseCoupon>;\n\t\tthis.userModel = UserModel as typeof UserModel & SoftDeleteModel<User>;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\t\tthis.shopModel = ShopModel as typeof ShopModel & SoftDeleteModel<Shop>;\n\t\tthis.referralRewardModel = ReferralRewardCouponModel as typeof ReferralRewardCouponModel &\n\t\t\tSoftDeleteModel<ReferralRewardCoupon>;\n\t\tthis.punchHistoryService = punchMarketingHistoryService;\n\t}\n\n\tprivate get coreUserModel() {\n\t\tif (!this._coreUserModel) {\n\t\t\tthis._coreUserModel = getCoreUserModel();\n\t\t}\n\t\treturn this._coreUserModel;\n\t}\n\n\t/**\n\t * Create a new record\n\t * @param data Data for the new record\n\t */\n\tpublic async create(data: AllCouponsValidationDTO): Promise<DocumentType<Model>> {\n\t\tlet coupon: DocumentType<Model>;\n\n\t\tconst checkCoupon = await this.model.findOne({\n\t\t\tcode: data.code,\n\t\t\tdeletedAt: null,\n\t\t});\n\n\t\tif (checkCoupon) conflictError('Coupon code already exists');\n\n\t\tswitch (data.couponType) {\n\t\t\tcase CouponType.GLOBAL: {\n\t\t\t\tcoupon = await globalCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst globalCoupon = coupon as DocumentType<GlobalCoupon>;\n\t\t\t\t\tif (!globalCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.assignCouponToMultipleUser({}, coupon._id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.assignCouponToNewUsers(coupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.REFERRAL_CODE: {\n\t\t\t\tcoupon = await referralCodeCouponService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.REFERRAL_REWARD: {\n\t\t\t\tcoupon = await referralRewardCouponService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.SHOPS_CATEGORIES: {\n\t\t\t\tcoupon = await shopsCategoriesCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst shopsCategoriesCoupon = coupon as DocumentType<ShopsCategoriesCoupon>;\n\t\t\t\t\tif (!shopsCategoriesCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.assignCouponToMultipleUser({}, coupon._id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.assignCouponToNewUsers(coupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.INDIVIDUAL_STORE: {\n\t\t\t\tcoupon = await individualStoreCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst individualStoreCoupon = coupon as DocumentType<IndividualStoreCoupon>;\n\t\t\t\t\tif (!individualStoreCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.assignCouponToMultipleUser({}, coupon._id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait this.assignCouponToNewUsers(coupon._id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.INDIVIDUAL_USER: {\n\t\t\t\tcoupon = await individualUserCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst individualUserCoupon = coupon as DocumentType<IndividualUserCoupon>;\n\t\t\t\t\tconst users = individualUserCoupon.users;\n\t\t\t\t\tawait this.assignCouponToMultipleUser({ _id: { $in: users } }, coupon._id);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase CouponType.CUSTOM_COUPON: {\n\t\t\t\tcoupon = await customCouponService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tbadRequestError('Coupon type is not valid');\n\t\t\t}\n\t\t}\n\n\t\tif (!coupon) internalServerError('Could not create coupon');\n\n\t\t// Send Notification\n\t\tconst dispatcher = getLibraries().getMicroServiceDispatcher();\n\t\tconst notificationRouter =\n\t\t\tawait dispatcher.getMicroService<NotificationMicroserviceRouter>('notification');\n\n\t\tawait notificationRouter.notificationRouter.sendPushNotificationForCoupon.mutate(coupon._id);\n\n\t\treturn coupon;\n\t}\n\n\t/**\n\t * Get record by ID\n\t * @param id ID of the record\n\t */\n\tpublic async findById(id: string | mongoose.Types.ObjectId): Promise<DocumentType<Model>> {\n\t\tconst result = await this.model\n\t\t\t.findOne({\n\t\t\t\t_id: id,\n\t\t\t\tdeletedAt: null,\n\t\t\t})\n\t\t\t.populate([\n\t\t\t\t{\n\t\t\t\t\tpath: 'previousVersions',\n\t\t\t\t},\n\t\t\t]);\n\t\tif (!result) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Record not found',\n\t\t\t});\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Get records\n\t * @param query Query to find records\n\t */\n\tpublic async find(data?: Partial<FilterDTO>): Promise<PaginatedResponse<DocumentType<ModelType<Model>>>> {\n\t\ttry {\n\t\t\tconst populate = [\n\t\t\t\t...data?.populate,\n\t\t\t\t{\n\t\t\t\t\tpath: 'users',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpath: 'influencer',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpath: 'referralUser',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpath: 'user',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tpath: 'referralCodeUsedBy',\n\t\t\t\t\tpopulate: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: 'coreUser',\n\t\t\t\t\t\t\tmodel: this.coreUserModel,\n\t\t\t\t\t\t\tselect: 'name profilePhoto -_id',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tselect: 'coreUser phoneNumber',\n\t\t\t\t},\n\t\t\t];\n\n\t\t\tconst paginate = createRawDocumentPaginatorObject(this.model as ReturnModelType<typeof this.model>);\n\t\t\tconst options: PaginatorOptions<typeof Model> = {\n\t\t\t\tpage: data?.page,\n\t\t\t\tsize: data?.size,\n\t\t\t\tsort: data?.sort,\n\t\t\t\tquery: { ...data?.query, updatedVersion: { $exists: false } },\n\t\t\t\tselect: data?.select,\n\t\t\t\tpopulate: populate,\n\t\t\t};\n\t\t\tconst paginatedResult = await paginate(options);\n\t\t\treturn paginatedResult;\n\t\t} catch (err) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: `err: ${err}`,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Update record\n\t * @param id ID of the old coupon\n\t * @param data Data of the updated coupon\n\t */\n\tpublic async update(id: string, data: AllCouponsValidationDTO): Promise<DocumentType<Model>> {\n\t\tlet coupon: DocumentType<BaseCoupon> | null;\n\n\t\tconst [oldCoupon, oldOrders, checkCouponCode] = await Promise.all([\n\t\t\tthis.baseCouponModel.findById(id),\n\t\t\tthis.orderModel\n\t\t\t\t.find({\n\t\t\t\t\t'finance.coupon.coupon': id,\n\t\t\t\t})\n\t\t\t\t.select(['user', 'finance']),\n\t\t\tthis.model.findOne({\n\t\t\t\tcode: data.code,\n\t\t\t\t_id: { $ne: id },\n\t\t\t\tupdatedVersion: { $exists: false },\n\t\t\t}),\n\t\t]);\n\n\t\tif (!oldCoupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: `Coupon not found`,\n\t\t\t});\n\t\t}\n\n\t\tif (checkCouponCode) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'CONFLICT',\n\t\t\t\tmessage: `Coupon code already exists`,\n\t\t\t});\n\t\t}\n\n\t\tconst oldCouponUsers = oldOrders.map(order => order.user);\n\n\t\tswitch (data.couponType) {\n\t\t\tcase CouponType.GLOBAL: {\n\t\t\t\tcoupon = await globalCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst globalCoupon = coupon as DocumentType<GlobalCoupon>;\n\t\t\t\t\tif (!globalCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.exchangeCouponForMultipleUser(\n\t\t\t\t\t\t\t{ _id: { $nin: oldCouponUsers } },\n\t\t\t\t\t\t\toldCoupon._id,\n\t\t\t\t\t\t\tcoupon._id\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CouponType.SHOPS_CATEGORIES: {\n\t\t\t\tcoupon = await shopsCategoriesCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst shopsCategoriesCoupon = coupon as DocumentType<ShopsCategoriesCoupon>;\n\t\t\t\t\tif (!shopsCategoriesCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.exchangeCouponForMultipleUser(\n\t\t\t\t\t\t\t{ _id: { $nin: oldCouponUsers } },\n\t\t\t\t\t\t\toldCoupon._id,\n\t\t\t\t\t\t\tshopsCategoriesCoupon._id\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CouponType.INDIVIDUAL_STORE: {\n\t\t\t\tcoupon = await individualStoreCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst individualStoreCoupon = coupon as DocumentType<IndividualStoreCoupon>;\n\t\t\t\t\tif (!individualStoreCoupon.forNewUserOnly) {\n\t\t\t\t\t\tawait this.exchangeCouponForMultipleUser(\n\t\t\t\t\t\t\t{ _id: { $nin: oldCouponUsers } },\n\t\t\t\t\t\t\toldCoupon._id,\n\t\t\t\t\t\t\tindividualStoreCoupon._id\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CouponType.INDIVIDUAL_USER: {\n\t\t\t\tcoupon = await individualUserCouponService.create(data);\n\t\t\t\tif (coupon) {\n\t\t\t\t\tconst individualUserCoupon = coupon as DocumentType<IndividualUserCoupon>;\n\t\t\t\t\tawait this.removeCouponFromMultipleUser({ _id: { $nin: oldCouponUsers } }, oldCoupon._id);\n\t\t\t\t\tawait this.assignCouponToMultipleUser(\n\t\t\t\t\t\t{ _id: { $in: individualUserCoupon.users } },\n\t\t\t\t\t\tindividualUserCoupon._id\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CouponType.CUSTOM_COUPON: {\n\t\t\t\tcoupon = await customCouponService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: 'BAD_REQUEST',\n\t\t\t\t\tmessage: `Invalid coupon type`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (!coupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'BAD_REQUEST',\n\t\t\t\tmessage: `Could create updated coupon`,\n\t\t\t});\n\t\t}\n\n\t\t// add previous version to new coupon\n\t\tconst previousVersions = oldCoupon?.previousVersions || [];\n\t\tpreviousVersions.push(oldCoupon._id);\n\n\t\tconst updatedCoupon = await this.baseCouponModel.findByIdAndUpdate(\n\t\t\tcoupon._id,\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\tpreviousVersions,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\n\t\tif (!updatedCoupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: `Could not set previous versions of coupon`,\n\t\t\t});\n\t\t}\n\t\t// update old coupon\n\t\tconst updatedOldCoupon = await this.baseCouponModel.findByIdAndUpdate(\n\t\t\toldCoupon._id,\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\tupdatedVersion: coupon._id,\n\t\t\t\t\t'duration.end': coupon.duration.end,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\n\t\treturn updatedCoupon;\n\t}\n\n\tpublic async updateStatus(id: string, status: Status): Promise<DocumentType<Model>> {\n\t\tconst coupon = await this.baseCouponModel.findByIdAndUpdate(\n\t\t\tid,\n\t\t\t{\n\t\t\t\t$set: { status },\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\n\t\tif (!coupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Coupon not found',\n\t\t\t});\n\t\t}\n\n\t\t// also update the status of previous versions of the coupon\n\t\tconst previousVersions = coupon.previousVersions;\n\t\tif (previousVersions && previousVersions.length > 0) {\n\t\t\tawait this.baseCouponModel.updateMany(\n\t\t\t\t{ _id: { $in: previousVersions } },\n\t\t\t\t{\n\t\t\t\t\t$set: { status },\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\treturn coupon;\n\t}\n\n\t/**\n\t * Delete record\n\t * @param data Data for delete\n\t */\n\tpublic async deleteById(data: DeleteDTO): Promise<string> {\n\t\tconst { _id, softDelete } = data;\n\n\t\tconst coupon = await this.model.findById(_id);\n\n\t\tif (!coupon) {\n\t\t\tnotFoundError('Coupon not found');\n\t\t}\n\n\t\tconst result = await this.model.deleteRecord({ _id, deletedAt: null }, softDelete);\n\t\tif (!result) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Record not found',\n\t\t\t});\n\t\t}\n\n\t\t// remove coupons from users' coupon lists\n\t\tthis.removeCouponFromMultipleUser({}, _id);\n\n\t\t// also delete previous versions of the coupon\n\t\tconst previousVersions = coupon.previousVersions;\n\t\tif (previousVersions && previousVersions.length > 0) {\n\t\t\tawait this.model.deleteRecord({ _id: { $in: previousVersions }, deletedAt: null }, softDelete);\n\t\t}\n\n\t\treturn 'Record deleted successfully';\n\t}\n\n\t/**\n\t * Get User Coupons\n\t * @param data User and pagination data\n\t */\n\tpublic async getUserCoupons(\n\t\tuser: mongoose.Types.ObjectId | undefined,\n\t\tshop: mongoose.Types.ObjectId | undefined,\n\t\tpage: number = 0,\n\t\tsize: number = 0\n\t): Promise<{\n\t\tavailable: Array<DocumentType<Model>>;\n\t\tused: Array<DocumentType<Model>>;\n\t\texpired: Array<DocumentType<Model>>;\n\t}> {\n\t\tconst couponRepository = new CouponRepository();\n\t\tlet itemType: ItemType | undefined = undefined;\n\t\tif (shop) {\n\t\t\tconst shopDocument = await this.shopModel.findOne({ _id: shop }).select('itemType');\n\t\t\titemType = shopDocument?.itemType;\n\t\t}\n\t\tconst coupons = await couponRepository.getUserCoupons(user, shop, itemType);\n\n\t\tif (shop && user) {\n\t\t\tconst punch = await this.punchHistoryService.getPunchCoupon(user, shop);\n\t\t\tif (punch) {\n\t\t\t\tcoupons.available.unshift(punch);\n\t\t\t}\n\t\t}\n\n\t\treturn couponRepository.addLabelsToAllCoupons(coupons);\n\t}\n\n\tpublic async validateCoupon(data: ValidateCouponDTO): Promise<CouponValidationOutputDTO> {\n\t\tif (data.coupon === 'punch') {\n\t\t\treturn await punchMarketingHistoryService.getPunchDiscount(data);\n\t\t}\n\n\t\tconst user = await this.userModel.findById(data.user);\n\t\tif (!user) notFoundError('User not found');\n\n\t\tlet coupon = await this.model.findOne({\n\t\t\tcode: data.coupon,\n\t\t\t_id: { $in: user.coupons ?? [] },\n\t\t\tstatus: { $in: [Status.ACTIVE, null] },\n\t\t});\n\n\t\tif (!coupon) {\n\t\t\tcoupon = await this.model.findOne({\n\t\t\t\tcode: data.coupon,\n\t\t\t\tstatus: { $in: [Status.ACTIVE, null] },\n\t\t\t\tcouponType: { $in: [CouponType.REFERRAL_CODE, CouponType.CUSTOM_COUPON] },\n\t\t\t\tupdatedVersion: { $exists: false },\n\t\t\t});\n\n\t\t\tif (!coupon) {\n\t\t\t\tnotFoundError('Coupon not found');\n\t\t\t}\n\t\t}\n\n\t\tif (coupon.couponType == CouponType.REFERRAL_CODE) {\n\t\t\treturn await referralCodeCouponService.validateCoupon(data, coupon as DocumentType<ReferralCodeCoupon>);\n\t\t}\n\n\t\tconst baseCoupon = coupon as DocumentType<BaseCoupon>;\n\n\t\tconst { isValid, invalidMessage } = await this.validateBaseCoupon(\n\t\t\tbaseCoupon,\n\t\t\tuser._id,\n\t\t\tdata.amountBeforeCoupon\n\t\t);\n\n\t\tif (!isValid) {\n\t\t\treturn {\n\t\t\t\tisValid,\n\t\t\t\tmessage: invalidMessage,\n\t\t\t};\n\t\t}\n\n\t\tswitch (coupon.couponType) {\n\t\t\tcase CouponType.REFERRAL_REWARD:\n\t\t\t\treturn await referralRewardCouponService.validateCoupon(\n\t\t\t\t\tdata,\n\t\t\t\t\tcoupon as DocumentType<ReferralRewardCoupon>\n\t\t\t\t);\n\t\t\tcase CouponType.GLOBAL:\n\t\t\t\treturn await globalCouponService.validateCoupon(data, coupon as DocumentType<GlobalCoupon>);\n\t\t\tcase CouponType.SHOPS_CATEGORIES:\n\t\t\t\treturn await shopsCategoriesCouponService.validateCoupon(\n\t\t\t\t\tdata,\n\t\t\t\t\tcoupon as DocumentType<ShopsCategoriesCoupon>\n\t\t\t\t);\n\t\t\tcase CouponType.INDIVIDUAL_STORE:\n\t\t\t\treturn await individualStoreCouponService.validateCoupon(\n\t\t\t\t\tdata,\n\t\t\t\t\tcoupon as DocumentType<IndividualStoreCoupon>\n\t\t\t\t);\n\t\t\tcase CouponType.INDIVIDUAL_USER:\n\t\t\t\treturn await individualUserCouponService.validateCoupon(\n\t\t\t\t\tdata,\n\t\t\t\t\tcoupon as DocumentType<IndividualUserCoupon>\n\t\t\t\t);\n\t\t\tcase CouponType.CUSTOM_COUPON:\n\t\t\t\treturn await customCouponService.validateCoupon(data, coupon as DocumentType<CustomCoupon>);\n\t\t\tdefault:\n\t\t\t\tnotImplementedError(`Validation not implemented for ${coupon.couponType} coupons`);\n\t\t}\n\t}\n\n\tprivate isCouponExpired(coupon: DocumentType<BaseCoupon>): Boolean {\n\t\tif (coupon.expirationReason || (coupon?.duration?.end && new Date(coupon?.duration?.end) < new Date())) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t *\n\t * @param coupon Base coupon document\n\t * @param user ID of the user trying to user the coupon\n\t * @param orderAmount Order subtotal\n\t * @returns True if coupon is valid\n\t */\n\tprivate async validateBaseCoupon(\n\t\tcoupon: DocumentType<BaseCoupon>,\n\t\tuser: mongoose.Types.ObjectId,\n\t\torderAmount: number\n\t): Promise<{ isValid: boolean; invalidMessage?: string }> {\n\t\tconst invalidConditions = [\n\t\t\tthis.isCouponExpired(coupon), // check coupon expired\n\t\t\tcoupon.duration.start > dayjs().toDate(), // check coupon start\n\t\t\tcoupon.isMinOrderValueEnabled && coupon.minOrderValue && orderAmount < coupon.minOrderValue, // check minimum order value\n\t\t\tcoupon.forNewUserOnly && !(await this.verifyNewUserConditions(coupon, user)), // check if new user\n\t\t\tcoupon.isOrderLimitPerUserEnabled &&\n\t\t\t\tcoupon.orderLimitPerUser &&\n\t\t\t\t(await this.getCouponOrdersForUser(user, coupon.code)) >= coupon.orderLimitPerUser, // check order limit for user\n\t\t];\n\n\t\tconst invalidMessages = [\n\t\t\t'This coupon is expired',\n\t\t\t'This coupon is not available yet',\n\t\t\t'The minimum order amount for this coupon is not met',\n\t\t\t'This coupon is for new users only',\n\t\t\t'You have reached the order limit for this coupon',\n\t\t];\n\n\t\tconst isValid = invalidConditions.every(value => Boolean(value) == false);\n\t\tconst invalidMessage = invalidMessages.filter((_, index) => invalidConditions[index])?.[0];\n\n\t\treturn { isValid, invalidMessage };\n\t}\n\n\t// Returns true if new user conditions are met. False otherwise\n\tprivate async verifyNewUserConditions(\n\t\tcoupon: DocumentType<BaseCoupon>,\n\t\tuser: mongoose.Types.ObjectId\n\t): Promise<boolean> {\n\t\tconst forNewUserOnly = coupon.forNewUserOnly;\n\t\tconst isOrderLimitPerUserEnabled = coupon.isOrderLimitPerUserEnabled;\n\t\tconst orderLimitPerUser = coupon.orderLimitPerUser;\n\n\t\tif (forNewUserOnly) {\n\t\t\tif (isOrderLimitPerUserEnabled && orderLimitPerUser) {\n\t\t\t\tconst orderCount = await couponHelperService.getSameDeviceOrders(user);\n\t\t\t\treturn orderLimitPerUser > orderCount;\n\t\t\t}\n\t\t\treturn await couponHelperService.isNewUser(user);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate async getCouponOrdersForUser(user: mongoose.Types.ObjectId, couponCode: string): Promise<number> {\n\t\tconst orders = (await this.orderModel\n\t\t\t.find({\n\t\t\t\tuser: user,\n\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\torderType: OrderType.REGULAR,\n\t\t\t})\n\t\t\t.populate([{ path: 'cart' }])) as Array<DocumentType<RegularOrder> & { cart: DocumentType<Cart> }>;\n\n\t\tconst count = orders.filter(order => order.cart.couponCode == couponCode).length;\n\n\t\treturn count;\n\t}\n\n\tpublic async handleCouponExpiry(couponId: mongoose.Types.ObjectId) {\n\t\tconst coupon = await this.model.findById(couponId);\n\t\tif (!coupon || coupon.couponType == CouponType.REFERRAL_CODE) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst typedCoupon = coupon as DocumentType<BaseCoupon>;\n\n\t\tlet expirationReason: string | null = null;\n\n\t\tif (typedCoupon.isTotalOrderLimitEnabled && typedCoupon.totalOrderLimit) {\n\t\t\t// find the order count by aggregating the order collection,\n\t\t\t// checking orders that have adjustedFinance.pricing.couponDiscount > 0,\n\t\t\t// populating cart collection to match coupon code\n\n\t\t\tconst pipeline = [\n\t\t\t\t{\n\t\t\t\t\t$match: {\n\t\t\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\t\t\t'adjustedFinance.pricing.couponDiscount': { $gt: 0 },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$lookup: {\n\t\t\t\t\t\tfrom: 'carts',\n\t\t\t\t\t\tlocalField: 'cart',\n\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\tas: 'cart',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$unwind: '$cart',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$match: {\n\t\t\t\t\t\t'cart.couponCode': typedCoupon.code,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$count: 'orderCount',\n\t\t\t\t},\n\t\t\t];\n\t\t\tconst result = await this.orderModel.aggregate(pipeline);\n\t\t\tconst orderCount = result[0]?.orderCount ?? 0;\n\n\t\t\tif (orderCount > typedCoupon.totalOrderLimit) {\n\t\t\t\texpirationReason = CouponExpirationReason.TOTAL_ORDER_LIMIT;\n\t\t\t}\n\t\t}\n\t\tif (typedCoupon.isSpendLimitEnabled && typedCoupon.spendLimit) {\n\t\t\t// spend limit\n\n\t\t\tconst { totalCouponDiscount, totalSecondaryCouponDiscount } = await this.getCouponDiscountTotals(\n\t\t\t\ttypedCoupon.code\n\t\t\t);\n\n\t\t\tif (totalCouponDiscount >= typedCoupon.spendLimit) {\n\t\t\t\texpirationReason = CouponExpirationReason.SPEND_LIMIT;\n\t\t\t}\n\t\t}\n\n\t\tawait this.baseCouponModel.findByIdAndUpdate(\n\t\t\ttypedCoupon._id,\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\texpirationReason,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\t}\n\tprivate async findCouponByCode(code: string): Promise<DocumentType<Model> | null> {\n\t\tconst coupon = await this.model.findOne({ code: code, updatedVersion: { $exists: false } });\n\t\tif (!coupon) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'NOT_FOUND',\n\t\t\t\tmessage: 'Coupon not found',\n\t\t\t});\n\t\t}\n\t\treturn coupon;\n\t}\n\n\tprivate async getCouponDiscountTotals(couponCode: string) {\n\t\tconst pipeline = [\n\t\t\t{\n\t\t\t\t$match: {\n\t\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\t\t'adjustedFinance.pricing.couponDiscount': { $gt: 0 },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'carts',\n\t\t\t\t\tlocalField: 'cart',\n\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\tas: 'cart',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$unwind: '$cart',\n\t\t\t},\n\t\t\t{\n\t\t\t\t$match: {\n\t\t\t\t\t'cart.couponCode': couponCode,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalCouponDiscount: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$toDouble: {\n\t\t\t\t\t\t\t\t$ifNull: ['$finance.pricing.couponDiscount', 0],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\ttotalSecondaryCouponDiscount: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$toDouble: {\n\t\t\t\t\t\t\t\t$ifNull: ['$finance.pricing.secondaryCouponDiscount', 0],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tconst result = await this.orderModel.aggregate(pipeline);\n\n\t\treturn {\n\t\t\ttotalCouponDiscount: result[0]?.totalCouponDiscount ?? 0,\n\t\t\ttotalSecondaryCouponDiscount: result[0]?.totalSecondaryCouponDiscount ?? 0,\n\t\t};\n\t}\n\n\tprivate async assignCouponToUser(user: mongoose.Types.ObjectId, coupon: mongoose.Types.ObjectId) {\n\t\tconst updatedUser = await this.userModel.findByIdAndUpdate(\n\t\t\tuser,\n\t\t\t{\n\t\t\t\t$push: {\n\t\t\t\t\tcoupons: coupon,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\t}\n\n\tprivate async assignCouponToMultipleUser(\n\t\tquery: mongoose.FilterQuery<User>,\n\t\tcoupon: mongoose.Types.ObjectId\n\t) {\n\t\tconsole.log('Assigning coupon to multiple users with coupon:', coupon);\n\t\tconst updatedUsers = await this.userModel.updateMany(query, {\n\t\t\t$push: {\n\t\t\t\tcoupons: coupon,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async assignCouponToNewUsers(coupon: mongoose.Types.ObjectId) {\n\t\tconsole.log('Assigning coupon to new users', coupon);\n\n\t\tconst newUsers = await couponHelperService.getNewUsers();\n\t\tconst updatedUsers = await this.userModel.updateMany(\n\t\t\t{ _id: { $in: newUsers.map(user => user._id) } },\n\t\t\t{\n\t\t\t\t$push: {\n\t\t\t\t\tcoupons: coupon,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\t}\n\n\tprivate async removeCouponFromUser(user: mongoose.Types.ObjectId, coupon: mongoose.Types.ObjectId) {\n\t\tconst updatedUser = await this.userModel.findByIdAndUpdate(\n\t\t\tuser,\n\t\t\t{\n\t\t\t\t$pull: {\n\t\t\t\t\tcoupons: coupon,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\t}\n\n\tprivate async removeCouponFromMultipleUser(\n\t\tquery: mongoose.FilterQuery<User>,\n\t\tcoupon: mongoose.Types.ObjectId\n\t) {\n\t\tconst updatedUsers = await this.userModel.updateMany(query, {\n\t\t\t$pull: {\n\t\t\t\tcoupons: coupon,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate throwBadRequest(message: string): never {\n\t\tthrow new TRPCError({\n\t\t\tcode: 'BAD_REQUEST',\n\t\t\tmessage,\n\t\t});\n\t}\n\n\tpublic async addCouponToUser(user: any, couponCode: string): Promise<DocumentType<Model>> {\n\t\tconst coupon = await this.findCouponByCode(couponCode);\n\t\tif (!coupon) {\n\t\t\tthis.throwBadRequest('Coupon not found');\n\t\t}\n\t\tconst isNewUser = await couponHelperService.isNewUser(new mongoose.Types.ObjectId(user));\n\n\t\tif (coupon.couponType == CouponType.REFERRAL_CODE && !isNewUser) {\n\t\t\tthis.throwBadRequest('This coupon is valid for new users only');\n\t\t}\n\n\t\tif (coupon.couponType == CouponType.REFERRAL_CODE) {\n\t\t\tif ((coupon as DocumentType<ReferralCodeCoupon>).referralUser.toString() == user) {\n\t\t\t\tthis.throwBadRequest('You cannot add your own referral code');\n\t\t\t}\n\t\t}\n\n\t\tconst typedCoupon = coupon as DocumentType<BaseCoupon>;\n\n\t\tif (this.isCouponExpired(typedCoupon)) {\n\t\t\tthis.throwBadRequest('This coupon has expired and cannot be added');\n\t\t}\n\n\t\tif (typedCoupon.forNewUserOnly && !isNewUser) {\n\t\t\tthis.throwBadRequest('This coupon is valid for new users only');\n\t\t}\n\n\t\tconst alreadyApplied = await this.hasUserAlreadyAppliedCoupon(user, typedCoupon);\n\t\tif (alreadyApplied) {\n\t\t\tthis.throwBadRequest('Coupon already applied to user');\n\t\t}\n\n\t\tif (typedCoupon.couponType == CouponType.INDIVIDUAL_USER) {\n\t\t\tif (!(typedCoupon as DocumentType<IndividualUserCoupon>).users?.includes(user)) {\n\t\t\t\tthis.throwBadRequest('This coupon is not assigned to this user');\n\t\t\t}\n\t\t}\n\n\t\tawait this.userModel.findByIdAndUpdate(\n\t\t\tuser,\n\t\t\t{ $push: { coupons: typedCoupon._id } },\n\t\t\t{ new: true, runValidators: true }\n\t\t);\n\n\t\treturn coupon;\n\t}\n\n\tprivate async hasUserAlreadyAppliedCoupon(\n\t\tuserId: mongoose.Types.ObjectId,\n\t\tcoupon: DocumentType<BaseCoupon>\n\t): Promise<boolean> {\n\t\tconst couponIds = [coupon._id, ...(coupon.previousVersions ?? []).map(v => v._id)];\n\n\t\tconst user = await this.userModel.exists({\n\t\t\t_id: userId,\n\t\t\tcoupons: { $in: couponIds },\n\t\t});\n\n\t\treturn !!user;\n\t}\n\n\tprivate async exchangeCouponForMultipleUser(\n\t\tquery: mongoose.FilterQuery<User>,\n\t\toldCoupon: mongoose.Types.ObjectId,\n\t\tnewCoupon: mongoose.Types.ObjectId\n\t) {\n\t\tawait this.removeCouponFromMultipleUser(query, oldCoupon);\n\t\tawait this.assignCouponToMultipleUser(query, newCoupon);\n\t}\n\n\tpublic getShareableLink = async (code: string): Promise<ShareableLinkDTO> => {\n\t\tconst secretsService = getLibraries().getSecretsService();\n\t\tconst deepLinkUrl = (await secretsService.getKey('DEEP_LINK_URL')) ?? 'https://link.lyxa.ai';\n\n\t\tconst link = `${deepLinkUrl}/invite/${code}`;\n\n\t\tconst message = `Download Lyxa and explore the wide variety of offerings and benefits! Use my code at checkout to claim a special coupon : ${code}.\n\t\t${link}`;\n\n\t\treturn { link, message };\n\t};\n\n\tpublic async getUserCouponList(data?: Partial<FilterDTO>): Promise<PaginatedResponse<AllCouponsDTO>> {\n\t\ttry {\n\t\t\tlet query = data?.query || {};\n\n\t\t\tif (!query.user) {\n\t\t\t\tbadRequestError('User ID is required in query');\n\t\t\t}\n\n\t\t\tconst select = data?.select || {\n\t\t\t\t_id: 1,\n\t\t\t\t'createdBy.name': 1,\n\t\t\t\t'duration.start': 1,\n\t\t\t\t'duration.end': 1,\n\t\t\t\tcode: 1,\n\t\t\t\tstatus: 1,\n\t\t\t\tcreatedAt: 1,\n\t\t\t\tcouponType: 1,\n\t\t\t};\n\n\t\t\tlet isExpiredField = null;\n\n\t\t\tif (query.status) {\n\t\t\t\tif (query.status === 'expired') {\n\t\t\t\t\tisExpiredField = true;\n\t\t\t\t\tdelete query.status;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (query.createdAt) {\n\t\t\t\t// convert to date range\n\t\t\t\tif ('$gte' in query.createdAt) {\n\t\t\t\t\tquery.createdAt.$gte = new Date(query.createdAt.$gte);\n\t\t\t\t}\n\t\t\t\tif ('$lte' in query.createdAt) {\n\t\t\t\t\tquery.createdAt.$lte = new Date(query.createdAt.$lte);\n\t\t\t\t}\n\t\t\t\tif ('$gt' in query.createdAt) {\n\t\t\t\t\tquery.createdAt.$gt = new Date(query.createdAt.$gt);\n\t\t\t\t}\n\t\t\t\tif ('$lt' in query.createdAt) {\n\t\t\t\t\tquery.createdAt.$lt = new Date(query.createdAt.$lt);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst user = await this.userModel.findById(query.user).select('coupons');\n\t\t\tquery._id = { $in: user?.coupons ?? [] };\n\t\t\tdelete query.user; // remove user from query to avoid issues in aggregation match stage\n\n\t\t\tconst pipeline: any[] = [\n\t\t\t\t{ $match: { ...query, deletedAt: null } }, // Filter by search query\n\t\t\t\t{\n\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t// INNER JOIN on categories\n\t\t\t\t\t\tfrom: 'admins', // Mongoose auto-pluralizes collection names\n\t\t\t\t\t\tlocalField: 'createdBy',\n\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\tas: 'createdBy',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $unwind: { path: '$createdBy', preserveNullAndEmptyArrays: true } }, // Flatten the array\n\t\t\t\t{\n\t\t\t\t\t$addFields: {\n\t\t\t\t\t\tisExpired: {\n\t\t\t\t\t\t\t$cond: {\n\t\t\t\t\t\t\t\tif: {\n\t\t\t\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$duration.end', false] },\n\t\t\t\t\t\t\t\t\t\t\t\t{ $lt: ['$duration.end', dayjs().toDate()] },\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$expirationReason', false] },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tthen: true,\n\t\t\t\t\t\t\t\telse: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$match: isExpiredField\n\t\t\t\t\t\t? { isExpired: true }\n\t\t\t\t\t\t: query.status === 'active'\n\t\t\t\t\t\t\t? { isExpired: false }\n\t\t\t\t\t\t\t: {},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$addFields: {\n\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t$cond: {\n\t\t\t\t\t\t\t\tif: { $eq: ['$isExpired', true] },\n\t\t\t\t\t\t\t\tthen: 'expired',\n\t\t\t\t\t\t\t\telse: '$status',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$project: select,\n\t\t\t\t},\n\t\t\t];\n\n\t\t\tif (data?.search?.searchKey) {\n\t\t\t\tconst searchKey = data.search.searchKey;\n\t\t\t\tconst regex = new RegExp(searchKey, 'i'); // case-insensitive search\n\t\t\t\tconst fields = data.search.searchFields?.length ? data.search.searchFields : ['code']; // default field(s) to search in\n\n\t\t\t\tpipeline.push({\n\t\t\t\t\t$match: {\n\t\t\t\t\t\t$or: fields.map(field => ({ [field]: { $regex: regex } })),\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Execute the aggregation with pagination and sorting\n\t\t\tconst results = await paginateAggregation(this.model, pipeline, data?.page, data?.size, data?.sort);\n\n\t\t\treturn results as unknown as PaginatedResponse<AllCouponsDTO>;\n\t\t} catch (err) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: `err: ${err}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic async addExistingCouponsToNewUser(userId: mongoose.Types.ObjectId) {\n\t\tconst isNewUser = await couponHelperService.isNewUser(userId);\n\n\t\tconst query: any = {\n\t\t\tcouponType: { $in: [CouponType.GLOBAL, CouponType.INDIVIDUAL_STORE, CouponType.SHOPS_CATEGORIES] },\n\t\t\tdeletedAt: null,\n\t\t\texpirationReason: null,\n\t\t\t$or: [\n\t\t\t\t{ 'duration.end': { $gt: dayjs().toDate() } },\n\t\t\t\t{ 'duration.end': { $exists: false } },\n\t\t\t\t{ 'duration.end': null },\n\t\t\t],\n\t\t\tupdatedVersion: { $exists: false },\n\t\t};\n\n\t\tif (!isNewUser) {\n\t\t\tquery.forNewUserOnly = { $ne: true };\n\t\t}\n\n\t\t// assign all coupons that are not expired\n\t\tconst coupons = await this.baseCouponModel.find(query);\n\n\t\tconst couponIds = coupons.map(coupon => coupon._id);\n\n\t\tawait this.userModel.findByIdAndUpdate(\n\t\t\tuserId,\n\t\t\t{\n\t\t\t\t$addToSet: {\n\t\t\t\t\tcoupons: { $each: couponIds },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tnew: true,\n\t\t\t\trunValidators: true,\n\t\t\t}\n\t\t);\n\t}\n\n\tpublic async checkExistingNewUserCoupon(): Promise<CheckExistingNewUserCouponOutputDTO> {\n\t\tconst currentDate = dayjs().toDate();\n\t\tconst alreadyActiveForNewUserCoupon = await this.baseCouponModel.findOne({\n\t\t\tcouponType: CouponType.GLOBAL,\n\t\t\tforNewUserOnly: true,\n\t\t\tdeletedAt: null,\n\t\t\t$or: [\n\t\t\t\t{\n\t\t\t\t\texpirationReason: { $exists: false },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\texpirationReason: null,\n\t\t\t\t},\n\t\t\t],\n\t\t\t'duration.end': { $gte: currentDate },\n\t\t\tupdatedVersion: { $exists: false },\n\t\t});\n\n\t\tif (alreadyActiveForNewUserCoupon) {\n\t\t\treturn { exists: true };\n\t\t}\n\t\treturn { exists: false };\n\t}\n}\n\nexport const couponService = Container.get(CouponService);\n"]}
@@ -6,6 +6,7 @@ export declare class CouponHelperService {
6
6
  constructor();
7
7
  private get coreUserModel();
8
8
  isNewUser(user: mongoose.Types.ObjectId): Promise<boolean>;
9
+ getSameDeviceOrders(user: mongoose.Types.ObjectId): Promise<number>;
9
10
  getNewUsers(): Promise<mongoose.Types.ObjectId[]>;
10
11
  }
11
12
  export declare const couponHelperService: CouponHelperService;
@@ -1 +1 @@
1
- {"version":3,"file":"helper.service.d.ts","sourceRoot":"/","sources":["modules/coupon/services/helper.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAWhD,qBACa,mBAAmB;IAC/B,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,UAAU,CAA2D;IAC7E,OAAO,CAAC,cAAc,CAAoD;;IAO1E,OAAO,KAAK,aAAa,GAKxB;IAEY,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB1D,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;CAuE9D;AAED,eAAO,MAAM,mBAAmB,qBAAqC,CAAC"}
1
+ {"version":3,"file":"helper.service.d.ts","sourceRoot":"/","sources":["modules/coupon/services/helper.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAWhD,qBACa,mBAAmB;IAC/B,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,UAAU,CAA2D;IAC7E,OAAO,CAAC,cAAc,CAAoD;;IAO1E,OAAO,KAAK,aAAa,GAKxB;IAEY,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB1D,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBnE,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;CAuE9D;AAED,eAAO,MAAM,mBAAmB,qBAAqC,CAAC"}