feat(backend): add emprunt restitution with automatic anomaly detection
This commit is contained in:
@@ -7,6 +7,10 @@ export type EmpruntAvecMateriel = Prisma.EmpruntGetPayload<{
|
||||
include: { materiel: { include: { categorie: true } } };
|
||||
}>;
|
||||
|
||||
export type EmpruntAvecChecklists = Prisma.EmpruntGetPayload<{
|
||||
include: { checklists: { include: { elements: true } } };
|
||||
}>;
|
||||
|
||||
const STATUTS_EN_COURS: StatutEmprunt[] = ['EN_COURS', 'EN_RETARD'];
|
||||
|
||||
export function findEnCoursParUtilisateur(utilisateurId: number): Promise<EmpruntAvecMateriel[]> {
|
||||
@@ -20,6 +24,21 @@ export function findEnCoursParUtilisateur(utilisateurId: number): Promise<Emprun
|
||||
});
|
||||
}
|
||||
|
||||
export function findByIdAvecChecklists(id: number): Promise<EmpruntAvecChecklists | null> {
|
||||
return prisma.emprunt.findUnique({
|
||||
where: { id },
|
||||
include: { checklists: { include: { elements: true } } },
|
||||
});
|
||||
}
|
||||
|
||||
interface ChecklistElementData {
|
||||
accessoireId?: number;
|
||||
nomElement: string;
|
||||
etat: string;
|
||||
quantiteConstatee: number;
|
||||
commentaire?: string;
|
||||
}
|
||||
|
||||
export interface CreerEmpruntData {
|
||||
utilisateurId: number;
|
||||
materielId: number;
|
||||
@@ -29,13 +48,7 @@ export interface CreerEmpruntData {
|
||||
dateRetourPrevue: Date;
|
||||
modeIdentification: string;
|
||||
commentaireDepart?: string;
|
||||
elements: {
|
||||
accessoireId?: number;
|
||||
nomElement: string;
|
||||
etat: string;
|
||||
quantiteConstatee: number;
|
||||
commentaire?: string;
|
||||
}[];
|
||||
elements: ChecklistElementData[];
|
||||
}
|
||||
|
||||
/* Création atomique : réservation du matériel (DISPONIBLE -> EMPRUNTE), emprunt,
|
||||
@@ -90,3 +103,93 @@ export function creerEmpruntComplet(data: CreerEmpruntData): Promise<EmpruntAvec
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export interface RestituerEmpruntData {
|
||||
empruntId: number;
|
||||
utilisateurId: number;
|
||||
materielId: number;
|
||||
statutEmprunt: string;
|
||||
statutMateriel: string;
|
||||
modeIdentification: string;
|
||||
commentaireRetour?: string;
|
||||
elements: ChecklistElementData[];
|
||||
anomalie?: {
|
||||
type: string;
|
||||
description: string;
|
||||
responsablesIds: number[];
|
||||
};
|
||||
}
|
||||
|
||||
/* Restitution atomique : checklist de retour, mise à jour de l'emprunt et du
|
||||
matériel, et — si non conforme — création de l'anomalie et des notifications. */
|
||||
export function restituerEmpruntComplet(data: RestituerEmpruntData): Promise<EmpruntAvecMateriel> {
|
||||
return prisma.$transaction(async (tx) => {
|
||||
const maintenant = new Date();
|
||||
|
||||
await tx.checklist.create({
|
||||
data: {
|
||||
empruntId: data.empruntId,
|
||||
utilisateurId: data.utilisateurId,
|
||||
type: 'RETOUR',
|
||||
dateVerification: maintenant,
|
||||
elements: {
|
||||
create: data.elements.map((element) => ({
|
||||
accessoireId: element.accessoireId ?? null,
|
||||
nomElement: element.nomElement,
|
||||
etat: element.etat,
|
||||
quantiteConstatee: element.quantiteConstatee,
|
||||
commentaire: element.commentaire ?? null,
|
||||
})),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await tx.emprunt.update({
|
||||
where: { id: data.empruntId },
|
||||
data: {
|
||||
statut: data.statutEmprunt,
|
||||
dateRetourReelle: maintenant,
|
||||
modeIdentificationRetour: data.modeIdentification,
|
||||
commentaireRetour: data.commentaireRetour ?? null,
|
||||
},
|
||||
});
|
||||
|
||||
await tx.materiel.update({
|
||||
where: { id: data.materielId },
|
||||
data: { statut: data.statutMateriel },
|
||||
});
|
||||
|
||||
if (data.anomalie) {
|
||||
const infoAnomalie = data.anomalie;
|
||||
const anomalie = await tx.anomalie.create({
|
||||
data: {
|
||||
empruntId: data.empruntId,
|
||||
materielId: data.materielId,
|
||||
utilisateurId: data.utilisateurId,
|
||||
type: infoAnomalie.type,
|
||||
description: infoAnomalie.description,
|
||||
statut: 'DETECTEE',
|
||||
detecteeAutomatiquement: true,
|
||||
dateDetection: maintenant,
|
||||
},
|
||||
});
|
||||
|
||||
if (infoAnomalie.responsablesIds.length > 0) {
|
||||
await tx.notification.createMany({
|
||||
data: infoAnomalie.responsablesIds.map((responsableId) => ({
|
||||
utilisateurId: responsableId,
|
||||
anomalieId: anomalie.id,
|
||||
titre: 'Nouvelle anomalie detectee',
|
||||
message: infoAnomalie.description,
|
||||
type: 'ANOMALIE',
|
||||
})),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return tx.emprunt.findUniqueOrThrow({
|
||||
where: { id: data.empruntId },
|
||||
include: { materiel: { include: { categorie: true } } },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,3 +20,10 @@ export function findById(id: number): Promise<UtilisateurProfil | null> {
|
||||
include: { role: true, campus: true },
|
||||
});
|
||||
}
|
||||
|
||||
export function findResponsablesParCampus(campusId: number): Promise<{ id: number }[]> {
|
||||
return prisma.utilisateur.findMany({
|
||||
where: { campusId, actif: true, role: { code: 'RESPONSABLE' } },
|
||||
select: { id: true },
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user