Lien comptes courants / enveloppes
This commit is contained in:
1 parent
f507163369
commit
9591ae400e
13 files changed
+202
-79
No files matched your search
@@ -168,7 +168,7 @@ export default function InvestissementFormModal({
|
||||
|
||||
const handleMethodeChange = (methode) => {
|
||||
const defaultCompte = methode === 'compte_courant'
|
||||
? (comptesInvestisseur.find(c => c.type === 'compte_courant') ?? comptesInvestisseur[0])
|
||||
? (comptesInvestisseur.find(c => c.compte_reglement_par_defaut) ?? comptesInvestisseur[0])
|
||||
: null;
|
||||
onFormPatch({ methode_remboursement: methode, nom_compte_courant: defaultCompte?.nom || '', compte_id: String(defaultCompte?.id || '') });
|
||||
};
|
||||
|
||||
@@ -123,7 +123,7 @@ export default function RembFormModal({
|
||||
const modalTitle = title ?? (editingId ? 'Modifier le remboursement' : (locked ? 'Saisir le remboursement' : 'Nouveau remboursement'));
|
||||
|
||||
const handleMethodeChange = (m) => {
|
||||
const def = m === 'compte_courant' ? (comptesInvestisseur?.find(c => c.type === 'compte_courant') ?? comptesInvestisseur?.[0]) : null;
|
||||
const def = m === 'compte_courant' ? (comptesInvestisseur?.find(c => c.compte_reglement_par_defaut) ?? comptesInvestisseur?.[0]) : null;
|
||||
onFormPatch({ methode_remboursement: m, compte_id: def ? String(def.id) : '' });
|
||||
};
|
||||
|
||||
@@ -133,7 +133,7 @@ export default function RembFormModal({
|
||||
// 'compte_courant' — même pattern que handleFraisReglementChange côté investissement.
|
||||
const handleFraisModeChange = (mode) => {
|
||||
onFieldChange('frais_mode_reglement', mode);
|
||||
const def = mode === 'compte_courant' ? (comptesInvestisseur?.find(c => c.type === 'compte_courant') ?? comptesInvestisseur?.[0]) : null;
|
||||
const def = mode === 'compte_courant' ? (comptesInvestisseur?.find(c => c.compte_reglement_par_defaut) ?? comptesInvestisseur?.[0]) : null;
|
||||
onFormPatch({ frais_compte_id: def ? String(def.id) : '' });
|
||||
};
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ export default function InvestissementDetail() {
|
||||
.then(comptes => {
|
||||
setComptesInvestisseur(comptes);
|
||||
if (form.methode_remboursement === 'compte_courant' && !form.compte_id) {
|
||||
const def = comptes.find(c => c.type === 'compte_courant') ?? comptes[0];
|
||||
const def = comptes.find(c => c.compte_reglement_par_defaut) ?? comptes[0];
|
||||
if (def) setForm(f => ({ ...f, compte_id: String(def.id), nom_compte_courant: def.nom }));
|
||||
}
|
||||
})
|
||||
@@ -148,7 +148,7 @@ export default function InvestissementDetail() {
|
||||
.then(comptes => {
|
||||
setComptesRembInvestisseur(comptes);
|
||||
if (rembForm.methode_remboursement === 'compte_courant' && !rembForm.compte_id) {
|
||||
const def = comptes.find(c => c.type === 'compte_courant') ?? comptes[0];
|
||||
const def = comptes.find(c => c.compte_reglement_par_defaut) ?? comptes[0];
|
||||
if (def) setRembForm(f => ({ ...f, compte_id: String(def.id) }));
|
||||
}
|
||||
})
|
||||
|
||||
@@ -342,7 +342,7 @@ export default function Investissements() {
|
||||
.then(comptes => {
|
||||
setComptesInvestisseur(comptes);
|
||||
if (form.methode_remboursement === 'compte_courant' && !form.compte_id) {
|
||||
const def = comptes.find(c => c.type === 'compte_courant') ?? comptes[0];
|
||||
const def = comptes.find(c => c.compte_reglement_par_defaut) ?? comptes[0];
|
||||
if (def) setForm(f => ({ ...f, compte_id: String(def.id), nom_compte_courant: def.nom }));
|
||||
}
|
||||
})
|
||||
|
||||
@@ -727,7 +727,7 @@ export default function Remboursements() {
|
||||
if (next.methode_remboursement === 'compte_courant') {
|
||||
// Priorité : compte lié à l'investissement, sinon premier compte_courant
|
||||
const inherited = inv.compte_id ? comptes.find(c => c.id === inv.compte_id) : null;
|
||||
const def = inherited ?? comptes.find(c => c.type === 'compte_courant') ?? comptes[0];
|
||||
const def = inherited ?? comptes.find(c => c.compte_reglement_par_defaut) ?? comptes[0];
|
||||
if (def) setForm(f => ({ ...f, compte_id: String(def.id) }));
|
||||
}
|
||||
})
|
||||
|
||||
@@ -9,12 +9,7 @@ const EXONERATION_LABELS = {
|
||||
aucune: 'Aucune',
|
||||
pfnl_5ans: 'PFnl 5 ans',
|
||||
};
|
||||
const TYPE_COMPTE_LABELS = {
|
||||
compte_courant: 'Compte courant',
|
||||
pea_pme: 'PEA-PME',
|
||||
};
|
||||
|
||||
const EMPTY_COMPTE = { nom: '', type: 'compte_courant', investisseur_id: null, institution_id: null, banque: '', enveloppe_id: null, exoneration_fiscale: 'aucune' };
|
||||
const EMPTY_COMPTE = { nom: '', investisseur_id: null, institution_id: null, banque: '', enveloppe_id: null, exoneration_fiscale: 'aucune', compte_reglement_par_defaut: false };
|
||||
|
||||
// Référentiel institutions financières (Phase 2, 26/09/26) — logos servis au même endroit
|
||||
// que ceux des plateformes (/api/logos/:filename), cf. institutionsReferentiel.js.
|
||||
@@ -45,31 +40,22 @@ function CompteFormFields({ state, setter, investisseurs, institutions, envelopp
|
||||
onChange={e => setter({ ...state, nom: e.target.value })}
|
||||
placeholder="ex. Compte courant BNP" />
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
|
||||
<div>
|
||||
<label>Type *</label>
|
||||
<select value={state.type} onChange={e => setter({ ...state, type: e.target.value })}>
|
||||
<option value="compte_courant">Compte courant</option>
|
||||
<option value="pea_pme">PEA-PME</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label>Banque</label>
|
||||
<select
|
||||
value={state.institution_id ?? '__autre__'}
|
||||
onChange={e => {
|
||||
const v = e.target.value;
|
||||
if (v === '__autre__') { setter({ ...state, institution_id: null }); return; }
|
||||
const inst = institutions.find(i => i.id === Number(v));
|
||||
setter({ ...state, institution_id: Number(v), banque: inst ? inst.nom : state.banque });
|
||||
}}
|
||||
>
|
||||
<option value="__autre__">Autre (texte libre)</option>
|
||||
{institutions.map(inst => (
|
||||
<option key={inst.id} value={inst.id}>{inst.nom}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label>Banque</label>
|
||||
<select
|
||||
value={state.institution_id ?? '__autre__'}
|
||||
onChange={e => {
|
||||
const v = e.target.value;
|
||||
if (v === '__autre__') { setter({ ...state, institution_id: null }); return; }
|
||||
const inst = institutions.find(i => i.id === Number(v));
|
||||
setter({ ...state, institution_id: Number(v), banque: inst ? inst.nom : state.banque });
|
||||
}}
|
||||
>
|
||||
<option value="__autre__">Autre (texte libre)</option>
|
||||
{institutions.map(inst => (
|
||||
<option key={inst.id} value={inst.id}>{inst.nom}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
{isAutre && (
|
||||
<div>
|
||||
@@ -91,7 +77,7 @@ function CompteFormFields({ state, setter, investisseurs, institutions, envelopp
|
||||
))}
|
||||
</select>
|
||||
<p style={{ margin: '4px 0 0', fontSize: 11, color: 'var(--text-muted)' }}>
|
||||
Rattachement au référentiel (Admin > Enveloppes & supports) — informatif, sans effet sur le champ Type ci-dessus.
|
||||
Rattachement au référentiel (Admin > Enveloppes & supports).
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
@@ -104,6 +90,18 @@ function CompteFormFields({ state, setter, investisseurs, institutions, envelopp
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer' }}>
|
||||
<input type="checkbox" checked={!!state.compte_reglement_par_defaut} style={{ width: 'auto' }}
|
||||
onChange={e => setter({ ...state, compte_reglement_par_defaut: e.target.checked })} />
|
||||
Compte de règlement par défaut
|
||||
</label>
|
||||
<p style={{ margin: '2px 0 0', fontSize: 11, color: 'var(--text-muted)' }}>
|
||||
Utilisé pour pré-remplir automatiquement le compte de règlement sur les remboursements
|
||||
et frais de ce détenteur. Un seul compte par défaut par détenteur (28/09/26 — remplace
|
||||
l'ancien champ Type).
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<label>Exonération fiscale</label>
|
||||
<select value={state.exoneration_fiscale ?? 'aucune'}
|
||||
@@ -153,12 +151,12 @@ export default function ComptesSection() {
|
||||
try {
|
||||
await api.post('/comptes', {
|
||||
nom: newCompte.nom,
|
||||
type: newCompte.type,
|
||||
banque: newCompte.banque || null,
|
||||
institution_id: newCompte.institution_id ?? null,
|
||||
enveloppe_id: newCompte.enveloppe_id ?? null,
|
||||
investisseur_id: newCompte.investisseur_id ? Number(newCompte.investisseur_id) : null,
|
||||
exoneration_fiscale: newCompte.exoneration_fiscale ?? 'aucune',
|
||||
compte_reglement_par_defaut: !!newCompte.compte_reglement_par_defaut,
|
||||
});
|
||||
setShowNew(false); setNewCompte(EMPTY_COMPTE); reload();
|
||||
} catch (ex) { setErr(ex.message); }
|
||||
@@ -169,12 +167,12 @@ export default function ComptesSection() {
|
||||
try {
|
||||
await api.put(`/comptes/${editCompte.id}`, {
|
||||
nom: editCompte.nom,
|
||||
type: editCompte.type,
|
||||
banque: editCompte.banque || null,
|
||||
institution_id: editCompte.institution_id ?? null,
|
||||
enveloppe_id: editCompte.enveloppe_id ?? null,
|
||||
investisseur_id: editCompte.investisseur_id ? Number(editCompte.investisseur_id) : null,
|
||||
exoneration_fiscale: editCompte.exoneration_fiscale ?? 'aucune',
|
||||
compte_reglement_par_defaut: !!editCompte.compte_reglement_par_defaut,
|
||||
});
|
||||
setEditCompte(null); reload();
|
||||
} catch (ex) { setErr(ex.message); }
|
||||
@@ -182,7 +180,7 @@ export default function ComptesSection() {
|
||||
|
||||
const openEdit = (c) => {
|
||||
setErr(null);
|
||||
setEditCompte({ id: c.id, nom: c.nom, type: c.type, banque: c.banque || '', institution_id: c.institution_id ?? null, enveloppe_id: c.enveloppe_id ?? null, investisseur_id: c.investisseur_id ?? null, exoneration_fiscale: c.exoneration_fiscale ?? 'aucune' });
|
||||
setEditCompte({ id: c.id, nom: c.nom, banque: c.banque || '', institution_id: c.institution_id ?? null, enveloppe_id: c.enveloppe_id ?? null, investisseur_id: c.investisseur_id ?? null, exoneration_fiscale: c.exoneration_fiscale ?? 'aucune', compte_reglement_par_defaut: !!c.compte_reglement_par_defaut });
|
||||
};
|
||||
|
||||
const del = (c) => {
|
||||
@@ -219,11 +217,11 @@ export default function ComptesSection() {
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nom</th>
|
||||
<th style={{ width: '13%' }}>Type</th>
|
||||
{multiDetenteur && <th style={{ width: '18%' }}>Détenteur</th>}
|
||||
<th style={{ width: '14%' }}>Banque</th>
|
||||
<th style={{ width: '16%' }}>Enveloppe</th>
|
||||
<th style={{ width: '10%' }}>Exonération</th>
|
||||
<th style={{ width: '11%' }}>Défaut</th>
|
||||
<th style={{ width: '9%' }}>Exonération</th>
|
||||
<th style={{ width: 80 }} />
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -238,7 +236,6 @@ export default function ComptesSection() {
|
||||
return (
|
||||
<tr key={c.id}>
|
||||
<td style={{ fontWeight: 500 }}>{c.nom}</td>
|
||||
<td><span className="badge">{TYPE_COMPTE_LABELS[c.type] ?? c.type}</span></td>
|
||||
{multiDetenteur && <td>{inv ? memberLabel(inv) : <span className="text-muted">—</span>}</td>}
|
||||
<td>
|
||||
{c.institution_id ? (
|
||||
@@ -252,6 +249,13 @@ export default function ComptesSection() {
|
||||
) : (c.banque || <span className="text-muted">—</span>)}
|
||||
</td>
|
||||
<td>{c.enveloppe_nom || <span className="text-muted">—</span>}</td>
|
||||
<td>
|
||||
{c.compte_reglement_par_defaut ? (
|
||||
<span style={{ color: 'var(--primary)', fontWeight: 600, fontSize: 'var(--fs-sm)' }}>✓ Défaut</span>
|
||||
) : (
|
||||
<span className="text-muted" style={{ fontSize: 'var(--fs-sm)' }}>—</span>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{c.exoneration_fiscale && c.exoneration_fiscale !== 'aucune' ? (
|
||||
<span
|
||||
|
||||
Reference in new issue
Block a user