I'm not completely sure, if it was designed or not. The default price calculator doesn't include the given quantity once the price is queried without any adjustments in \Drupal\commerce_order\PriceCalculator::calculate()

Current code snippet:

    if (empty($adjustment_types) || empty($processors)) {
      return new PriceCalculatorResult($resolved_price, $resolved_price);
    }

Proposed solution:

Simply multiply the resolved price before creating a the PriceCalculatorResult

    if (empty($adjustment_types) || empty($processors)) {
      return new PriceCalculatorResult($resolved_price->multiply($quantity), $resolved_price);
    }

This behaviour can cause unexpected prices once there are no adjustments but quantity is provided.

Comments

bpstr created an issue. See original summary.

bpstr’s picture

Issue tags: +price adjustments, +calculator
vishalghyv’s picture

Price is being resolved over chainPriceResolver. Even then could you suggest a way to reproduce I am not able to. And what kind of unexpected behavior.

bpstr’s picture

I created a simple field formatter for order items to display prices without tax, but including promotion.
For this task, I used the commerce_order.price_calculator service, which passes the given PurchasableEntityInterface through the chainPriceResolver and then returns
the calculated price by creating an order item and applying the given parameters on that instance.
If you take a look at the code of \Drupal\commerce_order\PriceCalculator::calculate, the
quantity is only regarded when there are $adjustment_types or $processors provided.
In my case, there were no processors found when iterating through $adjustment_types, but I
believe this is the same case, when an empty array (default value) is passed as a fourth argument.

Another great example is a helper service to provide consistent price calculation through the site.
I had to write an extra check because the 'promotion' adjustment type did not have a processor, and the
quantity was not regarded when the service returned the 'calculated price'.
(The second method, calculateTotalPrice() always returned the correct amount.)

  public function calculateNetPrice(PurchasableEntityInterface $purchasableEntity, $quantity = 1): Price {
    $priceCalculatorResult = $this->priceCalculator->calculate($purchasableEntity, $quantity, $this->currentContext, ['promotion']);

    if ($priceCalculatorResult->getBasePrice() === $priceCalculatorResult->getCalculatedPrice() && $quantity > 1) {
      return $priceCalculatorResult->getBasePrice()->multiply($quantity);
    }

    return $priceCalculatorResult->getCalculatedPrice();
  }


  public function calculateTotalPrice(PurchasableEntityInterface $purchasableEntity, $quantity = 1): Price {
    $priceCalculatorResult = $this->priceCalculator->calculate($purchasableEntity, $quantity, $this->currentContext, ['tax', 'promotion']);
    // ...
loze’s picture

I also am experiencing this same behavior. Quantity is ignored if the adjustments array is empty.

loze’s picture

here is a patch that only returns early if either the processors or adjustments are empty AND the quantity is only 1

This allows me to calculate a total price of an item with a quantity > 1 and no processor/adjustments.

thanks.

loze’s picture

Status: Active » Needs review
StatusFileSize
new710 bytes

I'm sorry, disregard my last comment. The solution in the OP is better.
Here is a patch for that.

luksak’s picture

Status: Needs review » Reviewed & tested by the community

The patch in #7 works for me! Thanks!

jsacksick’s picture

I'm fine committing the fix, considering the quantity is taken into account when there are adjustments.

My only problem is PriceCalculatorResult::getCalculatedPrice() which currently says the following:

  /**
   * Gets the calculated price.
   *
   * This is the resolved unit price with adjustments applied.
   *
   * @return \Drupal\commerce_price\Price
   *   The calculated price.
   */

  • jsacksick committed 066575c on 3.0.x authored by loze
    Issue #3128698 by loze, bpstr, jsacksick, Lukas von Blarer: Price...

  • jsacksick committed f56b2b1 on 8.x-2.x authored by loze
    Issue #3128698 by loze, bpstr, jsacksick, Lukas von Blarer: Price...
jsacksick’s picture

Status: Reviewed & tested by the community » Fixed

Just changed the comment to:

This is the resolved price with adjustments applied.

And committed, thank you!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.