fix: 5 problemas recorrentes
1. PIX CNPJ: linha separada no Saldo de Caixa + incluído na soma sys-total 2. Casas decimais: fmtNum sempre 2 casas (padrão dinheiro) 3. btn-anterior: agora busca do Supabase via sb_carregar_rascunho e repovoa todas as tabelas 4. Impressão: reimplementado usb_windows (WriteFile no Windows); adicionado modo teste (grava .bin) 5. Supabase: feedback de erro com console.error; storage salvar_agora persiste TODAS as tabelas (sangrias, pixcnpj, vales, cancelamentos)
This commit is contained in:
+133
-20
@@ -392,7 +392,8 @@
|
||||
<div class="sys-row"><span class="lbl">Alimentação (+)</span><input type="text" id="sys-alimentacao" readonly tabindex="-1" /></div>
|
||||
<div class="sys-row"><span class="lbl">Vales (+)</span><input type="text" id="sys-vales" readonly tabindex="-1" /></div>
|
||||
<div class="sys-row"><span class="lbl">À Receber (+)</span><input type="text" id="sys-receber" readonly tabindex="-1" /></div>
|
||||
<div class="sys-row"><span class="lbl">PIX (+)</span><input type="text" id="sys-pix" readonly tabindex="-1" /></div>
|
||||
<div class="sys-row"><span class="lbl">PIX Cartão (+)</span><input type="text" id="sys-pix" readonly tabindex="-1" /></div>
|
||||
<div class="sys-row"><span class="lbl">PIX CNPJ (+)</span><input type="text" id="sys-pixcnpj" readonly tabindex="-1" /></div>
|
||||
<div class="sys-row total"><span class="lbl">TOTAL</span><span class="val" id="sys-total">R$ 0,00</span></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -602,9 +603,8 @@ const val = id => { const e = document.getElementById(id); return e ? e.value :
|
||||
const fmtNum = v => {
|
||||
const n = typeof v === 'number' ? v : parseNum(v);
|
||||
if (isNaN(n)) return '';
|
||||
// Only show decimals if not a whole number
|
||||
const decimals = Number.isInteger(n) ? 0 : 2;
|
||||
return n.toLocaleString('pt-BR', { minimumFractionDigits: decimals, maximumFractionDigits: 2 });
|
||||
// Always 2 decimal places for money
|
||||
return n.toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||||
};
|
||||
|
||||
// Format time: 4 digits → HH:MM
|
||||
@@ -815,9 +815,11 @@ function updateTotals() {
|
||||
document.getElementById('sys-debito').value = cartDeb > 0 ? fmtNum(cartDeb) : '';
|
||||
// Alimentação = total cartão alimentação
|
||||
document.getElementById('sys-alimentacao').value = cartAli > 0 ? fmtNum(cartAli) : '';
|
||||
// PIX = total cartão PIX + total PIX CNPJ
|
||||
// PIX Cartão = total cartão PIX
|
||||
document.getElementById('sys-pix').value = cartPix > 0 ? fmtNum(cartPix) : '';
|
||||
// PIX CNPJ = total PIX CNPJ
|
||||
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-pixcnpj').value = pixCnpjTotal > 0 ? fmtNum(pixCnpjTotal) : '';
|
||||
// Vales = total vales
|
||||
const valesTotal = estado.vales.reduce((s, r) => s + (parseNum(r['valor'] || 0) || 0), 0);
|
||||
document.getElementById('sys-vales').value = valesTotal > 0 ? fmtNum(valesTotal) : '';
|
||||
@@ -825,7 +827,7 @@ function updateTotals() {
|
||||
const receberTotal = estado.receber.reduce((s, r) => s + (parseNum(r['valor'] || 0) || 0), 0);
|
||||
document.getElementById('sys-receber').value = receberTotal > 0 ? fmtNum(receberTotal) : '';
|
||||
|
||||
// SYS total
|
||||
// SYS total = troco + crédito + débito + alimentação + vales + receber + pixCartão + pixCnpj
|
||||
const sysTotal = parseNum(val('sys-troco')) + cartCred + cartDeb + cartAli + valesTotal + receberTotal + cartPix + pixCnpjTotal;
|
||||
setText('sys-total', fmt(sysTotal));
|
||||
|
||||
@@ -1152,12 +1154,64 @@ async function tauriEnviar() {
|
||||
// 1. Salva local
|
||||
await window.__TAURI__.core.invoke('salvar_fechamento', { estado: data }).catch(e => console.warn('local save err:', e));
|
||||
// 2. Envia Supabase
|
||||
const result = await window.__TAURI__.core.invoke('sb_salvar_fechamento', { estado: data });
|
||||
return result;
|
||||
try {
|
||||
const result = await window.__TAURI__.core.invoke('sb_salvar_fechamento', { estado: data });
|
||||
console.log('Supabase salvo:', result);
|
||||
return result;
|
||||
} catch(e) {
|
||||
console.error('Erro sb_salvar_fechamento:', e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async function tauriRecibo() {
|
||||
const data = buildEstadoForBackend();
|
||||
// Build flat totals for the Rust ReciboData struct
|
||||
const cartCred = estado.cartoes.credito.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 cartPix = estado.cartoes.pix.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const pixCnpjTotal = estado.pixcnpj.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
|
||||
const sangriasTotal = estado.sangrias.reduce((s,r) => s+(parseNum(r.retirada||0)||0), 0);
|
||||
const despesasTotal = estado.despesas.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
|
||||
const valesTotal = estado.vales.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
|
||||
const receberTotal = estado.receber.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
|
||||
const cancelTotal = estado.cancelamentos.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0);
|
||||
const fechamentoCounted = parseNum(val('f-fech-dinheiro')) + parseNum(val('f-fech-cartoes')) + parseNum(val('f-fech-receber'));
|
||||
const saldoEsp = parseNum(val('f-saldo-esperado'));
|
||||
const sysTroco = parseNum(val('sys-troco'));
|
||||
|
||||
const data = {
|
||||
uuid: estado.uuid,
|
||||
id_local: estado.id_local,
|
||||
loja: estado.loja,
|
||||
data: estado.data,
|
||||
operador: estado.operador,
|
||||
turno: estado.turno,
|
||||
saldo_troco: sysTroco,
|
||||
saldo_esperado: saldoEsp,
|
||||
fechamento: fechamentoCounted,
|
||||
diferenca: sysTroco - saldoEsp,
|
||||
despesas: estado.despesas.map(r => ({ desc: r.desc||'', obs: r.obs||'', valor: r.valor||0 })),
|
||||
sangrias: estado.sangrias.map(r => ({ hora: r.hora||'', retirada: parseNum(r.retirada)||0, gerente: r.gerente||'' })),
|
||||
pixcnpj: estado.pixcnpj.map(r => ({ nome: r.nome||'', valor: r.valor||0 })),
|
||||
vales: estado.vales.map(r => ({ nome: r.nome||'', obs: r.obs||'', valor: r.valor||0 })),
|
||||
receber: estado.receber.map(r => ({ nome: r.nome||'', valor: r.valor||0 })),
|
||||
cancelamentos: estado.cancelamentos.map(r => ({ numero: r.numero||'', valor: r.valor||0, motivo: r.motivo||'' })),
|
||||
cartoes: { credito: cartCred, debito: cartDeb, alimentacao: cartAli, pix: cartPix },
|
||||
// Flat totals for ReciboData struct (Rust)
|
||||
credito: cartCred,
|
||||
debito: cartDeb,
|
||||
alimentacao: cartAli,
|
||||
voucher: cartPix,
|
||||
pixcnpj: pixCnpjTotal,
|
||||
sangrias: sangriasTotal,
|
||||
despesas: despesasTotal,
|
||||
vales: valesTotal,
|
||||
areceber: receberTotal,
|
||||
cancelamentos: cancelTotal,
|
||||
observacoes: estado.observacoes,
|
||||
sync_status: estado.sync_status,
|
||||
};
|
||||
return await window.__TAURI__.core.invoke('imprimir_recibo', { estado: JSON.stringify(data) });
|
||||
}
|
||||
|
||||
@@ -1285,18 +1339,77 @@ document.getElementById('btn-anterior').addEventListener('click', async () => {
|
||||
estado.uuid = crypto.randomUUID ? crypto.randomUUID() : Date.now().toString();
|
||||
estado.id_local = null;
|
||||
syncHeader();
|
||||
const rascunho = await tauriCarregarRascunho();
|
||||
if (rascunho) {
|
||||
if (rascunho.operador) setVal('f-operador', rascunho.operador);
|
||||
if (rascunho.turno) setVal('f-turno', rascunho.turno);
|
||||
estado.operador = rascunho.operador || '';
|
||||
estado.turno = rascunho.turno || '';
|
||||
if (rascunho.saldo_troco) setVal('sys-troco', fmtNum(rascunho.saldo_troco));
|
||||
if (rascunho.saldo_esperado) setVal('f-saldo-esperado', fmtNum(rascunho.saldo_esperado));
|
||||
if (rascunho.despesas && Array.isArray(rascunho.despesas)) {
|
||||
estado.despesas = rascunho.despesas.map(d => ({ desc: d.desc || d.descricao || '', obs: '', valor: d.valor || 0 }));
|
||||
|
||||
// Try Supabase first (source of truth for submitted closings)
|
||||
let rascunho = null;
|
||||
try {
|
||||
rascunho = await window.__TAURI__.core.invoke('sb_carregar_rascunho', {
|
||||
loja: val('f-loja'),
|
||||
data: prevDate
|
||||
});
|
||||
} catch(e) {
|
||||
console.warn('sb_carregar_rascunho falhou, tentando local:', e);
|
||||
}
|
||||
|
||||
// Fallback: local SQLite
|
||||
if (!rascunho) {
|
||||
try {
|
||||
rascunho = await window.__TAURI__.core.invoke('carregar_rascunho', {
|
||||
loja: val('f-loja'),
|
||||
data: prevDate
|
||||
});
|
||||
} catch(e) {
|
||||
console.warn('carregar_rascunho local falhou:', e);
|
||||
}
|
||||
}
|
||||
|
||||
if (rascunho) {
|
||||
// Meta fields
|
||||
if (rascunho.operador) { setVal('f-operador', rascunho.operador); estado.operador = rascunho.operador; }
|
||||
if (rascunho.turno) { setVal('f-turno', rascunho.turno); estado.turno = rascunho.turno; }
|
||||
if (rascunho.saldo_troco) setVal('sys-troco', fmtNum(rascunho.saldo_troco));
|
||||
if (rascunho.saldo_esperado) setVal('f-saldo-esperado', fmtNum(rascunho.saldo_esperado));
|
||||
if (rascunho.observacoes) { setVal('f-obs', rascunho.observacoes); estado.observacoes = rascunho.observacoes; }
|
||||
|
||||
// All tables from Supabase/local
|
||||
if (rascunho.despesas && Array.isArray(rascunho.despesas)) {
|
||||
estado.despesas = rascunho.despesas.map(d => ({ desc: d.desc || d.descricao || '', obs: d.obs || '', valor: parseNum(d.valor) || 0 }));
|
||||
}
|
||||
if (rascunho.sangrias && Array.isArray(rascunho.sangrias)) {
|
||||
estado.sangrias = rascunho.sangrias.map(s => ({ hora: s.hora || '', retirada: parseNum(s.retirada) || 0, gerente: s.gerente || '' }));
|
||||
}
|
||||
if (rascunho.pixcnpj && Array.isArray(rascunho.pixcnpj)) {
|
||||
estado.pixcnpj = rascunho.pixcnpj.map(p => ({ nome: p.nome || '', valor: parseNum(p.valor) || 0 }));
|
||||
}
|
||||
if (rascunho.vales && Array.isArray(rascunho.vales)) {
|
||||
estado.vales = rascunho.vales.map(v => ({ nome: v.nome || '', obs: v.obs || '', valor: parseNum(v.valor) || 0 }));
|
||||
}
|
||||
if (rascunho.receber && Array.isArray(rascunho.receber)) {
|
||||
estado.receber = rascunho.receber.map(r => ({ nome: r.nome || '', valor: parseNum(r.valor) || 0 }));
|
||||
}
|
||||
if (rascunho.cancelamentos && Array.isArray(rascunho.cancelamentos)) {
|
||||
estado.cancelamentos = rascunho.cancelamentos.map(c => ({ numero: c.numero || '', valor: parseNum(c.valor) || 0, motivo: c.motivo || '' }));
|
||||
}
|
||||
if (rascunho.cartoes) {
|
||||
estado.cartoes.credito = (rascunho.cartoes.credito || []).map(v => ({ valor: parseNum(v) || 0 }));
|
||||
estado.cartoes.debito = (rascunho.cartoes.debito || []).map(v => ({ valor: parseNum(v) || 0 }));
|
||||
estado.cartoes.alimentacao = (rascunho.cartoes.alimentacao || []).map(v => ({ valor: parseNum(v) || 0 }));
|
||||
estado.cartoes.pix = (rascunho.cartoes.pix || []).map(v => ({ valor: parseNum(v) || 0 }));
|
||||
}
|
||||
} else {
|
||||
// No data for previous day: clear everything
|
||||
estado.despesas = [];
|
||||
estado.sangrias = [];
|
||||
estado.pixcnpj = [];
|
||||
estado.vales = [];
|
||||
estado.receber = [];
|
||||
estado.cancelamentos = [];
|
||||
estado.cartoes = { credito: [], debito: [], alimentacao: [], pix: [] };
|
||||
setVal('sys-troco', '');
|
||||
setVal('f-saldo-esperado', '');
|
||||
setVal('f-obs', '');
|
||||
}
|
||||
|
||||
PRE_FILL_TABLES.forEach(ensureOneRow);
|
||||
Object.keys(TABLES).forEach(renderTable);
|
||||
updateTotals();
|
||||
|
||||
Reference in New Issue
Block a user