From 11790c63fe3f6a2bc996b23c6c3ca9bc0d82f242 Mon Sep 17 00:00:00 2001 From: Olivier Date: Sat, 4 Jul 2026 18:32:51 +0200 Subject: [PATCH] =?UTF-8?q?Correction=20de=20l'affichage=20en=20tant=20que?= =?UTF-8?q?=20mono=20d=C3=A9tenteur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/DepotsRetraits.jsx | 18 ++--- frontend/src/pages/Investissements.jsx | 14 ++-- frontend/src/pages/Plateformes.jsx | 7 +- frontend/src/pages/Remboursements.jsx | 20 ++--- .../src/pages/settings/ComptesSection.jsx | 8 +- .../src/pages/settings/PlateformesSection.jsx | 79 +++++++++++++++++-- 6 files changed, 109 insertions(+), 37 deletions(-) diff --git a/frontend/src/pages/DepotsRetraits.jsx b/frontend/src/pages/DepotsRetraits.jsx index ebb48cc..5270bb6 100644 --- a/frontend/src/pages/DepotsRetraits.jsx +++ b/frontend/src/pages/DepotsRetraits.jsx @@ -889,7 +889,7 @@ export default function DepotsRetraits() { ); - if (!loading && !modalOpen && allRows.length === 0) return ( + if (!loading && !modalOpen && !corrModal.open && allRows.length === 0) return ( <>

Dépôts / Retraits

- PlateformeDétenteurDépôtsRetraitsDiff. Dépôts vs RetraitsPorte-monnaiePoids + Plateforme{multiDetenteur && Détenteur}DépôtsRetraitsDiff. Dépôts vs RetraitsPorte-monnaiePoids {drPlatData.length === 0 && ( - Aucune plateforme + Aucune plateforme )} {(() => { const totalSolde = drPlatTotals.solde_net; @@ -1053,7 +1053,7 @@ export default function DepotsRetraits() { {p.nom} - {p.detenteur_nom || '—'} + {multiDetenteur && {p.detenteur_nom || '—'}} {fmtEUR(p.depots)} {fmtEUR(p.retraits)} {fmtEUR(p.solde_net)} @@ -1080,7 +1080,7 @@ export default function DepotsRetraits() { Total — {drPlatData.length} plateformes - + {multiDetenteur && } {fmtEUR(drPlatTotals.depots)} {fmtEUR(drPlatTotals.retraits)} {fmtEUR(drPlatTotals.solde_net)} @@ -1236,12 +1236,12 @@ export default function DepotsRetraits() { - + {multiDetenteur && } {tableRows.length === 0 && ( - )} @@ -1255,7 +1255,7 @@ export default function DepotsRetraits() { style={{ cursor: 'pointer' }}> - + {multiDetenteur && } - + {multiDetenteur && } - + {multiDetenteur && } @@ -974,7 +974,7 @@ export default function Investissements() { {platData.length === 0 && ( - )} @@ -999,7 +999,7 @@ export default function Investissements() { }}>! )} - + {multiDetenteur && } @@ -1032,7 +1032,7 @@ export default function Investissements() { - @@ -1202,7 +1202,7 @@ export default function Investissements() {
DatePlateformeDétenteurType de mouvementMontantDatePlateformeDétenteurType de mouvementMontant
+
{loading ? 'Chargement…' : 'Aucun mouvement'}
{fmtDate(r.date_operation)} {r.plateforme_nom}{r.plateforme_detenteur_nom || '—'}{r.plateforme_detenteur_nom || '—'} {fmtDate(r.date_operation)} {r.plateforme_nom}{r.plateforme_detenteur_nom || '—'}{r.plateforme_detenteur_nom || '—'} {r.type} {isAuto && ( diff --git a/frontend/src/pages/Investissements.jsx b/frontend/src/pages/Investissements.jsx index 37d93b1..c0ba535 100644 --- a/frontend/src/pages/Investissements.jsx +++ b/frontend/src/pages/Investissements.jsx @@ -962,7 +962,7 @@ export default function Investissements() {
PlateformeDétenteurDétenteurProjets Montant investi Capital investi
+
Aucun investissement
{p.detenteur_nom || '—'}{p.detenteur_nom || '—'}{p.count} {fmtEUR(p.investi)} {fmtEUR(p.encours)} Total — {platData.length} plateformes + {multiDetenteur && } {platTotals.count} {fmtEUR(platTotals.investi)} {fmtEUR(platTotals.encours)}
- + {multiDetenteur && } @@ -1213,7 +1213,7 @@ export default function Investissements() { {rows.length === 0 && ( - )} @@ -1233,7 +1233,7 @@ export default function Investissements() { {r.emetteur &&
{r.emetteur}
} - + {multiDetenteur && } diff --git a/frontend/src/pages/Plateformes.jsx b/frontend/src/pages/Plateformes.jsx index abc159e..24dbf54 100644 --- a/frontend/src/pages/Plateformes.jsx +++ b/frontend/src/pages/Plateformes.jsx @@ -424,6 +424,9 @@ export default function Plateformes() { ]; }, [platRows, investisseurs]); + /* ── Vrai/faux multi-détenteur global (indépendant de la plateforme sélectionnée) ── */ + const multiDetenteur = new Set(plats.map(p => p.investisseur_id)).size > 1; + /* ── Reset détenteur quand plateforme change (skip restauration initiale) ── */ const isFirstPlatChange = useRef(true); useEffect(() => { @@ -1534,7 +1537,7 @@ export default function Plateformes() { - + {multiDetenteur && } @@ -1555,7 +1558,7 @@ export default function Plateformes() { navigate(`/investissements/${r.id}`, { state: { from: { path: location.pathname, search: location.search, label: 'Plateformes' } } })}> - + {multiDetenteur && } diff --git a/frontend/src/pages/Remboursements.jsx b/frontend/src/pages/Remboursements.jsx index 87f9aab..9910797 100644 --- a/frontend/src/pages/Remboursements.jsx +++ b/frontend/src/pages/Remboursements.jsx @@ -899,7 +899,7 @@ export default function Remboursements() { - + {multiDetenteur && } @@ -911,7 +911,7 @@ export default function Remboursements() { {byPlatform.length === 0 && ( - )} @@ -927,7 +927,7 @@ export default function Remboursements() { title={isActive ? 'Cliquer pour retirer le filtre' : 'Cliquer pour filtrer sur cette plateforme'} > - + {multiDetenteur && } @@ -954,7 +954,7 @@ export default function Remboursements() { - @@ -1131,7 +1131,7 @@ export default function Remboursements() {
DateProjetPlateformeDétenteurDateProjetPlateformeDétenteurMontantTaux DuréeType remb. Inv. remboursésCap. restant dû
+
{loading ? 'Chargement…' : 'Aucun investissement'}
{r.plateforme_nom}{r.plateforme_detenteur_nom || '—'}{r.plateforme_detenteur_nom || '—'}{fmtEUR(capInv)} {r.taux_interet != null ? fmtPct(r.taux_interet) : '—'} {r.duree_mois ? `${r.duree_mois} m.` : '—'}
ProjetDétenteurDétenteurDate de souscription Date cible Montant
{r.nom_projet}{(() => { const inv = investisseurs.find(i => i.id === r.investisseur_id); return inv ? memberLabel(inv) : '—'; })()}{(() => { const inv = investisseurs.find(i => i.id === r.investisseur_id); return inv ? memberLabel(inv) : '—'; })()}{fmtDate(r.date_souscription)} {fmtDate(r.date_cible)} {fmtEUR(r.montant_investi)}
PlateformeDétenteurDétenteurCapital remboursé Cashback Intérêts ({netMode ? 'Net' : 'Brut'})
+
{loading ? 'Chargement…' : 'Aucun remboursement'}
{p.nom}{p.detenteur_nom || '—'}{p.detenteur_nom || '—'}{fmtEUR(p.capital)} {p.cashback > 0 ? fmtEUR(p.cashback) : '—'} {fmtEUR(val)}
Total — {byPlatform.length} plateformes + {multiDetenteur && } {fmtEUR(byPlatformTotals.capital)} {byPlatformTotals.cashback > 0 ? fmtEUR(byPlatformTotals.cashback) : '—'} {fmtEUR(netMode ? byPlatformTotals.interets_nets : byPlatformTotals.interets_bruts)}
- + {multiDetenteur && } @@ -1143,7 +1143,7 @@ export default function Remboursements() { {tableRows.length === 0 && ( - )} @@ -1169,9 +1169,11 @@ export default function Remboursements() { }}> - + {multiDetenteur && ( + + )} - + {multiDetenteur && } {comptes.length === 0 && ( - )} @@ -172,7 +174,7 @@ export default function ComptesSection() { - + {multiDetenteur && } - + {multiDetenteur && } {plats.length === 0 && ( - + )} {plats.map((p, i) => { const imgSrc = p.icone_filename ? logoUrl(p.icone_filename) : p.logo_filename ? logoUrl(p.logo_filename) : null; @@ -1054,9 +1117,11 @@ export default function PlateformesSection() { {sects.length === 0 && } - + {multiDetenteur && ( + + )}
DatePlateformeDétenteurNom du projetVersementDatePlateformeDétenteurNom du projetVersement Capital RembourséCapital Restant dû Cashback Intérêts Bruts
+
{loading ? 'Chargement…' : 'Aucun remboursement'}
{fmtDate(r.date_remb)} {r.plateforme_nom} - {isCorrection ? (r.investisseur_nom || '—') : (r.plateforme_detenteur_nom || '—')} - + {isCorrection ? (r.investisseur_nom || '—') : (r.plateforme_detenteur_nom || '—')} + {isCorrection ? {r.nom_projet} diff --git a/frontend/src/pages/settings/ComptesSection.jsx b/frontend/src/pages/settings/ComptesSection.jsx index 6dcce85..dcb8ad2 100644 --- a/frontend/src/pages/settings/ComptesSection.jsx +++ b/frontend/src/pages/settings/ComptesSection.jsx @@ -132,6 +132,8 @@ export default function ComptesSection() { }); }; + const multiDetenteur = investisseurs.length > 1; + return ( <>
@@ -154,7 +156,7 @@ export default function ComptesSection() {
Nom TypeDétenteurDétenteurBanque Exonération @@ -162,7 +164,7 @@ export default function ComptesSection() {
+
Aucun compte défini.
{c.nom} {TYPE_COMPTE_LABELS[c.type] ?? c.type}{inv ? memberLabel(inv) : }{inv ? memberLabel(inv) : }{c.banque || } {c.exoneration_fiscale && c.exoneration_fiscale !== 'aucune' ? ( diff --git a/frontend/src/pages/settings/PlateformesSection.jsx b/frontend/src/pages/settings/PlateformesSection.jsx index a32f672..53e3887 100644 --- a/frontend/src/pages/settings/PlateformesSection.jsx +++ b/frontend/src/pages/settings/PlateformesSection.jsx @@ -17,6 +17,12 @@ function dlBlob(content, filename, type) { URL.revokeObjectURL(url); } +/** Date du jour au format YYYY-MM-DD, en heure locale (ne pas utiliser toISOString ici, décale d'un jour selon le fuseau). */ +function localToday() { + const d = new Date(); + return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; +} + const countryLabel = code => COUNTRIES.find(c => c.code === code)?.name ?? code ?? '—'; const FISCALITE_LABELS = { flat_tax: 'Flat Tax', @@ -283,6 +289,13 @@ function PlatDetailPanel({ plat, onEdit }) { function PlatPickerModal({ open, onClose, referentiel, onSelect, onManual, err }) { const [search, setSearch] = useState(''); const [domFilter, setDomFilter] = useState('all'); // 'all' | 'fr' | 'etr' + const [confirming, setConfirming] = useState(null); // ref en cours de confirmation + const [dateOuverture, setDateOuverture] = useState(''); + + useEffect(() => { + if (open) { setConfirming(null); setDateOuverture(''); } + }, [open]); + if (!open) return null; const q = search.trim().toLowerCase(); @@ -298,6 +311,53 @@ function PlatPickerModal({ open, onClose, referentiel, onSelect, onManual, err } return f ? (LOGO_BASE + f) : null; }; + /* ── Étape de confirmation : date d'ouverture du compte ── */ + if (confirming) { + const img = imgFor(confirming); + return ( + + + + + } + > +
+ {err &&
{err}
} +
+ {img + ? {confirming.nom} + :
🏦
+ } +
{confirming.nom}
+
+

+ Pouvez-vous SVP préciser la date d'ouverture de votre compte sur cette plateforme ? +

+
+ + setDateOuverture(e.target.value)} + style={{ width: '100%', boxSizing: 'border-box' }} + /> +
+
+
+ ); + } + return ( onSelect(r)} + onClick={() => { setConfirming(r); setDateOuverture(localToday()); }} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, padding: '16px 10px 12px', @@ -779,7 +839,7 @@ export default function PlateformesSection() { }; /* ── Ajouter depuis le référentiel ──────────────────────────── */ - const addPlatFromRef = async (ref) => { + const addPlatFromRef = async (ref, dateOuverture) => { try { await api.post('/plateformes', { nom: ref.nom, @@ -792,6 +852,7 @@ export default function PlateformesSection() { type_pret_defaut: ref.type_pret_defaut || null, freq_interets_defaut: ref.freq_interets_defaut || null, referentiel_id: ref.id, + date_ouverture: dateOuverture || null, }); setShowAddPicker(false); await load(); @@ -942,6 +1003,8 @@ export default function PlateformesSection() { } catch (e) { setErr(e.message); } }; + const multiDetenteur = new Set(plats.map(p => p.investisseur_id)).size > 1; + /* ── PFU CRUD ────────────────────────────────────────────────── */ @@ -1000,14 +1063,14 @@ export default function PlateformesSection() {
Domiciliation Catégories SecteursDétenteurDétenteurInvest.
Aucune plateforme
Aucune plateforme
- {inv ? memberLabel(inv) : '—'} - + {inv ? memberLabel(inv) : '—'} + 0 ? 'var(--text)' : 'var(--text-muted)' }}> {p.nb_investissements ?? 0}