From 4c34f207058c04ba53a6e99bf1ba681db73d6974 Mon Sep 17 00:00:00 2001 From: karol Date: Fri, 3 Jul 2026 16:48:09 +0000 Subject: [PATCH] =?UTF-8?q?Actualizaci=C3=B3n=20CRUD=20m=C3=B3dulo=20factu?= =?UTF-8?q?ras=20externas=20y=20adici=C3=B3n=20de=20validaciones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../externalInvoice.interface.ts | 22 +++- .../externalInvoice.model.ts | 40 +++--- .../externalInvoice.routes.ts | 16 +-- .../externalInvoice.service.ts | 122 +++++++++++------- 4 files changed, 122 insertions(+), 78 deletions(-) diff --git a/backend/src/modules/external-invoices/externalInvoice.interface.ts b/backend/src/modules/external-invoices/externalInvoice.interface.ts index 2ba840f..f66d2dc 100644 --- a/backend/src/modules/external-invoices/externalInvoice.interface.ts +++ b/backend/src/modules/external-invoices/externalInvoice.interface.ts @@ -1,4 +1,4 @@ -import { ObjectId } from "mongoose"; +import { Types } from "mongoose"; export interface IExternalInvoice { @@ -14,22 +14,32 @@ export interface IExternalInvoice { departmentId:number; - fuelTypeId:ObjectId; + fuelTypeId:Types.ObjectId; invoiceDate:Date; - gallons:number; + gallonQuantity: number; pricePerGallon:number; totalAmount?:number; - createdBy:ObjectId; + previousMileage: number; - approvedBy?:ObjectId; + currentMileage: number; + + distanceTraveled?: number; + + createdBy:Types.ObjectId; + + approvedBy?:Types.ObjectId; comments?:string; - status:string; + odometerWorking: boolean; + status: + | "PENDIENTE" + | "APROBADO" + | "RECHAZADO"; } \ No newline at end of file diff --git a/backend/src/modules/external-invoices/externalInvoice.model.ts b/backend/src/modules/external-invoices/externalInvoice.model.ts index e42094f..0e2fa82 100644 --- a/backend/src/modules/external-invoices/externalInvoice.model.ts +++ b/backend/src/modules/external-invoices/externalInvoice.model.ts @@ -43,7 +43,7 @@ const externalInvoiceSchema = new mongoose.Schema({ required:true }, - gallons:{ + gallonQuantity:{ type:Number, required:true }, @@ -58,6 +58,21 @@ const externalInvoiceSchema = new mongoose.Schema({ default:0 }, + previousMileage:{ + type:Number, + required:true, + }, + + currentMileage:{ + type:Number, + required:true + }, + + distanceTraveled:{ + type:Number, + default:0 + }, + createdBy:{ type:mongoose.Schema.Types.ObjectId, ref:"User", @@ -73,6 +88,12 @@ const externalInvoiceSchema = new mongoose.Schema({ type:String }, + odometerWorking:{ + type:Boolean, + default:true + + }, + status:{ type:String, enum:[ @@ -89,20 +110,5 @@ const externalInvoiceSchema = new mongoose.Schema({ versionKey:false }); -//Calcular total antes de guardar -externalInvoiceSchema.pre( - "save", - async function () { - - this.totalAmount = - this.gallons * - this.pricePerGallon; - - } -); - -export default mongoose.model( - "ExternalInvoice", - externalInvoiceSchema -); \ No newline at end of file +export default mongoose.model( "ExternalInvoice", externalInvoiceSchema); \ No newline at end of file diff --git a/backend/src/modules/external-invoices/externalInvoice.routes.ts b/backend/src/modules/external-invoices/externalInvoice.routes.ts index 79d515e..a27f182 100644 --- a/backend/src/modules/external-invoices/externalInvoice.routes.ts +++ b/backend/src/modules/external-invoices/externalInvoice.routes.ts @@ -12,6 +12,14 @@ const controller = new ExternalInvoiceController(); invoicerouter.get("/", authMiddleware, controller.getAll); +//Buscar por estado + +invoicerouter.get("/status/:status", authMiddleware, controller.getByStatus); + +//Buscar por zona + +invoicerouter.get("/zone/:zone", authMiddleware, controller.getByZone); + //Obtener factura por ID invoicerouter.get("/:id", authMiddleware, controller.getById); @@ -24,14 +32,6 @@ invoicerouter.post("/", authMiddleware, controller.create); invoicerouter.put("/:id", authMiddleware, controller.update); -//Buscar por estado - -invoicerouter.get("/status/:status", authMiddleware, controller.getByStatus); - -//Buscar por zona - -invoicerouter.get("/zone/:zone", authMiddleware, controller.getByZone); - //Eliminar factura invoicerouter.delete("/:id", authMiddleware, controller.delete); diff --git a/backend/src/modules/external-invoices/externalInvoice.service.ts b/backend/src/modules/external-invoices/externalInvoice.service.ts index 36765d3..152d9bc 100644 --- a/backend/src/modules/external-invoices/externalInvoice.service.ts +++ b/backend/src/modules/external-invoices/externalInvoice.service.ts @@ -1,31 +1,15 @@ -import ExternalInvoiceModel from "./externalInvoice.model"; - +import externalInvoiceModel from "./externalInvoice.model"; import { IExternalInvoice } from "./externalInvoice.interface"; + + export class ExternalInvoiceService { - //Crear factura externa - - async create( - data: IExternalInvoice - ) { - - // Calcular monto total - data.totalAmount = - data.gallons * - data.pricePerGallon; - const invoice = - new ExternalInvoiceModel(data); - - return await invoice.save(); - - } //Obtener todas las facturas - async getAll() { - return await ExternalInvoiceModel + return await externalInvoiceModel .find() .populate("fuelTypeId") .populate("createdBy") @@ -36,13 +20,13 @@ export class ExternalInvoiceService { } + // Obtener factura por ID - async getById( id: string ) { - return await ExternalInvoiceModel + return await externalInvoiceModel .findById(id) .populate("fuelTypeId") .populate("createdBy") @@ -50,69 +34,113 @@ export class ExternalInvoiceService { } + + //Crear factura externa + async create( + data: IExternalInvoice + ) { + + if(data.currentMileage < data.previousMileage) { + throw new Error ("El kilometraje no puede ser menor que el anterior"); + } + + //Validar que los galones sean mayor a 0 + if(data.gallonQuantity <= 0){ + throw new Error ("La cantidad de galones debe ser mayor que 0"); + } + + // Calcular monto total + data.totalAmount = data.gallonQuantity * data.pricePerGallon; + + //Calcular distancia recorrida + data.distanceTraveled = data.currentMileage - data.previousMileage; + + const invoice = new externalInvoiceModel(data); + + return await invoice.save(); + + } + + //Actualizar factura - async update( id: string, data: Partial ) { - // Recalcular total si cambian datos - if ( - data.gallons && - data.pricePerGallon - ) { - - data.totalAmount = - data.gallons * - data.pricePerGallon; - + const invoice = await externalInvoiceModel.findById(id); + + if(!invoice){ + return null; + } + + const previousMileage = data.previousMileage ?? invoice.previousMileage; + + const currentMileage = data.currentMileage ?? invoice.currentMileage; + + const gallonQuantity = data.gallonQuantity ?? invoice.gallonQuantity; + + const pricePerGallon = data.pricePerGallon ?? invoice.pricePerGallon; + + //Recalcular distancia recorrida + data.distanceTraveled = currentMileage - previousMileage; + + //Validar kilometraje + + if(data.distanceTraveled < 0){ + throw new Error("El kilometraje actual no puede ser menor que el anterior"); } - return await ExternalInvoiceModel - .findByIdAndUpdate( - id, - data, - { - new: true - } - ); + + data.totalAmount = gallonQuantity * pricePerGallon; + + + + const updateInvoice = await externalInvoiceModel.findByIdAndUpdate( + id, + data, + { + new:true + } + ); + + return updateInvoice; } + // Buscar por estado - async getByStatus( status: string ) { - return await ExternalInvoiceModel + return await externalInvoiceModel .find({ status } as any); } + // Buscar por zona - async getByZone( zone: string ) { - return await ExternalInvoiceModel + return await externalInvoiceModel .find({ zone } as any); } + //Eliminar factura - async delete( id: string ) { - return await ExternalInvoiceModel + return await externalInvoiceModel .findByIdAndDelete(id); }