Mise en place de la notion de perte définitive, ainsi que la révision avec statut Polongation

This commit is contained in:
ocroguennec committed 2026-08-22 16:27:41 +02:00
1 parent 4ad6ea79e8
commit 8e1b82d161
21 files changed
+1069 -184

No files matched your search

+16 -2
View File
@@ -704,7 +704,9 @@ router.get('/interets-par-plateforme', (req, res) => {
i.date_souscription,
i.date_cible,
i.statut,
(SELECT MAX(r.date_remb) FROM remboursements r WHERE r.investissement_id = i.id) AS last_remb_date
(SELECT MAX(r.date_remb) FROM remboursements r WHERE r.investissement_id = i.id) AS last_remb_date,
(SELECT ip.date_effet FROM investissement_pertes ip WHERE ip.investissement_id = i.id ORDER BY ip.id DESC LIMIT 1) AS perte_date_effet,
(SELECT ip.montant_perte FROM investissement_pertes ip WHERE ip.investissement_id = i.id ORDER BY ip.id DESC LIMIT 1) AS perte_montant
FROM investissements i
WHERE ${invWhere.replace('investisseur_id', 'i.investisseur_id')}
`).all(...invParams);
@@ -792,10 +794,22 @@ router.get('/interets-par-plateforme', (req, res) => {
.reduce((s, r) => s + r.montant, 0);
const capitalRestant = Math.max(0, inv.montant_investi + reinvestsCumul - capitalRembCumul - capitalSimulCumul);
const actif = ['en_cours', 'en_retard', 'procedure'].includes(inv.statut);
// 'prolongation' compte normalement comme capital encours (comme en_retard/procedure
// dont il découle après renégociation) mais n'entre pas dans en_defaut : il est sorti
// temporairement du scope "à risque" tant que la nouvelle échéance n'est pas dépassée.
const actif = ['en_cours', 'en_retard', 'procedure', 'prolongation'].includes(inv.statut);
if (actif) {
capital += capitalRestant;
if (['en_retard', 'procedure'].includes(inv.statut)) enDefaut += capitalRestant;
} else if (inv.statut === 'perte_definitive' && inv.perte_date_effet) {
// Avant la déclaration de perte (fidélité historique) : capital compté normalement,
// comme si le dossier était encore en_retard/procedure ce mois-là. À partir du mois
// de déclaration : capital réduit du montant acté en perte (perte partielle possible).
if (lastDay < inv.perte_date_effet) {
capital += capitalRestant;
} else {
capital += Math.max(0, capitalRestant - (inv.perte_montant || 0));
}
} else {
// Remboursé/clôturé : était-il encore actif ce mois-ci ?
// Priorité : date_cible → dernier remboursement réel → exclure