diff --git a/frontend/src/components/DrillCellPanel.jsx b/frontend/src/components/DrillCellPanel.jsx
index a3266ff..82946ed 100644
--- a/frontend/src/components/DrillCellPanel.jsx
+++ b/frontend/src/components/DrillCellPanel.jsx
@@ -131,6 +131,10 @@ export default function DrillCellPanel({
const totalProjetes = projetes.reduce((s, p) => s + projRowValue(p), 0);
const grandTotal = (showRecus ? totalRecus : 0) + (showProjetes ? totalProjetes : 0);
+ /* Lignes visibles : masquer les lignes à 0 selon les critères actifs */
+ const recusVisible = recus.filter(r => recuRowValue(r) !== 0);
+ const projetesVisible = projetes.filter(p => projRowValue(p) !== 0);
+
/* ── Colonnes dynamiques ── */
const cols = [
inclureInterets && { key: 'interets', label: netMode ? 'Intérêts nets' : 'Intérêts bruts', color: chartInterets },
@@ -327,14 +331,14 @@ export default function DrillCellPanel({
background: hexToRgba(chartInterets, 0.07),
color: 'var(--text-muted)', letterSpacing: '.04em', textTransform: 'uppercase',
}}>
- Reçus ({recus.length})
+ Reçus ({recusVisible.length}{recusVisible.length !== recus.length ? `/${recus.length}` : ''})
- {recus.length === 0 ? (
+ {recusVisible.length === 0 ? (
- Aucun remboursement reçu ce mois
+ {recus.length === 0 ? 'Aucun remboursement reçu ce mois' : 'Aucun montant à afficher avec les critères sélectionnés'}
- ) : recus.map(r => (
+ ) : recusVisible.map(r => (
{fmtEUR(recuRowValue(r))}
))}
- {recus.length > 0 && (
+ {recusVisible.length > 0 && (
Sous-total reçus
@@ -383,7 +387,7 @@ export default function DrillCellPanel({
color: 'var(--text-muted)', letterSpacing: '.04em', textTransform: 'uppercase',
}}>
- Projetés ({projetes.length})
+ Projetés ({projetesVisible.length}{projetesVisible.length !== projetes.length ? `/${projetes.length}` : ''})
{projetes.length > 0 && (
openBulkModal()}
@@ -408,11 +412,11 @@ export default function DrillCellPanel({
- {projetes.length === 0 ? (
+ {projetesVisible.length === 0 ? (
- Aucune projection ce mois
+ {projetes.length === 0 ? 'Aucune projection ce mois' : 'Aucun montant à afficher avec les critères sélectionnés'}
- ) : projetes.map(p => (
+ ) : projetesVisible.map(p => (
{fmtEUR(projRowValue(p))}
))}
- {projetes.length > 0 && (
+ {projetesVisible.length > 0 && (
Sous-total projetés
diff --git a/frontend/src/pages/InvestissementDetail.jsx b/frontend/src/pages/InvestissementDetail.jsx
index 2ba1ca2..cc05da0 100644
--- a/frontend/src/pages/InvestissementDetail.jsx
+++ b/frontend/src/pages/InvestissementDetail.jsx
@@ -561,6 +561,12 @@ export default function InvestissementDetail() {
const showFinDeMois = (form.type_remb === 'in_fine' || form.type_remb === 'differe')
&& dayOfMonth(form.date_premiere_echeance) > 27;
+ // Validation date d'échéance pour les prêts différés
+ if (form.type_remb === 'differe' && !form.date_premiere_echeance) {
+ setEditErr("La date d'échéance est requise pour un prêt différé.");
+ return;
+ }
+
const payload = {
investisseur_id: Number(form.investisseur_id) || undefined,
plateforme_id: Number(form.plateforme_id),
@@ -1590,12 +1596,14 @@ export default function InvestissementDetail() {
freq_interets: t === 'differe' ? 'in_fine' : (form.freq_interets === 'in_fine' ? 'mensuel' : form.freq_interets),
};
if (t === 'differe') {
- if (form.date_premiere_echeance) next.date_cible = form.date_premiere_echeance;
- else if (form.date_souscription && form.duree_mois) {
+ // Recalculer la date d'échéance depuis souscription+durée (prioritaire sur l'ancienne valeur)
+ if (form.date_souscription && form.duree_mois) {
const dpe = addMonthsFE(form.date_souscription, 1);
const cible = addMonthsFE(dpe, Number(form.duree_mois) - 1);
next.date_premiere_echeance = cible;
next.date_cible = cible;
+ } else if (form.date_premiere_echeance) {
+ next.date_cible = form.date_premiere_echeance;
}
} else {
if (form.date_souscription) {
diff --git a/frontend/src/pages/Investissements.jsx b/frontend/src/pages/Investissements.jsx
index c4edea8..378f6a7 100644
--- a/frontend/src/pages/Investissements.jsx
+++ b/frontend/src/pages/Investissements.jsx
@@ -680,6 +680,12 @@ export default function Investissements() {
const showFinDeMois = (form.type_remb === 'in_fine' || form.type_remb === 'differe')
&& dayOfMonth(form.date_premiere_echeance) > 27;
+ // Validation date d'échéance pour les prêts différés
+ if (form.type_remb === 'differe' && !form.date_premiere_echeance) {
+ setErr("La date d'échéance est requise pour un prêt différé. Vérifiez que la durée et la date de souscription sont renseignées.");
+ return;
+ }
+
const payload = {
investisseur_id: Number(form.investisseur_id) || undefined,
plateforme_id: Number(form.plateforme_id),
@@ -1366,13 +1372,14 @@ export default function Investissements() {
freq_interets: t === 'differe' ? 'in_fine' : (form.freq_interets === 'in_fine' ? 'mensuel' : form.freq_interets),
};
if (t === 'differe') {
- if (form.date_premiere_echeance) {
- next.date_cible = form.date_premiere_echeance;
- } else if (form.date_souscription && form.duree_mois) {
+ // Recalculer la date d'échéance depuis souscription+durée (prioritaire sur l'ancienne valeur)
+ if (form.date_souscription && form.duree_mois) {
const dpe = addMonthsFE(form.date_souscription, 1);
const cible = addMonthsFE(dpe, Number(form.duree_mois) - 1);
next.date_premiere_echeance = cible;
next.date_cible = cible;
+ } else if (form.date_premiere_echeance) {
+ next.date_cible = form.date_premiere_echeance;
}
} else {
if (form.date_souscription) {
@@ -1434,7 +1441,7 @@ export default function Investissements() {
}} />
- Date 1ère échéance *
+ {form.type_remb === 'differe' ? "Date d'échéance (versement unique) *" : 'Date 1ère échéance *'}
{
const dpe = e.target.value;