import { ConflictException, Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { CreatePantryItemDto } from './dto/create-pantry-item.dto'; import { CreateInventoryDto } from '../inventory/dto/create-inventory.dto'; import { Prisma } from '@prisma/client'; type PantryQuery = { userId?: number; }; @Injectable() export class PantryService { constructor(private readonly prisma: PrismaService) {} findAll(userId: number) { return this.prisma.pantryItem.findMany({ where: { userId }, include: { product: true, }, orderBy: { product: { name: 'asc' }, }, }); } findAllAdmin(query?: PantryQuery) { return this.prisma.pantryItem.findMany({ where: typeof query?.userId === 'number' ? { userId: query.userId } : {}, include: { user: { select: { id: true, username: true, email: true, }, }, product: { include: { categoryRef: { include: { parent: { include: { parent: true, }, }, }, }, }, }, }, orderBy: [ { user: { username: 'asc' } }, { product: { name: 'asc' } }, ], }); } async create(userId: number, data: CreatePantryItemDto) { const existing = await this.prisma.pantryItem.findUnique({ where: { userId_productId: { userId, productId: data.productId, }, }, }); if (existing) { throw new ConflictException('Produkten finns redan i baslagret'); } return this.prisma.pantryItem.create({ data: { userId, productId: data.productId, location: data.location?.trim() || null, }, include: { product: true }, }); } async remove(userId: number, id: number) { const item = await this.prisma.pantryItem.findFirst({ where: { id, userId }, }); if (!item) { throw new NotFoundException(`PantryItem med id ${id} hittades inte`); } return this.prisma.pantryItem.delete({ where: { id } }); } async removeAdmin(id: number) { const item = await this.prisma.pantryItem.findUnique({ where: { id } }); if (!item) { throw new NotFoundException(`PantryItem med id ${id} hittades inte`); } return this.prisma.pantryItem.delete({ where: { id } }); } private async movePantryItemToInventoryCore( item: { id: number; userId: number; productId: number; location: string | null }, data: CreateInventoryDto, ) { return this.prisma.$transaction(async (tx) => { const inventoryItem = await tx.inventoryItem.create({ data: { userId: item.userId, productId: item.productId, quantity: new Prisma.Decimal(data.quantity), unit: data.unit.trim(), location: data.location?.trim() || item.location || undefined, purchaseDate: data.purchaseDate ? new Date(data.purchaseDate) : undefined, bestBeforeDate: data.bestBeforeDate ? new Date(data.bestBeforeDate) : undefined, brand: data.brand?.trim() || undefined, origin: data.origin?.trim() || undefined, receiptName: data.receiptName?.trim() || undefined, opened: data.opened ?? false, suitableFor: data.suitableFor?.trim() || undefined, comment: data.comment?.trim() || undefined, }, include: { product: true }, }); await tx.pantryItem.delete({ where: { id: item.id } }); return inventoryItem; }); } async moveToInventory(userId: number, pantryItemId: number, data: CreateInventoryDto) { const item = await this.prisma.pantryItem.findFirst({ where: { id: pantryItemId, userId }, }); if (!item) { throw new NotFoundException(`PantryItem med id ${pantryItemId} hittades inte`); } return this.movePantryItemToInventoryCore(item, data); } async moveToInventoryAdmin(pantryItemId: number, data: CreateInventoryDto) { const item = await this.prisma.pantryItem.findUnique({ where: { id: pantryItemId }, }); if (!item) { throw new NotFoundException(`PantryItem med id ${pantryItemId} hittades inte`); } return this.movePantryItemToInventoryCore(item, data); } }