fix: parseNum receives numbers not strings (was treating JS numbers' dot as thousand sep); updateTotals/confirm-summary use parseNum consistently
Build Fechamento de Caixa / build (macos-14, app) (push) Has been cancelled
Build Fechamento de Caixa / build (ubuntu-22.04, deb) (push) Has been cancelled
Build Fechamento de Caixa / build (windows-2022, msi) (push) Has been cancelled

This commit is contained in:
root
2026-06-23 01:51:37 +00:00
parent feeaa02396
commit 72c534a813
+24 -22
View File
@@ -577,21 +577,23 @@ let estado = {
// ─── Helpers ────────────────────────────────────────────────────────────── // ─── Helpers ──────────────────────────────────────────────────────────────
const fmt = v => 'R$ ' + (parseFloat(v) || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2 }); const fmt = v => 'R$ ' + (parseFloat(v) || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2 });
const parseNum = v => { const parseNum = v => {
const s = String(v || '0'); // Already a number? Return directly (don't treat '.' as thousand separator)
// Handle empty or whitespace if (typeof v === 'number') return isNaN(v) ? 0 : v;
if (!s.trim()) return 0; const s = String(v || '0').trim();
if (!s) return 0;
// Brazilian format: 1.234,56 → 1234.56 // Brazilian format: 1.234,56 → 1234.56
// Strategy: remove thousand dots, replace decimal comma with dot // Strategy: if string has comma, treat as BRL (decimal comma)
// "10,55" → "1055,00" (wrong) → fix: split on comma first // If no comma but has dot, treat as US (decimal dot)
// "1.055,00" → parts=["1.055","00"] → intPart="1055", decPart="00" → 1055.00
const lastComma = s.lastIndexOf(','); const lastComma = s.lastIndexOf(',');
if (lastComma === -1) { const lastDot = s.lastIndexOf('.');
// No comma: just remove thousand separators (dots) const hasCommaDecimal = lastComma > lastDot;
return parseFloat(s.replace(/,/g, '').replace(/\./g, '')) || 0; if (hasCommaDecimal) {
const intPart = s.slice(0, lastComma).replace(/\./g, '').replace(/,/g, '');
const decPart = s.slice(lastComma + 1);
return parseFloat(intPart + '.' + decPart) || 0;
} }
const intPart = s.slice(0, lastComma).replace(/\./g, '').replace(/,/g, ''); // No comma: US-style number, just strip any dots (thousand sep)
const decPart = s.slice(lastComma + 1); return parseFloat(s.replace(/,/g, '').replace(/\./g, '')) || 0;
return parseFloat(intPart + '.' + decPart) || 0;
}; };
const setText = (id, t) => { const e = document.getElementById(id); if (e) e.textContent = t; }; const setText = (id, t) => { const e = document.getElementById(id); if (e) e.textContent = t; };
const setVal = (id, v) => { const e = document.getElementById(id); if (e) e.value = v; }; const setVal = (id, v) => { const e = document.getElementById(id); if (e) e.value = v; };
@@ -773,7 +775,7 @@ document.querySelectorAll('.add-btn[data-tbl]').forEach(btn => {
// ─── Totals ──────────────────────────────────────────────────────────────── // ─── Totals ────────────────────────────────────────────────────────────────
function updateTotals() { function updateTotals() {
// ── Sangrias ── // ── Sangrias ──
const sangriasTotal = estado.sangrias.reduce((s, r) => s + (parseFloat(r['retirada'] || 0) || 0), 0); const sangriasTotal = estado.sangrias.reduce((s, r) => s + (parseNum(r['retirada'] || 0) || 0), 0);
setText('total-sangrias', fmt(sangriasTotal)); setText('total-sangrias', fmt(sangriasTotal));
// ── Tabelas de valor ── // ── Tabelas de valor ──
@@ -782,7 +784,7 @@ function updateTotals() {
'tbl-receber':'receber', 'tbl-cancelamentos':'cancelamentos', 'tbl-receber':'receber', 'tbl-cancelamentos':'cancelamentos',
}; };
Object.entries(map).forEach(([tblId, fieldName]) => { Object.entries(map).forEach(([tblId, fieldName]) => {
const total = estado[fieldName].reduce((s, r) => s + (parseFloat(r['valor'] || 0) || 0), 0); const total = estado[fieldName].reduce((s, r) => s + (parseNum(r['valor'] || 0) || 0), 0);
setText(tblId.replace('tbl-','total-'), fmt(total)); setText(tblId.replace('tbl-','total-'), fmt(total));
}); });
@@ -808,13 +810,13 @@ function updateTotals() {
// Alimentação = total cartão alimentação // Alimentação = total cartão alimentação
document.getElementById('sys-alimentacao').value = cartAli > 0 ? fmtNum(cartAli) : ''; document.getElementById('sys-alimentacao').value = cartAli > 0 ? fmtNum(cartAli) : '';
// PIX = total cartão PIX + total PIX CNPJ // PIX = total cartão PIX + total PIX CNPJ
const pixCnpjTotal = estado.pixcnpj.reduce((s, r) => s + (parseFloat(r['valor'] || 0) || 0), 0); const pixCnpjTotal = estado.pixcnpj.reduce((s, r) => s + (parseNum(r['valor'] || 0) || 0), 0);
document.getElementById('sys-pix').value = (cartPix + pixCnpjTotal) > 0 ? fmtNum(cartPix + pixCnpjTotal) : ''; document.getElementById('sys-pix').value = (cartPix + pixCnpjTotal) > 0 ? fmtNum(cartPix + pixCnpjTotal) : '';
// Vales = total vales // Vales = total vales
const valesTotal = estado.vales.reduce((s, r) => s + (parseFloat(r['valor'] || 0) || 0), 0); const valesTotal = estado.vales.reduce((s, r) => s + (parseNum(r['valor'] || 0) || 0), 0);
document.getElementById('sys-vales').value = valesTotal > 0 ? fmtNum(valesTotal) : ''; document.getElementById('sys-vales').value = valesTotal > 0 ? fmtNum(valesTotal) : '';
// À Receber = total receber // À Receber = total receber
const receberTotal = estado.receber.reduce((s, r) => s + (parseFloat(r['valor'] || 0) || 0), 0); const receberTotal = estado.receber.reduce((s, r) => s + (parseNum(r['valor'] || 0) || 0), 0);
document.getElementById('sys-receber').value = receberTotal > 0 ? fmtNum(receberTotal) : ''; document.getElementById('sys-receber').value = receberTotal > 0 ? fmtNum(receberTotal) : '';
// SYS total // SYS total
@@ -1175,11 +1177,11 @@ function openConfirmModal() {
const cartDeb = estado.cartoes.debito.reduce((s,r) => s+(r.valor||0), 0); const cartDeb = estado.cartoes.debito.reduce((s,r) => s+(r.valor||0), 0);
const cartAli = estado.cartoes.alimentacao.reduce((s,r) => s+(r.valor||0), 0); const cartAli = estado.cartoes.alimentacao.reduce((s,r) => s+(r.valor||0), 0);
const cartPix = estado.cartoes.pix.reduce((s,r) => s+(r.valor||0), 0); const cartPix = estado.cartoes.pix.reduce((s,r) => s+(r.valor||0), 0);
const sangrias = estado.sangrias.reduce((s,r) => s+(parseFloat(r.retirada||0)||0), 0); const sangrias = estado.sangrias.reduce((s,r) => s+(parseNum(r.retirada||0)||0), 0);
const despesas = estado.despesas.reduce((s,r) => s+(r.valor||0), 0); const despesas = estado.despesas.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
const vales = estado.vales.reduce((s,r) => s+(r.valor||0), 0); const vales = estado.vales.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
const receber = estado.receber.reduce((s,r) => s+(r.valor||0), 0); const receber = estado.receber.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
const cancelamentos = estado.cancelamentos.reduce((s,r) => s+(r.valor||0), 0); const cancelamentos = estado.cancelamentos.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
const fechamento = parseNum(val('f-fech-dinheiro')) + parseNum(val('f-fech-cartoes')) + parseNum(val('f-fech-receber')); const fechamento = parseNum(val('f-fech-dinheiro')) + parseNum(val('f-fech-cartoes')) + parseNum(val('f-fech-receber'));
const saldoEsp = parseNum(val('f-saldo-esperado')); const saldoEsp = parseNum(val('f-saldo-esperado'));
document.getElementById('confirm-summary').innerHTML = document.getElementById('confirm-summary').innerHTML =