diff --git a/backend/src/modules/anomalies/anomaly.controller.ts b/backend/src/modules/anomalies/anomaly.controller.ts index 0e8a8d7..8f14077 100644 --- a/backend/src/modules/anomalies/anomaly.controller.ts +++ b/backend/src/modules/anomalies/anomaly.controller.ts @@ -61,7 +61,9 @@ export class AnomalyController{ res.status(201).json(anomaly); }catch (error){ - res + res.status(500).json({ + message:"Error al crear anomalía" + }); } } @@ -103,7 +105,7 @@ export class AnomalyController{ const anomaly = await service.changeStatus( req.params.id as string, - req.body + req.body.status ); if(!anomaly) { @@ -130,9 +132,12 @@ export class AnomalyController{ ){ try{ + // Usuario autenticado + const user = (req as any).user; + const anomaly = await service.close( req.params.id as string, - req.body.resolvedBy, + user.id, req.body.comments ); @@ -143,6 +148,7 @@ export class AnomalyController{ }); } + res.json(anomaly); }catch (error) { res.status(500).json({ @@ -260,7 +266,5 @@ export class AnomalyController{ }) } - } - - + } } \ No newline at end of file diff --git a/backend/src/modules/anomalies/anomaly.interface.ts b/backend/src/modules/anomalies/anomaly.interface.ts index 97e761b..551b055 100644 --- a/backend/src/modules/anomalies/anomaly.interface.ts +++ b/backend/src/modules/anomalies/anomaly.interface.ts @@ -1,18 +1,18 @@ -import { ObjectId } from "mongoose"; +import { Types } from "mongoose"; export interface IAnomaly { - _id?: ObjectId; + _id?: Types.ObjectId; vehicleId: number; employeeId?: number; - fuelRequestId?: ObjectId; + fuelRequestId?: Types.ObjectId; - externalInvoiceId?: ObjectId; + externalInvoiceId?: Types.ObjectId; - lpgId?: ObjectId; + lpgId?: Types.ObjectId; anomalyType: | "RENDIMIENTO BAJO" @@ -30,9 +30,9 @@ export interface IAnomaly { | "SISTEMA" | "USUARIO"; - reportedBy?: ObjectId; + reportedBy?: Types.ObjectId; - resolvedBy?: ObjectId; + resolvedBy?: Types.ObjectId; resolvedDate?: Date; @@ -42,5 +42,4 @@ export interface IAnomaly { | "CERRADA"; comments?: string; - } \ No newline at end of file diff --git a/backend/src/modules/anomalies/anomaly.model.ts b/backend/src/modules/anomalies/anomaly.model.ts index f1b0490..16c5a91 100644 --- a/backend/src/modules/anomalies/anomaly.model.ts +++ b/backend/src/modules/anomalies/anomaly.model.ts @@ -21,7 +21,7 @@ const anomalySchema = new mongoose.Schema({ ref:"ExternalInvoice" }, - lpg:{ + lpgId:{ type:mongoose.Schema.Types.ObjectId, ref:"LPG" }, diff --git a/backend/src/modules/anomalies/anomaly.routes.ts b/backend/src/modules/anomalies/anomaly.routes.ts index e134373..5058fd1 100644 --- a/backend/src/modules/anomalies/anomaly.routes.ts +++ b/backend/src/modules/anomalies/anomaly.routes.ts @@ -8,13 +8,15 @@ const controller = new AnomalyController(); anomalyRouter.get("/", authMiddleware, controller.getAll); -anomalyRouter.get("/:id", authMiddleware, controller.getById); - anomalyRouter.get("/status/:status", authMiddleware, controller.getByStatus); -anomalyRouter.get("/vehicleId/:vehicleId", authMiddleware, controller.getByVehicle); +anomalyRouter.get("/vehicle/:vehicleId", authMiddleware, controller.getByVehicle); -anomalyRouter.get("/employeeId/:employeeId", authMiddleware, controller.getByEmployee); +anomalyRouter.get("/employee/:employeeId", authMiddleware, controller.getByEmployee); + +anomalyRouter.get("/type/:type", authMiddleware, controller.getByType); + +anomalyRouter.get("/:id", authMiddleware, controller.getById); anomalyRouter.post("/", authMiddleware, controller.create); diff --git a/backend/src/modules/anomalies/anomaly.service.ts b/backend/src/modules/anomalies/anomaly.service.ts index 827a502..ea79557 100644 --- a/backend/src/modules/anomalies/anomaly.service.ts +++ b/backend/src/modules/anomalies/anomaly.service.ts @@ -1,24 +1,22 @@ +import mongoose from "mongoose"; import anomalyModel from "./anomaly.model"; import { IAnomaly } from "./anomaly.interface"; export class AnomalyService{ - //Crear anomalía - async create( - data:IAnomaly - ){ - const anomaly = new anomalyModel(data); - - return await anomaly.save(); - } - //Obtener anomalía async getAll() { return await anomalyModel .find() - .populate("reportedBy") - .populate("resolvedBy") + .populate( + "reportedBy", + "userName" + ) + .populate( + "resolvedBy", + "userName" + ) .sort({ createdAt:-1 }); @@ -30,15 +28,68 @@ export class AnomalyService{ ){ return await anomalyModel .findById(id) - .populate("reportedBy") - .populate("resolvedBy") + .populate( + "reportedBy", + "userName" + ) + .populate( + "resolvedBy", + "userName" + ) } + //Crear anomalía + async create( + data:IAnomaly + ){ + + // Validar vehículo + if (!data.vehicleId) { + throw new Error( + "Debe indicar un vehículo." + ); + } + + // Validar descripción + if (!data.description?.trim()) { + throw new Error( + "La descripción es obligatoria." + ); + } + + // Estado inicial + data.status = "ABIERTA"; + + // Si no viene quién la detectó, + // se considera reportada por un usuario. + data.detectedBy = data.detectedBy ?? "USUARIO"; + + const anomaly = new anomalyModel(data); + + return await anomaly.save(); + + } + + //Actualizar async update( id:string, data:Partial ){ + + const anomaly = + await anomalyModel.findById(id); + + if(!anomaly){ + return null; + } + + if(anomaly.status==="CERRADA"){ + throw new Error( + "No es posible modificar una anomalía cerrada." + ); + } + return await anomalyModel.findByIdAndUpdate( id, data, @@ -51,18 +102,51 @@ export class AnomalyService{ //Cambiar estado async changeStatus( - id:string, - status:string - ){ - return await anomalyModel.findByIdAndUpdate( - id, - { - status - }, - { - new:true - } - ); + id: string, + status: string + ) { + + // Buscar la anomalía + const anomaly = await anomalyModel.findById(id); + + if (!anomaly) { + return null; + } + + // Validar estados permitidos + if ( + ![ + "ABIERTA", + "EN PROCESO", + "CERRADA" + ].includes(status) + ) { + throw new Error( + "Estado inválido." + ); + } + + // No permitir cambiar una anomalía ya cerrada + if (anomaly.status === "CERRADA") { + throw new Error( + "La anomalía ya está cerrada." + ); + } + + // Obligar a usar el método close() + if (status === "CERRADA") { + throw new Error( + "Para cerrar una anomalía utilice el método Close." + ); + } + + // Actualizar estado + anomaly.status = status as + "ABIERTA" | "EN PROCESO"; + + await anomaly.save(); + + return anomaly; } //Cerrar anomalía @@ -70,20 +154,33 @@ export class AnomalyService{ async close( id:string, resolvedBy:string, - comments?:String + comments?:string ){ - return await anomalyModel.findByIdAndUpdate( - id, - { - status:"CERRADA", - resolvedBy, - resolvedDate: new Date(), - comments - }, - { - new:true - } - ); + const anomaly = await anomalyModel.findById(id); + + if(!anomaly){ + return null; + } + + if(anomaly.status === "CERRADA"){ + throw new Error( + "La anomalía ya está cerrada." + ); + } + + // Actualizar la anomalía + anomaly.status = "CERRADA"; + + anomaly.resolvedBy = + new mongoose.Types.ObjectId(resolvedBy); + + anomaly.resolvedDate = new Date(); + + anomaly.comments = comments ?? ""; + + await anomaly.save(); + + return anomaly; } async getByStatus( @@ -123,5 +220,4 @@ export class AnomalyService{ ){ return await anomalyModel.findByIdAndDelete(id); } - } \ No newline at end of file