@lyxa.ai/marketing 1.0.37 → 1.0.40
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.
- package/dist/lib/index.d.ts +87 -7
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/modules/coupon/services/coupon.service.d.ts +3 -0
- package/dist/lib/modules/coupon/services/coupon.service.d.ts.map +1 -1
- package/dist/lib/modules/coupon/services/coupon.service.js +122 -5
- package/dist/lib/modules/coupon/services/coupon.service.js.map +1 -1
- package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.d.ts.map +1 -1
- package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.js +7 -0
- package/dist/lib/modules/coupon/services/patterns/repository/CouponRepository.js.map +1 -1
- package/dist/lib/modules/coupon/validations/coupon.validation.d.ts.map +1 -1
- package/dist/lib/modules/coupon/validations/coupon.validation.js +5 -14
- package/dist/lib/modules/coupon/validations/coupon.validation.js.map +1 -1
- package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts +39 -0
- package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts.map +1 -0
- package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.js +539 -0
- package/dist/lib/modules/marketing/patterns/repository/MarketingMetricsRepository.js.map +1 -0
- package/dist/lib/modules/marketing/routers/marketing.router.d.ts +87 -7
- package/dist/lib/modules/marketing/routers/marketing.router.d.ts.map +1 -1
- package/dist/lib/modules/marketing/routers/marketing.router.js +27 -8
- package/dist/lib/modules/marketing/routers/marketing.router.js.map +1 -1
- package/dist/lib/modules/marketing/services/marketing.service.d.ts +4 -8
- package/dist/lib/modules/marketing/services/marketing.service.d.ts.map +1 -1
- package/dist/lib/modules/marketing/services/marketing.service.js +65 -355
- package/dist/lib/modules/marketing/services/marketing.service.js.map +1 -1
- package/dist/lib/modules/marketing/services/product-marketing.service.d.ts +1 -0
- package/dist/lib/modules/marketing/services/product-marketing.service.d.ts.map +1 -1
- package/dist/lib/modules/marketing/services/product-marketing.service.js +4 -0
- package/dist/lib/modules/marketing/services/product-marketing.service.js.map +1 -1
- package/dist/lib/modules/marketing/validations/marketing.validation.d.ts +106 -1
- package/dist/lib/modules/marketing/validations/marketing.validation.d.ts.map +1 -1
- package/dist/lib/modules/marketing/validations/marketing.validation.js +31 -1
- package/dist/lib/modules/marketing/validations/marketing.validation.js.map +1 -1
- package/dist/lib/modules/punch-marketing-history/services/punch-marketing-history.service.d.ts.map +1 -1
- package/dist/lib/modules/punch-marketing-history/services/punch-marketing-history.service.js +19 -1
- package/dist/lib/modules/punch-marketing-history/services/punch-marketing-history.service.js.map +1 -1
- package/dist/lib/utility/utils.d.ts +3 -0
- package/dist/lib/utility/utils.d.ts.map +1 -0
- package/dist/lib/utility/utils.js +31 -0
- package/dist/lib/utility/utils.js.map +1 -0
- package/dist/types/index.d.ts +87 -7
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/modules/coupon/services/coupon.service.d.ts +3 -0
- package/dist/types/modules/coupon/services/coupon.service.d.ts.map +1 -1
- package/dist/types/modules/coupon/services/patterns/repository/CouponRepository.d.ts.map +1 -1
- package/dist/types/modules/coupon/validations/coupon.validation.d.ts.map +1 -1
- package/dist/types/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts +39 -0
- package/dist/types/modules/marketing/patterns/repository/MarketingMetricsRepository.d.ts.map +1 -0
- package/dist/types/modules/marketing/routers/marketing.router.d.ts +87 -7
- package/dist/types/modules/marketing/routers/marketing.router.d.ts.map +1 -1
- package/dist/types/modules/marketing/services/marketing.service.d.ts +4 -8
- package/dist/types/modules/marketing/services/marketing.service.d.ts.map +1 -1
- package/dist/types/modules/marketing/services/product-marketing.service.d.ts +1 -0
- package/dist/types/modules/marketing/services/product-marketing.service.d.ts.map +1 -1
- package/dist/types/modules/marketing/validations/marketing.validation.d.ts +106 -1
- package/dist/types/modules/marketing/validations/marketing.validation.d.ts.map +1 -1
- package/dist/types/modules/punch-marketing-history/services/punch-marketing-history.service.d.ts.map +1 -1
- package/dist/types/utility/utils.d.ts +15 -0
- package/dist/types/utility/utils.d.ts.map +1 -0
- package/package.json +2 -2
|
@@ -56,14 +56,17 @@ const _1 = require(".");
|
|
|
56
56
|
const enum_2 = require("@lyxa.ai/core/dist/utilities/enum");
|
|
57
57
|
const error_common_1 = require("@lyxa.ai/core/dist/utilities/error-common");
|
|
58
58
|
const mongo_stream_changes_batch_process_shops_event_1 = require("@lyxa.ai/core/dist/libraries/event/events/mongo-stream-changes-batch-process-shops-event");
|
|
59
|
+
const MarketingMetricsRepository_1 = require("../patterns/repository/MarketingMetricsRepository");
|
|
59
60
|
let MarketingService = class MarketingService {
|
|
60
61
|
model;
|
|
61
62
|
shopModel;
|
|
62
63
|
orderModel;
|
|
64
|
+
marketingMetricsRepository;
|
|
63
65
|
constructor() {
|
|
64
66
|
this.model = models_1.MarketingModel;
|
|
65
67
|
this.shopModel = models_1.ShopModel;
|
|
66
68
|
this.orderModel = models_1.RegularOrderModel;
|
|
69
|
+
this.marketingMetricsRepository = MarketingMetricsRepository_1.marketingMetricsRepository;
|
|
67
70
|
}
|
|
68
71
|
async create(data, admin) {
|
|
69
72
|
const now = (0, dayjs_1.dayjs)().toDate();
|
|
@@ -358,333 +361,6 @@ let MarketingService = class MarketingService {
|
|
|
358
361
|
}
|
|
359
362
|
return 'Product handled successfully';
|
|
360
363
|
}
|
|
361
|
-
async evaluateMarketingSpendLimits(marketings) {
|
|
362
|
-
this.evaluateItemBasedMarketings(marketings);
|
|
363
|
-
this.evalulateFreeDeliveryMarketings(marketings);
|
|
364
|
-
return 'Evaluated spend limits';
|
|
365
|
-
}
|
|
366
|
-
async evaluateItemBasedMarketings(marketings) {
|
|
367
|
-
const pipeline = [
|
|
368
|
-
{
|
|
369
|
-
$match: {
|
|
370
|
-
$and: [{ marketings: { $exists: true } }, { marketings: { $ne: null } }],
|
|
371
|
-
status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
|
|
372
|
-
$expr: {
|
|
373
|
-
$gt: [
|
|
374
|
-
{
|
|
375
|
-
$size: {
|
|
376
|
-
$setIntersection: ['$marketings', marketings],
|
|
377
|
-
},
|
|
378
|
-
},
|
|
379
|
-
0,
|
|
380
|
-
],
|
|
381
|
-
},
|
|
382
|
-
},
|
|
383
|
-
},
|
|
384
|
-
{
|
|
385
|
-
$lookup: {
|
|
386
|
-
from: 'lineItems',
|
|
387
|
-
localField: 'cart',
|
|
388
|
-
foreignField: 'cart',
|
|
389
|
-
as: 'lineItems',
|
|
390
|
-
},
|
|
391
|
-
},
|
|
392
|
-
{
|
|
393
|
-
$unwind: '$lineItems',
|
|
394
|
-
},
|
|
395
|
-
{
|
|
396
|
-
$lookup: {
|
|
397
|
-
from: 'marketings',
|
|
398
|
-
localField: 'lineItems.marketings',
|
|
399
|
-
foreignField: '_id',
|
|
400
|
-
as: 'marketing',
|
|
401
|
-
},
|
|
402
|
-
},
|
|
403
|
-
{
|
|
404
|
-
$unwind: '$marketing',
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
$group: {
|
|
408
|
-
_id: '$marketing._id',
|
|
409
|
-
marketingType: { $first: '$marketing.marketingType' },
|
|
410
|
-
spendLimit: { $first: '$marketing.spendLimit' },
|
|
411
|
-
isSpendLimitEnabled: { $first: '$marketing.isSpendLimitEnabled' },
|
|
412
|
-
totalCompanyDiscount: {
|
|
413
|
-
$sum: {
|
|
414
|
-
$cond: [
|
|
415
|
-
{ $eq: ['$marketing.marketingType', enum_2.MarketingType.DISCOUNT] },
|
|
416
|
-
'$lineItems.calculationSnap.itemDiscountByCompany',
|
|
417
|
-
0,
|
|
418
|
-
],
|
|
419
|
-
},
|
|
420
|
-
},
|
|
421
|
-
totalShopDiscount: {
|
|
422
|
-
$sum: {
|
|
423
|
-
$cond: [
|
|
424
|
-
{ $eq: ['$marketing.marketingType', enum_2.MarketingType.DISCOUNT] },
|
|
425
|
-
'$lineItems.calculationSnap.itemDiscountByShop',
|
|
426
|
-
0,
|
|
427
|
-
],
|
|
428
|
-
},
|
|
429
|
-
},
|
|
430
|
-
totalB1G1Company: {
|
|
431
|
-
$sum: {
|
|
432
|
-
$cond: [
|
|
433
|
-
{ $eq: ['$marketing.marketingType', enum_2.MarketingType.BUY1GET1] },
|
|
434
|
-
'$lineItems.calculationSnap.b1g1DiscountByCompany',
|
|
435
|
-
0,
|
|
436
|
-
],
|
|
437
|
-
},
|
|
438
|
-
},
|
|
439
|
-
totalB1G1Shop: {
|
|
440
|
-
$sum: {
|
|
441
|
-
$cond: [
|
|
442
|
-
{ $eq: ['$marketing.marketingType', enum_2.MarketingType.BUY1GET1] },
|
|
443
|
-
'$lineItems.calculationSnap.b1g1DiscountByShop',
|
|
444
|
-
0,
|
|
445
|
-
],
|
|
446
|
-
},
|
|
447
|
-
},
|
|
448
|
-
},
|
|
449
|
-
},
|
|
450
|
-
];
|
|
451
|
-
const result = await this.orderModel.aggregate(pipeline);
|
|
452
|
-
const promises = [];
|
|
453
|
-
result?.forEach(async (marketing) => {
|
|
454
|
-
if (marketing.isSpendLimitEnabled) {
|
|
455
|
-
const totalSpent = marketing.totalCompanyDiscount +
|
|
456
|
-
marketing.totalShopDiscount +
|
|
457
|
-
marketing.totalB1G1Company +
|
|
458
|
-
marketing.totalB1G1Shop;
|
|
459
|
-
if (totalSpent >= marketing.spendLimit) {
|
|
460
|
-
await this.model.findByIdAndUpdate(marketing._id, {
|
|
461
|
-
status: enum_1.MarketingStatus.EXPIRED,
|
|
462
|
-
});
|
|
463
|
-
promises.push(_1.productMarketingService.syncProductMarketingInfo(marketing._id));
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
await Promise.all(promises);
|
|
468
|
-
}
|
|
469
|
-
async evalulateFreeDeliveryMarketings(marketings) {
|
|
470
|
-
const pipeline = [
|
|
471
|
-
{
|
|
472
|
-
$match: {
|
|
473
|
-
$and: [{ marketings: { $exists: true } }, { marketings: { $ne: null } }],
|
|
474
|
-
status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
|
|
475
|
-
$expr: {
|
|
476
|
-
$gt: [
|
|
477
|
-
{
|
|
478
|
-
$size: {
|
|
479
|
-
$setIntersection: ['$marketings', marketings],
|
|
480
|
-
},
|
|
481
|
-
},
|
|
482
|
-
0,
|
|
483
|
-
],
|
|
484
|
-
},
|
|
485
|
-
},
|
|
486
|
-
},
|
|
487
|
-
{
|
|
488
|
-
$lookup: {
|
|
489
|
-
from: 'marketings',
|
|
490
|
-
localField: 'marketings',
|
|
491
|
-
foreignField: '_id',
|
|
492
|
-
as: 'marketing',
|
|
493
|
-
},
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
$unwind: '$marketing',
|
|
497
|
-
},
|
|
498
|
-
{
|
|
499
|
-
$match: {
|
|
500
|
-
'marketing.marketingType': enum_2.MarketingType.FREE_DELIVERY,
|
|
501
|
-
},
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
$group: {
|
|
505
|
-
_id: '$marketing._id',
|
|
506
|
-
marketingType: { $first: '$marketing.marketingType' },
|
|
507
|
-
spendLimit: { $first: '$marketing.spendLimit' },
|
|
508
|
-
isSpendLimitEnabled: { $first: '$marketing.isSpendLimitEnabled' },
|
|
509
|
-
totalFreeDeliveryCompany: {
|
|
510
|
-
$sum: {
|
|
511
|
-
$cond: [
|
|
512
|
-
{ $eq: ['$marketing.marketingType', enum_2.MarketingType.FREE_DELIVERY] },
|
|
513
|
-
'$adjustedFinance.freeDelivery.companyCut',
|
|
514
|
-
0,
|
|
515
|
-
],
|
|
516
|
-
},
|
|
517
|
-
},
|
|
518
|
-
totalFreeDeliveryShop: {
|
|
519
|
-
$sum: {
|
|
520
|
-
$cond: [
|
|
521
|
-
{ $eq: ['$marketing.marketingType', enum_2.MarketingType.FREE_DELIVERY] },
|
|
522
|
-
'$adjustedFinance.freeDelivery.shopCut',
|
|
523
|
-
0,
|
|
524
|
-
],
|
|
525
|
-
},
|
|
526
|
-
},
|
|
527
|
-
},
|
|
528
|
-
},
|
|
529
|
-
];
|
|
530
|
-
const result = await this.orderModel.aggregate(pipeline);
|
|
531
|
-
const promises = [];
|
|
532
|
-
result?.forEach(marketing => {
|
|
533
|
-
if (marketing.isSpendLimitEnabled) {
|
|
534
|
-
const totalSpent = marketing.totalFreeDeliveryCompany + marketing.totalFreeDeliveryShop;
|
|
535
|
-
if (totalSpent >= marketing.spendLimit) {
|
|
536
|
-
promises.push(this.model.findByIdAndUpdate(marketing._id, {
|
|
537
|
-
status: enum_1.MarketingStatus.EXPIRED,
|
|
538
|
-
}));
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
});
|
|
542
|
-
await Promise.all(promises);
|
|
543
|
-
}
|
|
544
|
-
async calculateMarketingSpent(marketingId) {
|
|
545
|
-
const marketing = await this.model.findById(marketingId).lean();
|
|
546
|
-
if (!marketing) {
|
|
547
|
-
throw new Error('Marketing not found');
|
|
548
|
-
}
|
|
549
|
-
let amount = 0;
|
|
550
|
-
switch (marketing.marketingType) {
|
|
551
|
-
case enum_2.MarketingType.FREE_DELIVERY:
|
|
552
|
-
amount = await this.calculateFreeDeliverySpent(marketingId);
|
|
553
|
-
break;
|
|
554
|
-
case enum_2.MarketingType.DISCOUNT:
|
|
555
|
-
case enum_2.MarketingType.BUY1GET1:
|
|
556
|
-
amount = await this.calculateItemBasedSpent(marketingId);
|
|
557
|
-
break;
|
|
558
|
-
case enum_2.MarketingType.PUNCH_MARKETING:
|
|
559
|
-
amount = await this.calculatePunchMarketingSpent(marketingId);
|
|
560
|
-
break;
|
|
561
|
-
default:
|
|
562
|
-
amount = 0;
|
|
563
|
-
}
|
|
564
|
-
return {
|
|
565
|
-
amount,
|
|
566
|
-
marketingType: marketing.marketingType,
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
async calculateItemBasedSpent(marketingId) {
|
|
570
|
-
const pipeline = [
|
|
571
|
-
{
|
|
572
|
-
$match: {
|
|
573
|
-
$and: [{ marketings: { $exists: true } }, { marketings: { $ne: null } }],
|
|
574
|
-
status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
|
|
575
|
-
marketings: marketingId,
|
|
576
|
-
},
|
|
577
|
-
},
|
|
578
|
-
{
|
|
579
|
-
$lookup: {
|
|
580
|
-
from: 'lineItems',
|
|
581
|
-
localField: 'cart',
|
|
582
|
-
foreignField: 'cart',
|
|
583
|
-
as: 'lineItems',
|
|
584
|
-
},
|
|
585
|
-
},
|
|
586
|
-
{ $unwind: '$lineItems' },
|
|
587
|
-
{
|
|
588
|
-
$lookup: {
|
|
589
|
-
from: 'marketings',
|
|
590
|
-
localField: 'lineItems.marketings',
|
|
591
|
-
foreignField: '_id',
|
|
592
|
-
as: 'marketing',
|
|
593
|
-
},
|
|
594
|
-
},
|
|
595
|
-
{ $unwind: '$marketing' },
|
|
596
|
-
{
|
|
597
|
-
$match: {
|
|
598
|
-
'marketing._id': marketingId,
|
|
599
|
-
},
|
|
600
|
-
},
|
|
601
|
-
{
|
|
602
|
-
$group: {
|
|
603
|
-
_id: null,
|
|
604
|
-
totalCompanyDiscount: {
|
|
605
|
-
$sum: '$lineItems.calculationSnap.itemDiscountByCompany',
|
|
606
|
-
},
|
|
607
|
-
totalShopDiscount: {
|
|
608
|
-
$sum: '$lineItems.calculationSnap.itemDiscountByShop',
|
|
609
|
-
},
|
|
610
|
-
totalB1G1Company: {
|
|
611
|
-
$sum: '$lineItems.calculationSnap.b1g1DiscountByCompany',
|
|
612
|
-
},
|
|
613
|
-
totalB1G1Shop: {
|
|
614
|
-
$sum: '$lineItems.calculationSnap.b1g1DiscountByShop',
|
|
615
|
-
},
|
|
616
|
-
},
|
|
617
|
-
},
|
|
618
|
-
];
|
|
619
|
-
const [result] = await this.orderModel.aggregate(pipeline);
|
|
620
|
-
if (!result)
|
|
621
|
-
return 0;
|
|
622
|
-
return (result.totalCompanyDiscount + result.totalShopDiscount + result.totalB1G1Company + result.totalB1G1Shop);
|
|
623
|
-
}
|
|
624
|
-
async calculateFreeDeliverySpent(marketingId) {
|
|
625
|
-
const pipeline = [
|
|
626
|
-
{
|
|
627
|
-
$match: {
|
|
628
|
-
$and: [{ marketings: { $exists: true } }, { marketings: { $ne: null } }],
|
|
629
|
-
status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
|
|
630
|
-
marketings: marketingId,
|
|
631
|
-
},
|
|
632
|
-
},
|
|
633
|
-
{
|
|
634
|
-
$lookup: {
|
|
635
|
-
from: 'marketings',
|
|
636
|
-
localField: 'marketings',
|
|
637
|
-
foreignField: '_id',
|
|
638
|
-
as: 'marketing',
|
|
639
|
-
},
|
|
640
|
-
},
|
|
641
|
-
{ $unwind: '$marketing' },
|
|
642
|
-
{
|
|
643
|
-
$match: {
|
|
644
|
-
'marketing._id': marketingId,
|
|
645
|
-
'marketing.marketingType': enum_2.MarketingType.FREE_DELIVERY,
|
|
646
|
-
},
|
|
647
|
-
},
|
|
648
|
-
{
|
|
649
|
-
$group: {
|
|
650
|
-
_id: null,
|
|
651
|
-
totalFreeDeliveryCompany: {
|
|
652
|
-
$sum: '$adjustedFinance.freeDelivery.companyCut',
|
|
653
|
-
},
|
|
654
|
-
totalFreeDeliveryShop: {
|
|
655
|
-
$sum: '$adjustedFinance.freeDelivery.shopCut',
|
|
656
|
-
},
|
|
657
|
-
},
|
|
658
|
-
},
|
|
659
|
-
];
|
|
660
|
-
const [result] = await this.orderModel.aggregate(pipeline);
|
|
661
|
-
if (!result)
|
|
662
|
-
return 0;
|
|
663
|
-
return result.totalFreeDeliveryCompany + result.totalFreeDeliveryShop;
|
|
664
|
-
}
|
|
665
|
-
async calculatePunchMarketingSpent(marketingId) {
|
|
666
|
-
const pipeline = [
|
|
667
|
-
{
|
|
668
|
-
$match: {
|
|
669
|
-
$and: [{ marketings: { $exists: true } }, { marketings: { $ne: null } }],
|
|
670
|
-
status: { $ne: enum_1.RegularOrderStatus.CANCELLED },
|
|
671
|
-
marketings: marketingId,
|
|
672
|
-
},
|
|
673
|
-
},
|
|
674
|
-
{
|
|
675
|
-
$group: {
|
|
676
|
-
_id: null,
|
|
677
|
-
totalPunchDiscount: {
|
|
678
|
-
$sum: {
|
|
679
|
-
$ifNull: ['$adjustedFinance.pricing.punchMarketingDiscount', 0],
|
|
680
|
-
},
|
|
681
|
-
},
|
|
682
|
-
},
|
|
683
|
-
},
|
|
684
|
-
];
|
|
685
|
-
const [result] = await this.orderModel.aggregate(pipeline);
|
|
686
|
-
return result?.totalPunchDiscount ?? 0;
|
|
687
|
-
}
|
|
688
364
|
async incrementMarketingSpentFromOrder(orderId) {
|
|
689
365
|
const order = (await this.orderModel
|
|
690
366
|
.findById(orderId)
|
|
@@ -692,7 +368,7 @@ let MarketingService = class MarketingService {
|
|
|
692
368
|
if (!order || !order.marketings?.length) {
|
|
693
369
|
return;
|
|
694
370
|
}
|
|
695
|
-
const marketingSpendMap = this.calculateMarketingSpendPerOrder(order);
|
|
371
|
+
const marketingSpendMap = this.marketingMetricsRepository.calculateMarketingSpendPerOrder(order);
|
|
696
372
|
const bulkOps = [...marketingSpendMap.entries()].map(([marketingId, amountSpent]) => ({
|
|
697
373
|
updateOne: {
|
|
698
374
|
filter: { _id: marketingId },
|
|
@@ -702,44 +378,78 @@ let MarketingService = class MarketingService {
|
|
|
702
378
|
if (bulkOps.length) {
|
|
703
379
|
await this.model.bulkWrite(bulkOps);
|
|
704
380
|
}
|
|
705
|
-
await this.expireMarketingsExceedingSpendLimits();
|
|
381
|
+
await this.expireMarketingsExceedingSpendLimits(Array.from(marketingSpendMap.keys()));
|
|
706
382
|
return 'Marketing amount spent incremented successfully';
|
|
707
383
|
}
|
|
708
|
-
async
|
|
384
|
+
async decrementMarketingSpentFromOrder(orderId) {
|
|
385
|
+
const order = (await this.orderModel
|
|
386
|
+
.findById(orderId)
|
|
387
|
+
.populate('lineItems'));
|
|
388
|
+
if (!order || !order.marketings?.length) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const marketingSpendMap = this.marketingMetricsRepository.calculateMarketingSpendPerOrder(order);
|
|
392
|
+
const bulkOps = [...marketingSpendMap.entries()].map(([marketingId, amountSpent]) => ({
|
|
393
|
+
updateOne: {
|
|
394
|
+
filter: { _id: marketingId },
|
|
395
|
+
update: { $inc: { amountSpent: -amountSpent } },
|
|
396
|
+
},
|
|
397
|
+
}));
|
|
398
|
+
if (bulkOps.length) {
|
|
399
|
+
await this.model.bulkWrite(bulkOps);
|
|
400
|
+
}
|
|
401
|
+
await this.unExpireMarketingsBelowSpendLimits(Array.from(marketingSpendMap.keys()));
|
|
402
|
+
return 'Marketing amount spent decremented successfully';
|
|
403
|
+
}
|
|
404
|
+
async expireMarketingsExceedingSpendLimits(marketingIds) {
|
|
709
405
|
await this.model.updateMany({
|
|
406
|
+
_id: { $in: marketingIds },
|
|
710
407
|
isSpendLimitEnabled: true,
|
|
711
408
|
status: { $ne: enum_1.MarketingStatus.EXPIRED },
|
|
712
409
|
$expr: { $gte: ['$amountSpent', '$spendLimit'] },
|
|
713
410
|
}, { $set: { status: enum_1.MarketingStatus.EXPIRED } });
|
|
714
411
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
};
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
412
|
+
async unExpireMarketingsBelowSpendLimits(marketingIds) {
|
|
413
|
+
await this.model.updateMany({
|
|
414
|
+
_id: { $in: marketingIds },
|
|
415
|
+
isSpendLimitEnabled: true,
|
|
416
|
+
status: enum_1.MarketingStatus.EXPIRED,
|
|
417
|
+
$expr: { $lt: ['$amountSpent', '$spendLimit'] },
|
|
418
|
+
}, { $set: { status: enum_1.MarketingStatus.ACTIVE } });
|
|
419
|
+
}
|
|
420
|
+
async recomputeAndSyncAllMarketingSpent() {
|
|
421
|
+
console.time('Recomputing all marketing spend');
|
|
422
|
+
const cursor = this.model
|
|
423
|
+
.find({ marketingType: { $ne: enum_2.MarketingType.FEATURED } }, { _id: 1 })
|
|
424
|
+
.lean()
|
|
425
|
+
.cursor();
|
|
426
|
+
const bulkOps = [];
|
|
427
|
+
const marketingIds = [];
|
|
428
|
+
for await (const marketing of cursor) {
|
|
429
|
+
console.log(`Recomputing marketing spend for marketing ID: ${marketing._id}`);
|
|
430
|
+
const { amount } = await this.marketingMetricsRepository.calculateMarketingSpent(marketing._id);
|
|
431
|
+
bulkOps.push({
|
|
432
|
+
updateOne: {
|
|
433
|
+
filter: { _id: marketing._id },
|
|
434
|
+
update: {
|
|
435
|
+
$set: { amountSpent: amount },
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
marketingIds.push(marketing._id);
|
|
440
|
+
if (bulkOps.length >= 500) {
|
|
441
|
+
console.log(`Flushing 500 marketing spend updates...`);
|
|
442
|
+
await this.model.bulkWrite(bulkOps);
|
|
443
|
+
bulkOps.length = 0;
|
|
735
444
|
}
|
|
736
445
|
}
|
|
737
|
-
if (
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
}
|
|
446
|
+
if (bulkOps.length) {
|
|
447
|
+
console.log(`Flushing remaining ${bulkOps.length} marketing spend updates...`);
|
|
448
|
+
await this.model.bulkWrite(bulkOps);
|
|
741
449
|
}
|
|
742
|
-
|
|
450
|
+
await this.expireMarketingsExceedingSpendLimits(marketingIds);
|
|
451
|
+
await this.unExpireMarketingsBelowSpendLimits(marketingIds);
|
|
452
|
+
console.timeEnd('Recomputing all marketing spend');
|
|
743
453
|
}
|
|
744
454
|
};
|
|
745
455
|
exports.MarketingService = MarketingService;
|