@lyxa.ai/marketing 1.0.40 → 1.0.41

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 (74) hide show
  1. package/dist/lib/index.d.ts +9 -0
  2. package/dist/lib/index.d.ts.map +1 -1
  3. package/dist/lib/modules/coupon/routers/coupon.router.d.ts +4 -0
  4. package/dist/lib/modules/coupon/routers/coupon.router.d.ts.map +1 -1
  5. package/dist/lib/modules/coupon/services/coupon.service.d.ts.map +1 -1
  6. package/dist/lib/modules/coupon/services/coupon.service.js +13 -25
  7. package/dist/lib/modules/coupon/services/coupon.service.js.map +1 -1
  8. package/dist/lib/modules/coupon/services/custom-coupon.service.d.ts +28 -2
  9. package/dist/lib/modules/coupon/services/custom-coupon.service.d.ts.map +1 -1
  10. package/dist/lib/modules/coupon/services/custom-coupon.service.js +13 -33
  11. package/dist/lib/modules/coupon/services/custom-coupon.service.js.map +1 -1
  12. package/dist/lib/modules/coupon/services/helper.service.d.ts +30 -2
  13. package/dist/lib/modules/coupon/services/helper.service.d.ts.map +1 -1
  14. package/dist/lib/modules/coupon/services/helper.service.js +112 -4
  15. package/dist/lib/modules/coupon/services/helper.service.js.map +1 -1
  16. package/dist/lib/modules/coupon/services/individual-store-coupon.service.d.ts +29 -3
  17. package/dist/lib/modules/coupon/services/individual-store-coupon.service.d.ts.map +1 -1
  18. package/dist/lib/modules/coupon/services/individual-store-coupon.service.js +10 -62
  19. package/dist/lib/modules/coupon/services/individual-store-coupon.service.js.map +1 -1
  20. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.d.ts.map +1 -1
  21. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.js +9 -6
  22. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.js.map +1 -1
  23. package/dist/lib/modules/coupon/services/referral-code-coupon.service.d.ts +9 -0
  24. package/dist/lib/modules/coupon/services/referral-code-coupon.service.d.ts.map +1 -1
  25. package/dist/lib/modules/coupon/services/referral-code-coupon.service.js +96 -29
  26. package/dist/lib/modules/coupon/services/referral-code-coupon.service.js.map +1 -1
  27. package/dist/lib/modules/coupon/services/shops-categories-coupon.service.d.ts +29 -3
  28. package/dist/lib/modules/coupon/services/shops-categories-coupon.service.d.ts.map +1 -1
  29. package/dist/lib/modules/coupon/services/shops-categories-coupon.service.js +10 -63
  30. package/dist/lib/modules/coupon/services/shops-categories-coupon.service.js.map +1 -1
  31. package/dist/lib/modules/coupon/validations/coupon.validation.d.ts +13 -0
  32. package/dist/lib/modules/coupon/validations/coupon.validation.d.ts.map +1 -1
  33. package/dist/lib/modules/coupon/validations/coupon.validation.js +3 -2
  34. package/dist/lib/modules/coupon/validations/coupon.validation.js.map +1 -1
  35. package/dist/lib/modules/deal-setting/services/deal-setting.service.d.ts.map +1 -1
  36. package/dist/lib/modules/deal-setting/services/deal-setting.service.js +4 -4
  37. package/dist/lib/modules/deal-setting/services/deal-setting.service.js.map +1 -1
  38. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts.map +1 -1
  39. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.js.map +1 -1
  40. package/dist/lib/modules/marketing/routers/marketing.router.d.ts +5 -0
  41. package/dist/lib/modules/marketing/routers/marketing.router.d.ts.map +1 -1
  42. package/dist/lib/modules/marketing/routers/marketing.router.js +3 -0
  43. package/dist/lib/modules/marketing/routers/marketing.router.js.map +1 -1
  44. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.d.ts.map +1 -1
  45. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.js +28 -7
  46. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.js.map +1 -1
  47. package/dist/lib/modules/marketing/validations/buy1-get1-marketing.validation.d.ts +12 -12
  48. package/dist/lib/modules/marketing/validations/discount-marketing.validation.d.ts +12 -12
  49. package/dist/types/index.d.ts +9 -0
  50. package/dist/types/index.d.ts.map +1 -1
  51. package/dist/types/modules/coupon/routers/coupon.router.d.ts +4 -0
  52. package/dist/types/modules/coupon/routers/coupon.router.d.ts.map +1 -1
  53. package/dist/types/modules/coupon/services/coupon.service.d.ts.map +1 -1
  54. package/dist/types/modules/coupon/services/custom-coupon.service.d.ts +28 -2
  55. package/dist/types/modules/coupon/services/custom-coupon.service.d.ts.map +1 -1
  56. package/dist/types/modules/coupon/services/helper.service.d.ts +30 -2
  57. package/dist/types/modules/coupon/services/helper.service.d.ts.map +1 -1
  58. package/dist/types/modules/coupon/services/individual-store-coupon.service.d.ts +29 -3
  59. package/dist/types/modules/coupon/services/individual-store-coupon.service.d.ts.map +1 -1
  60. package/dist/types/modules/coupon/services/patterns/repository/CouponRepository.d.ts.map +1 -1
  61. package/dist/types/modules/coupon/services/referral-code-coupon.service.d.ts +57 -0
  62. package/dist/types/modules/coupon/services/referral-code-coupon.service.d.ts.map +1 -1
  63. package/dist/types/modules/coupon/services/shops-categories-coupon.service.d.ts +29 -3
  64. package/dist/types/modules/coupon/services/shops-categories-coupon.service.d.ts.map +1 -1
  65. package/dist/types/modules/coupon/validations/coupon.validation.d.ts +13 -0
  66. package/dist/types/modules/coupon/validations/coupon.validation.d.ts.map +1 -1
  67. package/dist/types/modules/deal-setting/services/deal-setting.service.d.ts.map +1 -1
  68. package/dist/types/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts.map +1 -1
  69. package/dist/types/modules/marketing/routers/marketing.router.d.ts +5 -0
  70. package/dist/types/modules/marketing/routers/marketing.router.d.ts.map +1 -1
  71. package/dist/types/modules/marketing/services/synchronize-product-marketing.service.d.ts.map +1 -1
  72. package/dist/types/modules/marketing/validations/buy1-get1-marketing.validation.d.ts +12 -12
  73. package/dist/types/modules/marketing/validations/discount-marketing.validation.d.ts +12 -12
  74. package/package.json +2 -2
@@ -47,16 +47,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
48
  exports.couponHelperService = exports.CouponHelperService = void 0;
49
49
  const typedi_1 = __importStar(require("typedi"));
50
+ const typegoose_1 = require("@typegoose/typegoose");
50
51
  const models_1 = require("@lyxa.ai/core/dist/libraries/mongo/models");
51
52
  const enum_1 = require("@lyxa.ai/core/dist/utilities/enum");
52
53
  const dayjs_1 = __importDefault(require("@lyxa.ai/core/dist/utilities/dayjs/dayjs"));
54
+ const currency_1 = require("@lyxa.ai/core/dist/utilities/currency");
55
+ const shared_1 = require("@lyxa.ai/core/dist/utilities/shared");
53
56
  let CouponHelperService = class CouponHelperService {
54
57
  userModel;
55
58
  orderModel;
59
+ shopModel;
56
60
  _coreUserModel = null;
57
61
  constructor() {
58
62
  this.userModel = models_1.UserModel;
59
63
  this.orderModel = models_1.RegularOrderModel;
64
+ this.shopModel = models_1.ShopModel;
60
65
  }
61
66
  get coreUserModel() {
62
67
  if (!this._coreUserModel) {
@@ -83,7 +88,7 @@ let CouponHelperService = class CouponHelperService {
83
88
  });
84
89
  return orderCount < 1;
85
90
  }
86
- async getSameDeviceOrders(user) {
91
+ async getSameDeviceOrdersWithCoupon(user, coupon) {
87
92
  let users = [user._id.toString()];
88
93
  const existingUser = await this.userModel.findOne({
89
94
  _id: user,
@@ -99,6 +104,7 @@ let CouponHelperService = class CouponHelperService {
99
104
  const orderCount = await this.orderModel.countDocuments({
100
105
  user: { $in: users },
101
106
  status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
107
+ 'adjustedFinance.coupon.coupon': coupon._id,
102
108
  });
103
109
  return orderCount;
104
110
  }
@@ -162,13 +168,115 @@ let CouponHelperService = class CouponHelperService {
162
168
  }
163
169
  isDurationValid(start, end) {
164
170
  const getRoundedHourBack = (hoursBack = 0) => {
165
- return (0, dayjs_1.default)()
166
- .subtract(hoursBack, 'hour')
167
- .startOf('hour');
171
+ return (0, dayjs_1.default)().subtract(hoursBack, 'hour').startOf('hour');
168
172
  };
169
173
  const cutoffTime = getRoundedHourBack();
170
174
  return start >= cutoffTime && end >= cutoffTime;
171
175
  }
176
+ async calculateCouponDiscount(data, coupon) {
177
+ let discountAmount = coupon.valueType === enum_1.ValueType.FIXED
178
+ ? coupon.value
179
+ : (0, shared_1.roundBaseCurrency)((data.amountBeforeCoupon * coupon.value) / 100);
180
+ let secondaryDiscountAmount = coupon.valueType === enum_1.ValueType.FIXED
181
+ ? await (0, currency_1.convertToSecondary)(coupon.value)
182
+ : (0, shared_1.roundSecondaryCurrency)((data.secondaryAmountBeforeCoupon * coupon.value) / 100);
183
+ if (coupon.isMaxDiscountLimitEnabled && coupon.maxDiscountLimit) {
184
+ const secondaryMax = await (0, currency_1.convertToSecondary)(coupon.maxDiscountLimit);
185
+ discountAmount = Math.min(discountAmount, coupon.maxDiscountLimit);
186
+ secondaryDiscountAmount = Math.min(secondaryDiscountAmount, secondaryMax);
187
+ }
188
+ discountAmount = Math.min(discountAmount, data.amountBeforeCoupon);
189
+ secondaryDiscountAmount = Math.min(secondaryDiscountAmount, data.secondaryAmountBeforeCoupon);
190
+ return { discountAmount, secondaryDiscountAmount };
191
+ }
192
+ buildCouponResponse(data, discountAmount, secondaryDiscountAmount, isShopCoverExpenses, couponDetails) {
193
+ return {
194
+ isValid: true,
195
+ discountAmount,
196
+ secondaryDiscountAmount,
197
+ amountAfterCoupon: (0, shared_1.roundBaseCurrency)(data.amountBeforeCoupon - discountAmount),
198
+ secondaryAmountAfterCoupon: (0, shared_1.roundSecondaryCurrency)(data.secondaryAmountBeforeCoupon - secondaryDiscountAmount),
199
+ discountCut: {
200
+ companyCut: isShopCoverExpenses ? 0 : discountAmount,
201
+ secondaryCompanyCut: isShopCoverExpenses ? 0 : secondaryDiscountAmount,
202
+ shopCut: isShopCoverExpenses ? discountAmount : 0,
203
+ secondaryShopCut: isShopCoverExpenses ? secondaryDiscountAmount : 0,
204
+ },
205
+ couponDetails,
206
+ };
207
+ }
208
+ async validateShopEligibility({ data, coupon }) {
209
+ const shop = await this.shopModel.findOne({
210
+ _id: new typegoose_1.mongoose.Types.ObjectId(data.shop),
211
+ deletedAt: null,
212
+ });
213
+ if (!shop)
214
+ return { isValid: false, message: 'Shop not found' };
215
+ const singleShopError = await this.validateSingleShopRestriction(shop, coupon);
216
+ if (singleShopError)
217
+ return singleShopError;
218
+ const restrictionError = this.validateMultiRestrictions(shop, coupon);
219
+ if (restrictionError)
220
+ return restrictionError;
221
+ const firstOrderError = await this.validateFirstOrderOnly(data, shop, coupon);
222
+ if (firstOrderError)
223
+ return firstOrderError;
224
+ return { isValid: true, shop };
225
+ }
226
+ async validateSingleShopRestriction(shop, coupon) {
227
+ if (!coupon.shop)
228
+ return null;
229
+ const couponShopId = coupon.shop.toString();
230
+ const currentShopId = shop._id.toString();
231
+ if (couponShopId === currentShopId)
232
+ return null;
233
+ const validShop = await this.shopModel.findOne({ _id: coupon.shop, deletedAt: null }).select('name');
234
+ if (!validShop) {
235
+ return {
236
+ isValid: false,
237
+ message: 'Coupon is associated with an invalid shop',
238
+ };
239
+ }
240
+ return {
241
+ isValid: false,
242
+ message: `This coupon can be used at ${validShop.name} only`,
243
+ };
244
+ }
245
+ validateMultiRestrictions(shop, coupon) {
246
+ const hasShopRestriction = Array.isArray(coupon.shops) && coupon.shops.length > 0;
247
+ const hasItemTypeRestriction = Array.isArray(coupon.itemTypes) && coupon.itemTypes.length > 0;
248
+ if (!hasShopRestriction && !hasItemTypeRestriction)
249
+ return null;
250
+ const shopMatches = hasShopRestriction && coupon.shops.some((s) => s.toString() === shop._id.toString());
251
+ const itemTypeMatches = hasItemTypeRestriction && coupon.itemTypes.includes(shop.itemType);
252
+ if (!shopMatches && !itemTypeMatches) {
253
+ return { isValid: false, message: 'Coupon is not valid for this shop' };
254
+ }
255
+ return null;
256
+ }
257
+ async validateFirstOrderOnly(data, shop, coupon) {
258
+ if (!coupon.firstOrderOnly)
259
+ return null;
260
+ const existingOrder = await this.orderModel.exists({
261
+ user: new typegoose_1.mongoose.Types.ObjectId(data.user),
262
+ shop: shop._id,
263
+ status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
264
+ });
265
+ if (existingOrder) {
266
+ return {
267
+ isValid: false,
268
+ message: 'This coupon is only valid for the first order in the shop',
269
+ };
270
+ }
271
+ return null;
272
+ }
273
+ async fetchUserName(userId) {
274
+ const user = await this.userModel.findById(userId).select('coreUser').lean();
275
+ if (!user)
276
+ return 'Unknown User';
277
+ const coreUser = await this.coreUserModel.findById(user.coreUser).select('name').lean();
278
+ return coreUser ? coreUser.name : 'Unknown User';
279
+ }
172
280
  };
173
281
  exports.CouponHelperService = CouponHelperService;
174
282
  exports.CouponHelperService = CouponHelperService = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"helper.service.js","sourceRoot":"/","sources":["modules/coupon/services/helper.service.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { mongoose } from '@typegoose/typegoose';\nimport {\n\tgetCoreUserModel,\n\tRegularOrder,\n\tRegularOrderModel,\n\tUser,\n\tUserModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { RegularOrderStatus } from '@lyxa.ai/core/dist/utilities/enum';\nimport dayjs, { Dayjs } from '@lyxa.ai/core/dist/utilities/dayjs/dayjs';\n\n@Service()\nexport class CouponHelperService {\n\tprivate userModel: typeof UserModel & SoftDeleteModel<User>;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\tprivate _coreUserModel: ReturnType<typeof getCoreUserModel> | null = null;\n\n\tconstructor() {\n\t\tthis.userModel = UserModel as typeof UserModel & SoftDeleteModel<User>;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\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\tpublic async isNewUser(user: mongoose.Types.ObjectId): Promise<boolean> {\n\t\tlet users = [user._id.toString()];\n\n\t\tconst existingUser = await this.userModel.findOne({\n\t\t\t_id: user,\n\t\t});\n\n\t\tconst sameDeviceUsers = await this.userModel.find({\n\t\t\tdeviceId: existingUser?.deviceId,\n\t\t});\n\n\t\tsameDeviceUsers.forEach(u => {\n\t\t\tif (!users.includes(u._id.toString())) {\n\t\t\t\tusers.push(u._id.toString());\n\t\t\t}\n\t\t});\n\n\t\tconst orderCount = await this.orderModel.countDocuments({\n\t\t\tuser: { $in: users },\n\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t});\n\n\t\treturn orderCount < 1;\n\t}\n\n\tpublic async getSameDeviceOrders(user: mongoose.Types.ObjectId): Promise<number> {\n\t\tlet users = [user._id.toString()];\n\n\t\tconst existingUser = await this.userModel.findOne({\n\t\t\t_id: user,\n\t\t});\n\n\t\tconst sameDeviceUsers = await this.userModel.find({\n\t\t\tdeviceId: existingUser?.deviceId,\n\t\t});\n\n\t\tsameDeviceUsers.forEach(u => {\n\t\t\tif (!users.includes(u._id.toString())) {\n\t\t\t\tusers.push(u._id.toString());\n\t\t\t}\n\t\t});\n\n\t\tconst orderCount = await this.orderModel.countDocuments({\n\t\t\tuser: { $in: users },\n\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t});\n\n\t\treturn orderCount;\n\t}\n\n\tpublic async getNewUsers(): Promise<mongoose.Types.ObjectId[]> {\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\t// Step 1: Lookup all users who share the same deviceId\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'users',\n\t\t\t\t\tlocalField: 'deviceId',\n\t\t\t\t\tforeignField: 'deviceId',\n\t\t\t\t\tas: 'sameDeviceUsers',\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Step 2: Collect the list of userIds belonging to this device\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\tallUserIds: {\n\t\t\t\t\t\t$map: {\n\t\t\t\t\t\t\tinput: '$sameDeviceUsers',\n\t\t\t\t\t\t\tas: 'u',\n\t\t\t\t\t\t\tin: '$$u._id',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Step 3: Lookup orders attached to any of these users\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'orders',\n\t\t\t\t\tlet: { ids: '$allUserIds' },\n\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t$and: [{ $in: ['$user', '$$ids'] }, { $ne: ['$status', 'CANCELLED'] }],\n\t\t\t\t\t\t\t\t},\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\tas: 'orders',\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Step 4: Count orders\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\torderCount: { $size: '$orders' },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Step 5: New user = zero or one non-cancelled order\n\t\t\t{\n\t\t\t\t$match: {\n\t\t\t\t\torderCount: { $lte: 1 },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Optional: Remove temporary fields\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\tsameDeviceUsers: 0,\n\t\t\t\t\tallUserIds: 0,\n\t\t\t\t\torders: 0,\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tconst newUsers = await this.userModel.aggregate(pipeline).exec();\n\n\t\treturn newUsers.map(u => u._id);\n\t}\n\n\tpublic isDurationValid(start: Dayjs, end: Dayjs): boolean {\n\t\tconst getRoundedHourBack = (hoursBack = 0) => {\n\t\t\treturn dayjs()\n\t\t.subtract(hoursBack, 'hour')\n\t\t.startOf('hour');\n\t\t};\n\n\t\tconst cutoffTime = getRoundedHourBack();\n\t\t\n\t\treturn start >= cutoffTime && end >= cutoffTime;\n\t}\n}\n\nexport const couponHelperService = Container.get(CouponHelperService);\n"]}
1
+ {"version":3,"file":"helper.service.js","sourceRoot":"/","sources":["modules/coupon/services/helper.service.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { DocumentType, mongoose } from '@typegoose/typegoose';\nimport {\n\tBaseCoupon,\n\tgetCoreUserModel,\n\tRegularOrder,\n\tRegularOrderModel,\n\tShop,\n\tShopModel,\n\tUser,\n\tUserModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { RegularOrderStatus, ValueType } from '@lyxa.ai/core/dist/utilities/enum';\nimport dayjs, { Dayjs } from '@lyxa.ai/core/dist/utilities/dayjs/dayjs';\nimport { CouponValidationOutputDTO, ValidateCouponDTO } from '../validations';\nimport { convertToSecondary } from '@lyxa.ai/core/dist/utilities/currency';\nimport { roundBaseCurrency, roundSecondaryCurrency } from '@lyxa.ai/core/dist/utilities/shared';\n\n@Service()\nexport class CouponHelperService {\n\tprivate userModel: typeof UserModel & SoftDeleteModel<User>;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\tprivate shopModel: typeof ShopModel & SoftDeleteModel<Shop>;\n\tprivate _coreUserModel: ReturnType<typeof getCoreUserModel> | null = null;\n\n\tconstructor() {\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}\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\tpublic async isNewUser(user: mongoose.Types.ObjectId): Promise<boolean> {\n\t\tlet users = [user._id.toString()];\n\n\t\tconst existingUser = await this.userModel.findOne({\n\t\t\t_id: user,\n\t\t});\n\n\t\tconst sameDeviceUsers = await this.userModel.find({\n\t\t\tdeviceId: existingUser?.deviceId,\n\t\t});\n\n\t\tsameDeviceUsers.forEach(u => {\n\t\t\tif (!users.includes(u._id.toString())) {\n\t\t\t\tusers.push(u._id.toString());\n\t\t\t}\n\t\t});\n\n\t\tconst orderCount = await this.orderModel.countDocuments({\n\t\t\tuser: { $in: users },\n\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t});\n\n\t\treturn orderCount < 1;\n\t}\n\n\tpublic async getSameDeviceOrdersWithCoupon(\n\t\tuser: mongoose.Types.ObjectId,\n\t\tcoupon: DocumentType<BaseCoupon>\n\t): Promise<number> {\n\t\tlet users = [user._id.toString()];\n\n\t\tconst existingUser = await this.userModel.findOne({\n\t\t\t_id: user,\n\t\t});\n\n\t\tconst sameDeviceUsers = await this.userModel.find({\n\t\t\tdeviceId: existingUser?.deviceId,\n\t\t});\n\n\t\tsameDeviceUsers.forEach(u => {\n\t\t\tif (!users.includes(u._id.toString())) {\n\t\t\t\tusers.push(u._id.toString());\n\t\t\t}\n\t\t});\n\n\t\tconst orderCount = await this.orderModel.countDocuments({\n\t\t\tuser: { $in: users },\n\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t'adjustedFinance.coupon.coupon': coupon._id,\n\t\t});\n\n\t\treturn orderCount;\n\t}\n\n\tpublic async getNewUsers(): Promise<mongoose.Types.ObjectId[]> {\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\t// Step 1: Lookup all users who share the same deviceId\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'users',\n\t\t\t\t\tlocalField: 'deviceId',\n\t\t\t\t\tforeignField: 'deviceId',\n\t\t\t\t\tas: 'sameDeviceUsers',\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Step 2: Collect the list of userIds belonging to this device\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\tallUserIds: {\n\t\t\t\t\t\t$map: {\n\t\t\t\t\t\t\tinput: '$sameDeviceUsers',\n\t\t\t\t\t\t\tas: 'u',\n\t\t\t\t\t\t\tin: '$$u._id',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Step 3: Lookup orders attached to any of these users\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'orders',\n\t\t\t\t\tlet: { ids: '$allUserIds' },\n\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t$and: [{ $in: ['$user', '$$ids'] }, { $ne: ['$status', 'CANCELLED'] }],\n\t\t\t\t\t\t\t\t},\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\tas: 'orders',\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Step 4: Count orders\n\t\t\t{\n\t\t\t\t$set: {\n\t\t\t\t\torderCount: { $size: '$orders' },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Step 5: New user = zero or one non-cancelled order\n\t\t\t{\n\t\t\t\t$match: {\n\t\t\t\t\torderCount: { $lte: 1 },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Optional: Remove temporary fields\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\tsameDeviceUsers: 0,\n\t\t\t\t\tallUserIds: 0,\n\t\t\t\t\torders: 0,\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tconst newUsers = await this.userModel.aggregate(pipeline).exec();\n\n\t\treturn newUsers.map(u => u._id);\n\t}\n\n\tpublic isDurationValid(start: Dayjs, end: Dayjs): boolean {\n\t\tconst getRoundedHourBack = (hoursBack = 0) => {\n\t\t\treturn dayjs().subtract(hoursBack, 'hour').startOf('hour');\n\t\t};\n\n\t\tconst cutoffTime = getRoundedHourBack();\n\n\t\treturn start >= cutoffTime && end >= cutoffTime;\n\t}\n\n\tpublic async calculateCouponDiscount(data: ValidateCouponDTO, coupon: DocumentType<BaseCoupon>) {\n\t\tlet discountAmount =\n\t\t\tcoupon.valueType === ValueType.FIXED\n\t\t\t\t? coupon.value\n\t\t\t\t: roundBaseCurrency((data.amountBeforeCoupon * coupon.value) / 100);\n\n\t\tlet secondaryDiscountAmount =\n\t\t\tcoupon.valueType === ValueType.FIXED\n\t\t\t\t? await convertToSecondary(coupon.value)\n\t\t\t\t: roundSecondaryCurrency((data.secondaryAmountBeforeCoupon * coupon.value) / 100);\n\n\t\tif (coupon.isMaxDiscountLimitEnabled && coupon.maxDiscountLimit) {\n\t\t\tconst secondaryMax = await convertToSecondary(coupon.maxDiscountLimit);\n\n\t\t\tdiscountAmount = Math.min(discountAmount, coupon.maxDiscountLimit);\n\t\t\tsecondaryDiscountAmount = Math.min(secondaryDiscountAmount, secondaryMax);\n\t\t}\n\n\t\t// Prevent negative totals\n\t\tdiscountAmount = Math.min(discountAmount, data.amountBeforeCoupon);\n\t\tsecondaryDiscountAmount = Math.min(secondaryDiscountAmount, data.secondaryAmountBeforeCoupon);\n\n\t\treturn { discountAmount, secondaryDiscountAmount };\n\t}\n\n\tpublic buildCouponResponse(\n\t\tdata: ValidateCouponDTO,\n\t\tdiscountAmount: number,\n\t\tsecondaryDiscountAmount: number,\n\t\tisShopCoverExpenses: boolean,\n\t\tcouponDetails?: Record<string, any>\n\t): CouponValidationOutputDTO {\n\t\treturn {\n\t\t\tisValid: true,\n\t\t\tdiscountAmount,\n\t\t\tsecondaryDiscountAmount,\n\t\t\tamountAfterCoupon: roundBaseCurrency(data.amountBeforeCoupon - discountAmount),\n\t\t\tsecondaryAmountAfterCoupon: roundSecondaryCurrency(\n\t\t\t\tdata.secondaryAmountBeforeCoupon - secondaryDiscountAmount\n\t\t\t),\n\t\t\tdiscountCut: {\n\t\t\t\tcompanyCut: isShopCoverExpenses ? 0 : discountAmount,\n\t\t\t\tsecondaryCompanyCut: isShopCoverExpenses ? 0 : secondaryDiscountAmount,\n\t\t\t\tshopCut: isShopCoverExpenses ? discountAmount : 0,\n\t\t\t\tsecondaryShopCut: isShopCoverExpenses ? secondaryDiscountAmount : 0,\n\t\t\t},\n\t\t\tcouponDetails,\n\t\t};\n\t}\n\n\tpublic async validateShopEligibility({ data, coupon }: { data: ValidateCouponDTO; coupon: any }) {\n\t\tconst shop = await this.shopModel.findOne({\n\t\t\t_id: new mongoose.Types.ObjectId(data.shop),\n\t\t\tdeletedAt: null,\n\t\t});\n\n\t\tif (!shop) return { isValid: false, message: 'Shop not found' };\n\n\t\tconst singleShopError = await this.validateSingleShopRestriction(shop, coupon);\n\t\tif (singleShopError) return singleShopError;\n\n\t\tconst restrictionError = this.validateMultiRestrictions(shop, coupon);\n\t\tif (restrictionError) return restrictionError;\n\n\t\tconst firstOrderError = await this.validateFirstOrderOnly(data, shop, coupon);\n\t\tif (firstOrderError) return firstOrderError;\n\n\t\treturn { isValid: true, shop };\n\t}\n\n\tprivate async validateSingleShopRestriction(shop: any, coupon: any) {\n\t\tif (!coupon.shop) return null;\n\n\t\tconst couponShopId = coupon.shop.toString();\n\t\tconst currentShopId = shop._id.toString();\n\n\t\tif (couponShopId === currentShopId) return null;\n\n\t\tconst validShop = await this.shopModel.findOne({ _id: coupon.shop, deletedAt: null }).select('name');\n\n\t\tif (!validShop) {\n\t\t\treturn {\n\t\t\t\tisValid: false,\n\t\t\t\tmessage: 'Coupon is associated with an invalid shop',\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tisValid: false,\n\t\t\tmessage: `This coupon can be used at ${validShop.name} only`,\n\t\t};\n\t}\n\n\tprivate validateMultiRestrictions(shop: any, coupon: any) {\n\t\tconst hasShopRestriction = Array.isArray(coupon.shops) && coupon.shops.length > 0;\n\t\tconst hasItemTypeRestriction = Array.isArray(coupon.itemTypes) && coupon.itemTypes.length > 0;\n\n\t\tif (!hasShopRestriction && !hasItemTypeRestriction) return null;\n\n\t\tconst shopMatches =\n\t\t\thasShopRestriction && coupon.shops.some((s: any) => s.toString() === shop._id.toString());\n\n\t\tconst itemTypeMatches = hasItemTypeRestriction && coupon.itemTypes.includes(shop.itemType);\n\n\t\tif (!shopMatches && !itemTypeMatches) {\n\t\t\treturn { isValid: false, message: 'Coupon is not valid for this shop' };\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate async validateFirstOrderOnly(data: ValidateCouponDTO, shop: any, coupon: any) {\n\t\tif (!coupon.firstOrderOnly) return null;\n\n\t\tconst existingOrder = await this.orderModel.exists({\n\t\t\tuser: new mongoose.Types.ObjectId(data.user),\n\t\t\tshop: shop._id,\n\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t});\n\n\t\tif (existingOrder) {\n\t\t\treturn {\n\t\t\t\tisValid: false,\n\t\t\t\tmessage: 'This coupon is only valid for the first order in the shop',\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic async fetchUserName(userId: mongoose.Types.ObjectId): Promise<string> {\n\t\tconst user = await this.userModel.findById(userId).select('coreUser').lean();\n\t\t\n\t\tif (!user) return 'Unknown User';\n\n\t\tconst coreUser = await this.coreUserModel.findById(user.coreUser).select('name').lean();\n\n\t\treturn coreUser ? coreUser.name : 'Unknown User';\n\t}\n}\n\nexport const couponHelperService = Container.get(CouponHelperService);\n"]}
@@ -1,6 +1,6 @@
1
- import { DocumentType } from '@typegoose/typegoose';
1
+ import { DocumentType, mongoose } from '@typegoose/typegoose';
2
2
  import { IndividualStoreCoupon as Model } from '@lyxa.ai/core/dist/libraries/mongo/models/';
3
- import { CouponValidationOutputDTO, CreateIndividualStoreCouponDTO as CreateDTO, UpdateIndividualStoreCouponDTO as UpdateDTO, ValidateCouponDTO } from '../../coupon/validations';
3
+ import { CreateIndividualStoreCouponDTO as CreateDTO, UpdateIndividualStoreCouponDTO as UpdateDTO, ValidateCouponDTO } from '../../coupon/validations';
4
4
  export declare class IndividualStoreCouponService {
5
5
  private model;
6
6
  private readonly shopModelForCoupon;
@@ -8,7 +8,33 @@ export declare class IndividualStoreCouponService {
8
8
  constructor();
9
9
  create(data: CreateDTO): Promise<DocumentType<Model>>;
10
10
  update(id: string, data: UpdateDTO): Promise<DocumentType<Model>>;
11
- validateCoupon(data: ValidateCouponDTO, couponDocument: DocumentType<Model>): Promise<CouponValidationOutputDTO>;
11
+ validateCoupon(data: ValidateCouponDTO, coupon: DocumentType<Model>): Promise<{
12
+ isValid: boolean;
13
+ message?: string | undefined;
14
+ amountAfterCoupon?: number | undefined;
15
+ secondaryAmountAfterCoupon?: number | undefined;
16
+ discountAmount?: number | undefined;
17
+ secondaryDiscountAmount?: number | undefined;
18
+ discountCut?: {
19
+ companyCut?: number | undefined;
20
+ secondaryCompanyCut?: number | undefined;
21
+ shopCut?: number | undefined;
22
+ secondaryShopCut?: number | undefined;
23
+ } | undefined;
24
+ couponDetails?: Record<string, unknown> | undefined;
25
+ } | {
26
+ isValid: boolean;
27
+ message: string;
28
+ shop?: undefined;
29
+ } | {
30
+ isValid: boolean;
31
+ shop: mongoose.Document<unknown, import("@typegoose/typegoose/lib/types").BeAnObject, import("@lyxa.ai/core/dist/libraries/mongo/models/shop.model").Shop, import("@typegoose/typegoose/lib/types").BeAnyObject, {}> & Omit<import("@lyxa.ai/core/dist/libraries/mongo/models/shop.model").Shop & {
32
+ _id: mongoose.Types.ObjectId;
33
+ } & {
34
+ __v: number;
35
+ }, "typegooseName"> & import("@typegoose/typegoose/lib/types").IObjectWithTypegooseFunction;
36
+ message?: undefined;
37
+ }>;
12
38
  }
13
39
  export declare const individualStoreCouponService: IndividualStoreCouponService;
14
40
  //# sourceMappingURL=individual-store-coupon.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"individual-store-coupon.service.d.ts","sourceRoot":"/","sources":["modules/coupon/services/individual-store-coupon.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAY,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAEN,qBAAqB,IAAI,KAAK,EAI9B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACN,yBAAyB,EACzB,8BAA8B,IAAI,SAAS,EAC3C,8BAA8B,IAAI,SAAS,EAC3C,iBAAiB,EACjB,MAAM,6BAA6B,CAAC;AAMrC,qBACa,4BAA4B;IACxC,OAAO,CAAC,KAAK,CAAC;IACd,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAmB;IACtD,OAAO,CAAC,UAAU,CAA2D;;IAYhE,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAWrD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAuBjE,cAAc,CAC1B,IAAI,EAAE,iBAAiB,EACvB,cAAc,EAAE,YAAY,CAAC,KAAK,CAAC,GACjC,OAAO,CAAC,yBAAyB,CAAC;CA8ErC;AAED,eAAO,MAAM,4BAA4B,8BAA8C,CAAC"}
1
+ {"version":3,"file":"individual-store-coupon.service.d.ts","sourceRoot":"/","sources":["modules/coupon/services/individual-store-coupon.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAEN,qBAAqB,IAAI,KAAK,EAI9B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACN,8BAA8B,IAAI,SAAS,EAC3C,8BAA8B,IAAI,SAAS,EAC3C,iBAAiB,EACjB,MAAM,6BAA6B,CAAC;AAIrC,qBACa,4BAA4B;IACxC,OAAO,CAAC,KAAK,CAAC;IACd,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAmB;IACtD,OAAO,CAAC,UAAU,CAA2D;;IAYhE,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAWrD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAuBjE,cAAc,CAAC,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYhF;AAED,eAAO,MAAM,4BAA4B,8BAA8C,CAAC"}
@@ -45,11 +45,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.individualStoreCouponService = exports.IndividualStoreCouponService = void 0;
46
46
  const typedi_1 = __importStar(require("typedi"));
47
47
  const server_1 = require("@trpc/server");
48
- const typegoose_1 = require("@typegoose/typegoose");
49
48
  const models_1 = require("@lyxa.ai/core/dist/libraries/mongo/models/");
50
- const currency_1 = require("@lyxa.ai/core/dist/utilities/currency");
51
- const shared_1 = require("@lyxa.ai/core/dist/utilities/shared");
52
- const enum_1 = require("@lyxa.ai/core/dist/utilities/enum");
49
+ const helper_service_1 = require("./helper.service");
53
50
  let IndividualStoreCouponService = class IndividualStoreCouponService {
54
51
  model;
55
52
  shopModelForCoupon;
@@ -79,64 +76,15 @@ let IndividualStoreCouponService = class IndividualStoreCouponService {
79
76
  }
80
77
  return record;
81
78
  }
82
- async validateCoupon(data, couponDocument) {
83
- const shopId = new typegoose_1.mongoose.Types.ObjectId(data.shop);
84
- const shop = await this.shopModelForCoupon.findOne({ _id: shopId, deletedAt: null });
85
- if (!shop) {
86
- return {
87
- isValid: false,
88
- message: 'Shop not found',
89
- };
90
- }
91
- if (couponDocument?.shop?.toString() !== shopId.toString()) {
92
- return {
93
- isValid: false,
94
- message: 'Coupon is not valid for this shop',
95
- };
96
- }
97
- if (couponDocument.firstOrderOnly) {
98
- const order = await this.orderModel.findOne({
99
- user: new typegoose_1.mongoose.Types.ObjectId(data.user),
100
- shop: new typegoose_1.mongoose.Types.ObjectId(data.shop),
101
- status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
102
- });
103
- if (order) {
104
- return {
105
- isValid: false,
106
- message: 'This coupon is only valid for the first order in the shop',
107
- };
108
- }
109
- }
110
- let discountAmount = couponDocument.valueType == enum_1.ValueType.FIXED
111
- ? couponDocument.value
112
- : (0, shared_1.roundBaseCurrency)((data.amountBeforeCoupon * couponDocument.value) / 100);
113
- let secondaryDiscountAmount = couponDocument.valueType == enum_1.ValueType.FIXED
114
- ? await (0, currency_1.convertToSecondary)(couponDocument.value)
115
- : (0, shared_1.roundSecondaryCurrency)((data.secondaryAmountBeforeCoupon * couponDocument.value) / 100);
116
- if (couponDocument.isMaxDiscountLimitEnabled && couponDocument.maxDiscountLimit) {
117
- discountAmount = Math.min(discountAmount, couponDocument.maxDiscountLimit);
118
- secondaryDiscountAmount = Math.min(secondaryDiscountAmount, await (0, currency_1.convertToSecondary)(couponDocument.maxDiscountLimit));
119
- }
120
- if (discountAmount > data.amountBeforeCoupon) {
121
- discountAmount = data.amountBeforeCoupon;
122
- }
123
- if (secondaryDiscountAmount > data.secondaryAmountBeforeCoupon) {
124
- secondaryDiscountAmount = data.secondaryAmountBeforeCoupon;
125
- }
126
- const isShopCoverExpenses = couponDocument.isShopCoverExpenses;
127
- return {
128
- isValid: true,
129
- discountAmount,
130
- secondaryDiscountAmount,
131
- amountAfterCoupon: (0, shared_1.roundBaseCurrency)(data.amountBeforeCoupon - discountAmount),
132
- secondaryAmountAfterCoupon: (0, shared_1.roundSecondaryCurrency)(data.secondaryAmountBeforeCoupon - secondaryDiscountAmount),
133
- discountCut: {
134
- companyCut: isShopCoverExpenses ? 0 : discountAmount,
135
- secondaryCompanyCut: isShopCoverExpenses ? 0 : secondaryDiscountAmount,
136
- shopCut: isShopCoverExpenses ? discountAmount : 0,
137
- secondaryShopCut: isShopCoverExpenses ? secondaryDiscountAmount : 0,
138
- },
139
- };
79
+ async validateCoupon(data, coupon) {
80
+ const validation = await helper_service_1.couponHelperService.validateShopEligibility({
81
+ data,
82
+ coupon
83
+ });
84
+ if (!validation.isValid)
85
+ return validation;
86
+ const { discountAmount, secondaryDiscountAmount } = await helper_service_1.couponHelperService.calculateCouponDiscount(data, coupon);
87
+ return helper_service_1.couponHelperService.buildCouponResponse(data, discountAmount, secondaryDiscountAmount, coupon.isShopCoverExpenses ?? false);
140
88
  }
141
89
  };
142
90
  exports.IndividualStoreCouponService = IndividualStoreCouponService;
@@ -1 +1 @@
1
- {"version":3,"file":"individual-store-coupon.service.js","sourceRoot":"/","sources":["modules/coupon/services/individual-store-coupon.service.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { TRPCError } from '@trpc/server';\nimport { DocumentType, mongoose } from '@typegoose/typegoose';\nimport {\n\tIndividualStoreCouponModel,\n\tIndividualStoreCoupon as Model,\n\tRegularOrder,\n\tRegularOrderModel,\n\tShopModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models/';\nimport {\n\tCouponValidationOutputDTO,\n\tCreateIndividualStoreCouponDTO as CreateDTO,\n\tUpdateIndividualStoreCouponDTO as UpdateDTO,\n\tValidateCouponDTO,\n} from '@modules/coupon/validations';\nimport { convertToSecondary } from '@lyxa.ai/core/dist/utilities/currency';\nimport { roundBaseCurrency, roundSecondaryCurrency } from '@lyxa.ai/core/dist/utilities/shared';\nimport { RegularOrderStatus, ValueType } from '@lyxa.ai/core/dist/utilities/enum';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\n\n@Service()\nexport class IndividualStoreCouponService {\n\tprivate model;\n\tprivate readonly shopModelForCoupon: typeof ShopModel;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\n\tconstructor() {\n\t\tthis.model = IndividualStoreCouponModel;\n\t\tthis.shopModelForCoupon = ShopModel as typeof ShopModel;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\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: CreateDTO): Promise<DocumentType<Model>> {\n\t\tconst coupon = this.model.create(data);\n\n\t\treturn coupon;\n\t}\n\n\t/**\n\t * Update record\n\t * @param id ID of the record\n\t * @param data Data to update\n\t */\n\tpublic async update(id: string, data: UpdateDTO): Promise<DocumentType<Model>> {\n\t\tconst record = await this.model.findOneAndUpdate(\n\t\t\t{\n\t\t\t\t_id: id,\n\t\t\t\tdeletedAt: null,\n\t\t\t},\n\t\t\tdata,\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 (!record) {\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\treturn record;\n\t}\n\n\tpublic async validateCoupon(\n\t\tdata: ValidateCouponDTO,\n\t\tcouponDocument: DocumentType<Model>\n\t): Promise<CouponValidationOutputDTO> {\n\t\tconst shopId = new mongoose.Types.ObjectId(data.shop);\n\t\tconst shop = await this.shopModelForCoupon.findOne({ _id: shopId, deletedAt: null });\n\t\tif (!shop) {\n\t\t\treturn {\n\t\t\t\tisValid: false,\n\t\t\t\tmessage: 'Shop not found',\n\t\t\t};\n\t\t}\n\n\t\t// Check if the coupon is applicable to the shop and item-type\n\t\tif (couponDocument?.shop?.toString() !== shopId.toString()) {\n\t\t\treturn {\n\t\t\t\tisValid: false,\n\t\t\t\tmessage: 'Coupon is not valid for this shop',\n\t\t\t};\n\t\t}\n\n\t\t// Add condition to check first order only\n\n\t\tif (couponDocument.firstOrderOnly) {\n\t\t\tconst order = await this.orderModel.findOne({\n\t\t\t\tuser: new mongoose.Types.ObjectId(data.user),\n\t\t\t\tshop: new mongoose.Types.ObjectId(data.shop),\n\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t});\n\n\t\t\tif (order) {\n\t\t\t\treturn {\n\t\t\t\t\tisValid: false,\n\t\t\t\t\tmessage: 'This coupon is only valid for the first order in the shop',\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tlet discountAmount =\n\t\t\tcouponDocument.valueType == ValueType.FIXED\n\t\t\t\t? couponDocument.value\n\t\t\t\t: roundBaseCurrency((data.amountBeforeCoupon * couponDocument.value) / 100);\n\n\t\tlet secondaryDiscountAmount =\n\t\t\tcouponDocument.valueType == ValueType.FIXED\n\t\t\t\t? await convertToSecondary(couponDocument.value)\n\t\t\t\t: roundSecondaryCurrency((data.secondaryAmountBeforeCoupon * couponDocument.value) / 100);\n\n\t\tif (couponDocument.isMaxDiscountLimitEnabled && couponDocument.maxDiscountLimit) {\n\t\t\tdiscountAmount = Math.min(discountAmount, couponDocument.maxDiscountLimit);\n\t\t\tsecondaryDiscountAmount = Math.min(\n\t\t\t\tsecondaryDiscountAmount,\n\t\t\t\tawait convertToSecondary(couponDocument.maxDiscountLimit)\n\t\t\t);\n\t\t}\n\n\t\tif (discountAmount > data.amountBeforeCoupon) {\n\t\t\tdiscountAmount = data.amountBeforeCoupon;\n\t\t}\n\t\tif (secondaryDiscountAmount > data.secondaryAmountBeforeCoupon) {\n\t\t\tsecondaryDiscountAmount = data.secondaryAmountBeforeCoupon;\n\t\t}\n\n\t\tconst isShopCoverExpenses = couponDocument.isShopCoverExpenses;\n\n\t\treturn {\n\t\t\tisValid: true,\n\t\t\tdiscountAmount,\n\t\t\tsecondaryDiscountAmount,\n\t\t\tamountAfterCoupon: roundBaseCurrency(data.amountBeforeCoupon - discountAmount),\n\t\t\tsecondaryAmountAfterCoupon: roundSecondaryCurrency(\n\t\t\t\tdata.secondaryAmountBeforeCoupon - secondaryDiscountAmount\n\t\t\t),\n\t\t\tdiscountCut: {\n\t\t\t\tcompanyCut: isShopCoverExpenses ? 0 : discountAmount,\n\t\t\t\tsecondaryCompanyCut: isShopCoverExpenses ? 0 : secondaryDiscountAmount,\n\t\t\t\tshopCut: isShopCoverExpenses ? discountAmount : 0,\n\t\t\t\tsecondaryShopCut: isShopCoverExpenses ? secondaryDiscountAmount : 0,\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport const individualStoreCouponService = Container.get(IndividualStoreCouponService);\n"]}
1
+ {"version":3,"file":"individual-store-coupon.service.js","sourceRoot":"/","sources":["modules/coupon/services/individual-store-coupon.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAA4C;AAC5C,yCAAyC;AAEzC,uEAMoD;AAOpD,qDAAuD;AAGhD,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IAChC,KAAK,CAAC;IACG,kBAAkB,CAAmB;IAC9C,UAAU,CAA2D;IAE7E;QACC,IAAI,CAAC,KAAK,GAAG,mCAA0B,CAAC;QACxC,IAAI,CAAC,kBAAkB,GAAG,kBAA6B,CAAC;QACxD,IAAI,CAAC,UAAU,GAAG,0BAA6E,CAAC;IACjG,CAAC;IAMM,KAAK,CAAC,MAAM,CAAC,IAAe;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEvC,OAAO,MAAM,CAAC;IACf,CAAC;IAOM,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,IAAe;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAC/C;YACC,GAAG,EAAE,EAAE;YACP,SAAS,EAAE,IAAI;SACf,EACD,IAAI,EACJ;YACC,GAAG,EAAE,IAAI;YACT,aAAa,EAAE,IAAI;SACnB,CACD,CAAC;QAEF,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,IAAI,kBAAS,CAAC;gBACnB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,kBAAkB;aAC3B,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,IAAuB,EAAE,MAA2B;QAC/E,MAAM,UAAU,GAAG,MAAM,oCAAmB,CAAC,uBAAuB,CAAC;YACpE,IAAI;YACJ,MAAM;SACN,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,CAAC,OAAO;YAAE,OAAO,UAAU,CAAC;QAE3C,MAAM,EAAE,cAAc,EAAE,uBAAuB,EAAE,GAAG,MAAM,oCAAmB,CAAC,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAEpH,OAAO,oCAAmB,CAAC,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,CAAC,mBAAmB,IAAI,KAAK,CAAC,CAAC;IACpI,CAAC;CACD,CAAA;AA7DY,oEAA4B;uCAA5B,4BAA4B;IADxC,IAAA,gBAAO,GAAE;;GACG,4BAA4B,CA6DxC;AAEY,QAAA,4BAA4B,GAAG,gBAAS,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC","sourcesContent":["import Container, { Service } from 'typedi';\nimport { TRPCError } from '@trpc/server';\nimport { DocumentType, mongoose } from '@typegoose/typegoose';\nimport {\n\tIndividualStoreCouponModel,\n\tIndividualStoreCoupon as Model,\n\tRegularOrder,\n\tRegularOrderModel,\n\tShopModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models/';\nimport {\n\tCreateIndividualStoreCouponDTO as CreateDTO,\n\tUpdateIndividualStoreCouponDTO as UpdateDTO,\n\tValidateCouponDTO,\n} from '@modules/coupon/validations';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { couponHelperService } from './helper.service';\n\n@Service()\nexport class IndividualStoreCouponService {\n\tprivate model;\n\tprivate readonly shopModelForCoupon: typeof ShopModel;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\n\tconstructor() {\n\t\tthis.model = IndividualStoreCouponModel;\n\t\tthis.shopModelForCoupon = ShopModel as typeof ShopModel;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\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: CreateDTO): Promise<DocumentType<Model>> {\n\t\tconst coupon = this.model.create(data);\n\n\t\treturn coupon;\n\t}\n\n\t/**\n\t * Update record\n\t * @param id ID of the record\n\t * @param data Data to update\n\t */\n\tpublic async update(id: string, data: UpdateDTO): Promise<DocumentType<Model>> {\n\t\tconst record = await this.model.findOneAndUpdate(\n\t\t\t{\n\t\t\t\t_id: id,\n\t\t\t\tdeletedAt: null,\n\t\t\t},\n\t\t\tdata,\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 (!record) {\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\treturn record;\n\t}\n\n\tpublic async validateCoupon(data: ValidateCouponDTO, coupon: DocumentType<Model>) {\n\t\tconst validation = await couponHelperService.validateShopEligibility({\n\t\t\tdata,\n\t\t\tcoupon\n\t\t});\n\n\t\tif (!validation.isValid) return validation;\n\n\t\tconst { discountAmount, secondaryDiscountAmount } = await couponHelperService.calculateCouponDiscount(data, coupon);\n\n\t\treturn couponHelperService.buildCouponResponse(data, discountAmount, secondaryDiscountAmount, coupon.isShopCoverExpenses ?? false);\n\t}\n}\n\nexport const individualStoreCouponService = Container.get(IndividualStoreCouponService);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CouponRepository.d.ts","sourceRoot":"/","sources":["modules/coupon/services/patterns/repository/CouponRepository.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAEN,QAAQ,EAIR,MAAM,mCAAmC,CAAC;AAK3C,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+C;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2C;IACrE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAiE;IACvG,OAAO,CAAC,cAAc,CAAoD;;IAS1E,OAAO,KAAK,aAAa,GAKxB;IAEY,cAAc,CAC1B,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,EACzC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,EACzC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAC5B,OAAO,CAAC,GAAG,CAAC;IAoVR,qBAAqB,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG;IAQxC,kBAAkB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE;IA6ChD,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,iBAAiB;IA0DzB,OAAO,CAAC,2BAA2B;CAyGnC"}
1
+ {"version":3,"file":"CouponRepository.d.ts","sourceRoot":"/","sources":["modules/coupon/services/patterns/repository/CouponRepository.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAEN,QAAQ,EAIR,MAAM,mCAAmC,CAAC;AAK3C,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+C;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2C;IACrE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAiE;IACvG,OAAO,CAAC,cAAc,CAAoD;;IAS1E,OAAO,KAAK,aAAa,GAKxB;IAEY,cAAc,CAC1B,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,EACzC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,EACzC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAC5B,OAAO,CAAC,GAAG,CAAC;IAoVR,qBAAqB,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG;IAQxC,kBAAkB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE;IA6ChD,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,iBAAiB;IA0DzB,OAAO,CAAC,2BAA2B;CAyGnC"}
@@ -345,20 +345,23 @@ class CouponRepository {
345
345
  if (coupon.isOrderLimitPerUserEnabled && coupon.orderLimitPerUser > 0) {
346
346
  validityParts.push(`applied on ${coupon.orderLimitPerUser} order`);
347
347
  }
348
- if (coupon.couponType === enum_1.CouponType.REFERRAL_CODE || coupon.couponType === enum_1.CouponType.REFERRAL_REWARD) {
349
- validityParts = [];
350
- validityParts.push(`Applied on 1 Order`);
351
- }
352
348
  coupon.couponValidityLabel = validityParts.join('. ');
353
349
  return coupon;
354
350
  });
355
351
  return resultsWithLabels;
356
352
  }
357
353
  formatCurrency(value, secondaryCurrencyValue) {
354
+ const formatterUSD = new Intl.NumberFormat('en-US', {
355
+ minimumFractionDigits: 0,
356
+ maximumFractionDigits: 2,
357
+ });
358
+ const formatterLBP = new Intl.NumberFormat('en-US', {
359
+ minimumFractionDigits: 0,
360
+ });
358
361
  if (secondaryCurrencyValue !== null && secondaryCurrencyValue !== undefined) {
359
- return 'LBP ' + String(secondaryCurrencyValue);
362
+ return 'LBP ' + formatterLBP.format(Number(secondaryCurrencyValue));
360
363
  }
361
- return '$' + String(value ?? 0);
364
+ return '$' + formatterUSD.format(Number(value ?? 0));
362
365
  }
363
366
  filterShopCoupons(shop, itemType) {
364
367
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"CouponRepository.js","sourceRoot":"/","sources":["modules/coupon/services/patterns/repository/CouponRepository.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tCoupon,\n\tCouponModel,\n\tgetCoreUserModel,\n\tReferralSetting,\n\tReferralSettingModel,\n\tUser,\n\tUserModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { mongoose } from '@typegoose/typegoose';\nimport { getRoundSecondaryCurrencyStage } from '@lyxa.ai/core/dist/utilities/pipelines/common-pipeline-functions';\nimport {\n\tCouponType,\n\tItemType,\n\tRegularOrderStatus,\n\tStatus,\n\tValueType,\n} from '@lyxa.ai/core/dist/utilities/enum';\nimport { getExchangeRate } from '@lyxa.ai/core/dist/utilities/currency';\nimport { roundSecondaryCurrency } from '@lyxa.ai/core/dist/utilities/shared';\nimport { dayjs } from '@lyxa.ai/core/dist/utilities/dayjs';\n\nexport class CouponRepository {\n\tprivate readonly model: typeof CouponModel & SoftDeleteModel<Coupon>;\n\tprivate readonly userModel: typeof UserModel & SoftDeleteModel<User>;\n\tprivate readonly referralSettingsModel: typeof ReferralSettingModel & SoftDeleteModel<ReferralSetting>;\n\tprivate _coreUserModel: ReturnType<typeof getCoreUserModel> | null = null;\n\n\tconstructor() {\n\t\tthis.model = CouponModel as typeof CouponModel & SoftDeleteModel<Coupon>;\n\t\tthis.userModel = UserModel as typeof UserModel & SoftDeleteModel<User>;\n\t\tthis.referralSettingsModel = ReferralSettingModel as typeof ReferralSettingModel &\n\t\t\tSoftDeleteModel<ReferralSetting>;\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\tpublic async getUserCoupons(\n\t\tuser: mongoose.Types.ObjectId | undefined,\n\t\tshop: mongoose.Types.ObjectId | undefined,\n\t\titemType: ItemType | undefined\n\t): Promise<any> {\n\t\tconst exchangeRate = await getExchangeRate();\n\n\t\tconst referralSettings = await this.referralSettingsModel.findOne();\n\n\t\tconst secondaryReferralReceiverValue =\n\t\t\treferralSettings?.receiver?.valueType == ValueType.PERCENTAGE\n\t\t\t\t? null\n\t\t\t\t: roundSecondaryCurrency((referralSettings?.receiver?.value ?? 0) * exchangeRate);\n\n\t\tconst secondaryReferralReceiverMinOrderAmount = roundSecondaryCurrency(\n\t\t\t(referralSettings?.receiver?.minimumOrderValue ?? 0) * exchangeRate\n\t\t);\n\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\t// Match the user\n\t\t\t{\n\t\t\t\t$match: { _id: user },\n\t\t\t},\n\n\t\t\t// Lookup coupon documents\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'coupons',\n\t\t\t\t\tlocalField: 'coupons',\n\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\tas: 'couponDocs',\n\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$eq: [{ $ifNull: ['$status', Status.ACTIVE] }, Status.ACTIVE],\n\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\t$lte: [{ $ifNull: ['$duration.start', dayjs().toDate()] }, dayjs().toDate()],\n\t\t\t\t\t\t\t\t\t\t},\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},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\tfrom: 'users',\n\t\t\t\t\t\t\t\tlocalField: 'referralUser',\n\t\t\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\t\t\tas: 'referralUser',\n\t\t\t\t\t\t\t\tpipeline: [{ $project: { coreUser: 1 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\tfrom: 'users',\n\t\t\t\t\t\t\t\tlocalField: 'influencer',\n\t\t\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\t\t\tas: 'influencer',\n\t\t\t\t\t\t\t\tpipeline: [{ $project: { coreUser: 1 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\tfrom: 'shops',\n\t\t\t\t\t\t\t\tlocalField: 'shop',\n\t\t\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\t\t\tas: 'shop',\n\t\t\t\t\t\t\t\tpipeline: [{ $project: { name: 1 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$unwind: { path: '$shop', preserveNullAndEmptyArrays: true },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$unwind: { path: '$referralUser', preserveNullAndEmptyArrays: true },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$unwind: { path: '$influencer', preserveNullAndEmptyArrays: true },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$addFields: {\n\t\t\t\t\t\t\t\treferringUser: {\n\t\t\t\t\t\t\t\t\t$ifNull: ['$referralUser.coreUser', '$influencer.coreUser'],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$project: { referralUser: 0, influencer: 0 },\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Lookup orders containing coupons for this user\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'orders',\n\t\t\t\t\tlet: { userId: '$_id' },\n\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t$expr: { $eq: ['$user', '$$userId'] },\n\t\t\t\t\t\t\t\t'adjustedFinance.coupon': { $exists: true },\n\t\t\t\t\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\tfrom: 'coupons',\n\t\t\t\t\t\t\t\tlocalField: 'adjustedFinance.coupon.coupon',\n\t\t\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\t\t\tas: 'couponInfo',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$unwind: '$couponInfo',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$group: {\n\t\t\t\t\t\t\t\t_id: '$adjustedFinance.coupon.coupon',\n\t\t\t\t\t\t\t\tsnap: { $first: '$couponInfo' },\n\t\t\t\t\t\t\t\tcount: { $sum: 1 },\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\tas: 'couponUsage',\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Unwind coupons to classify individually\n\t\t\t{\n\t\t\t\t$unwind: '$couponDocs',\n\t\t\t},\n\n\t\t\t// Filter individual shop and shops categories coupons\n\t\t\tthis.filterShopCoupons(shop, itemType),\n\n\t\t\t// Filter first order only coupons\n\t\t\t...this.filterFirstOrderOnlyCoupons(shop),\n\n\t\t\t// Join usage count for this coupon\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\tusageData: {\n\t\t\t\t\t\t$arrayElemAt: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$filter: {\n\t\t\t\t\t\t\t\t\tinput: '$couponUsage',\n\t\t\t\t\t\t\t\t\tas: 'cu',\n\t\t\t\t\t\t\t\t\tcond: { $eq: ['$$cu._id', '$couponDocs._id'] },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Classify expiration exactly like isCouponExpired()\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\tisExpired: {\n\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t// true only if expirationReason is a non-empty string\n\t\t\t\t\t\t\t{ $gt: [{ $strLenCP: { $ifNull: ['$couponDocs.expirationReason', ''] } }, 0] },\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t{ $ifNull: ['$couponDocs.duration.end', false] },\n\t\t\t\t\t\t\t\t\t{ $lt: ['$couponDocs.duration.end', '$$NOW'] }, // consistent “now”\n\t\t\t\t\t\t\t\t],\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\tusedCount: { $ifNull: ['$usageData.count', 0] },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Add exchange rate and secondary currency rounding factor\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\texchangeRate: exchangeRate,\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Compute and add secondary currency values to coupon documents\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\t// base value\n\t\t\t\t\t'couponDocs.value': {\n\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\tthen: referralSettings?.receiver?.value ?? 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: '$couponDocs.value',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// value type\n\t\t\t\t\t'couponDocs.valueType': {\n\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\tthen: referralSettings?.receiver?.valueType ?? 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: '$couponDocs.valueType',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t'couponDocs.secondaryCurrencyValue': {\n\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t// If valueType is percentage => null always\n\t\t\t\t\t\t\t{ $eq: ['$couponDocs.valueType', ValueType.PERCENTAGE] },\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\t\t\tthen: secondaryReferralReceiverValue,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\tdefault: getRoundSecondaryCurrencyStage({\n\t\t\t\t\t\t\t\t\t\t$multiply: ['$couponDocs.value', exchangeRate],\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},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\n\t\t\t\t\t'couponDocs.secondaryCurrencyMaxDiscountLimit': {\n\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\tthen: null,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: getRoundSecondaryCurrencyStage({\n\t\t\t\t\t\t\t\t$multiply: ['$couponDocs.maxDiscountLimit', exchangeRate],\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\t'couponDocs.secondaryCurrencyMinOrderValue': {\n\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\tthen: secondaryReferralReceiverMinOrderAmount,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: getRoundSecondaryCurrencyStage({\n\t\t\t\t\t\t\t\t$multiply: ['$couponDocs.minOrderValue', exchangeRate],\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\n\t\t\t// Category logic\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\tcategory: {\n\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t'$isExpired',\n\t\t\t\t\t\t\t'expired',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t\t{ $gt: ['$usedCount', 0] },\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ $not: ['$couponDocs.orderLimitPerUser'] },\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ $lt: ['$usedCount', '$couponDocs.orderLimitPerUser'] },\n\t\t\t\t\t\t\t\t\t\t\t\t],\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},\n\t\t\t\t\t\t\t\t\t'available',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$cond: [{ $gt: ['$usedCount', 0] }, 'used', 'available'],\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},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Group into arrays\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: '$_id',\n\t\t\t\t\tavailable: {\n\t\t\t\t\t\t$push: {\n\t\t\t\t\t\t\t$cond: [{ $eq: ['$category', 'available'] }, '$couponDocs', '$$REMOVE'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tused: {\n\t\t\t\t\t\t$push: {\n\t\t\t\t\t\t\t$cond: [{ $eq: ['$category', 'used'] }, '$usageData.snap', '$$REMOVE'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\texpired: {\n\t\t\t\t\t\t$push: {\n\t\t\t\t\t\t\t$cond: [{ $eq: ['$category', 'expired'] }, '$couponDocs', '$$REMOVE'],\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\t{\n\t\t\t\t$project: {\n\t\t\t\t\t_id: 0,\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tconst [results] = await this.userModel.aggregate(pipeline);\n\n\t\tif (!results) {\n\t\t\treturn {\n\t\t\t\tavailable: [],\t\n\t\t\t\tused: [],\n\t\t\t\texpired: [],\n\t\t\t};\n\t\t}\n\n\t\tconst populatedResults = await this.userModel.populate(results, {\n\t\t\tpath: 'available.referringUser',\n\t\t\tmodel: this.coreUserModel,\n\t\t\tselect: { _id: 0, name: 1 },\n\t\t});\n\n\t\treturn populatedResults;\n\t}\n\n\tpublic addLabelsToAllCoupons(coupons: any): any {\n\t\treturn {\n\t\t\tavailable: this.addLabelsToCoupons(coupons.available).reverse(), // Just to make newly added coupon at the top\n\t\t\tused: this.addLabelsToCoupons(coupons.used).reverse(), // Just to make newly added coupon at the top\n\t\t\texpired: this.addLabelsToCoupons(coupons.expired).reverse(), // Just to make newly added coupon at the top\n\t\t};\n\t}\n\n\tpublic addLabelsToCoupons(coupons: any[]): any[] {\n\t\tconst resultsWithLabels = coupons.map(coupon => {\n\t\t\t// couponOfferLabel\n\t\t\tconst valuePart =\n\t\t\t\tcoupon.valueType === 'fixed'\n\t\t\t\t\t? this.formatCurrency(coupon.value, coupon.secondaryCurrencyValue)\n\t\t\t\t\t: `${coupon.value}%`;\n\n\t\t\tconst maxDiscountPart =\n\t\t\t\tcoupon.isMaxDiscountLimitEnabled && coupon.maxDiscountLimit > 0\n\t\t\t\t\t? ` up to ${this.formatCurrency(coupon.maxDiscountLimit, coupon.secondaryCurrencyMaxDiscountLimit)}`\n\t\t\t\t\t: '';\n\n\t\t\tconst influencerPart = coupon.referringUser ? ` (Referred by ${coupon.referringUser.name})` : '';\n\n\t\t\tcoupon.couponOfferLabel = `Save ${valuePart}${maxDiscountPart}${influencerPart}`;\n\n\t\t\t// couponValidityLabel\n\t\t\tlet validityParts: string[] = [];\n\n\t\t\t// 1. Minimum Order\n\t\t\tif (coupon.isMinOrderValueEnabled && coupon.minOrderValue > 0) {\n\t\t\t\tvalidityParts.push(\n\t\t\t\t\t`Minimum order ${this.formatCurrency(coupon.minOrderValue, coupon.secondaryCurrencyMinOrderValue)}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// 2. Order Limit\n\t\t\tif (coupon.isOrderLimitPerUserEnabled && coupon.orderLimitPerUser > 0) {\n\t\t\t\tvalidityParts.push(`applied on ${coupon.orderLimitPerUser} order`);\n\t\t\t}\n\n\t\t\tif(coupon.couponType === CouponType.REFERRAL_CODE || coupon.couponType === CouponType.REFERRAL_REWARD){\n\t\t\t\tvalidityParts = [];\n\t\t\t\tvalidityParts.push(`Applied on 1 Order`);\n\t\t\t}\n\n\t\t\tcoupon.couponValidityLabel = validityParts.join('. ');\n\n\t\t\treturn coupon;\n\t\t});\n\n\t\treturn resultsWithLabels;\n\t}\n\n\tprivate formatCurrency(value: any, secondaryCurrencyValue: any) {\n\t\tif (secondaryCurrencyValue !== null && secondaryCurrencyValue !== undefined) {\n\t\t\treturn 'LBP ' + String(secondaryCurrencyValue);\n\t\t}\n\t\treturn '$' + String(value ?? 0);\n\t}\n\n\tprivate filterShopCoupons(\n\t\tshop: mongoose.Types.ObjectId | undefined,\n\t\titemType: ItemType | undefined\n\t): mongoose.PipelineStage {\n\t\treturn {\n\t\t\t$match: {\n\t\t\t\t$expr: {\n\t\t\t\t\t// If shopId is undefined → skip filtering (always true)\n\t\t\t\t\t$cond: [\n\t\t\t\t\t\t{ $not: [shop] }, // means shopId is null/undefined\n\t\t\t\t\t\ttrue, // skip filtering\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t\t// Case 1: INDIVIDUAL_STORE → shop must match\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.couponType', CouponType.INDIVIDUAL_STORE] },\n\t\t\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.shop._id', shop] },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Case 2: SHOP_CATEGORY\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.couponType', CouponType.SHOPS_CATEGORIES] },\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t\t\t\t\t\t// itemType matches\n\t\t\t\t\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.itemType', itemType] },\n\n\t\t\t\t\t\t\t\t\t\t\t\t// or shopId is inside couponDocs.shops[]\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t$in: [shop, { $ifNull: ['$couponDocs.shops', []] }],\n\t\t\t\t\t\t\t\t\t\t\t\t},\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],\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Case 3: All other coupon types → keep\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$not: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$in: [\n\t\t\t\t\t\t\t\t\t\t\t\t'$couponDocs.couponType',\n\t\t\t\t\t\t\t\t\t\t\t\t[CouponType.INDIVIDUAL_STORE, CouponType.SHOPS_CATEGORIES],\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],\n\t\t\t\t\t\t\t\t},\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\t}\n\n\tprivate filterFirstOrderOnlyCoupons(shop?: mongoose.Types.ObjectId): mongoose.PipelineStage[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'orders',\n\t\t\t\t\tlet: {\n\t\t\t\t\t\tuserId: '$_id',\n\t\t\t\t\t\tshopId: shop ?? '$couponDocs.shop._id',\n\t\t\t\t\t\tcouponShops: { $ifNull: ['$couponDocs.shops', []] },\n\t\t\t\t\t},\n\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t{ $eq: ['$user', '$$userId'] },\n\n\t\t\t\t\t\t\t\t\t\t{ $ne: ['$status', RegularOrderStatus.CANCELLED] },\n\n\t\t\t\t\t\t\t\t\t\t// If shop is provided → only that shop\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t\t\t\t{ $ne: ['$$shopId', null] },\n\t\t\t\t\t\t\t\t\t\t\t\t{ $eq: ['$shop', '$$shopId'] },\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Else → any shop in coupon.shops\n\t\t\t\t\t\t\t\t\t\t\t\t{ $in: ['$shop', '$$couponShops'] },\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],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$group: {\n\t\t\t\t\t\t\t\t_id: null,\n\t\t\t\t\t\t\t\torderedShops: { $addToSet: '$shop' },\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\tas: 'orderStats',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\torderedShops: {\n\t\t\t\t\t\t$ifNull: [{ $arrayElemAt: ['$orderStats.orderedShops', 0] }, []],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\t// Individual store logic\n\t\t\t\t\thasOrderedFromStore: {\n\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t{ $eq: ['$couponDocs.couponType', CouponType.INDIVIDUAL_STORE] },\n\t\t\t\t\t\t\t{ $in: [shop ?? '$couponDocs.shop._id', '$orderedShops'] },\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\n\t\t\t\t\t// Multiple store logic\n\t\t\t\t\thasUnusedShopInCategory: {\n\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t{ $eq: ['$couponDocs.couponType', CouponType.SHOPS_CATEGORIES] },\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t{ $ifNull: [shop, false] },\n\t\t\t\t\t\t\t\t\t// shop provided → hide if user has ordered from this shop\n\t\t\t\t\t\t\t\t\t{ $in: [shop, '$orderedShops'] },\n\t\t\t\t\t\t\t\t\t// no shop provided → hide if no unused shops\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$eq: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t$size: { $setDifference: [{ $ifNull: ['$couponDocs.shops', []] }, '$orderedShops'] },\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t],\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},\n\t\t\t\t\t\t\tfalse,\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\t{\n\t\t\t\t$match: {\n\t\t\t\t\t$expr: {\n\t\t\t\t\t\t$not: {\n\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$in: ['$couponDocs.couponType', [CouponType.INDIVIDUAL_STORE, CouponType.SHOPS_CATEGORIES]],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.firstOrderOnly', true] },\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$or: ['$hasOrderedFromStore', '$hasUnusedShopInCategory'],\n\t\t\t\t\t\t\t\t},\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\t}\n}\n"]}
1
+ {"version":3,"file":"CouponRepository.js","sourceRoot":"/","sources":["modules/coupon/services/patterns/repository/CouponRepository.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tCoupon,\n\tCouponModel,\n\tgetCoreUserModel,\n\tReferralSetting,\n\tReferralSettingModel,\n\tUser,\n\tUserModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { mongoose } from '@typegoose/typegoose';\nimport { getRoundSecondaryCurrencyStage } from '@lyxa.ai/core/dist/utilities/pipelines/common-pipeline-functions';\nimport {\n\tCouponType,\n\tItemType,\n\tRegularOrderStatus,\n\tStatus,\n\tValueType,\n} from '@lyxa.ai/core/dist/utilities/enum';\nimport { getExchangeRate } from '@lyxa.ai/core/dist/utilities/currency';\nimport { roundSecondaryCurrency } from '@lyxa.ai/core/dist/utilities/shared';\nimport { dayjs } from '@lyxa.ai/core/dist/utilities/dayjs';\n\nexport class CouponRepository {\n\tprivate readonly model: typeof CouponModel & SoftDeleteModel<Coupon>;\n\tprivate readonly userModel: typeof UserModel & SoftDeleteModel<User>;\n\tprivate readonly referralSettingsModel: typeof ReferralSettingModel & SoftDeleteModel<ReferralSetting>;\n\tprivate _coreUserModel: ReturnType<typeof getCoreUserModel> | null = null;\n\n\tconstructor() {\n\t\tthis.model = CouponModel as typeof CouponModel & SoftDeleteModel<Coupon>;\n\t\tthis.userModel = UserModel as typeof UserModel & SoftDeleteModel<User>;\n\t\tthis.referralSettingsModel = ReferralSettingModel as typeof ReferralSettingModel &\n\t\t\tSoftDeleteModel<ReferralSetting>;\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\tpublic async getUserCoupons(\n\t\tuser: mongoose.Types.ObjectId | undefined,\n\t\tshop: mongoose.Types.ObjectId | undefined,\n\t\titemType: ItemType | undefined\n\t): Promise<any> {\n\t\tconst exchangeRate = await getExchangeRate();\n\n\t\tconst referralSettings = await this.referralSettingsModel.findOne();\n\n\t\tconst secondaryReferralReceiverValue =\n\t\t\treferralSettings?.receiver?.valueType == ValueType.PERCENTAGE\n\t\t\t\t? null\n\t\t\t\t: roundSecondaryCurrency((referralSettings?.receiver?.value ?? 0) * exchangeRate);\n\n\t\tconst secondaryReferralReceiverMinOrderAmount = roundSecondaryCurrency(\n\t\t\t(referralSettings?.receiver?.minimumOrderValue ?? 0) * exchangeRate\n\t\t);\n\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\t// Match the user\n\t\t\t{\n\t\t\t\t$match: { _id: user },\n\t\t\t},\n\n\t\t\t// Lookup coupon documents\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'coupons',\n\t\t\t\t\tlocalField: 'coupons',\n\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\tas: 'couponDocs',\n\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$eq: [{ $ifNull: ['$status', Status.ACTIVE] }, Status.ACTIVE],\n\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\t$lte: [{ $ifNull: ['$duration.start', dayjs().toDate()] }, dayjs().toDate()],\n\t\t\t\t\t\t\t\t\t\t},\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},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\tfrom: 'users',\n\t\t\t\t\t\t\t\tlocalField: 'referralUser',\n\t\t\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\t\t\tas: 'referralUser',\n\t\t\t\t\t\t\t\tpipeline: [{ $project: { coreUser: 1 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\tfrom: 'users',\n\t\t\t\t\t\t\t\tlocalField: 'influencer',\n\t\t\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\t\t\tas: 'influencer',\n\t\t\t\t\t\t\t\tpipeline: [{ $project: { coreUser: 1 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\tfrom: 'shops',\n\t\t\t\t\t\t\t\tlocalField: 'shop',\n\t\t\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\t\t\tas: 'shop',\n\t\t\t\t\t\t\t\tpipeline: [{ $project: { name: 1 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$unwind: { path: '$shop', preserveNullAndEmptyArrays: true },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$unwind: { path: '$referralUser', preserveNullAndEmptyArrays: true },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$unwind: { path: '$influencer', preserveNullAndEmptyArrays: true },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$addFields: {\n\t\t\t\t\t\t\t\treferringUser: {\n\t\t\t\t\t\t\t\t\t$ifNull: ['$referralUser.coreUser', '$influencer.coreUser'],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$project: { referralUser: 0, influencer: 0 },\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Lookup orders containing coupons for this user\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'orders',\n\t\t\t\t\tlet: { userId: '$_id' },\n\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t$expr: { $eq: ['$user', '$$userId'] },\n\t\t\t\t\t\t\t\t'adjustedFinance.coupon': { $exists: true },\n\t\t\t\t\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lookup: {\n\t\t\t\t\t\t\t\tfrom: 'coupons',\n\t\t\t\t\t\t\t\tlocalField: 'adjustedFinance.coupon.coupon',\n\t\t\t\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\t\t\t\tas: 'couponInfo',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$unwind: '$couponInfo',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$group: {\n\t\t\t\t\t\t\t\t_id: '$adjustedFinance.coupon.coupon',\n\t\t\t\t\t\t\t\tsnap: { $first: '$couponInfo' },\n\t\t\t\t\t\t\t\tcount: { $sum: 1 },\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\tas: 'couponUsage',\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Unwind coupons to classify individually\n\t\t\t{\n\t\t\t\t$unwind: '$couponDocs',\n\t\t\t},\n\n\t\t\t// Filter individual shop and shops categories coupons\n\t\t\tthis.filterShopCoupons(shop, itemType),\n\n\t\t\t// Filter first order only coupons\n\t\t\t...this.filterFirstOrderOnlyCoupons(shop),\n\n\t\t\t// Join usage count for this coupon\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\tusageData: {\n\t\t\t\t\t\t$arrayElemAt: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$filter: {\n\t\t\t\t\t\t\t\t\tinput: '$couponUsage',\n\t\t\t\t\t\t\t\t\tas: 'cu',\n\t\t\t\t\t\t\t\t\tcond: { $eq: ['$$cu._id', '$couponDocs._id'] },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Classify expiration exactly like isCouponExpired()\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\tisExpired: {\n\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t// true only if expirationReason is a non-empty string\n\t\t\t\t\t\t\t{ $gt: [{ $strLenCP: { $ifNull: ['$couponDocs.expirationReason', ''] } }, 0] },\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t{ $ifNull: ['$couponDocs.duration.end', false] },\n\t\t\t\t\t\t\t\t\t{ $lt: ['$couponDocs.duration.end', '$$NOW'] }, // consistent “now”\n\t\t\t\t\t\t\t\t],\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\tusedCount: { $ifNull: ['$usageData.count', 0] },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Add exchange rate and secondary currency rounding factor\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\texchangeRate: exchangeRate,\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Compute and add secondary currency values to coupon documents\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\t// base value\n\t\t\t\t\t'couponDocs.value': {\n\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\tthen: referralSettings?.receiver?.value ?? 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: '$couponDocs.value',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t// value type\n\t\t\t\t\t'couponDocs.valueType': {\n\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\tthen: referralSettings?.receiver?.valueType ?? 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: '$couponDocs.valueType',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\n\t\t\t\t\t'couponDocs.secondaryCurrencyValue': {\n\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t// If valueType is percentage => null always\n\t\t\t\t\t\t\t{ $eq: ['$couponDocs.valueType', ValueType.PERCENTAGE] },\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\t\t\tthen: secondaryReferralReceiverValue,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\tdefault: getRoundSecondaryCurrencyStage({\n\t\t\t\t\t\t\t\t\t\t$multiply: ['$couponDocs.value', exchangeRate],\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},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\n\t\t\t\t\t'couponDocs.secondaryCurrencyMaxDiscountLimit': {\n\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\tthen: null,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: getRoundSecondaryCurrencyStage({\n\t\t\t\t\t\t\t\t$multiply: ['$couponDocs.maxDiscountLimit', exchangeRate],\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\t'couponDocs.secondaryCurrencyMinOrderValue': {\n\t\t\t\t\t\t$switch: {\n\t\t\t\t\t\t\tbranches: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase: { $eq: ['$couponDocs.couponType', CouponType.REFERRAL_CODE] },\n\t\t\t\t\t\t\t\t\tthen: secondaryReferralReceiverMinOrderAmount,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdefault: getRoundSecondaryCurrencyStage({\n\t\t\t\t\t\t\t\t$multiply: ['$couponDocs.minOrderValue', exchangeRate],\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\n\t\t\t// Category logic\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\tcategory: {\n\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t'$isExpired',\n\t\t\t\t\t\t\t'expired',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t\t{ $gt: ['$usedCount', 0] },\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ $not: ['$couponDocs.orderLimitPerUser'] },\n\t\t\t\t\t\t\t\t\t\t\t\t\t{ $lt: ['$usedCount', '$couponDocs.orderLimitPerUser'] },\n\t\t\t\t\t\t\t\t\t\t\t\t],\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},\n\t\t\t\t\t\t\t\t\t'available',\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$cond: [{ $gt: ['$usedCount', 0] }, 'used', 'available'],\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},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Group into arrays\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: '$_id',\n\t\t\t\t\tavailable: {\n\t\t\t\t\t\t$push: {\n\t\t\t\t\t\t\t$cond: [{ $eq: ['$category', 'available'] }, '$couponDocs', '$$REMOVE'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tused: {\n\t\t\t\t\t\t$push: {\n\t\t\t\t\t\t\t$cond: [{ $eq: ['$category', 'used'] }, '$usageData.snap', '$$REMOVE'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\texpired: {\n\t\t\t\t\t\t$push: {\n\t\t\t\t\t\t\t$cond: [{ $eq: ['$category', 'expired'] }, '$couponDocs', '$$REMOVE'],\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\t{\n\t\t\t\t$project: {\n\t\t\t\t\t_id: 0,\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tconst [results] = await this.userModel.aggregate(pipeline);\n\n\t\tif (!results) {\n\t\t\treturn {\n\t\t\t\tavailable: [],\t\n\t\t\t\tused: [],\n\t\t\t\texpired: [],\n\t\t\t};\n\t\t}\n\n\t\tconst populatedResults = await this.userModel.populate(results, {\n\t\t\tpath: 'available.referringUser',\n\t\t\tmodel: this.coreUserModel,\n\t\t\tselect: { _id: 0, name: 1 },\n\t\t});\n\n\t\treturn populatedResults;\n\t}\n\n\tpublic addLabelsToAllCoupons(coupons: any): any {\n\t\treturn {\n\t\t\tavailable: this.addLabelsToCoupons(coupons.available).reverse(), // Just to make newly added coupon at the top\n\t\t\tused: this.addLabelsToCoupons(coupons.used).reverse(), // Just to make newly added coupon at the top\n\t\t\texpired: this.addLabelsToCoupons(coupons.expired).reverse(), // Just to make newly added coupon at the top\n\t\t};\n\t}\n\n\tpublic addLabelsToCoupons(coupons: any[]): any[] {\n\t\tconst resultsWithLabels = coupons.map(coupon => {\n\t\t\t// couponOfferLabel\n\t\t\tconst valuePart =\n\t\t\t\tcoupon.valueType === 'fixed'\n\t\t\t\t\t? this.formatCurrency(coupon.value, coupon.secondaryCurrencyValue)\n\t\t\t\t\t: `${coupon.value}%`;\n\n\t\t\tconst maxDiscountPart =\n\t\t\t\tcoupon.isMaxDiscountLimitEnabled && coupon.maxDiscountLimit > 0\n\t\t\t\t\t? ` up to ${this.formatCurrency(coupon.maxDiscountLimit, coupon.secondaryCurrencyMaxDiscountLimit)}`\n\t\t\t\t\t: '';\n\n\t\t\tconst influencerPart = coupon.referringUser ? ` (Referred by ${coupon.referringUser.name})` : '';\n\n\t\t\tcoupon.couponOfferLabel = `Save ${valuePart}${maxDiscountPart}${influencerPart}`;\n\n\t\t\t// couponValidityLabel\n\t\t\tlet validityParts: string[] = [];\n\n\t\t\t// 1. Minimum Order\n\t\t\tif (coupon.isMinOrderValueEnabled && coupon.minOrderValue > 0) {\n\t\t\t\tvalidityParts.push(\n\t\t\t\t\t`Minimum order ${this.formatCurrency(coupon.minOrderValue, coupon.secondaryCurrencyMinOrderValue)}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// 2. Order Limit\n\t\t\tif (coupon.isOrderLimitPerUserEnabled && coupon.orderLimitPerUser > 0) {\n\t\t\t\tvalidityParts.push(`applied on ${coupon.orderLimitPerUser} order`);\n\t\t\t}\n\n\t\t\t// if(coupon.couponType === CouponType.REFERRAL_CODE || coupon.couponType === CouponType.REFERRAL_REWARD){\n\t\t\t// \tvalidityParts = [];\n\t\t\t// \tvalidityParts.push(`Applied on 1 Order`);\n\t\t\t// }\n\n\t\t\tcoupon.couponValidityLabel = validityParts.join('. ');\n\n\t\t\treturn coupon;\n\t\t});\n\n\t\treturn resultsWithLabels;\n\t}\n\n\tprivate formatCurrency(value: any, secondaryCurrencyValue: any) {\n\t\t// Use coma separator for thousands and round secondary currency value\n\t\tconst formatterUSD = new Intl.NumberFormat('en-US', {\n\t\t\tminimumFractionDigits: 0,\n\t\t\tmaximumFractionDigits: 2,\n\t\t});\n\n\t\tconst formatterLBP = new Intl.NumberFormat('en-US', {\n\t\t\tminimumFractionDigits: 0,\n\t\t});\n\n\t\tif (secondaryCurrencyValue !== null && secondaryCurrencyValue !== undefined) {\n\t\t\treturn 'LBP ' + formatterLBP.format(Number(secondaryCurrencyValue));\n\t\t}\n\n\t\treturn '$' + formatterUSD.format(Number(value ?? 0));\n\t}\n\n\tprivate filterShopCoupons(\n\t\tshop: mongoose.Types.ObjectId | undefined,\n\t\titemType: ItemType | undefined\n\t): mongoose.PipelineStage {\n\t\treturn {\n\t\t\t$match: {\n\t\t\t\t$expr: {\n\t\t\t\t\t// If shopId is undefined → skip filtering (always true)\n\t\t\t\t\t$cond: [\n\t\t\t\t\t\t{ $not: [shop] }, // means shopId is null/undefined\n\t\t\t\t\t\ttrue, // skip filtering\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t\t// Case 1: INDIVIDUAL_STORE → shop must match\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.couponType', CouponType.INDIVIDUAL_STORE] },\n\t\t\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.shop._id', shop] },\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Case 2: SHOP_CATEGORY\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.couponType', CouponType.SHOPS_CATEGORIES] },\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$or: [\n\t\t\t\t\t\t\t\t\t\t\t\t// itemType matches\n\t\t\t\t\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.itemType', itemType] },\n\n\t\t\t\t\t\t\t\t\t\t\t\t// or shopId is inside couponDocs.shops[]\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t$in: [shop, { $ifNull: ['$couponDocs.shops', []] }],\n\t\t\t\t\t\t\t\t\t\t\t\t},\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],\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Case 3: All other coupon types → keep\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$not: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$in: [\n\t\t\t\t\t\t\t\t\t\t\t\t'$couponDocs.couponType',\n\t\t\t\t\t\t\t\t\t\t\t\t[CouponType.INDIVIDUAL_STORE, CouponType.SHOPS_CATEGORIES],\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],\n\t\t\t\t\t\t\t\t},\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\t}\n\n\tprivate filterFirstOrderOnlyCoupons(shop?: mongoose.Types.ObjectId): mongoose.PipelineStage[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'orders',\n\t\t\t\t\tlet: {\n\t\t\t\t\t\tuserId: '$_id',\n\t\t\t\t\t\tshopId: shop ?? '$couponDocs.shop._id',\n\t\t\t\t\t\tcouponShops: { $ifNull: ['$couponDocs.shops', []] },\n\t\t\t\t\t},\n\t\t\t\t\tpipeline: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$match: {\n\t\t\t\t\t\t\t\t$expr: {\n\t\t\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t\t\t{ $eq: ['$user', '$$userId'] },\n\n\t\t\t\t\t\t\t\t\t\t{ $ne: ['$status', RegularOrderStatus.CANCELLED] },\n\n\t\t\t\t\t\t\t\t\t\t// If shop is provided → only that shop\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t\t\t\t{ $ne: ['$$shopId', null] },\n\t\t\t\t\t\t\t\t\t\t\t\t{ $eq: ['$shop', '$$shopId'] },\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Else → any shop in coupon.shops\n\t\t\t\t\t\t\t\t\t\t\t\t{ $in: ['$shop', '$$couponShops'] },\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],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$group: {\n\t\t\t\t\t\t\t\t_id: null,\n\t\t\t\t\t\t\t\torderedShops: { $addToSet: '$shop' },\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\tas: 'orderStats',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\torderedShops: {\n\t\t\t\t\t\t$ifNull: [{ $arrayElemAt: ['$orderStats.orderedShops', 0] }, []],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t$addFields: {\n\t\t\t\t\t// Individual store logic\n\t\t\t\t\thasOrderedFromStore: {\n\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t{ $eq: ['$couponDocs.couponType', CouponType.INDIVIDUAL_STORE] },\n\t\t\t\t\t\t\t{ $in: [shop ?? '$couponDocs.shop._id', '$orderedShops'] },\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\n\t\t\t\t\t// Multiple store logic\n\t\t\t\t\thasUnusedShopInCategory: {\n\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t{ $eq: ['$couponDocs.couponType', CouponType.SHOPS_CATEGORIES] },\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t{ $ifNull: [shop, false] },\n\t\t\t\t\t\t\t\t\t// shop provided → hide if user has ordered from this shop\n\t\t\t\t\t\t\t\t\t{ $in: [shop, '$orderedShops'] },\n\t\t\t\t\t\t\t\t\t// no shop provided → hide if no unused shops\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$eq: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t$size: { $setDifference: [{ $ifNull: ['$couponDocs.shops', []] }, '$orderedShops'] },\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t],\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},\n\t\t\t\t\t\t\tfalse,\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\t{\n\t\t\t\t$match: {\n\t\t\t\t\t$expr: {\n\t\t\t\t\t\t$not: {\n\t\t\t\t\t\t\t$and: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$in: ['$couponDocs.couponType', [CouponType.INDIVIDUAL_STORE, CouponType.SHOPS_CATEGORIES]],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{ $eq: ['$couponDocs.firstOrderOnly', true] },\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$or: ['$hasOrderedFromStore', '$hasUnusedShopInCategory'],\n\t\t\t\t\t\t\t\t},\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\t}\n}\n"]}
@@ -5,9 +5,18 @@ export declare class ReferralCodeCouponService {
5
5
  private model;
6
6
  private settingsModel;
7
7
  private userModel;
8
+ private _coreUserModel;
8
9
  constructor();
10
+ private get coreUserModel();
9
11
  create(data: CreateDTO): Promise<DocumentType<Model>>;
10
12
  update(id: string, data: UpdateDTO): Promise<DocumentType<Model>>;
13
+ private normalizeName;
14
+ private padToThree;
15
+ private containsArabic;
16
+ private generateRandomAlphaNumeric;
17
+ private generateThreeDigits;
18
+ private generateCouponFromName;
19
+ private splitName;
11
20
  private generateCode;
12
21
  private generateCouponCode;
13
22
  createReferralCodeForUser(userId: mongoose.Types.ObjectId | undefined): Promise<DocumentType<Model>>;
@@ -1 +1 @@
1
- {"version":3,"file":"referral-code-coupon.service.d.ts","sourceRoot":"/","sources":["modules/coupon/services/referral-code-coupon.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAEN,kBAAkB,IAAI,KAAK,EAK3B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACN,yBAAyB,EACzB,2BAA2B,IAAI,SAAS,EACxC,6BAA6B,EAC7B,2BAA2B,IAAI,SAAS,EACxC,iBAAiB,EACjB,MAAM,6BAA6B,CAAC;AAQrC,qBACa,yBAAyB;IACrC,OAAO,CAAC,KAAK,CAAC;IACd,OAAO,CAAC,aAAa,CAAiE;IACtF,OAAO,CAAC,SAAS,CAA2C;;IAa/C,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IASrD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAuB9E,OAAO,CAAC,YAAY;YASN,kBAAkB;IAanB,yBAAyB,CACrC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,GACzC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAkClB,cAAc,CAC1B,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,GACzB,OAAO,CAAC,yBAAyB,CAAC;IAgExB,qBAAqB,CACjC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAC7B,OAAO,CAAC,6BAA6B,CAAC;YAc3B,mBAAmB;CAKjC;AAED,eAAO,MAAM,yBAAyB,2BAA2C,CAAC"}
1
+ {"version":3,"file":"referral-code-coupon.service.d.ts","sourceRoot":"/","sources":["modules/coupon/services/referral-code-coupon.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAEN,kBAAkB,IAAI,KAAK,EAM3B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACN,yBAAyB,EACzB,2BAA2B,IAAI,SAAS,EACxC,6BAA6B,EAC7B,2BAA2B,IAAI,SAAS,EACxC,iBAAiB,EACjB,MAAM,6BAA6B,CAAC;AASrC,qBACa,yBAAyB;IACrC,OAAO,CAAC,KAAK,CAAC;IACd,OAAO,CAAC,aAAa,CAAiE;IACtF,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,cAAc,CAAoD;;IAS1E,OAAO,KAAK,aAAa,GAKxB;IAMY,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IASrD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IA8B9E,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,UAAU;IAgBlB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,0BAA0B;IAgBlC,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,sBAAsB;IAmC9B,OAAO,CAAC,SAAS;IAgBjB,OAAO,CAAC,YAAY;YAqBN,kBAAkB;IAiBnB,yBAAyB,CACrC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,GACzC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAkClB,cAAc,CAC1B,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,GACzB,OAAO,CAAC,yBAAyB,CAAC;IA2ExB,qBAAqB,CACjC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAC7B,OAAO,CAAC,6BAA6B,CAAC;YAc3B,mBAAmB;CAKjC;AAED,eAAO,MAAM,yBAAyB,2BAA2C,CAAC"}