diff --git a/client/src/pages/DsiOpex.tsx b/client/src/pages/DsiOpex.tsx index fe767f7..d5daa77 100644 --- a/client/src/pages/DsiOpex.tsx +++ b/client/src/pages/DsiOpex.tsx @@ -597,14 +597,44 @@ export default function DsiOpex() { ); // Établissements (vue par établissement) - const filteredEtabs = useMemo(() => { + // ── Vue établissements : recalcul dynamique depuis les postes éditables (version C) ──────────── + // Le total de chaque établissement = somme(montant_poste × ratio_etab) + // ratio_etab = base_repartition_etab / somme_base_repartition_tous_etabs + const etablissementsRecalcules = useMemo(() => { const srcData = getOpexDataForAnnee(annee); - return srcData.etablissements.filter(e => { + const totalBase = srcData.etablissements.reduce((s, e) => s + e.base_repartition, 0); + if (totalBase === 0) return srcData.etablissements; + + // Total des postes éditables (source de vérité) + const totalPostes = opexState.lignes.reduce((s, l) => s + l.montant, 0); + + return srcData.etablissements.map(etab => { + const ratio = etab.base_repartition / totalBase; + const totalEtab = Math.round(totalPostes * ratio); + + // Ventiler chaque poste éditable au prorata + const montantsRecalcules: Record = {}; + for (const ligne of opexState.lignes) { + if (ligne.montant > 0) { + montantsRecalcules[ligne.libelle] = Math.round(ligne.montant * ratio); + } + } + + return { + ...etab, + montants: montantsRecalcules, + total: totalEtab, + }; + }); + }, [opexState.lignes, annee]); + + const filteredEtabs = useMemo(() => { + return etablissementsRecalcules.filter(e => { if (search && !e.nom.toLowerCase().includes(search.toLowerCase()) && !e.code.toLowerCase().includes(search.toLowerCase())) return false; return true; }); - }, [search]); + }, [etablissementsRecalcules, search]); const sortedEtabs = useMemo(() => { const arr = [...filteredEtabs];