Initial commit
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { Router } from 'express';
|
||||
import { z } from 'zod';
|
||||
import db from '../db/index.js';
|
||||
import { HttpError } from '../middleware/errorHandler.js';
|
||||
|
||||
const router = Router();
|
||||
// Monté sous requireAuth dans server.js
|
||||
|
||||
/* ─────────────────────────────────────────────────────────────
|
||||
GET /api/categories-inv
|
||||
Retourne les catégories globales (user_id IS NULL) + privées
|
||||
de l'utilisateur connecté.
|
||||
Chaque entrée : { id, nom, is_global, nb_plateformes, nb_investissements }
|
||||
───────────────────────────────────────────────────────────────*/
|
||||
router.get('/', (req, res) => {
|
||||
const userId = req.user.id;
|
||||
const rows = db.prepare(`
|
||||
SELECT
|
||||
c.id,
|
||||
c.nom,
|
||||
CASE WHEN c.user_id IS NULL THEN 1 ELSE 0 END AS is_global,
|
||||
(SELECT COUNT(*) FROM plateforme_categories_inv pc WHERE pc.categorie_id = c.id
|
||||
AND pc.plateforme_id IN (
|
||||
SELECT p.id FROM plateformes p
|
||||
JOIN investisseurs i ON i.id = p.investisseur_id
|
||||
WHERE i.user_id = ?
|
||||
)
|
||||
) AS nb_plateformes,
|
||||
(SELECT COUNT(*) FROM investissement_categories_inv ic WHERE ic.categorie_id = c.id
|
||||
AND ic.investissement_id IN (
|
||||
SELECT inv.id FROM investissements inv
|
||||
JOIN investisseurs i ON i.id = inv.investisseur_id
|
||||
WHERE i.user_id = ?
|
||||
)
|
||||
) AS nb_investissements
|
||||
FROM categories_inv c
|
||||
WHERE c.user_id IS NULL OR c.user_id = ?
|
||||
ORDER BY is_global DESC, c.nom
|
||||
`).all(userId, userId, userId);
|
||||
res.json(rows);
|
||||
});
|
||||
|
||||
/* ─────────────────────────────────────────────────────────────
|
||||
POST /api/categories-inv — créer une catégorie privée
|
||||
───────────────────────────────────────────────────────────────*/
|
||||
router.post('/', (req, res, next) => {
|
||||
try {
|
||||
const { nom } = z.object({ nom: z.string().min(1).max(200) }).parse(req.body);
|
||||
const userId = req.user.id;
|
||||
const dup = db.prepare(
|
||||
'SELECT id FROM categories_inv WHERE nom = ? AND (user_id IS NULL OR user_id = ?)'
|
||||
).get(nom.trim(), userId);
|
||||
if (dup) throw new HttpError(409, `La catégorie "${nom.trim()}" existe déjà.`);
|
||||
const r = db.prepare(
|
||||
'INSERT INTO categories_inv (nom, user_id) VALUES (?, ?)'
|
||||
).run(nom.trim(), userId);
|
||||
res.status(201).json({ id: r.lastInsertRowid, nom: nom.trim(), is_global: 0, nb_plateformes: 0, nb_investissements: 0 });
|
||||
} catch (e) { next(e); }
|
||||
});
|
||||
|
||||
/* ─────────────────────────────────────────────────────────────
|
||||
PUT /api/categories-inv/:id — renommer (uniquement les privées)
|
||||
───────────────────────────────────────────────────────────────*/
|
||||
router.put('/:id', (req, res, next) => {
|
||||
try {
|
||||
const { nom } = z.object({ nom: z.string().min(1).max(200) }).parse(req.body);
|
||||
const userId = req.user.id;
|
||||
const row = db.prepare('SELECT id, nom, user_id FROM categories_inv WHERE id = ?').get(req.params.id);
|
||||
if (!row) throw new HttpError(404, 'Catégorie introuvable');
|
||||
if (row.user_id === null) throw new HttpError(403, 'Les catégories globales ne peuvent pas être modifiées.');
|
||||
if (row.user_id !== userId) throw new HttpError(403, 'Cette catégorie ne vous appartient pas.');
|
||||
const dup = db.prepare(
|
||||
'SELECT id FROM categories_inv WHERE nom = ? AND (user_id IS NULL OR user_id = ?) AND id != ?'
|
||||
).get(nom.trim(), userId, row.id);
|
||||
if (dup) throw new HttpError(409, `La catégorie "${nom.trim()}" existe déjà.`);
|
||||
db.prepare('UPDATE categories_inv SET nom = ? WHERE id = ?').run(nom.trim(), row.id);
|
||||
res.json({ id: row.id, nom: nom.trim(), is_global: 0 });
|
||||
} catch (e) { next(e); }
|
||||
});
|
||||
|
||||
/* ─────────────────────────────────────────────────────────────
|
||||
DELETE /api/categories-inv/:id — supprimer (uniquement les privées)
|
||||
───────────────────────────────────────────────────────────────*/
|
||||
router.delete('/:id', (req, res, next) => {
|
||||
try {
|
||||
const userId = req.user.id;
|
||||
const row = db.prepare('SELECT id, user_id FROM categories_inv WHERE id = ?').get(req.params.id);
|
||||
if (!row) throw new HttpError(404, 'Catégorie introuvable');
|
||||
if (row.user_id === null) throw new HttpError(403, 'Les catégories globales ne peuvent pas être supprimées.');
|
||||
if (row.user_id !== userId) throw new HttpError(403, 'Cette catégorie ne vous appartient pas.');
|
||||
|
||||
// Retirer des associations avant suppression
|
||||
db.transaction(() => {
|
||||
db.prepare('DELETE FROM plateforme_categories_inv WHERE categorie_id = ?').run(row.id);
|
||||
db.prepare('DELETE FROM investissement_categories_inv WHERE categorie_id = ?').run(row.id);
|
||||
db.prepare('DELETE FROM categories_inv WHERE id = ?').run(row.id);
|
||||
})();
|
||||
res.status(204).end();
|
||||
} catch (e) { next(e); }
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user