Maj Phase 2 - Institutions financières
This commit is contained in:
1 parent
1dcb33aa74
commit
b18ffc63ee
18 files changed
+383
-16
No files matched your search
@@ -832,4 +832,90 @@ router.post('/exports/:filename/restore', async (req, res, next) => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/* ── Comptes orphelins (banque texte libre non reliée au référentiel institutions) ───────
|
||||
Phase 2 du chantier "Référentiel Institutions financières" (cf. plan de déploiement, doc
|
||||
projet claude/plan_referentiel_institutions_financieres.md). Contrairement aux plateformes
|
||||
orphelines (une ligne par plateforme), ici on regroupe par valeur `banque` distincte car
|
||||
plusieurs comptes (potentiellement de plusieurs utilisateurs) partagent souvent le même
|
||||
texte libre — Lier/Importer agit donc sur tous les comptes portant cette valeur d'un coup. */
|
||||
|
||||
/** Liste les valeurs `banque` distinctes non reliées à institution_id, avec suggestion */
|
||||
router.get('/comptes-orphelins', (_req, res) => {
|
||||
const rows = db.prepare(`
|
||||
SELECT c.banque, u.id AS user_id, u.email AS user_email, u.display_name AS user_display_name, COUNT(*) AS nb
|
||||
FROM comptes c
|
||||
JOIN users u ON u.id = c.user_id
|
||||
WHERE c.institution_id IS NULL AND c.banque IS NOT NULL AND TRIM(c.banque) != ''
|
||||
GROUP BY c.banque, u.id
|
||||
ORDER BY c.banque, u.email
|
||||
`).all();
|
||||
|
||||
const byBanque = {};
|
||||
for (const r of rows) {
|
||||
if (!byBanque[r.banque]) byBanque[r.banque] = { banque: r.banque, total: 0, users: [] };
|
||||
byBanque[r.banque].total += r.nb;
|
||||
byBanque[r.banque].users.push({ id: r.user_id, email: r.user_email, display_name: r.user_display_name, nb: r.nb });
|
||||
}
|
||||
|
||||
const refs = db.prepare('SELECT id, nom FROM institutions_referentiel ORDER BY nom').all();
|
||||
|
||||
const enriched = Object.values(byBanque).map(g => {
|
||||
let bestRef = null, bestScore = 0;
|
||||
for (const ref of refs) {
|
||||
const score = similarity(g.banque, ref.nom);
|
||||
if (score > bestScore) { bestScore = score; bestRef = ref; }
|
||||
}
|
||||
return {
|
||||
...g,
|
||||
suggestion: bestScore >= SIMILARITY_THRESHOLD
|
||||
? { institution_id: bestRef.id, institution_nom: bestRef.nom, score: Math.round(bestScore * 100) }
|
||||
: null,
|
||||
};
|
||||
}).sort((a, b) => a.banque.localeCompare(b.banque, 'fr'));
|
||||
|
||||
res.json(enriched);
|
||||
});
|
||||
|
||||
/** Lie tous les comptes portant cette valeur `banque` à une institution existante du référentiel */
|
||||
router.post('/comptes-orphelins/lier', (req, res, next) => {
|
||||
try {
|
||||
const { banque, institution_id } = z.object({
|
||||
banque: z.string().min(1),
|
||||
institution_id: z.number().int().positive(),
|
||||
}).parse(req.body);
|
||||
|
||||
const ref = db.prepare('SELECT * FROM institutions_referentiel WHERE id = ?').get(institution_id);
|
||||
if (!ref) throw new HttpError(404, 'Institution introuvable');
|
||||
|
||||
const r = db.prepare(
|
||||
'UPDATE comptes SET institution_id = ? WHERE banque = ? AND institution_id IS NULL'
|
||||
).run(institution_id, banque);
|
||||
|
||||
res.json({ linked: true, nb_comptes: r.changes, institution: ref });
|
||||
} catch (e) { next(e); }
|
||||
});
|
||||
|
||||
/** Crée une nouvelle institution dans le référentiel à partir de la valeur `banque`, et lie
|
||||
tous les comptes correspondants (ou lie simplement si une institution de ce nom existe déjà) */
|
||||
router.post('/comptes-orphelins/importer', (req, res, next) => {
|
||||
try {
|
||||
const { banque } = z.object({ banque: z.string().min(1) }).parse(req.body);
|
||||
|
||||
let ref = db.prepare('SELECT * FROM institutions_referentiel WHERE nom = ?').get(banque);
|
||||
let created = false;
|
||||
if (!ref) {
|
||||
const r = db.prepare('INSERT INTO institutions_referentiel (nom) VALUES (?)').run(banque);
|
||||
ref = db.prepare('SELECT * FROM institutions_referentiel WHERE id = ?').get(r.lastInsertRowid);
|
||||
created = true;
|
||||
}
|
||||
|
||||
const upd = db.prepare(
|
||||
'UPDATE comptes SET institution_id = ? WHERE banque = ? AND institution_id IS NULL'
|
||||
).run(ref.id, banque);
|
||||
|
||||
res.status(created ? 201 : 200).json({ linked: true, created, nb_comptes: upd.changes, institution: ref });
|
||||
} catch (e) { next(e); }
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in new issue
Block a user