"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.InventoryService = void 0; const common_1 = require("@nestjs/common"); const client_1 = require("@prisma/client"); const prisma_service_1 = require("../prisma/prisma.service"); let InventoryService = class InventoryService { constructor(prisma) { this.prisma = prisma; this.productWithCategoryInclude = { include: { categoryRef: { include: { parent: { include: { parent: true, }, }, }, }, }, }; } throwInventoryItemNotFound(id) { throw new common_1.NotFoundException(`Inventory item with id ${id} not found`); } async findInventoryItemByIdOrThrow(id) { const existing = await this.prisma.inventoryItem.findUnique({ where: { id } }); if (!existing) { this.throwInventoryItemNotFound(id); } return existing; } async ensureProductExists(productId) { const product = await this.prisma.product.findUnique({ where: { id: productId } }); if (!product) { throw new common_1.NotFoundException('Product not found'); } return product; } async findAll(query) { const where = {}; const orderBy = []; if (query?.location) { where.location = query.location; } if (query?.sort === 'bestBeforeAsc') { orderBy.push({ bestBeforeDate: 'asc' }); } else if (query?.sort === 'bestBeforeDesc') { orderBy.push({ bestBeforeDate: 'desc' }); } else if (query?.sort === 'nameAsc') { orderBy.push({ product: { name: 'asc' } }); } else if (query?.sort === 'purchaseDateAsc') { orderBy.push({ purchaseDate: 'asc' }); } else if (query?.sort === 'purchaseDateDesc') { orderBy.push({ purchaseDate: 'desc' }); } else { orderBy.push({ createdAt: 'desc' }); } return this.prisma.inventoryItem.findMany({ where, include: { product: this.productWithCategoryInclude, }, orderBy, }); } async consume(id, data) { const existing = await this.findInventoryItemByIdOrThrow(id); const currentQuantity = Number(existing.quantity); const newQuantity = Math.max(0, currentQuantity - data.amountUsed); return this.prisma.$transaction(async (tx) => { const updatedItem = await tx.inventoryItem.update({ where: { id }, data: { quantity: new client_1.Prisma.Decimal(newQuantity), }, include: { product: this.productWithCategoryInclude, }, }); await tx.inventoryConsumption.create({ data: { inventoryItemId: id, amountUsed: new client_1.Prisma.Decimal(data.amountUsed), comment: data.comment?.trim() || null, }, }); return updatedItem; }); } async findConsumptionHistory(id) { await this.findInventoryItemByIdOrThrow(id); return this.prisma.inventoryConsumption.findMany({ where: { inventoryItemId: id, }, select: { id: true, inventoryItemId: true, amountUsed: true, comment: true, createdAt: true, inventoryItem: { select: { unit: true }, }, }, orderBy: { createdAt: 'desc', }, }); } async findExpiring() { const now = new Date(); return this.prisma.inventoryItem.findMany({ where: { bestBeforeDate: { not: null, gte: now, }, }, include: { product: true, }, orderBy: [{ bestBeforeDate: 'asc' }, { createdAt: 'desc' }], }); } async create(data) { await this.ensureProductExists(data.productId); return this.prisma.inventoryItem.create({ data: { ...data, quantity: new client_1.Prisma.Decimal(data.quantity), location: data.location?.trim() || undefined, brand: data.brand?.trim() || undefined, origin: data.origin?.trim() || undefined, receiptName: data.receiptName?.trim() || undefined, suitableFor: data.suitableFor?.trim() || undefined, comment: data.comment?.trim() || undefined, purchaseDate: data.purchaseDate ? new Date(data.purchaseDate) : undefined, bestBeforeDate: data.bestBeforeDate ? new Date(data.bestBeforeDate) : undefined, }, include: { product: this.productWithCategoryInclude, }, }); } async update(id, data) { await this.findInventoryItemByIdOrThrow(id); if (typeof data.productId === 'number') { await this.ensureProductExists(data.productId); } const updateData = {}; if (typeof data.productId === 'number') { updateData.product = { connect: { id: data.productId }, }; } if (typeof data.quantity === 'number') { updateData.quantity = new client_1.Prisma.Decimal(data.quantity); } if (typeof data.unit === 'string') { updateData.unit = data.unit.trim(); } if (typeof data.location === 'string') { updateData.location = data.location.trim(); } if (typeof data.brand === 'string') { updateData.brand = data.brand.trim(); } if (typeof data.receiptName === 'string') { updateData.receiptName = data.receiptName.trim(); } if (typeof data.purchaseDate === 'string') { updateData.purchaseDate = data.purchaseDate ? new Date(data.purchaseDate) : null; } if (typeof data.bestBeforeDate === 'string') { updateData.bestBeforeDate = data.bestBeforeDate ? new Date(data.bestBeforeDate) : null; } if (typeof data.opened === 'boolean') { updateData.opened = data.opened; } if (typeof data.suitableFor === 'string') { updateData.suitableFor = data.suitableFor.trim(); } if (typeof data.comment === 'string') { updateData.comment = data.comment.trim(); } return this.prisma.inventoryItem.update({ where: { id }, data: updateData, include: { product: this.productWithCategoryInclude, }, }); } async remove(id) { await this.findInventoryItemByIdOrThrow(id); return this.prisma.inventoryItem.delete({ where: { id } }); } }; exports.InventoryService = InventoryService; exports.InventoryService = InventoryService = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [prisma_service_1.PrismaService]) ], InventoryService); //# sourceMappingURL=inventory.service.js.map