-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Description
Preconditions and environment
- Magento version 2.4.7-p4
Steps to reproduce
- Create two virtual products (test1, test2) and make them buyable in storefront.
- Create a cart price rule for free shipping, add skus from created products and select "For matching items only" in dropdown.
- Go to test1 product detail page and add it to cart with qty 1.
- Check field applied_rule_ids for item test1 in quote_item table (should have the id of the sales rule created in step 2)
- Check field free_shipping for item test1 in quote_item table (should be 1).
- Go to test2 product detail page and add it to cart with qty 1.
- Check field applied_rule_ids for item test2 in quote_item table (should have the id of the sales rule created in step 2)
- Check field free_shipping for item test2 in quote_item table (should be 1 but is 0).
Expected result
free_shipping should be 1 for item test2, because the sale rule was applied correctly.
Actual result
free_shipping is 0 for item test2, even if the sale rule was applied correctly.
Additional information
The issue is in method isFreeShipping in file vendor\magento\module-offline-shipping\Model\Quote\Address\FreeShipping.php. If you add a virtual product to the cart, free_shipping is set for both addresses (shipping and billing) to 1:
$shippingAddress->setFreeShipping((int)$result);
$this->applyToItems($items, $result);
If you add another virtual product to the cart, the billing address already has free_shipping set to 1, which breaks the loop:
$this->calculator->processFreeShipping($item);
// at least one item matches to the rule and the rule mode is not a strict
if ((bool)$item->getAddress()->getFreeShipping()) {
$result = true;
break;
}
This is because only the shipping address is reset before the loop:
$shippingAddress = $quote->getShippingAddress();
$shippingAddress->setFreeShipping(0);
If we reset the billing address before the loop as well, everything works fine andthe free_shipping flag is correct for every quote_item:
$shippingAddress = $quote->getShippingAddress();
$shippingAddress->setFreeShipping(0);
$billingAddress = $quote->getBillingAddress();
$billingAddress ->setFreeShipping(0);
Perhaps someone thought that the free_shipping flag is irrelevant for virtual products. However, if you rely on this, as we do in one of our custom modules, this behaviour is incorrect.
Release note
No response
Triage and priority
- Severity: S0 - Affects critical data or functionality and leaves users without workaround.
- Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
- Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
- Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
- Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status