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 valorPago = Number((payment as any).valor_pago || 0);
|
||||||
const discount = Number(payment.discount || 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) {
|
if (isPaid) {
|
||||||
const displayValue = valorPago > 0 ? valorPago : (payment.amount - discount);
|
const displayValue = valorPago > 0 ? valorPago : (payment.amount - discount);
|
||||||
return (
|
return (
|
||||||
|
|
@ -1200,13 +1214,18 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="font-bold text-slate-700 text-sm">
|
<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>
|
</div>
|
||||||
{discount > 0 && (
|
{discount > 0 && (
|
||||||
<div className="text-[10px] text-emerald-600 font-bold">
|
<div className="text-[10px] text-emerald-600 font-bold">
|
||||||
- R$ {discount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
- R$ {discount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{additions > 0 && (
|
||||||
|
<div className="text-[10px] text-red-500 font-bold">
|
||||||
|
+ R$ {additions.toLocaleString('pt-BR', { minimumFractionDigits: 2 })} (Juros/Multa)
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1287,6 +1306,20 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
||||||
const valorPago = Number((payment as any).valor_pago || 0);
|
const valorPago = Number((payment as any).valor_pago || 0);
|
||||||
const discount = Number(payment.discount || 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) {
|
if (isPaid) {
|
||||||
const displayValue = valorPago > 0 ? valorPago : (payment.amount - discount);
|
const displayValue = valorPago > 0 ? valorPago : (payment.amount - discount);
|
||||||
return (
|
return (
|
||||||
|
|
@ -1298,13 +1331,18 @@ const Finance: React.FC<FinanceProps> = ({ data, updateData }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="font-black text-slate-900 text-sm">
|
<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>
|
</div>
|
||||||
{discount > 0 && (
|
{discount > 0 && (
|
||||||
<div className="text-[10px] text-emerald-600 font-bold">
|
<div className="text-[10px] text-emerald-600 font-bold">
|
||||||
- R$ {discount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
- R$ {discount.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
|
||||||
</div>
|
</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)
|
// Se está pago mas o banco ainda não sincronizou o valor_pago (fallback)
|
||||||
if (isPaid) return payment.amount - (payment.discount || 0);
|
if (isPaid) return payment.amount - (payment.discount || 0);
|
||||||
|
|
||||||
// Se está pendente ou atrasado, mostramos o que falta pagar (Líquido esperado)
|
const baseAmount = payment.amount - (payment.discount || 0);
|
||||||
return 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
|
const totalPending = payments
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue