@@ -27,9 +27,21 @@ public function resetMultiplier(DateTimeInterface $dateTime, string $bulkIdentif
27
27
$ connection ->beginTransaction ();
28
28
29
29
try {
30
- $ ids = $ this ->createQueryBuilder ('o ' )
30
+ $ qb = $ this ->createQueryBuilder ('o ' );
31
+ $ ids = $ qb
31
32
->select ('o.id ' )
32
- ->andWhere ('o.multiplier != 1 ' )
33
+ ->andWhere ('o.bulkIdentifier != :bulkIdentifier ' ) // this ensures that the loop we are in doesn't turn into an infinite loop
34
+ ->andWhere (
35
+ $ qb ->expr ()->orX (
36
+ // if the multiplier is different from 1 we know that it was discounted before
37
+ 'o.multiplier != 1 ' ,
38
+
39
+ // if the previous job timed out, the bulk identifier will be different from the
40
+ // bulk identifier for this run. This will ensure that they will also be handled in this run
41
+ 'o.bulkIdentifier is not null ' ,
42
+ )
43
+ )
44
+ ->setParameter ('bulkIdentifier ' , $ bulkIdentifier )
33
45
->setMaxResults (100 )
34
46
->getQuery ()
35
47
->getResult ()
@@ -83,6 +95,22 @@ public function updateMultiplier(
83
95
$ qb ->update ()
84
96
->andWhere ('channelPricing.productVariant IN (:productVariantIds) ' )
85
97
->andWhere ('channelPricing.channelCode IN (:channelCodes) ' )
98
+ // this 'or' is a safety check. If the previous run timed out, but managed to update some multipliers
99
+ // this will end up in discounts being compounded. With this check we ensure we only operate on pricings
100
+ // from this run or pricings that haven't been touched
101
+ ->andWhere ($ qb ->expr ()->orX (
102
+ 'channelPricing.bulkIdentifier is null ' ,
103
+ 'channelPricing.bulkIdentifier = :bulkIdentifier ' ,
104
+ ))
105
+ // here is another safety check. If the promotion code is already applied,
106
+ // do not select this pricing for a discount
107
+ ->andWhere ($ qb ->expr ()->orX (
108
+ 'channelPricing.appliedPromotions IS NULL ' ,
109
+ $ qb ->expr ()->andX (
110
+ 'channelPricing.appliedPromotions NOT LIKE :promotionEnding ' ,
111
+ 'channelPricing.appliedPromotions NOT LIKE :promotionMiddle ' ,
112
+ )
113
+ ))
86
114
->set ('channelPricing.updatedAt ' , ':date ' )
87
115
->set ('channelPricing.bulkIdentifier ' , ':bulkIdentifier ' )
88
116
->set ('channelPricing.appliedPromotions ' , "CONCAT(COALESCE(channelPricing.appliedPromotions, ''), CONCAT(',', :promotion)) " )
@@ -91,6 +119,12 @@ public function updateMultiplier(
91
119
->setParameter ('date ' , $ dateTime )
92
120
->setParameter ('bulkIdentifier ' , $ bulkIdentifier )
93
121
->setParameter ('promotion ' , $ promotionCode )
122
+ // if you are checking for the promo code 'all_10_percent' there are two options for the applied_promotions column:
123
+ // 1. ,single_tshirt,all_10_percent
124
+ // 2. ,all_10_percent,single_tshirt
125
+ // and these two wildcards selections will handle those two options
126
+ ->setParameter ('promotionEnding ' , '%, ' . $ promotionCode )
127
+ ->setParameter ('promotionMiddle ' , '%, ' . $ promotionCode . ',% ' )
94
128
;
95
129
96
130
if ($ manuallyDiscountedProductsExcluded ) {
0 commit comments