|
|
|
@@ -384,7 +384,7 @@
|
|
|
|
|
|
|
|
|
|
<!-- SALDO DE CAIXA -->
|
|
|
|
|
<div class="section">
|
|
|
|
|
<div class="section-header">🖥️ Saldo de Caixa (Valores do Sistema)</div>
|
|
|
|
|
<div class="section-header">🖥️ Fechamento de Caixa</div>
|
|
|
|
|
<div class="sys-grid">
|
|
|
|
|
<div class="sys-row"><span class="lbl">Troco (+)</span><input type="text" id="sys-troco" class="editable" placeholder="0,00" /></div>
|
|
|
|
|
<div class="sys-row"><span class="lbl">Crédito (+)</span><input type="text" id="sys-credito" readonly tabindex="-1" /></div>
|
|
|
|
@@ -415,7 +415,7 @@
|
|
|
|
|
|
|
|
|
|
<!-- FECHAMENTO (VALORES CONTADOS) -->
|
|
|
|
|
<div class="section">
|
|
|
|
|
<div class="section-header">🛒 Fechamento (Valores Contados)</div>
|
|
|
|
|
<div class="section-header">🛒 Saldo de Caixa</div>
|
|
|
|
|
<div class="fech-grid">
|
|
|
|
|
<div class="fech-item"><div class="fech-item-label">Dinheiro</div><input type="text" id="f-fech-dinheiro" placeholder="0,00" /></div>
|
|
|
|
|
<div class="fech-item"><div class="fech-item-label">Cartões</div><input type="text" id="f-fech-cartoes" placeholder="0,00" /></div>
|
|
|
|
@@ -1229,68 +1229,91 @@ async function tauriEnviar() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ─── Print Preview Window ──────────────────────────────────────────────────
|
|
|
|
|
function buildPrintHTML(data) {
|
|
|
|
|
function buildConfirmHTML(data) {
|
|
|
|
|
// Relatório completo — mesmo layout do PDF
|
|
|
|
|
const fmt = v => 'R$ ' + (v || 0).toFixed(2).replace('.', ',');
|
|
|
|
|
const diferenca = (data.fechamento || 0) - (data.total_operado || 0);
|
|
|
|
|
const diffStr = diferenca >= 0 ? `+${fmt(diferenca)}` : fmt(diferenca);
|
|
|
|
|
const diffColor = diferenca === 0 ? '#2e7d32' : (diferenca > 0 ? '#e65100' : '#c0272d');
|
|
|
|
|
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 diffOk = diferenca === 0;
|
|
|
|
|
|
|
|
|
|
let rows = '';
|
|
|
|
|
// Cancelamentos (sum the array first — single cancelamentos is a float total, array is from confirm-print)
|
|
|
|
|
const cancelTotal = Array.isArray(data.cancelamentos)
|
|
|
|
|
? data.cancelamentos.reduce((s, c) => s + (parseNum(c.valor || 0) || 0), 0)
|
|
|
|
|
: (data.cancelamentos || 0);
|
|
|
|
|
// PIX total (flat number from tauriRecibo; pixcnpj is also flat total)
|
|
|
|
|
const pixTotal = data.pix || data.voucher || 0;
|
|
|
|
|
const pixCnpjTotal = typeof data.pixcnpj === 'number' ? data.pixcnpj : 0;
|
|
|
|
|
// Sangrias
|
|
|
|
|
if (data.sangrias && data.sangrias.length > 0) {
|
|
|
|
|
data.sangrias.forEach(s => { if (s.hora || s.retirada) rows += `<tr><td>${s.hora||''}</td><td>${fmt(s.retirada)}</td><td>${s.gerente||''}</td></tr>`; });
|
|
|
|
|
}
|
|
|
|
|
// Despesas
|
|
|
|
|
if (data.despesas && data.despesas.length > 0) {
|
|
|
|
|
data.despesas.forEach(d => { if (d.desc || d.valor) rows += `<tr><td>${d.desc||''}</td><td>${fmt(d.valor)}</td><td>${d.obs||''}</td></tr>`; });
|
|
|
|
|
}
|
|
|
|
|
// Vales
|
|
|
|
|
if (data.vales && data.vales.length > 0) {
|
|
|
|
|
data.vales.forEach(v => { if (v.nome || v.valor) rows += `<tr><td>${v.nome||''}</td><td>${fmt(v.valor)}</td><td>${v.obs||''}</td></tr>`; });
|
|
|
|
|
}
|
|
|
|
|
// Receber
|
|
|
|
|
if (data.receber && data.receber.length > 0) {
|
|
|
|
|
data.receber.forEach(r => { if (r.nome || r.valor) rows += `<tr><td>${r.nome||''}</td><td>${fmt(r.valor)}</td><td></td></tr>`; });
|
|
|
|
|
}
|
|
|
|
|
// PIX CNPJ (flat total, not array)
|
|
|
|
|
if (pixCnpjTotal > 0) {
|
|
|
|
|
rows += `<tr><td>PIX CNPJ</td><td>${fmt(pixCnpjTotal)}</td><td></td></tr>`;
|
|
|
|
|
}
|
|
|
|
|
// Cancelamentos
|
|
|
|
|
if (cancelTotal > 0) {
|
|
|
|
|
rows += `<tr><td>Cancelamentos</td><td>${fmt(cancelTotal)}</td><td></td></tr>`;
|
|
|
|
|
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 : [];
|
|
|
|
|
|
|
|
|
|
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>`;
|
|
|
|
|
}
|
|
|
|
|
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 #000; margin: 6px 0; }
|
|
|
|
|
.section { 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; }
|
|
|
|
|
.row.space-between { justify-content: space-between; }
|
|
|
|
|
.row.below { margin-top: 4px; }
|
|
|
|
|
table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
|
|
|
td { padding: 2px 4px; vertical-align: top; }
|
|
|
|
|
td:nth-child(2) { text-align: right; }
|
|
|
|
|
td:nth-child(3) { text-align: right; color: #555; font-size: 11px; }
|
|
|
|
|
.total-row { font-weight: bold; border-top: 1px dashed #000; }
|
|
|
|
|
.grand-total { font-size: 16px; font-weight: bold; text-align: center; padding: 6px; border: 2px solid #000; margin: 8px 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; }
|
|
|
|
|
@media print { body { margin: 0; } }
|
|
|
|
@@ -1305,30 +1328,286 @@ 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>
|
|
|
|
|
|
|
|
|
|
<div class="section-title">ENTRADAS</div>
|
|
|
|
|
<div class="row"><span>Saldo Troco:</span><span>${fmt(data.saldo_troco)}</span></div>
|
|
|
|
|
<div class="row"><span>Fechamento:</span><span>${fmt(data.total_operado || 0)}</span></div>
|
|
|
|
|
<div class="row"><span>Saldo Esperado:</span><span>${fmt(data.saldo_esperado)}</span></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>` : ''}
|
|
|
|
|
|
|
|
|
|
${rows ? `<div class="section-title">DETALHES</div><table><tbody>${rows}</tbody></table>` : ''}
|
|
|
|
|
${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>` : ''}
|
|
|
|
|
|
|
|
|
|
${data.observacoes ? `<div class="obs">Obs: ${data.observacoes}</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>` : ''}
|
|
|
|
|
|
|
|
|
|
<hr>
|
|
|
|
|
<div class="section-title">CARTÕES</div>
|
|
|
|
|
<div class="row"><span>Crédito:</span><span>${fmt(data.credito||0)}</span></div>
|
|
|
|
|
<div class="row"><span>Débito:</span><span>${fmt(data.debito||0)}</span></div>
|
|
|
|
|
<div class="row"><span>Alimentação:</span><span>${fmt(data.alimentacao||0)}</span></div>
|
|
|
|
|
<div class="row"><span>PIX Cartão:</span><span>${fmt(pixTotal)}</span></div>
|
|
|
|
|
<div class="row"><span>Cancelamentos:</span><span>${fmt(cancelTotal)}</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>` : ''}
|
|
|
|
|
|
|
|
|
|
<hr>
|
|
|
|
|
<div class="grand-total">DIFERENÇA: ${diffStr}</div>
|
|
|
|
|
<div class="footer">Gerado em ${new Date().toLocaleString('pt-BR')}</div>
|
|
|
|
|
</body></html>`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function openPrintPreview(data) {
|
|
|
|
|
// ─── 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) {
|
|
|
|
|
const html = mode === 'confirm' ? buildConfirmHTML(data) : buildPrintHTML(data);
|
|
|
|
|
// Remove preview anterior se existir
|
|
|
|
|
const existing = document.getElementById('print-preview-overlay');
|
|
|
|
|
if (existing) document.body.removeChild(existing);
|
|
|
|
@@ -1362,7 +1641,6 @@ function openPrintPreview(data) {
|
|
|
|
|
</style>
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const html = buildPrintHTML(data);
|
|
|
|
|
const fullHtml = `<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Recibo</title>${previewStyle}</head><body>${html}</body></html>`;
|
|
|
|
|
|
|
|
|
|
const iframe = document.createElement('iframe');
|
|
|
|
@@ -1409,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);
|
|
|
|
@@ -1423,21 +1702,23 @@ async function tauriRecibo() {
|
|
|
|
|
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 saldoEsp = parseNum(val('f-saldo-esperado'));
|
|
|
|
|
const sysTroco = parseNum(val('sys-troco'));
|
|
|
|
|
// total_operado = soma de todas operações creditadas (não é o fechamento contado)
|
|
|
|
|
const totalOperado = cartCred + cartDeb + cartAli + cartPix + pixCnpjTotal;
|
|
|
|
|
const data = {
|
|
|
|
|
// 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;
|
|
|
|
|
return {
|
|
|
|
|
uuid: estado.uuid,
|
|
|
|
|
id_local: estado.id_local,
|
|
|
|
|
loja: estado.loja,
|
|
|
|
|
data: estado.data,
|
|
|
|
|
operador: estado.operador,
|
|
|
|
|
turno: estado.turno,
|
|
|
|
|
saldo_troco: sysTroco,
|
|
|
|
|
saldo_troco: parseNum(val('sys-troco')),
|
|
|
|
|
saldo_esperado: saldoEsp,
|
|
|
|
|
fechamento: fechamentoCounted,
|
|
|
|
|
diferenca: fechamentoCounted - saldoEsp,
|
|
|
|
|
total_operado: totalOperado,
|
|
|
|
|
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,
|
|
|
|
@@ -1449,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', { estado: JSON.stringify(data) });
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1482,13 +1769,17 @@ async function tauriCarregarRascunho() {
|
|
|
|
|
|
|
|
|
|
// ─── Confirm Modal ────────────────────────────────────────────────────────
|
|
|
|
|
function openConfirmModal() {
|
|
|
|
|
console.log('[DEBUG] openConfirmModal chamado');
|
|
|
|
|
const operador = val('f-operador').trim();
|
|
|
|
|
const turno = val('f-turno').trim();
|
|
|
|
|
const loja = val('f-loja').trim();
|
|
|
|
|
console.log('[DEBUG] openConfirmModal campos:', {operador, turno, loja});
|
|
|
|
|
if (!operador || !turno || !loja) {
|
|
|
|
|
console.log('[DEBUG] openConfirmModal: campos faltando, alert');
|
|
|
|
|
alert('⚠️ Preencha Operador, Turno e Loja antes de enviar.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
console.log('[DEBUG] openConfirmModal: campos OK, montando modal');
|
|
|
|
|
// Build summary
|
|
|
|
|
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);
|
|
|
|
@@ -1502,7 +1793,8 @@ function openConfirmModal() {
|
|
|
|
|
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 saldoEsp = parseNum(val('f-saldo-esperado'));
|
|
|
|
|
const diferenca = fechamento - 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');
|
|
|
|
|
document.getElementById('confirm-summary').innerHTML =
|
|
|
|
|
`<div style="margin-bottom:6px"><strong>📅 Data:</strong> ${estado.data} <strong>👤 Operador:</strong> ${operador} <strong>⏰ Turno:</strong> ${turno} <strong>🏪 Loja:</strong> ${loja}</div>
|
|
|
|
@@ -1516,11 +1808,13 @@ function openConfirmModal() {
|
|
|
|
|
<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>
|
|
|
|
|
<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">
|
|
|
|
|
<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;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');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1532,36 +1826,20 @@ 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 — abre preview no navegador
|
|
|
|
|
// 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 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 saldoEsp = parseNum(val('f-saldo-esperado'));
|
|
|
|
|
const totalOperado = cartCred + cartDeb + cartAli + cartPix + (estado.pixcnpj.reduce((s,r) => s+(parseNum(r.valor||0)||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: saldoEsp,
|
|
|
|
|
fechamento: fechamentoCounted,
|
|
|
|
|
diferenca: fechamentoCounted - saldoEsp,
|
|
|
|
|
total_operado: totalOperado,
|
|
|
|
|
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,
|
|
|
|
|
pix: cartPix, // flat float for buildPrintHTML
|
|
|
|
|
cartoes: { credito: estado.cartoes.credito, debito: estado.cartoes.debito, alimentacao: estado.cartoes.alimentacao, pix: estado.cartoes.pix },
|
|
|
|
|
observacoes: estado.observacoes,
|
|
|
|
|
};
|
|
|
|
|
openPrintPreview(data);
|
|
|
|
|
openPrintPreview(data, 'confirm');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Confirm send
|
|
|
|
@@ -1593,6 +1871,11 @@ document.getElementById('confirm-send').addEventListener('click', async () => {
|
|
|
|
|
|
|
|
|
|
// ─── Buttons ───────────────────────────────────────────────────────────────
|
|
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@@ -1600,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;
|
|
|
|
|
}
|
|
|
|
@@ -1616,131 +1905,179 @@ document.getElementById('btn-limpar').addEventListener('click', () => {
|
|
|
|
|
if (!confirm('Limpar rascunho? Esta acção não pode ser revertida.')) return;
|
|
|
|
|
localStorage.removeItem(LS_KEY);
|
|
|
|
|
// Reseta estado e re-renderiza sem reload
|
|
|
|
|
estado = newEstado();
|
|
|
|
|
estado.loja = val('f-loja') || 'União';
|
|
|
|
|
estado.data = val('f-data') || new Date().toISOString().split('T')[0];
|
|
|
|
|
estado = {
|
|
|
|
|
uuid: crypto.randomUUID ? crypto.randomUUID() : Date.now().toString(),
|
|
|
|
|
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();
|
|
|
|
|
renderAllTables();
|
|
|
|
|
syncUI();
|
|
|
|
|
showToast('Rascunho limpo.', 'info');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.getElementById('btn-anterior').addEventListener('click', async () => {
|
|
|
|
|
const loja = val('f-loja') || 'União';
|
|
|
|
|
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';
|
|
|
|
|
console.log('[DEBUG] btn-anterior loja:', loja);
|
|
|
|
|
const hasTauri = !!(window.__TAURI__ && window.__TAURI__.core);
|
|
|
|
|
|
|
|
|
|
// Carrega lista de fechamentos recentes do Supabase com uuid
|
|
|
|
|
let recentList = [];
|
|
|
|
|
try {
|
|
|
|
|
recentList = await window.__TAURI__.core.invoke('sb_listar_recentes', { loja, limite: 20 });
|
|
|
|
|
} catch(e) {
|
|
|
|
|
console.warn('sb_listar_recentes falhou:', e);
|
|
|
|
|
}
|
|
|
|
|
// Salva rascunho atual antes de tudo
|
|
|
|
|
if (hasTauri) {
|
|
|
|
|
try { await window.__TAURI__.core.invoke('salvar_rascunho_local', {}); } catch(e) { console.warn('salvar_rascunho_local:', e); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Extrai datas únicas ordenadas + mapeamento data→id
|
|
|
|
|
const dateIdMap = {};
|
|
|
|
|
const dateList = [];
|
|
|
|
|
if (recentList && recentList.length > 0) {
|
|
|
|
|
recentList.forEach(item => {
|
|
|
|
|
if (item.data && !dateIdMap[item.data]) {
|
|
|
|
|
dateIdMap[item.data] = item.id;
|
|
|
|
|
dateList.push(item.data);
|
|
|
|
|
// Calcula dia anterior
|
|
|
|
|
const prevDate = new Date(estado.data);
|
|
|
|
|
prevDate.setDate(prevDate.getDate() - 1);
|
|
|
|
|
const prevDateStr = prevDate.toISOString().split('T')[0];
|
|
|
|
|
|
|
|
|
|
// Confirmação explícita antes de trocar de dia
|
|
|
|
|
const confirmMsg = `ATENÇÃO: vai carregar o fechamento de ${prevDateStr}.\n\nO formulário atual será LIMPO caso não tenha enviado.\n\nContinuar?`;
|
|
|
|
|
if (!confirm(confirmMsg)) {
|
|
|
|
|
console.log('[DEBUG] btn-anterior cancelado pelo usuário');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Carrega lista de fechamentos recentes do Supabase com uuid
|
|
|
|
|
let recentList = [];
|
|
|
|
|
if (hasTauri) {
|
|
|
|
|
try {
|
|
|
|
|
recentList = await window.__TAURI__.core.invoke('sb_listar_recentes', { loja, limite: 20 });
|
|
|
|
|
console.log('[DEBUG] sb_listar_recentes retornou:', recentList?.length, 'itens');
|
|
|
|
|
} catch(e) {
|
|
|
|
|
console.warn('sb_listar_recentes falhou:', e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
dateList.sort().reverse();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.warn('Tauri não disponível, pulando sb_listar_recentes');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let selectedDate = null;
|
|
|
|
|
let selectedId = null;
|
|
|
|
|
if (dateList.length > 0) {
|
|
|
|
|
const msg = dateList.map((d, i) => `${i + 1}) ${d}`).join('\n');
|
|
|
|
|
const escolha = prompt(`Selecione o número do dia anterior:\n${msg}\n\n(Deixe em branco e clique Cancelar para ver só o dia anterior automático)`);
|
|
|
|
|
if (escolha !== null && escolha.trim() !== '') {
|
|
|
|
|
const idx = parseInt(escolha) - 1;
|
|
|
|
|
if (idx >= 0 && idx < dateList.length) {
|
|
|
|
|
selectedDate = dateList[idx];
|
|
|
|
|
selectedId = dateIdMap[selectedDate];
|
|
|
|
|
// Extrai datas únicas ordenadas + mapeamento data→id
|
|
|
|
|
const dateIdMap = {};
|
|
|
|
|
const dateList = [];
|
|
|
|
|
if (recentList && recentList.length > 0) {
|
|
|
|
|
recentList.forEach(item => {
|
|
|
|
|
if (item.data && !dateIdMap[item.data]) {
|
|
|
|
|
dateIdMap[item.data] = item.id;
|
|
|
|
|
dateList.push(item.data);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
dateList.sort().reverse();
|
|
|
|
|
}
|
|
|
|
|
console.log('[DEBUG] dateList:', dateList);
|
|
|
|
|
|
|
|
|
|
let selectedDate = null;
|
|
|
|
|
let selectedId = null;
|
|
|
|
|
if (dateList.length > 0) {
|
|
|
|
|
const msg = dateList.map((d, i) => `${i + 1}) ${d}`).join('\n');
|
|
|
|
|
const escolha = prompt(`Selecione o número do dia anterior:\n${msg}\n\n(Deixe em branco e clique Cancelar para ver só o dia anterior automático)`);
|
|
|
|
|
if (escolha !== null && escolha.trim() !== '') {
|
|
|
|
|
const idx = parseInt(escolha) - 1;
|
|
|
|
|
if (idx >= 0 && idx < dateList.length) {
|
|
|
|
|
selectedDate = dateList[idx];
|
|
|
|
|
selectedId = dateIdMap[selectedDate];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Se não escolheu data, usa dia anterior automático (sem id — carrega por data)
|
|
|
|
|
if (!selectedDate) {
|
|
|
|
|
const d = new Date(estado.data); d.setDate(d.getDate() - 1);
|
|
|
|
|
selectedDate = d.toISOString().split('T')[0];
|
|
|
|
|
}
|
|
|
|
|
// Se não escolheu data, usa dia anterior automático (sem id — carrega por data)
|
|
|
|
|
if (!selectedDate) {
|
|
|
|
|
selectedDate = prevDateStr;
|
|
|
|
|
}
|
|
|
|
|
console.log('[DEBUG] selectedDate:', selectedDate, 'selectedId:', selectedId);
|
|
|
|
|
|
|
|
|
|
await tauriSaveLocal();
|
|
|
|
|
setVal('f-data', selectedDate);
|
|
|
|
|
estado.data = selectedDate;
|
|
|
|
|
estado.uuid = crypto.randomUUID ? crypto.randomUUID() : Date.now().toString();
|
|
|
|
|
estado.id_local = null;
|
|
|
|
|
syncHeader();
|
|
|
|
|
setVal('f-data', selectedDate);
|
|
|
|
|
estado.data = selectedDate;
|
|
|
|
|
estado.uuid = crypto.randomUUID ? crypto.randomUUID() : Date.now().toString();
|
|
|
|
|
estado.id_local = null;
|
|
|
|
|
syncHeader();
|
|
|
|
|
|
|
|
|
|
// Tenta Supabase primeiro (com id se disponível), senão local
|
|
|
|
|
let rascunho = null;
|
|
|
|
|
if (selectedId) {
|
|
|
|
|
// Usa sb_buscar_por_id para buscar por id numérico do Supabase
|
|
|
|
|
try {
|
|
|
|
|
rascunho = await window.__TAURI__.core.invoke('sb_buscar_por_id', { id: selectedId });
|
|
|
|
|
} catch(e) { console.warn('sb_buscar_por_id falhou:', e); }
|
|
|
|
|
}
|
|
|
|
|
if (!rascunho) {
|
|
|
|
|
try {
|
|
|
|
|
rascunho = await window.__TAURI__.core.invoke('sb_carregar_rascunho', { loja, data: selectedDate });
|
|
|
|
|
} catch(e) { console.warn('sb_carregar_rascunho falhou:', e); }
|
|
|
|
|
}
|
|
|
|
|
// Tenta Supabase primeiro (com id se disponível), senão local
|
|
|
|
|
let rascunho = null;
|
|
|
|
|
if (hasTauri) {
|
|
|
|
|
if (selectedId) {
|
|
|
|
|
try {
|
|
|
|
|
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); }
|
|
|
|
|
}
|
|
|
|
|
if (!rascunho) {
|
|
|
|
|
try {
|
|
|
|
|
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); }
|
|
|
|
|
}
|
|
|
|
|
if (!rascunho) {
|
|
|
|
|
try {
|
|
|
|
|
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); }
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.warn('Tauri não disponível, não foi possível carregar rascunho');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!rascunho) {
|
|
|
|
|
try {
|
|
|
|
|
rascunho = await window.__TAURI__.core.invoke('carregar_rascunho', { loja, data: selectedDate });
|
|
|
|
|
} catch(e) { console.warn('carregar_rascunho local falhou:', e); }
|
|
|
|
|
}
|
|
|
|
|
if (rascunho) {
|
|
|
|
|
console.log('[DEBUG] rascunho carregado com sucesso');
|
|
|
|
|
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.saldo_troco) setVal('sys-troco', fmtNum(rascunho.saldo_troco));
|
|
|
|
|
if (rascunho.saldo_esperado) setVal('f-saldo-esperado', fmtNum(rascunho.saldo_esperado));
|
|
|
|
|
if (rascunho.observacoes) { setVal('f-obs', rascunho.observacoes); estado.observacoes = rascunho.observacoes; }
|
|
|
|
|
if (rascunho.despesas && Array.isArray(rascunho.despesas)) {
|
|
|
|
|
estado.despesas = rascunho.despesas.map(d => ({ desc: d.desc || d.descricao || '', obs: d.obs || '', valor: parseNum(d.valor) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.sangrias && Array.isArray(rascunho.sangrias)) {
|
|
|
|
|
estado.sangrias = rascunho.sangrias.map(s => ({ hora: s.hora || '', retirada: parseNum(s.retirada) || 0, gerente: s.gerente || '' }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.pixcnpj && Array.isArray(rascunho.pixcnpj)) {
|
|
|
|
|
estado.pixcnpj = rascunho.pixcnpj.map(p => ({ nome: p.nome || '', valor: parseNum(p.valor) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.vales && Array.isArray(rascunho.vales)) {
|
|
|
|
|
estado.vales = rascunho.vales.map(v => ({ nome: v.nome || '', obs: v.obs || '', valor: parseNum(v.valor) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.receber && Array.isArray(rascunho.receber)) {
|
|
|
|
|
estado.receber = rascunho.receber.map(r => ({ nome: r.nome || '', valor: parseNum(r.valor) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.cancelamentos && Array.isArray(rascunho.cancelamentos)) {
|
|
|
|
|
estado.cancelamentos = rascunho.cancelamentos.map(c => ({ numero: c.numero || '', valor: parseNum(c.valor) || 0, motivo: c.motivo || '' }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.cartoes) {
|
|
|
|
|
const norm = (arr) => Array.isArray(arr) ? arr.map(v => ({ valor: (typeof v === 'object' && v !== null) ? (parseNum(v.valor) || 0) : (parseNum(v) || 0) })) : [];
|
|
|
|
|
estado.cartoes.credito = norm(rascunho.cartoes.credito);
|
|
|
|
|
estado.cartoes.debito = norm(rascunho.cartoes.debito);
|
|
|
|
|
estado.cartoes.alimentacao = norm(rascunho.cartoes.alimentacao);
|
|
|
|
|
estado.cartoes.pix = norm(rascunho.cartoes.pix);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
console.log('[DEBUG] nenhum rascunho encontrado para esta data');
|
|
|
|
|
estado.despesas = []; estado.sangrias = []; estado.pixcnpj = [];
|
|
|
|
|
estado.vales = []; estado.receber = []; estado.cancelamentos = [];
|
|
|
|
|
estado.cartoes = { credito: [], debito: [], alimentacao: [], pix: [] };
|
|
|
|
|
setVal('sys-troco', ''); setVal('f-saldo-esperado', ''); setVal('f-obs', '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rascunho) {
|
|
|
|
|
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.saldo_troco) setVal('sys-troco', fmtNum(rascunho.saldo_troco));
|
|
|
|
|
if (rascunho.saldo_esperado) setVal('f-saldo-esperado', fmtNum(rascunho.saldo_esperado));
|
|
|
|
|
if (rascunho.observacoes) { setVal('f-obs', rascunho.observacoes); estado.observacoes = rascunho.observacoes; }
|
|
|
|
|
if (rascunho.despesas && Array.isArray(rascunho.despesas)) {
|
|
|
|
|
estado.despesas = rascunho.despesas.map(d => ({ desc: d.desc || d.descricao || '', obs: d.obs || '', valor: parseNum(d.valor) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.sangrias && Array.isArray(rascunho.sangrias)) {
|
|
|
|
|
estado.sangrias = rascunho.sangrias.map(s => ({ hora: s.hora || '', retirada: parseNum(s.retirada) || 0, gerente: s.gerente || '' }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.pixcnpj && Array.isArray(rascunho.pixcnpj)) {
|
|
|
|
|
estado.pixcnpj = rascunho.pixcnpj.map(p => ({ nome: p.nome || '', valor: parseNum(p.valor) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.vales && Array.isArray(rascunho.vales)) {
|
|
|
|
|
estado.vales = rascunho.vales.map(v => ({ nome: v.nome || '', obs: v.obs || '', valor: parseNum(v.valor) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.receber && Array.isArray(rascunho.receber)) {
|
|
|
|
|
estado.receber = rascunho.receber.map(r => ({ nome: r.nome || '', valor: parseNum(r.valor) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.cancelamentos && Array.isArray(rascunho.cancelamentos)) {
|
|
|
|
|
estado.cancelamentos = rascunho.cancelamentos.map(c => ({ numero: c.numero || '', valor: parseNum(c.valor) || 0, motivo: c.motivo || '' }));
|
|
|
|
|
}
|
|
|
|
|
if (rascunho.cartoes) {
|
|
|
|
|
estado.cartoes.credito = (rascunho.cartoes.credito || []).map(v => ({ valor: parseNum(v) || 0 }));
|
|
|
|
|
estado.cartoes.debito = (rascunho.cartoes.debito || []).map(v => ({ valor: parseNum(v) || 0 }));
|
|
|
|
|
estado.cartoes.alimentacao = (rascunho.cartoes.alimentacao || []).map(v => ({ valor: parseNum(v) || 0 }));
|
|
|
|
|
estado.cartoes.pix = (rascunho.cartoes.pix || []).map(v => ({ valor: parseNum(v) || 0 }));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
estado.despesas = []; estado.sangrias = []; estado.pixcnpj = [];
|
|
|
|
|
estado.vales = []; estado.receber = []; estado.cancelamentos = [];
|
|
|
|
|
estado.cartoes = { credito: [], debito: [], alimentacao: [], pix: [] };
|
|
|
|
|
setVal('sys-troco', ''); setVal('f-saldo-esperado', ''); setVal('f-obs', '');
|
|
|
|
|
}
|
|
|
|
|
estado.sync_status = rascunho ? 'loaded' : 'local';
|
|
|
|
|
|
|
|
|
|
// Marcar que este é um rascunho carregado (não novo)
|
|
|
|
|
estado.sync_status = rascunho ? 'loaded' : 'local';
|
|
|
|
|
|
|
|
|
|
PRE_FILL_TABLES.forEach(ensureOneRow);
|
|
|
|
|
Object.keys(TABLES).forEach(renderTable);
|
|
|
|
|
updateTotals();
|
|
|
|
|
scheduleSave();
|
|
|
|
|
});
|
|
|
|
|
PRE_FILL_TABLES.forEach(ensureOneRow);
|
|
|
|
|
Object.keys(TABLES).forEach(renderTable);
|
|
|
|
|
updateTotals();
|
|
|
|
|
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(); });
|
|
|
|
|
|
|
|
|
|