"use strict"; /** * SubcontractorService - Servicio de gestión de subcontratistas * * Catálogo de subcontratistas con evaluaciones. * * @module Contracts */ Object.defineProperty(exports, "__esModule", { value: true }); exports.SubcontractorService = void 0; class SubcontractorService { subcontractorRepository; constructor(subcontractorRepository) { this.subcontractorRepository = subcontractorRepository; } generateCode() { const now = new Date(); const year = now.getFullYear().toString().slice(-2); const random = Math.random().toString(36).substring(2, 6).toUpperCase(); return `SC-${year}-${random}`; } async findWithFilters(ctx, filters = {}, page = 1, limit = 20) { const skip = (page - 1) * limit; const queryBuilder = this.subcontractorRepository .createQueryBuilder('sc') .leftJoinAndSelect('sc.createdBy', 'createdBy') .where('sc.tenant_id = :tenantId', { tenantId: ctx.tenantId }) .andWhere('sc.deleted_at IS NULL'); if (filters.specialty) { queryBuilder.andWhere('sc.primary_specialty = :specialty', { specialty: filters.specialty }); } if (filters.status) { queryBuilder.andWhere('sc.status = :status', { status: filters.status }); } if (filters.search) { queryBuilder.andWhere('(sc.business_name ILIKE :search OR sc.trade_name ILIKE :search OR sc.rfc ILIKE :search)', { search: `%${filters.search}%` }); } if (filters.minRating !== undefined) { queryBuilder.andWhere('sc.average_rating >= :minRating', { minRating: filters.minRating }); } queryBuilder .orderBy('sc.business_name', 'ASC') .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.subcontractorRepository.findOne({ where: { id, tenantId: ctx.tenantId, deletedAt: null, }, }); } async findByRfc(ctx, rfc) { return this.subcontractorRepository.findOne({ where: { rfc: rfc.toUpperCase(), tenantId: ctx.tenantId, deletedAt: null, }, }); } async create(ctx, dto) { // Check for existing RFC const existing = await this.findByRfc(ctx, dto.rfc); if (existing) { throw new Error('A subcontractor with this RFC already exists'); } const subcontractor = this.subcontractorRepository.create({ tenantId: ctx.tenantId, createdById: ctx.userId, code: this.generateCode(), businessName: dto.businessName, tradeName: dto.tradeName, rfc: dto.rfc.toUpperCase(), address: dto.address, phone: dto.phone, email: dto.email, contactName: dto.contactName, contactPhone: dto.contactPhone, primarySpecialty: dto.primarySpecialty, secondarySpecialties: dto.secondarySpecialties, bankName: dto.bankName, bankAccount: dto.bankAccount, clabe: dto.clabe, notes: dto.notes, status: 'active', }); return this.subcontractorRepository.save(subcontractor); } async update(ctx, id, dto) { const subcontractor = await this.findById(ctx, id); if (!subcontractor) { return null; } Object.assign(subcontractor, { ...dto, updatedById: ctx.userId || '', }); return this.subcontractorRepository.save(subcontractor); } async updateRating(ctx, id, rating) { const subcontractor = await this.findById(ctx, id); if (!subcontractor) { return null; } // Calculate new average rating const totalRatings = subcontractor.completedContracts; const currentTotal = subcontractor.averageRating * totalRatings; const newTotal = currentTotal + rating; subcontractor.averageRating = newTotal / (totalRatings + 1); subcontractor.updatedById = ctx.userId || ''; return this.subcontractorRepository.save(subcontractor); } async incrementContracts(ctx, id, completed = false) { const subcontractor = await this.findById(ctx, id); if (!subcontractor) { return null; } subcontractor.totalContracts += 1; if (completed) { subcontractor.completedContracts += 1; } subcontractor.updatedById = ctx.userId || ''; return this.subcontractorRepository.save(subcontractor); } async incrementIncidents(ctx, id) { const subcontractor = await this.findById(ctx, id); if (!subcontractor) { return null; } subcontractor.totalIncidents += 1; subcontractor.updatedById = ctx.userId || ''; return this.subcontractorRepository.save(subcontractor); } async deactivate(ctx, id) { const subcontractor = await this.findById(ctx, id); if (!subcontractor) { return null; } subcontractor.status = 'inactive'; subcontractor.updatedById = ctx.userId || ''; return this.subcontractorRepository.save(subcontractor); } async blacklist(ctx, id, reason) { const subcontractor = await this.findById(ctx, id); if (!subcontractor) { return null; } subcontractor.status = 'blacklisted'; subcontractor.notes = `${subcontractor.notes || ''}\n[BLACKLISTED] ${reason}`; subcontractor.updatedById = ctx.userId || ''; return this.subcontractorRepository.save(subcontractor); } async softDelete(ctx, id) { const subcontractor = await this.findById(ctx, id); if (!subcontractor) { return false; } await this.subcontractorRepository.update({ id, tenantId: ctx.tenantId }, { deletedAt: new Date(), deletedById: ctx.userId || '' }); return true; } async getBySpecialty(ctx, specialty) { return this.subcontractorRepository.find({ where: { tenantId: ctx.tenantId, primarySpecialty: specialty, status: 'active', deletedAt: null, }, order: { averageRating: 'DESC' }, }); } } exports.SubcontractorService = SubcontractorService; //# sourceMappingURL=subcontractor.service.js.map