feat: show student name and class in payment notifications
Build and Deploy (Gitea) / build-and-deploy (push) Successful in 2m6s Details

This commit is contained in:
Sidney 2026-07-16 23:53:51 -03:00
parent 79a1e8657e
commit 717fab8581
1 changed files with 63 additions and 7 deletions

View File

@ -1858,8 +1858,64 @@ app.post('/api/webhook_asaas', async (req, res) => {
} }
const asaasPaymentId = payload.payment.id; const asaasPaymentId = payload.payment.id;
const asaasCustomerId = payload.payment.customer;
let updateData = {}; let updateData = {};
const targetName = payload.payment.customerName || 'Cliente'; let targetName = payload.payment.customerName || 'Cliente';
let className = '';
// Buscar o aluno e a turma no banco usando o asaas_payment_id ou asaas_customer_id
try {
let studentRes = await pool.query(
`SELECT a.nome as student_name, t.nome as class_name
FROM alunos a
LEFT JOIN turmas t ON a.turma_id = t.id
WHERE a.id = (
SELECT aluno_id
FROM alunos_cobrancas
WHERE asaas_payment_id = $1
LIMIT 1
)`,
[asaasPaymentId]
);
if (studentRes.rows.length === 0 && asaasCustomerId) {
studentRes = await pool.query(
`SELECT a.nome as student_name, t.nome as class_name
FROM alunos a
LEFT JOIN turmas t ON a.turma_id = t.id
WHERE a.id = (
SELECT aluno_id
FROM alunos_cobrancas
WHERE asaas_customer_id = $1
LIMIT 1
)`,
[asaasCustomerId]
);
}
if (studentRes.rows.length > 0) {
targetName = studentRes.rows[0].student_name || targetName;
className = studentRes.rows[0].class_name || '';
} else {
const nameClean = targetName.trim();
const alunoByName = await pool.query(
`SELECT a.nome as student_name, t.nome as class_name
FROM alunos a
LEFT JOIN turmas t ON a.turma_id = t.id
WHERE LOWER(a.nome) = LOWER($1)
LIMIT 1`,
[nameClean]
);
if (alunoByName.rows.length > 0) {
targetName = alunoByName.rows[0].student_name || targetName;
className = alunoByName.rows[0].class_name || '';
}
}
} catch (err) {
console.error('[Webhook:StudentLookup] Erro ao resolver aluno/turma:', err.message);
}
const studentDisplay = className ? `${targetName} (${className})` : targetName;
switch (payload.event) { switch (payload.event) {
case 'PAYMENT_CREATED': case 'PAYMENT_CREATED':
@ -1898,7 +1954,7 @@ app.post('/api/webhook_asaas', async (req, res) => {
// Alerta no Sino (Admin) // Alerta no Sino (Admin)
createAdminNotification( createAdminNotification(
'✅ Pagamento Confirmado', '✅ Pagamento Confirmado',
`Recebemos R$ ${Number(payload.payment.value).toFixed(2)} de ${targetName}.`, `Recebemos R$ ${Number(payload.payment.value).toFixed(2)} de ${studentDisplay}.`,
{ type: 'finance', status: 'paid', paymentId: asaasPaymentId } { type: 'finance', status: 'paid', paymentId: asaasPaymentId }
); );
@ -1911,7 +1967,7 @@ app.post('/api/webhook_asaas', async (req, res) => {
// Alerta no Sino (Admin) // Alerta no Sino (Admin)
createAdminNotification( createAdminNotification(
'⚠️ Pagamento em Atraso', '⚠️ Pagamento em Atraso',
`A cobrança de ${targetName} no valor de R$ ${Number(payload.payment.value).toFixed(2)} está vencida.`, `A cobrança de ${studentDisplay} no valor de R$ ${Number(payload.payment.value).toFixed(2)} está vencida.`,
{ type: 'finance', status: 'overdue', paymentId: asaasPaymentId } { type: 'finance', status: 'overdue', paymentId: asaasPaymentId }
); );
@ -1928,7 +1984,7 @@ app.post('/api/webhook_asaas', async (req, res) => {
// Alerta no Sino (Admin) // Alerta no Sino (Admin)
createAdminNotification( createAdminNotification(
'📝 Cobrança Alterada', '📝 Cobrança Alterada',
`A cobrança de ${targetName} foi atualizada no Asaas para R$ ${Number(payload.payment.value).toFixed(2)}.`, `A cobrança de ${studentDisplay} foi atualizada no Asaas para R$ ${Number(payload.payment.value).toFixed(2)}.`,
{ type: 'finance', status: 'updated', paymentId: asaasPaymentId } { type: 'finance', status: 'updated', paymentId: asaasPaymentId }
); );
if (payload.event === 'PAYMENT_UPDATED') sendEvolutionMessage(asaasPaymentId, 'PAYMENT_UPDATED'); if (payload.event === 'PAYMENT_UPDATED') sendEvolutionMessage(asaasPaymentId, 'PAYMENT_UPDATED');
@ -1939,7 +1995,7 @@ app.post('/api/webhook_asaas', async (req, res) => {
// Alerta no Sino (Admin) // Alerta no Sino (Admin)
createAdminNotification( createAdminNotification(
'🗑️ Cobrança Removida', '🗑️ Cobrança Removida',
`A cobrança de ${targetName} (R$ ${Number(payload.payment.value).toFixed(2)}) foi excluída no Asaas.`, `A cobrança de ${studentDisplay} (R$ ${Number(payload.payment.value).toFixed(2)}) foi excluída no Asaas.`,
{ type: 'finance', status: 'deleted', paymentId: asaasPaymentId } { type: 'finance', status: 'deleted', paymentId: asaasPaymentId }
); );
const installmentId = payload.payment.installment; const installmentId = payload.payment.installment;
@ -1955,10 +2011,10 @@ app.post('/api/webhook_asaas', async (req, res) => {
await deleteCobranca(asaasPaymentId); await deleteCobranca(asaasPaymentId);
if (sent) { if (sent) {
createAdminNotification('✅ WhatsApp Enviado', `O aluno ${targetName} foi notificado sobre o cancelamento da cobrança.`, { type: 'whatsapp', status: 'success' }); createAdminNotification('✅ WhatsApp Enviado', `O aluno ${studentDisplay} foi notificado sobre o cancelamento da cobrança.`, { type: 'whatsapp', status: 'success' });
addLog('WhatsApp', 'Cancelamento Enviado', { aluno: targetName, asaasPaymentId }); addLog('WhatsApp', 'Cancelamento Enviado', { aluno: targetName, asaasPaymentId });
} else { } else {
createAdminNotification('⚠️ Falha no WhatsApp', `Não foi possível enviar a notificação de cancelamento para ${targetName}.`, { type: 'whatsapp', status: 'error' }); createAdminNotification('⚠️ Falha no WhatsApp', `Não foi possível enviar a notificação de cancelamento para ${studentDisplay}.`, { type: 'whatsapp', status: 'error' });
addLog('WhatsApp', 'Erro no Cancelamento', { aluno: targetName, asaasPaymentId }); addLog('WhatsApp', 'Erro no Cancelamento', { aluno: targetName, asaasPaymentId });
} }