Completed
Push — 1.3 ( ea96f1...08f6de )
by Kamil
13:44
created

thereIsAPromotionWithHasAtLeastOneFromTaxonsRuleConfiguredWith()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
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) has already reached its usage limit$/
253
     */
254
    public function thisCouponHasReachedItsUsageLimit(PromotionCouponInterface $coupon)
255
    {
256
        $coupon->setUsed(42);
257
        $coupon->setUsageLimit(42);
258
259
        $this->objectManager->flush();
260
    }
261
262
    /**
263
     * @Given /^(this coupon) can be used (\d+) times?$/
264
     */
265
    public function thisCouponCanBeUsedNTimes(PromotionCouponInterface $coupon, $usageLimit)
266
    {
267
        $coupon->setUsageLimit((int) $usageLimit);
268
269
        $this->objectManager->flush();
270
    }
271
272
    /**
273
     * @Given /^(this coupon) can be used twice per customer$/
274
     */
275
    public function thisCouponCanBeUsedTwicePerCustomer(PromotionCouponInterface $coupon)
276
    {
277
        $coupon->setPerCustomerUsageLimit(2);
278
279
        $this->objectManager->flush();
280
    }
281
282
    /**
283
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order$/
284
     */
285
    public function itGivesFixedDiscountToEveryOrder(PromotionInterface $promotion, $discount)
286
    {
287
        $this->createFixedPromotion($promotion, $discount);
288
    }
289
290
    /**
291
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order in the ("[^"]+" channel) and ("(?:€|£|\$)[^"]+") discount to every order in the ("[^"]+" channel)$/
292
     */
293
    public function thisPromotionGivesDiscountToEveryOrderInTheChannelAndDiscountToEveryOrderInTheChannel(
294
        PromotionInterface $promotion,
295
        $firstChannelDiscount,
296
        ChannelInterface $firstChannel,
297
        $secondChannelDiscount,
298
        ChannelInterface $secondChannel
299
    ) {
300
        /** @var PromotionActionInterface $action */
301
        $action = $this->actionFactory->createFixedDiscount($firstChannelDiscount, $firstChannel->getCode());
302
        $action->setConfiguration(array_merge($action->getConfiguration(), [$secondChannel->getCode() => ['amount' => $secondChannelDiscount]]));
303
304
        $promotion->addChannel($firstChannel);
305
        $promotion->addChannel($secondChannel);
306
        $promotion->addAction($action);
307
308
        $this->objectManager->flush();
309
    }
310
311
    /**
312
     * @Given /^([^"]+) gives ("[^"]+%") discount to every order$/
313
     */
314
    public function itGivesPercentageDiscountToEveryOrder(PromotionInterface $promotion, $discount)
315
    {
316
        $this->createPercentagePromotion($promotion, $discount);
317
    }
318
319
    /**
320
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order with quantity at least ([^"]+)$/
321
     */
322
    public function itGivesFixedDiscountToEveryOrderWithQuantityAtLeast(
323
        PromotionInterface $promotion,
324
        $discount,
325
        $quantity
326
    ) {
327
        $rule = $this->ruleFactory->createCartQuantity((int) $quantity);
328
329
        $this->createFixedPromotion($promotion, $discount, [], $rule);
330
    }
331
332
    /**
333
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") discount to every order with items total at least ("[^"]+")$/
334
     */
335
    public function itGivesFixedDiscountToEveryOrderWithItemsTotalAtLeast(
336
        PromotionInterface $promotion,
337
        $discount,
338
        $targetAmount
339
    ) {
340
        $channelCode = $this->sharedStorage->get('channel')->getCode();
341
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
342
343
        $this->createFixedPromotion($promotion, $discount, [], $rule);
344
    }
345
346
    /**
347
     * @Given /^([^"]+) gives ("[^"]+%") discount to every order with items total at least ("[^"]+")$/
348
     */
349
    public function itGivesPercentageDiscountToEveryOrderWithItemsTotalAtLeast(
350
        PromotionInterface $promotion,
351
        $discount,
352
        $targetAmount
353
    ) {
354
        $channelCode = $this->sharedStorage->get('channel')->getCode();
355
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
356
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
357
    }
358
359
    /**
360
     * @Given /^([^"]+) gives ("[^"]+%") off on every product when the item total is at least ("(?:€|£|\$)[^"]+")$/
361
     */
362
    public function itGivesOffOnEveryItemWhenItemTotalExceeds(
363
        PromotionInterface $promotion,
364
        $discount,
365
        $targetAmount
366
    ) {
367
        $channelCode = $this->sharedStorage->get('channel')->getCode();
368
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
369
370
        $this->createUnitPercentagePromotion($promotion, $discount, [], $rule);
371
    }
372
373
    /**
374
     * @Given /^([^"]+) gives ("[^"]+%") discount on shipping to every order$/
375
     */
376
    public function itGivesPercentageDiscountOnShippingToEveryOrder(PromotionInterface $promotion, $discount)
377
    {
378
        $action = $this->actionFactory->createShippingPercentageDiscount($discount);
379
        $promotion->addAction($action);
380
381
        $this->objectManager->flush();
382
    }
383
384
    /**
385
     * @Given /^([^"]+) gives free shipping to every order$/
386
     */
387
    public function thePromotionGivesFreeShippingToEveryOrder(PromotionInterface $promotion)
388
    {
389
        $this->itGivesPercentageDiscountOnShippingToEveryOrder($promotion, 1);
390
    }
391
392
    /**
393
     * @Given /^([^"]+) gives(?:| another) ("[^"]+%") off every product (classified as "[^"]+")$/
394
     */
395
    public function itGivesPercentageOffEveryProductClassifiedAs(
396
        PromotionInterface $promotion,
397
        $discount,
398
        TaxonInterface $taxon
399
    ) {
400
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getTaxonFilterConfiguration([$taxon->getCode()]));
401
    }
402
403
    /**
404
     * @Given /^([^"]+) gives(?:| another) ("(?:€|£|\$)[^"]+") off on every product (classified as "[^"]+")$/
405
     */
406
    public function itGivesFixedOffEveryProductClassifiedAs(
407
        PromotionInterface $promotion,
408
        $discount,
409
        TaxonInterface $taxon
410
    ) {
411
        $this->createUnitFixedPromotion($promotion, $discount, $this->getTaxonFilterConfiguration([$taxon->getCode()]));
412
    }
413
414
    /**
415
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product with minimum price at ("(?:€|£|\$)[^"]+")$/
416
     */
417
    public function thisPromotionGivesOffOnEveryProductWithMinimumPriceAt(
418
        PromotionInterface $promotion,
419
        $discount,
420
        $amount
421
    ) {
422
        $this->createUnitFixedPromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
423
    }
424
425
    /**
426
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:€|£|\$)[^"]+")$/
427
     */
428
    public function thisPromotionGivesOffOnEveryProductPricedBetween(
429
        PromotionInterface $promotion,
430
        $discount,
431
        $minAmount,
432
        $maxAmount
433
    ) {
434
        $this->createUnitFixedPromotion(
435
            $promotion,
436
            $discount,
437
            $this->getPriceRangeFilterConfiguration($minAmount, $maxAmount)
438
        );
439
    }
440
441
    /**
442
     * @Given /^([^"]+) gives ("[^"]+%") off on every product with minimum price at ("(?:€|£|\$)[^"]+")$/
443
     */
444
    public function thisPromotionPercentageGivesOffOnEveryProductWithMinimumPriceAt(
445
        PromotionInterface $promotion,
446
        $discount,
447
        $amount
448
    ) {
449
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getPriceRangeFilterConfiguration($amount));
450
    }
451
452
    /**
453
     * @Given /^([^"]+) gives ("[^"]+%") off on every product priced between ("(?:€|£|\$)[^"]+") and ("(?:€|£|\$)[^"]+")$/
454
     */
455
    public function thisPromotionPercentageGivesOffOnEveryProductPricedBetween(
456
        PromotionInterface $promotion,
457
        $discount,
458
        $minAmount,
459
        $maxAmount
460
    ) {
461
        $this->createUnitPercentagePromotion(
462
            $promotion,
463
            $discount,
464
            $this->getPriceRangeFilterConfiguration($minAmount, $maxAmount)
465
        );
466
    }
467
468
    /**
469
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+")$/
470
     */
471
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAs(
472
        PromotionInterface $promotion,
473
        $discount,
474
        TaxonInterface $taxon
475
    ) {
476
        $rule = $this->ruleFactory->createHasTaxon([$taxon->getCode()]);
477
478
        $this->createFixedPromotion($promotion, $discount, [], $rule);
479
    }
480
481
    /**
482
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+" or "[^"]+")$/
483
     */
484
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsOr(
485
        PromotionInterface $promotion,
486
        $discount,
487
        array $taxons
488
    ) {
489
        $rule = $this->ruleFactory->createHasTaxon([$taxons[0]->getCode(), $taxons[1]->getCode()]);
490
491
        $this->createFixedPromotion($promotion, $discount, [], $rule);
492
    }
493
494
    /**
495
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+") with a minimum value of ("(?:€|£|\$)[^"]+")$/
496
     */
497
    public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsAndPricedAt(
498
        PromotionInterface $promotion,
499
        $discount,
500
        TaxonInterface $taxon,
501
        $amount
502
    ) {
503
        $channelCode = $this->sharedStorage->get('channel')->getCode();
504
        $rule = $this->ruleFactory->createItemsFromTaxonTotal($channelCode, $taxon->getCode(), $amount);
505
506
        $this->createFixedPromotion($promotion, $discount, [], $rule);
507
    }
508
509
    /**
510
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off customer's (\d)(?:st|nd|rd|th) order$/
511
     */
512
    public function itGivesFixedOffCustomersNthOrder(PromotionInterface $promotion, $discount, $nth)
513
    {
514
        $rule = $this->ruleFactory->createNthOrder((int) $nth);
515
516
        $this->createFixedPromotion($promotion, $discount, [], $rule);
517
    }
518
519
    /**
520
     * @Given /^([^"]+) gives ("[^"]+%") off on the customer's (\d)(?:st|nd|rd|th) order$/
521
     */
522
    public function itGivesPercentageOffCustomersNthOrder(PromotionInterface $promotion, $discount, $nth)
523
    {
524
        $rule = $this->ruleFactory->createNthOrder((int) $nth);
525
526
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
527
    }
528
529
    /**
530
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") and ("(?:€|£|\$)[^"]+") discount on every order$/
531
     */
532
    public function itGivesPercentageOffOnEveryProductClassifiedAsAndAmountDiscountOnOrder(
533
        PromotionInterface $promotion,
534
        $productDiscount,
535
        TaxonInterface $discountTaxon,
536
        $orderDiscount
537
    ) {
538
        $this->createUnitPercentagePromotion($promotion, $productDiscount, $this->getTaxonFilterConfiguration([$discountTaxon->getCode()]));
539
        $this->createFixedPromotion($promotion, $orderDiscount);
540
    }
541
542
    /**
543
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on every product (classified as "[^"]+") and a free shipping to every order with items total equal at least ("[^"]+")$/
544
     */
545
    public function itGivesOffOnEveryProductClassifiedAsAndAFreeShippingToEveryOrderWithItemsTotalEqualAtLeast(
546
        PromotionInterface $promotion,
547
        $discount,
548
        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...
549
        $targetAmount
550
    ) {
551
        $freeShippingAction = $this->actionFactory->createShippingPercentageDiscount(1);
552
        $promotion->addAction($freeShippingAction);
553
554
        $channelCode = $this->sharedStorage->get('channel')->getCode();
555
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
556
557
        $this->createUnitFixedPromotion($promotion, $discount, [], $rule);
558
    }
559
560
    /**
561
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") and a ("(?:€|£|\$)[^"]+") discount to every order with items total equal at least ("(?:€|£|\$)[^"]+")$/
562
     */
563
    public function itGivesOffOnEveryProductClassifiedAsAndAFixedDiscountToEveryOrderWithItemsTotalEqualAtLeast(
564
        PromotionInterface $promotion,
565
        $taxonDiscount,
566
        TaxonInterface $taxon,
567
        $orderDiscount,
568
        $targetAmount
569
    ) {
570
        $orderDiscountAction = $this->actionFactory->createFixedDiscount($orderDiscount, $this->sharedStorage->get('channel')->getCode());
571
        $promotion->addAction($orderDiscountAction);
572
573
        $channelCode = $this->sharedStorage->get('channel')->getCode();
574
        $rule = $this->ruleFactory->createItemTotal($channelCode, $targetAmount);
575
576
        $this->createUnitPercentagePromotion(
577
            $promotion,
578
            $taxonDiscount,
579
            $this->getTaxonFilterConfiguration([$taxon->getCode()]),
580
            $rule
581
        );
582
    }
583
584
    /**
585
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+" or "[^"]+") if order contains any product (classified as "[^"]+" or "[^"]+")$/
586
     */
587
    public function itGivesOffOnEveryProductClassifiedAsOrIfOrderContainsAnyProductClassifiedAsOr(
588
        PromotionInterface $promotion,
589
        $discount,
590
        array $discountTaxons,
591
        array $targetTaxons
592
    ) {
593
        $discountTaxonsCodes = [$discountTaxons[0]->getCode(), $discountTaxons[1]->getCode()];
594
        $targetTaxonsCodes = [$targetTaxons[0]->getCode(), $targetTaxons[1]->getCode()];
595
596
        $rule = $this->ruleFactory->createHasTaxon($targetTaxonsCodes);
597
598
        $this->createUnitPercentagePromotion(
599
            $promotion,
600
            $discount,
601
            $this->getTaxonFilterConfiguration($discountTaxonsCodes),
602
            $rule
603
        );
604
    }
605
606
    /**
607
     * @Given /^([^"]+) gives ("[^"]+%") off on every product (classified as "[^"]+") if order contains any product (classified as "[^"]+")$/
608
     */
609
    public function itGivesOffOnEveryProductClassifiedAsIfOrderContainsAnyProductClassifiedAs(
610
        PromotionInterface $promotion,
611
        $discount,
612
        $discountTaxon,
613
        $targetTaxon
614
    ) {
615
        $rule = $this->ruleFactory->createHasTaxon([$targetTaxon->getCode()]);
616
617
        $this->createUnitPercentagePromotion(
618
            $promotion,
619
            $discount,
620
            $this->getTaxonFilterConfiguration([$discountTaxon->getCode()]),
621
            $rule
622
        );
623
    }
624
625
    /**
626
     * @Given /^(it) is coupon based promotion$/
627
     */
628
    public function itIsCouponBasedPromotion(PromotionInterface $promotion)
629
    {
630
        $promotion->setCouponBased(true);
631
632
        $this->objectManager->flush();
633
    }
634
635
    /**
636
     * @Given /^(the promotion) was disabled for the (channel "[^"]+")$/
637
     */
638
    public function thePromotionWasDisabledForTheChannel(PromotionInterface $promotion, ChannelInterface $channel)
639
    {
640
        $promotion->removeChannel($channel);
641
642
        $this->objectManager->flush();
643
    }
644
645
    /**
646
     * @Given /^the (coupon "[^"]+") was used up to its usage limit$/
647
     */
648
    public function theCouponWasUsed(PromotionCouponInterface $coupon)
649
    {
650
        $coupon->setUsed($coupon->getUsageLimit());
651
652
        $this->objectManager->flush();
653
    }
654
655
    /**
656
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains (?:a|an) ("[^"]+" product)$/
657
     */
658
    public function thePromotionGivesOffIfOrderContainsProducts(PromotionInterface $promotion, $discount, ProductInterface $product)
659
    {
660
        $rule = $this->ruleFactory->createContainsProduct($product->getCode());
661
662
        $this->createFixedPromotion($promotion, $discount, [], $rule);
663
    }
664
665
    /**
666
     * @Given /^([^"]+) gives ("(?:€|£|\$)[^"]+") off on a ("[^"]*" product)$/
667
     */
668
    public function itGivesFixedDiscountOffOnAProduct(PromotionInterface $promotion, $discount, ProductInterface $product)
669
    {
670
        $this->createUnitFixedPromotion($promotion, $discount, $this->getProductsFilterConfiguration([$product->getCode()]));
671
    }
672
673
    /**
674
     * @Given /^([^"]+) gives ("[^"]+%") off on a ("[^"]*" product)$/
675
     */
676
    public function itGivesPercentageDiscountOffOnAProduct(PromotionInterface $promotion, $discount, ProductInterface $product)
677
    {
678
        $this->createUnitPercentagePromotion($promotion, $discount, $this->getProductsFilterConfiguration([$product->getCode()]));
679
    }
680
681
    /**
682
     * @Given /^([^"]+) gives ("[^"]+%") off the order for customers from ("[^"]*" group)$/
683
     */
684
    public function thePromotionGivesOffTheOrderForCustomersFromGroup(
685
        PromotionInterface $promotion,
686
        $discount,
687
        CustomerGroupInterface $customerGroup
688
    ) {
689
        /** @var PromotionRuleInterface $rule */
690
        $rule = $this->ruleFactory->createNew();
691
        $rule->setType(CustomerGroupRuleChecker::TYPE);
692
        $rule->setConfiguration(['group_code' => $customerGroup->getCode()]);
693
694
        $this->createPercentagePromotion($promotion, $discount, [], $rule);
695
    }
696
697
    /**
698
     * @Given /^([^"]+) gives ("[^"]+%") discount on shipping to every order over ("(?:€|£|\$)[^"]+")$/
699
     */
700
    public function itGivesDiscountOnShippingToEveryOrderOver(
701
        PromotionInterface $promotion,
702
        $discount,
703
        $itemTotal
704
    ) {
705
        $channelCode = $this->sharedStorage->get('channel')->getCode();
706
        $rule = $this->ruleFactory->createItemTotal($channelCode, $itemTotal);
707
        $action = $this->actionFactory->createShippingPercentageDiscount($discount);
708
709
        $this->persistPromotion($promotion, $action, [], $rule);
710
    }
711
712
    /**
713
     * @Given /^([^"]+) gives free shipping to every order over ("(?:€|£|\$)[^"]+")$/
714
     */
715
    public function itGivesFreeShippingToEveryOrderOver(PromotionInterface $promotion, $itemTotal)
716
    {
717
        $this->itGivesDiscountOnShippingToEveryOrderOver($promotion, 1, $itemTotal);
718
    }
719
720
    /**
721
     * @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...
722
     */
723
    private function getTaxonFilterConfiguration(array $taxonCodes)
724
    {
725
        return ['filters' => ['taxons_filter' => ['taxons' => $taxonCodes]]];
726
    }
727
728
    /**
729
     * @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...
730
     */
731
    private function getProductsFilterConfiguration(array $productCodes)
732
    {
733
        return ['filters' => ['products_filter' => ['products' => $productCodes]]];
734
    }
735
736
    /**
737
     * @param int $minAmount
738
     * @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...
739
     *
740
     * @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...
741
     */
742
    private function getPriceRangeFilterConfiguration($minAmount, $maxAmount = null)
743
    {
744
        $configuration = ['filters' => ['price_range_filter' => ['min' => $minAmount]]];
745
        if (null !== $maxAmount) {
746
            $configuration['filters']['price_range_filter']['max'] = $maxAmount;
747
        }
748
749
        return $configuration;
750
    }
751
752
    private function createPromotion(string $name, ?string $code = null): PromotionInterface
753
    {
754
        $promotion = $this->testPromotionFactory->createForChannel($name, $this->sharedStorage->get('channel'));
755
756
        if (null !== $code) {
757
            $promotion->setCode($code);
758
        }
759
760
        $this->promotionRepository->add($promotion);
761
        $this->sharedStorage->set('promotion', $promotion);
762
763
        return $promotion;
764
    }
765
766
    /**
767
     * @param int $discount
768
     */
769
    private function createUnitFixedPromotion(PromotionInterface $promotion, $discount, array $configuration = [], PromotionRuleInterface $rule = null)
770
    {
771
        $channelCode = $this->sharedStorage->get('channel')->getCode();
772
773
        $this->persistPromotion(
774
            $promotion,
775
            $this->actionFactory->createUnitFixedDiscount($discount, $channelCode),
776
            [$channelCode => $configuration],
777
            $rule
778
        );
779
    }
780
781
    /**
782
     * @param int $discount
783
     */
784
    private function createUnitPercentagePromotion(PromotionInterface $promotion, $discount, array $configuration = [], PromotionRuleInterface $rule = null)
785
    {
786
        $channelCode = $this->sharedStorage->get('channel')->getCode();
787
788
        $this->persistPromotion(
789
            $promotion,
790
            $this->actionFactory->createUnitPercentageDiscount($discount, $channelCode),
791
            [$channelCode => $configuration],
792
            $rule
793
        );
794
    }
795
796
    /**
797
     * @param int $discount
798
     */
799
    private function createFixedPromotion(
800
        PromotionInterface $promotion,
801
        $discount,
802
        array $configuration = [],
803
        PromotionRuleInterface $rule = null,
804
        ChannelInterface $channel = null
805
    ) {
806
        $channelCode = (null !== $channel) ? $channel->getCode() : $this->sharedStorage->get('channel')->getCode();
807
808
        $this->persistPromotion($promotion, $this->actionFactory->createFixedDiscount($discount, $channelCode), $configuration, $rule);
809
    }
810
811
    /**
812
     * @param float $discount
813
     * @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...
814
     */
815
    private function createPercentagePromotion(
816
        PromotionInterface $promotion,
817
        $discount,
818
        array $configuration = [],
819
        PromotionRuleInterface $rule = null
820
    ) {
821
        $this->persistPromotion($promotion, $this->actionFactory->createPercentageDiscount($discount), $configuration, $rule);
822
    }
823
824
    private function persistPromotion(PromotionInterface $promotion, PromotionActionInterface $action, array $configuration, PromotionRuleInterface $rule = null)
825
    {
826
        $configuration = array_merge_recursive($action->getConfiguration(), $configuration);
827
        $action->setConfiguration($configuration);
828
829
        $promotion->addAction($action);
830
        if (null !== $rule) {
831
            $promotion->addRule($rule);
832
        }
833
834
        $this->objectManager->flush();
835
    }
836
837
    private function createCoupon(string $couponCode, ?int $usageLimit = null): PromotionCouponInterface
838
    {
839
        /** @var PromotionCouponInterface $coupon */
840
        $coupon = $this->couponFactory->createNew();
841
        $coupon->setCode($couponCode);
842
        $coupon->setUsageLimit($usageLimit);
843
844
        return $coupon;
845
    }
846
}
847