erp-construccion-backend/dist/modules/inventory/services/consumo-obra.service.js

144 lines
5.6 KiB
JavaScript

"use strict";
/**
* ConsumoObraService - Servicio de consumos de materiales
*
* Gestión de consumos de materiales por obra/lote.
*
* @module Inventory
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConsumoObraService = void 0;
class ConsumoObraService {
repository;
constructor(repository) {
this.repository = repository;
}
async findWithFilters(ctx, filters = {}, page = 1, limit = 20) {
const skip = (page - 1) * limit;
const queryBuilder = this.repository
.createQueryBuilder('consumo')
.leftJoinAndSelect('consumo.fraccionamiento', 'fraccionamiento')
.leftJoinAndSelect('consumo.lote', 'lote')
.leftJoinAndSelect('consumo.concepto', 'concepto')
.leftJoinAndSelect('consumo.registeredBy', 'registeredBy')
.where('consumo.tenant_id = :tenantId', { tenantId: ctx.tenantId })
.andWhere('consumo.deleted_at IS NULL');
if (filters.fraccionamientoId) {
queryBuilder.andWhere('consumo.fraccionamiento_id = :fraccionamientoId', {
fraccionamientoId: filters.fraccionamientoId,
});
}
if (filters.loteId) {
queryBuilder.andWhere('consumo.lote_id = :loteId', { loteId: filters.loteId });
}
if (filters.conceptoId) {
queryBuilder.andWhere('consumo.concepto_id = :conceptoId', { conceptoId: filters.conceptoId });
}
if (filters.productId) {
queryBuilder.andWhere('consumo.product_id = :productId', { productId: filters.productId });
}
if (filters.dateFrom) {
queryBuilder.andWhere('consumo.consumption_date >= :dateFrom', { dateFrom: filters.dateFrom });
}
if (filters.dateTo) {
queryBuilder.andWhere('consumo.consumption_date <= :dateTo', { dateTo: filters.dateTo });
}
queryBuilder
.orderBy('consumo.consumption_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.repository.findOne({
where: {
id,
tenantId: ctx.tenantId,
deletedAt: null,
},
relations: ['fraccionamiento', 'lote', 'concepto', 'registeredBy'],
});
}
async create(ctx, dto) {
const consumo = this.repository.create({
tenantId: ctx.tenantId,
createdById: ctx.userId,
registeredById: ctx.userId,
fraccionamientoId: dto.fraccionamientoId,
loteId: dto.loteId,
departamentoId: dto.departamentoId,
conceptoId: dto.conceptoId,
productId: dto.productId,
quantity: dto.quantity,
unitCost: dto.unitCost,
consumptionDate: dto.consumptionDate,
notes: dto.notes,
});
return this.repository.save(consumo);
}
async getStats(ctx, fraccionamientoId) {
const baseQuery = this.repository
.createQueryBuilder('consumo')
.where('consumo.tenant_id = :tenantId', { tenantId: ctx.tenantId })
.andWhere('consumo.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId })
.andWhere('consumo.deleted_at IS NULL');
// Get totals
const totals = await baseQuery
.clone()
.select('COUNT(*)', 'total')
.addSelect('SUM(consumo.quantity)', 'totalQuantity')
.addSelect('SUM(consumo.quantity * COALESCE(consumo.unit_cost, 0))', 'totalCost')
.getRawOne();
// Get by product
const byProduct = await baseQuery
.clone()
.select('consumo.product_id', 'productId')
.addSelect('SUM(consumo.quantity)', 'quantity')
.addSelect('SUM(consumo.quantity * COALESCE(consumo.unit_cost, 0))', 'cost')
.groupBy('consumo.product_id')
.getRawMany();
// Get by concepto
const byConcepto = await baseQuery
.clone()
.select('consumo.concepto_id', 'conceptoId')
.addSelect('SUM(consumo.quantity)', 'quantity')
.addSelect('SUM(consumo.quantity * COALESCE(consumo.unit_cost, 0))', 'cost')
.where('consumo.concepto_id IS NOT NULL')
.groupBy('consumo.concepto_id')
.getRawMany();
return {
totalConsumos: parseInt(totals.total || '0', 10),
totalQuantity: parseFloat(totals.totalQuantity || '0'),
totalCost: parseFloat(totals.totalCost || '0'),
byProduct: byProduct.map((p) => ({
productId: p.productId,
quantity: parseFloat(p.quantity || '0'),
cost: parseFloat(p.cost || '0'),
})),
byConcepto: byConcepto.map((c) => ({
conceptoId: c.conceptoId,
quantity: parseFloat(c.quantity || '0'),
cost: parseFloat(c.cost || '0'),
})),
};
}
async softDelete(ctx, id) {
const consumo = await this.findById(ctx, id);
if (!consumo) {
return false;
}
await this.repository.update({ id, tenantId: ctx.tenantId }, { deletedAt: new Date(), deletedById: ctx.userId });
return true;
}
}
exports.ConsumoObraService = ConsumoObraService;
//# sourceMappingURL=consumo-obra.service.js.map