144 lines
5.6 KiB
JavaScript
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
|