@lyxa.ai/marketing 1.0.41 → 1.0.42

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 (209) hide show
  1. package/dist/lib/event/event-initializations.d.ts.map +1 -1
  2. package/dist/lib/event/event-initializations.js +2 -0
  3. package/dist/lib/event/event-initializations.js.map +1 -1
  4. package/dist/lib/event/event-listeners/event-listeners.d.ts.map +1 -1
  5. package/dist/lib/event/event-listeners/event-listeners.js.map +1 -1
  6. package/dist/lib/index.d.ts +643 -0
  7. package/dist/lib/index.d.ts.map +1 -1
  8. package/dist/lib/index.js +6 -6
  9. package/dist/lib/index.js.map +1 -1
  10. package/dist/lib/modules/coupon/routers/coupon.router.d.ts.map +1 -1
  11. package/dist/lib/modules/coupon/services/coupon.service.d.ts +1 -0
  12. package/dist/lib/modules/coupon/services/coupon.service.d.ts.map +1 -1
  13. package/dist/lib/modules/coupon/services/coupon.service.js +61 -40
  14. package/dist/lib/modules/coupon/services/coupon.service.js.map +1 -1
  15. package/dist/lib/modules/coupon/services/helper.service.d.ts.map +1 -1
  16. package/dist/lib/modules/coupon/services/helper.service.js +11 -6
  17. package/dist/lib/modules/coupon/services/helper.service.js.map +1 -1
  18. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.d.ts.map +1 -1
  19. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.js +108 -149
  20. package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.js.map +1 -1
  21. package/dist/lib/modules/coupon/services/referral-code-coupon.service.d.ts.map +1 -1
  22. package/dist/lib/modules/coupon/services/referral-code-coupon.service.js +1 -1
  23. package/dist/lib/modules/coupon/services/referral-code-coupon.service.js.map +1 -1
  24. package/dist/lib/modules/coupon/services/referral-reward-coupon.service.d.ts.map +1 -1
  25. package/dist/lib/modules/coupon/services/referral-reward-coupon.service.js +5 -1
  26. package/dist/lib/modules/coupon/services/referral-reward-coupon.service.js.map +1 -1
  27. package/dist/lib/modules/deal-setting/routers/deal-setting.router.d.ts.map +1 -1
  28. package/dist/lib/modules/featured-setting/routers/featured-setting.router.d.ts.map +1 -1
  29. package/dist/lib/modules/limited-time-offer/campaign/campaign.router.d.ts +339 -0
  30. package/dist/lib/modules/limited-time-offer/campaign/campaign.router.d.ts.map +1 -0
  31. package/dist/lib/modules/limited-time-offer/campaign/campaign.router.js +77 -0
  32. package/dist/lib/modules/limited-time-offer/campaign/campaign.router.js.map +1 -0
  33. package/dist/lib/modules/limited-time-offer/campaign/jobs/index.d.ts +4 -0
  34. package/dist/lib/modules/limited-time-offer/campaign/jobs/index.d.ts.map +1 -0
  35. package/dist/lib/modules/limited-time-offer/campaign/jobs/index.js +24 -0
  36. package/dist/lib/modules/limited-time-offer/campaign/jobs/index.js.map +1 -0
  37. package/dist/lib/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.producer.d.ts +12 -0
  38. package/dist/lib/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.producer.d.ts.map +1 -0
  39. package/dist/lib/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.producer.js +29 -0
  40. package/dist/lib/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.producer.js.map +1 -0
  41. package/dist/lib/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.worker.d.ts +8 -0
  42. package/dist/lib/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.worker.d.ts.map +1 -0
  43. package/dist/lib/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.worker.js +79 -0
  44. package/dist/lib/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.worker.js.map +1 -0
  45. package/dist/lib/modules/limited-time-offer/campaign/limited-time-offer-campaign.validation.d.ts +851 -0
  46. package/dist/lib/modules/limited-time-offer/campaign/limited-time-offer-campaign.validation.d.ts.map +1 -0
  47. package/dist/lib/modules/limited-time-offer/campaign/limited-time-offer-campaign.validation.js +100 -0
  48. package/dist/lib/modules/limited-time-offer/campaign/limited-time-offer-campaign.validation.js.map +1 -0
  49. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.d.ts +11 -0
  50. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.d.ts.map +1 -0
  51. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.js +75 -0
  52. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.js.map +1 -0
  53. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-scheduler.service.d.ts +9 -0
  54. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-scheduler.service.d.ts.map +1 -0
  55. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-scheduler.service.js +42 -0
  56. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-scheduler.service.js.map +1 -0
  57. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.d.ts +78 -0
  58. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.d.ts.map +1 -0
  59. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.js +308 -0
  60. package/dist/lib/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.js.map +1 -0
  61. package/dist/lib/modules/limited-time-offer/config/limited-time-offer-config.service.d.ts +12 -0
  62. package/dist/lib/modules/limited-time-offer/config/limited-time-offer-config.service.d.ts.map +1 -0
  63. package/dist/lib/modules/limited-time-offer/config/limited-time-offer-config.service.js +94 -0
  64. package/dist/lib/modules/limited-time-offer/config/limited-time-offer-config.service.js.map +1 -0
  65. package/dist/lib/modules/limited-time-offer/config/limited-time-offer-config.validation.d.ts +189 -0
  66. package/dist/lib/modules/limited-time-offer/config/limited-time-offer-config.validation.d.ts.map +1 -0
  67. package/dist/lib/modules/limited-time-offer/config/limited-time-offer-config.validation.js +24 -0
  68. package/dist/lib/modules/limited-time-offer/config/limited-time-offer-config.validation.js.map +1 -0
  69. package/dist/lib/modules/limited-time-offer/config/limited-time-offer.router.d.ts +122 -0
  70. package/dist/lib/modules/limited-time-offer/config/limited-time-offer.router.d.ts.map +1 -0
  71. package/dist/lib/modules/limited-time-offer/config/limited-time-offer.router.js +37 -0
  72. package/dist/lib/modules/limited-time-offer/config/limited-time-offer.router.js.map +1 -0
  73. package/dist/lib/modules/limited-time-offer/limited-time-offer.router.d.ts +644 -0
  74. package/dist/lib/modules/limited-time-offer/limited-time-offer.router.d.ts.map +1 -0
  75. package/dist/lib/modules/limited-time-offer/limited-time-offer.router.js +13 -0
  76. package/dist/lib/modules/limited-time-offer/limited-time-offer.router.js.map +1 -0
  77. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.router.d.ts +170 -0
  78. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.router.d.ts.map +1 -0
  79. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.router.js +51 -0
  80. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.router.js.map +1 -0
  81. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.validation.d.ts +603 -0
  82. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.validation.d.ts.map +1 -0
  83. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.validation.js +85 -0
  84. package/dist/lib/modules/limited-time-offer/participant/limited-time-offer-participant.validation.js.map +1 -0
  85. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.d.ts +12 -0
  86. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.d.ts.map +1 -0
  87. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.js +98 -0
  88. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.js.map +1 -0
  89. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.d.ts +21 -0
  90. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.d.ts.map +1 -0
  91. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.js +133 -0
  92. package/dist/lib/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.js.map +1 -0
  93. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts +2 -1
  94. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts.map +1 -1
  95. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.js +23 -15
  96. package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.js.map +1 -1
  97. package/dist/lib/modules/marketing/routers/marketing.router.d.ts.map +1 -1
  98. package/dist/lib/modules/marketing/routers/marketing.router.js.map +1 -1
  99. package/dist/lib/modules/marketing/services/buy1-get1-marketing.service.d.ts +0 -2
  100. package/dist/lib/modules/marketing/services/buy1-get1-marketing.service.d.ts.map +1 -1
  101. package/dist/lib/modules/marketing/services/buy1-get1-marketing.service.js +18 -39
  102. package/dist/lib/modules/marketing/services/buy1-get1-marketing.service.js.map +1 -1
  103. package/dist/lib/modules/marketing/services/discount-marketing.service.d.ts +0 -3
  104. package/dist/lib/modules/marketing/services/discount-marketing.service.d.ts.map +1 -1
  105. package/dist/lib/modules/marketing/services/discount-marketing.service.js +26 -52
  106. package/dist/lib/modules/marketing/services/discount-marketing.service.js.map +1 -1
  107. package/dist/lib/modules/marketing/services/marketing.service.d.ts +1 -0
  108. package/dist/lib/modules/marketing/services/marketing.service.d.ts.map +1 -1
  109. package/dist/lib/modules/marketing/services/marketing.service.js +55 -25
  110. package/dist/lib/modules/marketing/services/marketing.service.js.map +1 -1
  111. package/dist/lib/modules/marketing/services/product-marketing.service.d.ts +9 -2
  112. package/dist/lib/modules/marketing/services/product-marketing.service.d.ts.map +1 -1
  113. package/dist/lib/modules/marketing/services/product-marketing.service.js +132 -7
  114. package/dist/lib/modules/marketing/services/product-marketing.service.js.map +1 -1
  115. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.d.ts.map +1 -1
  116. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.js +30 -24
  117. package/dist/lib/modules/marketing/services/synchronize-product-marketing.service.js.map +1 -1
  118. package/dist/lib/modules/marketing/transformers/buy1-get1-marketing.transformer.d.ts +3 -0
  119. package/dist/lib/modules/marketing/transformers/buy1-get1-marketing.transformer.d.ts.map +1 -1
  120. package/dist/lib/modules/marketing/transformers/discount-marketing.transformer.d.ts +3 -0
  121. package/dist/lib/modules/marketing/transformers/discount-marketing.transformer.d.ts.map +1 -1
  122. package/dist/lib/modules/marketing/transformers/product-marketing.transformer.d.ts +1 -0
  123. package/dist/lib/modules/marketing/transformers/product-marketing.transformer.d.ts.map +1 -1
  124. package/dist/lib/modules/marketing/validations/buy1-get1-marketing.validation.d.ts +30 -0
  125. package/dist/lib/modules/marketing/validations/buy1-get1-marketing.validation.d.ts.map +1 -1
  126. package/dist/lib/modules/marketing/validations/discount-marketing.validation.d.ts +45 -9
  127. package/dist/lib/modules/marketing/validations/discount-marketing.validation.d.ts.map +1 -1
  128. package/dist/lib/modules/marketing/validations/product-marketing.validation.d.ts +77 -0
  129. package/dist/lib/modules/marketing/validations/product-marketing.validation.d.ts.map +1 -1
  130. package/dist/lib/modules/marketing/validations/product-marketing.validation.js +20 -1
  131. package/dist/lib/modules/marketing/validations/product-marketing.validation.js.map +1 -1
  132. package/dist/lib/modules/punch-marketing-history/routers/punch-marketing-history.router.d.ts.map +1 -1
  133. package/dist/types/event/event-initializations.d.ts.map +1 -1
  134. package/dist/types/event/event-listeners/event-listeners.d.ts.map +1 -1
  135. package/dist/types/index.d.ts +643 -0
  136. package/dist/types/index.d.ts.map +1 -1
  137. package/dist/types/modules/coupon/routers/coupon.router.d.ts.map +1 -1
  138. package/dist/types/modules/coupon/services/coupon.service.d.ts +1 -0
  139. package/dist/types/modules/coupon/services/coupon.service.d.ts.map +1 -1
  140. package/dist/types/modules/coupon/services/helper.service.d.ts.map +1 -1
  141. package/dist/types/modules/coupon/services/patterns/repository/CouponRepository.d.ts.map +1 -1
  142. package/dist/types/modules/coupon/services/referral-code-coupon.service.d.ts.map +1 -1
  143. package/dist/types/modules/coupon/services/referral-reward-coupon.service.d.ts.map +1 -1
  144. package/dist/types/modules/deal-setting/routers/deal-setting.router.d.ts.map +1 -1
  145. package/dist/types/modules/featured-setting/routers/featured-setting.router.d.ts.map +1 -1
  146. package/dist/types/modules/limited-time-offer/campaign/campaign.router.d.ts +339 -0
  147. package/dist/types/modules/limited-time-offer/campaign/campaign.router.d.ts.map +1 -0
  148. package/dist/types/modules/limited-time-offer/campaign/jobs/index.d.ts +4 -0
  149. package/dist/types/modules/limited-time-offer/campaign/jobs/index.d.ts.map +1 -0
  150. package/dist/types/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.producer.d.ts +12 -0
  151. package/dist/types/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.producer.d.ts.map +1 -0
  152. package/dist/types/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.worker.d.ts +8 -0
  153. package/dist/types/modules/limited-time-offer/campaign/jobs/limited-time-offer-campaign.worker.d.ts.map +1 -0
  154. package/dist/types/modules/limited-time-offer/campaign/limited-time-offer-campaign.validation.d.ts +851 -0
  155. package/dist/types/modules/limited-time-offer/campaign/limited-time-offer-campaign.validation.d.ts.map +1 -0
  156. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.d.ts +11 -0
  157. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-lifecycle.service.d.ts.map +1 -0
  158. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-scheduler.service.d.ts +9 -0
  159. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign-scheduler.service.d.ts.map +1 -0
  160. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.d.ts +78 -0
  161. package/dist/types/modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.d.ts.map +1 -0
  162. package/dist/types/modules/limited-time-offer/config/limited-time-offer-config.service.d.ts +12 -0
  163. package/dist/types/modules/limited-time-offer/config/limited-time-offer-config.service.d.ts.map +1 -0
  164. package/dist/types/modules/limited-time-offer/config/limited-time-offer-config.validation.d.ts +189 -0
  165. package/dist/types/modules/limited-time-offer/config/limited-time-offer-config.validation.d.ts.map +1 -0
  166. package/dist/types/modules/limited-time-offer/config/limited-time-offer.router.d.ts +122 -0
  167. package/dist/types/modules/limited-time-offer/config/limited-time-offer.router.d.ts.map +1 -0
  168. package/dist/types/modules/limited-time-offer/limited-time-offer.router.d.ts +644 -0
  169. package/dist/types/modules/limited-time-offer/limited-time-offer.router.d.ts.map +1 -0
  170. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.router.d.ts +170 -0
  171. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.router.d.ts.map +1 -0
  172. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.service.d.ts +1 -0
  173. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.service.d.ts.map +1 -0
  174. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.validation.d.ts +603 -0
  175. package/dist/types/modules/limited-time-offer/participant/limited-time-offer-participant.validation.d.ts.map +1 -0
  176. package/dist/types/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.d.ts +12 -0
  177. package/dist/types/modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service.d.ts.map +1 -0
  178. package/dist/types/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.d.ts +21 -0
  179. package/dist/types/modules/limited-time-offer/participant/services/limited-time-offer-participant.service.d.ts.map +1 -0
  180. package/dist/types/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts +2 -1
  181. package/dist/types/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts.map +1 -1
  182. package/dist/types/modules/marketing/routers/marketing.router.d.ts.map +1 -1
  183. package/dist/types/modules/marketing/services/buy1-get1-marketing.service.d.ts +0 -2
  184. package/dist/types/modules/marketing/services/buy1-get1-marketing.service.d.ts.map +1 -1
  185. package/dist/types/modules/marketing/services/discount-marketing.service.d.ts +0 -3
  186. package/dist/types/modules/marketing/services/discount-marketing.service.d.ts.map +1 -1
  187. package/dist/types/modules/marketing/services/marketing.service.d.ts +1 -0
  188. package/dist/types/modules/marketing/services/marketing.service.d.ts.map +1 -1
  189. package/dist/types/modules/marketing/services/product-marketing.service.d.ts +13 -2
  190. package/dist/types/modules/marketing/services/product-marketing.service.d.ts.map +1 -1
  191. package/dist/types/modules/marketing/services/synchronize-product-marketing.service.d.ts.map +1 -1
  192. package/dist/types/modules/marketing/transformers/buy1-get1-marketing.transformer.d.ts +3 -0
  193. package/dist/types/modules/marketing/transformers/buy1-get1-marketing.transformer.d.ts.map +1 -1
  194. package/dist/types/modules/marketing/transformers/discount-marketing.transformer.d.ts +3 -0
  195. package/dist/types/modules/marketing/transformers/discount-marketing.transformer.d.ts.map +1 -1
  196. package/dist/types/modules/marketing/transformers/product-marketing.transformer.d.ts +1 -0
  197. package/dist/types/modules/marketing/transformers/product-marketing.transformer.d.ts.map +1 -1
  198. package/dist/types/modules/marketing/validations/buy1-get1-marketing.validation.d.ts +30 -0
  199. package/dist/types/modules/marketing/validations/buy1-get1-marketing.validation.d.ts.map +1 -1
  200. package/dist/types/modules/marketing/validations/discount-marketing.validation.d.ts +45 -9
  201. package/dist/types/modules/marketing/validations/discount-marketing.validation.d.ts.map +1 -1
  202. package/dist/types/modules/marketing/validations/product-marketing.validation.d.ts +77 -0
  203. package/dist/types/modules/marketing/validations/product-marketing.validation.d.ts.map +1 -1
  204. package/dist/types/modules/punch-marketing-history/routers/punch-marketing-history.router.d.ts.map +1 -1
  205. package/package.json +2 -2
  206. package/dist/lib/events/event-initializations.d.ts +0 -2
  207. package/dist/lib/events/event-initializations.d.ts.map +0 -1
  208. package/dist/lib/events/event-initializations.js +0 -5
  209. package/dist/lib/events/event-initializations.js.map +0 -1
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.ltoCampaignService = exports.LtoCampaignService = void 0;
46
+ const typedi_1 = __importStar(require("typedi"));
47
+ const models_1 = require("@lyxa.ai/core/dist/libraries/mongo/models");
48
+ const enum_1 = require("@lyxa.ai/core/dist/utilities/enum");
49
+ const error_common_1 = require("@lyxa.ai/core/dist/utilities/error-common");
50
+ const limited_time_offer_campaign_lifecycle_service_1 = require("./limited-time-offer-campaign-lifecycle.service");
51
+ const limited_time_offer_campaign_scheduler_service_1 = require("./limited-time-offer-campaign-scheduler.service");
52
+ const limited_time_offer_participant_marketing_service_1 = require("../../../limited-time-offer/participant/services/limited-time-offer-participant-marketing.service");
53
+ const ACTIVE_STATUSES = [enum_1.LimitedTimeOfferCampaignStatus.SCHEDULED, enum_1.LimitedTimeOfferCampaignStatus.ACTIVE];
54
+ const ARCHIVED_STATUSES = [enum_1.LimitedTimeOfferCampaignStatus.EXPIRED, enum_1.LimitedTimeOfferCampaignStatus.CANCELLED];
55
+ let LtoCampaignService = class LtoCampaignService {
56
+ model;
57
+ scheduler;
58
+ lifecycle;
59
+ participantMarketing;
60
+ constructor() {
61
+ this.model = models_1.LimitedTimeOfferCampaignModel;
62
+ this.scheduler = typedi_1.default.get(limited_time_offer_campaign_scheduler_service_1.LtoCampaignSchedulerService);
63
+ this.lifecycle = typedi_1.default.get(limited_time_offer_campaign_lifecycle_service_1.LtoCampaignLifecycleService);
64
+ this.participantMarketing = typedi_1.default.get(limited_time_offer_participant_marketing_service_1.LtoParticipantMarketingService);
65
+ }
66
+ async create(dto) {
67
+ await this.assertNoCampaignRunning();
68
+ const now = new Date();
69
+ const config = await this.loadConfigSnapshot();
70
+ const status = dto.startDate <= now
71
+ ? enum_1.LimitedTimeOfferCampaignStatus.ACTIVE
72
+ : enum_1.LimitedTimeOfferCampaignStatus.SCHEDULED;
73
+ const campaign = await this.model.create({
74
+ campaignNumber: await this.nextCampaignNumber(),
75
+ title: dto.title,
76
+ subTitle: dto.subTitle,
77
+ startDate: dto.startDate,
78
+ endDate: dto.endDate,
79
+ status,
80
+ discountOptions: config.discountOptions,
81
+ maxDiscountCaps: config.maxDiscountCaps,
82
+ });
83
+ const campaignId = campaign._id;
84
+ if (status === enum_1.LimitedTimeOfferCampaignStatus.SCHEDULED) {
85
+ await this.scheduler.scheduleActivation(campaignId, dto.startDate);
86
+ }
87
+ await this.scheduler.scheduleExpiry(campaignId, dto.endDate);
88
+ return campaign.toObject();
89
+ }
90
+ async getCurrent() {
91
+ const campaign = await this.model
92
+ .findOne({ status: { $in: ACTIVE_STATUSES } })
93
+ .sort({ createdAt: -1 });
94
+ return campaign ? campaign.toObject() : null;
95
+ }
96
+ async getActiveCampaign() {
97
+ const campaign = await this.model
98
+ .findOne({ status: enum_1.LimitedTimeOfferCampaignStatus.ACTIVE })
99
+ .sort({ createdAt: -1 });
100
+ return campaign ? campaign.toObject() : null;
101
+ }
102
+ async getById(campaignId) {
103
+ const campaign = await this.model.findById(campaignId);
104
+ if (!campaign)
105
+ throw (0, error_common_1.notFoundError)('Campaign not found');
106
+ return campaign.toObject();
107
+ }
108
+ async getHistory(dto) {
109
+ const query = dto.status
110
+ ? { status: dto.status }
111
+ : { status: { $in: ARCHIVED_STATUSES } };
112
+ const sortFieldMap = {
113
+ id: '_id',
114
+ campaignNumber: 'campaignNumber',
115
+ startDateTime: 'startDate',
116
+ endDateTime: 'endDate',
117
+ shopsJoined: 'shopsJoined',
118
+ status: 'status',
119
+ };
120
+ const sortField = dto.sortBy ? sortFieldMap[dto.sortBy] : 'createdAt';
121
+ const sortDirection = dto.sortOrder === 'asc' ? 1 : -1;
122
+ const participantCollection = models_1.LimitedTimeOfferParticipantModel.collection.name;
123
+ const [total, documents] = await Promise.all([
124
+ this.model.countDocuments(query),
125
+ this.model.aggregate([
126
+ { $match: query },
127
+ {
128
+ $lookup: {
129
+ from: participantCollection,
130
+ let: { campaignId: '$_id' },
131
+ pipeline: [
132
+ {
133
+ $match: {
134
+ $expr: {
135
+ $and: [
136
+ { $eq: ['$campaign', '$$campaignId'] },
137
+ { $eq: ['$isWithdrawn', false] },
138
+ ],
139
+ },
140
+ },
141
+ },
142
+ { $count: 'count' },
143
+ ],
144
+ as: 'joinedStats',
145
+ },
146
+ },
147
+ {
148
+ $addFields: {
149
+ shopsJoined: { $ifNull: [{ $arrayElemAt: ['$joinedStats.count', 0] }, 0] },
150
+ },
151
+ },
152
+ { $sort: { [sortField]: sortDirection, _id: sortDirection } },
153
+ {
154
+ $project: {
155
+ _id: 1,
156
+ campaignNumber: 1,
157
+ startDate: 1,
158
+ endDate: 1,
159
+ status: 1,
160
+ shopsJoined: 1,
161
+ },
162
+ },
163
+ { $skip: (dto.page - 1) * dto.size },
164
+ { $limit: dto.size },
165
+ ]),
166
+ ]);
167
+ return {
168
+ documents: documents.map(d => ({
169
+ id: d._id.toString(),
170
+ campaignNumber: d.campaignNumber,
171
+ startDateTime: d.startDate,
172
+ endDateTime: d.endDate,
173
+ shopsJoined: d.shopsJoined,
174
+ status: d.status,
175
+ })),
176
+ metadata: { page: dto.page, size: dto.size, totalElements: total, totalPages: Math.ceil(total / dto.size) },
177
+ };
178
+ }
179
+ async update(dto) {
180
+ const campaign = await this.model.findById(dto._id);
181
+ if (!campaign)
182
+ throw (0, error_common_1.notFoundError)('Campaign not found');
183
+ this.assertUpdateAllowed(campaign, dto);
184
+ const updates = this.buildCampaignUpdates(campaign, dto);
185
+ if (this.shouldExpireImmediately(campaign.status, dto.endDate)) {
186
+ return this.applyImmediateExpiry(dto._id, updates);
187
+ }
188
+ const result = await this.model.findByIdAndUpdate(dto._id, { $set: updates }, { new: true });
189
+ if (!result)
190
+ throw (0, error_common_1.notFoundError)('Campaign not found after update');
191
+ await this.rescheduleIfDatesChanged(dto._id, result.status, campaign, dto);
192
+ return result.toObject();
193
+ }
194
+ async cancel(campaignId) {
195
+ const campaign = await this.model.findById(campaignId);
196
+ if (!campaign)
197
+ throw (0, error_common_1.notFoundError)('Campaign not found');
198
+ this.assertEditable(campaign.status);
199
+ await this.scheduler.cancelJobs(campaignId);
200
+ if (campaign.status === enum_1.LimitedTimeOfferCampaignStatus.ACTIVE) {
201
+ await this.participantMarketing.removeAllCampaignMarketings(campaignId);
202
+ }
203
+ await this.lifecycle.cancelCampaign(campaignId);
204
+ }
205
+ async getParticipants(dto) {
206
+ const query = { campaign: dto.campaignId, isWithdrawn: false };
207
+ const search = dto.search?.trim();
208
+ if (search) {
209
+ const matchingShops = await models_1.ShopModel.find({ name: { $regex: search, $options: 'i' } }).select('_id');
210
+ const matchingShopIds = matchingShops.map(shop => shop._id);
211
+ if (matchingShopIds.length === 0) {
212
+ return {
213
+ documents: [],
214
+ metadata: { page: dto.page, size: dto.size, totalElements: 0, totalPages: 0 },
215
+ };
216
+ }
217
+ query.shop = { $in: matchingShopIds };
218
+ }
219
+ const [total, participants] = await Promise.all([
220
+ models_1.LimitedTimeOfferParticipantModel.countDocuments(query),
221
+ models_1.LimitedTimeOfferParticipantModel.find(query)
222
+ .populate('shop', 'name logo')
223
+ .sort({ joinedAt: -1 })
224
+ .skip((dto.page - 1) * dto.size)
225
+ .limit(dto.size),
226
+ ]);
227
+ return {
228
+ documents: participants.map(p => {
229
+ const raw = p.toObject();
230
+ return {
231
+ shopName: raw.shop?.name ?? null,
232
+ shopPhoto: raw.shop?.logo ?? null,
233
+ joinedAt: raw.joinedAt,
234
+ discountPercentage: raw.discountPercentage,
235
+ maxDiscountCap: raw.maxDiscountCap,
236
+ };
237
+ }),
238
+ metadata: { page: dto.page, size: dto.size, totalElements: total, totalPages: Math.ceil(total / dto.size) },
239
+ };
240
+ }
241
+ assertUpdateAllowed(campaign, dto) {
242
+ this.assertEditable(campaign.status);
243
+ if (campaign.status === enum_1.LimitedTimeOfferCampaignStatus.ACTIVE && !dto.confirmActive) {
244
+ throw (0, error_common_1.badRequestError)('Set confirmActive=true to confirm editing a live campaign.');
245
+ }
246
+ if (dto.startDate < new Date() && campaign.status === enum_1.LimitedTimeOfferCampaignStatus.SCHEDULED) {
247
+ throw (0, error_common_1.badRequestError)('Start date cannot be in the past.');
248
+ }
249
+ }
250
+ buildCampaignUpdates(campaign, dto) {
251
+ return {
252
+ title: dto.title ?? campaign.title,
253
+ subTitle: dto.subTitle ?? campaign.subTitle,
254
+ startDate: dto.startDate,
255
+ endDate: dto.endDate,
256
+ ...(dto.discountOptions && { discountOptions: dto.discountOptions }),
257
+ ...(dto.maxDiscountCaps && { maxDiscountCaps: dto.maxDiscountCaps }),
258
+ };
259
+ }
260
+ shouldExpireImmediately(status, endDate) {
261
+ return status === enum_1.LimitedTimeOfferCampaignStatus.ACTIVE && endDate <= new Date();
262
+ }
263
+ async applyImmediateExpiry(campaignId, updates) {
264
+ await this.scheduler.cancelJobs(campaignId);
265
+ await this.model.findByIdAndUpdate(campaignId, { $set: updates });
266
+ await this.lifecycle.expireCampaign(campaignId);
267
+ return (await this.model.findById(campaignId)).toObject();
268
+ }
269
+ async rescheduleIfDatesChanged(campaignId, currentStatus, original, dto) {
270
+ const datesChanged = dto.startDate.getTime() !== original.startDate.getTime() ||
271
+ dto.endDate.getTime() !== original.endDate.getTime();
272
+ if (!datesChanged)
273
+ return;
274
+ await this.scheduler.cancelJobs(campaignId);
275
+ if (currentStatus === enum_1.LimitedTimeOfferCampaignStatus.SCHEDULED) {
276
+ await this.scheduler.scheduleActivation(campaignId, dto.startDate);
277
+ }
278
+ await this.scheduler.scheduleExpiry(campaignId, dto.endDate);
279
+ }
280
+ async assertNoCampaignRunning() {
281
+ const exists = await this.model.exists({ status: { $in: ACTIVE_STATUSES } });
282
+ if (exists)
283
+ throw (0, error_common_1.conflictError)('A campaign is already scheduled or active. Delete it before creating a new one.');
284
+ }
285
+ assertEditable(status) {
286
+ if (!ACTIVE_STATUSES.includes(status)) {
287
+ throw (0, error_common_1.badRequestError)('Only SCHEDULED or ACTIVE campaigns can be modified.');
288
+ }
289
+ }
290
+ async loadConfigSnapshot() {
291
+ const config = await models_1.LimitedTimeOfferConfigModel.findOne({ campaignType: enum_1.MarketingType.DISCOUNT });
292
+ if (!config || config.discountOptions.length === 0 || config.maxDiscountCaps.length === 0) {
293
+ throw (0, error_common_1.badRequestError)('Global config is incomplete. Set discount options and max caps first.');
294
+ }
295
+ return config;
296
+ }
297
+ async nextCampaignNumber() {
298
+ const counter = await models_1.CounterModel.findOneAndUpdate({ counterType: enum_1.CounterType.LTO_CAMPAIGN }, { $inc: { value: 1 } }, { upsert: true, new: true, setDefaultsOnInsert: true });
299
+ return counter.value;
300
+ }
301
+ };
302
+ exports.LtoCampaignService = LtoCampaignService;
303
+ exports.LtoCampaignService = LtoCampaignService = __decorate([
304
+ (0, typedi_1.Service)(),
305
+ __metadata("design:paramtypes", [])
306
+ ], LtoCampaignService);
307
+ exports.ltoCampaignService = typedi_1.default.get(LtoCampaignService);
308
+ //# sourceMappingURL=limited-time-offer-campaign.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limited-time-offer-campaign.service.js","sourceRoot":"/","sources":["modules/limited-time-offer/campaign/services/limited-time-offer-campaign.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAA0C;AAE1C,sEAOmD;AAEnD,4DAA6G;AAC7G,4EAAwG;AAOxG,mHAA4F;AAC5F,mHAA4F;AAC5F,wKAAiJ;AAEjJ,MAAM,eAAe,GAAG,CAAC,qCAA8B,CAAC,SAAS,EAAE,qCAA8B,CAAC,MAAM,CAAC,CAAC;AAC1G,MAAM,iBAAiB,GAAG,CAAC,qCAA8B,CAAC,OAAO,EAAE,qCAA8B,CAAC,SAAS,CAAC,CAAC;AAGtG,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IACnB,KAAK,CAAgE;IACrE,SAAS,CAA8B;IACvC,SAAS,CAA8B;IACvC,oBAAoB,CAAiC;IAE7D;QACI,IAAI,CAAC,KAAK,GAAG,sCAA8F,CAAC;QAC5G,IAAI,CAAC,SAAS,GAAG,gBAAS,CAAC,GAAG,CAAC,2EAA2B,CAAC,CAAC;QAC5D,IAAI,CAAC,SAAS,GAAG,gBAAS,CAAC,GAAG,CAAC,2EAA2B,CAAC,CAAC;QAC5D,IAAI,CAAC,oBAAoB,GAAG,gBAAS,CAAC,GAAG,CAAC,iFAA8B,CAAC,CAAC;IAC9E,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,GAAyB;QACzC,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAErC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QAEvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,IAAI,GAAG;YAC/B,CAAC,CAAC,qCAA8B,CAAC,MAAM;YACvC,CAAC,CAAC,qCAA8B,CAAC,SAAS,CAAC;QAE/C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;YACrC,cAAc,EAAE,MAAM,IAAI,CAAC,kBAAkB,EAAE;YAC/C,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,MAAM;YACN,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,eAAe,EAAE,MAAM,CAAC,eAAe;SAC1C,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC;QAChC,IAAI,MAAM,KAAK,qCAA8B,CAAC,SAAS,EAAE,CAAC;YACtD,MAAM,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAE7D,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAEM,KAAK,CAAC,UAAU;QACnB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK;aAC5B,OAAO,CAAC,EAAC,MAAM,EAAE,EAAC,GAAG,EAAE,eAAe,EAAC,EAAC,CAAC;aACzC,IAAI,CAAC,EAAC,SAAS,EAAE,CAAC,CAAC,EAAC,CAAC,CAAC;QAC3B,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IAEM,KAAK,CAAC,iBAAiB;QAC1B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK;aAC5B,OAAO,CAAC,EAAC,MAAM,EAAE,qCAA8B,CAAC,MAAM,EAAC,CAAC;aACxD,IAAI,CAAC,EAAC,SAAS,EAAE,CAAC,CAAC,EAAC,CAAC,CAAC;QAC3B,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,UAAmC;QACpD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAA,4BAAa,EAAC,oBAAoB,CAAC,CAAC;QACzD,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,GAA6B;QACjD,MAAM,KAAK,GAAwB,GAAG,CAAC,MAAM;YACzC,CAAC,CAAC,EAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAC;YACtB,CAAC,CAAC,EAAC,MAAM,EAAE,EAAC,GAAG,EAAE,iBAAiB,EAAC,EAAC,CAAC;QACzC,MAAM,YAAY,GAA2B;YACzC,EAAE,EAAE,KAAK;YACT,cAAc,EAAE,gBAAgB;YAChC,aAAa,EAAE,WAAW;YAC1B,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,aAAa;YAC1B,MAAM,EAAE,QAAQ;SACnB,CAAC;QACF,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QACtE,MAAM,aAAa,GAAG,GAAG,CAAC,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,qBAAqB,GAAG,yCAAgC,CAAC,UAAU,CAAC,IAAI,CAAC;QAC/E,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACzC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;gBACjB,EAAC,MAAM,EAAE,KAAK,EAAC;gBACf;oBACI,OAAO,EAAE;wBACL,IAAI,EAAE,qBAAqB;wBAC3B,GAAG,EAAE,EAAC,UAAU,EAAE,MAAM,EAAC;wBACzB,QAAQ,EAAE;4BACN;gCACI,MAAM,EAAE;oCACJ,KAAK,EAAE;wCACH,IAAI,EAAE;4CACF,EAAC,GAAG,EAAE,CAAC,WAAW,EAAE,cAAc,CAAC,EAAC;4CACpC,EAAC,GAAG,EAAE,CAAC,cAAc,EAAE,KAAK,CAAC,EAAC;yCACjC;qCACJ;iCACJ;6BACJ;4BACD,EAAC,MAAM,EAAE,OAAO,EAAC;yBACpB;wBACD,EAAE,EAAE,aAAa;qBACpB;iBACJ;gBACD;oBACI,UAAU,EAAE;wBACR,WAAW,EAAE,EAAC,OAAO,EAAE,CAAC,EAAC,YAAY,EAAE,CAAC,oBAAoB,EAAE,CAAC,CAAC,EAAC,EAAE,CAAC,CAAC,EAAC;qBACzE;iBACJ;gBACD,EAAC,KAAK,EAAE,EAAC,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,aAAa,EAAC,EAAC;gBACzD;oBACI,QAAQ,EAAE;wBACN,GAAG,EAAE,CAAC;wBACN,cAAc,EAAE,CAAC;wBACjB,SAAS,EAAE,CAAC;wBACZ,OAAO,EAAE,CAAC;wBACV,MAAM,EAAE,CAAC;wBACT,WAAW,EAAE,CAAC;qBACjB;iBACJ;gBACD,EAAC,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,EAAC;gBAClC,EAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAC;aACrB,CAAC;SACL,CAAC,CAAC;QAEH,OAAO;YACH,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC3B,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACpB,cAAc,EAAE,CAAC,CAAC,cAAc;gBAChC,aAAa,EAAE,CAAC,CAAC,SAAS;gBAC1B,WAAW,EAAE,CAAC,CAAC,OAAO;gBACtB,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,MAAM,EAAE,CAAC,CAAC,MAAM;aACnB,CAAC,CAAC;YACH,QAAQ,EAAE,EAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,EAAC;SAC5G,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,GAAyB;QACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAA,4BAAa,EAAC,oBAAoB,CAAC,CAAC;QAEzD,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAExC,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAEzD,IAAI,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7D,OAAO,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,EAAC,IAAI,EAAE,OAAO,EAAC,EAAE,EAAC,GAAG,EAAE,IAAI,EAAC,CAAC,CAAC;QACzF,IAAI,CAAC,MAAM;YAAE,MAAM,IAAA,4BAAa,EAAC,iCAAiC,CAAC,CAAC;QAEpE,MAAM,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;QAE3E,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,UAAmC;QACnD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAA,4BAAa,EAAC,oBAAoB,CAAC,CAAC;QAEzD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAE5C,IAAI,QAAQ,CAAC,MAAM,KAAK,qCAA8B,CAAC,MAAM,EAAE,CAAC;YAC5D,MAAM,IAAI,CAAC,oBAAoB,CAAC,2BAA2B,CAAC,UAAU,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC;IAEM,KAAK,CAAC,eAAe,CAAC,GAAkC;QAC3D,MAAM,KAAK,GAAwB,EAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,EAAC,CAAC;QAClF,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;QAElC,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,aAAa,GAAG,MAAM,kBAAS,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAC,EAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAClG,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAE5D,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,OAAO;oBACH,SAAS,EAAE,EAAE;oBACb,QAAQ,EAAE,EAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAC;iBAC9E,CAAC;YACN,CAAC;YAED,KAAK,CAAC,IAAI,GAAG,EAAC,GAAG,EAAE,eAAe,EAAC,CAAC;QACxC,CAAC;QAED,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC5C,yCAAgC,CAAC,cAAc,CAAC,KAAK,CAAC;YACtD,yCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC;iBACvC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;iBAC7B,IAAI,CAAC,EAAC,QAAQ,EAAE,CAAC,CAAC,EAAC,CAAC;iBACpB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC;iBAC/B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;SACvB,CAAC,CAAC;QAEH,OAAO;YACH,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBAC5B,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAS,CAAC;gBAChC,OAAO;oBACH,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,IAAI;oBAChC,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,IAAI;oBACjC,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,kBAAkB,EAAE,GAAG,CAAC,kBAAkB;oBAC1C,cAAc,EAAE,GAAG,CAAC,cAAc;iBACrC,CAAC;YACN,CAAC,CAAC;YACF,QAAQ,EAAE,EAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,EAAC;SAC5G,CAAC;IACN,CAAC;IAEO,mBAAmB,CAAC,QAAe,EAAE,GAAyB;QAClE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAErC,IAAI,QAAQ,CAAC,MAAM,KAAK,qCAA8B,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YAClF,MAAM,IAAA,8BAAe,EAAC,4DAA4D,CAAC,CAAC;QACxF,CAAC;QAED,IAAI,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,IAAI,QAAQ,CAAC,MAAM,KAAK,qCAA8B,CAAC,SAAS,EAAE,CAAC;YAC7F,MAAM,IAAA,8BAAe,EAAC,mCAAmC,CAAC,CAAC;QAC/D,CAAC;IACL,CAAC;IAEO,oBAAoB,CAAC,QAAe,EAAE,GAAyB;QACnE,OAAO;YACH,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK;YAClC,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ;YAC3C,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,EAAC,eAAe,EAAE,GAAG,CAAC,eAAe,EAAC,CAAC;YAClE,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,EAAC,eAAe,EAAE,GAAG,CAAC,eAAe,EAAC,CAAC;SACrE,CAAC;IACN,CAAC;IAEO,uBAAuB,CAAC,MAAsC,EAAE,OAAa;QACjF,OAAO,MAAM,KAAK,qCAA8B,CAAC,MAAM,IAAI,OAAO,IAAI,IAAI,IAAI,EAAE,CAAC;IACrF,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,UAAmC,EAAE,OAA4B;QAChG,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,UAAU,EAAE,EAAC,IAAI,EAAE,OAAO,EAAC,CAAC,CAAC;QAChE,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAChD,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAE,CAAC,QAAQ,EAAE,CAAC;IAC/D,CAAC;IAEO,KAAK,CAAC,wBAAwB,CAClC,UAAmC,EACnC,aAA6C,EAC7C,QAAe,EACf,GAAyB;QAEzB,MAAM,YAAY,GACd,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE;YACxD,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAEzD,IAAI,CAAC,YAAY;YAAE,OAAO;QAE1B,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,aAAa,KAAK,qCAA8B,CAAC,SAAS,EAAE,CAAC;YAC7D,MAAM,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACjE,CAAC;IAEO,KAAK,CAAC,uBAAuB;QACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAC,MAAM,EAAE,EAAC,GAAG,EAAE,eAAe,EAAC,EAAC,CAAC,CAAC;QACzE,IAAI,MAAM;YAAE,MAAM,IAAA,4BAAa,EAAC,iFAAiF,CAAC,CAAC;IACvH,CAAC;IAEO,cAAc,CAAC,MAAsC;QACzD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,MAAM,IAAA,8BAAe,EAAC,qDAAqD,CAAC,CAAC;QACjF,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC5B,MAAM,MAAM,GAAG,MAAM,oCAA2B,CAAC,OAAO,CAAC,EAAC,YAAY,EAAE,oBAAa,CAAC,QAAQ,EAAC,CAAC,CAAC;QACjG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxF,MAAM,IAAA,8BAAe,EAAC,uEAAuE,CAAC,CAAC;QACnG,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC5B,MAAM,OAAO,GAAG,MAAM,qBAAY,CAAC,gBAAgB,CAC/C,EAAC,WAAW,EAAE,kBAAW,CAAC,YAAY,EAAC,EACvC,EAAC,IAAI,EAAE,EAAC,KAAK,EAAE,CAAC,EAAC,EAAC,EAClB,EAAC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAC,CACvD,CAAC;QACF,OAAO,OAAO,CAAC,KAAK,CAAC;IACzB,CAAC;CACJ,CAAA;AApSY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,gBAAO,GAAE;;GACG,kBAAkB,CAoS9B;AAEY,QAAA,kBAAkB,GAAG,gBAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC","sourcesContent":["import Container, {Service} from 'typedi';\nimport {mongoose} from '@typegoose/typegoose';\nimport {\n CounterModel,\n LimitedTimeOfferCampaign as Model,\n LimitedTimeOfferCampaignModel,\n LimitedTimeOfferConfigModel,\n LimitedTimeOfferParticipantModel,\n ShopModel,\n} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {SoftDeleteModel} from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport {CounterType, LimitedTimeOfferCampaignStatus, MarketingType} from '@lyxa.ai/core/dist/utilities/enum';\nimport {badRequestError, conflictError, notFoundError} from '@lyxa.ai/core/dist/utilities/error-common';\nimport {\n CreateLtoCampaignDTO,\n GetLtoCampaignHistoryDTO,\n GetLtoCampaignParticipantsDTO,\n UpdateLtoCampaignDTO,\n} from '../limited-time-offer-campaign.validation';\nimport {LtoCampaignLifecycleService} from './limited-time-offer-campaign-lifecycle.service';\nimport {LtoCampaignSchedulerService} from './limited-time-offer-campaign-scheduler.service';\nimport {LtoParticipantMarketingService} from '@modules/limited-time-offer/participant/services/limited-time-offer-participant-marketing.service';\n\nconst ACTIVE_STATUSES = [LimitedTimeOfferCampaignStatus.SCHEDULED, LimitedTimeOfferCampaignStatus.ACTIVE];\nconst ARCHIVED_STATUSES = [LimitedTimeOfferCampaignStatus.EXPIRED, LimitedTimeOfferCampaignStatus.CANCELLED];\n\n@Service()\nexport class LtoCampaignService {\n private model: typeof LimitedTimeOfferCampaignModel & SoftDeleteModel<Model>;\n private scheduler: LtoCampaignSchedulerService;\n private lifecycle: LtoCampaignLifecycleService;\n private participantMarketing: LtoParticipantMarketingService;\n\n constructor() {\n this.model = LimitedTimeOfferCampaignModel as typeof LimitedTimeOfferCampaignModel & SoftDeleteModel<Model>;\n this.scheduler = Container.get(LtoCampaignSchedulerService);\n this.lifecycle = Container.get(LtoCampaignLifecycleService);\n this.participantMarketing = Container.get(LtoParticipantMarketingService);\n }\n\n public async create(dto: CreateLtoCampaignDTO) {\n await this.assertNoCampaignRunning();\n\n const now = new Date();\n\n const config = await this.loadConfigSnapshot();\n const status = dto.startDate <= now\n ? LimitedTimeOfferCampaignStatus.ACTIVE\n : LimitedTimeOfferCampaignStatus.SCHEDULED;\n\n const campaign = await this.model.create({\n campaignNumber: await this.nextCampaignNumber(),\n title: dto.title,\n subTitle: dto.subTitle,\n startDate: dto.startDate,\n endDate: dto.endDate,\n status,\n discountOptions: config.discountOptions,\n maxDiscountCaps: config.maxDiscountCaps,\n });\n\n const campaignId = campaign._id;\n if (status === LimitedTimeOfferCampaignStatus.SCHEDULED) {\n await this.scheduler.scheduleActivation(campaignId, dto.startDate);\n }\n await this.scheduler.scheduleExpiry(campaignId, dto.endDate);\n\n return campaign.toObject();\n }\n\n public async getCurrent() {\n const campaign = await this.model\n .findOne({status: {$in: ACTIVE_STATUSES}})\n .sort({createdAt: -1});\n return campaign ? campaign.toObject() : null;\n }\n\n public async getActiveCampaign() {\n const campaign = await this.model\n .findOne({status: LimitedTimeOfferCampaignStatus.ACTIVE})\n .sort({createdAt: -1});\n return campaign ? campaign.toObject() : null;\n }\n\n public async getById(campaignId: mongoose.Types.ObjectId) {\n const campaign = await this.model.findById(campaignId);\n if (!campaign) throw notFoundError('Campaign not found');\n return campaign.toObject();\n }\n\n public async getHistory(dto: GetLtoCampaignHistoryDTO) {\n const query: Record<string, any> = dto.status\n ? {status: dto.status}\n : {status: {$in: ARCHIVED_STATUSES}};\n const sortFieldMap: Record<string, string> = {\n id: '_id',\n campaignNumber: 'campaignNumber',\n startDateTime: 'startDate',\n endDateTime: 'endDate',\n shopsJoined: 'shopsJoined',\n status: 'status',\n };\n const sortField = dto.sortBy ? sortFieldMap[dto.sortBy] : 'createdAt';\n const sortDirection = dto.sortOrder === 'asc' ? 1 : -1;\n const participantCollection = LimitedTimeOfferParticipantModel.collection.name;\n const [total, documents] = await Promise.all([\n this.model.countDocuments(query),\n this.model.aggregate([\n {$match: query},\n {\n $lookup: {\n from: participantCollection,\n let: {campaignId: '$_id'},\n pipeline: [\n {\n $match: {\n $expr: {\n $and: [\n {$eq: ['$campaign', '$$campaignId']},\n {$eq: ['$isWithdrawn', false]},\n ],\n },\n },\n },\n {$count: 'count'},\n ],\n as: 'joinedStats',\n },\n },\n {\n $addFields: {\n shopsJoined: {$ifNull: [{$arrayElemAt: ['$joinedStats.count', 0]}, 0]},\n },\n },\n {$sort: {[sortField]: sortDirection, _id: sortDirection}},\n {\n $project: {\n _id: 1,\n campaignNumber: 1,\n startDate: 1,\n endDate: 1,\n status: 1,\n shopsJoined: 1,\n },\n },\n {$skip: (dto.page - 1) * dto.size},\n {$limit: dto.size},\n ]),\n ]);\n\n return {\n documents: documents.map(d => ({\n id: d._id.toString(),\n campaignNumber: d.campaignNumber,\n startDateTime: d.startDate,\n endDateTime: d.endDate,\n shopsJoined: d.shopsJoined,\n status: d.status,\n })),\n metadata: {page: dto.page, size: dto.size, totalElements: total, totalPages: Math.ceil(total / dto.size)},\n };\n }\n\n public async update(dto: UpdateLtoCampaignDTO) {\n const campaign = await this.model.findById(dto._id);\n if (!campaign) throw notFoundError('Campaign not found');\n\n this.assertUpdateAllowed(campaign, dto);\n\n const updates = this.buildCampaignUpdates(campaign, dto);\n\n if (this.shouldExpireImmediately(campaign.status, dto.endDate)) {\n return this.applyImmediateExpiry(dto._id, updates);\n }\n\n const result = await this.model.findByIdAndUpdate(dto._id, {$set: updates}, {new: true});\n if (!result) throw notFoundError('Campaign not found after update');\n\n await this.rescheduleIfDatesChanged(dto._id, result.status, campaign, dto);\n\n return result.toObject();\n }\n\n public async cancel(campaignId: mongoose.Types.ObjectId) {\n const campaign = await this.model.findById(campaignId);\n if (!campaign) throw notFoundError('Campaign not found');\n\n this.assertEditable(campaign.status);\n await this.scheduler.cancelJobs(campaignId);\n\n if (campaign.status === LimitedTimeOfferCampaignStatus.ACTIVE) {\n await this.participantMarketing.removeAllCampaignMarketings(campaignId);\n }\n\n await this.lifecycle.cancelCampaign(campaignId);\n }\n\n public async getParticipants(dto: GetLtoCampaignParticipantsDTO) {\n const query: Record<string, any> = {campaign: dto.campaignId, isWithdrawn: false};\n const search = dto.search?.trim();\n\n if (search) {\n const matchingShops = await ShopModel.find({name: {$regex: search, $options: 'i'}}).select('_id');\n const matchingShopIds = matchingShops.map(shop => shop._id);\n\n if (matchingShopIds.length === 0) {\n return {\n documents: [],\n metadata: {page: dto.page, size: dto.size, totalElements: 0, totalPages: 0},\n };\n }\n\n query.shop = {$in: matchingShopIds};\n }\n\n const [total, participants] = await Promise.all([\n LimitedTimeOfferParticipantModel.countDocuments(query),\n LimitedTimeOfferParticipantModel.find(query)\n .populate('shop', 'name logo')\n .sort({joinedAt: -1})\n .skip((dto.page - 1) * dto.size)\n .limit(dto.size),\n ]);\n\n return {\n documents: participants.map(p => {\n const raw = p.toObject() as any;\n return {\n shopName: raw.shop?.name ?? null,\n shopPhoto: raw.shop?.logo ?? null,\n joinedAt: raw.joinedAt,\n discountPercentage: raw.discountPercentage,\n maxDiscountCap: raw.maxDiscountCap,\n };\n }),\n metadata: {page: dto.page, size: dto.size, totalElements: total, totalPages: Math.ceil(total / dto.size)},\n };\n }\n\n private assertUpdateAllowed(campaign: Model, dto: UpdateLtoCampaignDTO): void {\n this.assertEditable(campaign.status);\n\n if (campaign.status === LimitedTimeOfferCampaignStatus.ACTIVE && !dto.confirmActive) {\n throw badRequestError('Set confirmActive=true to confirm editing a live campaign.');\n }\n\n if (dto.startDate < new Date() && campaign.status === LimitedTimeOfferCampaignStatus.SCHEDULED) {\n throw badRequestError('Start date cannot be in the past.');\n }\n }\n\n private buildCampaignUpdates(campaign: Model, dto: UpdateLtoCampaignDTO): Record<string, any> {\n return {\n title: dto.title ?? campaign.title,\n subTitle: dto.subTitle ?? campaign.subTitle,\n startDate: dto.startDate,\n endDate: dto.endDate,\n ...(dto.discountOptions && {discountOptions: dto.discountOptions}),\n ...(dto.maxDiscountCaps && {maxDiscountCaps: dto.maxDiscountCaps}),\n };\n }\n\n private shouldExpireImmediately(status: LimitedTimeOfferCampaignStatus, endDate: Date): boolean {\n return status === LimitedTimeOfferCampaignStatus.ACTIVE && endDate <= new Date();\n }\n\n private async applyImmediateExpiry(campaignId: mongoose.Types.ObjectId, updates: Record<string, any>) {\n await this.scheduler.cancelJobs(campaignId);\n await this.model.findByIdAndUpdate(campaignId, {$set: updates});\n await this.lifecycle.expireCampaign(campaignId);\n return (await this.model.findById(campaignId))!.toObject();\n }\n\n private async rescheduleIfDatesChanged(\n campaignId: mongoose.Types.ObjectId,\n currentStatus: LimitedTimeOfferCampaignStatus,\n original: Model,\n dto: UpdateLtoCampaignDTO,\n ): Promise<void> {\n const datesChanged =\n dto.startDate.getTime() !== original.startDate.getTime() ||\n dto.endDate.getTime() !== original.endDate.getTime();\n\n if (!datesChanged) return;\n\n await this.scheduler.cancelJobs(campaignId);\n if (currentStatus === LimitedTimeOfferCampaignStatus.SCHEDULED) {\n await this.scheduler.scheduleActivation(campaignId, dto.startDate);\n }\n await this.scheduler.scheduleExpiry(campaignId, dto.endDate);\n }\n\n private async assertNoCampaignRunning(): Promise<void> {\n const exists = await this.model.exists({status: {$in: ACTIVE_STATUSES}});\n if (exists) throw conflictError('A campaign is already scheduled or active. Delete it before creating a new one.');\n }\n\n private assertEditable(status: LimitedTimeOfferCampaignStatus): void {\n if (!ACTIVE_STATUSES.includes(status)) {\n throw badRequestError('Only SCHEDULED or ACTIVE campaigns can be modified.');\n }\n }\n\n private async loadConfigSnapshot() {\n const config = await LimitedTimeOfferConfigModel.findOne({campaignType: MarketingType.DISCOUNT});\n if (!config || config.discountOptions.length === 0 || config.maxDiscountCaps.length === 0) {\n throw badRequestError('Global config is incomplete. Set discount options and max caps first.');\n }\n return config;\n }\n\n private async nextCampaignNumber(): Promise<number> {\n const counter = await CounterModel.findOneAndUpdate(\n {counterType: CounterType.LTO_CAMPAIGN},\n {$inc: {value: 1}},\n {upsert: true, new: true, setDefaultsOnInsert: true}\n );\n return counter.value;\n }\n}\n\nexport const ltoCampaignService = Container.get(LtoCampaignService);\n"]}
@@ -0,0 +1,12 @@
1
+ import { MarketingType } from '@lyxa.ai/core/dist/utilities/enum';
2
+ import { CreateLimitedTimeOfferConfigDTO, LimitedTimeOfferConfigDTO, UpdateLimitedTimeOfferConfigDTO } from './limited-time-offer-config.validation';
3
+ export declare class LimitedTimeOfferConfigService {
4
+ private model;
5
+ constructor();
6
+ private validateConfigUnique;
7
+ create(input: CreateLimitedTimeOfferConfigDTO): Promise<LimitedTimeOfferConfigDTO>;
8
+ getByType(campaignType: MarketingType): Promise<LimitedTimeOfferConfigDTO>;
9
+ update(input: UpdateLimitedTimeOfferConfigDTO): Promise<LimitedTimeOfferConfigDTO>;
10
+ }
11
+ export declare const limitedTimeOfferConfigService: LimitedTimeOfferConfigService;
12
+ //# sourceMappingURL=limited-time-offer-config.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limited-time-offer-config.service.d.ts","sourceRoot":"/","sources":["modules/limited-time-offer/config/limited-time-offer-config.service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,aAAa,EAAC,MAAM,mCAAmC,CAAC;AAChE,OAAO,EACH,+BAA+B,EAC/B,yBAAyB,EACzB,+BAA+B,EAClC,MAAM,wCAAwC,CAAC;AAGhD,qBACa,6BAA6B;IACtC,OAAO,CAAC,KAAK,CAA8D;;YAM7D,oBAAoB;IAOrB,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAMlF,SAAS,CAAC,YAAY,EAAE,aAAa,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAU1E,MAAM,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,yBAAyB,CAAC;CA0BlG;AAED,eAAO,MAAM,6BAA6B,+BAA+C,CAAC"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.limitedTimeOfferConfigService = exports.LimitedTimeOfferConfigService = void 0;
46
+ const typedi_1 = __importStar(require("typedi"));
47
+ const server_1 = require("@trpc/server");
48
+ const models_1 = require("@lyxa.ai/core/dist/libraries/mongo/models");
49
+ const error_common_1 = require("@lyxa.ai/core/dist/utilities/error-common");
50
+ let LimitedTimeOfferConfigService = class LimitedTimeOfferConfigService {
51
+ model;
52
+ constructor() {
53
+ this.model = models_1.LimitedTimeOfferConfigModel;
54
+ }
55
+ async validateConfigUnique(marketingType) {
56
+ const exists = await this.model.exists({ campaignType: marketingType });
57
+ if (exists) {
58
+ throw (0, error_common_1.conflictError)("Config for this campaign type already exists. Use update instead.");
59
+ }
60
+ }
61
+ async create(input) {
62
+ await this.validateConfigUnique(input.campaignType);
63
+ const result = await this.model.create(input);
64
+ return result.toObject();
65
+ }
66
+ async getByType(campaignType) {
67
+ const result = await this.model.findOne({ campaignType });
68
+ if (!result) {
69
+ throw (0, error_common_1.notFoundError)("Config not found");
70
+ }
71
+ return result.toObject();
72
+ }
73
+ async update(input) {
74
+ if (input.discountOptions.length === 0 || input.maxDiscountCaps.length === 0) {
75
+ throw (0, error_common_1.badRequestError)("At least one discount option and one max discount cap are required");
76
+ }
77
+ const oldConfig = await this.model.findById(input._id);
78
+ if (!oldConfig) {
79
+ throw (0, error_common_1.notFoundError)("Config not found");
80
+ }
81
+ const result = await this.model.findByIdAndUpdate(input._id, { $set: { discountOptions: input.discountOptions, maxDiscountCaps: input.maxDiscountCaps } }, { new: true });
82
+ if (!result) {
83
+ throw new server_1.TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to update config' });
84
+ }
85
+ return result.toObject();
86
+ }
87
+ };
88
+ exports.LimitedTimeOfferConfigService = LimitedTimeOfferConfigService;
89
+ exports.LimitedTimeOfferConfigService = LimitedTimeOfferConfigService = __decorate([
90
+ (0, typedi_1.Service)(),
91
+ __metadata("design:paramtypes", [])
92
+ ], LimitedTimeOfferConfigService);
93
+ exports.limitedTimeOfferConfigService = typedi_1.default.get(LimitedTimeOfferConfigService);
94
+ //# sourceMappingURL=limited-time-offer-config.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limited-time-offer-config.service.js","sourceRoot":"/","sources":["modules/limited-time-offer/config/limited-time-offer-config.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAA0C;AAC1C,yCAAuC;AACvC,sEAAuH;AAQvH,4EAAwG;AAGjG,IAAM,6BAA6B,GAAnC,MAAM,6BAA6B;IAC9B,KAAK,CAA8D;IAE3E;QACI,IAAI,CAAC,KAAK,GAAG,oCAA0F,CAAC;IAC5G,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,aAA4B;QAC3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAC,YAAY,EAAE,aAAa,EAAC,CAAC,CAAC;QACtE,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,IAAA,4BAAa,EAAC,mEAAmE,CAAC,CAAA;QAC5F,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,KAAsC;QACtD,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAEM,KAAK,CAAC,SAAS,CAAC,YAA2B;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAC,YAAY,EAAC,CAAC,CAAC;QAExD,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,IAAA,4BAAa,EAAC,kBAAkB,CAAC,CAAA;QAC3C,CAAC;QAED,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IAEM,KAAK,CAAC,MAAM,CAAC,KAAsC;QAEtD,IAAI,KAAK,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3E,MAAM,IAAA,8BAAe,EAAC,oEAAoE,CAAC,CAAA;QAC/F,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC,SAAS,EAAE,CAAC;YACb,MAAM,IAAA,4BAAa,EAAC,kBAAkB,CAAC,CAAA;QAC3C,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAC7C,KAAK,CAAC,GAAG,EACT,EAAC,IAAI,EAAE,EAAC,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAC,EAAC,EACxF,EAAC,GAAG,EAAE,IAAI,EAAC,CACd,CAAC;QAEF,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,IAAI,kBAAS,CAAC,EAAC,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,yBAAyB,EAAC,CAAC,CAAC;QAC7F,CAAC;QAED,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;CAIJ,CAAA;AAxDY,sEAA6B;wCAA7B,6BAA6B;IADzC,IAAA,gBAAO,GAAE;;GACG,6BAA6B,CAwDzC;AAEY,QAAA,6BAA6B,GAAG,gBAAS,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC","sourcesContent":["import Container, {Service} from 'typedi';\nimport {TRPCError} from '@trpc/server';\nimport {LimitedTimeOfferConfig as Model, LimitedTimeOfferConfigModel} from '@lyxa.ai/core/dist/libraries/mongo/models';\nimport {SoftDeleteModel} from '@lyxa.ai/core/dist/libraries/mongo/plugins/soft-delete-plugin';\nimport {MarketingType} from '@lyxa.ai/core/dist/utilities/enum';\nimport {\n CreateLimitedTimeOfferConfigDTO,\n LimitedTimeOfferConfigDTO,\n UpdateLimitedTimeOfferConfigDTO\n} from './limited-time-offer-config.validation';\nimport {badRequestError, conflictError, notFoundError} from '@lyxa.ai/core/dist/utilities/error-common';\n\n@Service()\nexport class LimitedTimeOfferConfigService {\n private model: typeof LimitedTimeOfferConfigModel & SoftDeleteModel<Model>;\n\n constructor() {\n this.model = LimitedTimeOfferConfigModel as typeof LimitedTimeOfferConfigModel & SoftDeleteModel<Model>;\n }\n\n private async validateConfigUnique(marketingType: MarketingType) {\n const exists = await this.model.exists({campaignType: marketingType});\n if (exists) {\n throw conflictError(\"Config for this campaign type already exists. Use update instead.\")\n }\n }\n\n public async create(input: CreateLimitedTimeOfferConfigDTO): Promise<LimitedTimeOfferConfigDTO> {\n await this.validateConfigUnique(input.campaignType);\n const result = await this.model.create(input);\n return result.toObject();\n }\n\n public async getByType(campaignType: MarketingType): Promise<LimitedTimeOfferConfigDTO> {\n const result = await this.model.findOne({campaignType});\n\n if (!result) {\n throw notFoundError(\"Config not found\")\n }\n\n return result.toObject();\n }\n\n public async update(input: UpdateLimitedTimeOfferConfigDTO): Promise<LimitedTimeOfferConfigDTO> {\n\n if (input.discountOptions.length === 0 || input.maxDiscountCaps.length === 0) {\n throw badRequestError(\"At least one discount option and one max discount cap are required\")\n }\n\n const oldConfig = await this.model.findById(input._id);\n if (!oldConfig) {\n throw notFoundError(\"Config not found\")\n }\n\n const result = await this.model.findByIdAndUpdate(\n input._id,\n {$set: {discountOptions: input.discountOptions, maxDiscountCaps: input.maxDiscountCaps}},\n {new: true}\n );\n\n if (!result) {\n throw new TRPCError({code: 'INTERNAL_SERVER_ERROR', message: 'Failed to update config'});\n }\n\n return result.toObject();\n }\n\n // TODO [limited-time-offer] @zbib - add admin logging\n\n}\n\nexport const limitedTimeOfferConfigService = Container.get(LimitedTimeOfferConfigService);\n"]}