278 lines
8.5 KiB
TypeScript
278 lines
8.5 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,
|
|
parseTriEmprunt,
|
|
} 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'),
|
|
};
|
|
}
|
|
|
|
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 materiels = await listerMaterielsResponsable(user.roleCode, user.campusId, {
|
|
statut,
|
|
categorieId,
|
|
recherche,
|
|
});
|
|
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 anomalies = await listerAnomaliesResponsable(user.roleCode, user.campusId, {
|
|
statut,
|
|
type,
|
|
});
|
|
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'));
|
|
}
|