mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-05 20:57:12 +00:00
Add per-channel configuration for promotion rules and actions
This commit is contained in:
parent
96233aa29a
commit
6b327f4db8
18 changed files with 852 additions and 2 deletions
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Action;
|
||||||
|
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\ChannelCollectionType;
|
||||||
|
use Sylius\Bundle\PromotionBundle\Form\Type\Action\PercentageDiscountConfigurationType;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
final class ChannelBasedPercentageDiscountConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'entry_type' => PercentageDiscountConfigurationType::class,
|
||||||
|
'entry_options' => fn (ChannelInterface $channel) => [
|
||||||
|
'label' => $channel->getName(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent(): string
|
||||||
|
{
|
||||||
|
return ChannelCollectionType::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||||
|
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\ChannelCollectionType;
|
||||||
|
use Sylius\Bundle\PromotionBundle\Form\Type\Rule\CartQuantityConfigurationType;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
final class ChannelBasedCartQuantityConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'entry_type' => CartQuantityConfigurationType::class,
|
||||||
|
'entry_options' => fn (ChannelInterface $channel) => [
|
||||||
|
'label' => $channel->getName(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent(): string
|
||||||
|
{
|
||||||
|
return ChannelCollectionType::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||||
|
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\ChannelCollectionType;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
final class ChannelBasedContainsProductConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'entry_type' => ContainsProductConfigurationType::class,
|
||||||
|
'entry_options' => fn (ChannelInterface $channel) => [
|
||||||
|
'label' => $channel->getName(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent(): string
|
||||||
|
{
|
||||||
|
return ChannelCollectionType::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||||
|
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\ChannelCollectionType;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
final class ChannelBasedCustomerGroupConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'entry_type' => CustomerGroupConfigurationType::class,
|
||||||
|
'entry_options' => fn (ChannelInterface $channel) => [
|
||||||
|
'label' => $channel->getName(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent(): string
|
||||||
|
{
|
||||||
|
return ChannelCollectionType::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||||
|
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\ChannelCollectionType;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
final class ChannelBasedHasTaxonConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'entry_type' => HasTaxonConfigurationType::class,
|
||||||
|
'entry_options' => fn (ChannelInterface $channel) => [
|
||||||
|
'label' => $channel->getName(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent(): string
|
||||||
|
{
|
||||||
|
return ChannelCollectionType::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||||
|
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\ChannelCollectionType;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
final class ChannelBasedNthOrderConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'entry_type' => NthOrderConfigurationType::class,
|
||||||
|
'entry_options' => fn (ChannelInterface $channel) => [
|
||||||
|
'label' => $channel->getName(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent(): string
|
||||||
|
{
|
||||||
|
return ChannelCollectionType::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||||
|
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\ChannelCollectionType;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
final class ChannelBasedShippingCountryConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'entry_type' => ShippingCountryConfigurationType::class,
|
||||||
|
'entry_options' => fn (ChannelInterface $channel) => [
|
||||||
|
'label' => $channel->getName(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent(): string
|
||||||
|
{
|
||||||
|
return ChannelCollectionType::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,9 +44,15 @@ sylius_promotion:
|
||||||
order_percentage_discount:
|
order_percentage_discount:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_action_order_percentage_discount'
|
- 'sylius_promotion_action_order_percentage_discount'
|
||||||
|
order_percentage_discount_per_channel:
|
||||||
|
- 'sylius'
|
||||||
|
- 'sylius_promotion_action_order_percentage_discount_per_channel'
|
||||||
shipping_percentage_discount:
|
shipping_percentage_discount:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_action_shipping_percentage_discount'
|
- 'sylius_promotion_action_shipping_percentage_discount'
|
||||||
|
shipping_percentage_discount_per_channel:
|
||||||
|
- 'sylius'
|
||||||
|
- 'sylius_promotion_action_shipping_percentage_discount_per_channel'
|
||||||
order_fixed_discount:
|
order_fixed_discount:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_action_order_fixed_discount'
|
- 'sylius_promotion_action_order_fixed_discount'
|
||||||
|
|
@ -62,18 +68,36 @@ sylius_promotion:
|
||||||
customer_group:
|
customer_group:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_rule_customer_group'
|
- 'sylius_promotion_rule_customer_group'
|
||||||
|
customer_group_per_channel:
|
||||||
|
- 'sylius'
|
||||||
|
- 'sylius_promotion_rule_customer_group_per_channel'
|
||||||
nth_order:
|
nth_order:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_rule_nth_order'
|
- 'sylius_promotion_rule_nth_order'
|
||||||
|
nth_order_per_channel:
|
||||||
|
- 'sylius'
|
||||||
|
- 'sylius_promotion_rule_nth_order_per_channel'
|
||||||
shipping_country:
|
shipping_country:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_rule_shipping_country'
|
- 'sylius_promotion_rule_shipping_country'
|
||||||
|
shipping_country_per_channel:
|
||||||
|
- 'sylius'
|
||||||
|
- 'sylius_promotion_rule_shipping_country_per_channel'
|
||||||
has_taxon:
|
has_taxon:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_rule_has_taxon'
|
- 'sylius_promotion_rule_has_taxon'
|
||||||
|
has_taxon_per_channel:
|
||||||
|
- 'sylius'
|
||||||
|
- 'sylius_promotion_rule_has_taxon_per_channel'
|
||||||
total_of_items_from_taxon:
|
total_of_items_from_taxon:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_rule_total_of_items_from_taxon'
|
- 'sylius_promotion_rule_total_of_items_from_taxon'
|
||||||
contains_product:
|
contains_product:
|
||||||
- 'sylius'
|
- 'sylius'
|
||||||
- 'sylius_promotion_rule_contains_product'
|
- 'sylius_promotion_rule_contains_product'
|
||||||
|
contains_product_per_channel:
|
||||||
|
- 'sylius'
|
||||||
|
- 'sylius_promotion_rule_contains_product_per_channel'
|
||||||
|
cart_quantity_per_channel:
|
||||||
|
- 'sylius'
|
||||||
|
- 'sylius_promotion_rule_cart_quantity_per_channel'
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,16 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
||||||
|
|
||||||
use Sylius\Bundle\CoreBundle\Doctrine\ORM\Promotion\Modifier\AtomicOrderPromotionsUsageModifier;
|
use Sylius\Bundle\CoreBundle\Doctrine\ORM\Promotion\Modifier\AtomicOrderPromotionsUsageModifier;
|
||||||
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Action\ChannelBasedFixedDiscountConfigurationType;
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Action\ChannelBasedFixedDiscountConfigurationType;
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Action\ChannelBasedPercentageDiscountConfigurationType;
|
||||||
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Action\ChannelBasedUnitFixedDiscountConfigurationType;
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Action\ChannelBasedUnitFixedDiscountConfigurationType;
|
||||||
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Action\ChannelBasedUnitPercentageDiscountConfigurationType;
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Action\ChannelBasedUnitPercentageDiscountConfigurationType;
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedCartQuantityConfigurationType;
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedContainsProductConfigurationType;
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedCustomerGroupConfigurationType;
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedHasTaxonConfigurationType;
|
||||||
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedItemTotalConfigurationType;
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedItemTotalConfigurationType;
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedNthOrderConfigurationType;
|
||||||
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedShippingCountryConfigurationType;
|
||||||
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedTotalOfItemsFromTaxonConfigurationType;
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ChannelBasedTotalOfItemsFromTaxonConfigurationType;
|
||||||
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ContainsProductConfigurationType;
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ContainsProductConfigurationType;
|
||||||
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\CustomerGroupConfigurationType;
|
use Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\CustomerGroupConfigurationType;
|
||||||
|
|
@ -32,6 +39,7 @@ use Sylius\Component\Core\Factory\PromotionRuleFactory;
|
||||||
use Sylius\Component\Core\Factory\PromotionRuleFactoryInterface;
|
use Sylius\Component\Core\Factory\PromotionRuleFactoryInterface;
|
||||||
use Sylius\Component\Core\Promotion\Action\FixedDiscountPromotionActionCommand;
|
use Sylius\Component\Core\Promotion\Action\FixedDiscountPromotionActionCommand;
|
||||||
use Sylius\Component\Core\Promotion\Action\PercentageDiscountPromotionActionCommand;
|
use Sylius\Component\Core\Promotion\Action\PercentageDiscountPromotionActionCommand;
|
||||||
|
use Sylius\Component\Core\Promotion\Action\PerChannelPromotionActionCommand;
|
||||||
use Sylius\Component\Core\Promotion\Action\ShippingPercentageDiscountPromotionActionCommand;
|
use Sylius\Component\Core\Promotion\Action\ShippingPercentageDiscountPromotionActionCommand;
|
||||||
use Sylius\Component\Core\Promotion\Action\UnitFixedDiscountPromotionActionCommand;
|
use Sylius\Component\Core\Promotion\Action\UnitFixedDiscountPromotionActionCommand;
|
||||||
use Sylius\Component\Core\Promotion\Action\UnitPercentageDiscountPromotionActionCommand;
|
use Sylius\Component\Core\Promotion\Action\UnitPercentageDiscountPromotionActionCommand;
|
||||||
|
|
@ -46,6 +54,7 @@ use Sylius\Component\Core\Promotion\Checker\Rule\CustomerGroupRuleChecker;
|
||||||
use Sylius\Component\Core\Promotion\Checker\Rule\HasTaxonRuleChecker;
|
use Sylius\Component\Core\Promotion\Checker\Rule\HasTaxonRuleChecker;
|
||||||
use Sylius\Component\Core\Promotion\Checker\Rule\ItemTotalRuleChecker;
|
use Sylius\Component\Core\Promotion\Checker\Rule\ItemTotalRuleChecker;
|
||||||
use Sylius\Component\Core\Promotion\Checker\Rule\NthOrderRuleChecker;
|
use Sylius\Component\Core\Promotion\Checker\Rule\NthOrderRuleChecker;
|
||||||
|
use Sylius\Component\Core\Promotion\Checker\Rule\PerChannelRuleChecker;
|
||||||
use Sylius\Component\Core\Promotion\Checker\Rule\ShippingCountryRuleChecker;
|
use Sylius\Component\Core\Promotion\Checker\Rule\ShippingCountryRuleChecker;
|
||||||
use Sylius\Component\Core\Promotion\Checker\Rule\TotalOfItemsFromTaxonRuleChecker;
|
use Sylius\Component\Core\Promotion\Checker\Rule\TotalOfItemsFromTaxonRuleChecker;
|
||||||
use Sylius\Component\Core\Promotion\Checker\TaxonInPromotionRuleChecker;
|
use Sylius\Component\Core\Promotion\Checker\TaxonInPromotionRuleChecker;
|
||||||
|
|
@ -123,6 +132,42 @@ return static function (ContainerConfigurator $container) {
|
||||||
->tag('sylius.promotion_rule_checker', ['type' => 'cart_quantity', 'label' => 'sylius.form.promotion_rule.cart_quantity', 'form_type' => CartQuantityConfigurationType::class])
|
->tag('sylius.promotion_rule_checker', ['type' => 'cart_quantity', 'label' => 'sylius.form.promotion_rule.cart_quantity', 'form_type' => CartQuantityConfigurationType::class])
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$services
|
||||||
|
->set('sylius.checker.promotion_rule.customer_group_per_channel', PerChannelRuleChecker::class)
|
||||||
|
->args([service('sylius.checker.promotion_rule.customer_group')])
|
||||||
|
->tag('sylius.promotion_rule_checker', ['type' => 'customer_group_per_channel', 'label' => 'sylius.form.promotion_rule.customer_group_per_channel', 'form_type' => ChannelBasedCustomerGroupConfigurationType::class])
|
||||||
|
;
|
||||||
|
|
||||||
|
$services
|
||||||
|
->set('sylius.checker.promotion_rule.nth_order_per_channel', PerChannelRuleChecker::class)
|
||||||
|
->args([service('sylius.checker.promotion_rule.nth_order')])
|
||||||
|
->tag('sylius.promotion_rule_checker', ['type' => 'nth_order_per_channel', 'label' => 'sylius.form.promotion_rule.nth_order_per_channel', 'form_type' => ChannelBasedNthOrderConfigurationType::class])
|
||||||
|
;
|
||||||
|
|
||||||
|
$services
|
||||||
|
->set('sylius.checker.promotion_rule.shipping_country_per_channel', PerChannelRuleChecker::class)
|
||||||
|
->args([service('sylius.checker.promotion_rule.shipping_country')])
|
||||||
|
->tag('sylius.promotion_rule_checker', ['type' => 'shipping_country_per_channel', 'label' => 'sylius.form.promotion_rule.shipping_country_per_channel', 'form_type' => ChannelBasedShippingCountryConfigurationType::class])
|
||||||
|
;
|
||||||
|
|
||||||
|
$services
|
||||||
|
->set('sylius.checker.promotion_rule.has_taxon_per_channel', PerChannelRuleChecker::class)
|
||||||
|
->args([service('sylius.checker.promotion_rule.has_taxon')])
|
||||||
|
->tag('sylius.promotion_rule_checker', ['type' => 'has_taxon_per_channel', 'label' => 'sylius.form.promotion_rule.has_at_least_one_from_taxons_per_channel', 'form_type' => ChannelBasedHasTaxonConfigurationType::class])
|
||||||
|
;
|
||||||
|
|
||||||
|
$services
|
||||||
|
->set('sylius.checker.promotion_rule.contains_product_per_channel', PerChannelRuleChecker::class)
|
||||||
|
->args([service('sylius.checker.promotion_rule.contains_product')])
|
||||||
|
->tag('sylius.promotion_rule_checker', ['type' => 'contains_product_per_channel', 'label' => 'sylius.form.promotion_rule.contains_product_per_channel', 'form_type' => ChannelBasedContainsProductConfigurationType::class])
|
||||||
|
;
|
||||||
|
|
||||||
|
$services
|
||||||
|
->set('sylius.checker.promotion_rule.cart_quantity_per_channel', PerChannelRuleChecker::class)
|
||||||
|
->args([service('sylius.checker.promotion_rule.cart_quantity')])
|
||||||
|
->tag('sylius.promotion_rule_checker', ['type' => 'cart_quantity_per_channel', 'label' => 'sylius.form.promotion_rule.cart_quantity_per_channel', 'form_type' => ChannelBasedCartQuantityConfigurationType::class])
|
||||||
|
;
|
||||||
|
|
||||||
$services
|
$services
|
||||||
->set('sylius.command.promotion_action.fixed_discount', FixedDiscountPromotionActionCommand::class)
|
->set('sylius.command.promotion_action.fixed_discount', FixedDiscountPromotionActionCommand::class)
|
||||||
->args([
|
->args([
|
||||||
|
|
@ -173,6 +218,18 @@ return static function (ContainerConfigurator $container) {
|
||||||
->tag('sylius.promotion_action', ['type' => 'shipping_percentage_discount', 'label' => 'sylius.form.promotion_action.shipping_percentage_discount', 'form_type' => PercentageDiscountConfigurationType::class])
|
->tag('sylius.promotion_action', ['type' => 'shipping_percentage_discount', 'label' => 'sylius.form.promotion_action.shipping_percentage_discount', 'form_type' => PercentageDiscountConfigurationType::class])
|
||||||
;
|
;
|
||||||
|
|
||||||
|
$services
|
||||||
|
->set('sylius.command.promotion_action.percentage_discount_per_channel', PerChannelPromotionActionCommand::class)
|
||||||
|
->args([service('sylius.command.promotion_action.percentage_discount')])
|
||||||
|
->tag('sylius.promotion_action', ['type' => 'order_percentage_discount_per_channel', 'label' => 'sylius.form.promotion_action.order_percentage_discount_per_channel', 'form_type' => ChannelBasedPercentageDiscountConfigurationType::class])
|
||||||
|
;
|
||||||
|
|
||||||
|
$services
|
||||||
|
->set('sylius.command.promotion_action.shipping_percentage_discount_per_channel', PerChannelPromotionActionCommand::class)
|
||||||
|
->args([service('sylius.command.promotion_action.shipping_percentage_discount')])
|
||||||
|
->tag('sylius.promotion_action', ['type' => 'shipping_percentage_discount_per_channel', 'label' => 'sylius.form.promotion_action.shipping_percentage_discount_per_channel', 'form_type' => ChannelBasedPercentageDiscountConfigurationType::class])
|
||||||
|
;
|
||||||
|
|
||||||
$services
|
$services
|
||||||
->set('sylius.checker.promotion.promotion_coupon_per_customer_usage_limit_eligibility', PromotionCouponPerCustomerUsageLimitEligibilityChecker::class)
|
->set('sylius.checker.promotion.promotion_coupon_per_customer_usage_limit_eligibility', PromotionCouponPerCustomerUsageLimitEligibilityChecker::class)
|
||||||
->args([service('sylius.repository.order')])
|
->args([service('sylius.repository.order')])
|
||||||
|
|
|
||||||
|
|
@ -280,6 +280,46 @@
|
||||||
</constraint>
|
</constraint>
|
||||||
</option>
|
</option>
|
||||||
</constraint>
|
</constraint>
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">
|
||||||
|
<value>sylius_promotion_action_order_percentage_discount_per_channel</value>
|
||||||
|
<value>sylius_promotion_action_shipping_percentage_discount_per_channel</value>
|
||||||
|
</option>
|
||||||
|
<option name="validateAgainstAllChannels">true</option>
|
||||||
|
<option name="channelAwarePropertyPath">promotion</option>
|
||||||
|
<option name="constraints">
|
||||||
|
<constraint name="Collection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="fields">
|
||||||
|
<value key="percentage">
|
||||||
|
<constraint name="NotBlank">
|
||||||
|
<option name="groups">
|
||||||
|
<value>sylius_promotion_action_order_percentage_discount_per_channel</value>
|
||||||
|
<value>sylius_promotion_action_shipping_percentage_discount_per_channel</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Type">
|
||||||
|
<option name="type">numeric</option>
|
||||||
|
<option name="groups">
|
||||||
|
<value>sylius_promotion_action_order_percentage_discount_per_channel</value>
|
||||||
|
<value>sylius_promotion_action_shipping_percentage_discount_per_channel</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Range">
|
||||||
|
<option name="min">0</option>
|
||||||
|
<option name="max">1</option>
|
||||||
|
<option name="notInRangeMessage">sylius.promotion_action.percentage_discount_configuration.not_in_range</option>
|
||||||
|
<option name="groups">
|
||||||
|
<value>sylius_promotion_action_order_percentage_discount_per_channel</value>
|
||||||
|
<value>sylius_promotion_action_shipping_percentage_discount_per_channel</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\PromotionConfigurationChannelCodes">
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\PromotionConfigurationChannelCodes">
|
||||||
<option name="groups">
|
<option name="groups">
|
||||||
<value>sylius</value>
|
<value>sylius</value>
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,163 @@
|
||||||
</constraint>
|
</constraint>
|
||||||
</option>
|
</option>
|
||||||
</constraint>
|
</constraint>
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_cart_quantity_per_channel</option>
|
||||||
|
<option name="validateAgainstAllChannels">true</option>
|
||||||
|
<option name="channelAwarePropertyPath">promotion</option>
|
||||||
|
<option name="constraints">
|
||||||
|
<constraint name="Collection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_cart_quantity_per_channel</option>
|
||||||
|
<option name="fields">
|
||||||
|
<value key="count">
|
||||||
|
<constraint name="NotBlank">
|
||||||
|
<option name="groups">sylius_promotion_rule_cart_quantity_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Type">
|
||||||
|
<option name="type">numeric</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_cart_quantity_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_customer_group_per_channel</option>
|
||||||
|
<option name="validateAgainstAllChannels">true</option>
|
||||||
|
<option name="channelAwarePropertyPath">promotion</option>
|
||||||
|
<option name="constraints">
|
||||||
|
<constraint name="Collection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_customer_group_per_channel</option>
|
||||||
|
<option name="fields">
|
||||||
|
<value key="group_code">
|
||||||
|
<constraint name="NotBlank">
|
||||||
|
<option name="groups">sylius_promotion_rule_customer_group_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Type">
|
||||||
|
<option name="type">string</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_customer_group_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\CustomerGroupCodeExists">
|
||||||
|
<option name="groups">sylius_promotion_rule_customer_group_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_nth_order_per_channel</option>
|
||||||
|
<option name="validateAgainstAllChannels">true</option>
|
||||||
|
<option name="channelAwarePropertyPath">promotion</option>
|
||||||
|
<option name="constraints">
|
||||||
|
<constraint name="Collection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_nth_order_per_channel</option>
|
||||||
|
<option name="fields">
|
||||||
|
<value key="nth">
|
||||||
|
<constraint name="NotBlank">
|
||||||
|
<option name="groups">sylius_promotion_rule_nth_order_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Type">
|
||||||
|
<option name="type">numeric</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_nth_order_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_shipping_country_per_channel</option>
|
||||||
|
<option name="validateAgainstAllChannels">true</option>
|
||||||
|
<option name="channelAwarePropertyPath">promotion</option>
|
||||||
|
<option name="constraints">
|
||||||
|
<constraint name="Collection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_shipping_country_per_channel</option>
|
||||||
|
<option name="fields">
|
||||||
|
<value key="country">
|
||||||
|
<constraint name="NotBlank">
|
||||||
|
<option name="groups">sylius_promotion_rule_shipping_country_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Type">
|
||||||
|
<option name="type">string</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_shipping_country_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\CountryCodeExists">
|
||||||
|
<option name="groups">sylius_promotion_rule_shipping_country_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_has_taxon_per_channel</option>
|
||||||
|
<option name="validateAgainstAllChannels">true</option>
|
||||||
|
<option name="channelAwarePropertyPath">promotion</option>
|
||||||
|
<option name="constraints">
|
||||||
|
<constraint name="Collection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_has_taxon_per_channel</option>
|
||||||
|
<option name="fields">
|
||||||
|
<value key="taxons">
|
||||||
|
<constraint name="All">
|
||||||
|
<option name="groups">sylius_promotion_rule_has_taxon_per_channel</option>
|
||||||
|
<option name="constraints">
|
||||||
|
<constraint name="NotBlank">
|
||||||
|
<option name="groups">sylius_promotion_rule_has_taxon_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\TaxonCodeExists">
|
||||||
|
<option name="groups">sylius_promotion_rule_has_taxon_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ChannelCodeCollection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_contains_product_per_channel</option>
|
||||||
|
<option name="validateAgainstAllChannels">true</option>
|
||||||
|
<option name="channelAwarePropertyPath">promotion</option>
|
||||||
|
<option name="constraints">
|
||||||
|
<constraint name="Collection">
|
||||||
|
<option name="allowExtraFields">true</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_contains_product_per_channel</option>
|
||||||
|
<option name="fields">
|
||||||
|
<value key="product_code">
|
||||||
|
<constraint name="NotBlank">
|
||||||
|
<option name="groups">sylius_promotion_rule_contains_product_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Type">
|
||||||
|
<option name="type">string</option>
|
||||||
|
<option name="groups">sylius_promotion_rule_contains_product_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\ProductCodeExists">
|
||||||
|
<option name="groups">sylius_promotion_rule_contains_product_per_channel</option>
|
||||||
|
</constraint>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
</option>
|
||||||
|
</constraint>
|
||||||
|
|
||||||
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\PromotionConfigurationChannelCodes">
|
<constraint name="Sylius\Bundle\CoreBundle\Validator\Constraints\PromotionConfigurationChannelCodes">
|
||||||
<option name="groups">
|
<option name="groups">
|
||||||
<value>sylius</value>
|
<value>sylius</value>
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@ sylius:
|
||||||
item_percentage_discount: Item percentage discount
|
item_percentage_discount: Item percentage discount
|
||||||
order_fixed_discount: Order fixed discount
|
order_fixed_discount: Order fixed discount
|
||||||
order_percentage_discount: Order percentage discount
|
order_percentage_discount: Order percentage discount
|
||||||
|
order_percentage_discount_per_channel: Order percentage discount (per channel)
|
||||||
shipping_percentage_discount: Shipping percentage discount
|
shipping_percentage_discount: Shipping percentage discount
|
||||||
|
shipping_percentage_discount_per_channel: Shipping percentage discount (per channel)
|
||||||
filters: Filters
|
filters: Filters
|
||||||
fixed_discount_configuration:
|
fixed_discount_configuration:
|
||||||
amount: Amount
|
amount: Amount
|
||||||
|
|
@ -56,12 +58,18 @@ sylius:
|
||||||
price_range: Price range filter
|
price_range: Price range filter
|
||||||
promotion_rule:
|
promotion_rule:
|
||||||
cart_quantity: Cart quantity
|
cart_quantity: Cart quantity
|
||||||
|
cart_quantity_per_channel: Cart quantity (per channel)
|
||||||
contains_product: Contains product
|
contains_product: Contains product
|
||||||
|
contains_product_per_channel: Contains product (per channel)
|
||||||
customer_group: Customer group
|
customer_group: Customer group
|
||||||
|
customer_group_per_channel: Customer group (per channel)
|
||||||
has_at_least_one_from_taxons: Has at least one from taxons
|
has_at_least_one_from_taxons: Has at least one from taxons
|
||||||
|
has_at_least_one_from_taxons_per_channel: Has at least one from taxons (per channel)
|
||||||
item_total: Item total
|
item_total: Item total
|
||||||
nth_order: Nth order
|
nth_order: Nth order
|
||||||
|
nth_order_per_channel: Nth order (per channel)
|
||||||
shipping_country: Shipping country
|
shipping_country: Shipping country
|
||||||
|
shipping_country_per_channel: Shipping country (per channel)
|
||||||
taxonomy: Taxonomy
|
taxonomy: Taxonomy
|
||||||
total_price_of_items_from_taxon: Total price of items from taxon
|
total_price_of_items_from_taxon: Total price of items from taxon
|
||||||
cart_quantity_configuration:
|
cart_quantity_configuration:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Component\Core\Promotion\Action;
|
||||||
|
|
||||||
|
use Sylius\Component\Core\Model\OrderInterface;
|
||||||
|
use Sylius\Component\Promotion\Action\PromotionActionCommandInterface;
|
||||||
|
use Sylius\Component\Promotion\Model\PromotionInterface;
|
||||||
|
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
|
||||||
|
use Sylius\Resource\Exception\UnexpectedTypeException;
|
||||||
|
|
||||||
|
final class PerChannelPromotionActionCommand implements PromotionActionCommandInterface
|
||||||
|
{
|
||||||
|
public function __construct(private PromotionActionCommandInterface $decorated)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param array<string, mixed> $configuration */
|
||||||
|
public function execute(PromotionSubjectInterface $subject, array $configuration, PromotionInterface $promotion): bool
|
||||||
|
{
|
||||||
|
if (!$subject instanceof OrderInterface) {
|
||||||
|
throw new UnexpectedTypeException($subject, OrderInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
$channelCode = $subject->getChannel()->getCode();
|
||||||
|
if (!isset($configuration[$channelCode])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->decorated->execute($subject, $configuration[$channelCode], $promotion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param array<string, mixed> $configuration */
|
||||||
|
public function revert(PromotionSubjectInterface $subject, array $configuration, PromotionInterface $promotion): void
|
||||||
|
{
|
||||||
|
if (!$subject instanceof OrderInterface) {
|
||||||
|
throw new UnexpectedTypeException($subject, OrderInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
$channelCode = $subject->getChannel()->getCode();
|
||||||
|
if (!isset($configuration[$channelCode])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->decorated->revert($subject, $configuration[$channelCode], $promotion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sylius\Component\Core\Promotion\Checker\Rule;
|
||||||
|
|
||||||
|
use Sylius\Component\Core\Model\OrderInterface;
|
||||||
|
use Sylius\Component\Promotion\Checker\Rule\RuleCheckerInterface;
|
||||||
|
use Sylius\Component\Promotion\Exception\UnsupportedTypeException;
|
||||||
|
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
|
||||||
|
|
||||||
|
final class PerChannelRuleChecker implements RuleCheckerInterface
|
||||||
|
{
|
||||||
|
public function __construct(private RuleCheckerInterface $decorated)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $configuration
|
||||||
|
*
|
||||||
|
* @throws UnsupportedTypeException
|
||||||
|
*/
|
||||||
|
public function isEligible(PromotionSubjectInterface $subject, array $configuration): bool
|
||||||
|
{
|
||||||
|
if (!$subject instanceof OrderInterface) {
|
||||||
|
throw new UnsupportedTypeException($subject, OrderInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
$channelCode = $subject->getChannel()->getCode();
|
||||||
|
if (!isset($configuration[$channelCode])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->decorated->isEligible($subject, $configuration[$channelCode]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\Sylius\Component\Core\Promotion\Action;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Sylius\Component\Core\Model\OrderInterface;
|
||||||
|
use Sylius\Component\Core\Promotion\Action\PerChannelPromotionActionCommand;
|
||||||
|
use Sylius\Component\Promotion\Action\PromotionActionCommandInterface;
|
||||||
|
use Sylius\Component\Promotion\Model\PromotionInterface;
|
||||||
|
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
|
||||||
|
use Sylius\Resource\Exception\UnexpectedTypeException;
|
||||||
|
|
||||||
|
#[CoversClass(PerChannelPromotionActionCommand::class)]
|
||||||
|
final class PerChannelPromotionActionCommandTest extends TestCase
|
||||||
|
{
|
||||||
|
private MockObject&PromotionActionCommandInterface $decorated;
|
||||||
|
|
||||||
|
private ChannelInterface&MockObject $channel;
|
||||||
|
|
||||||
|
private MockObject&OrderInterface $order;
|
||||||
|
|
||||||
|
private MockObject&PromotionInterface $promotion;
|
||||||
|
|
||||||
|
private PerChannelPromotionActionCommand $command;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->decorated = $this->createMock(PromotionActionCommandInterface::class);
|
||||||
|
$this->channel = $this->createMock(ChannelInterface::class);
|
||||||
|
$this->order = $this->createMock(OrderInterface::class);
|
||||||
|
$this->promotion = $this->createMock(PromotionInterface::class);
|
||||||
|
$this->command = new PerChannelPromotionActionCommand($this->decorated);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldImplementPromotionActionCommandInterface(): void
|
||||||
|
{
|
||||||
|
$this->assertInstanceOf(PromotionActionCommandInterface::class, $this->command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldExecuteDecoratedCommandWithTheChannelConfiguration(): void
|
||||||
|
{
|
||||||
|
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
|
||||||
|
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
|
||||||
|
$this->decorated->expects($this->once())
|
||||||
|
->method('execute')
|
||||||
|
->with($this->order, ['percentage' => 0.2], $this->promotion)
|
||||||
|
->willReturn(true)
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->assertTrue($this->command->execute($this->order, ['WEB_US' => ['percentage' => 0.2]], $this->promotion));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldNotExecuteDecoratedCommandIfThereIsNoConfigurationForTheOrderChannel(): void
|
||||||
|
{
|
||||||
|
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
|
||||||
|
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
|
||||||
|
$this->decorated->expects($this->never())->method('execute');
|
||||||
|
|
||||||
|
$this->assertFalse($this->command->execute($this->order, ['WEB_EU' => ['percentage' => 0.2]], $this->promotion));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldThrowExceptionWhenExecutingIfPromotionSubjectIsNotOrder(): void
|
||||||
|
{
|
||||||
|
$this->expectException(UnexpectedTypeException::class);
|
||||||
|
|
||||||
|
$this->command->execute($this->createMock(PromotionSubjectInterface::class), [], $this->promotion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldRevertDecoratedCommandWithTheChannelConfiguration(): void
|
||||||
|
{
|
||||||
|
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
|
||||||
|
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
|
||||||
|
$this->decorated->expects($this->once())
|
||||||
|
->method('revert')
|
||||||
|
->with($this->order, ['percentage' => 0.2], $this->promotion)
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->command->revert($this->order, ['WEB_US' => ['percentage' => 0.2]], $this->promotion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldNotRevertDecoratedCommandIfThereIsNoConfigurationForTheOrderChannel(): void
|
||||||
|
{
|
||||||
|
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
|
||||||
|
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
|
||||||
|
$this->decorated->expects($this->never())->method('revert');
|
||||||
|
|
||||||
|
$this->command->revert($this->order, ['WEB_EU' => ['percentage' => 0.2]], $this->promotion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldThrowExceptionWhenRevertingIfPromotionSubjectIsNotOrder(): void
|
||||||
|
{
|
||||||
|
$this->expectException(UnexpectedTypeException::class);
|
||||||
|
|
||||||
|
$this->command->revert($this->createMock(PromotionSubjectInterface::class), [], $this->promotion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Sylius package.
|
||||||
|
*
|
||||||
|
* (c) Sylius Sp. z o.o.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\Sylius\Component\Core\Promotion\Checker\Rule;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
|
use Sylius\Component\Core\Model\OrderInterface;
|
||||||
|
use Sylius\Component\Core\Promotion\Checker\Rule\PerChannelRuleChecker;
|
||||||
|
use Sylius\Component\Promotion\Checker\Rule\RuleCheckerInterface;
|
||||||
|
use Sylius\Component\Promotion\Exception\UnsupportedTypeException;
|
||||||
|
use Sylius\Component\Promotion\Model\PromotionSubjectInterface;
|
||||||
|
|
||||||
|
#[CoversClass(PerChannelRuleChecker::class)]
|
||||||
|
final class PerChannelRuleCheckerTest extends TestCase
|
||||||
|
{
|
||||||
|
private MockObject&RuleCheckerInterface $decorated;
|
||||||
|
|
||||||
|
private ChannelInterface&MockObject $channel;
|
||||||
|
|
||||||
|
private MockObject&OrderInterface $order;
|
||||||
|
|
||||||
|
private PerChannelRuleChecker $ruleChecker;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->decorated = $this->createMock(RuleCheckerInterface::class);
|
||||||
|
$this->channel = $this->createMock(ChannelInterface::class);
|
||||||
|
$this->order = $this->createMock(OrderInterface::class);
|
||||||
|
$this->ruleChecker = new PerChannelRuleChecker($this->decorated);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldImplementRuleCheckerInterface(): void
|
||||||
|
{
|
||||||
|
$this->assertInstanceOf(RuleCheckerInterface::class, $this->ruleChecker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldDelegateToDecoratedCheckerWithTheChannelConfiguration(): void
|
||||||
|
{
|
||||||
|
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
|
||||||
|
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
|
||||||
|
$this->decorated->expects($this->once())
|
||||||
|
->method('isEligible')
|
||||||
|
->with($this->order, ['nth' => 5])
|
||||||
|
->willReturn(true)
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->assertTrue($this->ruleChecker->isEligible($this->order, ['WEB_US' => ['nth' => 5]]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldReturnDecoratedCheckerResultForTheOrderChannel(): void
|
||||||
|
{
|
||||||
|
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
|
||||||
|
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
|
||||||
|
$this->decorated->expects($this->once())
|
||||||
|
->method('isEligible')
|
||||||
|
->with($this->order, ['nth' => 5])
|
||||||
|
->willReturn(false)
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->assertFalse($this->ruleChecker->isEligible($this->order, ['WEB_US' => ['nth' => 5]]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldReturnFalseAndNotDelegateIfThereIsNoConfigurationForTheOrderChannel(): void
|
||||||
|
{
|
||||||
|
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
|
||||||
|
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
|
||||||
|
$this->decorated->expects($this->never())->method('isEligible');
|
||||||
|
|
||||||
|
$this->assertFalse($this->ruleChecker->isEligible($this->order, ['WEB_EU' => ['nth' => 5]]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testShouldThrowExceptionIfPromotionSubjectIsNotOrder(): void
|
||||||
|
{
|
||||||
|
$this->expectException(UnsupportedTypeException::class);
|
||||||
|
|
||||||
|
$this->ruleChecker->isEligible($this->createMock(PromotionSubjectInterface::class), []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"propertyPath": "actions[5].type",
|
"propertyPath": "actions[5].type",
|
||||||
"message": "Promotion action type is invalid. Available action types are order_fixed_discount, unit_fixed_discount, order_percentage_discount, unit_percentage_discount, shipping_percentage_discount.",
|
"message": "Promotion action type is invalid. Available action types are order_fixed_discount, unit_fixed_discount, order_percentage_discount, unit_percentage_discount, shipping_percentage_discount, order_percentage_discount_per_channel, shipping_percentage_discount_per_channel.",
|
||||||
"code": null
|
"code": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"propertyPath": "rules[8].type",
|
"propertyPath": "rules[8].type",
|
||||||
"message": "Promotion rule type is invalid. Available rule types are customer_group, nth_order, shipping_country, has_taxon, total_of_items_from_taxon, contains_product, item_total, cart_quantity.",
|
"message": "Promotion rule type is invalid. Available rule types are customer_group, nth_order, shipping_country, has_taxon, total_of_items_from_taxon, contains_product, item_total, cart_quantity, customer_group_per_channel, nth_order_per_channel, shipping_country_per_channel, has_taxon_per_channel, contains_product_per_channel, cart_quantity_per_channel.",
|
||||||
"code": null
|
"code": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue