From bd972deda316aefc9b27541924dd8815d444d402 Mon Sep 17 00:00:00 2001 From: Sidney Date: Thu, 21 May 2026 09:22:43 -0300 Subject: [PATCH] fix(finance): fix deletion notification order race condition by delegating local deletion to webhook (Rule 34) --- MEMORY.md | 1 + manager/server.selfhosted.js | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MEMORY.md b/MEMORY.md index cb58eeb..26b129e 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -49,6 +49,7 @@ - [x] **Migração do Módulo Financeiro para SQL (Fase 1 e 2):** Aba financeiro do Manager migrada para ler diretamente a tabela PostgreSQL `alunos_cobrancas` (via `currentPayments`). - [x] **Parser Global de NUMERIC (Postgres):** Configurado o driver `pg` nos servidores do Manager e do Portal para converter automaticamente `NUMERIC`/`DECIMAL` (OID 1700) para `Number`, cumprindo as regras 19 e 32 do `GEMINI.md`. - [x] **Resolução de Condição de Corrida:** Implementado `await` no update duplo de cobranças do SQL na edição de cobranças do Manager (`Finance.tsx`), assegurando consistência na re-busca de dados. +- [x] **Ordem de Exclusão e Notificação (Regra 34):** Removida a exclusão local imediata no endpoint `/api/excluir_cobranca`. A remoção local é delegada ao webhook do Asaas, permitindo que a mensagem de WhatsApp acesse os dados necessários antes da deleção. - [x] **Validação de Build e Git Push:** Confirmada compilação bem-sucedida do frontend/backend e efetuado o push para a branch remota `main` sob autorização do usuário. ## 📋 Próximos Passos diff --git a/manager/server.selfhosted.js b/manager/server.selfhosted.js index a6d0c2c..28ea0ae 100644 --- a/manager/server.selfhosted.js +++ b/manager/server.selfhosted.js @@ -1247,19 +1247,18 @@ app.post('/api/excluir_cobranca', async (req, res) => { if (!isSinglePayment) { const asaasTargetId = formatInstallmentId(id); const resp = await fetch(`${ASAAS_BASE_URL}/v3/installments/${asaasTargetId}`, { method: 'DELETE', headers: { 'access_token': process.env.ASAAS_API_KEY } }); - if (resp.ok) { - addLog('Asaas', 'Exclusão Parcelamento OK', { id: asaasTargetId }); - } - await pool.query('DELETE FROM alunos_cobrancas WHERE asaas_installment_id = $1', [asaasTargetId]); + if (!resp.ok) { const e = await resp.json().catch(() => ({})); return res.status(400).json({ error: e.errors?.[0]?.description || 'Falha Asaas' }); } + addLog('Asaas', 'Exclusão Parcelamento OK', { id: asaasTargetId }); + // Deletar localmente apenas via webhook para não apagar antes de enviar o WhatsApp (Regra 34) } else { const resp = await fetch(`${ASAAS_BASE_URL}/v3/payments/${id}`, { method: 'DELETE', headers: { 'access_token': process.env.ASAAS_API_KEY } }); if (!resp.ok) { const e = await resp.json().catch(() => ({})); return res.status(400).json({ error: e.errors?.[0]?.description || 'Falha Asaas' }); } addLog('Asaas', 'Exclusão Cobrança OK', { id }); - await pool.query('DELETE FROM alunos_cobrancas WHERE asaas_payment_id = $1', [id]); + // Deletar localmente apenas via webhook para não apagar antes de enviar o WhatsApp (Regra 34) } - return res.status(200).json({ message: 'Excluído no Asaas e na base local' }); + return res.status(200).json({ message: 'Exclusão solicitada ao Asaas. A remoção local ocorrerá via Webhook.' }); } catch (error) { console.error('[Exclusão] Erro:', error); return res.status(500).json({ error: 'Erro interno.' });