Compare commits

...

5 Commits

Author SHA1 Message Date
root f850831e98 fix: buildPrintHTML usa data.diferenca (sys_total - saldo_esperado); btn-anterior null-check robusto
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
2026-06-26 02:23:57 +00:00
root e70f31e00f debug: btn-anterior logs; cartoes.norm guard
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
2026-06-26 01:44:15 +00:00
root 79e1dbd645 fix: capabilities Tauri 2 dialog; imprimir_recibo {data}; cartoes.map guard; debug logs
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
2026-06-25 17:44:22 +00:00
root cce8f3df60 fix: newEstado is not defined — reset estado inline; clear form fields on limpar
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
2026-06-25 17:30:07 +00:00
root 318d44e934 fix: modal confirm usa sysTotal pra diferenca, nao so sys-troco
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
2026-06-25 16:38:26 +00:00
3 changed files with 185 additions and 115 deletions
+23
View File
@@ -0,0 +1,23 @@
{
"identifier": "default",
"description": "Default capabilities for Fechamento de Caixa",
"windows": ["main"],
"permissions": [
"core:default",
"shell:allow-open",
"dialog:allow-message",
"dialog:allow-confirm",
"dialog:allow-ask",
"dialog:allow-save",
"dialog:allow-open",
"fs:default",
"fs:allow-app-read",
"fs:allow-app-write",
"fs:allow-appdata-read",
"fs:allow-appdata-write",
"fs:allow-appconfig-read",
"fs:allow-appconfig-write",
"fs:allow-applocaldata-read",
"fs:allow-applocaldata-write"
]
}
+11 -4
View File
@@ -11,7 +11,7 @@
"app": { "app": {
"windows": [ "windows": [
{ {
"title": "Fechamento de Caixa O Frangão", "title": "Fechamento de Caixa \u2014 O Frang\u00e3o",
"width": 1100, "width": 1100,
"height": 780, "height": 780,
"minWidth": 900, "minWidth": 900,
@@ -22,13 +22,18 @@
} }
], ],
"security": { "security": {
"csp": null "csp": null,
"capabilities": [
"default"
]
}, },
"withGlobalTauri": true "withGlobalTauri": true
}, },
"bundle": { "bundle": {
"active": true, "active": true,
"targets": ["nsis"], "targets": [
"nsis"
],
"icon": [ "icon": [
"icons/32x32.png", "icons/32x32.png",
"icons/128x128.png", "icons/128x128.png",
@@ -37,7 +42,9 @@
"icons/icon.ico" "icons/icon.ico"
], ],
"windows": { "windows": {
"webviewInstallMode": { "type": "embedBootstrapper" } "webviewInstallMode": {
"type": "embedBootstrapper"
}
}, },
"resources": { "resources": {
"../src/*": "./" "../src/*": "./"
+56 -16
View File
@@ -1290,7 +1290,10 @@ function buildConfirmHTML(data) {
// ─── Print Preview Window ────────────────────────────────────────────────── // ─── Print Preview Window ──────────────────────────────────────────────────
function buildPrintHTML(data) { function buildPrintHTML(data) {
const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ','); const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ',');
const diferenca = (data.fechamento || 0) - (data.saldo_esperado || 0); // Usa a diferenca ja calculada pelo tauriRecibo (sys_total - saldo_esperado),
// igual ao modal de confirmacao — nao recalcula de fechamento.
const diferenca = data.diferenca !== undefined ? data.diferenca
: ((data.sys_total || 0) - (data.saldo_esperado || 0));
const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmt(diferenca); const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmt(diferenca);
const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d'); const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d');
@@ -1520,7 +1523,7 @@ async function tauriRecibo() {
// Tenta ESC/POS via Tauri primeiro; se falhar, abre preview // Tenta ESC/POS via Tauri primeiro; se falhar, abre preview
try { try {
return await window.__TAURI__.core.invoke('imprimir_recibo', { estado: JSON.stringify(data) }); return await window.__TAURI__.core.invoke('imprimir_recibo', { data: JSON.stringify(data) });
} catch(e) { } catch(e) {
console.warn('ESC/POS falhou, abrindo preview:', e); console.warn('ESC/POS falhou, abrindo preview:', e);
openPrintPreview(data); openPrintPreview(data);
@@ -1539,13 +1542,17 @@ async function tauriCarregarRascunho() {
// ─── Confirm Modal ──────────────────────────────────────────────────────── // ─── Confirm Modal ────────────────────────────────────────────────────────
function openConfirmModal() { function openConfirmModal() {
console.log('[DEBUG] openConfirmModal chamado');
const operador = val('f-operador').trim(); const operador = val('f-operador').trim();
const turno = val('f-turno').trim(); const turno = val('f-turno').trim();
const loja = val('f-loja').trim(); const loja = val('f-loja').trim();
console.log('[DEBUG] openConfirmModal campos:', {operador, turno, loja});
if (!operador || !turno || !loja) { if (!operador || !turno || !loja) {
console.log('[DEBUG] openConfirmModal: campos faltando, alert');
alert('⚠️ Preencha Operador, Turno e Loja antes de enviar.'); alert('⚠️ Preencha Operador, Turno e Loja antes de enviar.');
return; return;
} }
console.log('[DEBUG] openConfirmModal: campos OK, montando modal');
// Build summary // Build summary
const cartCred = estado.cartoes.credito.reduce((s,r) => s+(r.valor||0), 0); 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 cartDeb = estado.cartoes.debito.reduce((s,r) => s+(r.valor||0), 0);
@@ -1559,7 +1566,8 @@ function openConfirmModal() {
const pixcnpj = estado.pixcnpj.reduce((s,r) => s+(parseNum(r.valor||0)||0), 0); const pixcnpj = estado.pixcnpj.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'));
const diferenca = (parseNum(val('sys-troco')) || 0) - saldoEsp; const sysTotal = (parseNum(val('sys-troco')) || 0) + cartCred + cartDeb + cartAli + cartPix + vales + receber + pixcnpj;
const diferenca = sysTotal - saldoEsp;
const diffClass = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d'); const diffClass = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d');
document.getElementById('confirm-summary').innerHTML = document.getElementById('confirm-summary').innerHTML =
`<div style="margin-bottom:6px"><strong>📅 Data:</strong> ${estado.data} &nbsp; <strong>👤 Operador:</strong> ${operador} &nbsp; <strong>⏰ Turno:</strong> ${turno} &nbsp; <strong>🏪 Loja:</strong> ${loja}</div> `<div style="margin-bottom:6px"><strong>📅 Data:</strong> ${estado.data} &nbsp; <strong>👤 Operador:</strong> ${operador} &nbsp; <strong>⏰ Turno:</strong> ${turno} &nbsp; <strong>🏪 Loja:</strong> ${loja}</div>
@@ -1573,11 +1581,13 @@ function openConfirmModal() {
<div>💳 Débito: <strong>${fmt(cartDeb)}</strong></div> <div>💳 Débito: <strong>${fmt(cartDeb)}</strong></div>
<div>💳 Alimentação: <strong>${fmt(cartAli)}</strong></div> <div>💳 Alimentação: <strong>${fmt(cartAli)}</strong></div>
<div>❌ Cancelamentos: <strong>${fmt(cancelamentos)}</strong></div> <div>❌ Cancelamentos: <strong>${fmt(cancelamentos)}</strong></div>
<div>📋 Fechamento: <strong>${fmt(fechamento)}</strong></div> <div>📋 Fechamento (contado): <strong>${fmt(fechamento)}</strong></div>
<div>🖥️ Total Sistema: <strong>${fmt(sysTotal)}</strong></div>
<hr style="border:none;border-top:1px dashed #b3d9f7;margin:6px 0"> <hr style="border:none;border-top:1px dashed #b3d9f7;margin:6px 0">
<div>🎯 Saldo Esperado: <strong>${fmt(saldoEsp)}</strong></div> <div>🎯 Saldo Esperado (contado): <strong>${fmt(saldoEsp)}</strong></div>
<div style="margin-top:4px">📐 Diferença: <strong style="color:${diffClass}">${fmt(diferenca)}</strong></div> <div style="margin-top:4px">📐 Diferença: <strong style="color:${diffClass}">${fmt(diferenca)}</strong></div>
<div style="margin-top:4px;font-size:10px;color:#888">ID: ${estado.loja}_${estado.data}_${estado.operador}</div>`; <div style="margin-top:4px;font-size:10px;color:#888">ID: ${estado.loja}_${estado.data}_${estado.operador}</div>`;
console.log('[DEBUG] openConfirmModal: tentando abrir modal');
document.getElementById('modal-confirm').classList.add('open'); document.getElementById('modal-confirm').classList.add('open');
} }
@@ -1646,6 +1656,11 @@ document.getElementById('confirm-send').addEventListener('click', async () => {
// ─── Buttons ─────────────────────────────────────────────────────────────── // ─── Buttons ───────────────────────────────────────────────────────────────
document.getElementById('btn-enviar').addEventListener('click', () => { document.getElementById('btn-enviar').addEventListener('click', () => {
console.log('[DEBUG] btn-enviar clicado');
const operador = document.getElementById('f-operador')?.value;
const turno = document.getElementById('f-turno')?.value;
const loja = document.getElementById('f-loja')?.value;
console.log('[DEBUG] operador:', operador, 'turno:', turno, 'loja:', loja);
openConfirmModal(); openConfirmModal();
}); });
@@ -1669,22 +1684,37 @@ document.getElementById('btn-limpar').addEventListener('click', () => {
if (!confirm('Limpar rascunho? Esta acção não pode ser revertida.')) return; if (!confirm('Limpar rascunho? Esta acção não pode ser revertida.')) return;
localStorage.removeItem(LS_KEY); localStorage.removeItem(LS_KEY);
// Reseta estado e re-renderiza sem reload // Reseta estado e re-renderiza sem reload
estado = newEstado(); estado = {
estado.loja = val('f-loja') || 'União'; uuid: crypto.randomUUID ? crypto.randomUUID() : Date.now().toString(),
estado.data = val('f-data') || new Date().toISOString().split('T')[0]; loja: estado.loja, data: estado.data, operador: '', turno: '',
saldo_troco: 0, fechamento: 0, saldo_esperado: 0, diferenca: 0,
despesas: [], sangrias: [], pixcnpj: [], vales: [], receber: [], cancelamentos: [],
cartoes: { credito: [], debito: [], alimentacao: [], pix: [] },
fechamento_contado: { dinheiro: 0, cartoes: 0, receber: 0 },
observacoes: '', id_local: null, sync_status: 'local'
};
setVal('f-operador', ''); setVal('f-turno', '');
setVal('f-fech-dinheiro', ''); setVal('f-fech-cartoes', ''); setVal('f-fech-receber', '');
setVal('f-saldo-esperado', ''); setVal('f-obs', '');
setVal('sys-troco', '');
calcular(); calcular();
renderAllTables(); renderAllTables();
syncUI(); syncUI();
showToast('Rascunho limpo.', 'info'); showToast('Rascunho limpo.', 'info');
}); });
document.getElementById('btn-anterior').addEventListener('click', async () => { const btnAnterior = document.getElementById('btn-anterior');
if (btnAnterior) {
btnAnterior.addEventListener('click', async () => {
console.log('[DEBUG] btn-anterior clicado');
const loja = val('f-loja') || 'União'; const loja = val('f-loja') || 'União';
console.log('[DEBUG] btn-anterior loja:', loja);
// Carrega lista de fechamentos recentes do Supabase com uuid // Carrega lista de fechamentos recentes do Supabase com uuid
let recentList = []; let recentList = [];
try { try {
recentList = await window.__TAURI__.core.invoke('sb_listar_recentes', { loja, limite: 20 }); recentList = await window.__TAURI__.core.invoke('sb_listar_recentes', { loja, limite: 20 });
console.log('[DEBUG] sb_listar_recentes retornou:', recentList?.length, 'itens');
} catch(e) { } catch(e) {
console.warn('sb_listar_recentes falhou:', e); console.warn('sb_listar_recentes falhou:', e);
} }
@@ -1701,6 +1731,7 @@ document.getElementById('btn-anterior').addEventListener('click', async () => {
}); });
dateList.sort().reverse(); dateList.sort().reverse();
} }
console.log('[DEBUG] dateList:', dateList);
let selectedDate = null; let selectedDate = null;
let selectedId = null; let selectedId = null;
@@ -1721,6 +1752,7 @@ document.getElementById('btn-anterior').addEventListener('click', async () => {
const d = new Date(estado.data); d.setDate(d.getDate() - 1); const d = new Date(estado.data); d.setDate(d.getDate() - 1);
selectedDate = d.toISOString().split('T')[0]; selectedDate = d.toISOString().split('T')[0];
} }
console.log('[DEBUG] selectedDate:', selectedDate, 'selectedId:', selectedId);
await tauriSaveLocal(); await tauriSaveLocal();
setVal('f-data', selectedDate); setVal('f-data', selectedDate);
@@ -1732,24 +1764,27 @@ document.getElementById('btn-anterior').addEventListener('click', async () => {
// Tenta Supabase primeiro (com id se disponível), senão local // Tenta Supabase primeiro (com id se disponível), senão local
let rascunho = null; let rascunho = null;
if (selectedId) { if (selectedId) {
// Usa sb_buscar_por_id para buscar por id numérico do Supabase
try { try {
rascunho = await window.__TAURI__.core.invoke('sb_buscar_por_id', { id: selectedId }); rascunho = await window.__TAURI__.core.invoke('sb_buscar_por_id', { id: selectedId });
console.log('[DEBUG] sb_buscar_por_id retornou:', !!rascunho);
} catch(e) { console.warn('sb_buscar_por_id falhou:', e); } } catch(e) { console.warn('sb_buscar_por_id falhou:', e); }
} }
if (!rascunho) { if (!rascunho) {
try { try {
rascunho = await window.__TAURI__.core.invoke('sb_carregar_rascunho', { loja, data: selectedDate }); rascunho = await window.__TAURI__.core.invoke('sb_carregar_rascunho', { loja, data: selectedDate });
console.log('[DEBUG] sb_carregar_rascunho retornou:', !!rascunho);
} catch(e) { console.warn('sb_carregar_rascunho falhou:', e); } } catch(e) { console.warn('sb_carregar_rascunho falhou:', e); }
} }
if (!rascunho) { if (!rascunho) {
try { try {
rascunho = await window.__TAURI__.core.invoke('carregar_rascunho', { loja, data: selectedDate }); rascunho = await window.__TAURI__.core.invoke('carregar_rascunho', { loja, data: selectedDate });
console.log('[DEBUG] carregar_rascunho local retornou:', !!rascunho);
} catch(e) { console.warn('carregar_rascunho local falhou:', e); } } catch(e) { console.warn('carregar_rascunho local falhou:', e); }
} }
if (rascunho) { if (rascunho) {
console.log('[DEBUG] rascunho carregado com sucesso');
if (rascunho.operador) { setVal('f-operador', rascunho.operador); estado.operador = rascunho.operador; } 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.turno) { setVal('f-turno', rascunho.turno); estado.turno = rascunho.turno; }
if (rascunho.saldo_troco) setVal('sys-troco', fmtNum(rascunho.saldo_troco)); if (rascunho.saldo_troco) setVal('sys-troco', fmtNum(rascunho.saldo_troco));
@@ -1774,26 +1809,31 @@ document.getElementById('btn-anterior').addEventListener('click', async () => {
estado.cancelamentos = rascunho.cancelamentos.map(c => ({ numero: c.numero || '', valor: parseNum(c.valor) || 0, motivo: c.motivo || '' })); estado.cancelamentos = rascunho.cancelamentos.map(c => ({ numero: c.numero || '', valor: parseNum(c.valor) || 0, motivo: c.motivo || '' }));
} }
if (rascunho.cartoes) { if (rascunho.cartoes) {
estado.cartoes.credito = (rascunho.cartoes.credito || []).map(v => ({ valor: parseNum(v) || 0 })); const norm = (arr) => Array.isArray(arr) ? arr.map(v => ({ valor: (typeof v === 'object' && v !== null) ? (parseNum(v.valor) || 0) : (parseNum(v) || 0) })) : [];
estado.cartoes.debito = (rascunho.cartoes.debito || []).map(v => ({ valor: parseNum(v) || 0 })); estado.cartoes.credito = norm(rascunho.cartoes.credito);
estado.cartoes.alimentacao = (rascunho.cartoes.alimentacao || []).map(v => ({ valor: parseNum(v) || 0 })); estado.cartoes.debito = norm(rascunho.cartoes.debito);
estado.cartoes.pix = (rascunho.cartoes.pix || []).map(v => ({ valor: parseNum(v) || 0 })); estado.cartoes.alimentacao = norm(rascunho.cartoes.alimentacao);
estado.cartoes.pix = norm(rascunho.cartoes.pix);
} }
} else { } else {
console.log('[DEBUG] nenhum rascunho encontrado para esta data');
estado.despesas = []; estado.sangrias = []; estado.pixcnpj = []; estado.despesas = []; estado.sangrias = []; estado.pixcnpj = [];
estado.vales = []; estado.receber = []; estado.cancelamentos = []; estado.vales = []; estado.receber = []; estado.cancelamentos = [];
estado.cartoes = { credito: [], debito: [], alimentacao: [], pix: [] }; estado.cartoes = { credito: [], debito: [], alimentacao: [], pix: [] };
setVal('sys-troco', ''); setVal('f-saldo-esperado', ''); setVal('f-obs', ''); setVal('sys-troco', ''); setVal('f-saldo-esperado', ''); setVal('f-obs', '');
} }
// Marcar que este é um rascunho carregado (não novo)
estado.sync_status = rascunho ? 'loaded' : 'local'; estado.sync_status = rascunho ? 'loaded' : 'local';
PRE_FILL_TABLES.forEach(ensureOneRow); PRE_FILL_TABLES.forEach(ensureOneRow);
Object.keys(TABLES).forEach(renderTable); Object.keys(TABLES).forEach(renderTable);
updateTotals(); updateTotals();
scheduleSave(); scheduleSave();
}); console.log('[DEBUG] btn-anterior concluído');
});
} else {
console.error('[DEBUG] btn-anterior NÃO encontrado no DOM!');
}
document.getElementById('f-obs').addEventListener('input', e => { estado.observacoes = e.target.value; scheduleSave(); }); document.getElementById('f-obs').addEventListener('input', e => { estado.observacoes = e.target.value; scheduleSave(); });