feat(backend): expose POST /api/emprunts with departure checklist
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { prisma } from '../db/prisma';
|
||||
import { StatutEmprunt } from '../models/enums';
|
||||
import { AppError } from '../errors/app-error';
|
||||
|
||||
export type EmpruntAvecMateriel = Prisma.EmpruntGetPayload<{
|
||||
include: { materiel: { include: { categorie: true } } };
|
||||
@@ -18,3 +19,74 @@ export function findEnCoursParUtilisateur(utilisateurId: number): Promise<Emprun
|
||||
orderBy: { dateRetourPrevue: 'asc' },
|
||||
});
|
||||
}
|
||||
|
||||
export interface CreerEmpruntData {
|
||||
utilisateurId: number;
|
||||
materielId: number;
|
||||
campusId: number;
|
||||
sallePretId: number;
|
||||
posteEmpruntId: number;
|
||||
dateRetourPrevue: Date;
|
||||
modeIdentification: string;
|
||||
commentaireDepart?: string;
|
||||
elements: {
|
||||
accessoireId?: number;
|
||||
nomElement: string;
|
||||
etat: string;
|
||||
quantiteConstatee: number;
|
||||
commentaire?: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
/* Création atomique : réservation du matériel (DISPONIBLE -> EMPRUNTE), emprunt,
|
||||
checklist de départ et ses éléments. Si une étape échoue, tout est annulé. */
|
||||
export function creerEmpruntComplet(data: CreerEmpruntData): Promise<EmpruntAvecMateriel> {
|
||||
return prisma.$transaction(async (tx) => {
|
||||
// Réservation atomique : empêche un double emprunt du même matériel (RG07).
|
||||
const reservation = await tx.materiel.updateMany({
|
||||
where: { id: data.materielId, statut: 'DISPONIBLE' },
|
||||
data: { statut: 'EMPRUNTE' },
|
||||
});
|
||||
if (reservation.count === 0) {
|
||||
throw new AppError(409, 'Materiel non disponible');
|
||||
}
|
||||
|
||||
const emprunt = await tx.emprunt.create({
|
||||
data: {
|
||||
utilisateurId: data.utilisateurId,
|
||||
materielId: data.materielId,
|
||||
campusId: data.campusId,
|
||||
sallePretId: data.sallePretId,
|
||||
posteEmpruntId: data.posteEmpruntId,
|
||||
dateEmprunt: new Date(),
|
||||
dateRetourPrevue: data.dateRetourPrevue,
|
||||
statut: 'EN_COURS',
|
||||
modeIdentificationEmprunt: data.modeIdentification,
|
||||
commentaireDepart: data.commentaireDepart ?? null,
|
||||
},
|
||||
});
|
||||
|
||||
await tx.checklist.create({
|
||||
data: {
|
||||
empruntId: emprunt.id,
|
||||
utilisateurId: data.utilisateurId,
|
||||
type: 'DEPART',
|
||||
dateVerification: new Date(),
|
||||
elements: {
|
||||
create: data.elements.map((element) => ({
|
||||
accessoireId: element.accessoireId ?? null,
|
||||
nomElement: element.nomElement,
|
||||
etat: element.etat,
|
||||
quantiteConstatee: element.quantiteConstatee,
|
||||
commentaire: element.commentaire ?? null,
|
||||
})),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return tx.emprunt.findUniqueOrThrow({
|
||||
where: { id: emprunt.id },
|
||||
include: { materiel: { include: { categorie: true } } },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user