Modificación CRUD módulo aprobaciones

This commit is contained in:
2026-07-04 14:40:16 +00:00
parent 2c8e5ad894
commit 432e89110c
6 changed files with 193 additions and 287 deletions

View File

@ -6,9 +6,8 @@ const service = new ApprovalService();
export class ApprovalController { export class ApprovalController {
/** //Obtener todas las aprobaciones
* Obtener todas las aprobaciones
*/
async getAll( async getAll(
req: Request, req: Request,
res: Response res: Response
@ -36,9 +35,8 @@ export class ApprovalController {
} }
/** //Obtener aprobación por ID
* Obtener aprobación por ID
*/
async getById( async getById(
req: Request, req: Request,
res: Response res: Response
@ -54,34 +52,26 @@ export class ApprovalController {
if (!approval) { if (!approval) {
return res.status(404).json({ return res.status(404).json({
message: message:"Aprobación no encontrada"
"Aprobación no encontrada"
}); });
} }
res.json( res.json(approval);
approval
);
} } catch(error){
catch (error:any) {
console.error(error);
res.status(500).json({ res.status(500).json({
message: "Error al aprobar solicitud", message: "Error al obtener solicitud",
error: error.message, error
stack: error.stack
}); });
} }
} }
/** //Crear aprobación
* Crear aprobación
*/
async create( async create(
req: Request, req: Request,
res: Response res: Response
@ -89,8 +79,7 @@ export class ApprovalController {
try { try {
const approval = const approval = await service.create(
await service.create(
req.body req.body
); );
@ -98,12 +87,9 @@ export class ApprovalController {
approval approval
); );
} } catch (error) {
catch (error) {
res.status(500).json({ res.status(500).json({
message: message:"Error al crear aprobación",
"Error al crear aprobación",
error error
}); });
@ -111,9 +97,8 @@ export class ApprovalController {
} }
/** //Aprobar solicitud
* Aprobar solicitud
*/
async approve( async approve(
req: Request, req: Request,
res: Response res: Response
@ -121,27 +106,20 @@ export class ApprovalController {
try { try {
const approval = const approval = await service.approve(
await service.approve(
req.params.id as string, req.params.id as string,
req.body.approvedBy, req.body.approvedBy,
req.body.comments req.body.comments
); );
res.json( res.json(approval);
approval
);
} } catch (error) {
catch (error) {
res.status(500).json({ res.status(500).json({
message: message:"Error al aprobar solicitud",
"Error al aprobar solicitud",
error error
}); });
@ -149,9 +127,8 @@ export class ApprovalController {
} }
/** //Rechazar solicitud
* Rechazar solicitud
*/
async reject( async reject(
req: Request, req: Request,
res: Response res: Response
@ -159,27 +136,18 @@ export class ApprovalController {
try { try {
const approval = const approval = await service.reject(
await service.reject(
req.params.id as string, req.params.id as string,
req.body.approvedBy, req.body.approvedBy,
req.body.comments req.body.comments
); );
res.json( res.json(approval);
approval
);
} }catch (error) {
catch (error) {
res.status(500).json({ res.status(500).json({
message: message:"Error al rechazar solicitud",
"Error al rechazar solicitud",
error error
}); });
@ -187,9 +155,8 @@ export class ApprovalController {
} }
/** //Buscar por estado
* Buscar por estado
*/
async getByStatus( async getByStatus(
req: Request, req: Request,
res: Response res: Response
@ -197,21 +164,16 @@ export class ApprovalController {
try { try {
const approvals = const approvals = await service.getByStatus(
await service.getByStatus(
req.params.status as string req.params.status as string
); );
res.json( res.json(approvals);
approvals
);
} } catch (error) {
catch (error) {
res.status(500).json({ res.status(500).json({
message: message:"Error al buscar aprobaciones",
"Error al buscar aprobaciones",
error error
}); });
@ -219,9 +181,8 @@ export class ApprovalController {
} }
/** //Buscar por tipo de referencia
* Buscar por tipo de referencia
*/
async getByReferenceType( async getByReferenceType(
req: Request, req: Request,
res: Response res: Response
@ -229,21 +190,16 @@ export class ApprovalController {
try { try {
const approvals = const approvals = await service.getByReferenceType(
await service.getByReferenceType(
req.params.referenceType as string req.params.referenceType as string
); );
res.json( res.json(approvals);
approvals
);
} } catch (error) {
catch (error) {
res.status(500).json({ res.status(500).json({
message: message:"Error al buscar aprobaciones",
"Error al buscar aprobaciones",
error error
}); });
@ -251,9 +207,8 @@ export class ApprovalController {
} }
/** // Eliminar aprobación
* Eliminar aprobación
*/
async delete( async delete(
req: Request, req: Request,
res: Response res: Response
@ -261,31 +216,26 @@ export class ApprovalController {
try { try {
const approval = const approval = await service.delete(
await service.delete(
req.params.id as string req.params.id as string
); );
if (!approval) { if (!approval) {
return res.status(404).json({ return res.status(404).json({
message: message:"Aprobación no encontrada"
"Aprobación no encontrada"
}); });
} }
res.json({ res.json({
message: message: "Aprobación eliminada correctamente"
"Aprobación eliminada correctamente"
}); });
} } catch (error) {
catch (error) {
res.status(500).json({ res.status(500).json({
message: message:"Error al eliminar aprobación",
"Error al eliminar aprobación",
error error
}); });

View File

@ -1,16 +1,19 @@
import { ObjectId } from "mongoose"; import { Types } from "mongoose";
export interface IApproval { export interface IApproval {
referenceType:string; referenceType:string;
referenceId:ObjectId; referenceId:Types.ObjectId;
approvedBy?:ObjectId; approvedBy?:Types.ObjectId;
approvedDate?:Date; approvedDate?:Date;
status:string; status:
| "PENDIENTE"
| "APROBADO"
| "RECHAZADO";
comments?:string; comments?:string;

View File

@ -40,7 +40,4 @@ new mongoose.Schema({
timestamps:true timestamps:true
}); });
export default mongoose.model( export default mongoose.model("Approval", approvalSchema);
"Approval",
approvalSchema
);

View File

@ -1,11 +1,7 @@
import ApprovalModel from "./approval.model"; import ApprovalModel from "./approval.model";
import FuelRequestModel from "../fuel-requests/fuelRequest.model"; import FuelRequestModel from "../fuel-requests/fuelRequest.model";
import externalInvoiceModel from "../external-invoices/externalInvoice.model"; import externalInvoiceModel from "../external-invoices/externalInvoice.model";
import lpgModel from "../lpg/lpg.model"; import lpgModel from "../lpg/lpg.model";
import { IApproval } from "./approval.interface"; import { IApproval } from "./approval.interface";
@ -42,8 +38,18 @@ export class ApprovalService {
data: IApproval data: IApproval
) { ) {
const approval = const exists = await ApprovalModel.findOne({
new ApprovalModel(data); referenceType: data.referenceType,
referenceId: data.referenceId
});
if (exists) {
throw new Error(
"La solicitud ya tiene una aprobación registrada."
);
}
const approval = new ApprovalModel(data);
return await approval.save(); return await approval.save();
@ -57,105 +63,72 @@ export class ApprovalService {
) { ) {
// Buscar aprobación // Buscar aprobación
const approval = const approval = await ApprovalModel.findById(
await ApprovalModel.findById(
approvalId approvalId
); );
if (!approval) { if (!approval) {
throw new Error( throw new Error(
"Aprobación no encontrada" "Aprobación no encontrada"
); );
} }
// Actualizar aprobación // Validar que aún esté pendiente
approval.status = if (approval.status !== "PENDIENTE") {
"APROBADO"; throw new Error("Esta solicitud ya fue procesada.");
}
approval.approvedBy = // Actualizar datos de la aprobación
approvedBy as any; approval.status = "APROBADO";
approval.approvedDate = approval.approvedBy = approvedBy as any;
new Date();
approval.comments = approval.approvedDate = new Date();
comments || "";
approval.comments = comments || "";
await approval.save(); await approval.save();
if ( // Actualizar el documento relacionado
approval.referenceType === if (approval.referenceType === "FuelRequest") {
"FuelRequest"
) {
await FuelRequestModel
.findByIdAndUpdate(
await FuelRequestModel.findByIdAndUpdate(
approval.referenceId, approval.referenceId,
{ {
status: status: "APROBADO"
"APROBADO"
}, },
{ {
new: true new: true
} }
); );
} } else if (approval.referenceType === "ExternalInvoice") {
if (
approval.referenceType ===
"ExternalInvoice"
) {
await externalInvoiceModel
.findByIdAndUpdate(
await externalInvoiceModel.findByIdAndUpdate(
approval.referenceId, approval.referenceId,
{ {
status: status: "APROBADO"
"APROBADO"
}, },
{ {
new: true new: true
} }
); );
} } else if (approval.referenceType === "LPG") {
if (
approval.referenceType ===
"LPG"
) {
await lpgModel
.findByIdAndUpdate(
await lpgModel.findByIdAndUpdate(
approval.referenceId, approval.referenceId,
{ {
status: status: "APROBADO"
"APROBADO"
}, },
{ {
new: true new: true
} }
); );
}
}
return approval; return approval;
} }
//Rechazar solicitud //Rechazar solicitud
@ -167,104 +140,70 @@ export class ApprovalService {
) { ) {
// Buscar aprobación // Buscar aprobación
const approval = const approval = await ApprovalModel.findById(
await ApprovalModel.findById(
approvalId approvalId
); );
if (!approval) { if (!approval) {
throw new Error("Aprobación no encontrada");
throw new Error(
"Aprobación no encontrada"
);
} }
// Actualizar aprobación // Validar que aún esté pendiente
approval.status = if (approval.status !== "PENDIENTE") {
"RECHAZADO"; throw new Error("Esta solicitud ya fue procesada.");
}
approval.approvedBy = // Actualizar datos de la aprobación
approvedBy as any; approval.status = "RECHAZADO";
approval.approvedDate = approval.approvedBy = approvedBy as any;
new Date();
approval.comments = approval.approvedDate = new Date();
comments || "";
approval.comments = comments || "";
await approval.save(); await approval.save();
if ( // Actualizar el documento relacionado
approval.referenceType === if (approval.referenceType === "FuelRequest") {
"FuelRequest"
) {
await FuelRequestModel
.findByIdAndUpdate(
await FuelRequestModel.findByIdAndUpdate(
approval.referenceId, approval.referenceId,
{ {
status: status: "RECHAZADO"
"RECHAZADO"
}, },
{ {
new: true new: true
} }
); );
} } else if (approval.referenceType === "ExternalInvoice") {
if (
approval.referenceType ===
"ExternalInvoice"
) {
await externalInvoiceModel
.findByIdAndUpdate(
await externalInvoiceModel.findByIdAndUpdate(
approval.referenceId, approval.referenceId,
{ {
status: status: "RECHAZADO"
"RECHAZADO"
}, },
{ {
new: true new: true
} }
); );
} } else if (approval.referenceType === "LPG") {
if (
approval.referenceType ===
"LPG"
) {
await lpgModel
.findByIdAndUpdate(
await lpgModel.findByIdAndUpdate(
approval.referenceId, approval.referenceId,
{ {
status: status: "RECHAZADO"
"RECHAZADO"
}, },
{ {
new: true new: true
} }
); );
} }
return approval; return approval;
} }
//Obtener aprobaciones por estado //Obtener aprobaciones por estado

View File

@ -1,17 +1,30 @@
import {ObjectId} from 'mongoose'; import {Types} from 'mongoose';
export interface IPumpReading { export interface IPumpReading {
readingNumber:string; readingNumber?:string;
fuelPumpId:ObjectId;
fuelTypeId:ObjectId; fuelPumpId:Types.ObjectId;
fuelTypeId:Types.ObjectId;
readingDate:Date; readingDate:Date;
initialReading:number; initialReading:number;
finalReading:number; finalReading:number;
gallonsDispensed?:number; gallonsDispensed?:number;
systemDispensed?:number; systemDispensed?:number;
difference:number;
createdBy:ObjectId; difference?:number;
status:string;
createdBy:Types.ObjectId;
status?:
| "ABIERTA"
| "CUADRADA"
| "CON_DIFERENCIA";
comments?:string; comments?:string;
} }

View File

@ -5,3 +5,7 @@ export const generateRequestNumber = ():string =>{
export const generateRequestLPGNumber =():string =>{ export const generateRequestLPGNumber =():string =>{
return `LPG-${Date.now()}`; return `LPG-${Date.now()}`;
} }
export const generatePumpReadingNumber = (): string => {
return `PR-${Date.now()}`;
};