feat(financeiro): adiciona calculo dinamico local de juros e multas para exibir em tempo real
Build and Deploy (Gitea) / build-and-deploy (push) Successful in 2m11s
Details
Build and Deploy (Gitea) / build-and-deploy (push) Successful in 2m11s
Details
This commit is contained in:
parent
83720b0258
commit
7baafee2b1
|
|
@ -1189,6 +1189,20 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
|||
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());
|
||||
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;
|
||||
const dDays = Math.ceil((tt.getTime() - dd.getTime()) / 86400000);
|
||||
const fineAmt = baseA * ((Number(payment.lateFee) || 2) / 100);
|
||||
const intAmt = baseA * (((Number(payment.interest) || 1) / 30) / 100) * dDays;
|
||||
additions = fineAmt + intAmt;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPaid) {
|
||||
const displayValue = valorPago > 0 ? valorPago : (payment.amount - discount);
|
||||
return (
|
||||
|
|
@ -1200,13 +1214,18 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
|||
return (
|
||||
<>
|
||||
<div className="font-bold text-slate-700 text-sm">
|
||||
R$ {payment.amount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
||||
R$ {(payment.amount + additions).toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
||||
</div>
|
||||
{discount > 0 && (
|
||||
<div className="text-[10px] text-emerald-600 font-bold">
|
||||
- R$ {discount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
||||
</div>
|
||||
)}
|
||||
{additions > 0 && (
|
||||
<div className="text-[10px] text-red-500 font-bold">
|
||||
+ R$ {additions.toLocaleString('pt-BR', { minimumFractionDigits: 2 })} (Juros/Multa)
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -1286,6 +1305,20 @@ const Finance: React.FC<FinanceProps> = ({ 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());
|
||||
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;
|
||||
const dDays = Math.ceil((tt.getTime() - dd.getTime()) / 86400000);
|
||||
const fineAmt = baseA * ((Number(payment.lateFee) || 2) / 100);
|
||||
const intAmt = baseA * (((Number(payment.interest) || 1) / 30) / 100) * dDays;
|
||||
additions = fineAmt + intAmt;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPaid) {
|
||||
const displayValue = valorPago > 0 ? valorPago : (payment.amount - discount);
|
||||
|
|
@ -1298,13 +1331,18 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
|||
return (
|
||||
<>
|
||||
<div className="font-black text-slate-900 text-sm">
|
||||
R$ {payment.amount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
||||
R$ {(payment.amount + additions).toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
||||
</div>
|
||||
{discount > 0 && (
|
||||
<div className="text-[10px] text-emerald-600 font-bold">
|
||||
- R$ {discount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
||||
</div>
|
||||
)}
|
||||
{additions > 0 && (
|
||||
<div className="text-[10px] text-red-500 font-bold mt-0.5">
|
||||
+ R$ {additions.toLocaleString('pt-BR', { minimumFractionDigits: 2 })} (Multa/Juros)
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,8 +163,22 @@ export default function Financeiro() {
|
|||
// Se está pago mas o banco ainda não sincronizou o valor_pago (fallback)
|
||||
if (isPaid) return payment.amount - (payment.discount || 0);
|
||||
|
||||
// Se está pendente ou atrasado, mostramos o que falta pagar (Líquido esperado)
|
||||
return payment.amount - (payment.discount || 0);
|
||||
const baseAmount = payment.amount - (payment.discount || 0);
|
||||
|
||||
// Simulação Matemática de Atraso
|
||||
if (status === 'overdue' && 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 dDays = Math.ceil((tt.getTime() - dd.getTime()) / 86400000);
|
||||
const fineAmt = baseAmount * ((Number(payment.lateFee) || 2) / 100);
|
||||
const intAmt = baseAmount * (((Number(payment.interest) || 1) / 30) / 100) * dDays;
|
||||
return baseAmount + fineAmt + intAmt;
|
||||
}
|
||||
}
|
||||
|
||||
// Se está pendente ou atrasado sem juros aplicáveis, mostramos o líquido esperado
|
||||
return baseAmount;
|
||||
};
|
||||
|
||||
const totalPending = payments
|
||||
|
|
|
|||
Loading…
Reference in New Issue