Nouvelles features: revision des conditions des prêts

This commit is contained in:
2026-07-12 19:14:27 +02:00
parent ef4576d160
commit 96effbe15a
5 changed files with 552 additions and 7 deletions
+35
View File
@@ -429,6 +429,41 @@ db.exec(`
)
`);
// ── Migration : table des révisions de conditions de prêt (taux/date) ───
// Distincte de investissement_historique (qui est une piste d'audit générique
// auto-détectée sur tout changement de champ). Ici, on trace un événement métier
// explicite (retard projet, renégociation…) avec un motif obligatoire, et qui
// déclenche la régénération de l'échéancier (cf. routes/investissements.js).
db.exec(`
CREATE TABLE IF NOT EXISTS investissement_revisions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
investissement_id INTEGER NOT NULL REFERENCES investissements(id) ON DELETE CASCADE,
date_effet TEXT NOT NULL,
ancien_taux REAL,
nouveau_taux REAL,
ancienne_date_cible TEXT,
nouvelle_date_cible TEXT,
motif TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)
`);
db.exec('CREATE INDEX IF NOT EXISTS idx_revisions_inv ON investissement_revisions(investissement_id)');
// ── Migration : traçage de la durée lors d'une révision de date cible ────
// nouvelle_date_cible ne suffisait pas à elle seule à modifier l'échéancier généré
// (generateSimul se base sur duree_mois, pas sur date_cible). Quand une révision change
// la date cible, duree_mois doit être recalculé en conséquence — on trace l'ancienne et
// la nouvelle valeur ici pour permettre un rollback fidèle (DELETE /revisions/:rid).
{
const revCols = db.prepare('PRAGMA table_info(investissement_revisions)').all().map(c => c.name);
if (!revCols.includes('ancien_duree_mois')) {
db.exec('ALTER TABLE investissement_revisions ADD COLUMN ancien_duree_mois INTEGER');
}
if (!revCols.includes('nouveau_duree_mois')) {
db.exec('ALTER TABLE investissement_revisions ADD COLUMN nouveau_duree_mois INTEGER');
}
}
// ── Migration : rôle utilisateur ─────────────────────────────────────────
{
const userCols = db.prepare('PRAGMA table_info(users)').all().map(c => c.name);