import { Router } from 'express'; import { z } from 'zod'; import db from '../db/index.js'; import { HttpError } from '../middleware/errorHandler.js'; const router = Router(); const Schema = z.object({ nom: z.string().min(1), prenom: z.string().optional().or(z.literal('')), type: z.enum(['famille', 'entreprise']).default('famille'), type_fiscal: z.string().optional(), notes: z.string().optional(), }); router.get('/', (req, res) => { const rows = db .prepare( `SELECT id, nom, prenom, type, type_fiscal, is_principal, notes, created_at FROM investisseurs WHERE user_id = ? ORDER BY is_principal DESC, type, nom` ) .all(req.user.id); res.json(rows); }); router.post('/', (req, res, next) => { try { const body = Schema.parse(req.body); const r = db .prepare( 'INSERT INTO investisseurs (user_id, nom, prenom, type, type_fiscal, notes) VALUES (?,?,?,?,?,?)' ) .run( req.user.id, body.nom, body.prenom || null, body.type, body.type_fiscal || null, body.notes || null, ); const invId = r.lastInsertRowid; // Auto-créer un compte courant pour ce nouveau profil // body.nom contient déjà le nom complet (ex. "Marine CROGUENNEC") const label = `Compte courant — ${body.nom}`; db.prepare( 'INSERT INTO comptes (user_id, nom, type, investisseur_id) VALUES (?,?,?,?)' ).run(req.user.id, label, 'compte_courant', invId); res.status(201).json({ id: invId, ...body }); } catch (e) { next(e); } }); router.put('/:id', (req, res, next) => { try { const body = Schema.parse(req.body); const r = db .prepare( `UPDATE investisseurs SET nom=?, prenom=?, type=?, type_fiscal=?, notes=?, updated_at=datetime('now') WHERE id=? AND user_id=?` ) .run( body.nom, body.prenom || null, body.type, body.type_fiscal || null, body.notes || null, req.params.id, req.user.id, ); if (r.changes === 0) throw new HttpError(404, 'Not found'); res.json({ id: Number(req.params.id), ...body }); } catch (e) { next(e); } }); router.post('/reassign-to-principal', (req, res, next) => { try { const principal = db .prepare('SELECT id FROM investisseurs WHERE user_id = ? AND is_principal = 1') .get(req.user.id); if (!principal) throw new HttpError(400, 'Aucun compte principal trouvé.'); const principalId = principal.id; const userId = req.user.id; const reassign = db.transaction(() => { db.prepare( `UPDATE investissements SET investisseur_id = ? WHERE investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?) AND investisseur_id != ?` ).run(principalId, userId, principalId); db.prepare( `UPDATE depots_retraits SET investisseur_id = ? WHERE investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?) AND investisseur_id != ?` ).run(principalId, userId, principalId); }); reassign(); res.json({ ok: true, principal_id: principalId }); } catch (e) { next(e); } }); router.delete('/:id', (req, res, next) => { try { // Empêcher la suppression du compte principal const target = db .prepare('SELECT id, is_principal FROM investisseurs WHERE id=? AND user_id=?') .get(req.params.id, req.user.id); if (!target) throw new HttpError(404, 'Not found'); if (target.is_principal) throw new HttpError(400, 'Impossible de supprimer le compte principal.'); // Empêcher la suppression si c'est le seul membre const count = db .prepare('SELECT COUNT(*) AS n FROM investisseurs WHERE user_id=?') .get(req.user.id).n; if (count <= 1) throw new HttpError(400, 'Impossible de supprimer le dernier profil.'); const r = db .prepare('DELETE FROM investisseurs WHERE id=? AND user_id=?') .run(req.params.id, req.user.id); if (r.changes === 0) throw new HttpError(404, 'Not found'); res.status(204).end(); } catch (e) { next(e); } }); export default router;