Correctif
This commit is contained in:
1 parent
0334a63139
commit
981ddf5830
7 files changed
+115
-42
No files matched your search
@@ -8,7 +8,10 @@ import { requireAdmin } from '../middleware/auth.js';
|
||||
import sharp from 'sharp';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const iconsDir = path.resolve(__dirname, '../../../data/icons');
|
||||
const dataDir = process.env.DATA_DIR
|
||||
? path.resolve(process.env.DATA_DIR)
|
||||
: path.resolve(__dirname, '../../../data'); // fallback dev : 3 niveaux au-dessus de routes/
|
||||
const iconsDir = path.join(dataDir, 'icons');
|
||||
const historyDir = path.resolve(iconsDir, 'history');
|
||||
fs.mkdirSync(iconsDir, { recursive: true });
|
||||
fs.mkdirSync(historyDir, { recursive: true });
|
||||
|
||||
@@ -10,7 +10,10 @@ import fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const logosDir = path.resolve(__dirname, '../../../data/logos');
|
||||
const dataDir = process.env.DATA_DIR
|
||||
? path.resolve(process.env.DATA_DIR)
|
||||
: path.resolve(__dirname, '../../../data'); // fallback dev : 3 niveaux au-dessus de routes/
|
||||
const logosDir = path.join(dataDir, 'logos');
|
||||
fs.mkdirSync(logosDir, { recursive: true });
|
||||
|
||||
/** Sanitise un nom de plateforme pour en faire un nom de fichier safe */
|
||||
|
||||
@@ -17,12 +17,13 @@ const round2 = v => Math.round((v ?? 0) * 100) / 100;
|
||||
* n'est pas soldé. Seuls les champs `interets.*` peuvent être filtrés
|
||||
* par année via `?annee=`. `gain_net_depuis_debut` est TOUJOURS un cumul
|
||||
* total (indépendant de `?annee=`) : intérêts nets + cashback/bonus de
|
||||
* parrainage ou de plateforme + corrections de solde − frais réglés hors
|
||||
* remboursement (porte-monnaie ou compte courant du détenteur, cf.
|
||||
* /frais-operations — le détail est dans `gain_net_depuis_debut.frais_hors_remboursement`),
|
||||
* sur tout l'historique du portefeuille — reste valable même après un retrait
|
||||
* complet des plateformes, contrairement à une approche basée sur le
|
||||
* solde courant.
|
||||
* parrainage ou de plateforme + corrections de solde − tous les frais réellement payés en
|
||||
* dehors du passage brut → net d'un remboursement (à la souscription, porte-monnaie ou
|
||||
* compte courant du détenteur — cf. /frais-operations ; seul le mode "remboursement" est
|
||||
* exclu, déjà déduit des intérêts nets ci-dessus). Détail dans
|
||||
* `gain_net_depuis_debut.frais_hors_remboursement`. Sur tout l'historique du portefeuille —
|
||||
* reste valable même après un retrait complet des plateformes, contrairement à une approche
|
||||
* basée sur le solde courant.
|
||||
* tags: [Dashboard]
|
||||
* security: [{ ApiKeyAuth: [] }]
|
||||
* parameters:
|
||||
@@ -123,16 +124,24 @@ router.get('/', (req, res) => {
|
||||
WHERE ${invCond('investisseur_id')}
|
||||
`).get(invParam);
|
||||
|
||||
// ── Frais hors remboursement (Étape 5, 01/09/26 — cf. project_gain_net_depuis_debut.md) :
|
||||
// les frais réglés en mode "portefeuille" ou "compte_courant" sont une sortie d'argent réelle
|
||||
// et séparée des remboursements (contrairement au mode "remboursement", déjà déduit de
|
||||
// interets_nets ci-dessus) — ils doivent donc être soustraits du gain net, en miroir exact du
|
||||
// correctif appliqué au KPI "Gain net depuis le début" de l'app interne (Dashboard.jsx).
|
||||
// ── Frais hors remboursement (Étape 5, 02/09/26 — cf. project_gain_net_depuis_debut.md) :
|
||||
// tout frais réel payé par l'investisseur SAUF ceux retenus directement sur un remboursement
|
||||
// (mode "remboursement") est soustrait ici — ceux-là sont déjà déduits de interets_nets
|
||||
// ci-dessus au moment du passage brut → net par la plateforme (ex. Fundora), les soustraire une
|
||||
// 2ᵉ fois créerait une double déduction qui ne correspond à aucune sortie d'argent réelle
|
||||
// supplémentaire. Les modes "source" (déduit du versement à la souscription — déjà netté dans
|
||||
// montant_investi, une donnée de capital que ce total n'utilise jamais), "portefeuille" et
|
||||
// "compte_courant" sont chacun une vraie sortie d'argent jamais reflétée ailleurs dans cette
|
||||
// somme (qui ne comporte que des flux de revenu), donc tous les trois doivent être déduits — en
|
||||
// miroir exact du correctif appliqué au KPI "Gain net depuis le début" de l'app interne
|
||||
// (Dashboard.jsx). Ne pas réutiliser le filtre ('portefeuille','compte_courant') du XIRR net :
|
||||
// celui-ci exclut "source" pour une raison propre au XIRR (déjà représenté par un flux de
|
||||
// capital investi plus petit à t0), qui ne s'applique pas ici.
|
||||
const fraisHorsRembRow = db.prepare(`
|
||||
SELECT COALESCE(SUM(f.montant), 0) AS total
|
||||
FROM frais_operations f
|
||||
JOIN investissements i ON i.id = f.investissement_id
|
||||
WHERE f.mode_reglement IN ('portefeuille','compte_courant') AND ${invCond('i.investisseur_id')}
|
||||
WHERE f.mode_reglement != 'remboursement' AND ${invCond('i.investisseur_id')}
|
||||
`).get(invParam);
|
||||
|
||||
const gainNetTotal = round2(
|
||||
|
||||
@@ -18,9 +18,9 @@ const router = Router();
|
||||
* détenteur (`compte_nom`), sans impact sur le porte-monnaie ; "remboursement" : retenu
|
||||
* directement sur le remboursement lié (`remboursement_id`), déjà pris en compte dans les
|
||||
* champs `interets_nets`/`net_recu` de ce remboursement — ne pas le compter une seconde
|
||||
* fois. Seuls les modes "portefeuille" et "compte_courant" représentent une sortie
|
||||
* d'argent réelle et séparée (c'est ce sous-ensemble qui est déduit de
|
||||
* `gain_net_depuis_debut` sur /dashboard).
|
||||
* fois. Tous les autres modes ("source", "portefeuille", "compte_courant")
|
||||
* représentent chacun une sortie d'argent réelle (c'est cet ensemble — tout sauf
|
||||
* "remboursement" — qui est déduit de `gain_net_depuis_debut` sur /dashboard).
|
||||
* tags: [Frais]
|
||||
* security: [{ ApiKeyAuth: [] }]
|
||||
* parameters:
|
||||
|
||||
Reference in new issue
Block a user