---
name: project_invchart_capital_encours
description: "Formule unifiée capital investi (Dashboard + Investissements) : montant_investi + reinvests(≤date) − capital_remboursé(≤date)"
metadata: 
  node_type: memory
  type: project
  originSessionId: 09de8d8d-fa6d-4d2f-93bf-3920d2b93158
---

## Formule canonique — capital restant engagé à une date D

```
capital_restant(D) = montant_investi
                   + SUM(reinvestissements où date_reinvestissement ≤ D)
                   − SUM(remboursements.capital où date_remb ≤ D AND type='normal')
```

Cette formule doit être appliquée identiquement sur toutes les pages et tous les composants.

**Why:** Des divergences existaient car certains endroits utilisaient `capital_total` (tous reinvests sans filtre date) ou `montant_investi` brut (sans soustraire le capital remboursé). Corrigé en session 2026-05-29.

---

## Dashboard — backend (dashboard.js)

### portfolio.encours / portfolio.en_defaut

La requête SQL utilise des sous-requêtes corrélées :
```sql
SELECT i.id, ...
  COALESCE(SUM(CASE WHEN i.statut='en_cours' THEN
    i.montant_investi
    + COALESCE((SELECT SUM(rv.montant) FROM reinvestissements rv WHERE rv.investissement_id = i.id), 0)
    - COALESCE((SELECT SUM(rb.capital) FROM remboursements rb WHERE rb.investissement_id = i.id AND rb.type='normal'), 0)
  END), 0) AS encours,
  -- idem pour en_defaut (en_retard + procedure)
FROM investissements i WHERE ...
```

### capitalMensuel (interets-par-plateforme)

Boucle sur les 12 mois de l'année demandée, pour chaque investissement :
```js
capital_restant = montant_investi
                + reinvestsCumul(≤ lastDay)      // depuis reinvestMap
                - capitalRembCumul(≤ lastDay)    // depuis capitalRembMap (type='normal')
                - capitalSimulCumul              // depuis simul_remboursements :
                                                 //   date_prevue > today
                                                 //   ET date_prevue > last_remb_date
                                                 //   ET date_prevue ≤ lastDay
```
`capitalSimulCumul` permet aux années futures (2027+) de décrémenter le capital selon les projections de remboursement.

### KPI "Capital investi" Dashboard (Dashboard.jsx — DashboardKpis)

- **Mode global / année courante** → `portfolio.encours + portfolio.en_defaut`
- **Année passée** → dernier mois de `capitalMensuelData` pour cette année (ex. décembre 2025 = 24 345,13 €)
- `capitalMensuelData` est remonté via callback `onCapitalMensuel` depuis `TableauInteretsPlateforme`
- `prevCapitalAnnee` (référence N-1 pour TrendBadge) utilise encore `capitalParAnneeMap` (capital souscrit par année) faute de données N-1 disponibles

---

## Page Investissements (Investissements.jsx)

### Données chargées

- `allRembs` : tous les remboursements (scope courant)
- `allReinvests` : tous les réinvestissements via `GET /api/reinvestissements?scope=all`

### Memos de coupure (cutoff = platYear ? `${platYear}-12-31` : null)

- `rembParInv` → `{ [inv_id]: { capital, interets_bruts, interets_nets } }` filtrés par cutoff
- `capRembParInv` → alias `{ [inv_id]: capital }` pour rétrocompatibilité
- `reinvestCumulParInv` → `{ [inv_id]: montant_cumulé }` filtrés par cutoff
- `lastRembDateMap` → `{ [inv_id]: date_dernière_remb }` calculé depuis `allRembs`

### Filtre année (platYear) — sémantique "actif au 31/12"

`isActiveAtEndOfYear(r)` : investissement inclus si :
1. `date_souscription ≤ ${platYear}-12-31`
2. ET statut en [`en_cours`, `en_retard`, `procedure`] (actif aujourd'hui)
   OU `date_cible ?? lastRembDateMap[r.id] >= ${platYear}-12-01` (clôturé en décembre ou après)

Remplace l'ancien filtre `date_souscription.slice(0,4) === platYear` dans `kpiRows`, `platData`, et `chartRows`.

**Why:** Le filtre par année de souscription excluait les prêts souscrits en 2024 encore actifs en 2025, créant une divergence avec le Dashboard (24 345 € vs 16 118 €).

### Calcul capInv dans totals / platData / invDistRows

```js
const capInv = r.montant_investi + (reinvestCumulParInv[r.id] || 0);
const capRemb = capRembParInv[r.id] || 0;
const capRestant = Math.max(0, capInv - capRemb);
```

### InvChart.jsx

Props : `rows`, `remboursements`, `reinvestissements`, `platYear`

Deltas chronologiques :
- `+montant_investi` à `date_souscription` (plus `capital_total` — supprimé)
- `+reinvestissement.montant` à `date_reinvestissement` (nouveau)
- `−remboursement.capital` à `date_remb`

---

## GET /api/reinvestissements — mode scope=all

Route `reinvestissements.js` étendue pour supporter `?scope=all` (tous les reinvestissements de l'utilisateur, via JOIN investissements + investisseurs). Utilisé par la page Investissements au chargement.
