Outside-in TDD for all 5 remaining domains (128 tests total): - Recipe: CRUD, ingredients autocomplete/patch, tags, categories (27 tests) - Planning: week plans, slots, confirm, suggestions, variety score, cooking logs (24 tests) - Shopping: generate from plan, publish, check/add/remove items (15 tests) - Pantry: CRUD with expiry sorting (11 tests) - Admin: user management, password reset, audit logging (13 tests) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
99 lines
4.3 KiB
Java
99 lines
4.3 KiB
Java
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<PantryItemResponse> 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());
|
|
}
|
|
}
|