From 3cb3d599b5c8203f00a3403811f91ad347b8af39 Mon Sep 17 00:00:00 2001 From: Sidney Date: Wed, 10 Jun 2026 09:30:40 -0300 Subject: [PATCH] fix: align overdue interest, fine and discount expiration calculations with Asaas rules --- manager/components/Finance.tsx | 58 +++++++++++++++++++++++++-------- portal/server.selfhosted.js | 8 ++--- portal/src/pages/Financeiro.tsx | 26 ++++++++++----- 3 files changed, 66 insertions(+), 26 deletions(-) diff --git a/manager/components/Finance.tsx b/manager/components/Finance.tsx index 3d77b40..df21551 100644 --- a/manager/components/Finance.tsx +++ b/manager/components/Finance.tsx @@ -1188,21 +1188,36 @@ const Finance: React.FC = ({ data, updateData }) => { const isPaid = ['paid', 'pago', 'received', 'confirmed'].includes((payment.status || '').toLowerCase()); const valorPago = Number((payment as any).valor_pago || 0); const discount = Number(payment.discount || 0); - + let additions = 0; const isOverdue = ['overdue', 'atrasado'].includes((payment.status || '').toLowerCase()); + + // Para parcelas vencidas, o desconto perde a validade + const activeDiscount = (!isPaid && isOverdue) ? 0 : discount; + if (!isPaid && isOverdue && payment.dueDate) { const dd = new Date(payment.dueDate + 'T00:00:00'); const tt = new Date(); tt.setHours(0,0,0,0); - if (tt > dd) { - const baseA = payment.amount - discount; + + // Regra de Fins de Semana (Banco/Asaas): Vencimento no sábado ou domingo posterga cobrança de encargos para segunda + let vencimentoEfetivo = new Date(dd); + const diaSemana = dd.getDay(); // 0 = Domingo, 6 = Sábado + if (diaSemana === 6) { + vencimentoEfetivo.setDate(dd.getDate() + 2); + } else if (diaSemana === 0) { + vencimentoEfetivo.setDate(dd.getDate() + 1); + } + + if (tt > vencimentoEfetivo) { + // Vencido perde o desconto. Base de cálculo é o valor bruto original (payment.amount). + const baseA = payment.amount; const dDays = Math.ceil((tt.getTime() - dd.getTime()) / 86400000); const student = data.students.find(s => s.id === payment.studentId); const studentClass = data.classes.find(c => c.id === student?.classId); const course = data.courses.find(c => c.id === studentClass?.courseId); - const pLateFee = Number(payment.lateFee) || Number(course?.finePercentage) || 2; - const pInterest = Number(payment.interest) || Number(course?.interestPercentage) || 1; + const pLateFee = Number(payment.lateFee ?? course?.finePercentage ?? 0); + const pInterest = Number(payment.interest ?? course?.interestPercentage ?? 0); const fineAmt = baseA * (pLateFee / 100); const intAmt = baseA * ((pInterest / 30) / 100) * dDays; @@ -1223,9 +1238,9 @@ const Finance: React.FC = ({ data, updateData }) => {
R$ {(payment.amount + additions).toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
- {discount > 0 && ( + {activeDiscount > 0 && (
- - R$ {discount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })} + - R$ {activeDiscount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
)} {additions > 0 && ( @@ -1258,7 +1273,7 @@ const Finance: React.FC = ({ data, updateData }) => { {(payment.installmentId || payment.asaasInstallmentId) && (