MAJ
This commit is contained in:
1 parent
4cd4cbce71
commit
27c4c57a58
6 files changed
+243
-49
No files matched your search
@@ -3409,4 +3409,21 @@ if (!invPeCols.includes('capital_investissable')) {
|
||||
}
|
||||
db.exec('CREATE INDEX IF NOT EXISTS idx_remb_invpe ON remboursements(investissement_pe_id)');
|
||||
|
||||
// Migration : nature d'une distribution PE (18/09/26, demande Olivier — distinguer, au sein des
|
||||
// distributions reçues sur un deal PE, ce qui restitue le capital déployé ('capital') de ce qui
|
||||
// est un revenu d'intérêt versé sur le capital NON déployé, placé par le fonds sur un support
|
||||
// obligataire en attendant d'être appelé ('interet_non_deploye') — reprend la ligne "Obligation"
|
||||
// des captures Fundora, jusque-là non reconstituable faute de cette distinction. Nullable et
|
||||
// sans CHECK (validé côté Zod, cf. remboursements.js) : une distribution non classée n'est ni
|
||||
// l'un ni l'autre, elle reste comptée dans "Distributions" par défaut (cf.
|
||||
// investissementsPe.js::GET / et GET /:id). Sans effet sur les remboursements crowdlending
|
||||
// (type 'normal') ni sur les bonus (parrainage/plateforme), seul le type 'interets_plateforme'
|
||||
// (rebaptisé "Distribution" côté PE) l'utilise.
|
||||
{
|
||||
const rembCols3 = db.prepare('PRAGMA table_info(remboursements)').all().map(c => c.name);
|
||||
if (!rembCols3.includes('distribution_nature')) {
|
||||
db.exec('ALTER TABLE remboursements ADD COLUMN distribution_nature TEXT');
|
||||
}
|
||||
}
|
||||
|
||||
export default db;
|
||||
@@ -110,7 +110,14 @@ router.get('/', (req, res) => {
|
||||
WHERE v.investissement_pe_id = ipe.id
|
||||
ORDER BY v.date_valorisation DESC, v.id DESC LIMIT 1) AS derniere_valorisation_date,
|
||||
COALESCE((SELECT SUM(r.net_recu) FROM remboursements r
|
||||
WHERE r.investissement_pe_id = ipe.id), 0) AS distributions_cumulees
|
||||
WHERE r.investissement_pe_id = ipe.id), 0) AS distributions_cumulees,
|
||||
-- Sous-ensemble des distributions ci-dessus classées "intérêt sur capital non déployé"
|
||||
-- (18/09/26, demande Olivier — reconstitue la ligne "Obligation" des captures Fundora,
|
||||
-- distincte de la restitution de capital déployé). Inclus dans distributions_cumulees ET
|
||||
-- dans le TVPI (valeur réellement perçue), juste isolé ici pour l'affichage détaillé.
|
||||
COALESCE((SELECT SUM(r.net_recu) FROM remboursements r
|
||||
WHERE r.investissement_pe_id = ipe.id AND r.distribution_nature = 'interet_non_deploye'), 0)
|
||||
AS obligation_cumulee
|
||||
FROM investissements_pe ipe
|
||||
JOIN plateformes p ON p.id = ipe.plateforme_id
|
||||
JOIN investisseurs inv ON inv.id = ipe.investisseur_id
|
||||
@@ -212,7 +219,14 @@ router.get('/:id', (req, res, next) => {
|
||||
WHERE v.investissement_pe_id = ipe.id
|
||||
ORDER BY v.date_valorisation DESC, v.id DESC LIMIT 1) AS derniere_valorisation_date,
|
||||
COALESCE((SELECT SUM(r.net_recu) FROM remboursements r
|
||||
WHERE r.investissement_pe_id = ipe.id), 0) AS distributions_cumulees
|
||||
WHERE r.investissement_pe_id = ipe.id), 0) AS distributions_cumulees,
|
||||
-- Sous-ensemble des distributions ci-dessus classées "intérêt sur capital non déployé"
|
||||
-- (18/09/26, demande Olivier — reconstitue la ligne "Obligation" des captures Fundora,
|
||||
-- distincte de la restitution de capital déployé). Inclus dans distributions_cumulees ET
|
||||
-- dans le TVPI (valeur réellement perçue), juste isolé ici pour l'affichage détaillé.
|
||||
COALESCE((SELECT SUM(r.net_recu) FROM remboursements r
|
||||
WHERE r.investissement_pe_id = ipe.id AND r.distribution_nature = 'interet_non_deploye'), 0)
|
||||
AS obligation_cumulee
|
||||
FROM investissements_pe ipe
|
||||
JOIN plateformes p ON p.id = ipe.plateforme_id
|
||||
JOIN investisseurs inv ON inv.id = ipe.investisseur_id
|
||||
|
||||
@@ -20,6 +20,12 @@ const Schema = z.object({
|
||||
// plateforme (ex. Fundora) — cf. project_workspaces_transformation.md.
|
||||
// Sans effet sur le type 'normal' (crowdlending).
|
||||
investissement_pe_id: z.number().int().positive().nullable().optional(),
|
||||
// Nature de la distribution pour un deal PE (18/09/26, demande Olivier) : 'capital' = restitution
|
||||
// du capital déployé, 'interet_non_deploye' = intérêt versé sur le capital NON déployé (support
|
||||
// obligataire du fonds) — cf. migration distribution_nature dans db/index.js. Optionnel : une
|
||||
// distribution non classée reste comptée dans "Distributions" (pas "Obligation") côté PE. Sans
|
||||
// effet hors type 'interets_plateforme'.
|
||||
distribution_nature: z.enum(['capital', 'interet_non_deploye']).nullable().optional(),
|
||||
date_remb: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
||||
capital: z.number().nonnegative().default(0),
|
||||
cashback: z.number().nonnegative().default(0),
|
||||
@@ -337,14 +343,15 @@ router.post('/', (req, res, next) => {
|
||||
INSERT INTO remboursements
|
||||
(type, bonus_plateforme_id, bonus_investisseur_id, date_remb,
|
||||
capital, cashback, interets_bruts_avant_local, taxe_locale, interets_bruts, frais_ttc,
|
||||
prelev_sociaux, prelev_forfaitaire, interets_nets, net_recu, statut, source, notes, workspace_id, investissement_pe_id)
|
||||
VALUES ('interets_plateforme',?,?,?, 0,0,?,?,?,?,?,?, ?,?, ?, 'manuel', ?, ?, ?)
|
||||
prelev_sociaux, prelev_forfaitaire, interets_nets, net_recu, statut, source, notes, workspace_id,
|
||||
investissement_pe_id, distribution_nature)
|
||||
VALUES ('interets_plateforme',?,?,?, 0,0,?,?,?,?,?,?, ?,?, ?, 'manuel', ?, ?, ?, ?)
|
||||
`).run(
|
||||
body.bonus_plateforme_id, bonusInvestisseurId, body.date_remb,
|
||||
body.interets_bruts_avant_local, body.taxe_locale, body.interets_bruts, body.frais_ttc,
|
||||
body.prelev_sociaux, body.prelev_forfaitaire,
|
||||
interets_nets, net_recu, body.statut, body.notes || null,
|
||||
resolveActiveWorkspaceId(req), body.investissement_pe_id ?? null,
|
||||
resolveActiveWorkspaceId(req), body.investissement_pe_id ?? null, body.distribution_nature ?? null,
|
||||
);
|
||||
return res.status(201).json({ id: r.lastInsertRowid, ...body, interets_nets, net_recu });
|
||||
}
|
||||
@@ -513,12 +520,13 @@ router.put('/:id', (req, res, next) => {
|
||||
UPDATE remboursements
|
||||
SET date_remb=?, interets_bruts_avant_local=?, taxe_locale=?, interets_bruts=?, frais_ttc=?,
|
||||
prelev_sociaux=?, prelev_forfaitaire=?, interets_nets=?, net_recu=?, statut=?, notes=?,
|
||||
investissement_pe_id=?
|
||||
investissement_pe_id=?, distribution_nature=?
|
||||
WHERE id=?
|
||||
`).run(
|
||||
body.date_remb, body.interets_bruts_avant_local, body.taxe_locale, body.interets_bruts, body.frais_ttc,
|
||||
body.prelev_sociaux, body.prelev_forfaitaire,
|
||||
interets_nets, net_recu, body.statut, body.notes || null, body.investissement_pe_id ?? null, id,
|
||||
interets_nets, net_recu, body.statut, body.notes || null, body.investissement_pe_id ?? null,
|
||||
body.distribution_nature ?? null, id,
|
||||
);
|
||||
} else {
|
||||
const bonusInvestisseurId = body.bonus_investisseur_id ?? existing.bonus_investisseur_id;
|
||||
|
||||
Reference in new issue
Block a user