From 1aaee34a833d59e21adc0b30337943fab6c4853e Mon Sep 17 00:00:00 2001 From: karol Date: Mon, 29 Jun 2026 23:22:53 +0000 Subject: [PATCH] CRUD lecturas de bomba --- .../pump-reading/pumpReading.controller.ts | 119 ++++++++ .../pump-reading/pumpReading.interface.ts | 17 ++ .../modules/pump-reading/pumpReading.model.ts | 89 ++++++ .../pump-reading/pumpReading.service.ts | 282 ++++++++++++++++++ 4 files changed, 507 insertions(+) create mode 100644 backend/src/modules/pump-reading/pumpReading.controller.ts create mode 100644 backend/src/modules/pump-reading/pumpReading.interface.ts create mode 100644 backend/src/modules/pump-reading/pumpReading.model.ts create mode 100644 backend/src/modules/pump-reading/pumpReading.service.ts diff --git a/backend/src/modules/pump-reading/pumpReading.controller.ts b/backend/src/modules/pump-reading/pumpReading.controller.ts new file mode 100644 index 0000000..d171808 --- /dev/null +++ b/backend/src/modules/pump-reading/pumpReading.controller.ts @@ -0,0 +1,119 @@ +import {Request, Response } from "express"; +import { PumpReadingService } from "./pumpReading.service"; + + +const service = new PumpReadingService(); + +export class PumpReadingController { + + async create( + req:Request, + res:Response + ){ + try { + const reading = await service.create( + req.body + ) + res.status(201).json(reading); + }catch (error){ + res.status(500).json({ + message:"Error al crear la lectura", + error + }); + } + + } + + async getAll( + req:Request, + res:Response + ){ + try{ + const readings = await service.getAll(); + res.json(readings); + }catch(error){ + res.status(500).json({ + message:"Error al obtener las lecturas", + error + }); + } + } + + async getById( + req:Request, + res:Response + ){ + try{ + + const reading = await service.getById( + req.params.id as string + ) + if(!reading){ + return res.status(404).json({ + message:"Lectura no encontrada" + }); + } + res.json(reading); + }catch(error){ + res.status(500).json({ + message:"Error al obtener la lectura", + error + }); + } + } + + async update( + req:Request, + res:Response + ){ + try{ + + const reading = await service.update( + req.params.id as string, + req.body + ); + + if(!reading){ + return res.status(404).json({ + message:"Lectura no encontrada" + }); + } + res.json(reading); + + + }catch(error){ + res.status(500).json({ + message:"Error al actualizar lectura", + error + }); + + } + } + + async delete( + req:Request, + res:Response + ){ + try{ + const reading = await service.delete( + req.params.id as string + ); + if(!reading){ + return res.status(404).json({ + message:"Lectura no encontrada" + }); + } + res.json({ + message:"Lectura eliminada" + }); + + }catch (error){ + res.status(500).json({ + message:"Error al eliminiar lectura" + }); + } + } + + + +} \ No newline at end of file diff --git a/backend/src/modules/pump-reading/pumpReading.interface.ts b/backend/src/modules/pump-reading/pumpReading.interface.ts new file mode 100644 index 0000000..340d46a --- /dev/null +++ b/backend/src/modules/pump-reading/pumpReading.interface.ts @@ -0,0 +1,17 @@ +import {ObjectId} from 'mongoose'; + +export interface IPumpReading { + + readingNumber:string; + fuelPumpId:ObjectId; + fuelTypeId:ObjectId; + readingDate:Date; + initialReading:number; + finalReading:number; + gallonsDispensed?:number; + systemDispensed?:number; + difference:number; + createdBy:ObjectId; + status:string; + comments?:string; +} diff --git a/backend/src/modules/pump-reading/pumpReading.model.ts b/backend/src/modules/pump-reading/pumpReading.model.ts new file mode 100644 index 0000000..e8e4181 --- /dev/null +++ b/backend/src/modules/pump-reading/pumpReading.model.ts @@ -0,0 +1,89 @@ +import mongoose from "mongoose"; + +const pumpReadingSchema = new mongoose.Schema({ + + readingNumber:{ + type:String, + required:true, + unique:true + }, + + fuelPumpId:{ + type:mongoose.Schema.Types.ObjectId, + ref:"FuelPump", + required:true + }, + + fuelTypeId:{ + type:mongoose.Schema.Types.ObjectId, + ref:"FuelType", + required:true + }, + + readingDate:{ + type:Date, + required:true + }, + + initialReading:{ + type:Number, + required:true, + min:0 + }, + + finalReading:{ + type:Number, + required:true, + min:0 + }, + + gallonsDispensed:{ + type:Number, + default:0 + }, + + systemDispensed:{ + type:Number, + default:0 + }, + + difference:{ + type:Number, + default:0 + }, + + createdBy:{ + type:mongoose.Schema.Types.ObjectId, + ref:"User", + required:true + }, + + status:{ + type:String, + enum:["ABIERTA", + "CUADRADA", + "CON_DIFERENCIA" + ], + default:"ABIERTA" + + }, + + comments:{ + type:String + } +}, +{ + timestamps:true, + versionKey:false +} + +); + +pumpReadingSchema.pre("save", + function(){ + + this.gallonsDispensed = this.finalReading-this.initialReading; + } +); + +export default mongoose.model("PumpReading",pumpReadingSchema); \ No newline at end of file diff --git a/backend/src/modules/pump-reading/pumpReading.service.ts b/backend/src/modules/pump-reading/pumpReading.service.ts new file mode 100644 index 0000000..28d709a --- /dev/null +++ b/backend/src/modules/pump-reading/pumpReading.service.ts @@ -0,0 +1,282 @@ +import pumpReadingModel from "./pumpReading.model"; +import { IPumpReading } from "./pumpReading.interface"; +import fuelRequestModel from "../fuel-requests/fuelRequest.model"; +import anomalyModel from "../anomalies/anomaly.model"; + + +export class PumpReadingService{ + + //Crear nueva lectura de bomba + + async create( + data:IPumpReading + ){ + data.gallonsDispensed= + data.finalReading- + data.initialReading; + + const pumpReading = new pumpReadingModel(data); + + return await pumpReading.save(); + } + + //Obtener todas las lecturas + + async getAll(){ + + return await pumpReadingModel + .find() + .populate("fuelPumpId") + .populate("fuelTypeId") + .populate("createdBy") + .sort({ + readingDate:-1 + }); + } + + async getById( + id:string + ){ + + return await pumpReadingModel + .findById(id) + .populate("fuelPumpId") + .populate("fuelTypeId") + .populate("createdBy") + } + + async update ( + id:string, + data:Partial + ){ + if( + data.initialReading !== undefined&& + data.finalReading !== undefined + ){ + data.gallonsDispensed = + data.finalReading - + data.initialReading; + } + + return await pumpReadingModel.findByIdAndUpdate( + id, + data, + { + new:true + } + ); + } + + async delete ( + id:string + ){ + return await pumpReadingModel + .findByIdAndDelete + } + + //Calcular galones despachados + + async calculateDispensedGallons( + id:string + ){ + const reading = + await pumpReadingModel.findById(id); + + if(!reading){ + throw new Error( + "Lectura no encontrado" + ); + } + + reading.gallonsDispensed = + reading.finalReading - + reading.initialReading; + await reading.save(); + return reading.gallonsDispensed; + } + + //Calcular galones registrados + + async calculateSystemDispensed( + id:string + ){ + const reading = + await pumpReadingModel.findById(id); + + if(!reading){ + throw new Error ( + "Lectura no encontrada" + ); + } + + const requests = await fuelRequestModel.find({ + + fuelPumpId:reading.fuelPumpId, + createdAt:{ + $gte:reading.readingDate, + $lte:new Date() + } + }); + + const total = requests.reduce( + (sum, request) => + sum + request.gallonQuantity, + 0 + ); + + reading.systemDispensed = total; + await reading.save(); + return total; + } + + //Calcular diferencia + + async calculateDifference( + id:string + ){ + const reading = await pumpReadingModel.findById(id); + + if (!reading) { + throw new Error( + "Lectura no encontrada" + ); + } + + reading.difference = + reading.gallonsDispensed - + reading.systemDispensed; + await reading.save(); + return reading.difference; + } + + //Actualizar estado + + async updateSatatus( + id:string + ){ + const reading = await pumpReadingModel.findById(id); + + if (!reading) { + throw new Error( + "Lectura no encontrada" + ); + } + + if( + reading.difference === 0 + ){ + reading.status = "CUADRADA"; + } + + else{ + reading.status = "CON_DIFERENCIA" + } + + await reading.save(); + return reading.status; + } + + async updateFuelRequests( + id:string + ){ + const reading = await pumpReadingModel.findById(id); + + if(!reading){ + throw new Error( + "Lectura no encontrada" + ); + } + + const requests = await fuelRequestModel.find ({ + fuelPumpId:reading.fuelPumpId, + createdAt:{ + $gte:reading.readingDate, + $lte:new Date() + + } + }); + + for (const request of requests) { + request.pumpReading = + reading._id as any; + + request.pumpDifference = + reading.difference; + await request.save(); + + } + + return requests; + } + + //Crear anomalía por diferencencia + + async creataDifferenfeAnomaly( + id:string + ){ + const reading = await pumpReadingModel.findById(id); + + if(!reading){ + throw new Error ( + "Lectura no encontrada" + ); + } + + if (reading.difference ===0){ + return null; + } + + const anomaly = new anomalyModel({ + vehicleId:0, + + anomalyType: + "DIFERENCIA EN BOMBA", + + description: + `La bomba presenta una diferencia de ${reading.difference} galones`, + + detectedBy: "SISTEMA", + + status: "ABIERTA", + + comments: "Generada automáticamente por el sistema" + }); + + return await anomaly.save(); + } + + async closeReading( + id:string + ){ + + const reading = await pumpReadingModel.findById(id); + + if (!reading){ + throw new Error ( + "Lectura no encontrada" + ); + } + + await this.calculateDispensedGallons(id); + + await this.calculateSystemDispensed(id); + + const difference = await this.calculateDifference(id); + + await this.updateSatatus(id); + + await this.updateFuelRequests(id); + + //Crear anomalía + + if(difference !== 0){ + await this.creataDifferenfeAnomaly(id); + } + + return await pumpReadingModel + .findById(id) + .populate("fuelPumpId") + .populate("fuelTypeId") + .populate("createdBy") + } +} \ No newline at end of file