refactor(server): server-side integration of new recipe modelling

This commit is contained in:
Zhongheng Liu 2025-12-22 03:01:10 +02:00
commit 04a999147c
2 changed files with 23 additions and 4 deletions

View file

@ -167,7 +167,7 @@ public class IngredientController {
Ingredient example = new Ingredient(); Ingredient example = new Ingredient();
example.name = ingredient.name; example.name = ingredient.name;
if (ingredientRepository.exists(Example.of(example))) { if (ingredientRepository.existsById(ingredient.id) || ingredientRepository.exists(Example.of(example))) {
return ResponseEntity.badRequest().build(); return ResponseEntity.badRequest().build();
} }

View file

@ -1,5 +1,6 @@
package server.api; package server.api;
import commons.Ingredient;
import commons.Recipe; import commons.Recipe;
import commons.ws.Topics; import commons.ws.Topics;
@ -21,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import server.database.RecipeIngredientRepository;
import server.database.RecipeRepository; import server.database.RecipeRepository;
import java.util.List; import java.util.List;
@ -31,11 +33,17 @@ import java.util.Optional;
public class RecipeController { public class RecipeController {
private final RecipeRepository recipeRepository; // JPA repository used in this controller private final RecipeRepository recipeRepository; // JPA repository used in this controller
private final SimpMessagingTemplate messagingTemplate; private final SimpMessagingTemplate messagingTemplate;
private final RecipeIngredientRepository recipeIngredientRepository;
private final IngredientController ingredientController;
public RecipeController(RecipeRepository recipeRepository, public RecipeController(RecipeRepository recipeRepository,
SimpMessagingTemplate messagingTemplate) { SimpMessagingTemplate messagingTemplate,
IngredientController ingredientController,
RecipeIngredientRepository recipeIngredientRepository) {
this.recipeRepository = recipeRepository; this.recipeRepository = recipeRepository;
this.messagingTemplate = messagingTemplate; this.messagingTemplate = messagingTemplate;
this.recipeIngredientRepository = recipeIngredientRepository;
this.ingredientController = ingredientController;
} }
/** /**
@ -75,16 +83,21 @@ public class RecipeController {
/** /**
* Mapping for <code>POST /recipe/{id}</code>. * Mapping for <code>POST /recipe/{id}</code>.
* Also creates the ingredient elements if they do not exist.
* @param id The recipe id to replace * @param id The recipe id to replace
* @param recipe The new recipe to be replaced from the original * @param recipe The new recipe to be replaced from the original
* @return The changed recipe; returns 400 Bad Request if the recipe does not exist * @return The changed recipe; returns 400 Bad Request if the recipe does not exist
* @see IngredientController#createIngredient(Ingredient)
*/ */
@PostMapping("/recipe/{id}") @PostMapping("/recipe/{id}")
public ResponseEntity<Recipe> updateRecipe(@PathVariable Long id, @RequestBody Recipe recipe) { public ResponseEntity<Recipe> updateRecipe(@PathVariable Long id, @RequestBody Recipe recipe) {
if (!recipeRepository.existsById(id)) { if (!recipeRepository.existsById(id)) {
return ResponseEntity.badRequest().build(); return ResponseEntity.badRequest().build();
} }
recipe.getIngredients().stream()
.map(recipeIngredient -> recipeIngredient.ingredient)
.forEach(ingredientController::createIngredient);
recipeIngredientRepository.saveAll(recipe.getIngredients());
Recipe saved = recipeRepository.save(recipe); Recipe saved = recipeRepository.save(recipe);
messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved)); messagingTemplate.convertAndSend(Topics.RECIPES, new UpdateRecipeMessage(saved));
@ -93,11 +106,13 @@ public class RecipeController {
/** /**
* Mapping for <code>PUT /recipe/new</code>. * Mapping for <code>PUT /recipe/new</code>.
* Includes same transient object handling as the POST handler.
* <p> * <p>
* Inserts a new recipe into the repository * Inserts a new recipe into the repository
* </p> * </p>
* @param recipe The new recipe as a request body * @param recipe The new recipe as a request body
* @return 200 OK with the recipe you added; or 400 Bad Request if the recipe already exists by name * @return 200 OK with the recipe you added; or 400 Bad Request if the recipe already exists by name
* @see RecipeController#updateRecipe(Long, Recipe)
*/ */
@PutMapping("/recipe/new") @PutMapping("/recipe/new")
public ResponseEntity<Recipe> createRecipe(@RequestBody Recipe recipe) { public ResponseEntity<Recipe> createRecipe(@RequestBody Recipe recipe) {
@ -113,7 +128,11 @@ public class RecipeController {
if (recipeRepository.exists(Example.of(example))) { if (recipeRepository.exists(Example.of(example))) {
return ResponseEntity.badRequest().build(); return ResponseEntity.badRequest().build();
} }
// FIXME reduce code duplication
recipe.getIngredients().stream()
.map(recipeIngredient -> recipeIngredient.ingredient)
.forEach(ingredientController::createIngredient);
recipeIngredientRepository.saveAll(recipe.getIngredients());
Recipe saved = recipeRepository.save(recipe); Recipe saved = recipeRepository.save(recipe);
messagingTemplate.convertAndSend(Topics.RECIPES, new CreateRecipeMessage(saved)); messagingTemplate.convertAndSend(Topics.RECIPES, new CreateRecipeMessage(saved));