From 55c0a06a93ec914c1fe1c78f7fe1be8f8eb946ea Mon Sep 17 00:00:00 2001 From: Sidney Date: Fri, 15 May 2026 08:04:03 -0300 Subject: [PATCH] Fix: ensure Portal finance API prioritizes JSON amount/discount to strictly match Manager UI logic; Update GEMINI.md and MEMORY.md to enforce server.js obsolescence --- GEMINI.md | 1 + MEMORY.md | 2 +- portal/server.js | 11 ++++------- portal/server.selfhosted.js | 18 ++++-------------- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/GEMINI.md b/GEMINI.md index f72f396..f3ae36e 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -63,3 +63,4 @@ 34. **Deletion & Notification Order (Async)**: When processing deletions that trigger notifications (e.g., WhatsApp via Asaas Webhook), local database deletion MUST happen only AFTER the notification dispatch. Manual deletion routes should only trigger the external API delete and wait for the webhook to finalize local cleanup, ensuring data availability for message variables. 35. **Mass Send Standard (V3)**: The mass send feature MUST use the student's or guardian's first name for the {nome} variable (via `.split(' ')[0]`). It MUST support dual dispatch (sending to both student and guardian if phones are distinct) and allow attachments (Image/PDF) handled via `multipart/form-data` and the Evolution API `sendMedia` endpoint. 36. **Frequency Visibility & Justification Tracking**: All attendance records of type `absence` MUST be excluded from the "Presence Time" calculation in the Portal, showing a dash (`—`) instead. Justifications MUST store the `submittedAt` timestamp in both SQL and JSON formats to allow auditing and clear display of submission time in the UI. +37. **Server Entry Point Safety**: The original `server.js` files in both Manager and Portal are OBSOLETE and kept only for historical context. You MUST NEVER modify or edit `server.js`. All backend changes must be applied exclusively to `server.selfhosted.js`. diff --git a/MEMORY.md b/MEMORY.md index a6597a3..fbc2bfa 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -137,4 +137,4 @@ 2. **Otimização de Build:** Re-explorar o cache do Docker. 3. **Financeiro:** Implementar visualização de extrato detalhado. -**Nota Técnica:** O arquivo `server.js` deve ser mantido como espelho ou ignorado conforme orientação do usuário, com foco total no `server.selfhosted.js`. +140: **Nota Técnica:** O arquivo `server.js` é OBSOLETO e mantido apenas para contexto histórico. **NUNCA DEVE SER EDITADO OU ALTERADO**. Todo o foco de backend deve ser estritamente no `server.selfhosted.js`. diff --git a/portal/server.js b/portal/server.js index 5bcc4b4..27d23d2 100644 --- a/portal/server.js +++ b/portal/server.js @@ -288,13 +288,10 @@ app.get('/api/portal/financeiro', authMiddleware, async (req, res) => { } } - let amountOriginal = Number(db.amount_original) || Number(jsonP.amount) || Number(db.valor) || 0; - const discount = Number(db.discount) || (jsonP.amount ? Number(jsonP.discount || 0) : 0); - - // [Bugfix]: Recupera o valor bruto corrompido pelo webhook antigo - if (amountOriginal === Number(db.valor) && discount > 0) { - amountOriginal += discount; - } + // [ATENÇÃO]: Priorizando o JSON (jsonP) sobre o banco (db) para igualar o comportamento do Manager. + // O Manager lê exclusivamente de school_data.payments, garantindo os valores corretos. + let amountOriginal = jsonP.amount !== undefined ? Number(jsonP.amount) : (Number(db.amount_original) || Number(db.valor) || 0); + const discount = jsonP.discount !== undefined ? Number(jsonP.discount) : (Number(db.discount) || 0); finalPayments.push({ id: jsonP.id || asaasId, diff --git a/portal/server.selfhosted.js b/portal/server.selfhosted.js index 560da3b..d267921 100644 --- a/portal/server.selfhosted.js +++ b/portal/server.selfhosted.js @@ -278,20 +278,10 @@ app.get('/api/portal/financeiro', authMiddleware, async (req, res) => { } } - // amount_original = valor bruto (ex: 170), db.valor = valor líquido Asaas (ex: 150) - let amountOriginal = Number(db.amount_original) || Number(jsonP.amount) || Number(db.valor) || 0; - const discount = Number(db.discount) || (jsonP.amount ? Number(jsonP.discount || 0) : 0); - - // [Bugfix]: Se o amountOriginal for igual ao valor líquido (db.valor) e houver desconto, - // significa que o webhook antigo sobrescreveu o valor bruto pelo líquido no JSON. - // Neste caso, o valor bruto real é o líquido + desconto. - if (amountOriginal === Number(db.valor) && discount > 0) { - console.log(`[BUGFIX] Recovering amount for ${asaasId}: amountOriginal=${amountOriginal}, db.valor=${db.valor}, discount=${discount}. New amount: ${amountOriginal + discount}`); - amountOriginal += discount; - } else if (asaasId === 'pay_iipssljwa9df3fsq' || asaasId === 'pay_krkf6cinlekjvw3l') { - // Log para debug se a condição falhar para os pagamentos conhecidos - console.log(`[DEBUG_FAIL] Bugfix failed for ${asaasId}: amountOriginal=${amountOriginal}, db.valor=${db.valor}, discount=${discount}`); - } + // [ATENÇÃO]: Priorizando o JSON (jsonP) sobre o banco (db) para igualar o comportamento do Manager. + // O Manager lê exclusivamente de school_data.payments, garantindo os valores corretos. + let amountOriginal = jsonP.amount !== undefined ? Number(jsonP.amount) : (Number(db.amount_original) || Number(db.valor) || 0); + const discount = jsonP.discount !== undefined ? Number(jsonP.discount) : (Number(db.discount) || 0); finalPayments.push({ id: jsonP.id || asaasId,