Completed
Push — 1.5 ( 17c098...006ba9 )
by Kamil
30:59
created

PromotionContext::thisPromotionHasCoupons()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Behat\Context\Setup;
15
16
use Behat\Behat\Context\Context;
17
use Doctrine\Common\Persistence\ObjectManager;
18
use Sylius\Behat\Service\SharedStorageInterface;
19
use Sylius\Component\Core\Factory\PromotionActionFactoryInterface;
20
use Sylius\Component\Core\Factory\PromotionRuleFactoryInterface;
21
use Sylius\Component\Core\Model\ChannelInterface;
22
use Sylius\Component\Core\Model\ProductInterface;
23
use Sylius\Component\Core\Model\PromotionCouponInterface;
24
use Sylius\Component\Core\Model\PromotionInterface;
25
use Sylius\Component\Core\Model\TaxonInterface;
26
use Sylius\Component\Core\Promotion\Checker\Rule\CustomerGroupRuleChecker;
27
use Sylius\Component\Core\Test\Factory\TestPromotionFactoryInterface;
28
use Sylius\Component\Customer\Model\CustomerGroupInterface;
29
use Sylius\Component\Promotion\Factory\PromotionCouponFactoryInterface;
30
use Sylius\Component\Promotion\Model\PromotionActionInterface;
31
use Sylius\Component\Promotion\Model\PromotionRuleInterface;
32
use Sylius\Component\Promotion\Repository\PromotionRepositoryInterface;
33
34
final class PromotionContext implements Context
35
{
36
    /** @var SharedStorageInterface */
37
    private $sharedStorage;
38
39
    /** @var PromotionActionFactoryInterface */
40
    private $actionFactory;
41
42
    /** @var PromotionCouponFactoryInterface */
43
    private $couponFactory;
44
45
    /** @var PromotionRuleFactoryInterface */
46
    private $ruleFactory;
47
48
    /** @var TestPromotionFactoryInterface */
49
    private $testPromotionFactory;
50
51
    /** @var PromotionRepositoryInterface */
52
    private $promotionRepository;
53
54
    /** @var ObjectManager */
55
    private $objectManager;
56
57
    public function __construct(
58
        SharedStorageInterface $sharedStorage,
59
        PromotionActionFactoryInterface $actionFactory,
60
        PromotionCouponFactoryInterface $couponFactory,
61
        PromotionRuleFactoryInterface $ruleFactory,
62
        TestPromotionFactoryInterface $testPromotionFactory,
63
        PromotionRepositoryInterface $promotionRepository,
64
        ObjectManager $objectManager
65
    ) {
66
        $this->sharedStorage = $sharedStorage;
67
        $this->actionFactory = $actionFactory;
68
        $this->couponFactory = $couponFactory;
69
        $this->ruleFactory = $ruleFactory;
70
        $this->testPromotionFactory = $testPromotionFactory;
71
        $this->promotionRepository = $promotionRepository;
72
        $this->objectManager = $objectManager;
73
    }
74
75
    /**
76
     * @Given there is (also) a promotion :name
77
     * @Given there is a promotion :name identified by :code code
78
     */
79
    public function thereIsPromotion(string $name, ?string $code = null): void
80
    {
81
        $this->createPromotion($name, $code);
82
    }
83
84
    /**
85
     * @Given /^there is a promotion "([^"]+)" with "Has at least one from taxons" rule (configured with "[^"]+" and "[^"]+")$/
86
     */
87
    public function thereIsAPromotionWithHasAtLeastOneFromTaxonsRuleConfiguredWith(string $name, array $taxons): void
88
    {
89
        $promotion = $this->createPromotion($name);
90
        $rule = $this->ruleFactory->createHasTaxon([$taxons[0]->getCode(), $taxons[1]->getCode()]);
91
        $promotion->addRule($rule);
92
93
        $this->objectManager->flush();
94
    }
95
96
    /**
97
     * @Given /^there is a promotion "([^"]+)" with "Total price of items from taxon" rule configured with ("[^"]+" taxon) and (?:€|£|\$)([^"]+) amount for ("[^"]+" channel)$/
98
     */
99
    public function thereIsAPromotionWithTotalPriceOfItemsFromTaxonRuleConfiguredWithTaxonAndAmountForChannel(
100
        string $name,
101
        TaxonInterface $taxon,
102
        int $amount,
103
        ChannelInterface $channel
104
    ): void {
105
        $promotion = $this->createPromotion($name);
106
        $rule = $this->ruleFactory->createItemsFromTaxonTotal($channel->getCode(), $taxon->getCode(), $amount);
107
        $promotion->addRule($rule);
108
109
        $this->objectManager->flush();
110
    }
111
112
    /**
113
     * @Given /^there is a promotion "([^"]+)" with priority ([^"]+)$/
114
     */
115
    public function thereIsAPromotionWithPriority($promotionName, $priority)
116
    {
117
        $promotion = $this->testPromotionFactory
118
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
119
        ;
120
121
        $promotion->setPriority((int) $priority);
122
123
        $this->promotionRepository->add($promotion);
124
        $this->sharedStorage->set('promotion', $promotion);
125
    }
126
127
    /**
128
     * @Given /^there is an exclusive promotion "([^"]+)"(?:| with priority ([^"]+))$/
129
     */
130
    public function thereIsAnExclusivePromotionWithPriority($promotionName, $priority = 0)
131
    {
132
        $promotion = $this->testPromotionFactory
133
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
134
        ;
135
136
        $promotion->setExclusive(true);
137
        $promotion->setPriority((int) $priority);
138
139
        $this->promotionRepository->add($promotion);
140
        $this->sharedStorage->set('promotion', $promotion);
141
    }
142
143
    /**
144
     * @Given there is a promotion :promotionName limited to :usageLimit usages
145
     */
146
    public function thereIsPromotionLimitedToUsages($promotionName, $usageLimit)
147
    {
148
        $promotion = $this->testPromotionFactory->createForChannel($promotionName, $this->sharedStorage->get('channel'));
149
150
        $promotion->setUsageLimit((int) $usageLimit);
151
152
        $this->promotionRepository->add($promotion);
153
        $this->sharedStorage->set('promotion', $promotion);
154
    }
155
156
    /**
157
     * @Given the store has promotion :promotionName with coupon :couponCode
158
     * @Given the store has a promotion :promotionName with a coupon :couponCode that is limited to :usageLimit usages
159
     */
160
    public function thereIsPromotionWithCoupon(string $promotionName, string $couponCode, ?int $usageLimit = null): void
161
    {
162
        $coupon = $this->createCoupon($couponCode, $usageLimit);
163
164
        $promotion = $this->testPromotionFactory
165
            ->createForChannel($promotionName, $this->sharedStorage->get('channel'))
166
        ;
167
        $promotion->addCoupon($coupon);
168
        $promotion->setCouponBased(true);
169
170
        $this->promotionRepository->add($promotion);
171
172
        $this->sharedStorage->set('promotion', $promotion);
173
        $this->sharedStorage->set('coupon', $coupon);
174
    }
175
176
    /**
177
     * @Given /^(this promotion) has "([^"]+)", "([^"]+)" and "([^"]+)" coupons/
178
     */
179
    public function thisPromotionHasCoupons(PromotionInterface $promotion, string ...$couponCodes): void
180
    {
181
        foreach ($couponCodes as $couponCode) {
182
            $coupon = $this->createCoupon($couponCode);
183
            $promotion->addCoupon($coupon);
184
        }
185
186
        $promotion->setCouponBased(true);
187
188
        $this->objectManager->flush();
189
    }
190
191
    /**
192
     * @Given /^(this promotion) has already expired$/
193
     */
194
    public function thisPromotionHasExpired(PromotionInterface $promotion)
195
    {
196
        $promotion->setEndsAt(new \DateTime('1 day ago'));
197
198
        $this->objectManager->flush();
199
    }
200
201
    /**
202
     * @Given /^(this promotion) expires tomorrow$/
203
     */
204
    public function thisPromotionExpiresTomorrow(PromotionInterface $promotion)
205
    {
206
        $promotion->setEndsAt(new \DateTime('tomorrow'));
207
208
        $this->objectManager->flush();
209
    }
210
211
    /**
212
     * @Given /^(this promotion) has started yesterday$/
213
     */
214
    public function thisPromotionHasStartedYesterday(PromotionInterface $promotion)
215
    {
216
        $promotion->setStartsAt(new \DateTime('1 day ago'));
217
218
        $this->objectManager->flush();
219
    }
220
221
    /**
222
     * @Given /^(this promotion) starts tomorrow$/
223
     */
224
    public function thisPromotionStartsTomorrow(PromotionInterface $promotion)
225
    {
226
        $promotion->setStartsAt(new \DateTime('tomorrow'));
227
228
        $this->objectManager->flush();
229
    }
230
231
    /**
232
     * @Given /^(this coupon) has already expired$/
233
     */
234
    public function thisCouponHasExpired(PromotionCouponInterface $coupon)
235
    {
236
        $coupon->setExpiresAt(new \DateTime('1 day ago'));
237
238
        $this->objectManager->flush();
239
    }
240
241
    /**
242
     * @Given /^(this coupon) expires tomorrow$/
243
     */
244
    public function thisCouponExpiresTomorrow(PromotionCouponInterface $coupon)
245
    {
246
        $coupon->setExpiresAt(new \DateTime('tomorrow'));
247
248
        $this->objectManager->flush();
249
    }
250
251
    /**
252
     * @Given /^(this coupon) is set as non reusable after cancelling the order in which it has been used$/
253
     */
254
    public function thisIsSetAsNonReusableAfterCancellingTheOrderInWhichItHasBeenUsed(PromotionCouponInterface $coupon): void
255
    {
256
        $coupon->setReusableFromCancelledOrders(false);
257
258
        $this->objectManager->flush();
259
    }
260
261
    /**
262
     * @Given /^(this coupon) has already reached its usage limit$/
263
     */
264
    public function thisCouponHasReachedItsUsageLimit(PromotionCouponInterface $coupon)
265
    {
266
        $coupon->setUsed(42);
267
        $coupon->setUsageLimit(42);
268
269
        $this->objectManager->flush();
270
    }
271
272
    /**
273
     * @Given /^(this coupon) can be used (\d+) times?$/
274
     * @Given /^(this coupon) can be used once$/
275
     */
276
    public function thisCouponCanBeUsedNTimes(PromotionCouponInterface $coupon, int $usageLimit = 1): void
277
    {
278
        $coupon->setUsageLimit($usageLimit);
279
280
        $this->objectManager->flush();
281
    }
282
283
    /**
284
     * @Given /^(this coupon) can be used once per customer$/
285
     */
286
    public function thisCouponCanBeUsedOncePerCustomer(PromotionCouponInterface $coupon): void
287
    {
288
        $coupon->setPerCustomerUsageLimit(1);
289
290
        $this->objectManager->flush();
291
    }
292
293
    /**
294
     * @Given /^(this coupon) can be used twice per customer$/
295
     */
296
    public function thisCouponCanBeUsedTwicePerCustomer(PromotionCouponInterface $coupon): void
297
    {
298
        $coupon->setPerCustomerUsageLimit(2);
299
300
        $this->objectManager->flush();
301
    }
302
303
    /**
304
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order$/
305
     */
306
    public function itGivesFixedDiscountToEveryOrder(PromotionInterface $promotion, $discount)
307
    {
308
        $this->createFixedPromotion($promotion, $discount);
309
    }
310
311
    /**
312
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order in the ("[^"]+" channel) and ("(?:€|£|\$)[^"]+") discount to every order in the ("[^"]+" channel)$/
313
     */
314
    public function thisPromotionGivesDiscountToEveryOrderInTheChannelAndDiscountToEveryOrderInTheChannel(
315
        PromotionInterface $promotion,
316
        $firstChannelDiscount,
317
        ChannelInterface $firstChannel,
318
        $secondChannelDiscount,
319
        ChannelInterface $secondChannel
320
    ) {
321
        /** @var PromotionActionInterface $action */
322
        $action = $this->actionFactory->createFixedDiscount($firstChannelDiscount, $firstChannel->getCode());
323
        $action->setConfiguration(array_merge($action->getConfiguration(), [$secondChannel->getCode() => ['amount' => $secondChannelDiscount]]));
324
325
        $promotion->addChannel($firstChannel);
326
        $promotion->addChannel($secondChannel);
327
        $promotion->addAction($action);
328
329
        $this->objectManager->flush();
330
    }
331
332
    /**
333
     * @Given /^([^"]+) gives ("[^"]+%") discount to every order$/
334
     */
335
    public function itGivesPercentageDiscountToEveryOrder(PromotionInterface $promotion, $discount)
336
    {
337
        $this->createPercentagePromotion($promotion, $discount);
338
    }
339
340
    /**
341
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order with quantity at least ([^"]+)$/
342
     */
343
    public function itGivesFixedDiscountToEveryOrderWithQuantityAtLeast(
344
        PromotionInterface $promotion,
345
        $discount,
346
        $quantity
347
    ) {
348
        $rule = $this->ruleFactory->createCartQuantity((int) $quantity);
349
350
        $this->createFixedPromotion($promotion, $discount, [], $rule);
351
    }
352
353
    /**
354
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order with items total at least ("[^"]+")$/
355
     */
356
    public function itGivesFixedDiscountToEveryOrderWithItemsTotalAtLeast(
357
        PromotionInterface $promotion,
358
        $discount,
359
        $targetAmount
360
    ) {
361
        $channelCode = $this->sharedStorage->get('channel')->getCode();
362
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
363
364
        $this->createFixedPromotion($promotion, $discount, [], $rule);
365
    }
366
367
    /**
368
     * @Given /^([^"]+) gives ("[^"]+%") discount to every order with items total at least ("[^"]+")$/
369
     */
370
    public function itGivesPercentageDiscountToEveryOrderWithItemsTotalAtLeast(
371
        PromotionInterface $promotion,
372
        $discount,
373
        $targetAmount
374
    ) {
375
        $channelCode = $this->sharedStorage->get('channel')->getCode();
376
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
377
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
378
    }
379
380
    /**
381
     * @Given /^([^"]+) gives ("[^"]+%") off on every product when the item total is at least ("(?:€|£|\$)[^"]+")$/
382
     */
383
    public function itGivesOffOnEveryItemWhenItemTotalExceeds(
384
        PromotionInterface $promotion,
385
        $discount,
386
        $targetAmount
387
    ) {
388
        $channelCode = $this->sharedStorage->get('channel')->getCode();
389
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
390
391
        $this->createUnitPercentagePromotion($promotion, $discount, [], $rule);
392
    }
393
394
    /**
395
     * @Given /^([^"]+) gives ("[^"]+%") discount on shipping to every order$/
396
     */
397
    public function itGivesPercentageDiscountOnShippingToEveryOrder(PromotionInterface $promotion, $discount)
398
    {
399
        $action = $this->actionFactory->createShippingPercentageDiscount($discount);
400
        $promotion->addAction($action);
401
402
        $this->objectManager->flush();
403
    }
404
405
    /**
406
     * @Given /^([^"]+) gives free shipping to every order$/
407
     */
408
    public function thePromotionGivesFreeShippingToEveryOrder(PromotionInterface $promotion)
409
    {
410
        $this->itGivesPercentageDiscountOnShippingToEveryOrder($promotion, 1);
411
    }
412
413
    /**
414
     * @Given /^([^"]+) gives(?:| another) ("[^"]+%") off every product (classified as "[^"]+")$/
415
     */
416
    public function itGivesPercentageOffEveryProductClassifiedAs(
417
        PromotionInterface $promotion,
418
        $discount,
419
        TaxonInterface $taxon
420
    ) {
421
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getTaxonFilterConfiguration([$taxon->getCode()]));
422
    }
423
424
    /**
425
     * @Given /^([^"]+) gives(?:| another) ("(?:€|£|\$)[^"]+") off on every product (classified as "[^"]+")$/
426
     */
427
    public function itGivesFixedOffEveryProductClassifiedAs(
428
        PromotionInterface $promotion,
429
        $discount,
430
        TaxonInterface $taxon
431
    ) {
432
        $this->createUnitFixedPromotion($promotion, $discount, $this->getTaxonFilterConfiguration([$taxon->getCode()]));
433
    }
434
435
    /**
436
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product with minimum price at ("(?:€|£|\$)[^"]+")$/
437
     */
438
    public function thisPromotionGivesOffOnEveryProductWithMinimumPriceAt(
439
        PromotionInterface $promotion,
440
        $discount,
441
        $amount
442
    ) {
443
        $this->createUnitFixedPromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
444
    }
445
446
    /**
447
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:€|£|\$)[^"]+")$/
448
     */
449
    public function thisPromotionGivesOffOnEveryProductPricedBetween(
450
        PromotionInterface $promotion,
451
        $discount,
452
        $minAmount,
453
        $maxAmount
454
    ) {
455
        $this->createUnitFixedPromotion(
456
            $promotion,
457
            $discount,
458
            $this->getPriceRangeFilterConfiguration($minAmount, $maxAmount)
459
        );
460
    }
461
462
    /**
463
     * @Given /^([^"]+) gives ("[^"]+%") off on every product with minimum price at ("(?:€|£|\$)[^"]+")$/
464
     */
465
    public function thisPromotionPercentageGivesOffOnEveryProductWithMinimumPriceAt(
466
        PromotionInterface $promotion,
467
        $discount,
468
        $amount
469
    ) {
470
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
471
    }
472
473
    /**
474
     * @Given /^([^"]+) gives ("[^"]+%") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:€|£|\$)[^"]+")$/
475
     */
476
    public function thisPromotionPercentageGivesOffOnEveryProductPricedBetween(
477
        PromotionInterface $promotion,
478
        $discount,
479
        $minAmount,
480
        $maxAmount
481
    ) {
482
        $this->createUnitPercentagePromotion(
483
            $promotion,
484
            $discount,
485
            $this->getPriceRangeFilterConfiguration($minAmount, $maxAmount)
486
        );
487
    }
488
489
    /**
490
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+")$/
491
     */
492
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAs(
493
        PromotionInterface $promotion,
494
        $discount,
495
        TaxonInterface $taxon
496
    ) {
497
        $rule = $this->ruleFactory->createHasTaxon([$taxon->getCode()]);
498
499
        $this->createFixedPromotion($promotion, $discount, [], $rule);
500
    }
501
502
    /**
503
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+" or "[^"]+")$/
504
     */
505
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsOr(
506
        PromotionInterface $promotion,
507
        $discount,
508
        array $taxons
509
    ) {
510
        $rule = $this->ruleFactory->createHasTaxon([$taxons[0]->getCode(), $taxons[1]->getCode()]);
511
512
        $this->createFixedPromotion($promotion, $discount, [], $rule);
513
    }
514
515
    /**
516
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+") with a minimum value of ("(?:€|£|\$)[^"]+")$/
517
     */
518
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsAndPricedAt(
519
        PromotionInterface $promotion,
520
        $discount,
521
        TaxonInterface $taxon,
522
        $amount
523
    ) {
524
        $channelCode = $this->sharedStorage->get('channel')->getCode();
525
        $rule = $this->ruleFactory->createItemsFromTaxonTotal($channelCode, $taxon->getCode(), $amount);
526
527
        $this->createFixedPromotion($promotion, $discount, [], $rule);
528
    }
529
530
    /**
531
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off customer's (\d)(?:st|nd|rd|th) order$/
532
     */
533
    public function itGivesFixedOffCustomersNthOrder(PromotionInterface $promotion, $discount, $nth)
534
    {
535
        $rule = $this->ruleFactory->createNthOrder((int) $nth);
536
537
        $this->createFixedPromotion($promotion, $discount, [], $rule);
538
    }
539
540
    /**
541
     * @Given /^([^"]+) gives ("[^"]+%") off on the customer's (\d)(?:st|nd|rd|th) order$/
542
     */
543
    public function itGivesPercentageOffCustomersNthOrder(PromotionInterface $promotion, $discount, $nth)
544
    {
545
        $rule = $this->ruleFactory->createNthOrder((int) $nth);
546
547
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
548
    }
549
550
    /**
551
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") and ("(?:€|£|\$)[^"]+") discount on every order$/
552
     */
553
    public function itGivesPercentageOffOnEveryProductClassifiedAsAndAmountDiscountOnOrder(
554
        PromotionInterface $promotion,
555
        $productDiscount,
556
        TaxonInterface $discountTaxon,
557
        $orderDiscount
558
    ) {
559
        $this->createUnitPercentagePromotion($promotion, $productDiscount, $this->getTaxonFilterConfiguration([$discountTaxon->getCode()]));
560
        $this->createFixedPromotion($promotion, $orderDiscount);
561
    }
562
563
    /**
564
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product (classified as "[^"]+") and a free shipping to every order with items total equal at least ("[^"]+")$/
565
     */
566
    public function itGivesOffOnEveryProductClassifiedAsAndAFreeShippingToEveryOrderWithItemsTotalEqualAtLeast(
567
        PromotionInterface $promotion,
568
        $discount,
569
        TaxonInterface $taxon,
0 ignored issues
show
Unused Code introduced by
The parameter $taxon is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
570
        $targetAmount
571
    ) {
572
        $freeShippingAction = $this->actionFactory->createShippingPercentageDiscount(1);
573
        $promotion->addAction($freeShippingAction);
574
575
        $channelCode = $this->sharedStorage->get('channel')->getCode();
576
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
577
578
        $this->createUnitFixedPromotion($promotion, $discount, [], $rule);
579
    }
580
581
    /**
582
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") and a ("(?:€|£|\$)[^"]+") discount to every order with items total equal at least ("(?:€|£|\$)[^"]+")$/
583
     */
584
    public function itGivesOffOnEveryProductClassifiedAsAndAFixedDiscountToEveryOrderWithItemsTotalEqualAtLeast(
585
        PromotionInterface $promotion,
586
        $taxonDiscount,
587
        TaxonInterface $taxon,
588
        $orderDiscount,
589
        $targetAmount
590
    ) {
591
        $orderDiscountAction = $this->actionFactory->createFixedDiscount($orderDiscount, $this->sharedStorage->get('channel')->getCode());
592
        $promotion->addAction($orderDiscountAction);
593
594
        $channelCode = $this->sharedStorage->get('channel')->getCode();
595
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
596
597
        $this->createUnitPercentagePromotion(
598
            $promotion,
599
            $taxonDiscount,
600
            $this->getTaxonFilterConfiguration([$taxon->getCode()]),
601
            $rule
602
        );
603
    }
604
605
    /**
606
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+" or "[^"]+") if order contains any product (classified as "[^"]+" or "[^"]+")$/
607
     */
608
    public function itGivesOffOnEveryProductClassifiedAsOrIfOrderContainsAnyProductClassifiedAsOr(
609
        PromotionInterface $promotion,
610
        $discount,
611
        array $discountTaxons,
612
        array $targetTaxons
613
    ) {
614
        $discountTaxonsCodes = [$discountTaxons[0]->getCode(), $discountTaxons[1]->getCode()];
615
        $targetTaxonsCodes = [$targetTaxons[0]->getCode(), $targetTaxons[1]->getCode()];
616
617
        $rule = $this->ruleFactory->createHasTaxon($targetTaxonsCodes);
618
619
        $this->createUnitPercentagePromotion(
620
            $promotion,
621
            $discount,
622
            $this->getTaxonFilterConfiguration($discountTaxonsCodes),
623
            $rule
624
        );
625
    }
626
627
    /**
628
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") if order contains any product (classified as "[^"]+")$/
629
     */
630
    public function itGivesOffOnEveryProductClassifiedAsIfOrderContainsAnyProductClassifiedAs(
631
        PromotionInterface $promotion,
632
        $discount,
633
        $discountTaxon,
634
        $targetTaxon
635
    ) {
636
        $rule = $this->ruleFactory->createHasTaxon([$targetTaxon->getCode()]);
637
638
        $this->createUnitPercentagePromotion(
639
            $promotion,
640
            $discount,
641
            $this->getTaxonFilterConfiguration([$discountTaxon->getCode()]),
642
            $rule
643
        );
644
    }
645
646
    /**
647
     * @Given /^(it) is coupon based promotion$/
648
     * @Given /^(it) is a coupon based promotion$/
649
     */
650
    public function itIsCouponBasedPromotion(PromotionInterface $promotion): void
651
    {
652
        $promotion->setCouponBased(true);
653
654
        $this->objectManager->flush();
655
    }
656
657
    /**
658
     * @Given /^(the promotion) was disabled for the (channel "[^"]+")$/
659
     */
660
    public function thePromotionWasDisabledForTheChannel(PromotionInterface $promotion, ChannelInterface $channel)
661
    {
662
        $promotion->removeChannel($channel);
663
664
        $this->objectManager->flush();
665
    }
666
667
    /**
668
     * @Given /^the (coupon "[^"]+") was used up to its usage limit$/
669
     */
670
    public function theCouponWasUsed(PromotionCouponInterface $coupon)
671
    {
672
        $coupon->setUsed($coupon->getUsageLimit());
673
674
        $this->objectManager->flush();
675
    }
676
677
    /**
678
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains (?:a|an) ("[^"]+" product)$/
679
     */
680
    public function thePromotionGivesOffIfOrderContainsProducts(PromotionInterface $promotion, $discount, ProductInterface $product)
681
    {
682
        $rule = $this->ruleFactory->createContainsProduct($product->getCode());
683
684
        $this->createFixedPromotion($promotion, $discount, [], $rule);
685
    }
686
687
    /**
688
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on a ("[^"]*" product)$/
689
     */
690
    public function itGivesFixedDiscountOffOnAProduct(PromotionInterface $promotion, $discount, ProductInterface $product)
691
    {
692
        $this->createUnitFixedPromotion($promotion, $discount, $this->getProductsFilterConfiguration([$product->getCode()]));
693
    }
694
695
    /**
696
     * @Given /^([^"]+) gives ("[^"]+%") off on a ("[^"]*" product)$/
697
     */
698
    public function itGivesPercentageDiscountOffOnAProduct(PromotionInterface $promotion, $discount, ProductInterface $product)
699
    {
700
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getProductsFilterConfiguration([$product->getCode()]));
701
    }
702
703
    /**
704
     * @Given /^([^"]+) gives ("[^"]+%") off the order for customers from ("[^"]*" group)$/
705
     */
706
    public function thePromotionGivesOffTheOrderForCustomersFromGroup(
707
        PromotionInterface $promotion,
708
        $discount,
709
        CustomerGroupInterface $customerGroup
710
    ) {
711
        /** @var PromotionRuleInterface $rule */
712
        $rule = $this->ruleFactory->createNew();
713
        $rule->setType(CustomerGroupRuleChecker::TYPE);
714
        $rule->setConfiguration(['group_code' => $customerGroup->getCode()]);
715
716
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
717
    }
718
719
    /**
720
     * @Given /^([^"]+) gives ("[^"]+%") discount on shipping to every order over ("(?:€|£|\$)[^"]+")$/
721
     */
722
    public function itGivesDiscountOnShippingToEveryOrderOver(
723
        PromotionInterface $promotion,
724
        $discount,
725
        $itemTotal
726
    ) {
727
        $channelCode = $this->sharedStorage->get('channel')->getCode();
728
        $rule = $this->ruleFactory->createItemTotal($channelCode, $itemTotal);
729
        $action = $this->actionFactory->createShippingPercentageDiscount($discount);
730
731
        $this->persistPromotion($promotion, $action, [], $rule);
732
    }
733
734
    /**
735
     * @Given /^([^"]+) gives free shipping to every order over ("(?:€|£|\$)[^"]+")$/
736
     */
737
    public function itGivesFreeShippingToEveryOrderOver(PromotionInterface $promotion, $itemTotal)
738
    {
739
        $this->itGivesDiscountOnShippingToEveryOrderOver($promotion, 1, $itemTotal);
740
    }
741
742
    /**
743
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,array<string,array>>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
744
     */
745
    private function getTaxonFilterConfiguration(array $taxonCodes)
746
    {
747
        return ['filters' => ['taxons_filter' => ['taxons' => $taxonCodes]]];
748
    }
749
750
    /**
751
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,array<string,array>>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
752
     */
753
    private function getProductsFilterConfiguration(array $productCodes)
754
    {
755
        return ['filters' => ['products_filter' => ['products' => $productCodes]]];
756
    }
757
758
    /**
759
     * @param int $minAmount
760
     * @param int $maxAmount
0 ignored issues
show
Documentation introduced by
Should the type for parameter $maxAmount not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
761
     *
762
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,array<string,integer>>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
763
     */
764
    private function getPriceRangeFilterConfiguration($minAmount, $maxAmount = null)
765
    {
766
        $configuration = ['filters' => ['price_range_filter' => ['min' => $minAmount]]];
767
        if (null !== $maxAmount) {
768
            $configuration['filters']['price_range_filter']['max'] = $maxAmount;
769
        }
770
771
        return $configuration;
772
    }
773
774
    private function createPromotion(string $name, ?string $code = null): PromotionInterface
775
    {
776
        $promotion = $this->testPromotionFactory->createForChannel($name, $this->sharedStorage->get('channel'));
777
778
        if (null !== $code) {
779
            $promotion->setCode($code);
780
        }
781
782
        $this->promotionRepository->add($promotion);
783
        $this->sharedStorage->set('promotion', $promotion);
784
785
        return $promotion;
786
    }
787
788
    /**
789
     * @param int $discount
790
     */
791
    private function createUnitFixedPromotion(PromotionInterface $promotion, $discount, array $configuration = [], PromotionRuleInterface $rule = null)
792
    {
793
        $channelCode = $this->sharedStorage->get('channel')->getCode();
794
795
        $this->persistPromotion(
796
            $promotion,
797
            $this->actionFactory->createUnitFixedDiscount($discount, $channelCode),
798
            [$channelCode => $configuration],
799
            $rule
800
        );
801
    }
802
803
    /**
804
     * @param int $discount
805
     */
806
    private function createUnitPercentagePromotion(PromotionInterface $promotion, $discount, array $configuration = [], PromotionRuleInterface $rule = null)
807
    {
808
        $channelCode = $this->sharedStorage->get('channel')->getCode();
809
810
        $this->persistPromotion(
811
            $promotion,
812
            $this->actionFactory->createUnitPercentageDiscount($discount, $channelCode),
813
            [$channelCode => $configuration],
814
            $rule
815
        );
816
    }
817
818
    /**
819
     * @param int $discount
820
     */
821
    private function createFixedPromotion(
822
        PromotionInterface $promotion,
823
        $discount,
824
        array $configuration = [],
825
        PromotionRuleInterface $rule = null,
826
        ChannelInterface $channel = null
827
    ) {
828
        $channelCode = (null !== $channel) ? $channel->getCode() : $this->sharedStorage->get('channel')->getCode();
829
830
        $this->persistPromotion($promotion, $this->actionFactory->createFixedDiscount($discount, $channelCode), $configuration, $rule);
831
    }
832
833
    /**
834
     * @param float $discount
835
     * @param PromotionRuleInterface $rule
0 ignored issues
show
Documentation introduced by
Should the type for parameter $rule not be null|PromotionRuleInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
836
     */
837
    private function createPercentagePromotion(
838
        PromotionInterface $promotion,
839
        $discount,
840
        array $configuration = [],
841
        PromotionRuleInterface $rule = null
842
    ) {
843
        $this->persistPromotion($promotion, $this->actionFactory->createPercentageDiscount($discount), $configuration, $rule);
844
    }
845
846
    private function persistPromotion(PromotionInterface $promotion, PromotionActionInterface $action, array $configuration, PromotionRuleInterface $rule = null)
847
    {
848
        $configuration = array_merge_recursive($action->getConfiguration(), $configuration);
849
        $action->setConfiguration($configuration);
850
851
        $promotion->addAction($action);
852
        if (null !== $rule) {
853
            $promotion->addRule($rule);
854
        }
855
856
        $this->objectManager->flush();
857
    }
858
859
    private function createCoupon(string $couponCode, ?int $usageLimit = null): PromotionCouponInterface
860
    {
861
        /** @var PromotionCouponInterface $coupon */
862
        $coupon = $this->couponFactory->createNew();
863
        $coupon->setCode($couponCode);
864
        $coupon->setUsageLimit($usageLimit);
865
866
        return $coupon;
867
    }
868
}
869