Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 130b2b6da7 | |||
| b47d7766ad | |||
| 78fa778197 | |||
| 5e4340adca |
@@ -318,6 +318,8 @@ impl ReciboData {
|
||||
out.extend(escpos::divider());
|
||||
|
||||
// ── DIFERENÇA ──
|
||||
// Usa self.diferenca que o frontend calcula como sys_total - saldo_esperado
|
||||
// (não recalcula de fechamento, que é o valor contado e não deve ser usado na diferença)
|
||||
out.extend(escpos::line_bold("DIFERENCA"));
|
||||
let diff = self.diferenca;
|
||||
let diff_str = if diff >= 0.0 {
|
||||
|
||||
+379
-297
@@ -1230,271 +1230,92 @@ async function tauriEnviar() {
|
||||
}
|
||||
|
||||
function buildConfirmHTML(data) {
|
||||
// Relatório completo — mesmo layout do PDF
|
||||
const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ',');
|
||||
const fmtNeg = v => (v < 0 ? '-' : '') + 'R$ ' + Math.abs(v || 0).toFixed(2).replace('.', ',');
|
||||
const sangrias_arr = data.sangrias_arr || data.sangrias || [];
|
||||
const despesas_arr = data.despesas_arr || data.despesas || [];
|
||||
const vales_arr = data.vales_arr || data.vales || [];
|
||||
const receber_arr = data.receber_arr || data.receber || [];
|
||||
const pixcnpj_arr = data.pixcnpj_arr || data.pixcnpj || [];
|
||||
const cancelamentos_arr = data.cancelamentos_arr || data.cancelamentos || [];
|
||||
|
||||
const sangrias = sangrias_arr.reduce((s,r) => s+(parseNum(r.retirada)||0)+(parseNum(r.valor)||0), 0);
|
||||
const despesas = despesas_arr.reduce((s,r) => s+(parseNum(r.valor)||0), 0);
|
||||
const vales = vales_arr.reduce((s,r) => s+(parseNum(r.valor)||0), 0);
|
||||
const receber = receber_arr.reduce((s,r) => s+(parseNum(r.valor)||0), 0);
|
||||
const pixcnpj = pixcnpj_arr.reduce((s,r) => s+(parseNum(r.valor)||0), 0);
|
||||
const cancelamentos = cancelamentos_arr.reduce((s,c) => s+(parseNum(c.valor)||0), 0);
|
||||
const cartCred = data.credito || 0;
|
||||
const cartDeb = data.debito || 0;
|
||||
const cartAli = data.alimentacao || 0;
|
||||
const cartPix = data.voucher || data.pix || 0;
|
||||
const fechamento = data.fechamento || 0;
|
||||
const saldoEsp = data.saldo_esperado || 0;
|
||||
const diferenca = fechamento - saldoEsp;
|
||||
const diffClass = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d');
|
||||
const diferenca = data.diferenca !== undefined ? data.diferenca
|
||||
: ((data.sys_total || 0) - (data.saldo_esperado || 0));
|
||||
const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca);
|
||||
const diffOk = diferenca === 0;
|
||||
|
||||
// Monta linhas de detalhe
|
||||
let detailSections = '';
|
||||
const sangrias_arr = Array.isArray(data.sangrias_arr) ? data.sangrias_arr : [];
|
||||
const despesas_arr = Array.isArray(data.despesas_arr) ? data.despesas_arr : [];
|
||||
const pixcnpj_arr = Array.isArray(data.pixcnpj_arr) ? data.pixcnpj_arr : [];
|
||||
const vales_arr = Array.isArray(data.vales_arr) ? data.vales_arr : [];
|
||||
const receber_arr = Array.isArray(data.receber_arr) ? data.receber_arr : [];
|
||||
const cancelamentos_arr = Array.isArray(data.cancelamentos_arr) ? data.cancelamentos_arr : [];
|
||||
|
||||
function detailSection(title, rows, total) {
|
||||
if (!rows && total <= 0) return '';
|
||||
let html = `<div class="detail-section"><div class="detail-title">${title}</div>`;
|
||||
if (rows) html += rows;
|
||||
html += `<div class="detail-total"><span>Total:</span><span>${fmt(total)}</span></div></div>`;
|
||||
return html;
|
||||
const cartCred_arr = Array.isArray(data.cartoes_credito) ? data.cartoes_credito : [];
|
||||
const cartDeb_arr = Array.isArray(data.cartoes_debito) ? data.cartoes_debito : [];
|
||||
const cartAli_arr = Array.isArray(data.cartoes_alimentacao) ? data.cartoes_alimentacao : [];
|
||||
const cartPix_arr = Array.isArray(data.cartoes_pix) ? data.cartoes_pix : [];
|
||||
|
||||
const totalSangrias = sangrias_arr.reduce((s,r) => s+(r.retirada||0)+(r.valor||0), 0);
|
||||
const totalDespesas = despesas_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const totalPixCnpj = pixcnpj_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const totalVales = vales_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const totalReceber = receber_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const totalCancel = cancelamentos_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
|
||||
const cartCred = cartCred_arr.reduce((s,v) => s+(v||0), 0);
|
||||
const cartDeb = cartDeb_arr.reduce((s,v) => s+(v||0), 0);
|
||||
const cartAli = cartAli_arr.reduce((s,v) => s+(v||0), 0);
|
||||
const cartPix = cartPix_arr.reduce((s,v) => s+(v||0), 0);
|
||||
const totalCartoes = cartCred + cartDeb + cartAli + cartPix;
|
||||
|
||||
const fdin = data.fechamento_dinheiro || 0;
|
||||
const fcarts = data.fechamento_cartoes || 0;
|
||||
const frec = data.fechamento_receber || 0;
|
||||
const ftotal = data.fechamento || (fdin + fcarts + frec);
|
||||
const sysTotal = data.sys_total || 0;
|
||||
const saldoEsperado = data.saldo_esperado || 0;
|
||||
|
||||
// Cartoes table
|
||||
const maxRows = Math.max(cartCred_arr.length, cartDeb_arr.length, cartAli_arr.length, cartPix_arr.length);
|
||||
let cartTableRows = '';
|
||||
for (let i = 0; i < maxRows; i++) {
|
||||
const cr = cartCred_arr[i] || 0;
|
||||
const db = cartDeb_arr[i] || 0;
|
||||
const al = cartAli_arr[i] || 0;
|
||||
const px = cartPix_arr[i] || 0;
|
||||
cartTableRows += `<tr>
|
||||
<td>${cr > 0 ? fmt(cr) : '-'}</td>
|
||||
<td>${db > 0 ? fmt(db) : '-'}</td>
|
||||
<td>${al > 0 ? fmt(al) : '-'}</td>
|
||||
<td>${px > 0 ? fmt(px) : '-'}</td>
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
// Sangrias
|
||||
let sangriaRows = '';
|
||||
sangrias_arr.forEach(s => {
|
||||
const v = (parseNum(s.retirada)||0) + (parseNum(s.valor)||0);
|
||||
if (v > 0) {
|
||||
const hora = s.hora ? ` <span class="c2">${s.hora}</span>` : '';
|
||||
const gerente = s.gerente ? ` <span class="c2">(${s.gerente})</span>` : '';
|
||||
sangriaRows += `<div class="detail-row"><span>${hora}${gerente}</span><span>${fmt(v)}</span></div>`;
|
||||
}
|
||||
});
|
||||
detailSections += detailSection('SANGRIAS', sangriaRows, sangrias);
|
||||
|
||||
// Despesas
|
||||
let despRows = '';
|
||||
despesas_arr.forEach(d => {
|
||||
const v = parseNum(d.valor) || 0;
|
||||
if (v > 0) {
|
||||
const obs = d.obs ? ` <span class="c2">${d.obs}</span>` : '';
|
||||
despRows += `<div class="detail-row"><span>${d.desc||''}${obs}</span><span>${fmt(v)}</span></div>`;
|
||||
}
|
||||
});
|
||||
detailSections += detailSection('DESPESAS', despRows, despesas);
|
||||
|
||||
// Vales
|
||||
let valesRows = '';
|
||||
vales_arr.forEach(v => {
|
||||
const val = parseNum(v.valor) || 0;
|
||||
if (val > 0) {
|
||||
const obs = v.obs ? ` <span class="c2">${v.obs}</span>` : '';
|
||||
valesRows += `<div class="detail-row"><span>${v.nome||''}${obs}</span><span>${fmt(val)}</span></div>`;
|
||||
}
|
||||
});
|
||||
detailSections += detailSection('VALES', valesRows, vales);
|
||||
|
||||
// A Receber
|
||||
let recRows = '';
|
||||
receber_arr.forEach(r => {
|
||||
const v = parseNum(r.valor) || 0;
|
||||
if (v > 0) recRows += `<div class="detail-row"><span>${r.nome||''}</span><span>${fmt(v)}</span></div>`;
|
||||
});
|
||||
detailSections += detailSection('A RECEBER', recRows, receber);
|
||||
|
||||
// PIX CNPJ
|
||||
let pixRows = '';
|
||||
pixcnpj_arr.forEach(p => {
|
||||
const v = parseNum(p.valor) || 0;
|
||||
if (v > 0) pixRows += `<div class="detail-row"><span>${p.nome||''}</span><span>${fmt(v)}</span></div>`;
|
||||
});
|
||||
detailSections += detailSection('PIX CNPJ', pixRows, pixcnpj);
|
||||
|
||||
// Cancelamentos
|
||||
let cancRows = '';
|
||||
cancelamentos_arr.forEach(c => {
|
||||
const v = parseNum(c.valor) || 0;
|
||||
if (c.numero || v > 0) {
|
||||
const motivo = c.motivo ? ` <span class="c2">${c.motivo}</span>` : '';
|
||||
cancRows += `<div class="detail-row"><span>${c.numero||''}${motivo}</span><span>${fmt(v)}</span></div>`;
|
||||
}
|
||||
});
|
||||
detailSections += detailSection('CANCELAMENTOS', cancRows, cancelamentos);
|
||||
cartTableRows += `<tr class="total-row">
|
||||
<td>${cartCred > 0 ? fmt(cartCred) : '-'}</td>
|
||||
<td>${cartDeb > 0 ? fmt(cartDeb) : '-'}</td>
|
||||
<td>${cartAli > 0 ? fmt(cartAli) : '-'}</td>
|
||||
<td>${cartPix > 0 ? fmt(cartPix) : '-'}</td>
|
||||
</tr>`;
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Relatório de Fechamento</title>
|
||||
<title>Fechamento de Caixa</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: 'Courier New', monospace; font-size: 13px; width: 80mm; margin: 0 auto; padding: 8px; }
|
||||
.header { text-align: center; margin-bottom: 8px; }
|
||||
.header h1 { font-size: 18px; }
|
||||
.header h2 { font-size: 14px; font-weight: normal; }
|
||||
hr { border: none; border-top: 1px dashed #b3d9f7; margin: 6px 0; }
|
||||
.row { display: flex; justify-content: space-between; padding: 2px 0; }
|
||||
hr { border: none; border-top: 1px dashed #000; margin: 5px 0; }
|
||||
.section-title { font-weight: bold; font-size: 13px; border-top: 1px dashed #000; padding-top: 3px; margin-top: 6px; }
|
||||
.row { display: flex; justify-content: space-between; padding: 1px 0; font-size: 12px; }
|
||||
.row.total-row { font-weight: bold; }
|
||||
.cart-table { width: 100%; border-collapse: collapse; font-size: 11px; margin-top: 4px; }
|
||||
.cart-table th { font-weight: bold; border-bottom: 1px solid #000; padding: 2px; }
|
||||
.cart-table td { padding: 2px 4px; text-align: right; }
|
||||
.cart-table td:first-child { text-align: left; }
|
||||
.cart-table tr.total-row { font-weight: bold; border-top: 1px dashed #000; }
|
||||
.subtotal { font-size: 12px; margin-top: 4px; }
|
||||
.diff-ok { color: #2e7d32; }
|
||||
.diff-bad { color: #c0272d; }
|
||||
.obs { font-size: 11px; color: #555; margin-top: 6px; white-space: pre-wrap; }
|
||||
.footer { text-align: center; font-size: 11px; color: #555; margin-top: 8px; }
|
||||
.detail-section { margin: 6px 0; }
|
||||
.detail-title { font-weight: bold; font-size: 13px; border-top: 1px dashed #b3d9f7; padding-top: 3px; }
|
||||
.detail-row { display: flex; justify-content: space-between; padding: 1px 0; font-size: 12px; }
|
||||
.detail-total { display: flex; justify-content: space-between; padding: 1px 0; font-weight: bold; border-top: 1px dotted #b3d9f7; font-size: 12px; }
|
||||
.c2 { color: #888; }
|
||||
@media print { body { margin: 0; } }
|
||||
</style>
|
||||
</head><body>
|
||||
<div class="header">
|
||||
<h1>${data.loja}</h1>
|
||||
<h2>Fechamento de Caixa</h2>
|
||||
</div>
|
||||
<div style="margin-bottom:6px"><strong>📅 Data:</strong> ${data.data} <strong>👤 Operador:</strong> ${data.operador} <strong>⏰ Turno:</strong> ${data.turno}</div>
|
||||
<hr>
|
||||
${detailSections}
|
||||
<hr>
|
||||
<div>💸 Sangrias: <strong>${fmt(sangrias)}</strong></div>
|
||||
<div>📝 Despesas: <strong>${fmt(despesas)}</strong></div>
|
||||
<div>💰 Vales: <strong>${fmt(vales)}</strong></div>
|
||||
<div>👥 À Receber: <strong>${fmt(receber)}</strong></div>
|
||||
<div>🔵 PIX CNPJ: <strong>${fmt(pixcnpj)}</strong></div>
|
||||
<div>💳 Crédito: <strong>${fmt(cartCred)}</strong></div>
|
||||
<div>💳 Débito: <strong>${fmt(cartDeb)}</strong></div>
|
||||
<div>💳 Alimentação: <strong>${fmt(cartAli)}</strong></div>
|
||||
<div>❌ Cancelamentos: <strong>${fmt(cancelamentos)}</strong></div>
|
||||
<div>📋 Fechamento: <strong>${fmt(fechamento)}</strong></div>
|
||||
<hr>
|
||||
<div>🎯 Saldo Esperado: <strong>${fmt(saldoEsp)}</strong></div>
|
||||
<div style="margin-top:4px">📐 Diferença: <strong style="color:${diffClass}">${diffStr}</strong></div>
|
||||
<div style="margin-top:4px;font-size:10px;color:#888">ID: ${data.loja}_${data.data}_${data.operador}</div>
|
||||
<div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div>
|
||||
</body></html>`;
|
||||
}
|
||||
|
||||
// ─── Print Preview Window
|
||||
|
||||
function buildPrintHTML(data) {
|
||||
const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ',');
|
||||
const fmtNeg = v => (v < 0 ? '-' : '') + 'R$ ' + Math.abs(v || 0).toFixed(2).replace('.', ',');
|
||||
const sangrias_arr = data.sangrias_arr || data.sangrias || [];
|
||||
const despesas_arr = data.despesas_arr || data.despesas || [];
|
||||
const vales_arr = data.vales_arr || data.vales || [];
|
||||
const receber_arr = data.receber_arr || data.receber || [];
|
||||
const pixcnpj_arr = data.pixcnpj_arr || data.pixcnpj || [];
|
||||
const cancelamentos_arr = data.cancelamentos_arr || data.cancelamentos || [];
|
||||
|
||||
const sangrias = sangrias_arr.reduce((s,r) => s+(parseNum(r.retirada)||0)+(parseNum(r.valor)||0), 0);
|
||||
const despesas = despesas_arr.reduce((s,r) => s+(parseNum(r.valor)||0), 0);
|
||||
const vales = vales_arr.reduce((s,r) => s+(parseNum(r.valor)||0), 0);
|
||||
const receber = receber_arr.reduce((s,r) => s+(parseNum(r.valor)||0), 0);
|
||||
const pixcnpj = pixcnpj_arr.reduce((s,r) => s+(parseNum(r.valor)||0), 0);
|
||||
const cancelamentos = cancelamentos_arr.reduce((s,c) => s+(parseNum(c.valor)||0), 0);
|
||||
const cartCred = data.credito || 0;
|
||||
const cartDeb = data.debito || 0;
|
||||
const cartAli = data.alimentacao || 0;
|
||||
const cartPix = data.voucher || data.pix || 0;
|
||||
const fechamento = data.fechamento || data.sys_total || 0;
|
||||
const saldoEsp = data.saldo_esperado || 0;
|
||||
const diferenca = data.diferenca !== undefined ? data.diferenca : (fechamento - saldoEsp);
|
||||
const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca);
|
||||
const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d');
|
||||
|
||||
let detailSections = '';
|
||||
|
||||
function detailSection(title, rows, total) {
|
||||
if (!rows && total <= 0) return '';
|
||||
let html = `<div class="detail-section"><div class="detail-title">${title}</div>`;
|
||||
if (rows) html += rows;
|
||||
html += `<div class="detail-total"><span>Total:</span><span>${fmt(total)}</span></div></div>`;
|
||||
return html;
|
||||
}
|
||||
|
||||
// Sangrias
|
||||
let sangriaRows = '';
|
||||
sangrias_arr.forEach(s => {
|
||||
const v = (parseNum(s.retirada)||0) + (parseNum(s.valor)||0);
|
||||
if (v > 0) {
|
||||
const hora = s.hora ? ` <span class="c2">${s.hora}</span>` : '';
|
||||
const gerente = s.gerente ? ` <span class="c2">(${s.gerente})</span>` : '';
|
||||
sangriaRows += `<div class="detail-row"><span>${hora}${gerente}</span><span>${fmt(v)}</span></div>`;
|
||||
}
|
||||
});
|
||||
detailSections += detailSection('SANGRIAS', sangriaRows, sangrias);
|
||||
|
||||
// Despesas
|
||||
let despRows = '';
|
||||
despesas_arr.forEach(d => {
|
||||
const v = parseNum(d.valor) || 0;
|
||||
if (v > 0) {
|
||||
const obs = d.obs ? ` <span class="c2">${d.obs}</span>` : '';
|
||||
despRows += `<div class="detail-row"><span>${d.desc||''}${obs}</span><span>${fmt(v)}</span></div>`;
|
||||
}
|
||||
});
|
||||
detailSections += detailSection('DESPESAS', despRows, despesas);
|
||||
|
||||
// Vales
|
||||
let valesRows = '';
|
||||
vales_arr.forEach(v => {
|
||||
const val = parseNum(v.valor) || 0;
|
||||
if (val > 0) {
|
||||
const obs = v.obs ? ` <span class="c2">${v.obs}</span>` : '';
|
||||
valesRows += `<div class="detail-row"><span>${v.nome||''}${obs}</span><span>${fmt(val)}</span></div>`;
|
||||
}
|
||||
});
|
||||
detailSections += detailSection('VALES', valesRows, vales);
|
||||
|
||||
// A Receber
|
||||
let recRows = '';
|
||||
receber_arr.forEach(r => {
|
||||
const v = parseNum(r.valor) || 0;
|
||||
if (v > 0) recRows += `<div class="detail-row"><span>${r.nome||''}</span><span>${fmt(v)}</span></div>`;
|
||||
});
|
||||
detailSections += detailSection('A RECEBER', recRows, receber);
|
||||
|
||||
// PIX CNPJ
|
||||
let pixRows = '';
|
||||
pixcnpj_arr.forEach(p => {
|
||||
const v = parseNum(p.valor) || 0;
|
||||
if (v > 0) pixRows += `<div class="detail-row"><span>${p.nome||''}</span><span>${fmt(v)}</span></div>`;
|
||||
});
|
||||
detailSections += detailSection('PIX CNPJ', pixRows, pixcnpj);
|
||||
|
||||
// Cancelamentos
|
||||
let cancRows = '';
|
||||
cancelamentos_arr.forEach(c => {
|
||||
const v = parseNum(c.valor) || 0;
|
||||
if (c.numero || v > 0) {
|
||||
const motivo = c.motivo ? ` <span class="c2">${c.motivo}</span>` : '';
|
||||
cancRows += `<div class="detail-row"><span>${c.numero||''}${motivo}</span><span>${fmt(v)}</span></div>`;
|
||||
}
|
||||
});
|
||||
detailSections += detailSection('CANCELAMENTOS', cancRows, cancelamentos);
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Recibo de Fechamento</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: 'Courier New', monospace; font-size: 13px; width: 80mm; margin: 0 auto; padding: 8px; }
|
||||
.header { text-align: center; margin-bottom: 8px; }
|
||||
.header h1 { font-size: 18px; }
|
||||
.header h2 { font-size: 14px; font-weight: normal; }
|
||||
hr { border: none; border-top: 1px dashed #000; margin: 6px 0; }
|
||||
.section-title { font-weight: bold; font-size: 14px; border-top: 1px dashed #000; padding-top: 4px; margin-top: 6px; }
|
||||
.row { display: flex; justify-content: space-between; padding: 2px 0; }
|
||||
.detail-section { margin: 6px 0; }
|
||||
.detail-title { font-weight: bold; font-size: 13px; border-top: 1px dashed #000; padding-top: 3px; }
|
||||
.detail-row { display: flex; justify-content: space-between; padding: 1px 0; font-size: 12px; }
|
||||
.detail-total { display: flex; justify-content: space-between; padding: 1px 0; font-weight: bold; border-top: 1px dotted #000; font-size: 12px; }
|
||||
.grand-total { font-size: 16px; font-weight: bold; text-align: center; padding: 6px; border: 2px solid #000; margin: 8px 0; }
|
||||
.obs { font-size: 11px; color: #555; margin-top: 6px; white-space: pre-wrap; }
|
||||
.footer { text-align: center; font-size: 11px; color: #555; margin-top: 8px; }
|
||||
.c2 { color: #888; }
|
||||
@media print { body { margin: 0; } }
|
||||
</style>
|
||||
</head><body>
|
||||
@@ -1507,25 +1328,282 @@ function buildPrintHTML(data) {
|
||||
<div class="row"><span>Operador:</span><span>${data.operador}</span></div>
|
||||
<div class="row"><span>Turno:</span><span>${data.turno}</span></div>
|
||||
|
||||
${detailSections}
|
||||
<hr>
|
||||
<div class="row"><span>💸 Sangrias:</span><span>${fmt(sangrias)}</span></div>
|
||||
<div class="row"><span>📝 Despesas:</span><span>${fmt(despesas)}</span></div>
|
||||
<div class="row"><span>💰 Vales:</span><span>${fmt(vales)}</span></div>
|
||||
<div class="row"><span>👥 À Receber:</span><span>${fmt(receber)}</span></div>
|
||||
<div class="row"><span>🔵 PIX CNPJ:</span><span>${fmt(pixcnpj)}</span></div>
|
||||
<div class="row"><span>💳 Crédito:</span><span>${fmt(cartCred)}</span></div>
|
||||
<div class="row"><span>💳 Débito:</span><span>${fmt(cartDeb)}</span></div>
|
||||
<div class="row"><span>💳 Alimentação:</span><span>${fmt(cartAli)}</span></div>
|
||||
<div class="row"><span>❌ Cancelamentos:</span><span>${fmt(cancelamentos)}</span></div>
|
||||
<hr>
|
||||
<div class="grand-total">DIFERENÇA: ${diffStr}</div>
|
||||
${data.observacoes ? `<div class="obs">Obs: ${data.observacoes}</div>` : ''}
|
||||
${sangrias_arr.length > 0 ? `<div class="section-title">SANGRIAS</div>
|
||||
${sangrias_arr.map(s => `<div class="row"><span>${(s.hora||'')}: ${s.gerente||''}</span><span>${fmt((s.retirada||0)+(s.valor||0))}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL SANGRIAS:</span><span>${fmt(totalSangrias)}</span></div>` : ''}
|
||||
|
||||
${despesas_arr.length > 0 ? `<div class="section-title">DESPESAS</div>
|
||||
${despesas_arr.map(d => `<div class="row"><span>${d.desc||''}${d.obs ? ` (${d.obs})` : ''}</span><span>${fmt(d.valor||0)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL DESPESAS:</span><span>${fmt(totalDespesas)}</span></div>` : ''}
|
||||
|
||||
${pixcnpj_arr.length > 0 ? `<div class="section-title">PIX CNPJ</div>
|
||||
${pixcnpj_arr.map(p => `<div class="row"><span>${p.nome||''}</span><span>${fmt(p.valor||0)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL PIX CNPJ:</span><span>${fmt(totalPixCnpj)}</span></div>` : ''}
|
||||
|
||||
${vales_arr.length > 0 ? `<div class="section-title">VALES</div>
|
||||
${vales_arr.map(v => `<div class="row"><span>${v.nome||''}${v.obs ? ` (${v.obs})` : ''}</span><span>${fmt(v.valor||0)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL VALES:</span><span>${fmt(totalVales)}</span></div>` : ''}
|
||||
|
||||
${receber_arr.length > 0 ? `<div class="section-title">A RECEBER</div>
|
||||
${receber_arr.map(r => `<div class="row"><span>${r.nome||''}</span><span>${fmt(r.valor||0)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL A RECEBER:</span><span>${fmt(totalReceber)}</span></div>` : ''}
|
||||
|
||||
${cancelamentos_arr.length > 0 ? `<div class="section-title">CANCELAMENTOS</div>
|
||||
${cancelamentos_arr.map(c => `<div class="row"><span>${c.numero ? `Nº ${c.numero}` : ''}${c.motivo ? ` (${c.motivo})` : ''}</span><span>${fmt(c.valor||0)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL:</span><span>${fmt(totalCancel)}</span></div>` : ''}
|
||||
|
||||
<div class="section-title">DETALHAMENTO DE CARTÕES</div>
|
||||
<table class="cart-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>CRÉDITO</th><th>DÉBITO</th><th>ALIMENT.</th><th>PIX</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${cartTableRows}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="subtotal"><div class="row total-row"><span>Soma Cartões:</span><span>${fmt(totalCartoes)}</span></div></div>
|
||||
|
||||
<div class="section-title">SALDO DE CAIXA (SISTEMA) — RESUMO</div>
|
||||
<div class="row"><span>Troco</span><span>${fmt(data.saldo_troco||0)}</span></div>
|
||||
<div class="row"><span>Crédito</span><span>${fmt(cartCred)}</span></div>
|
||||
<div class="row"><span>Débito</span><span>${fmt(cartDeb)}</span></div>
|
||||
<div class="row"><span>Alimentação</span><span>${fmt(cartAli)}</span></div>
|
||||
<div class="row"><span>Vales</span><span>${fmt(totalVales)}</span></div>
|
||||
<div class="row"><span>À Receber</span><span>${fmt(totalReceber)}</span></div>
|
||||
<div class="row"><span>PIX Cartão</span><span>${fmt(cartPix)}</span></div>
|
||||
<div class="row"><span>PIX CNPJ</span><span>${fmt(totalPixCnpj)}</span></div>
|
||||
<div class="row total-row"><span>TOTAL SISTEMA</span><span>${fmt(sysTotal)}</span></div>
|
||||
<div class="row"><span>Saldo Esperado</span><span>${fmt(saldoEsperado)}</span></div>
|
||||
<div class="row"><span>DIFERENÇA</span><span class="${diffOk ? 'diff-ok' : 'diff-bad'}">${diffStr}${diffOk ? ' ✓ OK' : ''}</span></div>
|
||||
|
||||
<div class="section-title">FECHAMENTO (CONTADO)</div>
|
||||
<div class="row"><span>Dinheiro:</span><span>${fmt(fdin)}</span></div>
|
||||
<div class="row"><span>Cartões:</span><span>${fmt(fcarts)}</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>
|
||||
|
||||
${data.observacoes ? `<div class="obs">${data.observacoes}</div>` : ''}
|
||||
|
||||
<div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div>
|
||||
</body></html>`;
|
||||
}
|
||||
|
||||
// ─── Print Preview Window ──────────────────────────────────────────────────
|
||||
function buildPrintHTML(data) {
|
||||
const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ',');
|
||||
const fmtNeg = v => (v < 0 ? '-' : '') + 'R$ ' + Math.abs(v || 0).toFixed(2).replace('.', ',');
|
||||
const diferenca = data.diferenca !== undefined ? data.diferenca
|
||||
: ((data.sys_total || 0) - (data.saldo_esperado || 0));
|
||||
const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmtNeg(diferenca);
|
||||
const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d');
|
||||
|
||||
// Arrays — support both array-of-objects and flat totals
|
||||
const sangrias_arr = Array.isArray(data.sangrias_arr) ? data.sangrias_arr : [];
|
||||
const despesas_arr = Array.isArray(data.despesas_arr) ? data.despesas_arr : [];
|
||||
const pixcnpj_arr = Array.isArray(data.pixcnpj_arr) ? data.pixcnpj_arr : [];
|
||||
const vales_arr = Array.isArray(data.vales_arr) ? data.vales_arr : [];
|
||||
const receber_arr = Array.isArray(data.receber_arr) ? data.receber_arr : [];
|
||||
const cancelamentos_arr = Array.isArray(data.cancelamentos_arr) ? data.cancelamentos_arr : [];
|
||||
|
||||
// Cartoes arrays from estado
|
||||
const cartCred_arr = Array.isArray(data.cartoes_credito) ? data.cartoes_credito : [];
|
||||
const cartDeb_arr = Array.isArray(data.cartoes_debito) ? data.cartoes_debito : [];
|
||||
const cartAli_arr = Array.isArray(data.cartoes_alimentacao) ? data.cartoes_alimentacao : [];
|
||||
const cartPix_arr = Array.isArray(data.cartoes_pix) ? data.cartoes_pix : [];
|
||||
|
||||
// Flat totals
|
||||
const totalSangrias = sangrias_arr.reduce((s,r) => s+(r.retirada||0)+(r.valor||0), 0);
|
||||
const totalDespesas = despesas_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const totalPixCnpj = pixcnpj_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const totalVales = vales_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const totalReceber = receber_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
const totalCancel = cancelamentos_arr.reduce((s,r) => s+(r.valor||0), 0);
|
||||
|
||||
const cartCred = cartCred_arr.reduce((s,v) => s+(v||0), 0);
|
||||
const cartDeb = cartDeb_arr.reduce((s,v) => s+(v||0), 0);
|
||||
const cartAli = cartAli_arr.reduce((s,v) => s+(v||0), 0);
|
||||
const cartPix = cartPix_arr.reduce((s,v) => s+(v||0), 0);
|
||||
const totalCartoes = cartCred + cartDeb + cartAli + cartPix;
|
||||
|
||||
// Closed-form fields
|
||||
const fdin = data.fechamento_dinheiro || 0;
|
||||
const fcarts = data.fechamento_cartoes || 0;
|
||||
const frec = data.fechamento_receber || 0;
|
||||
const ftotal = data.fechamento || (fdin + fcarts + frec);
|
||||
|
||||
// Build section rows for sangrias, despesas, etc.
|
||||
function section(title, lines, total, fmtFn) {
|
||||
if (!lines.length && total <= 0) return '';
|
||||
let html = `<div class="section-title">${title}</div>`;
|
||||
lines.forEach(l => { if (l.valor > 0 || l.retirada > 0) { html += `<div class="row"><span>${l.label||''}</span><span>${fmtFn(l.valor||l.retirada||0)}</span></div>`; } });
|
||||
if (total > 0) html += `<div class="row total-row"><span>TOTAL ${title}:</span><span>${fmtFn(total)}</span></div>`;
|
||||
return html;
|
||||
}
|
||||
|
||||
// Sangrias rows
|
||||
const sangriaLines = sangrias_arr.map(s => ({
|
||||
label: (s.hora ? s.hora + ': ' : '') + (s.gerente ? `(${s.gerente})` : ''),
|
||||
valor: (s.retirada||0)+(s.valor||0)
|
||||
})).filter(l => l.valor > 0);
|
||||
|
||||
// Despesas rows
|
||||
const despLines = despesas_arr.map(d => ({
|
||||
label: (d.desc||'') + (d.obs ? ` (${d.obs})` : ''),
|
||||
valor: d.valor||0
|
||||
})).filter(l => l.valor > 0);
|
||||
|
||||
// PIX CNPJ rows
|
||||
const pixLines = pixcnpj_arr.map(p => ({
|
||||
label: p.nome||'PIX CNPJ',
|
||||
valor: p.valor||0
|
||||
})).filter(l => l.valor > 0);
|
||||
|
||||
// Vales rows
|
||||
const valesLines = vales_arr.map(v => ({
|
||||
label: (v.nome||'') + (v.obs ? ` (${v.obs})` : ''),
|
||||
valor: v.valor||0
|
||||
})).filter(l => l.valor > 0);
|
||||
|
||||
// A Receber rows
|
||||
const recLines = receber_arr.map(r => ({
|
||||
label: r.nome||'',
|
||||
valor: r.valor||0
|
||||
})).filter(l => l.valor > 0);
|
||||
|
||||
// Cancelamentos rows
|
||||
const cancLines = cancelamentos_arr.map(c => ({
|
||||
label: (c.numero ? `Nº ${c.numero}` : '') + (c.motivo ? ` (${c.motivo})` : ''),
|
||||
valor: c.valor||0
|
||||
})).filter(l => l.valor > 0);
|
||||
|
||||
// Cartoes table (4 columns)
|
||||
const maxRows = Math.max(cartCred_arr.length, cartDeb_arr.length, cartAli_arr.length, cartPix_arr.length);
|
||||
let cartTableRows = '';
|
||||
for (let i = 0; i < maxRows; i++) {
|
||||
const cr = cartCred_arr[i] || 0;
|
||||
const db = cartDeb_arr[i] || 0;
|
||||
const al = cartAli_arr[i] || 0;
|
||||
const px = cartPix_arr[i] || 0;
|
||||
cartTableRows += `<tr>
|
||||
<td>${cr > 0 ? fmt(cr) : '-'}</td>
|
||||
<td>${db > 0 ? fmt(db) : '-'}</td>
|
||||
<td>${al > 0 ? fmt(al) : '-'}</td>
|
||||
<td>${px > 0 ? fmt(px) : '-'}</td>
|
||||
</tr>`;
|
||||
}
|
||||
// Totals row
|
||||
cartTableRows += `<tr class="total-row">
|
||||
<td>${cartCred > 0 ? fmt(cartCred) : '-'}</td>
|
||||
<td>${cartDeb > 0 ? fmt(cartDeb) : '-'}</td>
|
||||
<td>${cartAli > 0 ? fmt(cartAli) : '-'}</td>
|
||||
<td>${cartPix > 0 ? fmt(cartPix) : '-'}</td>
|
||||
</tr>`;
|
||||
|
||||
const sysTotal = data.sys_total || 0;
|
||||
const saldoEsperado = data.saldo_esperado || 0;
|
||||
const diffOk = diferenca === 0;
|
||||
|
||||
let html = `<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Fechamento de Caixa</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: 'Courier New', monospace; font-size: 13px; width: 80mm; margin: 0 auto; padding: 8px; }
|
||||
.header { text-align: center; margin-bottom: 8px; }
|
||||
.header h1 { font-size: 18px; }
|
||||
.header h2 { font-size: 14px; font-weight: normal; }
|
||||
hr { border: none; border-top: 1px dashed #000; margin: 5px 0; }
|
||||
.section-title { font-weight: bold; font-size: 13px; border-top: 1px dashed #000; padding-top: 3px; margin-top: 6px; }
|
||||
.row { display: flex; justify-content: space-between; padding: 1px 0; font-size: 12px; }
|
||||
.row.total-row { font-weight: bold; }
|
||||
.cart-table { width: 100%; border-collapse: collapse; font-size: 11px; margin-top: 4px; }
|
||||
.cart-table th { font-weight: bold; border-bottom: 1px solid #000; padding: 2px; }
|
||||
.cart-table td { padding: 2px 4px; text-align: right; }
|
||||
.cart-table td:first-child { text-align: left; }
|
||||
.cart-table tr.total-row { font-weight: bold; border-top: 1px dashed #000; }
|
||||
.subtotal { font-size: 12px; margin-top: 4px; }
|
||||
.subtotal .row { padding: 1px 0; }
|
||||
.diff-ok { color: #2e7d32; }
|
||||
.diff-bad { color: #c0272d; }
|
||||
.obs { font-size: 11px; color: #555; margin-top: 6px; white-space: pre-wrap; }
|
||||
.footer { text-align: center; font-size: 11px; color: #555; margin-top: 8px; }
|
||||
@media print { body { margin: 0; } }
|
||||
</style>
|
||||
</head><body>
|
||||
<div class="header">
|
||||
<h1>${data.loja}</h1>
|
||||
<h2>Fechamento de Caixa</h2>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row"><span>Data:</span><span>${data.data}</span></div>
|
||||
<div class="row"><span>Operador:</span><span>${data.operador}</span></div>
|
||||
<div class="row"><span>Turno:</span><span>${data.turno}</span></div>
|
||||
|
||||
${sangriaLines.length > 0 ? `<div class="section-title">SANGRIAS</div>
|
||||
${sangriaLines.map(l => `<div class="row"><span>${l.label}</span><span>${fmt(l.valor)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL SANGRIAS:</span><span>${fmt(totalSangrias)}</span></div>` : ''}
|
||||
|
||||
${despLines.length > 0 ? `<div class="section-title">DESPESAS</div>
|
||||
${despLines.map(l => `<div class="row"><span>${l.label}</span><span>${fmt(l.valor)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL DESPESAS:</span><span>${fmt(totalDespesas)}</span></div>` : ''}
|
||||
|
||||
${pixLines.length > 0 ? `<div class="section-title">PIX CNPJ</div>
|
||||
${pixLines.map(l => `<div class="row"><span>${l.label}</span><span>${fmt(l.valor)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL PIX CNPJ:</span><span>${fmt(totalPixCnpj)}</span></div>` : ''}
|
||||
|
||||
${valesLines.length > 0 ? `<div class="section-title">VALES</div>
|
||||
${valesLines.map(l => `<div class="row"><span>${l.label}</span><span>${fmt(l.valor)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL VALES:</span><span>${fmt(totalVales)}</span></div>` : ''}
|
||||
|
||||
${recLines.length > 0 ? `<div class="section-title">A RECEBER</div>
|
||||
${recLines.map(l => `<div class="row"><span>${l.label}</span><span>${fmt(l.valor)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL A RECEBER:</span><span>${fmt(totalReceber)}</span></div>` : ''}
|
||||
|
||||
${cancLines.length > 0 ? `<div class="section-title">CANCELAMENTOS</div>
|
||||
${cancLines.map(l => `<div class="row"><span>${l.label}</span><span>${fmt(l.valor)}</span></div>`).join('')}
|
||||
<div class="row total-row"><span>TOTAL:</span><span>${fmt(totalCancel)}</span></div>` : ''}
|
||||
|
||||
<div class="section-title">DETALHAMENTO DE CARTÕES</div>
|
||||
<table class="cart-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>CRÉDITO</th><th>DÉBITO</th><th>ALIMENT.</th><th>PIX</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${cartTableRows}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="subtotal"><div class="row total-row"><span>Soma Cartões:</span><span>${fmt(totalCartoes)}</span></div></div>
|
||||
|
||||
<div class="section-title">SALDO DE CAIXA (SISTEMA) — RESUMO</div>
|
||||
<div class="row"><span>Troco</span><span>${fmt(data.saldo_troco||0)}</span></div>
|
||||
<div class="row"><span>Crédito</span><span>${fmt(cartCred)}</span></div>
|
||||
<div class="row"><span>Débito</span><span>${fmt(cartDeb)}</span></div>
|
||||
<div class="row"><span>Alimentação</span><span>${fmt(cartAli)}</span></div>
|
||||
<div class="row"><span>Vales</span><span>${fmt(totalVales)}</span></div>
|
||||
<div class="row"><span>À Receber</span><span>${fmt(totalReceber)}</span></div>
|
||||
<div class="row"><span>PIX Cartão</span><span>${fmt(cartPix)}</span></div>
|
||||
<div class="row"><span>PIX CNPJ</span><span>${fmt(totalPixCnpj)}</span></div>
|
||||
<div class="row total-row"><span>TOTAL SISTEMA</span><span>${fmt(sysTotal)}</span></div>
|
||||
<div class="row"><span>Saldo Esperado</span><span>${fmt(saldoEsperado)}</span></div>
|
||||
<div class="row"><span>DIFERENÇA</span><span class="${diffOk ? 'diff-ok' : 'diff-bad'}">${diffStr}${diffOk ? ' ✓ OK' : ''}</span></div>
|
||||
|
||||
<div class="section-title">FECHAMENTO (CONTADO)</div>
|
||||
<div class="row"><span>Dinheiro:</span><span>${fmt(fdin)}</span></div>
|
||||
<div class="row"><span>Cartões:</span><span>${fmt(fcarts)}</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>
|
||||
|
||||
${data.observacoes ? `<div class="obs">${data.observacoes}</div>` : ''}
|
||||
|
||||
<div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div>
|
||||
</body></html>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function openPrintPreview(data, mode) {
|
||||
@@ -1609,8 +1687,9 @@ function triggerWindowPrint() {
|
||||
}
|
||||
|
||||
// ─── Recibo 80mm via Tauri (ESC/POS USB) ─────────────────────────────────
|
||||
async function tauriRecibo() {
|
||||
// Build flat totals for the Rust ReciboData struct
|
||||
// ─── Recibo 80mm via Tauri (ESC/POS USB) ─────────────────────────────────
|
||||
// Build data object shared by both ESC/POS and preview
|
||||
function buildReciboData() {
|
||||
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);
|
||||
@@ -1625,7 +1704,7 @@ async function tauriRecibo() {
|
||||
const saldoEsp = parseNum(val('f-saldo-esperado'));
|
||||
// SYS total = troco + crédito + débito + alimentação + vales + receber + pixCartão + pixCnpj
|
||||
const sysTotal = parseNum(val('sys-troco')) + cartCred + cartDeb + cartAli + valesTotal + receberTotal + cartPix + pixCnpjTotal;
|
||||
const data = {
|
||||
return {
|
||||
uuid: estado.uuid,
|
||||
id_local: estado.id_local,
|
||||
loja: estado.loja,
|
||||
@@ -1637,6 +1716,9 @@ async function tauriRecibo() {
|
||||
fechamento: fechamentoCounted,
|
||||
diferenca: sysTotal - saldoEsp,
|
||||
sys_total: sysTotal,
|
||||
fechamento_dinheiro: parseNum(val('f-fech-dinheiro')),
|
||||
fechamento_cartoes: parseNum(val('f-fech-cartoes')),
|
||||
fechamento_receber: parseNum(val('f-fech-receber')),
|
||||
// Flat totals for ReciboData struct (Rust) — must be numbers
|
||||
credito: cartCred,
|
||||
debito: cartDeb,
|
||||
@@ -1648,25 +1730,31 @@ async function tauriRecibo() {
|
||||
vales: valesTotal,
|
||||
areceber: receberTotal,
|
||||
cancelamentos: cancelTotal,
|
||||
// Full arrays for backend/storage
|
||||
// Full arrays for preview
|
||||
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 },
|
||||
cartoes_credito: estado.cartoes.credito.map(r => r.valor || 0),
|
||||
cartoes_debito: estado.cartoes.debito.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),
|
||||
observacoes: estado.observacoes,
|
||||
sync_status: estado.sync_status,
|
||||
};
|
||||
}
|
||||
|
||||
// Tenta ESC/POS via Tauri primeiro; se falhar, abre preview
|
||||
async function tauriRecibo() {
|
||||
const data = buildReciboData();
|
||||
|
||||
// Tenta ESC/POS via Tauri primeiro; se falhar, so lanca erro (preview tratado pelo caller)
|
||||
try {
|
||||
return await window.__TAURI__.core.invoke('imprimir_recibo', { data: JSON.stringify(data) });
|
||||
} catch(e) {
|
||||
console.warn('ESC/POS falhou, abrindo preview:', e);
|
||||
openPrintPreview(data);
|
||||
throw e;
|
||||
console.warn('ESC/POS falhou:', e);
|
||||
throw e; // re-lanca para o caller tratar o preview
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1740,29 +1828,17 @@ document.getElementById('modal-confirm').addEventListener('click', e => { if (e.
|
||||
|
||||
// Print from confirm modal — abre preview idêntico ao modal de confirmação
|
||||
document.getElementById('confirm-print').addEventListener('click', async () => {
|
||||
// Usa buildReciboData para não duplicar lógica e ter todos os campos certos
|
||||
let data;
|
||||
try {
|
||||
data = buildReciboData();
|
||||
} catch(e) {
|
||||
console.error('Erro ao montar dados do recibo:', e);
|
||||
alert('Erro ao montar dados do recibo.');
|
||||
return;
|
||||
}
|
||||
// Fecha modal APÓS gerar preview (não antes)
|
||||
closeConfirmModal();
|
||||
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 fechamentoCounted = parseNum(val('f-fech-dinheiro')) + parseNum(val('f-fech-cartoes')) + parseNum(val('f-fech-receber'));
|
||||
const saldoEsp = parseNum(val('f-saldo-esperado'));
|
||||
const data = {
|
||||
loja: estado.loja, data: estado.data, operador: estado.operador, turno: estado.turno,
|
||||
saldo_troco: parseNum(val('sys-troco')) || 0,
|
||||
saldo_esperado: saldoEsp,
|
||||
fechamento: fechamentoCounted,
|
||||
diferenca: fechamentoCounted - saldoEsp,
|
||||
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||'' })),
|
||||
credito: cartCred, debito: cartDeb, alimentacao: cartAli,
|
||||
voucher: cartPix,
|
||||
observacoes: estado.observacoes,
|
||||
};
|
||||
openPrintPreview(data, 'confirm');
|
||||
});
|
||||
|
||||
@@ -1807,13 +1883,19 @@ 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
|
||||
// Tenta ESC/POS primeiro; se falhar, nada acontece visualmente
|
||||
// — siempre abre preview depois para o usuário ver algo
|
||||
await tauriRecibo();
|
||||
// Se chegou aqui sem erro, ESC/POS funcionou
|
||||
} catch(e) {
|
||||
// ESC/POS falhou — openPrintPreview já foi chamado dentro de tauriRecibo
|
||||
// Só mostra alerta se nem o preview abriu
|
||||
console.warn('Recibo:', e);
|
||||
console.warn('ESC/POS falhou:', e);
|
||||
}
|
||||
// Sempre abre preview depois da tentativa ESC/POS
|
||||
try {
|
||||
const data = buildReciboData();
|
||||
openPrintPreview(data, 'recibo');
|
||||
} catch(e2) {
|
||||
console.error('Preview falhou:', e2);
|
||||
alert('Erro ao gerar preview do recibo.');
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user