diff --git a/fechamento-caixa-v1.2.0.tar.gz b/fechamento-caixa-v1.2.0.tar.gz new file mode 100644 index 0000000..5f6974a Binary files /dev/null and b/fechamento-caixa-v1.2.0.tar.gz differ diff --git a/fechamento-caixa.exe b/fechamento-caixa.exe new file mode 100755 index 0000000..f2294da Binary files /dev/null and b/fechamento-caixa.exe differ diff --git a/src-tauri/src/plugins/printer.rs b/src-tauri/src/plugins/printer.rs index 5f5985b..fda3199 100644 --- a/src-tauri/src/plugins/printer.rs +++ b/src-tauri/src/plugins/printer.rs @@ -122,7 +122,6 @@ impl ReciboData { // Corta papel out.extend(escpos::FEED_CUT); - out.extend(escpos::CUT); out } diff --git a/src/index.html b/src/index.html index 0eb4e95..2300f66 100644 --- a/src/index.html +++ b/src/index.html @@ -1191,6 +1191,112 @@ async function tauriEnviar() { } } +// ─── Print Preview Window ────────────────────────────────────────────────── +function buildPrintHTML(data) { + const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ','); + const diff = (data.saldo_troco - data.saldo_esperado); + const diffStr = diff >= 0 ? `+${fmt(diff)}` : fmt(diff); + const diffColor = diff === 0 ? '#2e7d32' : (diff > 0 ? '#e65100' : '#c0272d'); + + let rows = ''; + // 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||''}`; }); + } + // Despesas + if (data.despesas && data.despesas.length > 0) { + data.despesas.forEach(d => { if (d.desc || d.valor) rows += `${d.desc||''}${fmt(d.valor)}${d.obs||''}`; }); + } + // Vales + if (data.vales && data.vales.length > 0) { + data.vales.forEach(v => { if (v.nome || v.valor) rows += `${v.nome||''}${fmt(v.valor)}${v.obs||''}`; }); + } + // Receber + 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)}`; }); + } + // 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||''}`; }); + } + + return ` + + +Relatório de Fechamento + + +
+

${data.loja}

+

Fechamento de Caixa

+
+
+
Data:${data.data}
+
Operador:${data.operador}
+
Turno:${data.turno}
+ +
ENTRADAS
+
Saldo Troco:${fmt(data.saldo_troco)}
+
Fechamento:${fmt(data.fechamento)}
+
Saldo Esperado:${fmt(data.saldo_esperado)}
+ +${rows ? `
DETALHES
${rows}
` : ''} + +${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)}
+ +
+
DIFERENÇA: ${diffStr}
+ +`; +} + +function openPrintPreview(data) { + const html = buildPrintHTML(data); + const win = window.open('', 'print_preview', 'width=400,height=700,scrollbars=yes,resizable=yes'); + if (!win) { alert('Bloqueador de pop-up impediu abrir a pré-visualização.'); return; } + win.document.write(html); + win.document.close(); +} + +function triggerWindowPrint() { + // Chama window.print() na janela pai (o próprio app) + window.print(); +} + +// ─── Recibo 80mm via Tauri (ESC/POS USB) ───────────────────────────────── async function tauriRecibo() { // Build flat totals for the Rust ReciboData struct const cartCred = estado.cartoes.credito.reduce((s,r) => s+(r.valor||0), 0); @@ -1239,7 +1345,15 @@ async function tauriRecibo() { observacoes: estado.observacoes, sync_status: estado.sync_status, }; - return await window.__TAURI__.core.invoke('imprimir_recibo', { estado: JSON.stringify(data) }); + + // Tenta ESC/POS via Tauri primeiro; se falhar, abre preview + try { + return await window.__TAURI__.core.invoke('imprimir_recibo', { estado: JSON.stringify(data) }); + } catch(e) { + console.warn('ESC/POS falhou, abrindo preview:', e); + openPrintPreview(data); + throw e; + } } async function tauriCarregarRascunho() { @@ -1303,19 +1417,30 @@ document.getElementById('confirm-close').addEventListener('click', closeConfirmM document.getElementById('confirm-cancel').addEventListener('click', closeConfirmModal); document.getElementById('modal-confirm').addEventListener('click', e => { if (e.target.id === 'modal-confirm') closeConfirmModal(); }); -// Print from confirm modal +// Print from confirm modal — abre preview no navegador document.getElementById('confirm-print').addEventListener('click', async () => { closeConfirmModal(); - const btn = document.getElementById('btn-recibo'); - btn.disabled = true; - try { - await tauriRecibo(); - alert('✅ Impressão enviada!'); - } catch(e) { - alert('Erro ao imprimir: ' + (e.message || e)); - } finally { - btn.disabled = false; - } + // Reconstrói os mesmos dados do tauriRecibo e abre preview + 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 data = { + loja: estado.loja, data: estado.data, operador: estado.operador, turno: estado.turno, + saldo_troco: parseNum(val('sys-troco')) || 0, + saldo_esperado: parseNum(val('f-saldo-esperado')) || 0, + fechamento: 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: 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||'' })), + credito: cartCred, debito: cartDeb, alimentacao: cartAli, + cartoes: { pix: cartPix }, + observacoes: estado.observacoes, + }; + openPrintPreview(data); }); // Confirm send @@ -1347,10 +1472,13 @@ document.getElementById('btn-recibo').addEventListener('click', async () => { const btn = document.getElementById('btn-recibo'); btn.disabled = true; try { + // Tenta ESC/POS primeiro; se falhar, abre preview no navegador await tauriRecibo(); - alert('✅ Impressão enviada!'); + // Se chegou aqui sem erro, ESC/POS funcionou } catch(e) { - alert('Erro ao imprimir: ' + (e.message || e)); + // ESC/POS falhou — openPrintPreview já foi chamado dentro de tauriRecibo + // Só mostra alerta se nem o preview abriu + console.warn('Recibo:', e); } finally { btn.disabled = false; }