Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { PurchaseRequisition } from '../schemas/requisition.schema'; import { EventBusService } from '../../../../platform/events/event-bus.service'; import { AuditLogService } from '../../../../platform/audit/audit-log.service'; @Injectable() export class RequisitionService { constructor( @InjectModel(PurchaseRequisition.name) private readonly requisitionModel: Model<PurchaseRequisition>, private readonly eventBus: EventBusService, private readonly auditLog: AuditLogService, ) {} async createRequisition(tenantId: string, requesterId: string, data: any, userId: string): Promise<PurchaseRequisition> { const count = await this.requisitionModel.countDocuments({ tenantId }).exec(); const requisitionNumber = `PR-${new Date().getFullYear()}-${(count + 1).toString().padStart(5, '0')}`; const estimatedCost = data.items.reduce((sum: number, item: any) => sum + (item.quantity * item.estimatedPrice), 0); // Mock Budget Check logic if (data.items.some((item: any) => item.costCenter === 'OVER_BUDGET')) { throw new BadRequestException('Request exceeds department budget allocations limit'); } const pr = await this.requisitionModel.create({ ...data, tenantId, requisitionNumber, requesterId, estimatedCost, status: 'submitted', }); await this.eventBus.publish('procurement.requisition.created.v1', { requisitionId: (pr as any)._id.toString(), tenantId, estimatedCost, }, tenantId); await this.auditLog.log({ tenantId, userId, action: 'CREATE', resource: 'PurchaseRequisition', resourceId: (pr as any)._id.toString(), newValues: { requisitionNumber, estimatedCost }, }); return pr; } async getRequisitions(tenantId: string, requesterId?: string): Promise<PurchaseRequisition[]> { const query: any = { tenantId }; if (requesterId) { query.requesterId = requesterId; } return this.requisitionModel.find(query).exec(); } async getRequisitionById(tenantId: string, id: string): Promise<PurchaseRequisition> { const pr = await this.requisitionModel.findOne({ _id: id, tenantId }).exec(); if (!pr) throw new NotFoundException('Purchase Requisition not found'); return pr; } async approveRequisition(tenantId: string, id: string, userId: string): Promise<PurchaseRequisition> { const pr = await this.requisitionModel.findOneAndUpdate( { _id: id, tenantId, status: 'submitted' }, { status: 'approved', approvedBy: userId, approvalDate: new Date() }, { new: true } ).exec(); if (!pr) throw new NotFoundException('Purchase Requisition not found or not in submitted status'); await this.eventBus.publish('procurement.requisition.approved.v1', { requisitionId: id, tenantId, approvedBy: userId, }, tenantId); await this.auditLog.log({ tenantId, userId, action: 'APPROVE', resource: 'PurchaseRequisition', resourceId: id, newValues: { requisitionNumber: pr.requisitionNumber }, }); return pr; } async rejectRequisition(tenantId: string, id: string, userId: string): Promise<PurchaseRequisition> { const pr = await this.requisitionModel.findOneAndUpdate( { _id: id, tenantId, status: 'submitted' }, { status: 'rejected', approvedBy: userId, approvalDate: new Date() }, { new: true } ).exec(); if (!pr) throw new NotFoundException('Purchase Requisition not found or not in submitted status'); await this.eventBus.publish('procurement.requisition.rejected.v1', { requisitionId: id, tenantId, approvedBy: userId, }, tenantId); await this.auditLog.log({ tenantId, userId, action: 'REJECT', resource: 'PurchaseRequisition', resourceId: id, newValues: { requisitionNumber: pr.requisitionNumber }, }); return pr; } } |