From 66139bff0d8c7f48214687640e58e723efcc72ee Mon Sep 17 00:00:00 2001 From: Sidney Date: Thu, 14 May 2026 16:09:04 -0300 Subject: [PATCH] Fix: implement hybrid finance logic (JSON + SQL) to ensure paid installments visibility --- portal/server.selfhosted.js | 45 +++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/portal/server.selfhosted.js b/portal/server.selfhosted.js index 4a71308..db6a796 100644 --- a/portal/server.selfhosted.js +++ b/portal/server.selfhosted.js @@ -215,13 +215,54 @@ app.get('/api/portal/me', authMiddleware, async (req, res) => { } }); -// GET /api/portal/financeiro +// GET /api/portal/financeiro (Mesclagem JSON + PostgreSQL para status atualizado) app.get('/api/portal/financeiro', authMiddleware, async (req, res) => { try { const schoolData = await getSchoolData(); const payments = (schoolData.payments || []).filter((p) => p.studentId === req.user.studentId); - res.json({ payments }); + + // Buscar status atualizado do PostgreSQL (fonte da verdade para pagamentos) + let dbBoletos = []; + try { + const { rows } = await pool.query( + 'SELECT asaas_payment_id, status, valor, data_pagamento, transaction_receipt_url FROM alunos_cobrancas WHERE aluno_id = $1', + [req.user.studentId] + ); + dbBoletos = rows || []; + } catch (dbErr) { + console.error('Financeiro: fallback to JSON only -', dbErr.message); + } + + // Mesclar: se o PostgreSQL tem um status mais atualizado, ele prevalece + const statusMap = { + 'pago': 'paid', 'paid': 'paid', 'received': 'paid', 'confirmed': 'paid', + 'atrasado': 'overdue', 'overdue': 'overdue', 'vencido': 'overdue', + 'pendente': 'pending', 'pending': 'pending', + 'cancelado': 'cancelled', 'cancelled': 'cancelled' + }; + + const enrichedPayments = payments.map(p => { + const asaasId = p.asaasPaymentId || p.asaas_payment_id; + if (!asaasId) return p; + + const dbRecord = dbBoletos.find(b => b.asaas_payment_id === asaasId); + if (!dbRecord) return p; + + const dbStatus = (dbRecord.status || '').toLowerCase().trim(); + const normalizedStatus = statusMap[dbStatus] || p.status; + + return { + ...p, + status: normalizedStatus, + amount: Number(dbRecord.valor) || p.amount, + paidDate: dbRecord.data_pagamento || p.paidDate, + transactionReceiptUrl: dbRecord.transaction_receipt_url || p.transactionReceiptUrl + }; + }); + + res.json({ payments: enrichedPayments }); } catch (err) { + console.error('Financeiro error:', err); res.status(500).json({ error: 'Erro interno' }); } });