Sylius version affected: 1.2.10
Description
If you have two promotions that both apply for a cart, but when both apply, checkout becomes impossible if one changes the order value as such to invalidate the other.
Steps to reproduce
Possible Solution
Not a clue at the moment
Thank you, Alex, for the report, we will take a deeper look at it in the nearest future (hopefully) and come up with some solution ideas :)
Do you think you could provide a Behat scenario describing this bug? BTW, I suppose Cart Quantity = 0 is not a valid configuration of the promotion rule (unless it's a typo :))
Hey @Zales0123 I'll see if I can get one together. I think the fixture that generates the test data picks a random integer, but seemingly 0 is valid if set manually.
Well, then it should not be for sure, minimum cart quantity should always be 1 :)
two bugs in one! :joy:
I've never written a behat scenario before, but here goes!
Feature: Ensure promotions work correctly
In order to checkout successfully with promotions
As a Visitor
I want to checkout successfully with promotions
Background:
Given the store operates on a single channel in "United States"
And default tax zone is "US"
And the store has included in price "US VAT" tax rate of 23% for "Clothes" within the "US" zone
And the store has a product "PHP T-Shirt" priced at "$100.00"
And it belongs to "Clothes" tax category
And there is a promotion "Christmas"
And the promotion gives "12%" off
And there is a promotion "New Year"
And the promotion gives "$10.00" off if item total is greater than "$100.00"
And the store ships everywhere for free
And the store allows paying offline
@ui
Scenario: Basket with several promotions is able to checkout
Given I have product "PHP T-Shirt" in the cart
And I have completed addressing step with email "[email protected]" and "United States" based shipping address
And I have proceeded order with "Free" shipping method and "Offline" payment
When I confirm my order
Then an email with the summary of order placed by "[email protected]" should be sent to him`
I encountered the same bug on 1.3.* with default fixtures.
After taking a deeper look I found out where the problem hides:
in PromotionProcessor and OrderPromotionIntegrityChecker promotions are applied in different order. Therefore while applying promotion in PromotionProcessor the new_year promotion is applied first and conditions fit. At checkout the OrderPromotionIntegrityChecker applies christmas promotion first which decreased order total so that the new_year promotion is no longer eligible.
To reproduce the bug make sure that christmas promotion drops order total below 100$.
So it is a Bug and not a Potential Bug.

Possible solution
Add the following usort to OrderPromotionIntegrityChecker to be sure that promotion are ordered by priority (same as they are retrieved in PromotionProcessor).
````
// we create a new promotion collection and remove them from cart
// so we can verify with original conditions (without the price being applied before check)
$promotions = $order->getPromotions()->toArray();
usort(
$promotions,
function($promotion1, $promotion2)
{
if ($promotion1->getPriority() == $promotion2->getPriority()) {
return 0;
}
return ($promotion1->getPriority() > $promotion2->getPriority()) ? -1 : 1;
}
);
````
This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in a week if no further activity occurs. Thank you for your contributions.
Please do not stale
Any progress on this important bug? There are moments when it is impossible to checkout due to this.
Hi @tautelis
It looks like you created something that looked like a solution. Could you create a PR to demonstrate that it works and create tests for it?
Should be fixed by #10603.
Most helpful comment
I encountered the same bug on 1.3.* with default fixtures.
After taking a deeper look I found out where the problem hides:
in
PromotionProcessorandOrderPromotionIntegrityCheckerpromotions are applied in different order. Therefore while applying promotion inPromotionProcessorthe new_year promotion is applied first and conditions fit. At checkout theOrderPromotionIntegrityCheckerapplies christmas promotion first which decreased order total so that the new_year promotion is no longer eligible.To reproduce the bug make sure that christmas promotion drops order total below 100$.
So it is a Bug and not a Potential Bug.
Possible solution
Add the following
usorttoOrderPromotionIntegrityCheckerto be sure that promotion are ordered by priority (same as they are retrieved in PromotionProcessor).````
// we create a new promotion collection and remove them from cart
// so we can verify with original conditions (without the price being applied before check)
$promotions = $order->getPromotions()->toArray();
usort(
$promotions,
function($promotion1, $promotion2)
{
if ($promotion1->getPriority() == $promotion2->getPriority()) {
return 0;
}
);
````