diff --git a/ui/src/pages/ProductPricing.vue b/ui/src/pages/ProductPricing.vue index ed80c05..9be349a 100644 --- a/ui/src/pages/ProductPricing.vue +++ b/ui/src/pages/ProductPricing.vue @@ -702,10 +702,26 @@ function round2 (value) { } function parseNumber (val) { - const normalized = String(val ?? '') - .replace(/\s/g, '') - .replace(/\./g, '') - .replace(',', '.') + if (typeof val === 'number') return Number.isFinite(val) ? val : 0 + const text = String(val ?? '').trim().replace(/\s/g, '') + if (!text) return 0 + + const lastComma = text.lastIndexOf(',') + const lastDot = text.lastIndexOf('.') + let normalized = text + + if (lastComma >= 0 && lastDot >= 0) { + if (lastComma > lastDot) { + normalized = text.replace(/\./g, '').replace(',', '.') + } else { + normalized = text.replace(/,/g, '') + } + } else if (lastComma >= 0) { + normalized = text.replace(/\./g, '').replace(',', '.') + } else { + normalized = text.replace(/,/g, '') + } + const n = Number(normalized) return Number.isFinite(n) ? n : 0 } @@ -713,11 +729,7 @@ function parseNumber (val) { function parseNullableNumber (val) { const text = String(val ?? '').trim() if (!text) return null - const normalized = text - .replace(/\s/g, '') - .replace(/\./g, '') - .replace(',', '.') - const n = Number(normalized) + const n = parseNumber(text) return Number.isFinite(n) ? n : null } diff --git a/ui/src/stores/ProductPricingStore.js b/ui/src/stores/ProductPricingStore.js index bc03f58..a401d8f 100644 --- a/ui/src/stores/ProductPricingStore.js +++ b/ui/src/stores/ProductPricingStore.js @@ -6,10 +6,36 @@ function toText (value) { } function toNumber (value) { - const n = Number(value) + const n = parseFlexibleNumber(value) return Number.isFinite(n) ? Number(n.toFixed(2)) : 0 } +function parseFlexibleNumber (value) { + if (typeof value === 'number') return value + const text = String(value ?? '').trim().replace(/\s/g, '') + if (!text) return 0 + + const lastComma = text.lastIndexOf(',') + const lastDot = text.lastIndexOf('.') + let normalized = text + + if (lastComma >= 0 && lastDot >= 0) { + // Keep the last separator as decimal, remove the other as thousand. + if (lastComma > lastDot) { + normalized = text.replace(/\./g, '').replace(',', '.') + } else { + normalized = text.replace(/,/g, '') + } + } else if (lastComma >= 0) { + normalized = text.replace(/\./g, '').replace(',', '.') + } else { + normalized = text.replace(/,/g, '') + } + + const n = Number(normalized) + return Number.isFinite(n) ? n : 0 +} + function mapRow (raw, index, baseIndex = 0) { return { id: baseIndex + index + 1, @@ -137,7 +163,7 @@ export const useProductPricingStore = defineStore('product-pricing-store', { updateCell (row, field, val) { if (!row || !field) return - row[field] = toNumber(String(val ?? '').replace(',', '.')) + row[field] = toNumber(val) }, updateBrandGroupSelection (row, val) {