127 lines
4.0 KiB
JavaScript
127 lines
4.0 KiB
JavaScript
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;
|