Skip to content

Tier price / grouped product issue #9265

Closed
@evgk

Description

@evgk

Preconditions

Magento 2.1.6
PHP 7.0.13
MySQL 5.7.14

Steps to reproduce

  1. Deploy a stock Magento version 2.1.6
  2. Create a simple product with a price of 100 and a tier-price of 50 for qty=1
  3. Create a grouped product and add the simple product created on step 2 to it.
  4. The "Default Quantity" field in the "Grouped Products" section on the grouped product should be 0
  5. Visit the grouped product from the frontend

Expected result

The grouped product page should show the lowest price for the simple product, which is 50

Actual result

The grouped product shows the price of 100

Technical description

This line: $quantity = $quantity ?: 1;
in ./vendor/magento/module-catalog/Pricing/Price/TierPrice.php, line 75,
uses the ternary shorthand operator to set the quantity to 1 when
the quantity that is passed can be converted to false.
At this point, the quantity comes from the SaleableInterface item - the simple product model itself.
Note that the type signature for the getQty method in SaleableInterface indicates that it should always
return a float:

/**
 * Returns quantity of saleable item
 *
 * @return float
 */
public function getQty();

However, on the grouped-product page this item comes from this collection:
./vendor/magento/module-catalog/Model/ResourceModel/Product/Link/Product/Collection.php
(a collection of linked products). So the quantity that is set in the product model comes from the
"Default quantity" field which is stored as an attribute of the link(catalog_product_link_attribute_decimal) -
however, since neither Magento nor the underlying Zend libraries have any conversion from the MySQL to PHP types when loading the collections,
and MySQL client/server communication is done via a text-based protocol, this "qty" field ends up being a string in PHP.
Thus, the getQty function will return a string representation of a decimal value("0.0000000") in a clear violation of the SaleableInterface, and it leads to this issue with the tier price above(since the ternary shorthand operator will treat "0.000000" string as true, not setting the quantity to 1 as a result).
Suggested fix does a forceful conversion of the link-attributes with type=decimal to a PHP float-value on the link-product-collection afterLoad event.
It is possible to do the same for the integer type as well, but doing it just for the type=decimal seems least intrusive, and it would solve this interface-mismatch and tier-price issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Fixed in 2.2.xThe issue has been fixed in 2.2 release lineIssue: Format is validGate 1 Passed. Automatic verification of issue format passedIssue: Ready for WorkGate 4. Acknowledged. Issue is added to backlog and ready for development

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions