Compare commits

...

7 Commits

Author SHA1 Message Date
root bd867e8419 v1.3.21: PDF/envio - CONTADORES no final do buildConfirmHTML
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 14:41:43 +00:00
root da861ef964 v1.3.20: Diferença tela = SaldoCaixa(Sistema) - SaldoEsperado - Cancelamentos; CONTADORES no final do Recibo 80mm
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 14:32:25 +00:00
root 8e642f2e0c v1.3.18: SaldoCaixa(Sistema) agora inclui TROCO. Diferença = SaldoCaixa(Sistema) - SaldoEsperado - Cancelamentos
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 14:02:41 +00:00
root 7473db6b1f Revert "v1.3.16: Diferença=SaldoCaixa(Sistema)-SaldoEsperado-Cancelamentos; nomes padronizados"
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
This reverts commit 13489d58cf.
2026-06-26 13:55:23 +00:00
root 13489d58cf v1.3.16: Diferença=SaldoCaixa(Sistema)-SaldoEsperado-Cancelamentos; nomes padronizados
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 13:52:34 +00:00
root 5ad8c1f395 v1.3.15: diferença=fechamento-saldo_esperado-cancelamentos; ESCPOS 80mm+HTML com clientes+frango
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 13:33:28 +00:00
root 103cd31e50 v1.3.14b: campos Clientes e Frango Assado no formulário, reports e modal
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 13:21:02 +00:00
2 changed files with 64 additions and 18 deletions
+10
View File
@@ -127,6 +127,10 @@ pub struct ReciboData {
pub cancelamentos_arr: Vec<ReciboLinha>, pub cancelamentos_arr: Vec<ReciboLinha>,
#[serde(default)] #[serde(default)]
pub observacoes: Option<String>, pub observacoes: Option<String>,
#[serde(default)]
pub clientes: i32,
#[serde(default)]
pub frango: i32,
} }
impl ReciboData { impl ReciboData {
@@ -329,6 +333,12 @@ impl ReciboData {
}; };
out.extend(escpos::title(&diff_str)); out.extend(escpos::title(&diff_str));
// ── CONTADORES ──
out.extend(escpos::line_bold("CONTADORES"));
out.extend(escpos::kv("Clientes:", &self.clientes.to_string()));
out.extend(escpos::kv("Frango Assado:", &self.frango.to_string()));
out.extend(escpos::divider());
// ── OBSERVAÇÕES ── // ── OBSERVAÇÕES ──
if let Some(ref obs) = self.observacoes { if let Some(ref obs) = self.observacoes {
if !obs.trim().is_empty() { if !obs.trim().is_empty() {
+54 -18
View File
@@ -427,6 +427,21 @@
</div> </div>
</div> </div>
<!-- CONTADORES -->
<div class="section">
<div class="section-header">👥 Clientes & Frango Assado</div>
<div style="display:flex;gap:12px">
<div style="flex:1">
<label style="font-size:12px;color:#666">Clientes</label>
<input type="number" id="f-clientes" min="0" placeholder="0" style="width:100%;padding:8px;border:1px solid var(--border);border-radius:var(--radius);font-size:15px" />
</div>
<div style="flex:1">
<label style="font-size:12px;color:#666">Frango Assado</label>
<input type="number" id="f-frango" min="0" placeholder="0" style="width:100%;padding:8px;border:1px solid var(--border);border-radius:var(--radius);font-size:15px" />
</div>
</div>
</div>
<!-- OBS --> <!-- OBS -->
<div class="section" style="flex:1;display:flex;flex-direction:column"> <div class="section" style="flex:1;display:flex;flex-direction:column">
<div class="section-header">📝 Observações</div> <div class="section-header">📝 Observações</div>
@@ -578,6 +593,7 @@ let estado = {
despesas: [], sangrias: [], pixcnpj: [], vales: [], receber: [], cancelamentos: [], despesas: [], sangrias: [], pixcnpj: [], vales: [], receber: [], cancelamentos: [],
cartoes: { credito: [], debito: [], alimentacao: [], pix: [] }, cartoes: { credito: [], debito: [], alimentacao: [], pix: [] },
fechamento_contado: { dinheiro: 0, cartoes: 0, receber: 0 }, fechamento_contado: { dinheiro: 0, cartoes: 0, receber: 0 },
clientes: 0, frango: 0, // contadores
observacoes: '', id_local: null, sync_status: 'local' observacoes: '', id_local: null, sync_status: 'local'
}; };
@@ -839,8 +855,8 @@ function updateTotals() {
const receberTotal = estado.receber.reduce((s, r) => s + (parseNum(r['valor'] || 0) || 0), 0); const receberTotal = estado.receber.reduce((s, r) => s + (parseNum(r['valor'] || 0) || 0), 0);
document.getElementById('sys-receber').value = receberTotal > 0 ? fmtNum(receberTotal) : ''; document.getElementById('sys-receber').value = receberTotal > 0 ? fmtNum(receberTotal) : '';
// SYS total = crédito + débito + alimentação + vales + receber + pixCartão + pixCnpj (NÃO inclui troco) // Saldo de Caixa (Sistema) = troco + crédito + débito + alimentação + vales + receber + pixCartão + pixCnpj
const sysTotal = cartCred + cartDeb + cartAli + valesTotal + receberTotal + cartPix + pixCnpjTotal; const sysTotal = parseNum(val('sys-troco')) + cartCred + cartDeb + cartAli + valesTotal + receberTotal + cartPix + pixCnpjTotal;
setText('sys-total', fmt(sysTotal)); setText('sys-total', fmt(sysTotal));
// ── Fechamento Contado — auto-populate (readonly, filled from tables) ── // ── Fechamento Contado — auto-populate (readonly, filled from tables) ──
@@ -857,10 +873,9 @@ function updateTotals() {
const fr = receberTotal; const fr = receberTotal;
setText('fech-total', fmt(fd + fc + fr)); setText('fech-total', fmt(fd + fc + fr));
// Diferença = fechamento - (saldo_esperado - cancelamentos) // Diferença = Saldo de Caixa (Sistema) - saldo_esperado - cancelamentos
const fechamentoTotal = fd + fc + fr;
const cancelTotal = estado.cancelamentos.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 diff = fechamentoTotal - (parseNum(val('f-saldo-esperado')) - cancelTotal); const diff = sysTotal - parseNum(val('f-saldo-esperado')) - cancelTotal;
const difEl = document.getElementById('diferenca'); const difEl = document.getElementById('diferenca');
const badgeEl = document.getElementById('dif-badge'); const badgeEl = document.getElementById('dif-badge');
if (difEl) { if (difEl) {
@@ -1068,6 +1083,8 @@ function buildEstadoForBackend() {
pix: estado.cartoes.pix.map(r => r.valor || 0), pix: estado.cartoes.pix.map(r => r.valor || 0),
}, },
observacoes: estado.observacoes, observacoes: estado.observacoes,
clientes: estado.clientes,
frango: estado.frango,
sync_status: estado.sync_status, sync_status: estado.sync_status,
}; };
} }
@@ -1084,6 +1101,8 @@ function saveState() {
cartoes: parseNum(val('f-fech-cartoes')), cartoes: parseNum(val('f-fech-cartoes')),
receber: parseNum(val('f-fech-receber')), receber: parseNum(val('f-fech-receber')),
}; };
estado.clientes = parseInt(document.getElementById('f-clientes').value) || 0;
estado.frango = parseInt(document.getElementById('f-frango').value) || 0;
estado.updatedAt = new Date().toISOString(); estado.updatedAt = new Date().toISOString();
try { localStorage.setItem(LS_KEY, JSON.stringify(estado)); } catch(e) {} try { localStorage.setItem(LS_KEY, JSON.stringify(estado)); } catch(e) {}
} }
@@ -1103,6 +1122,8 @@ function loadState() {
estado.saldo_esperado = saved.saldo_esperado || 0; estado.saldo_esperado = saved.saldo_esperado || 0;
estado.fechamento = saved.fechamento || 0; estado.fechamento = saved.fechamento || 0;
estado.observacoes = saved.observacoes || ''; estado.observacoes = saved.observacoes || '';
estado.clientes = saved.clientes || 0;
estado.frango = saved.frango || 0;
estado.sync_status = saved.sync_status || 'local'; estado.sync_status = saved.sync_status || 'local';
// Restore tables (always as arrays of objects) // Restore tables (always as arrays of objects)
estado.despesas = Array.isArray(saved.despesas) ? saved.despesas : []; estado.despesas = Array.isArray(saved.despesas) ? saved.despesas : [];
@@ -1243,9 +1264,9 @@ function buildConfirmHTML(data) {
// Relatório completo — mesmo layout do PDF // Relatório completo — mesmo layout do PDF
const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ','); const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ',');
const fmtNeg = v => (v < 0 ? '-' : '') + 'R$ ' + Math.abs(v || 0).toFixed(2).replace('.', ','); const fmtNeg = v => (v < 0 ? '-' : '') + 'R$ ' + Math.abs(v || 0).toFixed(2).replace('.', ',');
// Diferença = fechamento - (saldo_esperado - cancelamentos) // Diferença = fechamento - saldo_esperado - cancelamentos
const diferenca = data.diferenca !== undefined ? data.diferenca const diferenca = data.diferenca !== undefined ? data.diferenca
: ((data.fechamento || 0) - ((data.saldo_esperado || 0) - (data.cancelamentos || 0))); : ((data.fechamento || 0) - (data.saldo_esperado || 0) - (data.cancelamentos || 0));
const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca); const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca);
const diffOk = diferenca === 0; const diffOk = diferenca === 0;
@@ -1395,6 +1416,10 @@ ${cancelamentos_arr.map(c => `<div class="row"><span>${c.numero ? `Nº ${c.numer
<div class="row"><span>À Receber:</span><span>${fmt(frec)}</span></div> <div class="row"><span>À Receber:</span><span>${fmt(frec)}</span></div>
<div class="row total-row"><span>TOTAL:</span><span>${fmt(ftotal)}</span></div> <div class="row total-row"><span>TOTAL:</span><span>${fmt(ftotal)}</span></div>
<div class="section-title">CONTADORES</div>
<div class="row"><span>Clientes:</span><span>${data.clientes || 0}</span></div>
<div class="row"><span>Frango Assado:</span><span>${data.frango || 0}</span></div>
${data.observacoes ? `<div class="obs">${data.observacoes}</div>` : ''} ${data.observacoes ? `<div class="obs">${data.observacoes}</div>` : ''}
<div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div> <div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div>
@@ -1405,9 +1430,9 @@ ${data.observacoes ? `<div class="obs">${data.observacoes}</div>` : ''}
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 fmtNeg = v => (v < 0 ? '-' : '') + 'R$ ' + Math.abs(v || 0).toFixed(2).replace('.', ','); const fmtNeg = v => (v < 0 ? '-' : '') + 'R$ ' + Math.abs(v || 0).toFixed(2).replace('.', ',');
// Diferença = fechamento - (saldo_esperado - cancelamentos) // Diferença = fechamento - saldo_esperado - cancelamentos
const diferenca = data.diferenca !== undefined ? data.diferenca const diferenca = data.diferenca !== undefined ? data.diferenca
: ((data.fechamento || 0) - ((data.saldo_esperado || 0) - (data.cancelamentos || 0))); : ((data.fechamento || 0) - (data.saldo_esperado || 0) - (data.cancelamentos || 0));
const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca); const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca);
const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d'); const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d');
@@ -1610,6 +1635,10 @@ ${cancLines.map(l => `<div class="row"><span>${l.label}</span><span>${fmt(l.valo
<div class="row"><span>À Receber:</span><span>${fmt(frec)}</span></div> <div class="row"><span>À Receber:</span><span>${fmt(frec)}</span></div>
<div class="row total-row"><span>TOTAL:</span><span>${fmt(ftotal)}</span></div> <div class="row total-row"><span>TOTAL:</span><span>${fmt(ftotal)}</span></div>
<div class="section-title">CONTADORES</div>
<div class="row"><span>Clientes:</span><span>${data.clientes || 0}</span></div>
<div class="row"><span>Frango Assado:</span><span>${data.frango || 0}</span></div>
${data.observacoes ? `<div class="obs">${data.observacoes}</div>` : ''} ${data.observacoes ? `<div class="obs">${data.observacoes}</div>` : ''}
<div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div> <div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div>
@@ -1637,7 +1666,7 @@ function buildReportHTML(data) {
const sysTotal = data.sys_total || 0; const sysTotal = data.sys_total || 0;
const saldoEsp = data.saldo_esperado || 0; const saldoEsp = data.saldo_esperado || 0;
const diferenca = data.diferenca !== undefined ? data.diferenca const diferenca = data.diferenca !== undefined ? data.diferenca
: (fechamento - (saldoEsp - cancelamentos)); : (fechamento - saldoEsp - cancelamentos);
const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca); const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca);
const diffColor = diferenca === 0 ? '#2e7d32' : '#c0272d'; const diffColor = diferenca === 0 ? '#2e7d32' : '#c0272d';
@@ -1676,6 +1705,9 @@ function buildReportHTML(data) {
<div class="row"><span>🎯 Saldo Esperado (contado):</span><span class="val">${fmt(saldoEsp)}</span></div> <div class="row"><span>🎯 Saldo Esperado (contado):</span><span class="val">${fmt(saldoEsp)}</span></div>
<div class="row"><span>📐 Diferença:</span><span class="val" style="color:${diffColor}">${diffStr}</span></div> <div class="row"><span>📐 Diferença:</span><span class="val" style="color:${diffColor}">${diffStr}</span></div>
<hr> <hr>
<div class="row"><span>👥 Clientes:</span><span class="val">${data.clientes || 0}</span></div>
<div class="row"><span>🍗 Frango Assado:</span><span class="val">${data.frango || 0}</span></div>
<hr>
<div style="text-align:center;font-size:10px;color:#888">ID: ${data.loja}_${data.data}_${data.operador}</div> <div style="text-align:center;font-size:10px;color:#888">ID: ${data.loja}_${data.data}_${data.operador}</div>
<div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div> <div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div>
</body></html>`; </body></html>`;
@@ -1779,10 +1811,10 @@ function buildReciboData() {
const cancelTotal = estado.cancelamentos.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 fechamentoCounted = 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'));
// SYS total = crédito + débito + alimentação + voucher pix + pixcnpj + vales + receber (NÃO inclui troco) // Saldo de Caixa (Sistema) = troco + crédito + débito + alimentação + voucher pix + pixcnpj + vales + receber
const sysTotal = cartCred + cartDeb + cartAli + cartPix + pixCnpjTotal + valesTotal + receberTotal; const sysTotal = parseNum(val('sys-troco')) + cartCred + cartDeb + cartAli + cartPix + pixCnpjTotal + valesTotal + receberTotal;
// Diferença = fechamento - (saldo_esperado - cancelamentos) // Diferença = saldo de caixa (sistema) - saldo_esperado - cancelamentos
const diferenca = fechamentoCounted - (saldoEsp - cancelTotal); const diferenca = sysTotal - saldoEsp - cancelTotal;
return { return {
uuid: estado.uuid, uuid: estado.uuid,
id_local: estado.id_local, id_local: estado.id_local,
@@ -1821,6 +1853,8 @@ function buildReciboData() {
cartoes_alimentacao: estado.cartoes.alimentacao.map(r => r.valor || 0), cartoes_alimentacao: estado.cartoes.alimentacao.map(r => r.valor || 0),
cartoes_pix: estado.cartoes.pix.map(r => r.valor || 0), cartoes_pix: estado.cartoes.pix.map(r => r.valor || 0),
observacoes: estado.observacoes, observacoes: estado.observacoes,
clientes: estado.clientes,
frango: estado.frango,
sync_status: estado.sync_status, sync_status: estado.sync_status,
}; };
} }
@@ -1872,8 +1906,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 sysTotal = cartCred + cartDeb + cartAli + cartPix + vales + receber + pixcnpj; const sysTotal = parseNum(val('sys-troco')) + cartCred + cartDeb + cartAli + cartPix + vales + receber + pixcnpj;
const diferenca = fechamento - (saldoEsp - cancelamentos); const diferenca = sysTotal - saldoEsp - cancelamentos;
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>
@@ -1887,6 +1921,8 @@ 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>👥 Clientes: <strong>${estado.clientes || 0}</strong></div>
<div>🍗 Frango Assado: <strong>${estado.frango || 0}</strong></div>
<div>📋 Fechamento (contado): <strong>${fmt(fechamento)}</strong></div> <div>📋 Fechamento (contado): <strong>${fmt(fechamento)}</strong></div>
<div>🖥️ Total Sistema: <strong>${fmt(sysTotal)}</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">
@@ -1950,6 +1986,8 @@ document.getElementById('confirm-send').addEventListener('click', async () => {
// ─── Buttons ─────────────────────────────────────────────────────────────── // ─── Buttons ───────────────────────────────────────────────────────────────
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(); });
document.getElementById('f-clientes').addEventListener('input', e => { estado.clientes = parseInt(e.target.value) || 0; scheduleSave(); });
document.getElementById('f-frango').addEventListener('input', e => { estado.frango = parseInt(e.target.value) || 0; scheduleSave(); });
document.getElementById('btn-recibo').addEventListener('click', async () => { document.getElementById('btn-recibo').addEventListener('click', async () => {
const btn = document.getElementById('btn-recibo'); const btn = document.getElementById('btn-recibo');
@@ -2238,8 +2276,6 @@ async function salvarEdicaoSupabase() {
} }
} }
document.getElementById('f-obs').addEventListener('input', e => { estado.observacoes = e.target.value; scheduleSave(); });
// ─── Boot ───────────────────────────────────────────────────────────────── // ─── Boot ─────────────────────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
loadConfig(); loadConfig();