erp-construccion-backend/dist/modules/progress/services/bitacora-obra.service.js

133 lines
4.5 KiB
JavaScript

"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