diff --git a/backend/src/app.ts b/backend/src/app.ts index 131ffa5..045f8a7 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -13,6 +13,7 @@ import fuelRequestRouter from "./modules/fuel-requests/fuelRequest.routes"; import approvalrouter from "./modules/approvals/approval.routes"; import invoicerouter from "./modules/external-invoices/externalInvoice.routes"; import lpgRouter from "./modules/lpg/lpg.routes"; +import anomalyRouter from "./modules/anomalies/anomaly.routes"; @@ -34,6 +35,7 @@ app.use("/api/fuelRequest", fuelRequestRouter); app.use("/api/approvals", approvalrouter); app.use("/api/exterinvoice", invoicerouter); app.use("/api/lpg",lpgRouter); +app.use("/api/anomaly", anomalyRouter); app.use(express.urlencoded({ diff --git a/backend/src/modules/anomalies/anomaly.controller.ts b/backend/src/modules/anomalies/anomaly.controller.ts new file mode 100644 index 0000000..0e8a8d7 --- /dev/null +++ b/backend/src/modules/anomalies/anomaly.controller.ts @@ -0,0 +1,266 @@ +import { Request, Response } from "express"; +import { AnomalyService } from "./anomaly.service"; + + +const service = new AnomalyService(); + +export class AnomalyController{ + + //Obtener todas las anomalías + + async getAll( + req:Request, + res:Response + ){ + try{ + + const anomalies = await service.getAll(); + res.json(anomalies); + }catch(error){ + res.status(500).json({ + message:"Error al obtener anomalías", + error + }); + } + } + + //Obtener por ID + async getById( + req:Request, + res:Response + ){ + try{ + const anomaly = await service.getById( + req.params.id as string); + + if (!anomaly){ + return res.status(404).json({ + message:"Anomamía no encontrada" + }); + } + + res.json(anomaly); + } catch(error){ + res.status(500).json({ + message:"Error al obtener anomalías", + error + }); + } + } + + //Crear anomalía + async create( + req:Request, + res:Response + ){ + try{ + + const anomaly = await service.create( + req.body + ); + + res.status(201).json(anomaly); + }catch (error){ + res + } + } + + //Actualizar + async update( + req:Request, + res:Response + ){ + try{ + + const anomaly = await service.update( + req.params.id as string, + req.body + ); + + if (!anomaly){ + + return res.status(404).json({ + message:"Anomalía no encontrada" + }); + } + + res.json(anomaly); + }catch (error) { + res.status(500).json({ + message:"Error al actualizar anomalía", + error + }) + } + } + + //Cambiar estado + + async changeStatus( + req:Request, + res:Response + ){ + try{ + + const anomaly = await service.changeStatus( + req.params.id as string, + req.body + ); + + if(!anomaly) { + + return res.status(404).json({ + message:"Anomalía no encontrada" + }); + } + + res.json(anomaly); + + }catch(error) { + res.status(500).json({ + message:"Error al cambiar estado", + error + }); + + } + } + + async close( + req:Request, + res:Response + ){ + try{ + + const anomaly = await service.close( + req.params.id as string, + req.body.resolvedBy, + req.body.comments + ); + + if(!anomaly) { + + return res.status(404).json({ + message:"Anomalía no encontrada" + }); + } + + + }catch (error) { + res.status(500).json({ + message:"Error al cerrar anomalía", + error + }) + + } + } + + //Obtener pir estado + async getByStatus( + req:Request, + res:Response + ){ + try{ + + const anomaly = await service.getByStatus( + req.params.status as string + ); + + res.json(anomaly); + + + }catch(error) { + res.status(500).json({ + message:"Error al buscar anomalías", + error + }); + + } + } + + //Obtener por tipo + async getByType( + req:Request, + res:Response + ){ + try{ + const anomaly = await service.getByType( + req.params.type as string + ); + res.json(anomaly); + }catch(error){ + res.status(500).json({ + message:"Error al buscar anomalías", + error + }); + } + } + + async getByVehicle( + req:Request, + res:Response + ){ + try{ + const anomaly = await service.getByVehicle( + Number(req.params.vehicleId) + ); + + res.json(anomaly); + }catch(error){ + res.status(500).json({ + message:"Error al buscar anomalías", + error + }); + } + } + + async getByEmployee( + req:Request, + res:Response + ){ + try{ + + const anomaly = await service.getByEmployee( + Number(req.params.employeeId) + ); + + res.json(anomaly); + + }catch(error){ + res.status(500).json({ + message:"Error al buscar anomalías", + error + }); + + } + } + + async delete( + req:Request, + res:Response + ){ + try{ + + const anomaly = await service.delete( + req.params.id as string + ); + + if(!anomaly){ + return res.status(404).json({ + message:"Anomalía no encontrada" + }); + } + res.json({ + message:"Anomalía eliminada correctamente" + }); + + }catch(error){ + + res.status(500).json({ + message:"Error al elliminar anomalía", + error + }) + + } + } + + +} \ No newline at end of file diff --git a/backend/src/modules/anomalies/anomaly.interface.ts b/backend/src/modules/anomalies/anomaly.interface.ts new file mode 100644 index 0000000..e5fbc2d --- /dev/null +++ b/backend/src/modules/anomalies/anomaly.interface.ts @@ -0,0 +1,18 @@ +import { ObjectId } from "mongoose"; + +export interface IAnomaly { + + vehicleId:number; + employeeId:number; + fuelRequestId?:ObjectId; + externalInvoiceId:ObjectId; + lpgId?:ObjectId; + anomalyType:string; + description:string; + detectedBy:string; + reportedBy?:ObjectId; + resolvedVBy:ObjectId; + resolvedData:Date, + status:string; + 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 new file mode 100644 index 0000000..f1b0490 --- /dev/null +++ b/backend/src/modules/anomalies/anomaly.model.ts @@ -0,0 +1,94 @@ +import mongoose from "mongoose"; + +const anomalySchema = new mongoose.Schema({ + + vehicleId:{ + type:Number, + required:true + }, + + employeeId:{ + type:Number + }, + + fuelRequestId:{ + type:mongoose.Schema.Types.ObjectId, + ref:"FuelRequest" + }, + + externalInvoiceId:{ + type:mongoose.Schema.Types.ObjectId, + ref:"ExternalInvoice" + }, + + lpg:{ + type:mongoose.Schema.Types.ObjectId, + ref:"LPG" + }, + + anomalyType:{ + type:String, + required:true, + enum:[ + "RENDIMIENTO BAJO", + "CONSUMO ELEVADO", + "KILOMETRAJE FUERA DE RANGO", + "ODOMETRO EN MAL ESTADO", + "VEHICULO NO ASIGNADO", + "FUGA DE COMBUSTIBLE", + "DIFERENCIA EN BOMBA", + "OTRO" + ] + }, + + description:{ + type:String, + required:true + }, + + detectedBy:{ + type:String, + required:true, + enum:[ + "SISTEMA", + "USUARIO" + ] + }, + + reportedBy:{ + type:mongoose.Schema.Types.ObjectId, + ref:"User" + }, + + resolvedBy:{ + type:mongoose.Schema.Types.ObjectId, + ref:"User" + }, + + resolvedDate:{ + type:Date + }, + + status:{ + type:String, + required:true, + enum:[ + "ABIERTA", + "EN PROCESO", + "CERRADA" + ], + default:"ABIERTA" + }, + + comments:{ + type:String + } + +}, + { + timestamps:true + } + +); + +export default mongoose.model("Anomaly", anomalySchema); \ No newline at end of file diff --git a/backend/src/modules/anomalies/anomaly.routes.ts b/backend/src/modules/anomalies/anomaly.routes.ts new file mode 100644 index 0000000..e134373 --- /dev/null +++ b/backend/src/modules/anomalies/anomaly.routes.ts @@ -0,0 +1,30 @@ +import { Router } from "express"; +import { AnomalyController } from "./anomaly.controller"; +import { authMiddleware } from "../auth/auth.middleware"; + +const anomalyRouter = Router(); + +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("/employeeId/:employeeId", authMiddleware, controller.getByEmployee); + +anomalyRouter.post("/", authMiddleware, controller.create); + +anomalyRouter.put("/:id", authMiddleware, controller.update); + +anomalyRouter.put("/:id/status", authMiddleware, controller.changeStatus); + +anomalyRouter.put("/:id/close", authMiddleware, controller.close); + +anomalyRouter.delete("/:id", authMiddleware, controller.delete); + +export default anomalyRouter; + diff --git a/backend/src/modules/anomalies/anomaly.service.ts b/backend/src/modules/anomalies/anomaly.service.ts new file mode 100644 index 0000000..827a502 --- /dev/null +++ b/backend/src/modules/anomalies/anomaly.service.ts @@ -0,0 +1,127 @@ +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") + .sort({ + createdAt:-1 + }); + + } + + async getById( + id:string + ){ + return await anomalyModel + .findById(id) + .populate("reportedBy") + .populate("resolvedBy") + } + + //Actualizar + async update( + id:string, + data:Partial + ){ + return await anomalyModel.findByIdAndUpdate( + id, + data, + { + new:true + } + ) + } + + //Cambiar estado + + async changeStatus( + id:string, + status:string + ){ + return await anomalyModel.findByIdAndUpdate( + id, + { + status + }, + { + new:true + } + ); + } + + //Cerrar anomalía + + async close( + id:string, + resolvedBy:string, + comments?:String + ){ + return await anomalyModel.findByIdAndUpdate( + id, + { + status:"CERRADA", + resolvedBy, + resolvedDate: new Date(), + comments + }, + { + new:true + } + ); + } + + async getByStatus( + status:string + ){ + return await anomalyModel.find({ + status + } as any); + } + + async getByType( + anomalyType:string + ){ + return await anomalyModel.find({ + anomalyType + } as any); + } + + async getByVehicle( + vehicleId:number + ){ + return await anomalyModel.find({ + vehicleId + } as any); + } + + async getByEmployee( + employeeId:number + ){ + return await anomalyModel.find({ + employeeId + } as any); + } + + async delete( + id:string + ){ + return await anomalyModel.findByIdAndDelete(id); + } + +} \ No newline at end of file diff --git a/backend/src/modules/approvals/approval.controller.ts b/backend/src/modules/approvals/approval.controller.ts index 13c92b1..e4fd41d 100644 --- a/backend/src/modules/approvals/approval.controller.ts +++ b/backend/src/modules/approvals/approval.controller.ts @@ -1,16 +1,8 @@ -import { - Request, - Response -} -from "express"; +import { Request, Response } from "express"; -import { - ApprovalService -} -from "./approval.service"; +import { ApprovalService } from "./approval.service"; -const service = -new ApprovalService(); +const service = new ApprovalService(); export class ApprovalController { diff --git a/backend/src/modules/lpg/lpg.model.ts b/backend/src/modules/lpg/lpg.model.ts index 7b0dc0e..1d9b9b1 100644 --- a/backend/src/modules/lpg/lpg.model.ts +++ b/backend/src/modules/lpg/lpg.model.ts @@ -1,5 +1,4 @@ import mongoose from "mongoose"; -import { timeStamp } from "node:console"; const lpgSchema = new mongoose.Schema({ diff --git a/backend/src/modules/lpg/lpg.service.ts b/backend/src/modules/lpg/lpg.service.ts index b641cfe..6e1af77 100644 --- a/backend/src/modules/lpg/lpg.service.ts +++ b/backend/src/modules/lpg/lpg.service.ts @@ -1,11 +1,10 @@ import lpgModel from "./lpg.model"; import { ILpg } from "./lpg.interface"; -import { idText } from "typescript"; export class LPGService{ - //Crear solicitud gas LPG +//Crear solicitud gas LPG async create ( data:ILpg ){ @@ -16,7 +15,7 @@ export class LPGService{ const lpg = new lpgModel(data); return await lpg.save(); - } + } //Obtener todas las requisiciones async getAll() {