From f75b5af4ef13de6b6b8b00af7616f2778607eeb1 Mon Sep 17 00:00:00 2001 From: Sidney Date: Fri, 8 May 2026 10:07:33 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20sincroniza=C3=A7=C3=A3o=20financeira=20?= =?UTF-8?q?autom=C3=A1tica=20JSON=20->=20SQL=20para=20automa=C3=A7=C3=A3o?= =?UTF-8?q?=20de=20mensagens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manager/scratch/inspect_json.js | 23 +++++++++++++++++ manager/services/database.js | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 manager/scratch/inspect_json.js diff --git a/manager/scratch/inspect_json.js b/manager/scratch/inspect_json.js new file mode 100644 index 0000000..c7a66ce --- /dev/null +++ b/manager/scratch/inspect_json.js @@ -0,0 +1,23 @@ +import pg from 'pg'; +const DATABASE_URL = 'postgresql://edumanager:EduManager2026!Seguro@localhost:5432/edumanager'; +const pool = new pg.Pool({ connectionString: DATABASE_URL }); + +async function checkKeys() { + const { rows } = await pool.query('SELECT data FROM school_data WHERE id = 1'); + if (rows[0]) { + const data = rows[0].data; + console.log('Keys in school_data.json:', Object.keys(data)); + if (data.students && Array.isArray(data.students)) { + const studentWithPayments = data.students.find(s => s.payments && s.payments.length > 0); + if (studentWithPayments) { + console.log('Student found with payments. Student ID:', studentWithPayments.id); + console.log('First payment keys:', Object.keys(studentWithPayments.payments[0])); + console.log('First payment sample:', studentWithPayments.payments[0]); + } else { + console.log('No students found with payments array.'); + } + } + } + await pool.end(); +} +checkKeys(); diff --git a/manager/services/database.js b/manager/services/database.js index 4742c1b..f6541f1 100644 --- a/manager/services/database.js +++ b/manager/services/database.js @@ -277,6 +277,20 @@ export async function initNotasTable() { console.log('[PostgreSQL] ℹ️ Submissoes fkey já removidas ou tabela não existe.'); } + // Garantir unicidade do asaas_payment_id para permitir ON CONFLICT + try { + await pool.query(` + DO $$ + BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'unique_asaas_payment_id') THEN + ALTER TABLE alunos_cobrancas ADD CONSTRAINT unique_asaas_payment_id UNIQUE (asaas_payment_id); + END IF; + END $$; + `); + } catch (err) { + console.warn('[PostgreSQL] Erro ao garantir UNIQUE em alunos_cobrancas:', err.message); + } + await pool.query(` CREATE TABLE IF NOT EXISTS notas_boletim ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), @@ -526,6 +540,38 @@ export async function syncJsonToRelationalTables() { } } + // 8. Sincronizar Cobranças (Financeiro) + if (data.payments && Array.isArray(data.payments)) { + for (const p of data.payments) { + if (!p.asaasPaymentId || !p.studentId) continue; + + await client.query( + `INSERT INTO alunos_cobrancas ( + aluno_id, asaas_payment_id, asaas_installment_id, installment, + valor, vencimento, link_boleto, status + ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (asaas_payment_id) DO UPDATE SET + aluno_id = EXCLUDED.aluno_id, + asaas_installment_id = EXCLUDED.asaas_installment_id, + installment = EXCLUDED.installment, + valor = EXCLUDED.valor, + vencimento = EXCLUDED.vencimento, + link_boleto = EXCLUDED.link_boleto, + status = EXCLUDED.status`, + [ + p.studentId, + p.asaasPaymentId, + p.asaasInstallmentId || p.installmentId || null, + p.installment || null, + p.amount || 0, + p.dueDate, + p.bankSlipUrl || p.link || null, + (p.status || 'PENDENTE').toUpperCase() + ] + ).catch(err => console.warn(`[Sync:Finance] Erro no boleto ${p.asaasPaymentId}:`, err.message)); + } + } + await client.query('COMMIT'); console.log('[Sincronização] 🚀 Espelhamento TOTAL concluído com sucesso!'); } catch (err) {