import { Prisma } from '@prisma/client'; import { prisma } from '../db/prisma'; export interface StatutCount { statut: string; count: number; } export type ActiviteResponsable = Prisma.HistoriqueGetPayload<{ include: { utilisateur: true; materiel: true; emprunt: true; }; }>; export type EmpruntResponsable = Prisma.EmpruntGetPayload<{ include: { utilisateur: true; materiel: { include: { categorie: true } }; }; }>; export type MaterielResponsable = Prisma.MaterielGetPayload<{ include: { categorie: true; accessoires: { include: { accessoire: true } }; }; }>; export type AnomalieResponsable = Prisma.AnomalieGetPayload<{ include: { emprunt: true; etudiant: true; materiel: { include: { categorie: true } }; traitePar: true; }; }>; export type NotificationResponsable = Prisma.NotificationGetPayload<{ include: { anomalie: { include: { emprunt: true; materiel: true; }; }; }; }>; export type HistoriqueResponsable = Prisma.HistoriqueGetPayload<{ include: { utilisateur: true; materiel: true; emprunt: true; sallePret: true; posteEmprunt: true; }; }>; export interface EmpruntResponsableFiltres { statut?: string; } export interface MaterielResponsableFiltres { statut?: string; categorieId?: number; recherche?: string; } export interface AnomalieResponsableFiltres { statut?: string; type?: string; } export interface NotificationResponsableFiltres { lu?: boolean; } export interface HistoriqueResponsableFiltres { action?: string; utilisateurId?: number; materielId?: number; empruntId?: number; dateDebut?: Date; dateFin?: Date; } export interface ChangerStatutAnomalieData { anomalieId: number; campusId: number; responsableId: number; statut: string; observation?: string; } function mapStatutCounts(rows: Array<{ statut: string; _count: { _all: number } }>): StatutCount[] { return rows.map((row) => ({ statut: row.statut, count: row._count._all })); } export async function countMaterielsParStatut(campusId: number): Promise { const rows = await prisma.materiel.groupBy({ by: ['statut'], where: { campusId, actif: true }, _count: { _all: true }, }); return mapStatutCounts(rows); } export async function countEmpruntsParStatut(campusId: number): Promise { const rows = await prisma.emprunt.groupBy({ by: ['statut'], where: { campusId }, _count: { _all: true }, }); return mapStatutCounts(rows); } export async function countAnomaliesParStatut(campusId: number): Promise { const rows = await prisma.anomalie.groupBy({ by: ['statut'], where: { emprunt: { campusId } }, _count: { _all: true }, }); return mapStatutCounts(rows); } export function countNotificationsNonLues(utilisateurId: number): Promise { return prisma.notification.count({ where: { utilisateurId, lu: false }, }); } export function findActiviteRecente( campusId: number, limite: number, ): Promise { return prisma.historique.findMany({ where: { campusId }, include: { utilisateur: true, materiel: true, emprunt: true, }, orderBy: { dateAction: 'desc' }, take: limite, }); } export function findEmpruntsResponsable( campusId: number, filtres: EmpruntResponsableFiltres, ): Promise { return prisma.emprunt.findMany({ where: { campusId, ...(filtres.statut ? { statut: filtres.statut } : {}), }, include: { utilisateur: true, materiel: { include: { categorie: true } }, }, orderBy: { dateEmprunt: 'desc' }, }); } export function findMaterielsResponsable( campusId: number, filtres: MaterielResponsableFiltres, ): Promise { return prisma.materiel.findMany({ where: { campusId, actif: true, ...(filtres.statut ? { statut: filtres.statut } : {}), ...(filtres.categorieId !== undefined ? { categorieId: filtres.categorieId } : {}), ...(filtres.recherche ? { OR: [ { nom: { contains: filtres.recherche } }, { marque: { contains: filtres.recherche } }, { modele: { contains: filtres.recherche } }, { reference: { contains: filtres.recherche } }, ], } : {}), }, include: { categorie: true, accessoires: { include: { accessoire: true } }, }, orderBy: { nom: 'asc' }, }); } export function findAnomaliesResponsable( campusId: number, filtres: AnomalieResponsableFiltres, ): Promise { return prisma.anomalie.findMany({ where: { emprunt: { campusId }, ...(filtres.statut ? { statut: filtres.statut } : {}), ...(filtres.type ? { type: filtres.type } : {}), }, include: { emprunt: true, etudiant: true, materiel: { include: { categorie: true } }, traitePar: true, }, orderBy: { dateDetection: 'desc' }, }); } export function findAnomalieResponsableById( campusId: number, anomalieId: number, ): Promise { return prisma.anomalie.findFirst({ where: { id: anomalieId, emprunt: { campusId }, }, include: { emprunt: true, etudiant: true, materiel: { include: { categorie: true } }, traitePar: true, }, }); } export function changerStatutAnomalieResponsable( data: ChangerStatutAnomalieData, ): Promise { return prisma.$transaction(async (tx) => { const anomalie = await tx.anomalie.update({ where: { id: data.anomalieId }, data: { statut: data.statut, traiteeParId: data.responsableId, ...(data.observation !== undefined ? { observation: data.observation } : {}), ...(data.statut === 'RESOLUE' || data.statut === 'CLOTUREE' ? { dateResolution: new Date() } : {}), }, include: { emprunt: true, etudiant: true, materiel: { include: { categorie: true } }, traitePar: true, }, }); await tx.historique.create({ data: { utilisateurId: data.responsableId, empruntId: anomalie.empruntId, materielId: anomalie.materielId, campusId: data.campusId, action: 'TRAITEMENT_ANOMALIE', description: `Anomalie #${anomalie.id} passee au statut ${data.statut}`, dateAction: new Date(), }, }); return anomalie; }); } export function findNotificationsResponsable( utilisateurId: number, filtres: NotificationResponsableFiltres, ): Promise { return prisma.notification.findMany({ where: { utilisateurId, ...(filtres.lu !== undefined ? { lu: filtres.lu } : {}), }, include: { anomalie: { include: { emprunt: true, materiel: true, }, }, }, orderBy: { dateCreation: 'desc' }, }); } export function marquerNotificationLue( utilisateurId: number, notificationId: number, ): Promise { return prisma.notification.update({ where: { id: notificationId, utilisateurId, }, data: { lu: true }, include: { anomalie: { include: { emprunt: true, materiel: true, }, }, }, }); } export async function marquerNotificationsResponsableLues(utilisateurId: number): Promise { const result = await prisma.notification.updateMany({ where: { utilisateurId, lu: false }, data: { lu: true }, }); return result.count; } export function findHistoriqueResponsable( campusId: number, filtres: HistoriqueResponsableFiltres, ): Promise { return prisma.historique.findMany({ where: { campusId, ...(filtres.action ? { action: filtres.action } : {}), ...(filtres.utilisateurId !== undefined ? { utilisateurId: filtres.utilisateurId } : {}), ...(filtres.materielId !== undefined ? { materielId: filtres.materielId } : {}), ...(filtres.empruntId !== undefined ? { empruntId: filtres.empruntId } : {}), ...(filtres.dateDebut || filtres.dateFin ? { dateAction: { ...(filtres.dateDebut ? { gte: filtres.dateDebut } : {}), ...(filtres.dateFin ? { lte: filtres.dateFin } : {}), }, } : {}), }, include: { utilisateur: true, materiel: true, emprunt: true, sallePret: true, posteEmprunt: true, }, orderBy: { dateAction: 'desc' }, }); }