Création de la feature API V1
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { Router } from 'express';
|
||||
import db from '../../db/index.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /dashboard:
|
||||
* get:
|
||||
* summary: Synthèse du portefeuille (KPIs)
|
||||
* tags: [Dashboard]
|
||||
* security: [{ ApiKeyAuth: [] }]
|
||||
* responses:
|
||||
* 200: { description: Synthèse KPI }
|
||||
*/
|
||||
router.get('/', (req, res) => {
|
||||
const invId = req.investisseurId;
|
||||
|
||||
const investissements = db.prepare(`
|
||||
SELECT
|
||||
COUNT(*) AS nb_investissements,
|
||||
COALESCE(SUM(montant_investi), 0) AS total_investi,
|
||||
COALESCE(SUM(CASE WHEN statut='en_cours' THEN montant_investi END), 0) AS encours,
|
||||
COALESCE(SUM(CASE WHEN statut='rembourse' THEN montant_investi END), 0) AS rembourse
|
||||
FROM investissements WHERE investisseur_id = ?
|
||||
`).get(invId);
|
||||
|
||||
const interets = db.prepare(`
|
||||
SELECT
|
||||
COALESCE(SUM(r.interets_bruts), 0) AS interets_bruts,
|
||||
COALESCE(SUM(r.interets_nets), 0) AS interets_nets,
|
||||
COALESCE(SUM(r.capital), 0) AS capital_recu,
|
||||
COALESCE(SUM(r.net_recu), 0) AS net_recu_total
|
||||
FROM remboursements r
|
||||
JOIN investissements i ON i.id = r.investissement_id
|
||||
WHERE i.investisseur_id = ?
|
||||
`).get(invId);
|
||||
|
||||
const cash = db.prepare(`
|
||||
SELECT
|
||||
COALESCE(SUM(CASE WHEN type='depot' THEN montant END), 0) AS total_depots,
|
||||
COALESCE(SUM(CASE WHEN type='retrait' THEN montant END), 0) AS total_retraits
|
||||
FROM depots_retraits WHERE investisseur_id = ?
|
||||
`).get(invId);
|
||||
|
||||
res.json({ investissements, interets, cash });
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Router } from 'express';
|
||||
import db from '../../db/index.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /depots-retraits:
|
||||
* get:
|
||||
* summary: Liste des mouvements de cash (dépôts / retraits)
|
||||
* tags: [Dépôts / Retraits]
|
||||
* security: [{ ApiKeyAuth: [] }]
|
||||
* responses:
|
||||
* 200: { description: Liste des mouvements }
|
||||
*/
|
||||
router.get('/', (req, res) => {
|
||||
const rows = db.prepare(`
|
||||
SELECT dr.id, dr.date_operation, p.nom AS plateforme_nom, dr.type,
|
||||
dr.montant, dr.libelle
|
||||
FROM depots_retraits dr
|
||||
JOIN plateformes p ON p.id = dr.plateforme_id
|
||||
WHERE dr.investisseur_id = ?
|
||||
ORDER BY dr.date_operation DESC
|
||||
`).all(req.investisseurId);
|
||||
res.json(rows);
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Router } from 'express';
|
||||
import investisseurRouter from './investisseur.js';
|
||||
import investissementsRouter from './investissements.js';
|
||||
import remboursementsRouter from './remboursements.js';
|
||||
import depotsRetraitsRouter from './depotsRetraits.js';
|
||||
import dashboardRouter from './dashboard.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use('/investisseur', investisseurRouter);
|
||||
router.use('/investissements', investissementsRouter);
|
||||
router.use('/remboursements', remboursementsRouter);
|
||||
router.use('/depots-retraits', depotsRetraitsRouter);
|
||||
router.use('/dashboard', dashboardRouter);
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,82 @@
|
||||
import { Router } from 'express';
|
||||
import db from '../../db/index.js';
|
||||
import { HttpError } from '../../middleware/errorHandler.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
const LIST_COLUMNS = `
|
||||
i.id, i.nom_projet, i.emetteur, p.nom AS plateforme_nom,
|
||||
i.date_souscription, i.date_premiere_echeance, i.date_cible,
|
||||
i.montant_investi, i.taux_interet, i.duree_mois,
|
||||
i.type_remb, i.freq_interets, i.statut, i.reference
|
||||
`;
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /investissements:
|
||||
* get:
|
||||
* summary: Liste des investissements de l'investisseur
|
||||
* tags: [Investissements]
|
||||
* security: [{ ApiKeyAuth: [] }]
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: statut
|
||||
* schema: { type: string, enum: [en_cours, rembourse, en_retard, procedure, cloture] }
|
||||
* responses:
|
||||
* 200: { description: Liste des investissements }
|
||||
*/
|
||||
router.get('/', (req, res) => {
|
||||
const { statut } = req.query;
|
||||
const conds = ['i.investisseur_id = ?'];
|
||||
const args = [req.investisseurId];
|
||||
if (statut) { conds.push('i.statut = ?'); args.push(statut); }
|
||||
|
||||
const rows = db.prepare(`
|
||||
SELECT ${LIST_COLUMNS}
|
||||
FROM investissements i
|
||||
JOIN plateformes p ON p.id = i.plateforme_id
|
||||
WHERE ${conds.join(' AND ')}
|
||||
ORDER BY i.date_souscription DESC
|
||||
`).all(...args);
|
||||
res.json(rows);
|
||||
});
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /investissements/{id}:
|
||||
* get:
|
||||
* summary: Détail d'un investissement, avec ses remboursements réels
|
||||
* tags: [Investissements]
|
||||
* security: [{ ApiKeyAuth: [] }]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema: { type: integer }
|
||||
* responses:
|
||||
* 200: { description: Détail de l'investissement }
|
||||
* 404: { description: Investissement introuvable }
|
||||
*/
|
||||
router.get('/:id', (req, res, next) => {
|
||||
try {
|
||||
const inv = db.prepare(`
|
||||
SELECT ${LIST_COLUMNS}, i.notes
|
||||
FROM investissements i
|
||||
JOIN plateformes p ON p.id = i.plateforme_id
|
||||
WHERE i.id = ? AND i.investisseur_id = ?
|
||||
`).get(req.params.id, req.investisseurId);
|
||||
if (!inv) throw new HttpError(404, 'Investissement introuvable');
|
||||
|
||||
const remboursements = db.prepare(`
|
||||
SELECT id, date_remb, capital, interets_bruts, prelev_sociaux,
|
||||
prelev_forfaitaire, cashback, interets_nets, net_recu, statut
|
||||
FROM remboursements
|
||||
WHERE investissement_id = ?
|
||||
ORDER BY date_remb
|
||||
`).all(inv.id);
|
||||
|
||||
res.json({ ...inv, remboursements });
|
||||
} catch (e) { next(e); }
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Router } from 'express';
|
||||
import db from '../../db/index.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /investisseur:
|
||||
* get:
|
||||
* summary: Profil de l'investisseur lié à la clé API
|
||||
* tags: [Investisseur]
|
||||
* security: [{ ApiKeyAuth: [] }]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Profil investisseur
|
||||
* 401:
|
||||
* description: Clé API invalide ou manquante
|
||||
*/
|
||||
router.get('/', (req, res) => {
|
||||
const inv = db.prepare(`
|
||||
SELECT id, nom, prenom, type, type_fiscal, notes, created_at
|
||||
FROM investisseurs WHERE id = ?
|
||||
`).get(req.investisseurId);
|
||||
res.json(inv);
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Router } from 'express';
|
||||
import db from '../../db/index.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /remboursements:
|
||||
* get:
|
||||
* summary: Liste des remboursements réels perçus
|
||||
* tags: [Remboursements]
|
||||
* security: [{ ApiKeyAuth: [] }]
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: date_debut
|
||||
* schema: { type: string, format: date }
|
||||
* - in: query
|
||||
* name: date_fin
|
||||
* schema: { type: string, format: date }
|
||||
* responses:
|
||||
* 200: { description: Liste des remboursements }
|
||||
*/
|
||||
router.get('/', (req, res) => {
|
||||
const { date_debut, date_fin } = req.query;
|
||||
const conds = ['i.investisseur_id = ?'];
|
||||
const args = [req.investisseurId];
|
||||
if (date_debut) { conds.push('r.date_remb >= ?'); args.push(date_debut); }
|
||||
if (date_fin) { conds.push('r.date_remb <= ?'); args.push(date_fin); }
|
||||
|
||||
const rows = db.prepare(`
|
||||
SELECT r.id, r.date_remb, i.nom_projet, p.nom AS plateforme_nom,
|
||||
r.capital, r.interets_bruts, r.prelev_sociaux, r.prelev_forfaitaire,
|
||||
r.cashback, r.interets_nets, r.net_recu, r.statut
|
||||
FROM remboursements r
|
||||
JOIN investissements i ON i.id = r.investissement_id
|
||||
JOIN plateformes p ON p.id = i.plateforme_id
|
||||
WHERE ${conds.join(' AND ')}
|
||||
ORDER BY r.date_remb DESC
|
||||
`).all(...args);
|
||||
res.json(rows);
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user