diff --git a/backend/src/main/java/com/example/todoapp/controller/RecipesController.java b/backend/src/main/java/com/example/todoapp/controller/RecipesController.java index b2f97ab..6156ba5 100644 --- a/backend/src/main/java/com/example/todoapp/controller/RecipesController.java +++ b/backend/src/main/java/com/example/todoapp/controller/RecipesController.java @@ -8,6 +8,7 @@ import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -18,6 +19,8 @@ import com.example.todoapp.dto.RecipeDetailDTO; import com.example.todoapp.dto.RecipeRequestDTO; import com.example.todoapp.dto.RecipeResponseDTO; import com.example.todoapp.model.Recipes; +import com.example.todoapp.model.User; +import com.example.todoapp.repository.UserRepository; import com.example.todoapp.service.RecipeService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -36,6 +39,9 @@ public class RecipesController { @Autowired private RecipeService recipeService; + @Autowired + private UserRepository userRepository; + /** * 新しいレシピを作成する * @@ -62,7 +68,12 @@ public class RecipesController { */ @GetMapping("/getAll") public ResponseEntity> getRecipe(Authentication authentication) { + + User user = userRepository.findByUsername(authentication.getName()) + .orElseThrow(() -> new UsernameNotFoundException("User not found")); + List recipes = recipeService.getAllRecipes(); + // エンティティからDTOへの変換 List responseList = recipes.stream() .map(recipe -> { @@ -70,6 +81,7 @@ public class RecipesController { dto.setRecipeId(recipe.getRecipeId()); dto.setRecipeName(recipe.getRecipeName()); dto.setSummary(recipe.getSummary()); + dto.setMaxServings(recipeService.getRecipeMaxServings(user.getId(), recipe)); return dto; }) .collect(Collectors.toList()); diff --git a/backend/src/main/java/com/example/todoapp/dto/RecipeResponseDTO.java b/backend/src/main/java/com/example/todoapp/dto/RecipeResponseDTO.java index 38d69a3..b8d6887 100644 --- a/backend/src/main/java/com/example/todoapp/dto/RecipeResponseDTO.java +++ b/backend/src/main/java/com/example/todoapp/dto/RecipeResponseDTO.java @@ -28,4 +28,10 @@ public class RecipeResponseDTO { * レシピの簡単な説明文 */ private String summary; + + /** + * 最大調理可能数 + * そのレシピを何人分調理可能か + */ + private int maxServings; } diff --git a/backend/src/main/java/com/example/todoapp/repository/ToBuysRepository.java b/backend/src/main/java/com/example/todoapp/repository/ToBuysRepository.java index 0778f5f..24d464f 100644 --- a/backend/src/main/java/com/example/todoapp/repository/ToBuysRepository.java +++ b/backend/src/main/java/com/example/todoapp/repository/ToBuysRepository.java @@ -47,6 +47,17 @@ public interface ToBuysRepository extends JpaRepository { */ @Query("SELECT t FROM ToBuys t WHERE t.user.id = :userId ORDER BY t.tobuyId ASC") List findByUserIdOrderByTobuyIdAsc(@Param("userId") Long userId); + + /** + * 指定された「買うもの」IDに基づいて「買うもの」での数量を更新 + * + * @param tobuyId 「買うもの」ID + * @param amount 「買うもの」数量 + * @return 更新された行数 + */ + @Modifying + @Query("UPDATE ToBuys t SET t.amount = :amount WHERE t.tobuyId = :tobuyId") + int updateAmountByTobuyId(Long tobuyId, int amount); /** * 指定された「買うもの」IDに基づいて「買うもの」リストを削除 diff --git a/backend/src/main/java/com/example/todoapp/service/RecipeService.java b/backend/src/main/java/com/example/todoapp/service/RecipeService.java index 3329420..ad27f08 100644 --- a/backend/src/main/java/com/example/todoapp/service/RecipeService.java +++ b/backend/src/main/java/com/example/todoapp/service/RecipeService.java @@ -49,6 +49,9 @@ public class RecipeService { @Autowired private RecipeStuffsRepository recipeStuffsRepository; + @Autowired + private StocksService stockService; + /** * レシピを新規登録する * @@ -102,6 +105,34 @@ public class RecipeService { return recipesRepository.findAll(); } + /** + * レシピを指定して,現在の在庫を参照しそのレシピが最大何人分作れるか返す + * + * @param userId ユーザーID + * @param recipe レシピのエンティティ + * @throws RuntimeException レシピが材料を持たないなど,計算に失敗したとき + * @return 最大何人分作れるか + */ + public int getRecipeMaxServings(Long userId, Recipes recipe) { + + List recipeStuffs = recipeStuffsRepository.findByRecipesRecipeId(recipe.getRecipeId()); + + // 各材料がその料理のレシピで何人分在庫があるか計算し,それらの最小値が料理全体での人数になる + Integer minNServings = null; + for (RecipeStuffs recipeStuff : recipeStuffs) { + int stockAmount = stockService.calcAmountByStuffId(userId, recipeStuff.getStuff().getStuffId()); + int nServings = stockAmount / recipeStuff.getAmount(); // 小数点以下切り捨て(整数除算) + if (minNServings == null || minNServings > nServings) { + minNServings = nServings; + } + } + + // recipeStuffs が空の場合などに null のままになる(通常は起こりえない) + if (minNServings == null) throw new RuntimeException("Failed to calculate recipeMaxServings"); + + return minNServings; + } + /** * 指定されたIDのレシピ詳細情報を取得する * diff --git a/backend/src/main/java/com/example/todoapp/service/ToBuysService.java b/backend/src/main/java/com/example/todoapp/service/ToBuysService.java index d88d629..ddf5681 100644 --- a/backend/src/main/java/com/example/todoapp/service/ToBuysService.java +++ b/backend/src/main/java/com/example/todoapp/service/ToBuysService.java @@ -174,6 +174,16 @@ public class ToBuysService { return toBuysRepository.findByUserIdOrderByTobuyIdAsc(user.getId()); } + /** + * 指定された購入リストIDに基づいて「数量」を変更する + * + * @param tobuyId 購入リストID + */ + @Transactional + public int updateToBuysAmountByTobuyId(Long tobuyId, int amount) { + return toBuysRepository.updateAmountByTobuyId(tobuyId, amount); + } + /** * 指定された購入リストIDに基づいて「買うもの」を削除する * @@ -210,9 +220,17 @@ public class ToBuysService { stock.setBuyDate(dto.getBuyDate()); stock.setExpDate(dto.getExpDate()); - // 買うものリストから削除 + // まだ買うべき数量を計算 + int remainAmount = Math.max(tobuy.getAmount() - dto.getAmount(), 0); + System.out.println("remainAmount=" + remainAmount); + + // 買うものリストから削除または数量変更 System.out.println("tobuy.getTobuyId()=" + tobuy.getTobuyId()); - deleteToBuysByTobuyId(tobuy.getTobuyId()); + if (remainAmount > 0) { + updateToBuysAmountByTobuyId(tobuy.getTobuyId(), remainAmount); + } else { + deleteToBuysByTobuyId(tobuy.getTobuyId()); + } // データベースに保存 return stocksRepository.save(stock); diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts index 8aacbc6..72a1094 100644 --- a/frontend/src/services/api.ts +++ b/frontend/src/services/api.ts @@ -456,7 +456,12 @@ export const recipeApi = { errorData?.message ); } - return response.json(); + + // デバッグ用に表示 + const recipes = response.json(); + console.log('recipes: ', recipes); + + return recipes; }, /** diff --git a/frontend/src/types/types.ts b/frontend/src/types/types.ts index bd64d97..dc970d7 100644 --- a/frontend/src/types/types.ts +++ b/frontend/src/types/types.ts @@ -142,7 +142,8 @@ export interface Recipe { } export interface RecipeWithId extends Recipe { - recipeId: number; + recipeId: number; // レシピID + maxServings: number; // 最大調理可能数 } /**