119 lines
4.6 KiB
JavaScript
119 lines
4.6 KiB
JavaScript
import { Router } from 'express';
|
|
import { z } from 'zod';
|
|
import db from '../db/index.js';
|
|
import { HttpError } from '../middleware/errorHandler.js';
|
|
import { requireInvestisseur } from '../middleware/investisseurScope.js';
|
|
|
|
const router = Router();
|
|
|
|
const Schema = z.object({
|
|
investisseur_id: z.number().int().positive().optional(),
|
|
plateforme_id: z.number().int().positive(),
|
|
date_operation: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
type: z.enum(['depot', 'retrait']),
|
|
montant: z.number().nonnegative(),
|
|
libelle: z.string().optional(),
|
|
reference: z.string().optional(),
|
|
notes: z.string().optional(),
|
|
});
|
|
|
|
/** Résout l'investisseur_id : body en priorité (validé), sinon header */
|
|
function resolveInvestisseurId(req, bodyInvestisseurId) {
|
|
if (!bodyInvestisseurId) return req.investisseur.id;
|
|
const row = db.prepare('SELECT id FROM investisseurs WHERE id = ? AND user_id = ?')
|
|
.get(bodyInvestisseurId, req.user.id);
|
|
if (!row) throw new HttpError(403, 'Investisseur non autorisé');
|
|
return bodyInvestisseurId;
|
|
}
|
|
|
|
/**
|
|
* GET /api/depots-retraits
|
|
*
|
|
* ?scope=all → agrège tous les investisseurs de l'utilisateur (vue "Famille")
|
|
* (défaut) → filtre sur l'investisseur donné par X-Investisseur-Id
|
|
*/
|
|
router.get('/', (req, res) => {
|
|
const scopeAll = req.query.scope === 'all';
|
|
const userId = req.user.id;
|
|
|
|
let invCond, args;
|
|
if (scopeAll) {
|
|
invCond = 'dr.investisseur_id IN (SELECT id FROM investisseurs WHERE user_id = ?)';
|
|
args = [userId];
|
|
} else {
|
|
const raw = req.header('X-Investisseur-Id');
|
|
const id = Number(raw);
|
|
if (!id) return res.status(400).json({ error: 'Missing investisseur id (header X-Investisseur-Id)' });
|
|
const row = db.prepare('SELECT id FROM investisseurs WHERE id = ? AND user_id = ?').get(id, userId);
|
|
if (!row) return res.status(403).json({ error: 'Investisseur not found or not owned by user' });
|
|
invCond = 'dr.investisseur_id = ?';
|
|
args = [id];
|
|
}
|
|
|
|
const { from, to, type, plateforme_id } = req.query;
|
|
const conds = [invCond];
|
|
if (from) { conds.push('dr.date_operation >= ?'); args.push(from); }
|
|
if (to) { conds.push('dr.date_operation <= ?'); args.push(to); }
|
|
if (type) { conds.push('dr.type = ?'); args.push(type); }
|
|
if (plateforme_id) { conds.push('dr.plateforme_id = ?'); args.push(Number(plateforme_id)); }
|
|
|
|
const rows = db.prepare(`
|
|
SELECT dr.*, p.nom AS plateforme_nom,
|
|
plat_inv.nom AS plateforme_detenteur_nom
|
|
FROM depots_retraits dr
|
|
JOIN plateformes p ON p.id = dr.plateforme_id
|
|
LEFT JOIN investisseurs plat_inv ON plat_inv.id = p.investisseur_id
|
|
WHERE ${conds.join(' AND ')}
|
|
ORDER BY dr.date_operation DESC, dr.id DESC
|
|
`).all(...args);
|
|
res.json(rows);
|
|
});
|
|
|
|
router.post('/', requireInvestisseur, (req, res, next) => {
|
|
try {
|
|
const body = Schema.parse(req.body);
|
|
const investisseurId = resolveInvestisseurId(req, body.investisseur_id);
|
|
const r = db.prepare(`
|
|
INSERT INTO depots_retraits
|
|
(investisseur_id, plateforme_id, date_operation, type, montant, libelle, reference, source, notes)
|
|
VALUES (?,?,?,?,?,?,?, 'manuel', ?)
|
|
`).run(
|
|
investisseurId, body.plateforme_id, body.date_operation, body.type,
|
|
body.montant, body.libelle || null, body.reference || null, body.notes || null,
|
|
);
|
|
res.status(201).json({ id: r.lastInsertRowid, ...body });
|
|
} catch (e) { next(e); }
|
|
});
|
|
|
|
router.put('/:id', requireInvestisseur, (req, res, next) => {
|
|
try {
|
|
const body = Schema.parse(req.body);
|
|
const investisseurId = resolveInvestisseurId(req, body.investisseur_id);
|
|
const r = db.prepare(`
|
|
UPDATE depots_retraits
|
|
SET investisseur_id=?, plateforme_id=?, date_operation=?, type=?, montant=?,
|
|
libelle=?, reference=?, notes=?, updated_at=datetime('now')
|
|
WHERE id=? AND investisseur_id IN (SELECT id FROM investisseurs WHERE user_id=?)
|
|
`).run(
|
|
investisseurId, body.plateforme_id, body.date_operation, body.type, body.montant,
|
|
body.libelle || null, body.reference || 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.delete('/:id', requireInvestisseur, (req, res, next) => {
|
|
try {
|
|
const r = db.prepare(`
|
|
DELETE FROM depots_retraits
|
|
WHERE id=? AND investisseur_id IN (SELECT id FROM investisseurs WHERE 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;
|