Details
-
Type:
Bug
-
Status: Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: None
-
Fix Version/s: 5.13.0-b2
-
Component/s: None
-
Labels:None
Description
Credits to BW on discord for bringing to our attention
To reproduce
- update a currency to use a format with a comma decimal separator (ex. 1234,56)
- create an invoice with that currency, unit price anything but lets say 4
- download the invoice and see the unit price column shows 4,0000.00
To resolve, in app/models/currencies.php around line 400 replace
// Format the currency
switch ($formats[$currency][$company_id]->format) {
// Values with decimal separator
case '#,###.##':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', $with_separator ? ',' : ''),
$decimals,
'.'
);
break;
case '#.###,##':
$value = $this->truncateDecimal(
number_format($value, $decimals, ',', $with_separator ? '.' : ''),
$decimals,
','
);
break;
case '# ###.##':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', $with_separator ? ' ' : ''),
$decimals,
'.'
);
break;
case '# ###,##':
$value = $this->truncateDecimal(
number_format($value, $decimals, ',', $with_separator ? ' ' : ''),
$decimals,
','
);
break;
case '#,##,###.##':
$value = number_format($value, $decimals, '.', '');
// If value over 1000 need to format specially
if ($with_separator && $value >= 1000) {
$thousandths_length = strlen($value) - ($decimals + 2);
$temp_val = $value;
$value = substr($temp_val, -($decimals + 1)); // hold decimals
// format value
for ($j = 0, $i = $thousandths_length; $i >= 0; $i--, $j++) {
// Thousandths place
if ($j < 3) {
$value = $temp_val[$i] . $value;
} else {
// All others
$value = $temp_val[$i] . (($j + 3) % 2 == 0 ? ',' : '') . $value;
}
}
}
$value = $this->truncateDecimal($value, $decimals, '.');
break;
// Values with no decimal separator (unless explicitly given)
case '# ###':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', $with_separator ? ' ' : ''),
$decimals,
'.'
);
break;
case '#.###':
$value = $this->truncateDecimal(
number_format($value, $decimals, ',', $with_separator ? '.' : ''),
$decimals,
','
);
break;
case '#,###':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', $with_separator ? ',' : ''),
$decimals,
'.'
);
break;
case '####.##':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', ''),
$decimals,
'.'
);
break;
case '####,##':
$value = $this->truncateDecimal(
number_format($value, $decimals, ',', ''),
$decimals,
','
);
break;
default:
return $value; // format was unrecognized, return the value as-is
}
// Remove non-significant decimals
if ($significant_decimals) {
$value = preg_replace('/(\.[0-9]+?)0*$/', '$1', $value);
// Force at leas 2 decimals
if (strpos($value, '.') === false) {
$value .= '.00';
} else {
$decimals = strlen(substr(strrchr($value, '.'), 1));
if ($decimals < 2) {
$value .= str_repeat('0', 2 - $decimals);
}
}
}
With
// Format the currency
$decimal_separator = '.';
switch ($formats[$currency][$company_id]->format) {
// Values with decimal separator
case '#,###.##':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', $with_separator ? ',' : ''),
$decimals,
'.'
);
break;
case '#.###,##':
$decimal_separator = ',';
$value = $this->truncateDecimal(
number_format($value, $decimals, ',', $with_separator ? '.' : ''),
$decimals,
','
);
break;
case '# ###.##':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', $with_separator ? ' ' : ''),
$decimals,
'.'
);
break;
case '# ###,##':
$decimal_separator = ',';
$value = $this->truncateDecimal(
number_format($value, $decimals, ',', $with_separator ? ' ' : ''),
$decimals,
','
);
break;
case '#,##,###.##':
$value = number_format($value, $decimals, '.', '');
// If value over 1000 need to format specially
if ($with_separator && $value >= 1000) {
$thousandths_length = strlen($value) - ($decimals + 2);
$temp_val = $value;
$value = substr($temp_val, -($decimals + 1)); // hold decimals
// format value
for ($j = 0, $i = $thousandths_length; $i >= 0; $i--, $j++) {
// Thousandths place
if ($j < 3) {
$value = $temp_val[$i] . $value;
} else {
// All others
$value = $temp_val[$i] . (($j + 3) % 2 == 0 ? ',' : '') . $value;
}
}
}
$value = $this->truncateDecimal($value, $decimals, '.');
break;
// Values with no decimal separator (unless explicitly given)
case '# ###':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', $with_separator ? ' ' : ''),
$decimals,
'.'
);
break;
case '#.###':
$value = $this->truncateDecimal(
number_format($value, $decimals, ',', $with_separator ? '.' : ''),
$decimals,
','
);
break;
case '#,###':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', $with_separator ? ',' : ''),
$decimals,
'.'
);
break;
case '####.##':
$value = $this->truncateDecimal(
number_format($value, $decimals, '.', ''),
$decimals,
'.'
);
break;
case '####,##':
$decimal_separator = ',';
$value = $this->truncateDecimal(
number_format($value, $decimals, ',', ''),
$decimals,
','
);
break;
default:
return $value; // format was unrecognized, return the value as-is
}
// Remove non-significant decimals
if ($significant_decimals) {
$value = preg_replace('/(\\' . $decimal_separator . '[0-9]+?)0*$/', '$1', $value);
// Force at leas 2 decimals
if (strpos($value, $decimal_separator) === false) {
$value .= $decimal_separator . '00';
} else {
$decimals = strlen(substr(strrchr($value, $decimal_separator), 1));
if ($decimals < 2) {
$value .= str_repeat('0', 2 - $decimals);
}
}
}