"use strict"; /** * BitacoraObraService - Bitácora de Obra * * Gestiona el registro diario de bitácora de obra. * Genera automáticamente el número de entrada secuencial. * * @module Progress */ Object.defineProperty(exports, "__esModule", { value: true }); exports.BitacoraObraService = void 0; const base_service_1 = require("../../../shared/services/base.service"); class BitacoraObraService extends base_service_1.BaseService { constructor(repository) { super(repository); } /** * Crear nueva entrada de bitácora */ async createEntry(ctx, data) { const entryNumber = await this.getNextEntryNumber(ctx, data.fraccionamientoId); return this.create(ctx, { ...data, entryNumber, registeredById: ctx.userId, }); } /** * Obtener siguiente número de entrada */ async getNextEntryNumber(ctx, fraccionamientoId) { const result = await this.repository .createQueryBuilder('b') .select('MAX(b.entry_number)', 'maxNumber') .where('b.tenant_id = :tenantId', { tenantId: ctx.tenantId }) .andWhere('b.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId }) .getRawOne(); return (result?.maxNumber || 0) + 1; } /** * Obtener bitácora por fraccionamiento */ async findByFraccionamiento(ctx, fraccionamientoId, page = 1, limit = 20) { return this.findAll(ctx, { page, limit, where: { fraccionamientoId }, }); } /** * Obtener bitácora con filtros */ async findWithFilters(ctx, fraccionamientoId, filters, page = 1, limit = 20) { const qb = this.repository .createQueryBuilder('b') .where('b.tenant_id = :tenantId', { tenantId: ctx.tenantId }) .andWhere('b.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId }) .andWhere('b.deleted_at IS NULL'); if (filters.dateFrom) { qb.andWhere('b.entry_date >= :dateFrom', { dateFrom: filters.dateFrom }); } if (filters.dateTo) { qb.andWhere('b.entry_date <= :dateTo', { dateTo: filters.dateTo }); } if (filters.hasIncidents !== undefined) { if (filters.hasIncidents) { qb.andWhere('b.incidents IS NOT NULL'); } else { qb.andWhere('b.incidents IS NULL'); } } const skip = (page - 1) * limit; qb.orderBy('b.entry_date', 'DESC').skip(skip).take(limit); const [data, total] = await qb.getManyAndCount(); return { data, meta: { total, page, limit, totalPages: Math.ceil(total / limit), }, }; } /** * Obtener entrada por fecha */ async findByDate(ctx, fraccionamientoId, date) { return this.findOne(ctx, { fraccionamientoId, entryDate: date, }); } /** * Obtener última entrada */ async findLatest(ctx, fraccionamientoId) { const entries = await this.find(ctx, { where: { fraccionamientoId }, order: { entryNumber: 'DESC' }, take: 1, }); return entries[0] || null; } /** * Obtener estadísticas de bitácora */ async getStats(ctx, fraccionamientoId) { const totalEntries = await this.count(ctx, { fraccionamientoId }); const incidentsCount = await this.repository .createQueryBuilder('b') .where('b.tenant_id = :tenantId', { tenantId: ctx.tenantId }) .andWhere('b.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId }) .andWhere('b.deleted_at IS NULL') .andWhere('b.incidents IS NOT NULL') .getCount(); const avgWorkers = await this.repository .createQueryBuilder('b') .select('AVG(b.workers_count)', 'avg') .where('b.tenant_id = :tenantId', { tenantId: ctx.tenantId }) .andWhere('b.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId }) .andWhere('b.deleted_at IS NULL') .getRawOne(); return { totalEntries, entriesWithIncidents: incidentsCount, avgWorkersCount: parseFloat(avgWorkers?.avg || '0'), }; } } exports.BitacoraObraService = BitacoraObraService; //# sourceMappingURL=bitacora-obra.service.js.map