Fix TVPI
This commit is contained in:
1 parent
c2dbe506c5
commit
337d0c1a2c
2 files changed
+26
-20
No files matched your search
@@ -11,7 +11,7 @@ import FraisFormModal from '../components/FraisFormModal.jsx';
|
|||||||
import { FRAIS_CATEGORIE_LABELS } from '../components/MouvementsShared.jsx';
|
import { FRAIS_CATEGORIE_LABELS } from '../components/MouvementsShared.jsx';
|
||||||
import { useAsyncAction } from '../hooks/useAsyncAction.js';
|
import { useAsyncAction } from '../hooks/useAsyncAction.js';
|
||||||
import { fmtEUR, fmtDate, fmtOctets, today } from '../utils/format.js';
|
import { fmtEUR, fmtDate, fmtOctets, today } from '../utils/format.js';
|
||||||
import { emptyDealForm, AUTO_VAL_NOTE } from './InvestissementsPe.jsx';
|
import { emptyDealForm, AUTO_VAL_NOTE, AUTO_VAL_NOTE_LEGACY } from './InvestissementsPe.jsx';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fiche détaillée d'un deal Private Equity (chantier "fiche détail PE", 17/09/26 — demande
|
* Fiche détaillée d'un deal Private Equity (chantier "fiche détail PE", 17/09/26 — demande
|
||||||
@@ -117,7 +117,7 @@ export default function InvestissementPeDetail() {
|
|||||||
if (!deal) return;
|
if (!deal) return;
|
||||||
const entree = fraisOps.find(f => f.categorie === 'souscription');
|
const entree = fraisOps.find(f => f.categorie === 'souscription');
|
||||||
const gestion = fraisOps.find(f => f.categorie === 'gestion' && f.origine === 'souscription');
|
const gestion = fraisOps.find(f => f.categorie === 'gestion' && f.origine === 'souscription');
|
||||||
const autoVal = valorisations.find(v => v.notes === AUTO_VAL_NOTE);
|
const autoVal = valorisations.find(v => v.notes === AUTO_VAL_NOTE || v.notes === AUTO_VAL_NOTE_LEGACY);
|
||||||
setForm({
|
setForm({
|
||||||
...emptyDealForm,
|
...emptyDealForm,
|
||||||
plateforme_id: String(deal.plateforme_id || ''),
|
plateforme_id: String(deal.plateforme_id || ''),
|
||||||
@@ -178,15 +178,16 @@ export default function InvestissementPeDetail() {
|
|||||||
} catch { /* non bloquant */ }
|
} catch { /* non bloquant */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Toujours créée, même sans frais (= montant investi tel quel) — décision Olivier 18/09/26,
|
||||||
|
// cf. InvestissementsPe.jsx::syncValorisationInitiale (même logique, dupliquée ici pour la
|
||||||
|
// modale d'édition de la fiche détail).
|
||||||
const syncValorisationInitiale = async (totalFraisSource, valorisationInitialeId) => {
|
const syncValorisationInitiale = async (totalFraisSource, valorisationInitialeId) => {
|
||||||
try {
|
try {
|
||||||
if (valorisationInitialeId) await api.del(`/investissements-pe/${id}/valorisations/${valorisationInitialeId}`);
|
if (valorisationInitialeId) await api.del(`/investissements-pe/${id}/valorisations/${valorisationInitialeId}`);
|
||||||
if (totalFraisSource > 0) {
|
|
||||||
const initiale = Math.max(0, Math.round((Number(form.montant_investi) - totalFraisSource) * 100) / 100);
|
const initiale = Math.max(0, Math.round((Number(form.montant_investi) - totalFraisSource) * 100) / 100);
|
||||||
await api.post(`/investissements-pe/${id}/valorisations`, {
|
await api.post(`/investissements-pe/${id}/valorisations`, {
|
||||||
date_valorisation: form.date_souscription, valorisation_nette: initiale, notes: AUTO_VAL_NOTE,
|
date_valorisation: form.date_souscription, valorisation_nette: initiale, notes: AUTO_VAL_NOTE,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
} catch { /* non bloquant */ }
|
} catch { /* non bloquant */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,19 +41,23 @@ export const emptyDealForm = {
|
|||||||
// tard depuis la page Frais PE ou la liste des investissements).
|
// tard depuis la page Frais PE ou la liste des investissements).
|
||||||
frais_entree_mode_saisie: 'montant', frais_entree_valeur: '', frais_entree_mode_reglement: 'source', frais_entree_compte_id: '', frais_entree_id: null,
|
frais_entree_mode_saisie: 'montant', frais_entree_valeur: '', frais_entree_mode_reglement: 'source', frais_entree_compte_id: '', frais_entree_id: null,
|
||||||
frais_gestion_mode_saisie: 'montant', frais_gestion_valeur: '', frais_gestion_mode_reglement: 'source', frais_gestion_compte_id: '', frais_gestion_id: null,
|
frais_gestion_mode_saisie: 'montant', frais_gestion_valeur: '', frais_gestion_mode_reglement: 'source', frais_gestion_compte_id: '', frais_gestion_id: null,
|
||||||
// Id de la valorisation "initiale" auto-générée à la date de souscription pour refléter les
|
// Id de la valorisation "initiale" auto-générée à la date de souscription — null si aucune
|
||||||
// frais réglés "à la source" (cf. AUTO_VAL_NOTE / submit ci-dessous) — null si aucune n'existe
|
// n'existe encore pour ce deal. Décision Olivier 17/09/26 (puis 18/09/26 — systématique, même
|
||||||
// encore pour ce deal. Décision Olivier 17/09/26 : le montant investi (souscrit) ne bouge
|
// sans frais) : le montant investi (souscrit) ne bouge JAMAIS, c'est cette valorisation qui
|
||||||
// JAMAIS, c'est la valorisation qui encaisse immédiatement les frais d'entrée/de gestion à la
|
// encaisse immédiatement les frais d'entrée/de gestion éventuels à la date de souscription (ou
|
||||||
// date de souscription — jusqu'à ce qu'une vraie valorisation du fonds vienne la remplacer.
|
// simplement reprend le montant investi tel quel en l'absence de frais) — jusqu'à ce qu'une
|
||||||
|
// vraie valorisation du fonds vienne la remplacer.
|
||||||
valorisation_initiale_id: null,
|
valorisation_initiale_id: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Marqueur de la valorisation "initiale" auto-générée par l'étape "Frais" de la modale (cf.
|
// Marqueur de la valorisation "initiale" auto-générée à la souscription (cf. submit ci-dessous)
|
||||||
// submit ci-dessous) — permet de la retrouver/remplacer sans toucher aux valorisations saisies
|
// — permet de la retrouver/remplacer sans toucher aux valorisations saisies manuellement par
|
||||||
// manuellement par ailleurs (modale "Valorisations" annexe).
|
// ailleurs (modale "Valorisations" annexe). Créée systématiquement depuis le 18/09/26 (avant
|
||||||
export const AUTO_VAL_NOTE = 'Valorisation initiale (frais de souscription)';
|
// cette date, uniquement quand le deal avait des frais réglés "à la source" — cf.
|
||||||
|
// AUTO_VAL_NOTE_LEGACY pour reconnaître ces anciennes lignes lors du pré-remplissage).
|
||||||
|
export const AUTO_VAL_NOTE = 'Valorisation initiale (souscription)';
|
||||||
|
export const AUTO_VAL_NOTE_LEGACY = 'Valorisation initiale (frais de souscription)';
|
||||||
|
|
||||||
// Accès rapide "+ frais" depuis une ligne de la liste des investissements (chantier "frais PE",
|
// Accès rapide "+ frais" depuis une ligne de la liste des investissements (chantier "frais PE",
|
||||||
// 17/09/26, demande Olivier) — permet d'ajouter un frais complémentaire (gestion récurrente,
|
// 17/09/26, demande Olivier) — permet d'ajouter un frais complémentaire (gestion récurrente,
|
||||||
@@ -309,7 +313,7 @@ export default function InvestissementsPe() {
|
|||||||
]);
|
]);
|
||||||
const entree = fraisOps.find(f => f.categorie === 'souscription');
|
const entree = fraisOps.find(f => f.categorie === 'souscription');
|
||||||
const gestion = fraisOps.find(f => f.categorie === 'gestion' && f.origine === 'souscription');
|
const gestion = fraisOps.find(f => f.categorie === 'gestion' && f.origine === 'souscription');
|
||||||
const autoVal = valRows.find(v => v.notes === AUTO_VAL_NOTE);
|
const autoVal = valRows.find(v => v.notes === AUTO_VAL_NOTE || v.notes === AUTO_VAL_NOTE_LEGACY);
|
||||||
setForm(f => ({
|
setForm(f => ({
|
||||||
...f,
|
...f,
|
||||||
valorisation_initiale_id: autoVal ? autoVal.id : null,
|
valorisation_initiale_id: autoVal ? autoVal.id : null,
|
||||||
@@ -361,23 +365,24 @@ export default function InvestissementsPe() {
|
|||||||
|
|
||||||
// Gère la valorisation "initiale" auto-générée à la date de souscription (cf. AUTO_VAL_NOTE) :
|
// Gère la valorisation "initiale" auto-générée à la date de souscription (cf. AUTO_VAL_NOTE) :
|
||||||
// le montant investi (souscrit) ne bouge jamais, c'est cette valorisation qui encaisse
|
// le montant investi (souscrit) ne bouge jamais, c'est cette valorisation qui encaisse
|
||||||
// immédiatement les frais réglés "à la source" — décision Olivier 17/09/26. Comme l'API ne
|
// immédiatement les frais réglés "à la source" quand il y en a. Créée systématiquement,
|
||||||
// propose pas de PUT sur une valorisation, on supprime l'éventuelle ligne existante puis on
|
// même sans frais (= montant investi tel quel) — décision Olivier 18/09/26, pour que la courbe
|
||||||
// recrée à neuf (couvre aussi le cas où la date de souscription a changé). Best-effort, jamais
|
// de valorisation et le TVPI démarrent dès la souscription plutôt que rester sans point tant
|
||||||
// bloquant pour l'enregistrement principal du deal.
|
// qu'aucune valorisation manuelle n'a été saisie. Comme l'API ne propose pas de PUT sur une
|
||||||
|
// valorisation, on supprime l'éventuelle ligne existante puis on recrée à neuf (couvre aussi le
|
||||||
|
// cas où le montant investi, les frais ou la date de souscription ont changé). Best-effort,
|
||||||
|
// jamais bloquant pour l'enregistrement principal du deal.
|
||||||
const syncValorisationInitiale = async (dealId, totalFraisSource, valorisationInitialeId) => {
|
const syncValorisationInitiale = async (dealId, totalFraisSource, valorisationInitialeId) => {
|
||||||
try {
|
try {
|
||||||
if (valorisationInitialeId) {
|
if (valorisationInitialeId) {
|
||||||
await api.del(`/investissements-pe/${dealId}/valorisations/${valorisationInitialeId}`);
|
await api.del(`/investissements-pe/${dealId}/valorisations/${valorisationInitialeId}`);
|
||||||
}
|
}
|
||||||
if (totalFraisSource > 0) {
|
|
||||||
const initiale = Math.max(0, Math.round((Number(form.montant_investi) - totalFraisSource) * 100) / 100);
|
const initiale = Math.max(0, Math.round((Number(form.montant_investi) - totalFraisSource) * 100) / 100);
|
||||||
await api.post(`/investissements-pe/${dealId}/valorisations`, {
|
await api.post(`/investissements-pe/${dealId}/valorisations`, {
|
||||||
date_valorisation: form.date_souscription,
|
date_valorisation: form.date_souscription,
|
||||||
valorisation_nette: initiale,
|
valorisation_nette: initiale,
|
||||||
notes: AUTO_VAL_NOTE,
|
notes: AUTO_VAL_NOTE,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
} catch { /* non bloquant — rattrapable depuis la modale Valorisations */ }
|
} catch { /* non bloquant — rattrapable depuis la modale Valorisations */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user