package com.recipeapp.pantry; import com.recipeapp.common.ResourceNotFoundException; import com.recipeapp.common.ValidationException; import com.recipeapp.household.HouseholdRepository; import com.recipeapp.household.entity.Household; import com.recipeapp.pantry.dto.*; import com.recipeapp.pantry.entity.PantryItem; import com.recipeapp.recipe.IngredientRepository; import com.recipeapp.recipe.dto.RecipeDetailResponse.CategoryRef; import com.recipeapp.recipe.entity.Ingredient; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.UUID; @Service @Transactional public class PantryServiceImpl implements PantryService { private final PantryItemRepository pantryItemRepository; private final HouseholdRepository householdRepository; private final IngredientRepository ingredientRepository; public PantryServiceImpl(PantryItemRepository pantryItemRepository, HouseholdRepository householdRepository, IngredientRepository ingredientRepository) { this.pantryItemRepository = pantryItemRepository; this.householdRepository = householdRepository; this.ingredientRepository = ingredientRepository; } @Override @Transactional(readOnly = true) public List listItems(UUID householdId) { return pantryItemRepository.findByHouseholdIdOrderByBestBeforeAscNullsLast(householdId) .stream() .map(this::toResponse) .toList(); } @Override public PantryItemResponse createItem(UUID householdId, CreatePantryItemRequest request) { Household household = householdRepository.findById(householdId) .orElseThrow(() -> new ResourceNotFoundException("Household not found")); Ingredient ingredient = null; if (request.ingredientId() != null) { ingredient = ingredientRepository.findById(request.ingredientId()) .orElseThrow(() -> new ResourceNotFoundException("Ingredient not found")); } if (request.ingredientId() == null && (request.customName() == null || request.customName().isBlank())) { throw new ValidationException("Either ingredientId or customName must be provided"); } PantryItem item = new PantryItem(household, ingredient, request.customName(), request.quantity(), request.unit(), request.bestBefore(), request.openedOn()); item = pantryItemRepository.save(item); return toResponse(item); } @Override public PantryItemResponse updateItem(UUID householdId, UUID itemId, UpdatePantryItemRequest request) { PantryItem item = pantryItemRepository.findByIdAndHouseholdId(itemId, householdId) .orElseThrow(() -> new ResourceNotFoundException("Pantry item not found")); if (request.quantity() != null) item.setQuantity(request.quantity()); if (request.unit() != null) item.setUnit(request.unit()); if (request.bestBefore() != null) item.setBestBefore(request.bestBefore()); if (request.openedOn() != null) item.setOpenedOn(request.openedOn()); item = pantryItemRepository.save(item); return toResponse(item); } @Override public void deleteItem(UUID householdId, UUID itemId) { PantryItem item = pantryItemRepository.findByIdAndHouseholdId(itemId, householdId) .orElseThrow(() -> new ResourceNotFoundException("Pantry item not found")); pantryItemRepository.delete(item); } private PantryItemResponse toResponse(PantryItem item) { UUID ingredientId = item.getIngredient() != null ? item.getIngredient().getId() : null; String name = item.getIngredient() != null ? item.getIngredient().getName() : item.getCustomName(); CategoryRef category = null; if (item.getIngredient() != null && item.getIngredient().getCategory() != null) { category = new CategoryRef( item.getIngredient().getCategory().getId(), item.getIngredient().getCategory().getName()); } return new PantryItemResponse( item.getId(), ingredientId, name, category, item.getQuantity(), item.getUnit(), item.getBestBefore(), item.getOpenedOn()); } }