-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix unexpected error about not enough stocks while completing the payment in the Admin Panel #15688
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
@managing_orders | ||
Feature: Finalizing order payment | ||
In order to mark order's payment state as complete | ||
As an Administrator | ||
I want to be able to finalize payment | ||
|
||
Background: | ||
Given the store operates on a single channel in "United States" | ||
And the store has a product "Angel T-Shirt" | ||
And the store ships everywhere for Free | ||
And the store allows paying with "Cash on Delivery" | ||
And the "Angel T-Shirt" product's inventory has become tracked with 1 items | ||
And there is a customer "lucy@teamlucifer.com" that placed an order "#00000666" | ||
And the customer bought 1 "Angel T-Shirt" products | ||
And the customer "Lucifer Morningstar" addressed it to "Seaside Fwy", "90802" "Los Angeles" in the "United States" with identical billing address | ||
And the customer chose "Free" shipping method with "Cash on Delivery" payment | ||
And I am logged in as an administrator | ||
|
||
@ui | ||
Scenario: Finalizing order's payment | ||
Given I view the summary of the order "#00000666" | ||
When I mark this order as paid | ||
Then I should be notified that the order's payment has been successfully completed | ||
And it should have payment state "Completed" |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -15,15 +15,10 @@ | |||||||
|
||||||||
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent; | ||||||||
use Sylius\Component\Core\Model\PaymentInterface; | ||||||||
use Sylius\Component\Inventory\Checker\AvailabilityCheckerInterface; | ||||||||
use Sylius\Component\Core\Model\ProductVariantInterface; | ||||||||
|
||||||||
final class PaymentPreCompleteListener | ||||||||
{ | ||||||||
public function __construct( | ||||||||
private AvailabilityCheckerInterface $availabilityChecker, | ||||||||
) { | ||||||||
} | ||||||||
|
||||||||
public function checkStockAvailability(ResourceControllerEvent $event): void | ||||||||
{ | ||||||||
/** @var PaymentInterface $payment */ | ||||||||
|
@@ -33,7 +28,7 @@ public function checkStockAvailability(ResourceControllerEvent $event): void | |||||||
foreach ($orderItems as $orderItem) { | ||||||||
$variant = $orderItem->getVariant(); | ||||||||
|
||||||||
if (!$this->availabilityChecker->isStockSufficient($variant, $orderItem->getQuantity())) { | ||||||||
if (!$this->canBeCompleted($variant, $orderItem->getQuantity())) { | ||||||||
$event->setMessageType('error'); | ||||||||
$event->setMessage('sylius.resource.payment.cannot_be_completed'); | ||||||||
$event->setMessageParameters(['%productVariantCode%' => $variant->getCode()]); | ||||||||
|
@@ -43,4 +38,21 @@ public function checkStockAvailability(ResourceControllerEvent $event): void | |||||||
} | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
private function canBeCompleted(ProductVariantInterface $variant, int $quantity): bool | ||||||||
{ | ||||||||
if (!$variant->isTracked()) { | ||||||||
return true; | ||||||||
} | ||||||||
|
||||||||
if ($variant->getOnHold() - $quantity < 0) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
if ($variant->getOnHand() - $quantity < 0) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure, but I feel that we should only check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic comes from the <?php
// ...
Assert::greaterThanEq(
($variant->getOnHold() - $orderItem->getQuantity()),
0,
sprintf(
'Not enough units to decrease on hold quantity from the inventory of a variant "%s".',
$variant->getName(),
),
);
Assert::greaterThanEq(
($variant->getOnHand() - $orderItem->getQuantity()),
0,
sprintf(
'Not enough units to decrease on hand quantity from the inventory of a variant "%s".',
$variant->getName(),
),
);
// ... So both values are checked, same as in the example above. If you
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I guess we have to think about it, as currently it'll throw an exception. We'll discuss it on the daily meeting, and create a task if needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This onHand/onHold pre-sell check logic feels important enough to varant it's own checker. For example, why not add new method
OrderInventoryChecker
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it needs a bit of work.
Let me explain:
|
||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
return true; | ||||||||
} | ||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,7 +99,6 @@ | |
</service> | ||
|
||
<service id="Sylius\Bundle\CoreBundle\EventListener\PaymentPreCompleteListener"> | ||
<argument type="service" id="Sylius\Component\Inventory\Checker\AvailabilityCheckerInterface" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just in case, can service's argument be removed BC wise? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's debatable. In theory, it can "break" something in terms of the system might start behaving differently. On the other hand,
|
||
<tag name="kernel.event_listener" event="sylius.payment.pre_complete" method="checkStockAvailability" /> | ||
</service> | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something happened with this file,
finalizing_order_payment.feature
aside from inventory line.Can this line be moved from background to scenario, so original
Finalizing order payment
and this feature file could be merged?Otherwise, please rename file and feature accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I wanted to just reproduce the bug, I forgot to merge/rename that file.