mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-05 20:57:12 +00:00
Add include_child_taxons toggle to TotalOfItemsFromTaxon promotion rule
This commit is contained in:
parent
c4bc877222
commit
28accafe56
8 changed files with 93 additions and 13 deletions
|
|
@ -58,11 +58,11 @@ Feature: Receiving discount based on total of items from specific taxon
|
|||
And my discount should be "-$15.00"
|
||||
|
||||
@api @ui
|
||||
Scenario: Receiving discount on order while buying product from child taxon of promoted taxon
|
||||
Scenario: Receiving discount on order while buying product from child taxon of promoted taxon when child taxons are included
|
||||
Given the "T-Shirts" taxon has child taxon "Polo T-Shirts"
|
||||
And the store has a product "Polo T-Shirt" priced at "$100.00"
|
||||
And it belongs to "Polo T-Shirts"
|
||||
And the promotion gives "$20.00" off if order contains products classified as "T-Shirts" with a minimum value of "$50.00"
|
||||
And the promotion gives "$20.00" off if order contains products classified as "T-Shirts" with a minimum value of "$50.00", including child taxons
|
||||
And I added product "Polo T-Shirt" to the cart
|
||||
When I check the details of my cart
|
||||
Then my cart total should be "$80.00"
|
||||
|
|
@ -73,7 +73,7 @@ Feature: Receiving discount based on total of items from specific taxon
|
|||
Given the "T-Shirts" taxon has child taxon "Polo T-Shirts"
|
||||
And the store has a product "Polo T-Shirt" priced at "$30.00"
|
||||
And it belongs to "Polo T-Shirts"
|
||||
And the promotion gives "$20.00" off if order contains products classified as "T-Shirts" with a minimum value of "$50.00"
|
||||
And the promotion gives "$20.00" off if order contains products classified as "T-Shirts" with a minimum value of "$50.00", including child taxons
|
||||
And I added product "Polo T-Shirt" to the cart
|
||||
When I check the details of my cart
|
||||
Then my cart total should be "$30.00"
|
||||
|
|
@ -84,9 +84,20 @@ Feature: Receiving discount based on total of items from specific taxon
|
|||
Given the "T-Shirts" taxon has child taxon "Polo T-Shirts"
|
||||
And the store has a product "Polo T-Shirt" priced at "$60.00"
|
||||
And it belongs to "Polo T-Shirts"
|
||||
And the promotion gives "$10.00" off if order contains products classified as "T-Shirts" with a minimum value of "$50.00"
|
||||
And the promotion gives "$10.00" off if order contains products classified as "T-Shirts" with a minimum value of "$50.00", including child taxons
|
||||
And I added product "PHP T-Shirt" to the cart
|
||||
And I added product "Polo T-Shirt" to the cart
|
||||
When I check the details of my cart
|
||||
Then my cart total should be "$150.00"
|
||||
And my discount should be "-$10.00"
|
||||
|
||||
@api @ui
|
||||
Scenario: Receiving no discount on order while buying product from child taxon when child taxons are excluded from the rule
|
||||
Given the "T-Shirts" taxon has child taxon "Polo T-Shirts"
|
||||
And the store has a product "Polo T-Shirt" priced at "$100.00"
|
||||
And it belongs to "Polo T-Shirts"
|
||||
And the promotion gives "$20.00" off if order contains products classified as "T-Shirts" with a minimum value of "$50.00"
|
||||
And I added product "Polo T-Shirt" to the cart
|
||||
When I check the details of my cart
|
||||
Then my cart total should be "$100.00"
|
||||
And there should be no discount applied
|
||||
|
|
|
|||
|
|
@ -635,6 +635,19 @@ final readonly class PromotionContext implements Context
|
|||
$this->createFixedPromotion($promotion, $discount, [], $rule);
|
||||
}
|
||||
|
||||
#[Given('/^([^"]+) gives ("(?:€|£|\$)[^"]+") off if order contains products (classified as "[^"]+") with a minimum value of ("(?:€|£|\$)[^"]+"), including child taxons$/')]
|
||||
public function thePromotionGivesOffIfOrderContainsProductsClassifiedAsAndPricedAtIncludingChildTaxons(
|
||||
PromotionInterface $promotion,
|
||||
int $discount,
|
||||
TaxonInterface $taxon,
|
||||
int $amount,
|
||||
): void {
|
||||
$channelCode = $this->getChannelCode();
|
||||
$rule = $this->ruleFactory->createItemsFromTaxonTotal($channelCode, $taxon->getCode(), $amount, true);
|
||||
|
||||
$this->createFixedPromotion($promotion, $discount, [], $rule);
|
||||
}
|
||||
|
||||
#[Given('/^([^"]+) gives ("(?:€|£|\$)[^"]+") off customer\'s (\d)(?:st|nd|rd|th) order$/')]
|
||||
public function itGivesFixedOffCustomersNthOrder(PromotionInterface $promotion, int $discount, int $nth): void
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonAutocompleteChoiceType;
|
|||
use Sylius\Component\Core\Model\TaxonInterface;
|
||||
use Sylius\Resource\Doctrine\Persistence\RepositoryInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\ReversedTransformer;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
|
@ -40,6 +41,10 @@ final class TotalOfItemsFromTaxonConfigurationType extends AbstractType
|
|||
'label' => 'sylius.form.promotion_rule.total_of_items_from_taxon.amount',
|
||||
'currency' => $options['currency'],
|
||||
])
|
||||
->add('include_child_taxons', CheckboxType::class, [
|
||||
'label' => 'sylius.form.promotion_rule.total_of_items_from_taxon.include_child_taxons',
|
||||
'required' => false,
|
||||
])
|
||||
;
|
||||
|
||||
$builder->get('taxon')->addModelTransformer(
|
||||
|
|
|
|||
|
|
@ -205,8 +205,9 @@ sylius:
|
|||
product:
|
||||
products: Products
|
||||
total_of_items_from_taxon:
|
||||
taxon: Taxon
|
||||
amount: Amount
|
||||
include_child_taxons: Include products from child taxons
|
||||
taxon: Taxon
|
||||
payment_method:
|
||||
channels: Channels
|
||||
product_attribute:
|
||||
|
|
|
|||
|
|
@ -54,13 +54,16 @@ final class PromotionRuleFactory implements PromotionRuleFactoryInterface
|
|||
return $this->createPromotionRule(HasTaxonRuleChecker::TYPE, ['taxons' => $taxons]);
|
||||
}
|
||||
|
||||
public function createItemsFromTaxonTotal(string $channelCode, string $taxonCode, int $amount): PromotionRuleInterface
|
||||
{
|
||||
public function createItemsFromTaxonTotal(
|
||||
string $channelCode,
|
||||
string $taxonCode,
|
||||
int $amount,
|
||||
bool $includeChildTaxons = false,
|
||||
): PromotionRuleInterface {
|
||||
return $this->createPromotionRule(
|
||||
TotalOfItemsFromTaxonRuleChecker::TYPE,
|
||||
[$channelCode => ['taxon' => $taxonCode, 'amount' => $amount]],
|
||||
)
|
||||
;
|
||||
[$channelCode => ['amount' => $amount, 'include_child_taxons' => $includeChildTaxons, 'taxon' => $taxonCode]],
|
||||
);
|
||||
}
|
||||
|
||||
public function createNthOrder(int $nth): PromotionRuleInterface
|
||||
|
|
|
|||
|
|
@ -57,11 +57,15 @@ final class TotalOfItemsFromTaxonRuleChecker implements RuleCheckerInterface
|
|||
return false;
|
||||
}
|
||||
|
||||
$includeChildTaxons = $configuration['include_child_taxons'] ?? false;
|
||||
$itemsWithTaxonTotal = 0;
|
||||
|
||||
/** @var OrderItemInterface $item */
|
||||
foreach ($subject->getItems() as $item) {
|
||||
if ($this->productBelongsToTaxonOrDescendant($item->getProduct(), $targetTaxon)) {
|
||||
$belongs = $includeChildTaxons
|
||||
? $this->productBelongsToTaxonOrDescendant($item->getProduct(), $targetTaxon)
|
||||
: $this->productBelongsToTaxon($item->getProduct(), $targetTaxon);
|
||||
if ($belongs) {
|
||||
$itemsWithTaxonTotal += $item->getTotal();
|
||||
}
|
||||
}
|
||||
|
|
@ -69,6 +73,15 @@ final class TotalOfItemsFromTaxonRuleChecker implements RuleCheckerInterface
|
|||
return $itemsWithTaxonTotal >= $configuration['amount'];
|
||||
}
|
||||
|
||||
private function productBelongsToTaxon(?ProductInterface $product, TaxonInterface $targetTaxon): bool
|
||||
{
|
||||
if ($product === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $product->getTaxons()->contains($targetTaxon);
|
||||
}
|
||||
|
||||
private function productBelongsToTaxonOrDescendant(?ProductInterface $product, TaxonInterface $targetTaxon): bool
|
||||
{
|
||||
if ($product === null) {
|
||||
|
|
|
|||
|
|
@ -84,11 +84,20 @@ final class PromotionRuleFactoryTest extends TestCase
|
|||
{
|
||||
$this->decoratedFactory->expects($this->once())->method('createNew')->willReturn($this->rule);
|
||||
$this->rule->expects($this->once())->method('setType')->with(TotalOfItemsFromTaxonRuleChecker::TYPE);
|
||||
$this->rule->expects($this->once())->method('setConfiguration')->with(['WEB_US' => ['taxon' => 'spears', 'amount' => 1000]]);
|
||||
$this->rule->expects($this->once())->method('setConfiguration')->with(['WEB_US' => ['amount' => 1000, 'include_child_taxons' => false, 'taxon' => 'spears']]);
|
||||
|
||||
$this->assertSame($this->rule, $this->factory->createItemsFromTaxonTotal('WEB_US', 'spears', 1000));
|
||||
}
|
||||
|
||||
public function testShouldCreateTotalOfItemsFromTaxonRuleWithChildTaxons(): void
|
||||
{
|
||||
$this->decoratedFactory->expects($this->once())->method('createNew')->willReturn($this->rule);
|
||||
$this->rule->expects($this->once())->method('setType')->with(TotalOfItemsFromTaxonRuleChecker::TYPE);
|
||||
$this->rule->expects($this->once())->method('setConfiguration')->with(['WEB_US' => ['amount' => 1000, 'include_child_taxons' => true, 'taxon' => 'spears']]);
|
||||
|
||||
$this->assertSame($this->rule, $this->factory->createItemsFromTaxonTotal('WEB_US', 'spears', 1000, true));
|
||||
}
|
||||
|
||||
public function testShouldCreateNthOrderRule(): void
|
||||
{
|
||||
$this->decoratedFactory->expects($this->once())->method('createNew')->willReturn($this->rule);
|
||||
|
|
|
|||
|
|
@ -150,7 +150,32 @@ final class TotalOfItemsFromTaxonRuleCheckerTest extends TestCase
|
|||
$recurveBowItem->expects($this->once())->method('getTotal')->willReturn(5000);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->ruleChecker->isEligible($this->order, ['WEB_US' => ['taxon' => 'bows', 'amount' => 10000]]),
|
||||
$this->ruleChecker->isEligible($this->order, ['WEB_US' => ['taxon' => 'bows', 'amount' => 10000, 'include_child_taxons' => true]]),
|
||||
);
|
||||
}
|
||||
|
||||
public function testShouldNotRecognizeSubjectAsEligibleIfItHasItemsOnlyFromChildTaxonWhenChildTaxonsExcluded(): void
|
||||
{
|
||||
$recurveBows = $this->createMock(TaxonInterface::class);
|
||||
|
||||
$recurveBowItem = $this->createMock(OrderItemInterface::class);
|
||||
$recurveBow = $this->createMock(ProductInterface::class);
|
||||
|
||||
$this->order->expects($this->once())->method('getChannel')->willReturn($this->channel);
|
||||
$this->channel->expects($this->once())->method('getCode')->willReturn('WEB_US');
|
||||
$this->order->expects($this->once())->method('getItems')->willReturn(new ArrayCollection([
|
||||
$recurveBowItem,
|
||||
]));
|
||||
$this->taxonRepository
|
||||
->expects($this->once())
|
||||
->method('findOneBy')
|
||||
->with(['code' => 'bows'])
|
||||
->willReturn($this->bows);
|
||||
$recurveBowItem->expects($this->once())->method('getProduct')->willReturn($recurveBow);
|
||||
$recurveBow->expects($this->once())->method('getTaxons')->willReturn(new ArrayCollection([$recurveBows]));
|
||||
|
||||
$this->assertFalse(
|
||||
$this->ruleChecker->isEligible($this->order, ['WEB_US' => ['taxon' => 'bows', 'amount' => 5000, 'include_child_taxons' => false]]),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue