-
Notifications
You must be signed in to change notification settings - Fork 175
Description
What happened?
We have been seeing couple of ParseExceptions (Cannot parse "x.xxxxxxxx-14" to Money) in our logs recently.
This problem appears rarely, so it was hard to find out what was causing it, but the issue seems to be with some of our products (or some specific prices), and when a percentage discount is applied to the order for these products/prices when $this->getAdjustmentsTotal() is called.
In your Discount adjuster (adjusters/Discount.php) the adjustment amount is set:
$adjustment->amount = $amountOfPercentDiscount;
where the $amountOfPercentDiscount is the sum of two already rounded amounts. But that doesn't seem to be enough for some reason, but if I round the amount that is set as $adjusment->amount we get rid of the error:
The error:
Money\Exception\ParserException
Cannot parse "3.5527136788005E-15" to Money.
1. in /var/www/html/vendor/moneyphp/money/src/Parser/DecimalMoneyParser.php at line 46
37383940414243444546474849505152535455
}
$decimal = trim($money);
if ($decimal === '') {
return new Money(0, $fallbackCurrency);
}
if (! preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || ! isset($matches['digits'])) {
throw new ParserException(sprintf('Cannot parse "%s" to Money.', $decimal));
}
$negative = isset($matches['sign']) && $matches['sign'] === '-';
$decimal = $matches['digits'];
if ($negative) {
$decimal = '-' . $decimal;
}
2. in /var/www/html/vendor/moneyphp/money/src/Teller.php at line 364 – Money\Parser\DecimalMoneyParser::parse()
358359360361362363364365366367368369370
* Converts a monetary amount to a Money object.
*
* @param mixed $amount a monetary amount
*/
public function convertToMoney(mixed $amount): Money
{
return $this->parser->parse((string) $amount, $this->currency);
}
/**
* Converts an array of monetary amounts to an array of Money objects.
*
* @param array<int|string, mixed> $amounts an array of monetary amounts
3. in /var/www/html/vendor/moneyphp/money/src/Teller.php at line 117 – Money\Teller::convertToMoney()
111112113114115116117118119120121122123
* @return string the calculated monetary amount
*/
public function add(mixed $amount, mixed $other, mixed ...$others): string
{
return $this->convertToString(
$this->convertToMoney($amount)->add(
$this->convertToMoney($other),
...$this->convertToMoneyArray($others)
)
);
}
/**
4. in /var/www/html/vendor/craftcms/commerce/src/elements/Order.php at line 2683 – Money\Teller::add()
2677267826792680268126822683268426852686268726882689
/**
* Get the total price of the order, whose minimum value is enforced by the configured {@link Store::getMinimumTotalPriceStrategy() strategy set for minimum total price}.
*/
public function getTotalPrice(): float
{
$total = (float)$this->getTeller()->add($this->getItemSubtotal(), $this->getAdjustmentsTotal());
// Don't get the pre-rounded total.
$strategy = $this->getStore()->getMinimumTotalPriceStrategy();
if ($strategy === Store::MINIMUM_TOTAL_PRICE_STRATEGY_ZERO) {
return (float)$this->getTeller()->max(0, $total);
}
Craft CMS version
5.6.17
Craft Commerce version
5.3.8
PHP version
No response
Operating system and version
No response
Database type and version
No response
Image driver and version
No response