refactor: migração finaça para API local Postgres e fim do Supabase Sync
This commit is contained in:
parent
586f835ae7
commit
d537d31187
|
|
@ -355,6 +355,7 @@ const AttendanceQuery: React.FC<AttendanceQueryProps> = ({ data, updateData, dee
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return classStudents.map(student => {
|
||||||
const studentActualRecords = (data.attendance || []).filter(a => a.studentId === student.id && a.classId === selectedClass.id);
|
const studentActualRecords = (data.attendance || []).filter(a => a.studentId === student.id && a.classId === selectedClass.id);
|
||||||
const classLessonsRaw = (data.lessons || []).filter(l => l.classId === selectedClass.id && l.status !== 'cancelled');
|
const classLessonsRaw = (data.lessons || []).filter(l => l.classId === selectedClass.id && l.status !== 'cancelled');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,21 +178,19 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
||||||
}, [data.payments]);
|
}, [data.payments]);
|
||||||
|
|
||||||
const syncAsaasPayments = async () => {
|
const syncAsaasPayments = async () => {
|
||||||
if (!isSupabaseConfigured() || isSyncing) return;
|
if (isSyncing) return;
|
||||||
|
|
||||||
setIsSyncing(true);
|
setIsSyncing(true);
|
||||||
try {
|
try {
|
||||||
const { data: cloudPayments, error } = await supabase
|
const resp = await fetch('/api/admin/cobrancas');
|
||||||
.from('alunos_cobrancas')
|
if (!resp.ok) throw new Error('API fetch failed');
|
||||||
.select('asaas_payment_id, status, aluno_id, valor, vencimento, data_pagamento, installment, asaas_installment_id, link_boleto');
|
const cloudPayments = await resp.json();
|
||||||
|
|
||||||
if (error) throw error;
|
|
||||||
|
|
||||||
if (cloudPayments && cloudPayments.length > 0) {
|
if (cloudPayments && cloudPayments.length > 0) {
|
||||||
let updatedCount = 0;
|
let updatedCount = 0;
|
||||||
const currentPayments = dataPaymentsRef.current;
|
const currentPayments = dataPaymentsRef.current;
|
||||||
const updatedPayments = currentPayments.map(p => {
|
const updatedPayments = currentPayments.map(p => {
|
||||||
const match = cloudPayments.find(cp => {
|
const match = cloudPayments.find((cp: any) => {
|
||||||
if (p.asaasPaymentId) {
|
if (p.asaasPaymentId) {
|
||||||
return cp.asaas_payment_id === p.asaasPaymentId;
|
return cp.asaas_payment_id === p.asaasPaymentId;
|
||||||
}
|
}
|
||||||
|
|
@ -226,7 +224,6 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
||||||
if (updatedCount > 0) {
|
if (updatedCount > 0) {
|
||||||
updateData({ payments: updatedPayments });
|
updateData({ payments: updatedPayments });
|
||||||
|
|
||||||
// Check if any was updated to overdue
|
|
||||||
const hasOverdue = updatedPayments.some((p, idx) => {
|
const hasOverdue = updatedPayments.some((p, idx) => {
|
||||||
const oldP = currentPayments[idx];
|
const oldP = currentPayments[idx];
|
||||||
return oldP && oldP.status !== 'overdue' && p.status === 'overdue';
|
return oldP && oldP.status !== 'overdue' && p.status === 'overdue';
|
||||||
|
|
@ -243,33 +240,27 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
||||||
if (hasPaid && hasOverdue) message = 'Pagamentos e atrasos atualizados.';
|
if (hasPaid && hasOverdue) message = 'Pagamentos e atrasos atualizados.';
|
||||||
|
|
||||||
showAlert('Sincronização', message, 'success');
|
showAlert('Sincronização', message, 'success');
|
||||||
} else {
|
|
||||||
showAlert('Sincronização', 'Nenhum novo pagamento confirmado encontrado.', 'info');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao sincronizar pagamentos:', error);
|
console.error('Erro ao sincronizar pagamentos:', error);
|
||||||
showAlert('Erro', 'Falha ao sincronizar com o Asaas.', 'error');
|
// Suppress alert so it doesn't pop up randomly to the user if the server restarts temporarily
|
||||||
} finally {
|
} finally {
|
||||||
setIsSyncing(false);
|
setIsSyncing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchSupabaseRecords = async () => {
|
const fetchSupabaseRecords = async () => {
|
||||||
if (!isSupabaseConfigured()) return;
|
|
||||||
setIsFetchingSupabase(true);
|
setIsFetchingSupabase(true);
|
||||||
setSelectedSupabaseRows([]); // Clear selection on refresh
|
setSelectedSupabaseRows([]);
|
||||||
try {
|
try {
|
||||||
const { data: records, error } = await supabase
|
const resp = await fetch('/api/admin/cobrancas');
|
||||||
.from('alunos_cobrancas')
|
if (!resp.ok) throw new Error('API fetch failed');
|
||||||
.select('*')
|
const records = await resp.json();
|
||||||
.order('vencimento', { ascending: false });
|
|
||||||
|
|
||||||
if (error) throw error;
|
|
||||||
setSupabaseRecords(records || []);
|
setSupabaseRecords(records || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching Supabase records:', error);
|
console.error('Error fetching billing records from Postgres:', error);
|
||||||
showAlert('Erro', 'Falha ao buscar dados do Supabase.', 'error');
|
showAlert('Erro', 'Falha ao buscar dados do Banco de Dados.', 'error');
|
||||||
} finally {
|
} finally {
|
||||||
setIsFetchingSupabase(false);
|
setIsFetchingSupabase(false);
|
||||||
}
|
}
|
||||||
|
|
@ -277,34 +268,30 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
||||||
|
|
||||||
const deleteSupabaseRecord = async (id: string) => {
|
const deleteSupabaseRecord = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
const { error } = await supabase
|
const resp = await fetch(`/api/admin/cobrancas/${id}`, { method: 'DELETE' });
|
||||||
.from('alunos_cobrancas')
|
if (!resp.ok) throw new Error('Delete failed');
|
||||||
.delete()
|
|
||||||
.eq('asaas_payment_id', id);
|
|
||||||
|
|
||||||
if (error) throw error;
|
|
||||||
|
|
||||||
setSupabaseRecords(prev => prev.filter(r => r.asaas_payment_id !== id));
|
setSupabaseRecords(prev => prev.filter(r => r.asaas_payment_id !== id));
|
||||||
showAlert('Sucesso', 'Registro removido do Supabase.', 'success');
|
showAlert('Sucesso', 'Registro removido do Banco.', 'success');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting Supabase record:', error);
|
console.error('Error deleting record:', error);
|
||||||
showAlert('Erro', 'Falha ao excluir do Supabase.', 'error');
|
showAlert('Erro', 'Falha ao excluir do Banco de Dados.', 'error');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteSupabaseRecordsBulk = async () => {
|
const deleteSupabaseRecordsBulk = async () => {
|
||||||
if (selectedSupabaseRows.length === 0) return;
|
if (selectedSupabaseRows.length === 0) return;
|
||||||
|
|
||||||
if(!confirm(`Tem certeza que deseja excluir ${selectedSupabaseRows.length} registros diretamente do Supabase?`)) return;
|
if(!confirm(`Tem certeza que deseja excluir ${selectedSupabaseRows.length} registros diretamente do Banco de Dados?`)) return;
|
||||||
|
|
||||||
setIsFetchingSupabase(true);
|
setIsFetchingSupabase(true);
|
||||||
try {
|
try {
|
||||||
const { error } = await supabase
|
const resp = await fetch('/api/admin/cobrancas', {
|
||||||
.from('alunos_cobrancas')
|
method: 'DELETE',
|
||||||
.delete()
|
headers: { 'Content-Type': 'application/json' },
|
||||||
.in('asaas_payment_id', selectedSupabaseRows);
|
body: JSON.stringify({ ids: selectedSupabaseRows })
|
||||||
|
});
|
||||||
if (error) throw error;
|
if (!resp.ok) throw new Error('Bulk delete failed');
|
||||||
|
|
||||||
setSupabaseRecords(prev => prev.filter(r => !selectedSupabaseRows.includes(r.asaas_payment_id)));
|
setSupabaseRecords(prev => prev.filter(r => !selectedSupabaseRows.includes(r.asaas_payment_id)));
|
||||||
setSelectedSupabaseRows([]);
|
setSelectedSupabaseRows([]);
|
||||||
|
|
|
||||||
|
|
@ -473,6 +473,36 @@ app.post('/api/webhook_asaas', async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Admin Raw Cobrancas para a Aba Financeiro
|
||||||
|
app.get('/api/admin/cobrancas', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await pool.query('SELECT * FROM alunos_cobrancas ORDER BY vencimento DESC');
|
||||||
|
res.json(result.rows);
|
||||||
|
} catch(e) {
|
||||||
|
res.status(500).json({error: e.message});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.delete('/api/admin/cobrancas', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { ids } = req.body;
|
||||||
|
if (!Array.isArray(ids)) return res.status(400).end();
|
||||||
|
await pool.query('DELETE FROM alunos_cobrancas WHERE asaas_payment_id = ANY($1)', [ids]);
|
||||||
|
res.json({ success: true });
|
||||||
|
} catch(e) {
|
||||||
|
res.status(500).json({error: e.message});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.delete('/api/admin/cobrancas/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
await pool.query('DELETE FROM alunos_cobrancas WHERE asaas_payment_id = $1', [req.params.id]);
|
||||||
|
res.json({ success: true });
|
||||||
|
} catch(e) {
|
||||||
|
res.status(500).json({error: e.message});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Webhook Evolution
|
// Webhook Evolution
|
||||||
app.post('/api/webhooks/evolution', (req, res) => {
|
app.post('/api/webhooks/evolution', (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue