Lien comptes courants / enveloppes
This commit is contained in:
1 parent
f507163369
commit
9591ae400e
13 files changed
+202
-79
No files matched your search
+94
-12
@@ -2263,11 +2263,24 @@ console.log('[DB] Migrations 2FA OK');
|
||||
WHERE i.is_principal = 1
|
||||
AND NOT EXISTS (SELECT 1 FROM comptes c WHERE c.investisseur_id = i.id)
|
||||
`).all();
|
||||
for (const inv of principalsWithoutCompte) {
|
||||
db.prepare(
|
||||
'INSERT INTO comptes (user_id, nom, type, investisseur_id) VALUES (?,?,?,?)'
|
||||
).run(inv.user_id, `Compte courant — ${inv.nom}`, 'compte_courant', inv.investisseur_id);
|
||||
console.log(`[DB] backfill: compte courant créé pour l'investisseur principal #${inv.investisseur_id} (user #${inv.user_id})`);
|
||||
if (principalsWithoutCompte.length > 0) {
|
||||
// Rattache directement l'enveloppe "Compte courant non rémunéré" et marque le compte comme
|
||||
// compte de règlement par défaut (28/09/26 (suite), fusion Type/Enveloppe demandée par
|
||||
// Olivier). Ce bloc de backfill s'exécute AVANT la création de enveloppes_referentiel plus
|
||||
// bas dans ce fichier — garde d'existence de table pour ne jamais casser un premier
|
||||
// démarrage sur base neuve (où principalsWithoutCompte est de toute façon vide).
|
||||
const enveloppesTableExiste = db.prepare(
|
||||
"SELECT COUNT(*) AS n FROM sqlite_master WHERE type='table' AND name='enveloppes_referentiel'"
|
||||
).get().n > 0;
|
||||
const enveloppeCompteCourantNonRemunere = enveloppesTableExiste
|
||||
? db.prepare("SELECT id FROM enveloppes_referentiel WHERE nom = 'Compte courant non rémunéré'").get()
|
||||
: null;
|
||||
for (const inv of principalsWithoutCompte) {
|
||||
db.prepare(
|
||||
'INSERT INTO comptes (user_id, nom, type, enveloppe_id, investisseur_id, compte_reglement_par_defaut) VALUES (?,?,?,?,?,1)'
|
||||
).run(inv.user_id, `Compte courant — ${inv.nom}`, 'compte_courant', enveloppeCompteCourantNonRemunere?.id ?? null, inv.investisseur_id);
|
||||
console.log(`[DB] backfill: compte courant créé pour l'investisseur principal #${inv.investisseur_id} (user #${inv.user_id})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4134,13 +4147,13 @@ db.prepare("DELETE FROM supports_referentiel WHERE nom = 'Gestion pilotée / man
|
||||
// ── Migration : enveloppe_id sur comptes (Phase 3a, 28/09/26, demande Olivier) ────────────
|
||||
// Rattache un compte au référentiel enveloppes_referentiel — nullable, non-destructif, sur le
|
||||
// même principe que comptes.institution_id (Phase 2, cf. plan de déploiement Institutions
|
||||
// financières) : le champ `type` existant (compte_courant/pea_pme) reste en base tel quel et
|
||||
// continue de piloter la logique de remboursement/frais déjà en place (de nombreux écrans
|
||||
// investissement/remboursement font comptes.find(c => c.type === 'compte_courant') pour
|
||||
// proposer un compte de règlement par défaut) — enveloppe_id est un enrichissement PUREMENT
|
||||
// descriptif, ajouté à côté du champ type, jamais en remplacement, pour ne rien casser de cette
|
||||
// logique existante. Restreint aux enveloppes "compte financier" (eligible_compte = 1) côté
|
||||
// sélecteur frontend uniquement — pas de contrainte CHECK en base, pour rester simple.
|
||||
// financières). À l'origine ajouté PUREMENT à côté du champ `type` existant (compte_courant/
|
||||
// pea_pme), qui pilotait alors seul la logique de sélection d'un compte de règlement par défaut
|
||||
// sur les remboursements/frais. Depuis la migration compte_reglement_par_defaut plus bas dans ce
|
||||
// fichier (28/09/26 (suite), fusion Type/Enveloppe demandée par Olivier), c'est ce nouveau
|
||||
// booléen dédié qui pilote cette logique — `type` reste en base mais n'est plus lu nulle part.
|
||||
// Restreint aux enveloppes "compte financier" (eligible_compte = 1) côté sélecteur frontend
|
||||
// uniquement — pas de contrainte CHECK en base, pour rester simple.
|
||||
{
|
||||
const cols = db.prepare('PRAGMA table_info(comptes)').all().map(c => c.name);
|
||||
if (!cols.includes('enveloppe_id')) {
|
||||
@@ -4204,4 +4217,73 @@ db.exec(`
|
||||
db.exec('CREATE INDEX IF NOT EXISTS idx_emprunts_user ON emprunts(user_id)');
|
||||
db.exec('CREATE INDEX IF NOT EXISTS idx_emprunts_inv ON emprunts(investisseur_id)');
|
||||
|
||||
// ── Migration : compte_reglement_par_defaut sur comptes (28/09/26 (suite), demande Olivier —
|
||||
// fusion Type/Enveloppe) ──────────────────────────────────────────────────────────────────
|
||||
// Après la Phase 3a, Olivier a demandé d'aller plus loin : éliminer la redondance entre le
|
||||
// champ `type` (compte_courant/pea_pme, 2 valeurs codées en dur) et le rattachement au
|
||||
// référentiel `enveloppe_id` (cf. migration ci-dessus). Exploration du code réel (28/09/26) :
|
||||
// `type` n'a en réalité qu'UN SEUL consommateur métier dans toute l'application — la sélection
|
||||
// d'un compte de règlement par défaut pour un investisseur (comptes.find(c => c.type ===
|
||||
// 'compte_courant'), 7 emplacements frontend + 1 requête backend de rattrapage, tous avec un
|
||||
// repli sur le premier compte sinon). Toutes les autres occurrences de la chaîne
|
||||
// "compte_courant"/"pea_pme" dans le code appartiennent à des champs sans rapport
|
||||
// (methode_remboursement/mode_reglement sur remboursements/frais/investissements,
|
||||
// mode_detention côté Private Equity) et ne sont pas concernées par ce changement.
|
||||
// Remplacement choisi (validé par Olivier via AskUserQuestion, 28/09/26) : un booléen dédié
|
||||
// plutôt qu'une dérivation depuis le nom de l'enveloppe — découplé du choix d'enveloppe, donc
|
||||
// valable même si un jour un compte de règlement par défaut n'est pas un "compte courant" au
|
||||
// sens strict (ex. un livret ou un compte rémunéré fintech). `type` reste en base, non-destructif
|
||||
// comme toujours dans ce chantier, mais n'est plus lu par aucune logique ni affiché/modifiable
|
||||
// dans l'UI (Paramètres > Mes comptes courants) à partir de cette migration.
|
||||
{
|
||||
const cols = db.prepare('PRAGMA table_info(comptes)').all().map(c => c.name);
|
||||
if (!cols.includes('compte_reglement_par_defaut')) {
|
||||
db.exec('ALTER TABLE comptes ADD COLUMN compte_reglement_par_defaut INTEGER NOT NULL DEFAULT 0');
|
||||
// Backfill exécuté une seule fois, dans cette même garde de colonne : reproduit exactement
|
||||
// le comportement actuel (comptes.find(c => c.type === 'compte_courant')) pour chaque
|
||||
// investisseur ayant déjà un compte de type compte_courant — le premier par id, comme le
|
||||
// faisait `.find()` côté frontend. Une édition manuelle ultérieure n'est ensuite jamais
|
||||
// réécrasée par ce bloc (qui ne s'exécute qu'une fois, à la création de la colonne).
|
||||
const investisseurIds = db.prepare(
|
||||
'SELECT DISTINCT investisseur_id FROM comptes WHERE investisseur_id IS NOT NULL'
|
||||
).all().map(r => r.investisseur_id);
|
||||
const findDefault = db.prepare(
|
||||
"SELECT id FROM comptes WHERE investisseur_id = ? AND type = 'compte_courant' ORDER BY id LIMIT 1"
|
||||
);
|
||||
const setDefault = db.prepare('UPDATE comptes SET compte_reglement_par_defaut = 1 WHERE id = ?');
|
||||
db.transaction(() => {
|
||||
for (const invId of investisseurIds) {
|
||||
const row = findDefault.get(invId);
|
||||
if (row) setDefault.run(row.id);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
// ── Backfill : rattachement rétroactif de l'enveloppe "Compte courant non rémunéré" sur
|
||||
// les comptes existants (28/09/26 (suite), demande Olivier) ─────────────────────────────
|
||||
// La fusion Type/Enveloppe ci-dessus câble l'auto-rattachement enveloppe_id +
|
||||
// compte_reglement_par_defaut UNIQUEMENT sur les 4 points de création d'un compte courant
|
||||
// (inscription, invitation, ajout de membre, seed admin) — jamais en rattrapage sur les
|
||||
// comptes déjà existants avant ce chantier, puisque la règle "compte courant → enveloppe
|
||||
// Compte courant non rémunéré" n'existait pas encore au moment où enveloppe_id a été ajouté
|
||||
// (Phase 3a, purement additif, sans valeur par défaut). Olivier a signalé ce trou après coup
|
||||
// (« est-ce que les utilisateurs existants ont migré le compte courant vers la bonne
|
||||
// enveloppe ? ») — corrigé ici par un backfill toujours exécuté, gardé par
|
||||
// enveloppe_id IS NULL : ne touche donc jamais un compte déjà rattaché, que ce soit
|
||||
// manuellement (comme les comptes d'Olivier) ou par une exécution précédente de ce même
|
||||
// bloc. Ne s'applique qu'aux comptes type='compte_courant' — un PEA-PME reste sans
|
||||
// enveloppe automatique, cohérent avec le fait que seuls les comptes courants sont
|
||||
// auto-créés/auto-rattachés par les 4 points de création listés ci-dessus.
|
||||
{
|
||||
const enveloppeCompteCourantNonRemunere = db.prepare(
|
||||
"SELECT id FROM enveloppes_referentiel WHERE nom = 'Compte courant non rémunéré'"
|
||||
).get();
|
||||
if (enveloppeCompteCourantNonRemunere) {
|
||||
db.prepare(
|
||||
"UPDATE comptes SET enveloppe_id = ? WHERE type = 'compte_courant' AND enveloppe_id IS NULL"
|
||||
).run(enveloppeCompteCourantNonRemunere.id);
|
||||
}
|
||||
}
|
||||
|
||||
export default db;
|
||||
Reference in new issue
Block a user