"use strict"; /** * AsignacionService - Servicio de asignaciones de vivienda INFONAVIT * * Gestión de asignaciones de vivienda a derechohabientes. * * @module Infonavit */ Object.defineProperty(exports, "__esModule", { value: true }); exports.AsignacionService = void 0; class AsignacionService { asignacionRepository; ofertaRepository; derechohabienteRepository; constructor(asignacionRepository, ofertaRepository, derechohabienteRepository) { this.asignacionRepository = asignacionRepository; this.ofertaRepository = ofertaRepository; this.derechohabienteRepository = derechohabienteRepository; } generateAssignmentNumber() { const now = new Date(); const year = now.getFullYear().toString().slice(-2); const month = (now.getMonth() + 1).toString().padStart(2, '0'); const random = Math.random().toString(36).substring(2, 8).toUpperCase(); return `ASG-${year}${month}-${random}`; } async findWithFilters(ctx, filters = {}, page = 1, limit = 20) { const skip = (page - 1) * limit; const queryBuilder = this.asignacionRepository .createQueryBuilder('asig') .leftJoinAndSelect('asig.oferta', 'oferta') .leftJoinAndSelect('asig.derechohabiente', 'derechohabiente') .leftJoinAndSelect('asig.createdBy', 'createdBy') .where('asig.tenant_id = :tenantId', { tenantId: ctx.tenantId }); if (filters.ofertaId) { queryBuilder.andWhere('asig.oferta_id = :ofertaId', { ofertaId: filters.ofertaId }); } if (filters.derechohabienteId) { queryBuilder.andWhere('asig.derechohabiente_id = :derechohabienteId', { derechohabienteId: filters.derechohabienteId, }); } if (filters.status) { queryBuilder.andWhere('asig.status = :status', { status: filters.status }); } if (filters.dateFrom) { queryBuilder.andWhere('asig.assignment_date >= :dateFrom', { dateFrom: filters.dateFrom }); } if (filters.dateTo) { queryBuilder.andWhere('asig.assignment_date <= :dateTo', { dateTo: filters.dateTo }); } queryBuilder .orderBy('asig.assignment_date', 'DESC') .skip(skip) .take(limit); const [data, total] = await queryBuilder.getManyAndCount(); return { data, meta: { total, page, limit, totalPages: Math.ceil(total / limit), }, }; } async findById(ctx, id) { return this.asignacionRepository.findOne({ where: { id, tenantId: ctx.tenantId, }, }); } async findWithDetails(ctx, id) { return this.asignacionRepository.findOne({ where: { id, tenantId: ctx.tenantId, }, relations: ['oferta', 'oferta.registro', 'derechohabiente', 'createdBy'], }); } async create(ctx, dto) { // Validate oferta exists and is available const oferta = await this.ofertaRepository.findOne({ where: { id: dto.ofertaId, tenantId: ctx.tenantId, }, }); if (!oferta) { throw new Error('Housing offer not found'); } if (oferta.status !== 'available' && oferta.status !== 'reserved') { throw new Error('Housing offer is not available for assignment'); } // Validate derechohabiente exists and is qualified const derechohabiente = await this.derechohabienteRepository.findOne({ where: { id: dto.derechohabienteId, tenantId: ctx.tenantId, deletedAt: null, }, }); if (!derechohabiente) { throw new Error('Worker not found'); } if (derechohabiente.status !== 'qualified' && derechohabiente.status !== 'pre_qualified') { throw new Error('Worker must be pre-qualified or qualified for assignment'); } // Create assignment const asignacion = this.asignacionRepository.create({ tenantId: ctx.tenantId, createdById: ctx.userId, ofertaId: dto.ofertaId, derechohabienteId: dto.derechohabienteId, assignmentNumber: this.generateAssignmentNumber(), assignmentDate: dto.assignmentDate, creditAmount: dto.creditAmount, subsidyAmount: dto.subsidyAmount || 0, downPayment: dto.downPayment || 0, notes: dto.notes, status: 'pending', }); const saved = await this.asignacionRepository.save(asignacion); // Update oferta status oferta.status = 'reserved'; await this.ofertaRepository.save(oferta); return saved; } async approve(ctx, id) { const asignacion = await this.findWithDetails(ctx, id); if (!asignacion) { return null; } if (asignacion.status !== 'pending') { throw new Error('Can only approve pending assignments'); } asignacion.status = 'approved'; asignacion.approvalDate = new Date(); asignacion.updatedById = ctx.userId || ''; // Update oferta status asignacion.oferta.status = 'assigned'; await this.ofertaRepository.save(asignacion.oferta); // Update derechohabiente status await this.derechohabienteRepository.update({ id: asignacion.derechohabienteId }, { status: 'assigned', updatedById: ctx.userId || '' }); return this.asignacionRepository.save(asignacion); } async formalize(ctx, id, dto) { const asignacion = await this.findWithDetails(ctx, id); if (!asignacion) { return null; } if (asignacion.status !== 'approved') { throw new Error('Can only formalize approved assignments'); } asignacion.status = 'formalized'; asignacion.formalizationDate = dto.formalizationDate; asignacion.notaryName = dto.notaryName; asignacion.notaryNumber = dto.notaryNumber; asignacion.deedNumber = dto.deedNumber; asignacion.deedDate = dto.deedDate; asignacion.updatedById = ctx.userId || ''; return this.asignacionRepository.save(asignacion); } async deliver(ctx, id, deliveryDate) { const asignacion = await this.findWithDetails(ctx, id); if (!asignacion) { return null; } if (asignacion.status !== 'formalized') { throw new Error('Can only deliver formalized assignments'); } asignacion.status = 'delivered'; asignacion.deliveryDate = deliveryDate; asignacion.updatedById = ctx.userId || ''; // Update oferta status asignacion.oferta.status = 'delivered'; await this.ofertaRepository.save(asignacion.oferta); return this.asignacionRepository.save(asignacion); } async cancel(ctx, id, reason) { const asignacion = await this.findWithDetails(ctx, id); if (!asignacion) { return null; } if (asignacion.status === 'delivered') { throw new Error('Cannot cancel delivered assignments'); } const previousStatus = asignacion.status; asignacion.status = 'cancelled'; asignacion.notes = `${asignacion.notes || ''}\n[CANCELLED] ${reason}`; asignacion.updatedById = ctx.userId || ''; // Revert oferta status if it was assigned/reserved if (previousStatus === 'approved' || previousStatus === 'formalized') { asignacion.oferta.status = 'available'; await this.ofertaRepository.save(asignacion.oferta); // Revert derechohabiente status await this.derechohabienteRepository.update({ id: asignacion.derechohabienteId }, { status: 'qualified', updatedById: ctx.userId || '' }); } else if (previousStatus === 'pending') { asignacion.oferta.status = 'available'; await this.ofertaRepository.save(asignacion.oferta); } return this.asignacionRepository.save(asignacion); } } exports.AsignacionService = AsignacionService; //# sourceMappingURL=asignacion.service.js.map