We've had this problem for a while now and it's largely gone un-noticed but I'd like to raise it.
We have a bunch of products that are discounted when you buy them in bulk. E.g. 12 products for 69.99.
In order to achieve this we calculate what the price should be for each product, by dividing 69.99 / 12, which is 5.8325.
We put this in the database as the product price and I can see it is stored in the database correctly.
However when you add 12 items to the cart, the total is 69.96 - anything past 2 decimal places is being rounded off prior to multiplication.
I've managed to work out a fix for this, but its not ideal as it will get wiped out if anyone ever updates the LineItemModel.
Here is my solution to change the calculation:
public function getSubtotal()
{
// The subtotal should always be rounded.
return $this->qty * CommerceCurrencyHelper::round($this->salePrice);
}
to
public function getSubtotal()
{
// The subtotal should always be rounded.
return CommerceCurrencyHelper::round($this->qty * $this->salePrice);// Modified: JL
}
and change
public function fillFromPurchasable(Purchasable $purchasable)
{
$this->price = $purchasable->getPrice();
$this->taxCategoryId = $purchasable->getTaxCategoryId();
$this->shippingCategoryId = $purchasable->getShippingCategoryId();
// Since sales cannot apply to non core purchasables yet, set to price at default
$this->salePrice = $purchasable->getPrice();
$this->saleAmount = 0;
$snapshot = [
'price' => $purchasable->getPrice(),
'sku' => $purchasable->getSku(),
'description' => $purchasable->getDescription(),
'purchasableId' => $purchasable->getPurchasableId(),
'cpEditUrl' => '#',
'options' => $this->options
];
// Add our purchasable data to the snapshot, save our sales.
$this->snapshot = array_merge($purchasable->getSnapShot(), $snapshot);
$purchasable->populateLineItem($this);
//raising onPopulate event
$event = new Event($this, [
'lineItem' => $this,
'purchasable' => $this->purchasable
]);
craft()->commerce_lineItems->onPopulateLineItem($event);
// Always make sure salePrice is equal to the price and saleAmount
$this->salePrice = CommerceCurrencyHelper::round($this->saleAmount + $this->price);
}
to
public function fillFromPurchasable(Purchasable $purchasable)
{
$this->price = $purchasable->getPrice();
$this->taxCategoryId = $purchasable->getTaxCategoryId();
$this->shippingCategoryId = $purchasable->getShippingCategoryId();
// Since sales cannot apply to non core purchasables yet, set to price at default
$this->salePrice = $purchasable->getPrice();
$this->saleAmount = 0;
$snapshot = [
'price' => $purchasable->getPrice(),
'sku' => $purchasable->getSku(),
'description' => $purchasable->getDescription(),
'purchasableId' => $purchasable->getPurchasableId(),
'cpEditUrl' => '#',
'options' => $this->options
];
// Add our purchasable data to the snapshot, save our sales.
$this->snapshot = array_merge($purchasable->getSnapShot(), $snapshot);
$purchasable->populateLineItem($this);
//raising onPopulate event
$event = new Event($this, [
'lineItem' => $this,
'purchasable' => $this->purchasable
]);
craft()->commerce_lineItems->onPopulateLineItem($event);
// Always make sure salePrice is equal to the price and saleAmount
$this->salePrice = $this->saleAmount + $this->price;// Modified: JL
}
Can anyone tell me if this is a known issue and whether there is any reason why the code is not like this to begin with? Why store values at 4dp if it's always rounded off to 2dp when calculated?