@lyxa.ai/marketing 1.0.63 → 1.0.64

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 (182) hide show
  1. package/dist/lib/index.d.ts +19 -17
  2. package/dist/lib/index.d.ts.map +1 -1
  3. package/dist/lib/modules/coupon/routers/coupon.router.d.ts.map +1 -1
  4. package/dist/lib/modules/coupon/services/custom-coupon.service.d.ts +15 -3
  5. package/dist/lib/modules/coupon/services/custom-coupon.service.d.ts.map +1 -1
  6. package/dist/lib/modules/coupon/services/helper.service.d.ts +15 -3
  7. package/dist/lib/modules/coupon/services/helper.service.d.ts.map +1 -1
  8. package/dist/lib/modules/coupon/services/individual-store-coupon.service.d.ts +15 -3
  9. package/dist/lib/modules/coupon/services/individual-store-coupon.service.d.ts.map +1 -1
  10. package/dist/lib/modules/coupon/services/shops-categories-coupon.service.d.ts +15 -3
  11. package/dist/lib/modules/coupon/services/shops-categories-coupon.service.d.ts.map +1 -1
  12. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.d.ts +2 -0
  13. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.d.ts.map +1 -1
  14. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.js +18 -4
  15. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.js.map +1 -1
  16. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.d.ts.map +1 -1
  17. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.js +4 -0
  18. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.js.map +1 -1
  19. package/dist/lib/modules/limited-time-offer/limited-time-offer.service.d.ts.map +1 -1
  20. package/dist/lib/modules/limited-time-offer/limited-time-offer.service.js +3 -9
  21. package/dist/lib/modules/limited-time-offer/limited-time-offer.service.js.map +1 -1
  22. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.builder.d.ts +7 -1
  23. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.builder.d.ts.map +1 -1
  24. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.builder.js +5 -1
  25. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.builder.js.map +1 -1
  26. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.repository.d.ts +8 -0
  27. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.repository.d.ts.map +1 -1
  28. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.repository.js +60 -0
  29. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.repository.js.map +1 -1
  30. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.validation.d.ts +217 -213
  31. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.validation.d.ts.map +1 -1
  32. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.validation.js.map +1 -1
  33. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.d.ts +4 -0
  34. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.d.ts.map +1 -1
  35. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.js +14 -8
  36. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.js.map +1 -1
  37. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.d.ts +10 -9
  38. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.d.ts.map +1 -1
  39. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.js +64 -49
  40. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.js.map +1 -1
  41. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts +1 -0
  42. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts.map +1 -1
  43. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.js +15 -3
  44. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.js.map +1 -1
  45. package/dist/lib/modules/marketing/routers/marketing.router.d.ts +2 -0
  46. package/dist/lib/modules/marketing/routers/marketing.router.d.ts.map +1 -1
  47. package/dist/lib/modules/marketing/services/marketing.service.d.ts.map +1 -1
  48. package/dist/lib/modules/marketing/services/marketing.service.js +13 -3
  49. package/dist/lib/modules/marketing/services/marketing.service.js.map +1 -1
  50. package/dist/lib/modules/marketing/validations/buy1-get1-marketing.validation.d.ts +3 -3
  51. package/dist/lib/modules/marketing/validations/discount-marketing.validation.d.ts +3 -3
  52. package/dist/lib/modules/marketing/validations/marketing.validation.d.ts +6 -0
  53. package/dist/lib/modules/marketing/validations/marketing.validation.d.ts.map +1 -1
  54. package/dist/lib/modules/marketing/validations/marketing.validation.js +2 -0
  55. package/dist/lib/modules/marketing/validations/marketing.validation.js.map +1 -1
  56. package/dist/lib/modules/marketing/validations/product-marketing.validation.d.ts +2 -2
  57. package/dist/lib/modules/punch-marketing-history/routers/punch-marketing-history.router.d.ts +1 -1
  58. package/dist/lib/modules/punch-marketing-history/validations/punch-marketing-history.validation.d.ts +2 -2
  59. package/dist/lib/modules/spend-to-get-history/routers/index.d.ts +2 -0
  60. package/dist/lib/modules/spend-to-get-history/routers/index.d.ts.map +1 -0
  61. package/dist/lib/modules/spend-to-get-history/routers/index.js +18 -0
  62. package/dist/lib/modules/spend-to-get-history/routers/index.js.map +1 -0
  63. package/dist/lib/modules/spend-to-get-history/routers/spend-to-get-history.router.js +62 -0
  64. package/dist/lib/modules/spend-to-get-history/routers/spend-to-get-history.router.js.map +1 -0
  65. package/dist/lib/modules/spend-to-get-history/services/index.d.ts +2 -0
  66. package/dist/lib/modules/spend-to-get-history/services/index.d.ts.map +1 -0
  67. package/dist/lib/modules/spend-to-get-history/services/index.js +18 -0
  68. package/dist/lib/modules/spend-to-get-history/services/index.js.map +1 -0
  69. package/dist/lib/modules/spend-to-get-history/services/spend-to-get-history.service.d.ts +24 -0
  70. package/dist/lib/modules/spend-to-get-history/services/spend-to-get-history.service.d.ts.map +1 -0
  71. package/dist/lib/modules/spend-to-get-history/services/spend-to-get-history.service.js +136 -0
  72. package/dist/lib/modules/spend-to-get-history/services/spend-to-get-history.service.js.map +1 -0
  73. package/dist/lib/modules/spend-to-get-history/spend-to-get-history.repository.d.ts.map +1 -1
  74. package/dist/lib/modules/spend-to-get-history/spend-to-get-history.repository.js +13 -2
  75. package/dist/lib/modules/spend-to-get-history/spend-to-get-history.repository.js.map +1 -1
  76. package/dist/lib/modules/spend-to-get-history/spend-to-get-history.router.d.ts +16 -16
  77. package/dist/lib/modules/spend-to-get-history/spend-to-get-history.validation.d.ts +19 -19
  78. package/dist/lib/modules/spend-to-get-history/spend-to-get-history.validation.js +1 -1
  79. package/dist/lib/modules/spend-to-get-history/spend-to-get-history.validation.js.map +1 -1
  80. package/dist/lib/modules/spend-to-get-history/validations/index.d.ts +2 -0
  81. package/dist/lib/modules/spend-to-get-history/validations/index.d.ts.map +1 -0
  82. package/dist/lib/modules/spend-to-get-history/validations/index.js +18 -0
  83. package/dist/lib/modules/spend-to-get-history/validations/index.js.map +1 -0
  84. package/dist/lib/modules/spend-to-get-history/validations/spend-to-get-history.validation.d.ts +232 -0
  85. package/dist/lib/modules/spend-to-get-history/validations/spend-to-get-history.validation.d.ts.map +1 -0
  86. package/dist/lib/modules/spend-to-get-history/validations/spend-to-get-history.validation.js +30 -0
  87. package/dist/lib/modules/spend-to-get-history/validations/spend-to-get-history.validation.js.map +1 -0
  88. package/dist/lib/modules/tournament/match/events/match-ended.consumer.d.ts +2 -0
  89. package/dist/lib/modules/tournament/match/events/match-ended.consumer.d.ts.map +1 -0
  90. package/dist/lib/modules/tournament/match/events/match-ended.consumer.js +15 -0
  91. package/dist/lib/modules/tournament/match/events/match-ended.consumer.js.map +1 -0
  92. package/dist/lib/modules/tournament/match/events/match-ended.event.d.ts +14 -0
  93. package/dist/lib/modules/tournament/match/events/match-ended.event.d.ts.map +1 -0
  94. package/dist/lib/modules/tournament/match/events/match-ended.event.js +12 -0
  95. package/dist/lib/modules/tournament/match/events/match-ended.event.js.map +1 -0
  96. package/dist/lib/modules/tournament/notification/jobs/notification.producer.d.ts +10 -0
  97. package/dist/lib/modules/tournament/notification/jobs/notification.producer.d.ts.map +1 -0
  98. package/dist/lib/modules/tournament/notification/jobs/notification.producer.js +23 -0
  99. package/dist/lib/modules/tournament/notification/jobs/notification.producer.js.map +1 -0
  100. package/dist/lib/modules/tournament/notification/jobs/notification.worker.d.ts +9 -0
  101. package/dist/lib/modules/tournament/notification/jobs/notification.worker.d.ts.map +1 -0
  102. package/dist/lib/modules/tournament/notification/jobs/notification.worker.js +82 -0
  103. package/dist/lib/modules/tournament/notification/jobs/notification.worker.js.map +1 -0
  104. package/dist/lib/modules/tournament/notification/notification.schedule.config.d.ts +10 -0
  105. package/dist/lib/modules/tournament/notification/notification.schedule.config.d.ts.map +1 -0
  106. package/dist/lib/modules/tournament/notification/notification.schedule.config.js +15 -0
  107. package/dist/lib/modules/tournament/notification/notification.schedule.config.js.map +1 -0
  108. package/dist/lib/modules/tournament/notification/notification.scheduler.service.d.ts +10 -0
  109. package/dist/lib/modules/tournament/notification/notification.scheduler.service.d.ts.map +1 -0
  110. package/dist/lib/modules/tournament/notification/notification.scheduler.service.js +73 -0
  111. package/dist/lib/modules/tournament/notification/notification.scheduler.service.js.map +1 -0
  112. package/dist/types/events/event-initializations.d.ts +2 -0
  113. package/dist/types/events/event-initializations.d.ts.map +1 -0
  114. package/dist/types/index.d.ts +19 -17
  115. package/dist/types/index.d.ts.map +1 -1
  116. package/dist/types/modules/coupon/routers/coupon.router.d.ts.map +1 -1
  117. package/dist/types/modules/coupon/services/custom-coupon.service.d.ts +15 -3
  118. package/dist/types/modules/coupon/services/custom-coupon.service.d.ts.map +1 -1
  119. package/dist/types/modules/coupon/services/helper.service.d.ts +15 -3
  120. package/dist/types/modules/coupon/services/helper.service.d.ts.map +1 -1
  121. package/dist/types/modules/coupon/services/individual-store-coupon.service.d.ts +15 -3
  122. package/dist/types/modules/coupon/services/individual-store-coupon.service.d.ts.map +1 -1
  123. package/dist/types/modules/coupon/services/shops-categories-coupon.service.d.ts +15 -3
  124. package/dist/types/modules/coupon/services/shops-categories-coupon.service.d.ts.map +1 -1
  125. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.d.ts +2 -0
  126. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.d.ts.map +1 -1
  127. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.d.ts.map +1 -1
  128. package/dist/types/modules/limited-time-offer/limited-time-offer.service.d.ts.map +1 -1
  129. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.builder.d.ts +7 -1
  130. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.builder.d.ts.map +1 -1
  131. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.repository.d.ts +8 -0
  132. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.repository.d.ts.map +1 -1
  133. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.validation.d.ts +217 -213
  134. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.validation.d.ts.map +1 -1
  135. package/dist/types/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.d.ts +4 -0
  136. package/dist/types/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.d.ts.map +1 -1
  137. package/dist/types/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.d.ts +10 -9
  138. package/dist/types/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.d.ts.map +1 -1
  139. package/dist/types/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts +1 -0
  140. package/dist/types/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts.map +1 -1
  141. package/dist/types/modules/marketing/routers/marketing.router.d.ts +2 -0
  142. package/dist/types/modules/marketing/routers/marketing.router.d.ts.map +1 -1
  143. package/dist/types/modules/marketing/services/marketing.service.d.ts.map +1 -1
  144. package/dist/types/modules/marketing/validations/buy1-get1-marketing.validation.d.ts +3 -3
  145. package/dist/types/modules/marketing/validations/discount-marketing.validation.d.ts +3 -3
  146. package/dist/types/modules/marketing/validations/marketing.validation.d.ts +6 -0
  147. package/dist/types/modules/marketing/validations/marketing.validation.d.ts.map +1 -1
  148. package/dist/types/modules/marketing/validations/product-marketing.validation.d.ts +2 -2
  149. package/dist/types/modules/punch-marketing-history/routers/punch-marketing-history.router.d.ts +1 -1
  150. package/dist/types/modules/punch-marketing-history/validations/punch-marketing-history.validation.d.ts +2 -2
  151. package/dist/types/modules/spend-to-get-history/routers/index.d.ts +2 -0
  152. package/dist/types/modules/spend-to-get-history/routers/index.d.ts.map +1 -0
  153. package/dist/types/modules/spend-to-get-history/services/index.d.ts +2 -0
  154. package/dist/types/modules/spend-to-get-history/services/index.d.ts.map +1 -0
  155. package/dist/types/modules/spend-to-get-history/services/spend-to-get-history.service.d.ts +56 -0
  156. package/dist/types/modules/spend-to-get-history/services/spend-to-get-history.service.d.ts.map +1 -0
  157. package/dist/types/modules/spend-to-get-history/spend-to-get-history.repository.d.ts.map +1 -1
  158. package/dist/types/modules/spend-to-get-history/spend-to-get-history.router.d.ts +16 -16
  159. package/dist/types/modules/spend-to-get-history/spend-to-get-history.validation.d.ts +19 -19
  160. package/dist/types/modules/spend-to-get-history/validations/index.d.ts +2 -0
  161. package/dist/types/modules/spend-to-get-history/validations/index.d.ts.map +1 -0
  162. package/dist/types/modules/spend-to-get-history/validations/spend-to-get-history.validation.d.ts +241 -0
  163. package/dist/types/modules/spend-to-get-history/validations/spend-to-get-history.validation.d.ts.map +1 -0
  164. package/dist/types/modules/tournament/config/tournament-config.validation.d.ts +201 -0
  165. package/dist/types/modules/tournament/config/tournament-config.validation.d.ts.map +1 -0
  166. package/dist/types/modules/tournament/match/events/match-ended.consumer.d.ts +2 -0
  167. package/dist/types/modules/tournament/match/events/match-ended.consumer.d.ts.map +1 -0
  168. package/dist/types/modules/tournament/match/events/match-ended.event.d.ts +14 -0
  169. package/dist/types/modules/tournament/match/events/match-ended.event.d.ts.map +1 -0
  170. package/dist/types/modules/tournament/notification/jobs/notification.producer.d.ts +10 -0
  171. package/dist/types/modules/tournament/notification/jobs/notification.producer.d.ts.map +1 -0
  172. package/dist/types/modules/tournament/notification/jobs/notification.worker.d.ts +9 -0
  173. package/dist/types/modules/tournament/notification/jobs/notification.worker.d.ts.map +1 -0
  174. package/dist/types/modules/tournament/notification/notification.schedule.config.d.ts +10 -0
  175. package/dist/types/modules/tournament/notification/notification.schedule.config.d.ts.map +1 -0
  176. package/dist/types/modules/tournament/notification/notification.scheduler.service.d.ts +10 -0
  177. package/dist/types/modules/tournament/notification/notification.scheduler.service.d.ts.map +1 -0
  178. package/package.json +2 -2
  179. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.service.d.ts +0 -1
  180. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.service.d.ts.map +0 -1
  181. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.service.js +0 -2
  182. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.service.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MarketingMetricsRepository.js","sourceRoot":"/","sources":["modules/marketing/patterns/repository/MarketingMetricsRepository.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { dayjs } from '@lyxa.ai/core/dist/utilities/dayjs';\nimport { DocumentType, mongoose, ReturnModelType } from '@typegoose/typegoose';\nimport {\n\tFeaturedMarketing,\n\tLineItem,\n\tMarketing,\n\tMarketingModel,\n\tMarketing as Model,\n\tRegularOrder,\n\tRegularOrderModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {\n\tIncreaseDuringDiscountDTO,\n\tMarketingGraphInputDTO,\n\tMarketingMetricsDTO,\n\tMarketingOrdersGraphOutputDTO,\n} from '@modules/marketing/validations';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { GraphType, OrderType, RegularOrderStatus } from '@lyxa.ai/core/dist/utilities/enum';\nimport { productMarketingService } from '@modules/marketing/services/product-marketing.service';\nimport { MarketingType } from '@lyxa.ai/core/dist/utilities/enum';\nimport { notFoundError } from '@lyxa.ai/core/dist/utilities/error-common';\nimport { Duration } from '@lyxa.ai/core/dist/libraries/mongo/models/shared/duration.model';\nimport { LyxaTimezone } from '@lyxa.ai/core/dist/utilities/time';\nimport { fillMissingPeriods } from '@utility/utils';\n\n@Service()\nexport class MarketingMetricsRepository {\n\tprivate model: typeof MarketingModel & SoftDeleteModel<Model>;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\n\tconstructor() {\n\t\tthis.model = MarketingModel as typeof MarketingModel & SoftDeleteModel<Model>;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\t}\n\n\tpublic calculateMarketingSpendPerOrder(\n\t\torder: DocumentType<RegularOrder> & {\n\t\t\tlineItems: DocumentType<LineItem>[];\n\t\t\tmarketings: DocumentType<Marketing>[];\n\t\t}\n\t): Map<mongoose.Types.ObjectId, number> {\n\t\tconst spendMap = new Map<mongoose.Types.ObjectId, number>();\n\n\t\tconst marketingOwnerMap = new Map<string, 'COMPANY' | 'SHOP'>();\n\n\t\t// Build owner map\n\t\tfor (const marketing of order.marketings ?? []) {\n\t\t\tmarketingOwnerMap.set(marketing._id.toString(), marketing.isAppliedByCompany ? 'COMPANY' : 'SHOP');\n\t\t}\n\n\t\tconst addSpend = (marketingId: mongoose.Types.ObjectId, amount: number) => {\n\t\t\tif (!amount || amount <= 0) return;\n\t\t\tspendMap.set(marketingId, (spendMap.get(marketingId) ?? 0) + amount);\n\t\t};\n\n\t\tconst getRelevantAmount = (\n\t\t\tmarketingId: mongoose.Types.ObjectId,\n\t\t\tcompanyAmount: number,\n\t\t\tshopAmount: number\n\t\t) => {\n\t\t\tconst owner = marketingOwnerMap.get(marketingId.toString());\n\t\t\treturn owner === 'COMPANY' ? companyAmount : shopAmount;\n\t\t};\n\n\t\t/**\n\t\t * ITEM-BASED\n\t\t */\n\t\tfor (const lineItem of order.lineItems ?? []) {\n\t\t\tfor (const marketingId of lineItem.marketings ?? []) {\n\t\t\t\tconst snap = lineItem.calculationSnap ?? {};\n\n\t\t\t\taddSpend(\n\t\t\t\t\tmarketingId._id,\n\t\t\t\t\tgetRelevantAmount(\n\t\t\t\t\t\tmarketingId._id,\n\t\t\t\t\t\t(Number(snap.itemDiscountByCompany) || 0) + (Number(snap.b1g1DiscountByCompany) || 0),\n\t\t\t\t\t\t(Number(snap.itemDiscountByShop) || 0) + (Number(snap.b1g1DiscountByShop) || 0)\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * FREE DELIVERY\n\t\t */\n\t\tif (order.adjustedFinance?.freeDelivery) {\n\t\t\tfor (const marketingId of order.marketings ?? []) {\n\t\t\t\taddSpend(\n\t\t\t\t\tmarketingId._id,\n\t\t\t\t\tgetRelevantAmount(\n\t\t\t\t\t\tmarketingId._id,\n\t\t\t\t\t\torder.adjustedFinance.freeDelivery.companyCut ?? 0,\n\t\t\t\t\t\torder.adjustedFinance.freeDelivery.shopCut ?? 0\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * PUNCH MARKETING\n\t\t */\n\t\tif (order.adjustedFinance?.pricing?.punchMarketingDiscount) {\n\t\t\tfor (const marketingId of order.marketings ?? []) {\n\t\t\t\taddSpend(marketingId._id, order.adjustedFinance.pricing.punchMarketingDiscount);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * SPEND TO GET\n\t\t */\n\t\tif (order.adjustedFinance?.spendToGet) {\n\t\t\tfor (const marketingId of order.marketings ?? []) {\n\t\t\t\taddSpend(\n\t\t\t\t\tmarketingId._id,\n\t\t\t\t\tgetRelevantAmount(\n\t\t\t\t\t\tmarketingId._id,\n\t\t\t\t\t\torder.adjustedFinance.spendToGet.companyCut ?? 0,\n\t\t\t\t\t\torder.adjustedFinance.spendToGet.shopCut ?? 0\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn spendMap;\n\t}\n\n\tpublic async calculateMarketingSpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): Promise<{ amount: number; marketingType: MarketingType }> {\n\t\tconst marketing = await this.model.findById(marketingId).lean();\n\n\t\tif (!marketing) {\n\t\t\tnotFoundError('Marketing not found');\n\t\t}\n\n\t\tconst calculators: Record<MarketingType, () => Promise<number>> = {\n\t\t\t[MarketingType.FREE_DELIVERY]: () => this.calculateFreeDeliverySpent(marketingId, duration),\n\n\t\t\t[MarketingType.DISCOUNT]: () =>\n\t\t\t\tthis.calculateItemBasedSpent(marketingId, marketing.isAppliedByCompany, duration),\n\n\t\t\t[MarketingType.BUY1GET1]: () =>\n\t\t\t\tthis.calculateItemBasedSpent(marketingId, marketing.isAppliedByCompany, duration),\n\n\t\t\t[MarketingType.PUNCH_MARKETING]: () => this.calculatePunchMarketingSpent(marketingId, duration),\n\t\t\t[MarketingType.SPEND_TO_GET]: () => this.calculateSpendToGetSpent(marketingId, duration),\n\t\t\t[MarketingType.FEATURED]: function (): Promise<number> {\n\t\t\t\treturn Promise.resolve((marketing as DocumentType<FeaturedMarketing>).amount || 0);\n\t\t\t},\n\t\t};\n\n\t\tconst amount = calculators[marketing.marketingType] ? await calculators[marketing.marketingType]() : 0;\n\n\t\treturn {\n\t\t\tamount,\n\t\t\tmarketingType: marketing.marketingType,\n\t\t};\n\t}\n\n\tprivate async calculateItemBasedSpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tisAppliedByAdmin: boolean,\n\t\tduration?: Duration\n\t): Promise<number> {\n\t\tconst addBlock = isAppliedByAdmin\n\t\t\t? [\n\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.itemDiscountByCompany', 0] },\n\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.b1g1DiscountByCompany', 0] },\n\t\t\t\t]\n\t\t\t: [\n\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.itemDiscountByShop', 0] },\n\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.b1g1DiscountByShop', 0] },\n\t\t\t\t];\n\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\tthis.buildBaseMatch(marketingId, duration),\n\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'lineItems',\n\t\t\t\t\tlocalField: 'cart',\n\t\t\t\t\tforeignField: 'cart',\n\t\t\t\t\tas: 'lineItems',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ $unwind: '$lineItems' },\n\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalSpent: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$add: addBlock,\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\treturn this.runAggregateAndGetTotal(pipeline, 'totalSpent');\n\t}\n\n\tprivate async calculateFreeDeliverySpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): Promise<number> {\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\tthis.buildBaseMatch(marketingId, duration),\n\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalSpent: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$add: [\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.freeDelivery.companyCut', 0] },\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.freeDelivery.shopCut', 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\treturn this.runAggregateAndGetTotal(pipeline, 'totalSpent');\n\t}\n\n\tprivate async calculateSpendToGetSpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): Promise<number> {\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\tthis.buildBaseMatch(marketingId, duration),\n\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalSpent: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$add: [\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.spendToGet.companyCut', 0] },\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.spendToGet.shopCut', 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\treturn this.runAggregateAndGetTotal(pipeline, 'totalSpent');\n\t}\n\n\tprivate async calculatePunchMarketingSpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): Promise<number> {\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\tthis.buildBaseMatch(marketingId, duration),\n\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalSpent: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$ifNull: ['$adjustedFinance.pricing.punchMarketingDiscount', 0],\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\treturn this.runAggregateAndGetTotal(pipeline, 'totalSpent');\n\t}\n\n\tprivate buildBaseMatch(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): mongoose.PipelineStage.Match {\n\t\treturn {\n\t\t\t$match: {\n\t\t\t\tmarketings: marketingId,\n\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\t...(duration && {\n\t\t\t\t\tprocessedAt: {\n\t\t\t\t\t\t$gte: duration.start,\n\t\t\t\t\t\t$lte: duration.end,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async runAggregateAndGetTotal(pipeline: mongoose.PipelineStage[], field: string): Promise<number> {\n\t\tconst [result] = await this.orderModel.aggregate(pipeline);\n\t\treturn result?.[field] ?? 0;\n\t}\n\n\tpublic async getMetrics(marketingId: mongoose.Types.ObjectId): Promise<MarketingMetricsDTO> {\n\t\tconst marketing = await this.model.findById(marketingId).lean();\n\n\t\tif (!marketing) {\n\t\t\tnotFoundError('Marketing not found');\n\t\t}\n\n\t\t//TODO: fix current end and previous start\n\n\t\tconst currentDuration = { start: marketing.duration.start, end: dayjs().toDate() };\n\t\tconst previousDuration = {\n\t\t\tstart: dayjs(marketing.duration.start).subtract(dayjs().diff(marketing.duration.start)).toDate(),\n\t\t\tend: marketing.duration.start,\n\t\t};\n\n\t\tlet metrics: MarketingMetricsDTO = {};\n\n\t\tif ([MarketingType.DISCOUNT, MarketingType.BUY1GET1].includes(marketing.marketingType)) {\n\t\t\tmetrics.numberOfItems = await this.getMarketingItemCount(marketingId);\n\t\t}\n\n\t\tmetrics.orderIncreaseWithDiscount = await this.calculateOrderIncreaseWithDiscount(\n\t\t\tmarketingId,\n\t\t\tmarketing.shop._id,\n\t\t\tcurrentDuration,\n\t\t\tpreviousDuration\n\t\t);\n\t\tmetrics.customerIncreaseWithDiscount = await this.calculateCustomerIncreaseWithDiscount(\n\t\t\tmarketingId,\n\t\t\tmarketing.shop._id,\n\t\t\tcurrentDuration,\n\t\t\tpreviousDuration\n\t\t);\n\t\tmetrics.totalRedemptions = await this.orderModel.countDocuments({\n\t\t\tmarketings: marketingId,\n\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t});\n\n\t\treturn metrics;\n\t}\n\n\tprivate async getMarketingItemCount(marketingId: mongoose.Types.ObjectId): Promise<number> {\n\t\tconst result = await productMarketingService.countDocuments({ marketing: marketingId });\n\t\treturn result ?? 0;\n\t}\n\n\tprivate async calculateOrderIncreaseWithDiscount(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tshopId: mongoose.Types.ObjectId,\n\t\tcurrentDuration: Duration,\n\t\tpreviousDuration: Duration\n\t): Promise<IncreaseDuringDiscountDTO> {\n\t\tconst [currentOrders, previousOrders] = await Promise.all([\n\t\t\tthis.orderModel.countDocuments({\n\t\t\t\tcreatedAt: {\n\t\t\t\t\t$gte: currentDuration.start,\n\t\t\t\t\t$lte: currentDuration.end,\n\t\t\t\t},\n\t\t\t\tmarketings: marketingId, // marketing must be applied\n\t\t\t\tshop: shopId,\n\t\t\t}),\n\t\t\tthis.orderModel.countDocuments({\n\t\t\t\tcreatedAt: {\n\t\t\t\t\t$gte: previousDuration.start,\n\t\t\t\t\t$lte: previousDuration.end,\n\t\t\t\t},\n\t\t\t\tshop: shopId,\n\t\t\t}),\n\t\t]);\n\n\t\treturn this.calculateIncrease(currentOrders, previousOrders);\n\t}\n\n\tprivate async calculateCustomerIncreaseWithDiscount(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tshopId: mongoose.Types.ObjectId,\n\t\tcurrentDuration: Duration,\n\t\tpreviousDuration: Duration\n\t): Promise<IncreaseDuringDiscountDTO> {\n\t\tconst [currentNewCustomers, previousNewCustomers] = await Promise.all([\n\t\t\tthis.getNewCustomersForShop(shopId, currentDuration, { marketings: marketingId }),\n\t\t\tthis.getNewCustomersForShop(shopId, previousDuration),\n\t\t]);\n\n\t\treturn this.calculateIncrease(currentNewCustomers, previousNewCustomers);\n\t}\n\n\tprivate calculateIncrease(current: number, previous: number): IncreaseDuringDiscountDTO {\n\t\tconst count = current - previous;\n\n\t\tconst percentageIncrease = previous === 0 ? (current > 0 ? 100 : 0) : (count / previous) * 100;\n\n\t\treturn {\n\t\t\tcount,\n\t\t\tpercentageIncrease,\n\t\t};\n\t}\n\n\tprivate async getNewCustomersForShop(\n\t\tshopId: mongoose.Types.ObjectId,\n\t\tduration: Duration,\n\t\textraMatch: Record<string, any> = {}\n\t): Promise<number> {\n\t\t// Customers who ordered during the period\n\t\tconst customersInPeriod = await this.orderModel.distinct('user', {\n\t\t\tcreatedAt: {\n\t\t\t\t$gte: duration.start,\n\t\t\t\t$lte: duration.end,\n\t\t\t},\n\t\t\tshop: shopId,\n\t\t\t...extraMatch,\n\t\t});\n\n\t\tif (customersInPeriod.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Customers who had ordered from this shop BEFORE the period\n\t\tconst existingCustomers = await this.orderModel.distinct('user', {\n\t\t\tshop: shopId,\n\t\t\tcreatedAt: { $lt: duration.start },\n\t\t\tuser: { $in: customersInPeriod },\n\t\t});\n\n\t\t// New customers = in period − existing\n\t\treturn customersInPeriod.length - existingCustomers.length;\n\t}\n\n\tpublic async getOrdersGraph(data: MarketingGraphInputDTO): Promise<MarketingOrdersGraphOutputDTO> {\n\t\tconst dateFormat = data.type === GraphType.MONTHLY ? '%Y-%m' : '%Y-%m-%d';\n\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\t// Filter only delivered orders within the given date range\n\t\t\tthis.buildBaseMatch(new mongoose.Types.ObjectId(data.marketingId), {\n\t\t\t\tstart: data.startDate,\n\t\t\t\tend: data.endDate,\n\t\t\t}),\n\n\t\t\t// Extract formatted date from 'processedAt' for grouping\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\tdate: {\n\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\tdate: '$processedAt',\n\t\t\t\t\t\t\ttimezone: LyxaTimezone,\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 by formatted date and count orders\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: '$date',\n\t\t\t\t\torders: { $sum: 1 },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Sort results chronologically\n\t\t\t{\n\t\t\t\t$sort: { _id: 1 },\n\t\t\t},\n\n\t\t\t// Format the response to match output DTO structure\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\t_id: 0,\n\t\t\t\t\tdate: '$_id',\n\t\t\t\t\torders: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\t// Execute aggregation pipeline\n\t\tconst results = await this.orderModel.aggregate(pipeline).allowDiskUse(true).exec();\n\n\t\tconst graphData = fillMissingPeriods(results, data.startDate, data.endDate, data.type, {\n\t\t\torders: 0,\n\t\t});\n\n\t\treturn graphData;\n\t}\n\n\tpublic async getCustomersGraph(data: MarketingGraphInputDTO): Promise<{ date: string; users: number }[]> {\n\t\t// 1️⃣ Get shopId from marketing\n\t\tconst marketing = await this.model.findById(data.marketingId).select('shop').lean();\n\n\t\tif (!marketing) {\n\t\t\tnotFoundError('Marketing not found');\n\t\t}\n\n\t\tconst shopId = marketing.shop._id;\n\n\t\t// 2️⃣ Fetch users who ordered from this shop BEFORE the start date\n\t\tconst oldUsers = await this.orderModel.distinct('user', {\n\t\t\tshop: shopId,\n\t\t\tstatus: RegularOrderStatus.DELIVERED,\n\t\t\tprocessedAt: { $lt: data.startDate },\n\t\t});\n\n\t\tconst dateFormat = data.type === GraphType.MONTHLY ? '%Y-%m' : '%Y-%m-%d';\n\n\t\t// 3️⃣ Aggregation pipeline\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\t// Orders during the period with this marketing\n\t\t\t{\n\t\t\t\t$match: {\n\t\t\t\t\torderType: OrderType.REGULAR,\n\t\t\t\t\tstatus: RegularOrderStatus.DELIVERED,\n\t\t\t\t\tshop: shopId,\n\t\t\t\t\tmarketings: new mongoose.Types.ObjectId(data.marketingId),\n\t\t\t\t\tprocessedAt: { $gte: data.startDate, $lte: data.endDate },\n\t\t\t\t\tuser: { $nin: oldUsers }, // 🚫 exclude old users\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Sort so earliest order per user comes first\n\t\t\t{ $sort: { processedAt: 1 } },\n\n\t\t\t// First order per user (new users only)\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: '$user',\n\t\t\t\t\tfirstOrderDate: { $first: '$processedAt' },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Format date\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\tdate: {\n\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\tdate: '$firstOrderDate',\n\t\t\t\t\t\t\ttimezone: LyxaTimezone,\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 by date\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: '$date',\n\t\t\t\t\tusers: { $sum: 1 },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Sort chronologically\n\t\t\t{ $sort: { _id: 1 } },\n\n\t\t\t// Shape response\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\t_id: 0,\n\t\t\t\t\tdate: '$_id',\n\t\t\t\t\tusers: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tconst results = await this.orderModel.aggregate(pipeline).allowDiskUse(true).exec();\n\n\t\t// 4️⃣ Fill missing periods\n\t\treturn fillMissingPeriods(results, data.startDate, data.endDate, data.type, {\n\t\t\tusers: 0,\n\t\t});\n\t}\n\n\tpublic async getAmountSpentGraph(\n\t\tdata: MarketingGraphInputDTO\n\t): Promise<{ date: string; amount: number }[]> {\n\t\tconst marketing = await this.model.findById(data.marketingId).lean();\n\n\t\tif (!marketing) {\n\t\t\tnotFoundError('Marketing not found');\n\t\t}\n\n\t\tconst marketingId = new mongoose.Types.ObjectId(data.marketingId);\n\t\tconst dateFormat = data.type === GraphType.MONTHLY ? '%Y-%m' : '%Y-%m-%d';\n\n\t\tlet pipeline: mongoose.PipelineStage[] | null = null;\n\n\t\t/**\n\t\t * ITEM-BASED (DISCOUNT / BUY1GET1)\n\t\t */\n\t\tif ([MarketingType.DISCOUNT, MarketingType.BUY1GET1].includes(marketing.marketingType)) {\n\t\t\tpipeline = [\n\t\t\t\tthis.buildBaseMatch(marketingId, {\n\t\t\t\t\tstart: data.startDate,\n\t\t\t\t\tend: data.endDate,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\t$lookup: {\n\t\t\t\t\t\tfrom: 'lineItems',\n\t\t\t\t\t\tlocalField: 'cart',\n\t\t\t\t\t\tforeignField: 'cart',\n\t\t\t\t\t\tas: 'lineItems',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $unwind: '$lineItems' },\n\t\t\t\t{\n\t\t\t\t\t$match: {\n\t\t\t\t\t\t'lineItems.marketings': marketingId,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\tdate: {\n\t\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\t\tdate: '$processedAt',\n\t\t\t\t\t\t\t\ttimezone: LyxaTimezone,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tamount: {\n\t\t\t\t\t\t\t$add: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t\tmarketing.isAppliedByCompany,\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.itemDiscountByCompany', 0] },\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.itemDiscountByShop', 0] },\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\t{\n\t\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t\tmarketing.isAppliedByCompany,\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.b1g1DiscountByCompany', 0] },\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.b1g1DiscountByShop', 0] },\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\t{\n\t\t\t\t\t$group: {\n\t\t\t\t\t\t_id: '$date',\n\t\t\t\t\t\tamount: { $sum: '$amount' },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $sort: { _id: 1 } },\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\t_id: 0,\n\t\t\t\t\t\tdate: '$_id',\n\t\t\t\t\t\tamount: 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t} else if (marketing.marketingType === MarketingType.FREE_DELIVERY) {\n\t\t\t/**\n\t\t\t * FREE DELIVERY\n\t\t\t */\n\t\t\tpipeline = [\n\t\t\t\tthis.buildBaseMatch(marketingId, {\n\t\t\t\t\tstart: data.startDate,\n\t\t\t\t\tend: data.endDate,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\tdate: {\n\t\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\t\tdate: '$processedAt',\n\t\t\t\t\t\t\t\ttimezone: LyxaTimezone,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tamount: {\n\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\tmarketing.isAppliedByCompany,\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.freeDelivery.companyCut', 0] },\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.freeDelivery.shopCut', 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\t{\n\t\t\t\t\t$group: {\n\t\t\t\t\t\t_id: '$date',\n\t\t\t\t\t\tamount: { $sum: '$amount' },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $sort: { _id: 1 } },\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\t_id: 0,\n\t\t\t\t\t\tdate: '$_id',\n\t\t\t\t\t\tamount: 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t} else if (marketing.marketingType === MarketingType.PUNCH_MARKETING) {\n\t\t\t/**\n\t\t\t * PUNCH MARKETING\n\t\t\t */\n\t\t\tpipeline = [\n\t\t\t\tthis.buildBaseMatch(marketingId, {\n\t\t\t\t\tstart: data.startDate,\n\t\t\t\t\tend: data.endDate,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\tdate: {\n\t\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\t\tdate: '$processedAt',\n\t\t\t\t\t\t\t\ttimezone: LyxaTimezone,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tamount: {\n\t\t\t\t\t\t\t$ifNull: ['$adjustedFinance.pricing.punchMarketingDiscount', 0],\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$group: {\n\t\t\t\t\t\t_id: '$date',\n\t\t\t\t\t\tamount: { $sum: '$amount' },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $sort: { _id: 1 } },\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\t_id: 0,\n\t\t\t\t\t\tdate: '$_id',\n\t\t\t\t\t\tamount: 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// If marketing type doesn't produce spend graph → return empty graph\n\t\tif (!pipeline) {\n\t\t\treturn fillMissingPeriods(\n\t\t\t\t[] as { date: string; amount: number }[],\n\t\t\t\tdata.startDate,\n\t\t\t\tdata.endDate,\n\t\t\t\tdata.type,\n\t\t\t\t{\n\t\t\t\t\tamount: 0,\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tconst results = await this.orderModel.aggregate(pipeline).allowDiskUse(true).exec();\n\n\t\treturn fillMissingPeriods(results, data.startDate, data.endDate, data.type, {\n\t\t\tamount: 0,\n\t\t});\n\t}\n}\n\nexport const marketingMetricsRepository = Container.get(MarketingMetricsRepository);\n"]}
1
+ {"version":3,"file":"MarketingMetricsRepository.js","sourceRoot":"/","sources":["modules/marketing/patterns/repository/MarketingMetricsRepository.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { dayjs } from '@lyxa.ai/core/dist/utilities/dayjs';\nimport { DocumentType, mongoose, ReturnModelType } from '@typegoose/typegoose';\nimport {\n\tFeaturedMarketing,\n\tLineItem,\n\tMarketing,\n\tMarketingModel,\n\tMarketing as Model,\n\tRegularOrder,\n\tRegularOrderModel,\n\tSpendToGetMarketing,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {\n\tIncreaseDuringDiscountDTO,\n\tMarketingGraphInputDTO,\n\tMarketingMetricsDTO,\n\tMarketingOrdersGraphOutputDTO,\n} from '@modules/marketing/validations';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { GraphType, OrderType, RegularOrderStatus, SpendToGetRewardType } from '@lyxa.ai/core/dist/utilities/enum';\nimport { productMarketingService } from '@modules/marketing/services/product-marketing.service';\nimport { MarketingType } from '@lyxa.ai/core/dist/utilities/enum';\nimport { notFoundError } from '@lyxa.ai/core/dist/utilities/error-common';\nimport { Duration } from '@lyxa.ai/core/dist/libraries/mongo/models/shared/duration.model';\nimport { LyxaTimezone } from '@lyxa.ai/core/dist/utilities/time';\nimport { fillMissingPeriods } from '@utility/utils';\n\n@Service()\nexport class MarketingMetricsRepository {\n\tprivate model: typeof MarketingModel & SoftDeleteModel<Model>;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\n\tconstructor() {\n\t\tthis.model = MarketingModel as typeof MarketingModel & SoftDeleteModel<Model>;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\t}\n\n\tpublic calculateMarketingSpendPerOrder(\n\t\torder: DocumentType<RegularOrder> & {\n\t\t\tlineItems: DocumentType<LineItem>[];\n\t\t\tmarketings: DocumentType<Marketing>[];\n\t\t}\n\t): Map<mongoose.Types.ObjectId, number> {\n\t\tconst spendMap = new Map<mongoose.Types.ObjectId, number>();\n\n\t\tconst marketingOwnerMap = new Map<string, 'COMPANY' | 'SHOP'>();\n\n\t\t// Build owner map\n\t\tfor (const marketing of order.marketings ?? []) {\n\t\t\tmarketingOwnerMap.set(marketing._id.toString(), marketing.isAppliedByCompany ? 'COMPANY' : 'SHOP');\n\t\t}\n\n\t\tconst addSpend = (marketingId: mongoose.Types.ObjectId, amount: number) => {\n\t\t\tif (!amount || amount <= 0) return;\n\t\t\tspendMap.set(marketingId, (spendMap.get(marketingId) ?? 0) + amount);\n\t\t};\n\n\t\tconst getRelevantAmount = (\n\t\t\tmarketingId: mongoose.Types.ObjectId,\n\t\t\tcompanyAmount: number,\n\t\t\tshopAmount: number\n\t\t) => {\n\t\t\tconst owner = marketingOwnerMap.get(marketingId.toString());\n\t\t\treturn owner === 'COMPANY' ? companyAmount : shopAmount;\n\t\t};\n\n\t\t/**\n\t\t * ITEM-BASED\n\t\t */\n\t\tfor (const lineItem of order.lineItems ?? []) {\n\t\t\tfor (const marketingId of lineItem.marketings ?? []) {\n\t\t\t\tconst snap = lineItem.calculationSnap ?? {};\n\n\t\t\t\taddSpend(\n\t\t\t\t\tmarketingId._id,\n\t\t\t\t\tgetRelevantAmount(\n\t\t\t\t\t\tmarketingId._id,\n\t\t\t\t\t\t(Number(snap.itemDiscountByCompany) || 0) + (Number(snap.b1g1DiscountByCompany) || 0),\n\t\t\t\t\t\t(Number(snap.itemDiscountByShop) || 0) + (Number(snap.b1g1DiscountByShop) || 0)\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * FREE DELIVERY\n\t\t */\n\t\tif (order.adjustedFinance?.freeDelivery) {\n\t\t\tfor (const marketingId of order.marketings ?? []) {\n\t\t\t\taddSpend(\n\t\t\t\t\tmarketingId._id,\n\t\t\t\t\tgetRelevantAmount(\n\t\t\t\t\t\tmarketingId._id,\n\t\t\t\t\t\torder.adjustedFinance.freeDelivery.companyCut ?? 0,\n\t\t\t\t\t\torder.adjustedFinance.freeDelivery.shopCut ?? 0\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * PUNCH MARKETING\n\t\t */\n\t\tif (order.adjustedFinance?.pricing?.punchMarketingDiscount) {\n\t\t\tfor (const marketingId of order.marketings ?? []) {\n\t\t\t\taddSpend(marketingId._id, order.adjustedFinance.pricing.punchMarketingDiscount);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * SPEND TO GET (discount tiers)\n\t\t * A free-delivery tier mirrors its cut into adjustedFinance.freeDelivery and is counted by the\n\t\t * FREE DELIVERY block above, so it is skipped here to avoid double-debiting the budget. Discount\n\t\t * tiers are attributed to the single STG marketing that granted them — never spread across other\n\t\t * marketings on the order.\n\t\t */\n\t\tconst spendToGet = order.adjustedFinance?.spendToGet;\n\t\tif (spendToGet && spendToGet.rewardType !== SpendToGetRewardType.FREE_DELIVERY) {\n\t\t\tconst spendToGetMarketingId = (spendToGet.marketing as any)?._id ?? spendToGet.marketing;\n\t\t\tif (spendToGetMarketingId) {\n\t\t\t\taddSpend(\n\t\t\t\t\tspendToGetMarketingId,\n\t\t\t\t\tgetRelevantAmount(spendToGetMarketingId, spendToGet.companyCut ?? 0, spendToGet.shopCut ?? 0)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn spendMap;\n\t}\n\n\tpublic async calculateMarketingSpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): Promise<{ amount: number; marketingType: MarketingType }> {\n\t\tconst marketing = await this.model.findById(marketingId).lean();\n\n\t\tif (!marketing) {\n\t\t\tnotFoundError('Marketing not found');\n\t\t}\n\n\t\tconst calculators: Record<MarketingType, () => Promise<number>> = {\n\t\t\t[MarketingType.FREE_DELIVERY]: () => this.calculateFreeDeliverySpent(marketingId, duration),\n\n\t\t\t[MarketingType.DISCOUNT]: () =>\n\t\t\t\tthis.calculateItemBasedSpent(marketingId, marketing.isAppliedByCompany, duration),\n\n\t\t\t[MarketingType.BUY1GET1]: () =>\n\t\t\t\tthis.calculateItemBasedSpent(marketingId, marketing.isAppliedByCompany, duration),\n\n\t\t\t[MarketingType.PUNCH_MARKETING]: () => this.calculatePunchMarketingSpent(marketingId, duration),\n\t\t\t[MarketingType.SPEND_TO_GET]: () => this.calculateSpendToGetSpent(marketingId, duration),\n\t\t\t[MarketingType.FEATURED]: function (): Promise<number> {\n\t\t\t\treturn Promise.resolve((marketing as DocumentType<FeaturedMarketing>).amount || 0);\n\t\t\t},\n\t\t};\n\n\t\tconst amount = calculators[marketing.marketingType] ? await calculators[marketing.marketingType]() : 0;\n\n\t\treturn {\n\t\t\tamount,\n\t\t\tmarketingType: marketing.marketingType,\n\t\t};\n\t}\n\n\tprivate async calculateItemBasedSpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tisAppliedByAdmin: boolean,\n\t\tduration?: Duration\n\t): Promise<number> {\n\t\tconst addBlock = isAppliedByAdmin\n\t\t\t? [\n\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.itemDiscountByCompany', 0] },\n\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.b1g1DiscountByCompany', 0] },\n\t\t\t\t]\n\t\t\t: [\n\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.itemDiscountByShop', 0] },\n\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.b1g1DiscountByShop', 0] },\n\t\t\t\t];\n\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\tthis.buildBaseMatch(marketingId, duration),\n\n\t\t\t{\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: 'lineItems',\n\t\t\t\t\tlocalField: 'cart',\n\t\t\t\t\tforeignField: 'cart',\n\t\t\t\t\tas: 'lineItems',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ $unwind: '$lineItems' },\n\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalSpent: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$add: addBlock,\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\treturn this.runAggregateAndGetTotal(pipeline, 'totalSpent');\n\t}\n\n\tprivate async calculateFreeDeliverySpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): Promise<number> {\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\tthis.buildBaseMatch(marketingId, duration),\n\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalSpent: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$add: [\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.freeDelivery.companyCut', 0] },\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.freeDelivery.shopCut', 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\treturn this.runAggregateAndGetTotal(pipeline, 'totalSpent');\n\t}\n\n\tprivate async calculateSpendToGetSpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): Promise<number> {\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\tthis.buildBaseMatch(marketingId, duration),\n\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalSpent: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$add: [\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.spendToGet.companyCut', 0] },\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.spendToGet.shopCut', 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\treturn this.runAggregateAndGetTotal(pipeline, 'totalSpent');\n\t}\n\n\tprivate async calculatePunchMarketingSpent(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): Promise<number> {\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\tthis.buildBaseMatch(marketingId, duration),\n\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: null,\n\t\t\t\t\ttotalSpent: {\n\t\t\t\t\t\t$sum: {\n\t\t\t\t\t\t\t$ifNull: ['$adjustedFinance.pricing.punchMarketingDiscount', 0],\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\treturn this.runAggregateAndGetTotal(pipeline, 'totalSpent');\n\t}\n\n\tprivate buildBaseMatch(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tduration?: Duration\n\t): mongoose.PipelineStage.Match {\n\t\treturn {\n\t\t\t$match: {\n\t\t\t\tmarketings: marketingId,\n\t\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t\t\t...(duration && {\n\t\t\t\t\tprocessedAt: {\n\t\t\t\t\t\t$gte: duration.start,\n\t\t\t\t\t\t$lte: duration.end,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async runAggregateAndGetTotal(pipeline: mongoose.PipelineStage[], field: string): Promise<number> {\n\t\tconst [result] = await this.orderModel.aggregate(pipeline);\n\t\treturn result?.[field] ?? 0;\n\t}\n\n\tpublic async getMetrics(marketingId: mongoose.Types.ObjectId): Promise<MarketingMetricsDTO> {\n\t\tconst marketing = await this.model.findById(marketingId).lean();\n\n\t\tif (!marketing) {\n\t\t\tnotFoundError('Marketing not found');\n\t\t}\n\n\t\t//TODO: fix current end and previous start\n\n\t\tconst currentDuration = { start: marketing.duration.start, end: dayjs().toDate() };\n\t\tconst previousDuration = {\n\t\t\tstart: dayjs(marketing.duration.start).subtract(dayjs().diff(marketing.duration.start)).toDate(),\n\t\t\tend: marketing.duration.start,\n\t\t};\n\n\t\tlet metrics: MarketingMetricsDTO = {};\n\n\t\tif ([MarketingType.DISCOUNT, MarketingType.BUY1GET1].includes(marketing.marketingType)) {\n\t\t\tmetrics.numberOfItems = await this.getMarketingItemCount(marketingId);\n\t\t}\n\n\t\tmetrics.orderIncreaseWithDiscount = await this.calculateOrderIncreaseWithDiscount(\n\t\t\tmarketingId,\n\t\t\tmarketing.shop._id,\n\t\t\tcurrentDuration,\n\t\t\tpreviousDuration\n\t\t);\n\t\tmetrics.customerIncreaseWithDiscount = await this.calculateCustomerIncreaseWithDiscount(\n\t\t\tmarketingId,\n\t\t\tmarketing.shop._id,\n\t\t\tcurrentDuration,\n\t\t\tpreviousDuration\n\t\t);\n\t\tmetrics.totalRedemptions = await this.orderModel.countDocuments({\n\t\t\tmarketings: marketingId,\n\t\t\tstatus: { $ne: RegularOrderStatus.CANCELLED },\n\t\t});\n\n\t\tif (marketing.marketingType === MarketingType.SPEND_TO_GET) {\n\t\t\tObject.assign(metrics, this.getSpendToGetBudgetMetrics(marketing));\n\t\t}\n\n\t\treturn metrics;\n\t}\n\n\t// amountSpent is the running total of value given (discount + free-delivery cut), maintained on\n\t// order placement and restored on cancel — reuse it so totalValueGiven and remainingBudget stay\n\t// internally consistent (remainingBudget = spendLimit - totalValueGiven).\n\tprivate getSpendToGetBudgetMetrics(\n\t\tmarketing: Pick<SpendToGetMarketing, 'amountSpent' | 'isSpendLimitEnabled' | 'spendLimit'>\n\t): Pick<MarketingMetricsDTO, 'totalValueGiven' | 'remainingBudget'> {\n\t\tconst totalValueGiven = marketing.amountSpent ?? 0;\n\t\tconst remainingBudget =\n\t\t\tmarketing.isSpendLimitEnabled && marketing.spendLimit\n\t\t\t\t? Math.max(marketing.spendLimit - totalValueGiven, 0)\n\t\t\t\t: undefined;\n\n\t\treturn { totalValueGiven, remainingBudget };\n\t}\n\n\tprivate async getMarketingItemCount(marketingId: mongoose.Types.ObjectId): Promise<number> {\n\t\tconst result = await productMarketingService.countDocuments({ marketing: marketingId });\n\t\treturn result ?? 0;\n\t}\n\n\tprivate async calculateOrderIncreaseWithDiscount(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tshopId: mongoose.Types.ObjectId,\n\t\tcurrentDuration: Duration,\n\t\tpreviousDuration: Duration\n\t): Promise<IncreaseDuringDiscountDTO> {\n\t\tconst [currentOrders, previousOrders] = await Promise.all([\n\t\t\tthis.orderModel.countDocuments({\n\t\t\t\tcreatedAt: {\n\t\t\t\t\t$gte: currentDuration.start,\n\t\t\t\t\t$lte: currentDuration.end,\n\t\t\t\t},\n\t\t\t\tmarketings: marketingId, // marketing must be applied\n\t\t\t\tshop: shopId,\n\t\t\t}),\n\t\t\tthis.orderModel.countDocuments({\n\t\t\t\tcreatedAt: {\n\t\t\t\t\t$gte: previousDuration.start,\n\t\t\t\t\t$lte: previousDuration.end,\n\t\t\t\t},\n\t\t\t\tshop: shopId,\n\t\t\t}),\n\t\t]);\n\n\t\treturn this.calculateIncrease(currentOrders, previousOrders);\n\t}\n\n\tprivate async calculateCustomerIncreaseWithDiscount(\n\t\tmarketingId: mongoose.Types.ObjectId,\n\t\tshopId: mongoose.Types.ObjectId,\n\t\tcurrentDuration: Duration,\n\t\tpreviousDuration: Duration\n\t): Promise<IncreaseDuringDiscountDTO> {\n\t\tconst [currentNewCustomers, previousNewCustomers] = await Promise.all([\n\t\t\tthis.getNewCustomersForShop(shopId, currentDuration, { marketings: marketingId }),\n\t\t\tthis.getNewCustomersForShop(shopId, previousDuration),\n\t\t]);\n\n\t\treturn this.calculateIncrease(currentNewCustomers, previousNewCustomers);\n\t}\n\n\tprivate calculateIncrease(current: number, previous: number): IncreaseDuringDiscountDTO {\n\t\tconst count = current - previous;\n\n\t\tconst percentageIncrease = previous === 0 ? (current > 0 ? 100 : 0) : (count / previous) * 100;\n\n\t\treturn {\n\t\t\tcount,\n\t\t\tpercentageIncrease,\n\t\t};\n\t}\n\n\tprivate async getNewCustomersForShop(\n\t\tshopId: mongoose.Types.ObjectId,\n\t\tduration: Duration,\n\t\textraMatch: Record<string, any> = {}\n\t): Promise<number> {\n\t\t// Customers who ordered during the period\n\t\tconst customersInPeriod = await this.orderModel.distinct('user', {\n\t\t\tcreatedAt: {\n\t\t\t\t$gte: duration.start,\n\t\t\t\t$lte: duration.end,\n\t\t\t},\n\t\t\tshop: shopId,\n\t\t\t...extraMatch,\n\t\t});\n\n\t\tif (customersInPeriod.length === 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Customers who had ordered from this shop BEFORE the period\n\t\tconst existingCustomers = await this.orderModel.distinct('user', {\n\t\t\tshop: shopId,\n\t\t\tcreatedAt: { $lt: duration.start },\n\t\t\tuser: { $in: customersInPeriod },\n\t\t});\n\n\t\t// New customers = in period − existing\n\t\treturn customersInPeriod.length - existingCustomers.length;\n\t}\n\n\tpublic async getOrdersGraph(data: MarketingGraphInputDTO): Promise<MarketingOrdersGraphOutputDTO> {\n\t\tconst dateFormat = data.type === GraphType.MONTHLY ? '%Y-%m' : '%Y-%m-%d';\n\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\t// Filter only delivered orders within the given date range\n\t\t\tthis.buildBaseMatch(new mongoose.Types.ObjectId(data.marketingId), {\n\t\t\t\tstart: data.startDate,\n\t\t\t\tend: data.endDate,\n\t\t\t}),\n\n\t\t\t// Extract formatted date from 'processedAt' for grouping\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\tdate: {\n\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\tdate: '$processedAt',\n\t\t\t\t\t\t\ttimezone: LyxaTimezone,\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 by formatted date and count orders\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: '$date',\n\t\t\t\t\torders: { $sum: 1 },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Sort results chronologically\n\t\t\t{\n\t\t\t\t$sort: { _id: 1 },\n\t\t\t},\n\n\t\t\t// Format the response to match output DTO structure\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\t_id: 0,\n\t\t\t\t\tdate: '$_id',\n\t\t\t\t\torders: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\t// Execute aggregation pipeline\n\t\tconst results = await this.orderModel.aggregate(pipeline).allowDiskUse(true).exec();\n\n\t\tconst graphData = fillMissingPeriods(results, data.startDate, data.endDate, data.type, {\n\t\t\torders: 0,\n\t\t});\n\n\t\treturn graphData;\n\t}\n\n\tpublic async getCustomersGraph(data: MarketingGraphInputDTO): Promise<{ date: string; users: number }[]> {\n\t\t// 1️⃣ Get shopId from marketing\n\t\tconst marketing = await this.model.findById(data.marketingId).select('shop').lean();\n\n\t\tif (!marketing) {\n\t\t\tnotFoundError('Marketing not found');\n\t\t}\n\n\t\tconst shopId = marketing.shop._id;\n\n\t\t// 2️⃣ Fetch users who ordered from this shop BEFORE the start date\n\t\tconst oldUsers = await this.orderModel.distinct('user', {\n\t\t\tshop: shopId,\n\t\t\tstatus: RegularOrderStatus.DELIVERED,\n\t\t\tprocessedAt: { $lt: data.startDate },\n\t\t});\n\n\t\tconst dateFormat = data.type === GraphType.MONTHLY ? '%Y-%m' : '%Y-%m-%d';\n\n\t\t// 3️⃣ Aggregation pipeline\n\t\tconst pipeline: mongoose.PipelineStage[] = [\n\t\t\t// Orders during the period with this marketing\n\t\t\t{\n\t\t\t\t$match: {\n\t\t\t\t\torderType: OrderType.REGULAR,\n\t\t\t\t\tstatus: RegularOrderStatus.DELIVERED,\n\t\t\t\t\tshop: shopId,\n\t\t\t\t\tmarketings: new mongoose.Types.ObjectId(data.marketingId),\n\t\t\t\t\tprocessedAt: { $gte: data.startDate, $lte: data.endDate },\n\t\t\t\t\tuser: { $nin: oldUsers }, // 🚫 exclude old users\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Sort so earliest order per user comes first\n\t\t\t{ $sort: { processedAt: 1 } },\n\n\t\t\t// First order per user (new users only)\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: '$user',\n\t\t\t\t\tfirstOrderDate: { $first: '$processedAt' },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Format date\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\tdate: {\n\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\tdate: '$firstOrderDate',\n\t\t\t\t\t\t\ttimezone: LyxaTimezone,\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 by date\n\t\t\t{\n\t\t\t\t$group: {\n\t\t\t\t\t_id: '$date',\n\t\t\t\t\tusers: { $sum: 1 },\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t// Sort chronologically\n\t\t\t{ $sort: { _id: 1 } },\n\n\t\t\t// Shape response\n\t\t\t{\n\t\t\t\t$project: {\n\t\t\t\t\t_id: 0,\n\t\t\t\t\tdate: '$_id',\n\t\t\t\t\tusers: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tconst results = await this.orderModel.aggregate(pipeline).allowDiskUse(true).exec();\n\n\t\t// 4️⃣ Fill missing periods\n\t\treturn fillMissingPeriods(results, data.startDate, data.endDate, data.type, {\n\t\t\tusers: 0,\n\t\t});\n\t}\n\n\tpublic async getAmountSpentGraph(\n\t\tdata: MarketingGraphInputDTO\n\t): Promise<{ date: string; amount: number }[]> {\n\t\tconst marketing = await this.model.findById(data.marketingId).lean();\n\n\t\tif (!marketing) {\n\t\t\tnotFoundError('Marketing not found');\n\t\t}\n\n\t\tconst marketingId = new mongoose.Types.ObjectId(data.marketingId);\n\t\tconst dateFormat = data.type === GraphType.MONTHLY ? '%Y-%m' : '%Y-%m-%d';\n\n\t\tlet pipeline: mongoose.PipelineStage[] | null = null;\n\n\t\t/**\n\t\t * ITEM-BASED (DISCOUNT / BUY1GET1)\n\t\t */\n\t\tif ([MarketingType.DISCOUNT, MarketingType.BUY1GET1].includes(marketing.marketingType)) {\n\t\t\tpipeline = [\n\t\t\t\tthis.buildBaseMatch(marketingId, {\n\t\t\t\t\tstart: data.startDate,\n\t\t\t\t\tend: data.endDate,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\t$lookup: {\n\t\t\t\t\t\tfrom: 'lineItems',\n\t\t\t\t\t\tlocalField: 'cart',\n\t\t\t\t\t\tforeignField: 'cart',\n\t\t\t\t\t\tas: 'lineItems',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $unwind: '$lineItems' },\n\t\t\t\t{\n\t\t\t\t\t$match: {\n\t\t\t\t\t\t'lineItems.marketings': marketingId,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\tdate: {\n\t\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\t\tdate: '$processedAt',\n\t\t\t\t\t\t\t\ttimezone: LyxaTimezone,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tamount: {\n\t\t\t\t\t\t\t$add: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t\tmarketing.isAppliedByCompany,\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.itemDiscountByCompany', 0] },\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.itemDiscountByShop', 0] },\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\t{\n\t\t\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\t\t\tmarketing.isAppliedByCompany,\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.b1g1DiscountByCompany', 0] },\n\t\t\t\t\t\t\t\t\t\t{ $ifNull: ['$lineItems.calculationSnap.b1g1DiscountByShop', 0] },\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\t{\n\t\t\t\t\t$group: {\n\t\t\t\t\t\t_id: '$date',\n\t\t\t\t\t\tamount: { $sum: '$amount' },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $sort: { _id: 1 } },\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\t_id: 0,\n\t\t\t\t\t\tdate: '$_id',\n\t\t\t\t\t\tamount: 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t} else if (marketing.marketingType === MarketingType.FREE_DELIVERY) {\n\t\t\t/**\n\t\t\t * FREE DELIVERY\n\t\t\t */\n\t\t\tpipeline = [\n\t\t\t\tthis.buildBaseMatch(marketingId, {\n\t\t\t\t\tstart: data.startDate,\n\t\t\t\t\tend: data.endDate,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\tdate: {\n\t\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\t\tdate: '$processedAt',\n\t\t\t\t\t\t\t\ttimezone: LyxaTimezone,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tamount: {\n\t\t\t\t\t\t\t$cond: [\n\t\t\t\t\t\t\t\tmarketing.isAppliedByCompany,\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.freeDelivery.companyCut', 0] },\n\t\t\t\t\t\t\t\t{ $ifNull: ['$adjustedFinance.freeDelivery.shopCut', 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\t{\n\t\t\t\t\t$group: {\n\t\t\t\t\t\t_id: '$date',\n\t\t\t\t\t\tamount: { $sum: '$amount' },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $sort: { _id: 1 } },\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\t_id: 0,\n\t\t\t\t\t\tdate: '$_id',\n\t\t\t\t\t\tamount: 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t} else if (marketing.marketingType === MarketingType.PUNCH_MARKETING) {\n\t\t\t/**\n\t\t\t * PUNCH MARKETING\n\t\t\t */\n\t\t\tpipeline = [\n\t\t\t\tthis.buildBaseMatch(marketingId, {\n\t\t\t\t\tstart: data.startDate,\n\t\t\t\t\tend: data.endDate,\n\t\t\t\t}),\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\tdate: {\n\t\t\t\t\t\t\t$dateToString: {\n\t\t\t\t\t\t\t\tformat: dateFormat,\n\t\t\t\t\t\t\t\tdate: '$processedAt',\n\t\t\t\t\t\t\t\ttimezone: LyxaTimezone,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tamount: {\n\t\t\t\t\t\t\t$ifNull: ['$adjustedFinance.pricing.punchMarketingDiscount', 0],\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$group: {\n\t\t\t\t\t\t_id: '$date',\n\t\t\t\t\t\tamount: { $sum: '$amount' },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{ $sort: { _id: 1 } },\n\t\t\t\t{\n\t\t\t\t\t$project: {\n\t\t\t\t\t\t_id: 0,\n\t\t\t\t\t\tdate: '$_id',\n\t\t\t\t\t\tamount: 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// If marketing type doesn't produce spend graph → return empty graph\n\t\tif (!pipeline) {\n\t\t\treturn fillMissingPeriods(\n\t\t\t\t[] as { date: string; amount: number }[],\n\t\t\t\tdata.startDate,\n\t\t\t\tdata.endDate,\n\t\t\t\tdata.type,\n\t\t\t\t{\n\t\t\t\t\tamount: 0,\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tconst results = await this.orderModel.aggregate(pipeline).allowDiskUse(true).exec();\n\n\t\treturn fillMissingPeriods(results, data.startDate, data.endDate, data.type, {\n\t\t\tamount: 0,\n\t\t});\n\t}\n}\n\nexport const marketingMetricsRepository = Container.get(MarketingMetricsRepository);\n"]}
@@ -167,6 +167,8 @@ export declare const marketingRouter: import("@trpc/server").TRPCBuiltRouter<{
167
167
  percentageIncrease: number;
168
168
  } | undefined;
169
169
  totalRedemptions?: number | undefined;
170
+ totalValueGiven?: number | undefined;
171
+ remainingBudget?: number | undefined;
170
172
  } | undefined;
171
173
  };
172
174
  meta: object;
@@ -1 +1 @@
1
- {"version":3,"file":"marketing.router.d.ts","sourceRoot":"/","sources":["modules/marketing/routers/marketing.router.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAMxB,CAAD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyJD,CAAC"}
1
+ {"version":3,"file":"marketing.router.d.ts","sourceRoot":"/","sources":["modules/marketing/routers/marketing.router.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAMxB,CAAD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyJD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"marketing.service.d.ts","sourceRoot":"/","sources":["modules/marketing/services/marketing.service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAmB,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EAMjB,SAAS,IAAI,KAAK,EAOlB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAEN,0BAA0B,EAE1B,oCAAoC,EACpC,kBAAkB,IAAI,SAAS,EAC/B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACN,SAAS,EACT,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AA+C3D,qBACa,gBAAgB;IAC5B,OAAO,CAAC,KAAK,CAAiD;IAC9D,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,UAAU,CAA2D;IAC7E,OAAO,CAAC,0BAA0B,CAA6B;IAC/D,OAAO,CAAC,gCAAgC,CACM;;IAgBjC,MAAM,CAClB,IAAI,EAAE,0BAA0B,EAChC,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAC/B,OAAO,CAAC,EAAE;QAAE,yBAAyB,CAAC,EAAE,OAAO,CAAA;KAAE,GAC/C,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IA+JlB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAsB7D,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IA0B3F,MAAM,CAClB,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAC5B,IAAI,EAAE,SAAS,EACf,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAC7B,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAqIjB,uBAAuB;YA+BvB,uBAAuB;IAmBxB,UAAU,CACtB,IAAI,EAAE,SAAS,EACf,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAC/B,OAAO,CAAC,EAAE;QAAE,yBAAyB,CAAC,EAAE,OAAO,CAAA;KAAE,GAC/C,OAAO,CAAC,MAAM,CAAC;IAkDL,eAAe,CAAC,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,UAAU,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC1F,sCAAsC,CAAC,IAAI,EAAE,oCAAoC;IA8BjF,gCAAgC,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAiChF,gCAAgC,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;YAiC/E,oCAAoC;YAgBpC,kCAAkC;IAgBnC,iCAAiC,IAAI,OAAO,CAAC,IAAI,CAAC;YAqCjD,2BAA2B;IA2B5B,yBAAyB,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB9E,yBAAyB,CAAC,SAAS,EAAE,YAAY,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;CAqCrG;AAED,eAAO,MAAM,gBAAgB,kBAAkC,CAAC"}
1
+ {"version":3,"file":"marketing.service.d.ts","sourceRoot":"/","sources":["modules/marketing/services/marketing.service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAmB,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EAMjB,SAAS,IAAI,KAAK,EAOlB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAEN,0BAA0B,EAE1B,oCAAoC,EACpC,kBAAkB,IAAI,SAAS,EAC/B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACN,SAAS,EACT,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AA+C3D,qBACa,gBAAgB;IAC5B,OAAO,CAAC,KAAK,CAAiD;IAC9D,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,UAAU,CAA2D;IAC7E,OAAO,CAAC,0BAA0B,CAA6B;IAC/D,OAAO,CAAC,gCAAgC,CACM;;IAgBjC,MAAM,CAClB,IAAI,EAAE,0BAA0B,EAChC,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAC/B,OAAO,CAAC,EAAE;QAAE,yBAAyB,CAAC,EAAE,OAAO,CAAA;KAAE,GAC/C,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IA+JlB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAsB7D,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IA0B3F,MAAM,CAClB,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAC5B,IAAI,EAAE,SAAS,EACf,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAC7B,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAwIjB,uBAAuB;YAyCvB,uBAAuB;IAmBxB,UAAU,CACtB,IAAI,EAAE,SAAS,EACf,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAC/B,OAAO,CAAC,EAAE;QAAE,yBAAyB,CAAC,EAAE,OAAO,CAAA;KAAE,GAC/C,OAAO,CAAC,MAAM,CAAC;IAkDL,eAAe,CAAC,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,UAAU,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC1F,sCAAsC,CAAC,IAAI,EAAE,oCAAoC;IA8BjF,gCAAgC,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAiChF,gCAAgC,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;YAiC/E,oCAAoC;YAgBpC,kCAAkC;IAgBnC,iCAAiC,IAAI,OAAO,CAAC,IAAI,CAAC;YAqCjD,2BAA2B;IA2B5B,yBAAyB,CAAC,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB9E,yBAAyB,CAAC,SAAS,EAAE,YAAY,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;CAqCrG;AAED,eAAO,MAAM,gBAAgB,kBAAkC,CAAC"}
@@ -252,9 +252,10 @@ let MarketingService = class MarketingService {
252
252
  if (!oldMarketing) {
253
253
  (0, error_common_1.notFoundError)('Could not find marketing');
254
254
  }
255
- if (data.status && data.status === enum_1.MarketingStatus.ACTIVE && oldMarketing.status !== enum_1.MarketingStatus.ACTIVE) {
256
- if (oldMarketing.status === enum_1.MarketingStatus.PAUSED &&
257
- oldMarketing.marketingType === enum_2.MarketingType.DISCOUNT &&
255
+ if (data.status &&
256
+ data.status === enum_1.MarketingStatus.ACTIVE &&
257
+ oldMarketing.status === enum_1.MarketingStatus.PAUSED) {
258
+ if (oldMarketing.marketingType === enum_2.MarketingType.DISCOUNT &&
258
259
  (await limited_time_offer_participant_service_1.ltoParticipantService.isActiveParticipant(oldMarketing.shop._id))) {
259
260
  (0, error_common_1.forbiddenError)('You are currently participating in a Limited Time Offer. Please manage your discount from the Limited Time Offer section or withdraw first.');
260
261
  }
@@ -330,6 +331,15 @@ let MarketingService = class MarketingService {
330
331
  const marketing = await this.model.findOne({ _id: marketingId, deletedAt: null }).populate('products');
331
332
  if (!marketing)
332
333
  return;
334
+ const hasActiveLto = await this.model.exists({
335
+ shop: marketing.shop,
336
+ campaignType: enum_1.MarketingCampaignType.LIMITED_TIME_OFFER,
337
+ status: enum_1.MarketingStatus.ACTIVE,
338
+ deletedAt: null,
339
+ });
340
+ if (hasActiveLto) {
341
+ (0, error_common_1.conflictError)("Can't resume this discount while a limited time offer is active");
342
+ }
333
343
  if ([enum_2.MarketingType.BUY1GET1, enum_2.MarketingType.DISCOUNT].includes(marketing.marketingType)) {
334
344
  const typedMarketing = marketing;
335
345
  const productIds = typedMarketing.products.map((product) => product.product);
@@ -1 +1 @@
1
- {"version":3,"file":"marketing.service.js","sourceRoot":"/","sources":["modules/marketing/services/marketing.service.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { TRPCError } from '@trpc/server';\nimport { dayjs } from '@lyxa.ai/core/dist/utilities/dayjs';\nimport { getLibraries } from '@lyxa.ai/core';\nimport { DocumentType, mongoose, ReturnModelType } from '@typegoose/typegoose';\nimport {\n\tBuy1Get1Marketing,\n\tDiscountMarketing,\n\tLimitedTimeOfferParticipant,\n\tLimitedTimeOfferParticipantModel,\n\tLineItem,\n\tMarketing,\n\tMarketingModel,\n\tMarketing as Model,\n\tProductModel,\n\tProductMarketingModel,\n\tRegularOrder,\n\tRegularOrderModel,\n\tShop,\n\tShopModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {\n\tAllMarketingsDTO,\n\tAllMarketingsValidationDTO,\n\tCreateProductMarketingDTO,\n\tProductEntireMenuMarketingHandlerDTO,\n\tUpdateMarketingDTO as UpdateDTO,\n} from '@modules/marketing/validations';\nimport {\n\tFilterDTO,\n\tPaginatedResponse,\n\tDeleteDTO,\n\tGetByIdInputDTO,\n} from '@lyxa.ai/core/dist/utilities/validation';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { createRawDocumentPaginatorObject, PaginatorOptions } from '@lyxa.ai/core/dist/utilities/pagination';\nimport { ModelType } from '@typegoose/typegoose/lib/types';\nimport {\n\tfilterRelevantChanges,\n\tgetChangedFields,\n\tpublishSyncSingleShopSectionsInCacheProcessEvent,\n} from '@lyxa.ai/core/dist/utilities/events-common-methods';\nimport { AdminActivityLogsEvent } from '@lyxa.ai/core/dist/libraries/event/events/admin-logs-event';\nimport {\n\tAdminLogsUpdatedFieldsType, MarketingCampaignType,\n\tMarketingStatus,\n\tRegularOrderStatus,\n} from '@lyxa.ai/core/dist/utilities/enum';\nimport { publishEvent } from '@lyxa.ai/core/dist/libraries/event';\nimport { BaseEvent } from '@lyxa.ai/core/dist/libraries/event/BaseEvent';\nimport {\n\tMarketingEntireMenuSeedEvent,\n\tMarketingProductSeedPayload,\n} from '@events/events/marketing-product-seed.event';\nimport { MarketingProductSyncEvent } from '@events/events/marketing-product-sync.event';\nimport {\n\tbuy1Get1MarketingService,\n\tdiscountMarketingService,\n\tfeaturedMarketingService,\n\tfreeDeliveryMarketingService,\n\tproductMarketingService,\n\tpunchMarketingService,\n\tspendToGetMarketingService,\n\tsynchronizeProductMarketingService,\n\tmarketingConflictService,\n\tCONFLICT_CHECK_MARKETING_TYPES,\n} from '.';\nimport { MarketingType } from '@lyxa.ai/core/dist/utilities/enum';\nimport {\n\tconflictError,\n\tforbiddenError,\n\tinternalServerError,\n\tnotFoundError,\n\tunauthorizedError,\n} from '@lyxa.ai/core/dist/utilities/error-common';\nimport { ChangeStreamOperationTypes } from '@lyxa.ai/core/dist/libraries/event/events/mongo-stream-changes-batch-process-shops-event';\nimport {\n\tMarketingMetricsRepository,\n\tmarketingMetricsRepository,\n} from '../patterns/repository/MarketingMetricsRepository';\nimport { scheduleMarketingProductSync } from '../queues/marketing-product-sync.queue';\nimport { ltoParticipantService } from '@modules/limited-time-offer/participant/services/limited-time-offer-participant.service';\n\n@Service()\nexport class MarketingService {\n\tprivate model: typeof MarketingModel & SoftDeleteModel<Model>;\n\tprivate shopModel: typeof ShopModel & SoftDeleteModel<Shop>;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\tprivate marketingMetricsRepository: MarketingMetricsRepository;\n\tprivate limitedTimeOfferParticipantModel: typeof LimitedTimeOfferParticipantModel &\n\t\tSoftDeleteModel<LimitedTimeOfferParticipant>;\n\n\tconstructor() {\n\t\tthis.model = MarketingModel as typeof MarketingModel & SoftDeleteModel<Model>;\n\t\tthis.shopModel = ShopModel as typeof ShopModel & SoftDeleteModel<Shop>;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\t\tthis.marketingMetricsRepository = marketingMetricsRepository;\n\t\tthis.limitedTimeOfferParticipantModel =\n\t\t\tLimitedTimeOfferParticipantModel as typeof LimitedTimeOfferParticipantModel &\n\t\t\t\tSoftDeleteModel<LimitedTimeOfferParticipant>;\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(\n\t\tdata: AllMarketingsValidationDTO,\n\t\tadmin?: mongoose.Types.ObjectId,\n\t\toptions?: { skipLimitedTimeOfferGuard?: boolean }\n\t): Promise<DocumentType<Model>> {\n\t\tconst now = dayjs().toDate();\n\n\t\tif (\n\t\t\t!options?.skipLimitedTimeOfferGuard &&\n\t\t\tdata.marketingType === MarketingType.DISCOUNT &&\n\t\t\t(await ltoParticipantService.isActiveParticipant(data.shop))\n\t\t) {\n\t\t\tforbiddenError(\n\t\t\t\t'You are currently participating in a Limited Time Offer. Please manage your discount from the Limited Time Offer section or withdraw first.'\n\t\t\t);\n\t\t}\n\n\t\tconst existingRecord = await this.model.findOne({\n\t\t\tshop: data.shop,\n\t\t\tmarketingType: data.marketingType,\n\t\t\t'duration.end': { $gt: now },\n\t\t\tstatus: MarketingStatus.ACTIVE,\n\t\t\tisAppliedByCompany: data.isAppliedByCompany,\n\t\t\tcampaignType: data.campaignType,\n\t\t\tadmin: admin ? { $ne: null } : null,\n\t\t});\n\n\t\tif (existingRecord) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'CONFLICT',\n\t\t\t\tmessage: `This shop already has a ${data.marketingType} marketing`,\n\t\t\t});\n\t\t}\n\n\t\tif (CONFLICT_CHECK_MARKETING_TYPES.includes(data.marketingType)) {\n\t\t\tawait marketingConflictService.assertNoConflict({\n\t\t\t\tshop: data.shop,\n\t\t\t\tmarketingType: data.marketingType,\n\t\t\t\tduration: data.duration,\n\t\t\t\trewardTypeGroups: marketingConflictService.getRewardTypeGroups(data.marketingType, data.tiers),\n\t\t\t});\n\t\t}\n\n\t\tif (data.isEntireMenu) {\n\t\t\tconst existingMarketing = await this.model.findOne({\n\t\t\t\tshop: data.shop,\n\t\t\t\t'duration.start': { $lt: now },\n\t\t\t\t'duration.end': { $gt: now },\n\t\t\t\tstatus: MarketingStatus.ACTIVE,\n\t\t\t\tmarketingType: { $in: [MarketingType.BUY1GET1, MarketingType.DISCOUNT], $ne: data.marketingType },\n\t\t\t});\n\n\t\t\tif (existingMarketing) {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: 'CONFLICT',\n\t\t\t\t\tmessage: `Cannot create marketing for entire menu while another product based marketing exists for the shop`,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (data.products && data.products.length > 0) {\n\t\t\tconst productIds = data.products.map((product: CreateProductMarketingDTO) => product.product);\n\n\t\t\tconst hasDuplicates = new Set(productIds.map(String)).size !== productIds.length;\n\n\t\t\tif (hasDuplicates) {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: 'BAD_REQUEST',\n\t\t\t\t\tmessage: `Product list contains duplicate products`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (data.campaignType === MarketingCampaignType.LIMITED_TIME_OFFER) {\n\t\t\t\tawait productMarketingService.pauseConflictingMarketings(productIds);\n\t\t\t} else {\n\t\t\t\tconst isAvailable = await productMarketingService.checkProductMarketingAvailability(\n\t\t\t\t\tproductIds,\n\t\t\t\t\tdata.isAppliedByCompany\n\t\t\t\t);\n\n\t\t\t\tif (!isAvailable) {\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: 'CONFLICT',\n\t\t\t\t\t\tmessage: `Product list contains products which already have marketing applied`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (admin) {\n\t\t\tdata.admin = admin;\n\t\t}\n\n\t\tlet marketing: AllMarketingsDTO;\n\n\t\tswitch (data.marketingType) {\n\t\t\tcase MarketingType.DISCOUNT: {\n\t\t\t\tmarketing = await discountMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.BUY1GET1: {\n\t\t\t\tmarketing = await buy1Get1MarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.FEATURED: {\n\t\t\t\tif (!admin) {\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: 'UNAUTHORIZED',\n\t\t\t\t\t\tmessage: `Only admin is allowed to create ${data.marketingType} marketing`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tmarketing = await featuredMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.FREE_DELIVERY: {\n\t\t\t\tmarketing = await freeDeliveryMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.PUNCH_MARKETING: {\n\t\t\t\tmarketing = await punchMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.SPEND_TO_GET: {\n\t\t\t\tmarketing = await spendToGetMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tmarketing = await this.model.create(data, admin);\n\t\t\t}\n\t\t}\n\n\t\tawait this.assignMarketingToProducts(marketing);\n\n\t\tawait this.model.populate(marketing, {\n\t\t\tpath: 'shop',\n\t\t\tmodel: this.shopModel,\n\t\t\tselect: '_id name shopId',\n\t\t});\n\n\t\tif (admin) {\n\t\t\tthis.logMarketingAdminAction(\n\t\t\t\tadmin,\n\t\t\t\tAdminLogsUpdatedFieldsType.ACTIVATED_MARKETING_PROMOTIONS,\n\t\t\t\t'',\n\t\t\t\tmarketing\n\t\t\t);\n\t\t}\n\t\tif (marketing && !data.isEntireMenu)\n\t\t\tpublishSyncSingleShopSectionsInCacheProcessEvent({\n\t\t\t\tshopId: data.shop,\n\t\t\t\toperation: ChangeStreamOperationTypes.UPDATE,\n\t\t\t});\n\t\treturn marketing;\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(data: GetByIdInputDTO): Promise<DocumentType<Model>> {\n\t\tconst select = data.select || '';\n\t\tconst populate = data.populate || [];\n\t\tconst result = await this.model\n\t\t\t.findOne({\n\t\t\t\t_id: data._id,\n\t\t\t})\n\t\t\t.select(select)\n\t\t\t.populate(populate);\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 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,\n\t\t\t\tselect: data?.select,\n\t\t\t\tpopulate: data?.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 record\n\t * @param data Data to update\n\t */\n\tpublic async update(\n\t\t_id: mongoose.Types.ObjectId,\n\t\tdata: UpdateDTO,\n\t\tadmin?: mongoose.Types.ObjectId\n\t): Promise<DocumentType<Model>> {\n\t\tlet marketing: AllMarketingsDTO;\n\n\t\tconst partOfLimitedTimeOffer = await this.limitedTimeOfferParticipantModel.exists({\n\t\t\tmarketing: _id,\n\t\t});\n\n\t\tif (partOfLimitedTimeOffer) {\n\t\t\tforbiddenError(\n\t\t\t\t'You are currently participating in a Limited Time Offer. Please make your edits from the Limited Time Offer section.'\n\t\t\t);\n\t\t}\n\n\t\tconst oldMarketing = await this.model.findById(_id).populate({\n\t\t\tpath: 'shop',\n\t\t\tselect: '_id name shopId',\n\t\t});\n\n\t\tif (!oldMarketing) {\n\t\t\tnotFoundError('Could not find marketing');\n\t\t}\n\n\t\tif (data.status && data.status === MarketingStatus.ACTIVE && oldMarketing.status !== MarketingStatus.ACTIVE) {\n\t\t\tif (\n\t\t\t\toldMarketing.status === MarketingStatus.PAUSED &&\n\t\t\t\toldMarketing.marketingType === MarketingType.DISCOUNT &&\n\t\t\t\t(await ltoParticipantService.isActiveParticipant(oldMarketing.shop._id))\n\t\t\t) {\n\t\t\t\tforbiddenError(\n\t\t\t\t\t'You are currently participating in a Limited Time Offer. Please manage your discount from the Limited Time Offer section or withdraw first.'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tawait this.verifyUnpauseConditions(_id);\n\t\t}\n\n\t\tswitch (oldMarketing.marketingType) {\n\t\t\tcase MarketingType.DISCOUNT: {\n\t\t\t\tmarketing = await discountMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.BUY1GET1: {\n\t\t\t\tmarketing = await buy1Get1MarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.FEATURED: {\n\t\t\t\tif (!admin) {\n\t\t\t\t\tunauthorizedError(`Only admin is allowed to update ${data.marketingType} marketing`);\n\t\t\t\t}\n\t\t\t\tmarketing = await featuredMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.FREE_DELIVERY: {\n\t\t\t\tmarketing = await freeDeliveryMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.PUNCH_MARKETING: {\n\t\t\t\tmarketing = await punchMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.SPEND_TO_GET: {\n\t\t\t\tmarketing = await spendToGetMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tmarketing = await this.model\n\t\t\t\t\t.findOneAndUpdate(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_id: _id,\n\t\t\t\t\t\t\tdeletedAt: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnew: true,\n\t\t\t\t\t\t\trunValidators: true,\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.populate({\n\t\t\t\t\t\tpath: 'shop',\n\t\t\t\t\t\tselect: '_id name shopId',\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (!marketing) {\n\t\t\tinternalServerError('Could not update marketing');\n\t\t}\n\n\t\tif (admin) {\n\t\t\tconst allChanges = getChangedFields(oldMarketing, marketing);\n\t\t\tconst relevantChanges = filterRelevantChanges(allChanges, data);\n\n\t\t\tif (Object.keys(relevantChanges).includes('status')) {\n\t\t\t\tif (data.status == MarketingStatus.ACTIVE) {\n\t\t\t\t\tthis.logMarketingAdminAction(\n\t\t\t\t\t\tadmin,\n\t\t\t\t\t\tAdminLogsUpdatedFieldsType.CONTINUED_MARKETING_PROMOTIONS,\n\t\t\t\t\t\toldMarketing,\n\t\t\t\t\t\tmarketing\n\t\t\t\t\t);\n\t\t\t\t} else if (data.status == MarketingStatus.PAUSED) {\n\t\t\t\t\tthis.logMarketingAdminAction(\n\t\t\t\t\t\tadmin,\n\t\t\t\t\t\tAdminLogsUpdatedFieldsType.PAUSED_MARKETING_PROMOTIONS,\n\t\t\t\t\t\toldMarketing,\n\t\t\t\t\t\tmarketing\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.logMarketingAdminAction(\n\t\t\t\tadmin,\n\t\t\t\tAdminLogsUpdatedFieldsType.EDITED_MARKETING_PROMOTIONS,\n\t\t\t\toldMarketing,\n\t\t\t\tmarketing\n\t\t\t);\n\t\t}\n\n\t\tawait this.assignMarketingToProducts(marketing);\n\n\t\tpublishSyncSingleShopSectionsInCacheProcessEvent({\n\t\t\tshopId: marketing.shop,\n\t\t\toperation: ChangeStreamOperationTypes.UPDATE,\n\t\t});\n\n\t\treturn marketing;\n\t}\n\n\tprivate async verifyUnpauseConditions(marketingId: mongoose.Types.ObjectId): Promise<void> {\n\t\tconst marketing = await this.model.findOne({ _id: marketingId, deletedAt: null }).populate('products');\n\t\tif (!marketing) return;\n\n\t\tif ([MarketingType.BUY1GET1, MarketingType.DISCOUNT].includes(marketing.marketingType)) {\n\t\t\tconst typedMarketing = marketing as DocumentType<DiscountMarketing | Buy1Get1Marketing>;\n\t\t\tconst productIds = typedMarketing.products.map((product: any) => product.product);\n\t\t\tconst isAvailable = await productMarketingService.checkProductMarketingAvailability(\n\t\t\t\tproductIds,\n\t\t\t\tmarketing.isAppliedByCompany\n\t\t\t);\n\n\t\t\tif (!isAvailable) {\n\t\t\t\tconflictError(\"You can't activate discount and B1G1 on the same items at the same time\");\n\t\t\t}\n\t\t}\n\n\t\tif (CONFLICT_CHECK_MARKETING_TYPES.includes(marketing.marketingType)) {\n\t\t\tawait marketingConflictService.assertNoConflict({\n\t\t\t\tshop: marketing.shop as mongoose.Types.ObjectId,\n\t\t\t\tmarketingType: marketing.marketingType,\n\t\t\t\tduration: marketing.duration,\n\t\t\t\trewardTypeGroups: marketingConflictService.getRewardTypeGroups(\n\t\t\t\t\tmarketing.marketingType,\n\t\t\t\t\t(marketing as any).tiers\n\t\t\t\t),\n\t\t\t\texcludeMarketingId: marketingId,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async logMarketingAdminAction(\n\t\tadmin: mongoose.Types.ObjectId,\n\t\tactionType: AdminLogsUpdatedFieldsType,\n\t\toldDocument?: any,\n\t\tnewDocument?: any\n\t) {\n\t\tconst adminActivityLogsEvent: BaseEvent<Record<string, unknown>> = new AdminActivityLogsEvent({\n\t\t\tadmin,\n\t\t\tupdatedField: actionType,\n\t\t\toldDocument: oldDocument ?? '',\n\t\t\tnewDocument: newDocument ?? '',\n\t\t});\n\t\tawait publishEvent(adminActivityLogsEvent);\n\t}\n\n\t/**\n\t * Delete record\n\t * @param data Data for delete\n\t */\n\tpublic async deleteById(\n\t\tdata: DeleteDTO,\n\t\tadmin?: mongoose.Types.ObjectId,\n\t\toptions?: { skipLimitedTimeOfferGuard?: boolean }\n\t): Promise<string> {\n\t\tconst { _id, softDelete } = data;\n\n\t\tif (!options?.skipLimitedTimeOfferGuard) {\n\t\t\tconst partOfLimitedTimeOffer = await this.limitedTimeOfferParticipantModel.exists({\n\t\t\t\tmarketing: _id,\n\t\t\t});\n\n\t\t\tif (partOfLimitedTimeOffer) {\n\t\t\t\tforbiddenError(\n\t\t\t\t\t'You are currently participating in a Limited Time Offer. Please make your edits from the Limited Time Offer section.'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst record = await this.model.findById(_id).populate({\n\t\t\tpath: 'shop',\n\t\t\tselect: '_id name shopId',\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\trecord.status = MarketingStatus.DELETED;\n\t\tawait record.save();\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: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Unable to delete marketing',\n\t\t\t});\n\t\t}\n\n\t\tif (admin) {\n\t\t\tthis.logMarketingAdminAction(admin, AdminLogsUpdatedFieldsType.DELETED_MARKETING_PROMOTIONS, record);\n\t\t}\n\n\t\tproductMarketingService.deleteMany({ marketing: data._id }, data.softDelete);\n\t\tpublishSyncSingleShopSectionsInCacheProcessEvent({\n\t\t\tshopId: record.shop._id,\n\t\t\toperation: ChangeStreamOperationTypes.DELETE,\n\t\t});\n\t\treturn 'Record deleted successfully';\n\t}\n\n\tpublic async deleteManyByIds(marketingIds: mongoose.Types.ObjectId[], softDelete = true): Promise<void> {\n\t\tif (marketingIds.length === 0) return;\n\n\t\tconst marketings = await this.model\n\t\t\t.find({ _id: { $in: marketingIds } })\n\t\t\t.select('shop')\n\t\t\t.lean();\n\n\t\tawait this.model.updateMany(\n\t\t\t{ _id: { $in: marketingIds } },\n\t\t\t{ $set: { status: MarketingStatus.DELETED } }\n\t\t);\n\t\tawait this.model.deleteRecords({ _id: { $in: marketingIds } }, softDelete);\n\n\t\tawait productMarketingService.deleteManyByMarketingIds(marketingIds, softDelete);\n\n\t\tconst uniqueShopIds = [\n\t\t\t...new Map(\n\t\t\t\tmarketings\n\t\t\t\t\t.map((m: any) => m.shop)\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.map((s: any) => {\n\t\t\t\t\t\tconst id = s instanceof mongoose.Types.ObjectId ? s : new mongoose.Types.ObjectId(s);\n\t\t\t\t\t\treturn [id.toString(), id] as [string, mongoose.Types.ObjectId];\n\t\t\t\t\t})\n\t\t\t).values(),\n\t\t];\n\n\t\tfor (const shopId of uniqueShopIds) {\n\t\t\tpublishSyncSingleShopSectionsInCacheProcessEvent({\n\t\t\t\tshopId,\n\t\t\t\toperation: ChangeStreamOperationTypes.DELETE,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic async handleNewProductForEntireMenuMarketing(data: ProductEntireMenuMarketingHandlerDTO) {\n\t\tconst existingMarketing = await this.model.findOne({\n\t\t\tshop: data.shop,\n\t\t\tmarketingType: { $in: [MarketingType.BUY1GET1, MarketingType.DISCOUNT] },\n\t\t\t'duration.end': { $gt: new Date() },\n\t\t\tstatus: MarketingStatus.ACTIVE,\n\t\t\tisEntireMenu: true,\n\t\t});\n\n\t\t// check if existing marketing\n\t\tif (existingMarketing) {\n\t\t\tconst productMarketingData: CreateProductMarketingDTO = {\n\t\t\t\tproduct: data.product,\n\t\t\t\tmarketing: existingMarketing._id,\n\t\t\t};\n\t\t\tif (existingMarketing.marketingType == MarketingType.BUY1GET1) {\n\t\t\t\tproductMarketingData.isBuy1Get1 = true;\n\t\t\t}\n\t\t\tif (existingMarketing.marketingType == MarketingType.DISCOUNT) {\n\t\t\t\tproductMarketingData.value = (existingMarketing as DocumentType<DiscountMarketing>).value;\n\t\t\t\tproductMarketingData.valueType = (existingMarketing as DocumentType<DiscountMarketing>).valueType;\n\t\t\t}\n\n\t\t\tawait productMarketingService.create(productMarketingData);\n\t\t\tawait synchronizeProductMarketingService.syncProductMarketingInfoByProductId(data.product);\n\t\t}\n\n\t\treturn 'Product handled successfully';\n\t}\n\n\tpublic async incrementMarketingSpentFromOrder(orderId: mongoose.Types.ObjectId): Promise<any> {\n\t\tconst order = (await this.orderModel\n\t\t\t.findById(orderId)\n\t\t\t.populate([\n\t\t\t\t{ path: 'lineItems' },\n\t\t\t\t{ path: 'marketings', select: 'isAppliedByCompany' },\n\t\t\t])) as DocumentType<RegularOrder> & {\n\t\t\tlineItems: DocumentType<LineItem>[];\n\t\t\tmarketings: DocumentType<Marketing>[];\n\t\t};\n\n\t\tif (!order || !order.marketings?.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst marketingSpendMap = this.marketingMetricsRepository.calculateMarketingSpendPerOrder(order);\n\n\t\tconst bulkOps = [...marketingSpendMap.entries()].map(([marketingId, amountSpent]) => ({\n\t\t\tupdateOne: {\n\t\t\t\tfilter: { _id: marketingId },\n\t\t\t\tupdate: { $inc: { amountSpent } },\n\t\t\t},\n\t\t}));\n\n\t\tif (bulkOps.length) {\n\t\t\tawait this.model.bulkWrite(bulkOps);\n\t\t}\n\n\t\tawait this.expireMarketingsExceedingSpendLimits(Array.from(marketingSpendMap.keys()));\n\n\t\treturn 'Marketing amount spent incremented successfully';\n\t}\n\n\tpublic async decrementMarketingSpentFromOrder(orderId: mongoose.Types.ObjectId): Promise<any> {\n\t\tconst order = (await this.orderModel\n\t\t\t.findById(orderId)\n\t\t\t.populate([\n\t\t\t\t{ path: 'lineItems' },\n\t\t\t\t{ path: 'marketings', select: 'isAppliedByCompany' },\n\t\t\t])) as DocumentType<RegularOrder> & {\n\t\t\tlineItems: DocumentType<LineItem>[];\n\t\t\tmarketings: DocumentType<Marketing>[];\n\t\t};\n\n\t\tif (!order || !order.marketings?.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst marketingSpendMap = this.marketingMetricsRepository.calculateMarketingSpendPerOrder(order);\n\n\t\tconst bulkOps = [...marketingSpendMap.entries()].map(([marketingId, amountSpent]) => ({\n\t\t\tupdateOne: {\n\t\t\t\tfilter: { _id: marketingId },\n\t\t\t\tupdate: { $inc: { amountSpent: -amountSpent } },\n\t\t\t},\n\t\t}));\n\n\t\tif (bulkOps.length) {\n\t\t\tawait this.model.bulkWrite(bulkOps);\n\t\t}\n\n\t\tawait this.unExpireMarketingsBelowSpendLimits(Array.from(marketingSpendMap.keys()));\n\n\t\treturn 'Marketing amount spent decremented successfully';\n\t}\n\n\tprivate async expireMarketingsExceedingSpendLimits(marketingIds: mongoose.Types.ObjectId[]) {\n\t\tconst update = await this.model.updateMany(\n\t\t\t{\n\t\t\t\t_id: { $in: marketingIds },\n\t\t\t\tisSpendLimitEnabled: true,\n\t\t\t\tstatus: { $ne: MarketingStatus.EXPIRED },\n\t\t\t\t$expr: { $gte: ['$amountSpent', '$spendLimit'] },\n\t\t\t},\n\t\t\t{ $set: { status: MarketingStatus.EXPIRED, expiredAt: dayjs().toDate() } }\n\t\t);\n\n\t\tif (update.modifiedCount > 0) {\n\t\t\tawait synchronizeProductMarketingService.syncProductMarketingInfoByMarketingIds(marketingIds);\n\t\t}\n\t}\n\n\tprivate async unExpireMarketingsBelowSpendLimits(marketingIds: mongoose.Types.ObjectId[]) {\n\t\tconst update = await this.model.updateMany(\n\t\t\t{\n\t\t\t\t_id: { $in: marketingIds },\n\t\t\t\tisSpendLimitEnabled: true,\n\t\t\t\tstatus: MarketingStatus.EXPIRED,\n\t\t\t\t$expr: { $lt: ['$amountSpent', '$spendLimit'] },\n\t\t\t},\n\t\t\t{ $set: { status: MarketingStatus.ACTIVE }, $unset: { expiredAt: 1 } }\n\t\t);\n\n\t\tif (update.modifiedCount > 0) {\n\t\t\tawait synchronizeProductMarketingService.syncProductMarketingInfoByMarketingIds(marketingIds);\n\t\t}\n\t}\n\n\tpublic async recomputeAndSyncAllMarketingSpent(): Promise<void> {\n\t\tconst cursor = this.model\n\t\t\t.find({ marketingType: { $ne: MarketingType.FEATURED } }, { _id: 1 })\n\t\t\t.lean()\n\t\t\t.cursor();\n\n\t\tconst bulkOps: mongoose.AnyBulkWriteOperation[] = [];\n\t\tconst marketingIds: mongoose.Types.ObjectId[] = [];\n\n\t\tfor await (const marketing of cursor) {\n\t\t\tconst { amount } = await this.marketingMetricsRepository.calculateMarketingSpent(marketing._id);\n\n\t\t\tbulkOps.push({\n\t\t\t\tupdateOne: {\n\t\t\t\t\tfilter: { _id: marketing._id },\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\t$set: { amountSpent: amount },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tmarketingIds.push(marketing._id);\n\n\t\t\tif (bulkOps.length >= 500) {\n\t\t\t\tawait this.model.bulkWrite(bulkOps);\n\t\t\t\tbulkOps.length = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (bulkOps.length) {\n\t\t\tawait this.model.bulkWrite(bulkOps);\n\t\t}\n\n\t\tawait this.expireMarketingsExceedingSpendLimits(marketingIds);\n\t\tawait this.unExpireMarketingsBelowSpendLimits(marketingIds);\n\t}\n\n\tprivate async publishEntireMenuSeedEvents(\n\t\tmarketing: DocumentType<Buy1Get1Marketing | DiscountMarketing>\n\t): Promise<number> {\n\t\tconst PAGE_SIZE = 500;\n\t\tconst marketingId = marketing._id.toString();\n\t\tconst shopId = ((marketing.shop as any)?._id ?? marketing.shop).toString();\n\n\t\tconst products = await ProductModel.find({ shop: marketing.shop }).select('_id').lean();\n\t\tconst productIds = products.map((p: any) => p._id.toString());\n\n\t\tfor (let i = 0; i < productIds.length; i += PAGE_SIZE) {\n\t\t\tawait publishEvent(\n\t\t\t\tnew MarketingEntireMenuSeedEvent({\n\t\t\t\t\tmarketingId,\n\t\t\t\t\tshopId,\n\t\t\t\t\tisAppliedByCompany: marketing.isAppliedByCompany ?? false,\n\t\t\t\t\tisBuy1Get1: marketing.marketingType === MarketingType.BUY1GET1,\n\t\t\t\t\tvalue: (marketing as any).value,\n\t\t\t\t\tvalueType: (marketing as any).valueType,\n\t\t\t\t\tproductIds: productIds.slice(i, i + PAGE_SIZE),\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\treturn productIds.length;\n\t}\n\n\tpublic async reseedEntireMenuMarketing(marketingId: mongoose.Types.ObjectId): Promise<void> {\n\t\tconst logger = getLibraries().getLoggerKit();\n\n\t\tconst marketing = await this.model.findOne({ _id: marketingId, deletedAt: null });\n\t\tif (!marketing) internalServerError('Marketing not found');\n\n\t\tconst productCount = await this.publishEntireMenuSeedEvents(\n\t\t\tmarketing as DocumentType<Buy1Get1Marketing | DiscountMarketing>\n\t\t);\n\n\t\tlogger.debug(`entire-menu reseed dispatched — ${productCount} products`, {\n\t\t\ttag: 'marketing.seed.entire-menu',\n\t\t\tdata: { marketingId: marketingId.toString(), productCount },\n\t\t});\n\t}\n\n\tpublic async assignMarketingToProducts(marketing: DocumentType<Buy1Get1Marketing | DiscountMarketing>) {\n\t\tconst diffStartTime = dayjs(marketing.duration.start).diff(dayjs(), 'milliseconds');\n\t\tif (diffStartTime > 0) {\n\t\t\treturn await scheduleMarketingProductSync(marketing._id.toString(), diffStartTime);\n\t\t}\n\n\t\tif (marketing.isEntireMenu) {\n\t\t\tconst logger = getLibraries().getLoggerKit();\n\n\t\t\tconst productCount = await this.publishEntireMenuSeedEvents(marketing);\n\n\t\t\tlogger.debug(`entire-menu marketing seed dispatched — ${productCount} products`, {\n\t\t\t\ttag: 'marketing.seed.entire-menu',\n\t\t\t\tdata: { marketingId: marketing._id.toString(), productCount },\n\t\t\t});\n\t\t} else {\n\t\t\t// Non-entire-menu: the productMarketings were already created synchronously. The product-doc\n\t\t\t// sync is linear in product count (thousands → seconds), so page it into background events\n\t\t\t// instead of blocking the request — same pattern as the entire-menu branch above.\n\t\t\tconst shopId = ((marketing.shop as any)?._id ?? marketing.shop).toString();\n\t\t\tconst pms = await ProductMarketingModel.find({ marketing: marketing._id, deletedAt: null })\n\t\t\t\t.select('product')\n\t\t\t\t.lean();\n\t\t\tconst productIds = pms.map((p: any) => p.product.toString());\n\n\t\t\tconst PAGE_SIZE = 500;\n\t\t\tfor (let i = 0; i < productIds.length; i += PAGE_SIZE) {\n\t\t\t\tawait publishEvent(\n\t\t\t\t\tnew MarketingProductSyncEvent({\n\t\t\t\t\t\tmarketingId: marketing._id.toString(),\n\t\t\t\t\t\tshopId,\n\t\t\t\t\t\tproductIds: productIds.slice(i, i + PAGE_SIZE),\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport const marketingService = Container.get(MarketingService);\n"]}
1
+ {"version":3,"file":"marketing.service.js","sourceRoot":"/","sources":["modules/marketing/services/marketing.service.ts"],"names":[],"mappings":"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","sourcesContent":["import Container, { Service } from 'typedi';\nimport { TRPCError } from '@trpc/server';\nimport { dayjs } from '@lyxa.ai/core/dist/utilities/dayjs';\nimport { getLibraries } from '@lyxa.ai/core';\nimport { DocumentType, mongoose, ReturnModelType } from '@typegoose/typegoose';\nimport {\n\tBuy1Get1Marketing,\n\tDiscountMarketing,\n\tLimitedTimeOfferParticipant,\n\tLimitedTimeOfferParticipantModel,\n\tLineItem,\n\tMarketing,\n\tMarketingModel,\n\tMarketing as Model,\n\tProductModel,\n\tProductMarketingModel,\n\tRegularOrder,\n\tRegularOrderModel,\n\tShop,\n\tShopModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {\n\tAllMarketingsDTO,\n\tAllMarketingsValidationDTO,\n\tCreateProductMarketingDTO,\n\tProductEntireMenuMarketingHandlerDTO,\n\tUpdateMarketingDTO as UpdateDTO,\n} from '@modules/marketing/validations';\nimport {\n\tFilterDTO,\n\tPaginatedResponse,\n\tDeleteDTO,\n\tGetByIdInputDTO,\n} from '@lyxa.ai/core/dist/utilities/validation';\nimport { SoftDeleteModel } from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport { createRawDocumentPaginatorObject, PaginatorOptions } from '@lyxa.ai/core/dist/utilities/pagination';\nimport { ModelType } from '@typegoose/typegoose/lib/types';\nimport {\n\tfilterRelevantChanges,\n\tgetChangedFields,\n\tpublishSyncSingleShopSectionsInCacheProcessEvent,\n} from '@lyxa.ai/core/dist/utilities/events-common-methods';\nimport { AdminActivityLogsEvent } from '@lyxa.ai/core/dist/libraries/event/events/admin-logs-event';\nimport {\n\tAdminLogsUpdatedFieldsType, MarketingCampaignType,\n\tMarketingStatus,\n\tRegularOrderStatus,\n} from '@lyxa.ai/core/dist/utilities/enum';\nimport { publishEvent } from '@lyxa.ai/core/dist/libraries/event';\nimport { BaseEvent } from '@lyxa.ai/core/dist/libraries/event/BaseEvent';\nimport {\n\tMarketingEntireMenuSeedEvent,\n\tMarketingProductSeedPayload,\n} from '@events/events/marketing-product-seed.event';\nimport { MarketingProductSyncEvent } from '@events/events/marketing-product-sync.event';\nimport {\n\tbuy1Get1MarketingService,\n\tdiscountMarketingService,\n\tfeaturedMarketingService,\n\tfreeDeliveryMarketingService,\n\tproductMarketingService,\n\tpunchMarketingService,\n\tspendToGetMarketingService,\n\tsynchronizeProductMarketingService,\n\tmarketingConflictService,\n\tCONFLICT_CHECK_MARKETING_TYPES,\n} from '.';\nimport { MarketingType } from '@lyxa.ai/core/dist/utilities/enum';\nimport {\n\tconflictError,\n\tforbiddenError,\n\tinternalServerError,\n\tnotFoundError,\n\tunauthorizedError,\n} from '@lyxa.ai/core/dist/utilities/error-common';\nimport { ChangeStreamOperationTypes } from '@lyxa.ai/core/dist/libraries/event/events/mongo-stream-changes-batch-process-shops-event';\nimport {\n\tMarketingMetricsRepository,\n\tmarketingMetricsRepository,\n} from '../patterns/repository/MarketingMetricsRepository';\nimport { scheduleMarketingProductSync } from '../queues/marketing-product-sync.queue';\nimport { ltoParticipantService } from '@modules/limited-time-offer/participant/services/limited-time-offer-participant.service';\n\n@Service()\nexport class MarketingService {\n\tprivate model: typeof MarketingModel & SoftDeleteModel<Model>;\n\tprivate shopModel: typeof ShopModel & SoftDeleteModel<Shop>;\n\tprivate orderModel: typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\tprivate marketingMetricsRepository: MarketingMetricsRepository;\n\tprivate limitedTimeOfferParticipantModel: typeof LimitedTimeOfferParticipantModel &\n\t\tSoftDeleteModel<LimitedTimeOfferParticipant>;\n\n\tconstructor() {\n\t\tthis.model = MarketingModel as typeof MarketingModel & SoftDeleteModel<Model>;\n\t\tthis.shopModel = ShopModel as typeof ShopModel & SoftDeleteModel<Shop>;\n\t\tthis.orderModel = RegularOrderModel as typeof RegularOrderModel & SoftDeleteModel<RegularOrder>;\n\t\tthis.marketingMetricsRepository = marketingMetricsRepository;\n\t\tthis.limitedTimeOfferParticipantModel =\n\t\t\tLimitedTimeOfferParticipantModel as typeof LimitedTimeOfferParticipantModel &\n\t\t\t\tSoftDeleteModel<LimitedTimeOfferParticipant>;\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(\n\t\tdata: AllMarketingsValidationDTO,\n\t\tadmin?: mongoose.Types.ObjectId,\n\t\toptions?: { skipLimitedTimeOfferGuard?: boolean }\n\t): Promise<DocumentType<Model>> {\n\t\tconst now = dayjs().toDate();\n\n\t\tif (\n\t\t\t!options?.skipLimitedTimeOfferGuard &&\n\t\t\tdata.marketingType === MarketingType.DISCOUNT &&\n\t\t\t(await ltoParticipantService.isActiveParticipant(data.shop))\n\t\t) {\n\t\t\tforbiddenError(\n\t\t\t\t'You are currently participating in a Limited Time Offer. Please manage your discount from the Limited Time Offer section or withdraw first.'\n\t\t\t);\n\t\t}\n\n\t\tconst existingRecord = await this.model.findOne({\n\t\t\tshop: data.shop,\n\t\t\tmarketingType: data.marketingType,\n\t\t\t'duration.end': { $gt: now },\n\t\t\tstatus: MarketingStatus.ACTIVE,\n\t\t\tisAppliedByCompany: data.isAppliedByCompany,\n\t\t\tcampaignType: data.campaignType,\n\t\t\tadmin: admin ? { $ne: null } : null,\n\t\t});\n\n\t\tif (existingRecord) {\n\t\t\tthrow new TRPCError({\n\t\t\t\tcode: 'CONFLICT',\n\t\t\t\tmessage: `This shop already has a ${data.marketingType} marketing`,\n\t\t\t});\n\t\t}\n\n\t\tif (CONFLICT_CHECK_MARKETING_TYPES.includes(data.marketingType)) {\n\t\t\tawait marketingConflictService.assertNoConflict({\n\t\t\t\tshop: data.shop,\n\t\t\t\tmarketingType: data.marketingType,\n\t\t\t\tduration: data.duration,\n\t\t\t\trewardTypeGroups: marketingConflictService.getRewardTypeGroups(data.marketingType, data.tiers),\n\t\t\t});\n\t\t}\n\n\t\tif (data.isEntireMenu) {\n\t\t\tconst existingMarketing = await this.model.findOne({\n\t\t\t\tshop: data.shop,\n\t\t\t\t'duration.start': { $lt: now },\n\t\t\t\t'duration.end': { $gt: now },\n\t\t\t\tstatus: MarketingStatus.ACTIVE,\n\t\t\t\tmarketingType: { $in: [MarketingType.BUY1GET1, MarketingType.DISCOUNT], $ne: data.marketingType },\n\t\t\t});\n\n\t\t\tif (existingMarketing) {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: 'CONFLICT',\n\t\t\t\t\tmessage: `Cannot create marketing for entire menu while another product based marketing exists for the shop`,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (data.products && data.products.length > 0) {\n\t\t\tconst productIds = data.products.map((product: CreateProductMarketingDTO) => product.product);\n\n\t\t\tconst hasDuplicates = new Set(productIds.map(String)).size !== productIds.length;\n\n\t\t\tif (hasDuplicates) {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: 'BAD_REQUEST',\n\t\t\t\t\tmessage: `Product list contains duplicate products`,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (data.campaignType === MarketingCampaignType.LIMITED_TIME_OFFER) {\n\t\t\t\tawait productMarketingService.pauseConflictingMarketings(productIds);\n\t\t\t} else {\n\t\t\t\tconst isAvailable = await productMarketingService.checkProductMarketingAvailability(\n\t\t\t\t\tproductIds,\n\t\t\t\t\tdata.isAppliedByCompany\n\t\t\t\t);\n\n\t\t\t\tif (!isAvailable) {\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: 'CONFLICT',\n\t\t\t\t\t\tmessage: `Product list contains products which already have marketing applied`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (admin) {\n\t\t\tdata.admin = admin;\n\t\t}\n\n\t\tlet marketing: AllMarketingsDTO;\n\n\t\tswitch (data.marketingType) {\n\t\t\tcase MarketingType.DISCOUNT: {\n\t\t\t\tmarketing = await discountMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.BUY1GET1: {\n\t\t\t\tmarketing = await buy1Get1MarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.FEATURED: {\n\t\t\t\tif (!admin) {\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: 'UNAUTHORIZED',\n\t\t\t\t\t\tmessage: `Only admin is allowed to create ${data.marketingType} marketing`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tmarketing = await featuredMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.FREE_DELIVERY: {\n\t\t\t\tmarketing = await freeDeliveryMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.PUNCH_MARKETING: {\n\t\t\t\tmarketing = await punchMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.SPEND_TO_GET: {\n\t\t\t\tmarketing = await spendToGetMarketingService.create(data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tmarketing = await this.model.create(data, admin);\n\t\t\t}\n\t\t}\n\n\t\tawait this.assignMarketingToProducts(marketing);\n\n\t\tawait this.model.populate(marketing, {\n\t\t\tpath: 'shop',\n\t\t\tmodel: this.shopModel,\n\t\t\tselect: '_id name shopId',\n\t\t});\n\n\t\tif (admin) {\n\t\t\tthis.logMarketingAdminAction(\n\t\t\t\tadmin,\n\t\t\t\tAdminLogsUpdatedFieldsType.ACTIVATED_MARKETING_PROMOTIONS,\n\t\t\t\t'',\n\t\t\t\tmarketing\n\t\t\t);\n\t\t}\n\t\tif (marketing && !data.isEntireMenu)\n\t\t\tpublishSyncSingleShopSectionsInCacheProcessEvent({\n\t\t\t\tshopId: data.shop,\n\t\t\t\toperation: ChangeStreamOperationTypes.UPDATE,\n\t\t\t});\n\t\treturn marketing;\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(data: GetByIdInputDTO): Promise<DocumentType<Model>> {\n\t\tconst select = data.select || '';\n\t\tconst populate = data.populate || [];\n\t\tconst result = await this.model\n\t\t\t.findOne({\n\t\t\t\t_id: data._id,\n\t\t\t})\n\t\t\t.select(select)\n\t\t\t.populate(populate);\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 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,\n\t\t\t\tselect: data?.select,\n\t\t\t\tpopulate: data?.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 record\n\t * @param data Data to update\n\t */\n\tpublic async update(\n\t\t_id: mongoose.Types.ObjectId,\n\t\tdata: UpdateDTO,\n\t\tadmin?: mongoose.Types.ObjectId\n\t): Promise<DocumentType<Model>> {\n\t\tlet marketing: AllMarketingsDTO;\n\n\t\tconst partOfLimitedTimeOffer = await this.limitedTimeOfferParticipantModel.exists({\n\t\t\tmarketing: _id,\n\t\t});\n\n\t\tif (partOfLimitedTimeOffer) {\n\t\t\tforbiddenError(\n\t\t\t\t'You are currently participating in a Limited Time Offer. Please make your edits from the Limited Time Offer section.'\n\t\t\t);\n\t\t}\n\n\t\tconst oldMarketing = await this.model.findById(_id).populate({\n\t\t\tpath: 'shop',\n\t\t\tselect: '_id name shopId',\n\t\t});\n\n\t\tif (!oldMarketing) {\n\t\t\tnotFoundError('Could not find marketing');\n\t\t}\n\n\t\tif (\n\t\t\tdata.status &&\n\t\t\tdata.status === MarketingStatus.ACTIVE &&\n\t\t\toldMarketing.status === MarketingStatus.PAUSED\n\t\t) {\n\t\t\tif (\n\t\t\t\toldMarketing.marketingType === MarketingType.DISCOUNT &&\n\t\t\t\t(await ltoParticipantService.isActiveParticipant(oldMarketing.shop._id))\n\t\t\t) {\n\t\t\t\tforbiddenError(\n\t\t\t\t\t'You are currently participating in a Limited Time Offer. Please manage your discount from the Limited Time Offer section or withdraw first.'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tawait this.verifyUnpauseConditions(_id);\n\t\t}\n\n\t\tswitch (oldMarketing.marketingType) {\n\t\t\tcase MarketingType.DISCOUNT: {\n\t\t\t\tmarketing = await discountMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.BUY1GET1: {\n\t\t\t\tmarketing = await buy1Get1MarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.FEATURED: {\n\t\t\t\tif (!admin) {\n\t\t\t\t\tunauthorizedError(`Only admin is allowed to update ${data.marketingType} marketing`);\n\t\t\t\t}\n\t\t\t\tmarketing = await featuredMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.FREE_DELIVERY: {\n\t\t\t\tmarketing = await freeDeliveryMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.PUNCH_MARKETING: {\n\t\t\t\tmarketing = await punchMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase MarketingType.SPEND_TO_GET: {\n\t\t\t\tmarketing = await spendToGetMarketingService.update(_id, data);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tmarketing = await this.model\n\t\t\t\t\t.findOneAndUpdate(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t_id: _id,\n\t\t\t\t\t\t\tdeletedAt: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnew: true,\n\t\t\t\t\t\t\trunValidators: true,\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t\t.populate({\n\t\t\t\t\t\tpath: 'shop',\n\t\t\t\t\t\tselect: '_id name shopId',\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (!marketing) {\n\t\t\tinternalServerError('Could not update marketing');\n\t\t}\n\n\t\tif (admin) {\n\t\t\tconst allChanges = getChangedFields(oldMarketing, marketing);\n\t\t\tconst relevantChanges = filterRelevantChanges(allChanges, data);\n\n\t\t\tif (Object.keys(relevantChanges).includes('status')) {\n\t\t\t\tif (data.status == MarketingStatus.ACTIVE) {\n\t\t\t\t\tthis.logMarketingAdminAction(\n\t\t\t\t\t\tadmin,\n\t\t\t\t\t\tAdminLogsUpdatedFieldsType.CONTINUED_MARKETING_PROMOTIONS,\n\t\t\t\t\t\toldMarketing,\n\t\t\t\t\t\tmarketing\n\t\t\t\t\t);\n\t\t\t\t} else if (data.status == MarketingStatus.PAUSED) {\n\t\t\t\t\tthis.logMarketingAdminAction(\n\t\t\t\t\t\tadmin,\n\t\t\t\t\t\tAdminLogsUpdatedFieldsType.PAUSED_MARKETING_PROMOTIONS,\n\t\t\t\t\t\toldMarketing,\n\t\t\t\t\t\tmarketing\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.logMarketingAdminAction(\n\t\t\t\tadmin,\n\t\t\t\tAdminLogsUpdatedFieldsType.EDITED_MARKETING_PROMOTIONS,\n\t\t\t\toldMarketing,\n\t\t\t\tmarketing\n\t\t\t);\n\t\t}\n\n\t\tawait this.assignMarketingToProducts(marketing);\n\n\t\tpublishSyncSingleShopSectionsInCacheProcessEvent({\n\t\t\tshopId: marketing.shop,\n\t\t\toperation: ChangeStreamOperationTypes.UPDATE,\n\t\t});\n\n\t\treturn marketing;\n\t}\n\n\tprivate async verifyUnpauseConditions(marketingId: mongoose.Types.ObjectId): Promise<void> {\n\t\tconst marketing = await this.model.findOne({ _id: marketingId, deletedAt: null }).populate('products');\n\t\tif (!marketing) return;\n\n\t\tconst hasActiveLto = await this.model.exists({\n\t\t\tshop: marketing.shop,\n\t\t\tcampaignType: MarketingCampaignType.LIMITED_TIME_OFFER,\n\t\t\tstatus: MarketingStatus.ACTIVE,\n\t\t\tdeletedAt: null,\n\t\t});\n\t\tif (hasActiveLto) {\n\t\t\tconflictError(\"Can't resume this discount while a limited time offer is active\");\n\t\t}\n\n\t\tif ([MarketingType.BUY1GET1, MarketingType.DISCOUNT].includes(marketing.marketingType)) {\n\t\t\tconst typedMarketing = marketing as DocumentType<DiscountMarketing | Buy1Get1Marketing>;\n\t\t\tconst productIds = typedMarketing.products.map((product: any) => product.product);\n\t\t\tconst isAvailable = await productMarketingService.checkProductMarketingAvailability(\n\t\t\t\tproductIds,\n\t\t\t\tmarketing.isAppliedByCompany\n\t\t\t);\n\n\t\t\tif (!isAvailable) {\n\t\t\t\tconflictError(\"You can't activate discount and B1G1 on the same items at the same time\");\n\t\t\t}\n\t\t}\n\n\t\tif (CONFLICT_CHECK_MARKETING_TYPES.includes(marketing.marketingType)) {\n\t\t\tawait marketingConflictService.assertNoConflict({\n\t\t\t\tshop: marketing.shop as mongoose.Types.ObjectId,\n\t\t\t\tmarketingType: marketing.marketingType,\n\t\t\t\tduration: marketing.duration,\n\t\t\t\trewardTypeGroups: marketingConflictService.getRewardTypeGroups(\n\t\t\t\t\tmarketing.marketingType,\n\t\t\t\t\t(marketing as any).tiers\n\t\t\t\t),\n\t\t\t\texcludeMarketingId: marketingId,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async logMarketingAdminAction(\n\t\tadmin: mongoose.Types.ObjectId,\n\t\tactionType: AdminLogsUpdatedFieldsType,\n\t\toldDocument?: any,\n\t\tnewDocument?: any\n\t) {\n\t\tconst adminActivityLogsEvent: BaseEvent<Record<string, unknown>> = new AdminActivityLogsEvent({\n\t\t\tadmin,\n\t\t\tupdatedField: actionType,\n\t\t\toldDocument: oldDocument ?? '',\n\t\t\tnewDocument: newDocument ?? '',\n\t\t});\n\t\tawait publishEvent(adminActivityLogsEvent);\n\t}\n\n\t/**\n\t * Delete record\n\t * @param data Data for delete\n\t */\n\tpublic async deleteById(\n\t\tdata: DeleteDTO,\n\t\tadmin?: mongoose.Types.ObjectId,\n\t\toptions?: { skipLimitedTimeOfferGuard?: boolean }\n\t): Promise<string> {\n\t\tconst { _id, softDelete } = data;\n\n\t\tif (!options?.skipLimitedTimeOfferGuard) {\n\t\t\tconst partOfLimitedTimeOffer = await this.limitedTimeOfferParticipantModel.exists({\n\t\t\t\tmarketing: _id,\n\t\t\t});\n\n\t\t\tif (partOfLimitedTimeOffer) {\n\t\t\t\tforbiddenError(\n\t\t\t\t\t'You are currently participating in a Limited Time Offer. Please make your edits from the Limited Time Offer section.'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst record = await this.model.findById(_id).populate({\n\t\t\tpath: 'shop',\n\t\t\tselect: '_id name shopId',\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\trecord.status = MarketingStatus.DELETED;\n\t\tawait record.save();\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: 'INTERNAL_SERVER_ERROR',\n\t\t\t\tmessage: 'Unable to delete marketing',\n\t\t\t});\n\t\t}\n\n\t\tif (admin) {\n\t\t\tthis.logMarketingAdminAction(admin, AdminLogsUpdatedFieldsType.DELETED_MARKETING_PROMOTIONS, record);\n\t\t}\n\n\t\tproductMarketingService.deleteMany({ marketing: data._id }, data.softDelete);\n\t\tpublishSyncSingleShopSectionsInCacheProcessEvent({\n\t\t\tshopId: record.shop._id,\n\t\t\toperation: ChangeStreamOperationTypes.DELETE,\n\t\t});\n\t\treturn 'Record deleted successfully';\n\t}\n\n\tpublic async deleteManyByIds(marketingIds: mongoose.Types.ObjectId[], softDelete = true): Promise<void> {\n\t\tif (marketingIds.length === 0) return;\n\n\t\tconst marketings = await this.model\n\t\t\t.find({ _id: { $in: marketingIds } })\n\t\t\t.select('shop')\n\t\t\t.lean();\n\n\t\tawait this.model.updateMany(\n\t\t\t{ _id: { $in: marketingIds } },\n\t\t\t{ $set: { status: MarketingStatus.DELETED } }\n\t\t);\n\t\tawait this.model.deleteRecords({ _id: { $in: marketingIds } }, softDelete);\n\n\t\tawait productMarketingService.deleteManyByMarketingIds(marketingIds, softDelete);\n\n\t\tconst uniqueShopIds = [\n\t\t\t...new Map(\n\t\t\t\tmarketings\n\t\t\t\t\t.map((m: any) => m.shop)\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.map((s: any) => {\n\t\t\t\t\t\tconst id = s instanceof mongoose.Types.ObjectId ? s : new mongoose.Types.ObjectId(s);\n\t\t\t\t\t\treturn [id.toString(), id] as [string, mongoose.Types.ObjectId];\n\t\t\t\t\t})\n\t\t\t).values(),\n\t\t];\n\n\t\tfor (const shopId of uniqueShopIds) {\n\t\t\tpublishSyncSingleShopSectionsInCacheProcessEvent({\n\t\t\t\tshopId,\n\t\t\t\toperation: ChangeStreamOperationTypes.DELETE,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic async handleNewProductForEntireMenuMarketing(data: ProductEntireMenuMarketingHandlerDTO) {\n\t\tconst existingMarketing = await this.model.findOne({\n\t\t\tshop: data.shop,\n\t\t\tmarketingType: { $in: [MarketingType.BUY1GET1, MarketingType.DISCOUNT] },\n\t\t\t'duration.end': { $gt: new Date() },\n\t\t\tstatus: MarketingStatus.ACTIVE,\n\t\t\tisEntireMenu: true,\n\t\t});\n\n\t\t// check if existing marketing\n\t\tif (existingMarketing) {\n\t\t\tconst productMarketingData: CreateProductMarketingDTO = {\n\t\t\t\tproduct: data.product,\n\t\t\t\tmarketing: existingMarketing._id,\n\t\t\t};\n\t\t\tif (existingMarketing.marketingType == MarketingType.BUY1GET1) {\n\t\t\t\tproductMarketingData.isBuy1Get1 = true;\n\t\t\t}\n\t\t\tif (existingMarketing.marketingType == MarketingType.DISCOUNT) {\n\t\t\t\tproductMarketingData.value = (existingMarketing as DocumentType<DiscountMarketing>).value;\n\t\t\t\tproductMarketingData.valueType = (existingMarketing as DocumentType<DiscountMarketing>).valueType;\n\t\t\t}\n\n\t\t\tawait productMarketingService.create(productMarketingData);\n\t\t\tawait synchronizeProductMarketingService.syncProductMarketingInfoByProductId(data.product);\n\t\t}\n\n\t\treturn 'Product handled successfully';\n\t}\n\n\tpublic async incrementMarketingSpentFromOrder(orderId: mongoose.Types.ObjectId): Promise<any> {\n\t\tconst order = (await this.orderModel\n\t\t\t.findById(orderId)\n\t\t\t.populate([\n\t\t\t\t{ path: 'lineItems' },\n\t\t\t\t{ path: 'marketings', select: 'isAppliedByCompany' },\n\t\t\t])) as DocumentType<RegularOrder> & {\n\t\t\tlineItems: DocumentType<LineItem>[];\n\t\t\tmarketings: DocumentType<Marketing>[];\n\t\t};\n\n\t\tif (!order || !order.marketings?.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst marketingSpendMap = this.marketingMetricsRepository.calculateMarketingSpendPerOrder(order);\n\n\t\tconst bulkOps = [...marketingSpendMap.entries()].map(([marketingId, amountSpent]) => ({\n\t\t\tupdateOne: {\n\t\t\t\tfilter: { _id: marketingId },\n\t\t\t\tupdate: { $inc: { amountSpent } },\n\t\t\t},\n\t\t}));\n\n\t\tif (bulkOps.length) {\n\t\t\tawait this.model.bulkWrite(bulkOps);\n\t\t}\n\n\t\tawait this.expireMarketingsExceedingSpendLimits(Array.from(marketingSpendMap.keys()));\n\n\t\treturn 'Marketing amount spent incremented successfully';\n\t}\n\n\tpublic async decrementMarketingSpentFromOrder(orderId: mongoose.Types.ObjectId): Promise<any> {\n\t\tconst order = (await this.orderModel\n\t\t\t.findById(orderId)\n\t\t\t.populate([\n\t\t\t\t{ path: 'lineItems' },\n\t\t\t\t{ path: 'marketings', select: 'isAppliedByCompany' },\n\t\t\t])) as DocumentType<RegularOrder> & {\n\t\t\tlineItems: DocumentType<LineItem>[];\n\t\t\tmarketings: DocumentType<Marketing>[];\n\t\t};\n\n\t\tif (!order || !order.marketings?.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst marketingSpendMap = this.marketingMetricsRepository.calculateMarketingSpendPerOrder(order);\n\n\t\tconst bulkOps = [...marketingSpendMap.entries()].map(([marketingId, amountSpent]) => ({\n\t\t\tupdateOne: {\n\t\t\t\tfilter: { _id: marketingId },\n\t\t\t\tupdate: { $inc: { amountSpent: -amountSpent } },\n\t\t\t},\n\t\t}));\n\n\t\tif (bulkOps.length) {\n\t\t\tawait this.model.bulkWrite(bulkOps);\n\t\t}\n\n\t\tawait this.unExpireMarketingsBelowSpendLimits(Array.from(marketingSpendMap.keys()));\n\n\t\treturn 'Marketing amount spent decremented successfully';\n\t}\n\n\tprivate async expireMarketingsExceedingSpendLimits(marketingIds: mongoose.Types.ObjectId[]) {\n\t\tconst update = await this.model.updateMany(\n\t\t\t{\n\t\t\t\t_id: { $in: marketingIds },\n\t\t\t\tisSpendLimitEnabled: true,\n\t\t\t\tstatus: { $ne: MarketingStatus.EXPIRED },\n\t\t\t\t$expr: { $gte: ['$amountSpent', '$spendLimit'] },\n\t\t\t},\n\t\t\t{ $set: { status: MarketingStatus.EXPIRED, expiredAt: dayjs().toDate() } }\n\t\t);\n\n\t\tif (update.modifiedCount > 0) {\n\t\t\tawait synchronizeProductMarketingService.syncProductMarketingInfoByMarketingIds(marketingIds);\n\t\t}\n\t}\n\n\tprivate async unExpireMarketingsBelowSpendLimits(marketingIds: mongoose.Types.ObjectId[]) {\n\t\tconst update = await this.model.updateMany(\n\t\t\t{\n\t\t\t\t_id: { $in: marketingIds },\n\t\t\t\tisSpendLimitEnabled: true,\n\t\t\t\tstatus: MarketingStatus.EXPIRED,\n\t\t\t\t$expr: { $lt: ['$amountSpent', '$spendLimit'] },\n\t\t\t},\n\t\t\t{ $set: { status: MarketingStatus.ACTIVE }, $unset: { expiredAt: 1 } }\n\t\t);\n\n\t\tif (update.modifiedCount > 0) {\n\t\t\tawait synchronizeProductMarketingService.syncProductMarketingInfoByMarketingIds(marketingIds);\n\t\t}\n\t}\n\n\tpublic async recomputeAndSyncAllMarketingSpent(): Promise<void> {\n\t\tconst cursor = this.model\n\t\t\t.find({ marketingType: { $ne: MarketingType.FEATURED } }, { _id: 1 })\n\t\t\t.lean()\n\t\t\t.cursor();\n\n\t\tconst bulkOps: mongoose.AnyBulkWriteOperation[] = [];\n\t\tconst marketingIds: mongoose.Types.ObjectId[] = [];\n\n\t\tfor await (const marketing of cursor) {\n\t\t\tconst { amount } = await this.marketingMetricsRepository.calculateMarketingSpent(marketing._id);\n\n\t\t\tbulkOps.push({\n\t\t\t\tupdateOne: {\n\t\t\t\t\tfilter: { _id: marketing._id },\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\t$set: { amountSpent: amount },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tmarketingIds.push(marketing._id);\n\n\t\t\tif (bulkOps.length >= 500) {\n\t\t\t\tawait this.model.bulkWrite(bulkOps);\n\t\t\t\tbulkOps.length = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (bulkOps.length) {\n\t\t\tawait this.model.bulkWrite(bulkOps);\n\t\t}\n\n\t\tawait this.expireMarketingsExceedingSpendLimits(marketingIds);\n\t\tawait this.unExpireMarketingsBelowSpendLimits(marketingIds);\n\t}\n\n\tprivate async publishEntireMenuSeedEvents(\n\t\tmarketing: DocumentType<Buy1Get1Marketing | DiscountMarketing>\n\t): Promise<number> {\n\t\tconst PAGE_SIZE = 500;\n\t\tconst marketingId = marketing._id.toString();\n\t\tconst shopId = ((marketing.shop as any)?._id ?? marketing.shop).toString();\n\n\t\tconst products = await ProductModel.find({ shop: marketing.shop }).select('_id').lean();\n\t\tconst productIds = products.map((p: any) => p._id.toString());\n\n\t\tfor (let i = 0; i < productIds.length; i += PAGE_SIZE) {\n\t\t\tawait publishEvent(\n\t\t\t\tnew MarketingEntireMenuSeedEvent({\n\t\t\t\t\tmarketingId,\n\t\t\t\t\tshopId,\n\t\t\t\t\tisAppliedByCompany: marketing.isAppliedByCompany ?? false,\n\t\t\t\t\tisBuy1Get1: marketing.marketingType === MarketingType.BUY1GET1,\n\t\t\t\t\tvalue: (marketing as any).value,\n\t\t\t\t\tvalueType: (marketing as any).valueType,\n\t\t\t\t\tproductIds: productIds.slice(i, i + PAGE_SIZE),\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\treturn productIds.length;\n\t}\n\n\tpublic async reseedEntireMenuMarketing(marketingId: mongoose.Types.ObjectId): Promise<void> {\n\t\tconst logger = getLibraries().getLoggerKit();\n\n\t\tconst marketing = await this.model.findOne({ _id: marketingId, deletedAt: null });\n\t\tif (!marketing) internalServerError('Marketing not found');\n\n\t\tconst productCount = await this.publishEntireMenuSeedEvents(\n\t\t\tmarketing as DocumentType<Buy1Get1Marketing | DiscountMarketing>\n\t\t);\n\n\t\tlogger.debug(`entire-menu reseed dispatched — ${productCount} products`, {\n\t\t\ttag: 'marketing.seed.entire-menu',\n\t\t\tdata: { marketingId: marketingId.toString(), productCount },\n\t\t});\n\t}\n\n\tpublic async assignMarketingToProducts(marketing: DocumentType<Buy1Get1Marketing | DiscountMarketing>) {\n\t\tconst diffStartTime = dayjs(marketing.duration.start).diff(dayjs(), 'milliseconds');\n\t\tif (diffStartTime > 0) {\n\t\t\treturn await scheduleMarketingProductSync(marketing._id.toString(), diffStartTime);\n\t\t}\n\n\t\tif (marketing.isEntireMenu) {\n\t\t\tconst logger = getLibraries().getLoggerKit();\n\n\t\t\tconst productCount = await this.publishEntireMenuSeedEvents(marketing);\n\n\t\t\tlogger.debug(`entire-menu marketing seed dispatched — ${productCount} products`, {\n\t\t\t\ttag: 'marketing.seed.entire-menu',\n\t\t\t\tdata: { marketingId: marketing._id.toString(), productCount },\n\t\t\t});\n\t\t} else {\n\t\t\t// Non-entire-menu: the productMarketings were already created synchronously. The product-doc\n\t\t\t// sync is linear in product count (thousands → seconds), so page it into background events\n\t\t\t// instead of blocking the request — same pattern as the entire-menu branch above.\n\t\t\tconst shopId = ((marketing.shop as any)?._id ?? marketing.shop).toString();\n\t\t\tconst pms = await ProductMarketingModel.find({ marketing: marketing._id, deletedAt: null })\n\t\t\t\t.select('product')\n\t\t\t\t.lean();\n\t\t\tconst productIds = pms.map((p: any) => p.product.toString());\n\n\t\t\tconst PAGE_SIZE = 500;\n\t\t\tfor (let i = 0; i < productIds.length; i += PAGE_SIZE) {\n\t\t\t\tawait publishEvent(\n\t\t\t\t\tnew MarketingProductSyncEvent({\n\t\t\t\t\t\tmarketingId: marketing._id.toString(),\n\t\t\t\t\t\tshopId,\n\t\t\t\t\t\tproductIds: productIds.slice(i, i + PAGE_SIZE),\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport const marketingService = Container.get(MarketingService);\n"]}
@@ -59,6 +59,7 @@ declare const Buy1Get1MarketingValidationSchema: z.ZodObject<{
59
59
  isAppliedByCompany: boolean;
60
60
  isEntireMenu: boolean;
61
61
  pausedAt: Date | null;
62
+ marketingType: MarketingType.BUY1GET1;
62
63
  products: {
63
64
  product: import("mongoose").Types.ObjectId;
64
65
  value?: number | undefined;
@@ -67,7 +68,6 @@ declare const Buy1Get1MarketingValidationSchema: z.ZodObject<{
67
68
  marketing?: import("mongoose").Types.ObjectId | undefined;
68
69
  isBuy1Get1?: boolean | undefined;
69
70
  }[];
70
- marketingType: MarketingType.BUY1GET1;
71
71
  excludeProducts: import("mongoose").Types.ObjectId[];
72
72
  isOnlyForSubscriber: boolean;
73
73
  admin?: import("mongoose").Types.ObjectId | null | undefined;
@@ -437,6 +437,7 @@ declare const Buy1Get1MarketingValidationSchemaRefined: z.ZodEffects<z.ZodObject
437
437
  isAppliedByCompany: boolean;
438
438
  isEntireMenu: boolean;
439
439
  pausedAt: Date | null;
440
+ marketingType: MarketingType.BUY1GET1;
440
441
  products: {
441
442
  product: import("mongoose").Types.ObjectId;
442
443
  value?: number | undefined;
@@ -445,7 +446,6 @@ declare const Buy1Get1MarketingValidationSchemaRefined: z.ZodEffects<z.ZodObject
445
446
  marketing?: import("mongoose").Types.ObjectId | undefined;
446
447
  isBuy1Get1?: boolean | undefined;
447
448
  }[];
448
- marketingType: MarketingType.BUY1GET1;
449
449
  excludeProducts: import("mongoose").Types.ObjectId[];
450
450
  isOnlyForSubscriber: boolean;
451
451
  admin?: import("mongoose").Types.ObjectId | null | undefined;
@@ -487,6 +487,7 @@ declare const Buy1Get1MarketingValidationSchemaRefined: z.ZodEffects<z.ZodObject
487
487
  isAppliedByCompany: boolean;
488
488
  isEntireMenu: boolean;
489
489
  pausedAt: Date | null;
490
+ marketingType: MarketingType.BUY1GET1;
490
491
  products: {
491
492
  product: import("mongoose").Types.ObjectId;
492
493
  value?: number | undefined;
@@ -495,7 +496,6 @@ declare const Buy1Get1MarketingValidationSchemaRefined: z.ZodEffects<z.ZodObject
495
496
  marketing?: import("mongoose").Types.ObjectId | undefined;
496
497
  isBuy1Get1?: boolean | undefined;
497
498
  }[];
498
- marketingType: MarketingType.BUY1GET1;
499
499
  excludeProducts: import("mongoose").Types.ObjectId[];
500
500
  isOnlyForSubscriber: boolean;
501
501
  admin?: import("mongoose").Types.ObjectId | null | undefined;
@@ -67,6 +67,7 @@ declare const DiscountMarketingValidationSchema: z.ZodObject<{
67
67
  isMaxDiscountPerOrderEnabled: boolean;
68
68
  maxDiscountPerOrder: number;
69
69
  pausedAt: Date | null;
70
+ marketingType: MarketingType.DISCOUNT;
70
71
  products: {
71
72
  product: import("mongoose").Types.ObjectId;
72
73
  value?: number | undefined;
@@ -75,7 +76,6 @@ declare const DiscountMarketingValidationSchema: z.ZodObject<{
75
76
  marketing?: import("mongoose").Types.ObjectId | undefined;
76
77
  isBuy1Get1?: boolean | undefined;
77
78
  }[];
78
- marketingType: MarketingType.DISCOUNT;
79
79
  excludeProducts: import("mongoose").Types.ObjectId[];
80
80
  isOnlyForSubscriber: boolean;
81
81
  value?: number | undefined;
@@ -337,6 +337,7 @@ declare const DiscountMarketingValidationSchemaRefined: z.ZodEffects<z.ZodObject
337
337
  isMaxDiscountPerOrderEnabled: boolean;
338
338
  maxDiscountPerOrder: number;
339
339
  pausedAt: Date | null;
340
+ marketingType: MarketingType.DISCOUNT;
340
341
  products: {
341
342
  product: import("mongoose").Types.ObjectId;
342
343
  value?: number | undefined;
@@ -345,7 +346,6 @@ declare const DiscountMarketingValidationSchemaRefined: z.ZodEffects<z.ZodObject
345
346
  marketing?: import("mongoose").Types.ObjectId | undefined;
346
347
  isBuy1Get1?: boolean | undefined;
347
348
  }[];
348
- marketingType: MarketingType.DISCOUNT;
349
349
  excludeProducts: import("mongoose").Types.ObjectId[];
350
350
  isOnlyForSubscriber: boolean;
351
351
  value?: number | undefined;
@@ -399,6 +399,7 @@ declare const DiscountMarketingValidationSchemaRefined: z.ZodEffects<z.ZodObject
399
399
  isMaxDiscountPerOrderEnabled: boolean;
400
400
  maxDiscountPerOrder: number;
401
401
  pausedAt: Date | null;
402
+ marketingType: MarketingType.DISCOUNT;
402
403
  products: {
403
404
  product: import("mongoose").Types.ObjectId;
404
405
  value?: number | undefined;
@@ -407,7 +408,6 @@ declare const DiscountMarketingValidationSchemaRefined: z.ZodEffects<z.ZodObject
407
408
  marketing?: import("mongoose").Types.ObjectId | undefined;
408
409
  isBuy1Get1?: boolean | undefined;
409
410
  }[];
410
- marketingType: MarketingType.DISCOUNT;
411
411
  excludeProducts: import("mongoose").Types.ObjectId[];
412
412
  isOnlyForSubscriber: boolean;
413
413
  value?: number | undefined;
@@ -244,6 +244,8 @@ export declare const MarketingMetricsSchema: z.ZodObject<{
244
244
  percentageIncrease?: number | undefined;
245
245
  }>>;
246
246
  totalRedemptions: z.ZodOptional<z.ZodNumber>;
247
+ totalValueGiven: z.ZodOptional<z.ZodNumber>;
248
+ remainingBudget: z.ZodOptional<z.ZodNumber>;
247
249
  }, "strip", z.ZodTypeAny, {
248
250
  numberOfItems?: number | undefined;
249
251
  orderIncreaseWithDiscount?: {
@@ -255,6 +257,8 @@ export declare const MarketingMetricsSchema: z.ZodObject<{
255
257
  percentageIncrease: number;
256
258
  } | undefined;
257
259
  totalRedemptions?: number | undefined;
260
+ totalValueGiven?: number | undefined;
261
+ remainingBudget?: number | undefined;
258
262
  }, {
259
263
  numberOfItems?: number | undefined;
260
264
  orderIncreaseWithDiscount?: {
@@ -266,6 +270,8 @@ export declare const MarketingMetricsSchema: z.ZodObject<{
266
270
  percentageIncrease?: number | undefined;
267
271
  } | undefined;
268
272
  totalRedemptions?: number | undefined;
273
+ totalValueGiven?: number | undefined;
274
+ remainingBudget?: number | undefined;
269
275
  }>;
270
276
  export declare const MarketingGraphInputSchema: z.ZodObject<{
271
277
  marketingId: z.ZodType<string | import("mongoose").Types.ObjectId, z.ZodTypeDef, string | import("mongoose").Types.ObjectId>;