diff --git a/fechamento-caixa-v1.2.2.tar.gz b/fechamento-caixa-v1.2.2.tar.gz new file mode 100644 index 0000000..bb8e271 Binary files /dev/null and b/fechamento-caixa-v1.2.2.tar.gz differ diff --git a/fechamento-caixa.exe b/fechamento-caixa.exe index 7ee857e..43ccae9 100755 Binary files a/fechamento-caixa.exe and b/fechamento-caixa.exe differ diff --git a/src/index.html b/src/index.html index 4fea608..5cbd43b 100644 --- a/src/index.html +++ b/src/index.html @@ -1034,7 +1034,7 @@ const LS_KEY = 'fc_v7'; const CFG_KEY = 'fc_cfg'; function buildEstadoForBackend() { - // Monta o objeto exactly as o backend espera (storage.rs → salvar_fechamento) + // Monta o objeto que vai para o Supabase — inclui TUDO, todos os detalhes return { uuid: estado.uuid, id_local: estado.id_local, @@ -1042,7 +1042,7 @@ function buildEstadoForBackend() { data: estado.data, operador: estado.operador, turno: estado.turno, - saldo_troco: parseNum(val('sys-troco')), // troco do sistema + saldo_troco: parseNum(val('sys-troco')), 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'))), @@ -1052,11 +1052,12 @@ function buildEstadoForBackend() { 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 || '' })), + // Cartões com detalhes completos (não só totais) cartoes: { - credito: estado.cartoes.credito.map(r => r.valor || 0), - debito: estado.cartoes.debito.map(r => r.valor || 0), - alimentacao: estado.cartoes.alimentacao.map(r => r.valor || 0), - pix: estado.cartoes.pix.map(r => r.valor || 0), + credito: estado.cartoes.credito.map(r => ({ valor: r.valor || 0, obs: r.obs || '' })), + debito: estado.cartoes.debito.map(r => ({ valor: r.valor || 0, obs: r.obs || '' })), + alimentacao: estado.cartoes.alimentacao.map(r => ({ valor: r.valor || 0, obs: r.obs || '' })), + pix: estado.cartoes.pix.map(r => ({ valor: r.valor || 0, obs: r.obs || '' })), }, observacoes: estado.observacoes, sync_status: estado.sync_status, @@ -1194,35 +1195,37 @@ 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'); + const vSangrias = (data.sangrias||[]).reduce((s,r) => s+(parseFloat(r.retirada)||0), 0); + const vDespesas = (data.despesas||[]).reduce((s,r) => s+(parseFloat(r.valor)||0), 0); + const vVales = (data.vales||[]).reduce((s,r) => s+(parseFloat(r.valor)||0), 0); + const vReceber = (data.receber||[]).reduce((s,r) => s+(parseFloat(r.valor)||0), 0); + const vPixCnpj = (data.pixcnpj||[]).reduce((s,r) => s+(parseFloat(r.valor)||0), 0); + const vCredito = data.cartoes?.credito?.reduce?.((s,r) => s+(parseFloat(r)||0), 0) || data.credito || 0; + const vDebito = data.cartoes?.debito?.reduce?.((s,r) => s+(parseFloat(r)||0), 0) || data.debito || 0; + const vAliment = data.cartoes?.alimentacao?.reduce?.((s,r) => s+(parseFloat(r)||0), 0) || data.alimentacao || 0; + const vPixCartao = data.cartoes?.pix?.reduce?.((s,r) => s+(parseFloat(r)||0), 0) || 0; + const vCancel = (data.cancelamentos||[]).reduce((s,r) => s+(parseFloat(r.valor)||0), 0); + // Diferença = Fechamento Total − Saldo Esperado + const vFechamento = (data.fechamento || 0); + const diferenca = vFechamento - (data.saldo_esperado || 0); + const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmt(diferenca); + const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 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||''}`; }); - } + const fmtRow = (label, valor) => + `
${label}${fmt(valor)}
`; + const fmtDetail = (label, valor, obs) => + `
${label}${fmt(valor)}
`; + + const mkDet = (arr, fmtFn) => { + if (!arr || arr.length === 0) return ''; + return arr.map(r => { + if (!r) return ''; + const v = fmtFn(r); + const nome = r.nome || r.desc || r.hora || r.numero || ''; + const obs = r.obs || r.motivo || ''; + return fmtDetail(nome, v, obs); + }).join(''); + }; return ` @@ -1230,91 +1233,122 @@ function buildPrintHTML(data) { Relatório de Fechamento
-

${data.loja}

+

${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}
` : ''} +
DATA:${data.data || ''}
+
OPERADOR:${data.operador || ''}
+
TURNO:${data.turno || ''}

-
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)}
+
SANGRIAS
+${mkDet(data.sangrias, r => parseFloat(r.retirada)||0)} +${fmtRow('TOTAL SANGRIAS', vSangrias)} + +
DESPESAS
+${mkDet(data.despesas, r => parseFloat(r.valor)||0)} +${fmtRow('TOTAL DESPESAS', vDespesas)} + +
VALES
+${mkDet(data.vales, r => parseFloat(r.valor)||0)} +${fmtRow('TOTAL VALES', vVales)} + +
A RECEBER
+${mkDet(data.receber, r => parseFloat(r.valor)||0)} +${fmtRow('TOTAL A RECEBER', vReceber)} + +
PIX
+
— Cartão —
+${fmtRow('PIX CARTAO', vPixCartao)} +
— CNPJ —
+${mkDet(data.pixcnpj, r => parseFloat(r.valor)||0)} +${fmtRow('TOTAL PIX CNPJ', vPixCnpj)} + +
CARTOES
+${fmtRow('CREDITO', vCredito)} +${fmtRow('DEBITO', vDebito)} +${fmtRow('VOUCHER', vAliment)} + +
CANCELAMENTOS
+${mkDet(data.cancelamentos, r => parseFloat(r.valor)||0)} +${fmtRow('TOTAL CANCELAMENTOS', vCancel)}
-
DIFERENÇA: ${diffStr}
+${fmtRow('SALDO ESPERADO', data.saldo_esperado || 0)} +${fmtRow('FECHAMENTO', vFechamento)} +
DIFERENCA: ${diffStr}
`; } function openPrintPreview(data) { - // Gera HTML e injeta no body de uma div temporária para window.print() + // Gera HTML e injeta no body para window.print() const html = buildPrintHTML(data); const style = document.createElement('style'); + style.id = '_print_style'; style.textContent = ` @media print { body { width: 80mm; margin: 0 auto; font-family: 'Courier New', monospace; font-size: 13px; } - .no-print { display: none !important; } + .no-print, .print-actions { display: none !important; } + hr { border-top: 1px dashed #000 !important; } } .print-actions { position: fixed; top: 10px; right: 10px; z-index: 9999; } - .print-actions button { padding: 8px 16px; cursor: pointer; background: #2563eb; color: #fff; border: none; border-radius: 4px; font-size: 14px; } + .print-actions button { padding: 8px 16px; cursor: pointer; background: #2563eb; color: #fff; border: none; border-radius: 4px; font-size: 14px; margin-left: 8px; } .print-actions button:hover { background: #1d4ed8; } + .print-actions .btn-back { background: #6b7280; } + .print-actions .btn-back:hover { background: #4b5563; } `; const actions = document.createElement('div'); actions.className = 'print-actions no-print'; - actions.innerHTML = ''; + actions.innerHTML = + '' + + ''; - // Guarda conteúdo original + // Guarda originais const originalBody = document.body.innerHTML; + const originalOnAfterPrint = window.onafterprint; + + // Botão voltar restaura sem reload + document.addEventListener('click', function onBackClick(e) { + if (e.target.id === '_btn_back_print') { + document.body.innerHTML = originalBody; + const oldStyle = document.getElementById('_print_style'); + if (oldStyle) oldStyle.remove(); + document.removeEventListener('click', onBackClick); + window.onafterprint = originalOnAfterPrint; + // Re-init app state — mínimo viable restore + initApp(); + } + }); document.body.innerHTML = html; document.head.appendChild(style); document.body.insertBefore(actions, document.body.firstChild); - // Quando fechar print dialog, restaura - const onAfterPrint = () => { + window.onafterprint = () => { document.body.innerHTML = originalBody; - window.removeEventListener('afterprint', onAfterPrint); - // Re-carrega scripts essenciais - location.reload(); + const oldStyle = document.getElementById('_print_style'); + if (oldStyle) oldStyle.remove(); + window.onafterprint = originalOnAfterPrint; + document.removeEventListener('click', onBackClick); + initApp(); }; - window.addEventListener('afterprint', onAfterPrint); } function triggerWindowPrint() {