84 lines
2.4 KiB
PHP
84 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Import;
|
|
|
|
class DecimalNormalizer
|
|
{
|
|
/**
|
|
* Normalize a raw decimal string to a standard format (period as decimal separator).
|
|
* Handles European format (comma as decimal) and American format (period as decimal).
|
|
*
|
|
* Examples:
|
|
* - "958,31" => "958.31"
|
|
* - "1.234,56" => "1234.56"
|
|
* - "1,234.56" => "1234.56"
|
|
* - "1234" => "1234"
|
|
*
|
|
* Based on ImportProcessor::normalizeDecimal()
|
|
*/
|
|
public static function normalize(?string $raw): ?string
|
|
{
|
|
if ($raw === null) {
|
|
return null;
|
|
}
|
|
|
|
// Keep digits, comma, dot, and minus to detect separators
|
|
$s = preg_replace('/[^0-9,\.-]/', '', $raw) ?? '';
|
|
$s = trim($s);
|
|
|
|
if ($s === '') {
|
|
return null;
|
|
}
|
|
|
|
$lastComma = strrpos($s, ',');
|
|
$lastDot = strrpos($s, '.');
|
|
|
|
// Determine decimal separator by last occurrence
|
|
$decimalSep = null;
|
|
if ($lastComma !== false || $lastDot !== false) {
|
|
if ($lastComma === false) {
|
|
$decimalSep = '.';
|
|
} elseif ($lastDot === false) {
|
|
$decimalSep = ',';
|
|
} else {
|
|
$decimalSep = $lastComma > $lastDot ? ',' : '.';
|
|
}
|
|
}
|
|
|
|
// Remove all thousand separators and unify decimal to '.'
|
|
if ($decimalSep === ',') {
|
|
// Remove all dots (thousand separators)
|
|
$s = str_replace('.', '', $s);
|
|
// Replace last comma with dot
|
|
$pos = strrpos($s, ',');
|
|
if ($pos !== false) {
|
|
$s[$pos] = '.';
|
|
}
|
|
// Remove any remaining commas (unlikely)
|
|
$s = str_replace(',', '', $s);
|
|
} elseif ($decimalSep === '.') {
|
|
// Remove all commas (thousand separators)
|
|
$s = str_replace(',', '', $s);
|
|
// Dot is already decimal separator
|
|
} else {
|
|
// No decimal separator: remove commas/dots entirely
|
|
$s = str_replace([',', '.'], '', $s);
|
|
}
|
|
|
|
// Handle negative numbers
|
|
$s = ltrim($s, '+');
|
|
$neg = false;
|
|
if (str_starts_with($s, '-')) {
|
|
$neg = true;
|
|
$s = ltrim($s, '-');
|
|
}
|
|
// Remove any stray minus signs
|
|
$s = str_replace('-', '', $s);
|
|
if ($neg) {
|
|
$s = '-' . $s;
|
|
}
|
|
|
|
return $s;
|
|
}
|
|
}
|