Files
EME_APP/eme-backend/src/controllers/responsable.controller.ts
T
2026-07-24 15:47:48 +02:00

294 lines
9.0 KiB
TypeScript

import { Request, Response } from 'express';
import { AppError } from '../errors/app-error';
import {
changerStatutAnomalieResponsableService,
deciderEcartResponsableService,
getDashboardResponsable,
listerAnomaliesResponsable,
listerHistoriqueResponsable,
listerNotificationsResponsable,
listerMaterielsResponsable,
listerEmpruntsResponsable,
listerEcartsResponsable,
marquerNotificationResponsableLue,
marquerToutesNotificationsResponsableLues,
parseAnomalieId,
parseAnneeEmprunt,
parseEmpruntId,
parseCategorieId,
parseLu,
parseNotificationId,
parseOrdreTri,
parseDateQuery,
parsePositiveIntQuery,
parseStatutAnomalie,
parseStatutMateriel,
parseStatutEmprunt,
parseTriAnomalie,
parseTriEmprunt,
parseTriHistorique,
parseTriMateriel,
} from '../services/responsable.service';
import {
toAnomalieResponsableResponse,
toDashboardResponsableResponse,
toEmpruntResponsableResponse,
toEcartResponsableResponse,
toHistoriqueResponsableResponse,
toMaterielResponsableResponse,
toNotificationResponsableResponse,
} from '../dtos/responsable.dto';
function asBodyObject(value: unknown): Record<string, unknown> {
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
throw new AppError(400, 'Corps de requete invalide');
}
return value as Record<string, unknown>;
}
function getHistoriqueFiltres(req: Request) {
const action = typeof req.query.action === 'string' ? req.query.action : undefined;
return {
action,
utilisateurId: parsePositiveIntQuery(req.query.utilisateurId, 'utilisateurId'),
materielId: parsePositiveIntQuery(req.query.materielId, 'materielId'),
empruntId: parsePositiveIntQuery(req.query.empruntId, 'empruntId'),
dateDebut: parseDateQuery(req.query.dateDebut, 'dateDebut'),
dateFin: parseDateQuery(req.query.dateFin, 'dateFin'),
recherche: typeof req.query.q === 'string' ? req.query.q : undefined,
tri: parseTriHistorique(req.query.tri),
ordre: parseOrdreTri(req.query.ordre),
};
}
function escapeCsv(value: string | number | Date | null): string {
if (value === null) {
return '';
}
const raw = value instanceof Date ? value.toISOString() : String(value);
return `"${raw.replace(/"/g, '""')}"`;
}
export async function getDashboard(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const dashboard = await getDashboardResponsable(user.id, user.roleCode, user.campusId);
res.json({ data: toDashboardResponsableResponse(dashboard) });
}
export async function getEmprunts(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const statut = parseStatutEmprunt(req.query.statut);
const annee = parseAnneeEmprunt(req.query.annee);
const recherche = typeof req.query.q === 'string' ? req.query.q.trim() : undefined;
const tri = parseTriEmprunt(req.query.tri);
const ordre = parseOrdreTri(req.query.ordre);
const emprunts = await listerEmpruntsResponsable(user.roleCode, user.campusId, {
statut,
annee,
recherche: recherche || undefined,
tri,
ordre,
});
res.json({ data: emprunts.map(toEmpruntResponsableResponse) });
}
export async function getEcarts(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const ecarts = await listerEcartsResponsable(user.roleCode, user.campusId);
res.json({ data: ecarts.map(toEcartResponsableResponse) });
}
export async function patchEcartDecision(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const empruntId = parseEmpruntId(req.params.id);
const body = asBodyObject(req.body);
if (body.decision !== 'CONFIRMER' && body.decision !== 'REFUSER') {
throw new AppError(400, 'decision invalide');
}
const observation = typeof body.observation === 'string' ? body.observation : undefined;
const statutMateriel = parseStatutMateriel(body.statutMateriel);
const ecart = await deciderEcartResponsableService(
user.id,
user.roleCode,
user.campusId,
empruntId,
{
decision: body.decision,
observation,
statutMateriel,
},
);
res.json({ data: toEcartResponsableResponse(ecart) });
}
export async function getMateriels(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const statut = parseStatutMateriel(req.query.statut);
const categorieId = parseCategorieId(req.query.categorieId);
const recherche = typeof req.query.q === 'string' ? req.query.q : undefined;
const tri = parseTriMateriel(req.query.tri);
const ordre = parseOrdreTri(req.query.ordre);
const materiels = await listerMaterielsResponsable(user.roleCode, user.campusId, {
statut,
categorieId,
recherche,
tri,
ordre,
});
res.json({ data: materiels.map(toMaterielResponsableResponse) });
}
export async function getAnomalies(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const statut = parseStatutAnomalie(req.query.statut);
const type = typeof req.query.type === 'string' ? req.query.type : undefined;
const recherche = typeof req.query.q === 'string' ? req.query.q : undefined;
const tri = parseTriAnomalie(req.query.tri);
const ordre = parseOrdreTri(req.query.ordre);
const anomalies = await listerAnomaliesResponsable(user.roleCode, user.campusId, {
statut,
type,
recherche,
tri,
ordre,
});
res.json({ data: anomalies.map(toAnomalieResponsableResponse) });
}
export async function patchAnomalieStatut(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const anomalieId = parseAnomalieId(req.params.id);
const body = asBodyObject(req.body);
const statut = parseStatutAnomalie(body.statut);
if (!statut) {
throw new AppError(400, 'statut requis');
}
const observation = typeof body.observation === 'string' ? body.observation : undefined;
const anomalie = await changerStatutAnomalieResponsableService(
user.id,
user.roleCode,
user.campusId,
anomalieId,
{ statut, observation },
);
res.json({ data: toAnomalieResponsableResponse(anomalie) });
}
export async function getNotifications(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const lu = parseLu(req.query.lu);
const notifications = await listerNotificationsResponsable(user.id, user.roleCode, { lu });
res.json({ data: notifications.map(toNotificationResponsableResponse) });
}
export async function patchNotificationLue(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const notificationId = parseNotificationId(req.params.id);
const notification = await marquerNotificationResponsableLue(
user.id,
user.roleCode,
notificationId,
);
res.json({ data: toNotificationResponsableResponse(notification) });
}
export async function patchNotificationsLues(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const count = await marquerToutesNotificationsResponsableLues(user.id, user.roleCode);
res.json({ data: { count } });
}
export async function getHistorique(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const historique = await listerHistoriqueResponsable(
user.roleCode,
user.campusId,
getHistoriqueFiltres(req),
);
res.json({ data: historique.map(toHistoriqueResponsableResponse) });
}
export async function getHistoriqueCsv(req: Request, res: Response): Promise<void> {
const user = req.user;
if (!user) {
throw new AppError(401, 'Authentification requise');
}
const historique = await listerHistoriqueResponsable(
user.roleCode,
user.campusId,
getHistoriqueFiltres(req),
);
const lignes = [
['id', 'dateAction', 'action', 'description', 'utilisateur', 'email', 'materiel', 'empruntId']
.map(escapeCsv)
.join(','),
...historique.map((item) =>
[
item.id,
item.dateAction,
item.action,
item.description,
`${item.utilisateur.prenom} ${item.utilisateur.nom}`,
item.utilisateur.email,
item.materiel ? `${item.materiel.nom} (${item.materiel.reference})` : null,
item.empruntId,
]
.map(escapeCsv)
.join(','),
),
];
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
res.setHeader('Content-Disposition', 'attachment; filename="historique-responsable.csv"');
res.send(lignes.join('\n'));
}