diff --git a/fechamento-caixa-v1.2.7.tar.gz b/fechamento-caixa-v1.2.7.tar.gz new file mode 100644 index 0000000..c7b0680 Binary files /dev/null and b/fechamento-caixa-v1.2.7.tar.gz differ diff --git a/fechamento-caixa.exe b/fechamento-caixa.exe index 803dae0..2bc5af6 100755 Binary files a/fechamento-caixa.exe and b/fechamento-caixa.exe differ diff --git a/src/index.html b/src/index.html index f636ea6..cb246b2 100644 --- a/src/index.html +++ b/src/index.html @@ -1047,7 +1047,6 @@ function buildEstadoForBackend() { saldo_troco: parseNum(val('sys-troco')), // troco do sistema saldo_esperado: parseNum(val('f-saldo-esperado')), fechamento: parseNum(val('f-fech-dinheiro')) + parseNum(val('f-fech-cartoes')) + parseNum(val('f-fech-receber')), - diferenca: parseNum(val('f-saldo-esperado')) - (parseNum(val('f-fech-dinheiro')) + parseNum(val('f-fech-cartoes')) + parseNum(val('f-fech-receber'))), despesas: estado.despesas.map(r => ({ desc: r.desc || '', obs: r.obs || '', valor: r.valor || 0 })), sangrias: estado.sangrias.map(r => ({ hora: r.hora || '', retirada: r.retirada || 0, gerente: r.gerente || '' })), pixcnpj: estado.pixcnpj.map(r => ({ nome: r.nome || '', valor: r.valor || 0 })), @@ -1085,8 +1084,44 @@ function loadState() { const raw = localStorage.getItem(LS_KEY); if (!raw) return false; const saved = JSON.parse(raw); - // Merge carefully (cartoes may be in old format) - Object.assign(estado, saved); + // Restore simple fields + estado.uuid = saved.uuid || estado.uuid; + estado.id_local = saved.id_local !== undefined ? saved.id_local : null; + estado.loja = saved.loja || estado.loja; + estado.data = saved.data || estado.data; + estado.operador = saved.operador || estado.operador; + estado.turno = saved.turno || estado.turno; + estado.saldo_troco = saved.saldo_troco || 0; + estado.saldo_esperado = saved.saldo_esperado || 0; + estado.fechamento = saved.fechamento || 0; + estado.observacoes = saved.observacoes || ''; + estado.sync_status = saved.sync_status || 'local'; + // Restore tables (always as arrays of objects) + estado.despesas = Array.isArray(saved.despesas) ? saved.despesas : []; + estado.sangrias = Array.isArray(saved.sangrias) ? saved.sangrias : []; + estado.pixcnpj = Array.isArray(saved.pixcnpj) ? saved.pixcnpj : []; + estado.vales = Array.isArray(saved.vales) ? saved.vales : []; + estado.receber = Array.isArray(saved.receber) ? saved.receber : []; + estado.cancelamentos = Array.isArray(saved.cancelamentos) ? saved.cancelamentos : []; + // Restore cartoes — each entry must be { valor: number } + if (saved.cartoes) { + estado.cartoes.credito = Array.isArray(saved.cartoes.credito) + ? saved.cartoes.credito.map(v => ({ valor: typeof v === 'object' && v !== null ? (v.valor || 0) : (parseNum(v) || 0) })) + : []; + estado.cartoes.debito = Array.isArray(saved.cartoes.debito) + ? saved.cartoes.debito.map(v => ({ valor: typeof v === 'object' && v !== null ? (v.valor || 0) : (parseNum(v) || 0) })) + : []; + estado.cartoes.alimentacao = Array.isArray(saved.cartoes.alimentacao) + ? saved.cartoes.alimentacao.map(v => ({ valor: typeof v === 'object' && v !== null ? (v.valor || 0) : (parseNum(v) || 0) })) + : []; + estado.cartoes.pix = Array.isArray(saved.cartoes.pix) + ? saved.cartoes.pix.map(v => ({ valor: typeof v === 'object' && v !== null ? (v.valor || 0) : (parseNum(v) || 0) })) + : []; + } + // Restore fechamento_contado + if (saved.fechamento_contado) { + estado.fechamento_contado = saved.fechamento_contado; + } setVal('f-data', estado.data || ''); setVal('f-operador', estado.operador || ''); setVal('f-turno', estado.turno || ''); @@ -1094,9 +1129,10 @@ function loadState() { setVal('f-obs', estado.observacoes || ''); setVal('f-saldo-esperado', estado.saldo_esperado === 0 ? '' : fmtNum(estado.saldo_esperado)); setVal('sys-troco', estado.saldo_troco === 0 ? '' : fmtNum(estado.saldo_troco)); - setVal('f-fech-dinheiro', estado.fechamento_contado && estado.fechamento_contado.dinheiro ? fmtNum(estado.fechamento_contado.dinheiro) : ''); - setVal('f-fech-cartoes', estado.fechamento_contado && estado.fechamento_contado.cartoes ? fmtNum(estado.fechamento_contado.cartoes) : ''); - setVal('f-fech-receber', estado.fechamento_contado && estado.fechamento_contado.receber ? fmtNum(estado.fechamento_contado.receber) : ''); + const fc = estado.fechamento_contado || {}; + setVal('f-fech-dinheiro', fc.dinheiro ? fmtNum(fc.dinheiro) : ''); + setVal('f-fech-cartoes', fc.cartoes ? fmtNum(fc.cartoes) : ''); + setVal('f-fech-receber', fc.receber ? fmtNum(fc.receber) : ''); syncHeader(); PRE_FILL_TABLES.forEach(ensureOneRow); Object.keys(TABLES).forEach(renderTable); @@ -1201,6 +1237,13 @@ function buildPrintHTML(data) { const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d'); let rows = ''; + // Cancelamentos (sum the array first — single cancelamentos is a float total, array is from confirm-print) + const cancelTotal = Array.isArray(data.cancelamentos) + ? data.cancelamentos.reduce((s, c) => s + (parseNum(c.valor || 0) || 0), 0) + : (data.cancelamentos || 0); + // PIX total (flat number from tauriRecibo; pixcnpj is also flat total) + const pixTotal = data.pix || data.voucher || 0; + const pixCnpjTotal = typeof data.pixcnpj === 'number' ? data.pixcnpj : 0; // Sangrias if (data.sangrias && data.sangrias.length > 0) { data.sangrias.forEach(s => { if (s.hora || s.retirada) rows += `${s.hora||''}${fmt(s.retirada)}${s.gerente||''}`; }); @@ -1217,13 +1260,13 @@ function buildPrintHTML(data) { if (data.receber && data.receber.length > 0) { data.receber.forEach(r => { if (r.nome || r.valor) rows += `${r.nome||''}${fmt(r.valor)}`; }); } - // PIX CNPJ - if (data.pixcnpj && data.pixcnpj.length > 0) { - data.pixcnpj.forEach(p => { if (p.nome || p.valor) rows += `PIX: ${p.nome||''}${fmt(p.valor)}`; }); + // PIX CNPJ (flat total, not array) + if (pixCnpjTotal > 0) { + rows += `PIX CNPJ${fmt(pixCnpjTotal)}`; } // Cancelamentos - if (data.cancelamentos && data.cancelamentos.length > 0) { - data.cancelamentos.forEach(c => { if (c.numero || c.valor) rows += `${c.numero||''}${fmt(c.valor)}${c.motivo||''}`; }); + if (cancelTotal > 0) { + rows += `Cancelamentos${fmt(cancelTotal)}`; } return ` @@ -1273,11 +1316,11 @@ ${data.observacoes ? `
Obs: ${data.observacoes}
` : ''}
CARTÕES
-
Crédito:${fmt(data.credito)}
-
Débito:${fmt(data.debito)}
-
Alimentação:${fmt(data.alimentacao)}
-
PIX Cartão:${fmt(data.cartoes?.pix||0)}
-
Cancelamentos:${fmt(data.cancelamentos)}
+
Crédito:${fmt(data.credito||0)}
+
Débito:${fmt(data.debito||0)}
+
Alimentação:${fmt(data.alimentacao||0)}
+
PIX Cartão:${fmt(pixTotal)}
+
Cancelamentos:${fmt(cancelTotal)}

DIFERENÇA: ${diffStr}
@@ -1340,7 +1383,6 @@ async function tauriRecibo() { 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 fechamentoCounted = parseNum(val('f-fech-dinheiro')) + parseNum(val('f-fech-cartoes')) + parseNum(val('f-fech-receber')); const data = { uuid: estado.uuid, id_local: estado.id_local, @@ -1351,15 +1393,8 @@ async function tauriRecibo() { saldo_troco: sysTroco, saldo_esperado: saldoEsp, fechamento: fechamentoCounted, - diferenca: fechamentoCounted - saldoEsp, // CORRIGIDO: diferenca = fechamento - esperado - 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) + diferenca: fechamentoCounted - saldoEsp, + // Flat totals for ReciboData struct (Rust) — must be numbers credito: cartCred, debito: cartDeb, alimentacao: cartAli, @@ -1370,6 +1405,14 @@ async function tauriRecibo() { vales: valesTotal, areceber: receberTotal, cancelamentos: cancelTotal, + // Full arrays for backend/storage + despesas_arr: estado.despesas.map(r => ({ desc: r.desc||'', obs: r.obs||'', valor: r.valor||0 })), + sangrias_arr: estado.sangrias.map(r => ({ hora: r.hora||'', retirada: parseNum(r.retirada)||0, gerente: r.gerente||'' })), + pixcnpj_arr: estado.pixcnpj.map(r => ({ nome: r.nome||'', valor: r.valor||0 })), + vales_arr: estado.vales.map(r => ({ nome: r.nome||'', obs: r.obs||'', valor: r.valor||0 })), + receber_arr: estado.receber.map(r => ({ nome: r.nome||'', valor: r.valor||0 })), + cancelamentos_arr: estado.cancelamentos.map(r => ({ numero: r.numero||'', valor: r.valor||0, motivo: r.motivo||'' })), + cartoes: { credito: cartCred, debito: cartDeb, alimentacao: cartAli, pix: cartPix }, observacoes: estado.observacoes, sync_status: estado.sync_status, }; @@ -1468,6 +1511,7 @@ document.getElementById('confirm-print').addEventListener('click', async () => { 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||'' })), credito: cartCred, debito: cartDeb, alimentacao: cartAli, + pix: cartPix, // flat float for buildPrintHTML cartoes: { credito: estado.cartoes.credito, debito: estado.cartoes.debito, alimentacao: estado.cartoes.alimentacao, pix: estado.cartoes.pix }, observacoes: estado.observacoes, }; @@ -1531,30 +1575,42 @@ document.getElementById('btn-limpar').addEventListener('click', () => { document.getElementById('btn-anterior').addEventListener('click', async () => { const loja = val('f-loja') || 'União'; - // Carrega lista de datas recentes do Supabase - let datas = []; + // Carrega lista de fechamentos recentes do Supabase com uuid + let recentList = []; try { - const lista = await window.__TAURI__.core.invoke('sb_listar_recentes', { loja, limite: 20 }); - if (lista && lista.length > 0) { - // Extrai datas únicas e já ordenadas - datas = [...new Set(lista.map(l => l.data).filter(Boolean))].sort().reverse(); - } + recentList = await window.__TAURI__.core.invoke('sb_listar_recentes', { loja, limite: 20 }); } catch(e) { console.warn('sb_listar_recentes falhou:', e); } + // Extrai datas únicas ordenadas + mapeamento data→id + const dateIdMap = {}; + const dateList = []; + if (recentList && recentList.length > 0) { + recentList.forEach(item => { + if (item.data && !dateIdMap[item.data]) { + dateIdMap[item.data] = item.id; + dateList.push(item.data); + } + }); + dateList.sort().reverse(); + } + let selectedDate = null; - if (datas.length > 0) { - // Mostra seletor com as datas disponíveis - const msg = datas.map((d, i) => `${i + 1}) ${d}`).join('\n'); + let selectedId = null; + if (dateList.length > 0) { + const msg = dateList.map((d, i) => `${i + 1}) ${d}`).join('\n'); const escolha = prompt(`Selecione o número do dia anterior:\n${msg}\n\n(Deixe em branco e clique Cancelar para ver só o dia anterior automático)`); if (escolha !== null && escolha.trim() !== '') { const idx = parseInt(escolha) - 1; - if (idx >= 0 && idx < datas.length) selectedDate = datas[idx]; + if (idx >= 0 && idx < dateList.length) { + selectedDate = dateList[idx]; + selectedId = dateIdMap[selectedDate]; + } } } - // Se não escolheu data, usa dia anterior automático + // Se não escolheu data, usa dia anterior automático (sem id — carrega por data) if (!selectedDate) { const d = new Date(estado.data); d.setDate(d.getDate() - 1); selectedDate = d.toISOString().split('T')[0]; @@ -1567,11 +1623,19 @@ document.getElementById('btn-anterior').addEventListener('click', async () => { estado.id_local = null; syncHeader(); - // Tenta Supabase primeiro, senão local + // Tenta Supabase primeiro (com id se disponível), senão local let rascunho = null; - try { - rascunho = await window.__TAURI__.core.invoke('sb_carregar_rascunho', { loja, data: selectedDate }); - } catch(e) { console.warn('sb_carregar_rascunho falhou:', e); } + if (selectedId) { + // Usa sb_buscar_por_id para buscar por id numérico do Supabase + try { + rascunho = await window.__TAURI__.core.invoke('sb_buscar_por_id', { id: selectedId }); + } catch(e) { console.warn('sb_buscar_por_id falhou:', e); } + } + if (!rascunho) { + try { + rascunho = await window.__TAURI__.core.invoke('sb_carregar_rascunho', { loja, data: selectedDate }); + } catch(e) { console.warn('sb_carregar_rascunho falhou:', e); } + } if (!rascunho) { try {