Fix: double discount, dynamic column header, receipt link, remaining installments card
This commit is contained in:
parent
c2efa1729f
commit
00351031d1
|
|
@ -645,12 +645,12 @@ async function sendEvolutionMessage(asaasPaymentId, eventType, fallbackValorArg
|
|||
const pdfArrayBuffer = doc.output('arraybuffer');
|
||||
const pdfBuffer = Buffer.from(pdfArrayBuffer);
|
||||
|
||||
// Upload para o MinIO (Pasta recibos)
|
||||
// Upload para o MinIO (Pasta recibos) — apenas para envio via WhatsApp
|
||||
const minioFileName = `recibos/recibo_${asaasPaymentId}.pdf`;
|
||||
const minioUrl = await uploadReceiptToStorage(minioFileName, pdfBuffer);
|
||||
|
||||
// Atualiza o link no banco de dados para apontar para o seu MinIO
|
||||
await updateCobranca(asaasPaymentId, { transaction_receipt_url: minioUrl });
|
||||
// NÃO sobrescrever transaction_receipt_url — o link do Asaas (público) é salvo pelo webhook
|
||||
// O MinIO é usado apenas para o envio do PDF via WhatsApp
|
||||
|
||||
base64Pdf = pdfBuffer.toString('base64');
|
||||
fileName = `Recibo-${targetName.replace(/\s+/g, '')}.pdf`;
|
||||
|
|
|
|||
|
|
@ -281,8 +281,8 @@ app.get('/api/portal/financeiro', authMiddleware, async (req, res) => {
|
|||
studentId: req.user.studentId,
|
||||
asaasPaymentId: asaasId,
|
||||
asaasPaymentUrl: jsonP.asaasPaymentUrl || null,
|
||||
amount: Number(db.valor) || jsonP.amount || 0,
|
||||
discount: jsonP.discount || 0,
|
||||
amount: jsonP.amount || Number(db.valor) || 0,
|
||||
discount: jsonP.amount ? (jsonP.discount || 0) : 0,
|
||||
dueDate: db.vencimento || jsonP.dueDate,
|
||||
status: normalizedStatus,
|
||||
paidDate: db.data_pagamento || jsonP.paidDate || null,
|
||||
|
|
|
|||
|
|
@ -285,8 +285,10 @@ app.get('/api/portal/financeiro', authMiddleware, async (req, res) => {
|
|||
studentId: req.user.studentId,
|
||||
asaasPaymentId: asaasId,
|
||||
asaasPaymentUrl: jsonP.asaasPaymentUrl || null,
|
||||
amount: Number(db.valor) || jsonP.amount || 0,
|
||||
discount: jsonP.discount || 0,
|
||||
// jsonP.amount = valor BRUTO (ex: 170), db.valor = valor LÍQUIDO do Asaas (ex: 150)
|
||||
// Se o JSON tem o bruto, usa ele + desconto separado. Se não, usa SQL (já líquido) sem desconto.
|
||||
amount: jsonP.amount || Number(db.valor) || 0,
|
||||
discount: jsonP.amount ? (jsonP.discount || 0) : 0,
|
||||
dueDate: db.vencimento || jsonP.dueDate,
|
||||
status: normalizedStatus,
|
||||
paidDate: db.data_pagamento || jsonP.paidDate || null,
|
||||
|
|
|
|||
|
|
@ -96,9 +96,11 @@ export default function Financeiro() {
|
|||
};
|
||||
|
||||
const getReceiptLink = (payment: Payment): string | null => {
|
||||
if ((payment as any).transactionReceiptUrl) return (payment as any).transactionReceiptUrl;
|
||||
if ((payment as any).transaction_receipt_url) return (payment as any).transaction_receipt_url;
|
||||
// 1. Verificar campo direto no pagamento (vem do SQL ou JSON)
|
||||
const directUrl = (payment as any).transactionReceiptUrl || (payment as any).transaction_receipt_url;
|
||||
if (directUrl && typeof directUrl === 'string' && directUrl.startsWith('http')) return directUrl;
|
||||
|
||||
// 2. Cross-reference com boletos (tabela SQL separada)
|
||||
const asaasId = payment.asaasPaymentId || (payment as any).asaas_payment_id;
|
||||
|
||||
let boleto = null;
|
||||
|
|
@ -113,8 +115,10 @@ export default function Financeiro() {
|
|||
);
|
||||
}
|
||||
|
||||
if (!boleto) return null;
|
||||
return (boleto as any).link_recibo || (boleto as any).transaction_receipt_url || null;
|
||||
const boletoUrl = (boleto as any)?.transaction_receipt_url || (boleto as any)?.link_recibo;
|
||||
if (boletoUrl && typeof boletoUrl === 'string' && boletoUrl.startsWith('http')) return boletoUrl;
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const handleOpenReceipt = (payment: Payment) => {
|
||||
|
|
@ -122,6 +126,7 @@ export default function Financeiro() {
|
|||
if (receiptUrl) {
|
||||
window.open(receiptUrl, '_blank', 'noopener,noreferrer');
|
||||
} else {
|
||||
// Fallback: abrir modal local com dados do pagamento
|
||||
setReceiptPayment(payment);
|
||||
}
|
||||
};
|
||||
|
|
@ -244,10 +249,10 @@ export default function Financeiro() {
|
|||
</div>
|
||||
<div className="glass-card" style={{ padding: '1.25rem' }}>
|
||||
<p style={{ fontSize: '0.75rem', color: 'var(--color-text-secondary)', fontWeight: 500, marginBottom: '0.5rem' }}>
|
||||
TOTAL DE PARCELAS
|
||||
PARCELAS RESTANTES
|
||||
</p>
|
||||
<p style={{ fontSize: '1.375rem', fontWeight: 700 }}>
|
||||
{payments.length}
|
||||
<p style={{ fontSize: '1.375rem', fontWeight: 700, color: payments.filter(p => isPending(p)).length > 0 ? 'var(--color-warning)' : 'var(--color-success)' }}>
|
||||
{payments.filter(p => isPending(p)).length}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -307,7 +312,7 @@ export default function Financeiro() {
|
|||
<th>Vencimento</th>
|
||||
<th>Valor</th>
|
||||
<th>Desconto</th>
|
||||
<th>A Pagar</th>
|
||||
<th>{filter === 'paid' ? 'Pago' : 'A Pagar'}</th>
|
||||
<th>Status</th>
|
||||
<th>Ação</th>
|
||||
</tr>
|
||||
|
|
|
|||
Loading…
Reference in New Issue