Skip to content
Snippets Groups Projects
Commit 98db15de authored by Stian Lyng Stræte's avatar Stian Lyng Stræte
Browse files

Merge branch 'enhance-weekly-menu-suggestion' into 'main'

enhanced weekly menu

See merge request idatt2106-v23-03/backend!219
parents afa187a8 734030fa
No related branches found
No related tags found
No related merge requests found
......@@ -4,7 +4,6 @@ import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.RestController;
import lombok.AllArgsConstructor;
import ntnu.idatt2016.v233.SmartMat.dto.response.RecipeFridgeMatch;
import ntnu.idatt2016.v233.SmartMat.entity.Recipe;
import ntnu.idatt2016.v233.SmartMat.service.RecipeService;
......@@ -56,17 +55,6 @@ public class RecipeController {
return ResponseEntity.ok(recipes);
}
@GetMapping("/match/{fridgeId}/{recipeId}")
public ResponseEntity<List<RecipeFridgeMatch>> getRecipeWithByProductsInFridge(
@PathVariable("fridgeId") Long fridgeId, @PathVariable("recipeId") Long recipeId) {
List<RecipeFridgeMatch> recipe = recipeService.getRecipeWithFridgeProductMatch(fridgeId, recipeId);
if (recipe.isEmpty()) {
return ResponseEntity.notFound().build();
} else {
return ResponseEntity.ok(recipe);
}
}
/**
* add recipe to favorites in user
......
......@@ -9,7 +9,9 @@ import java.util.List;
import org.springframework.http.ResponseEntity;
import lombok.AllArgsConstructor;
import ntnu.idatt2016.v233.SmartMat.dto.response.RecipeWithMatchCount;
import ntnu.idatt2016.v233.SmartMat.dto.response.WeeklyMenuResponse;
import ntnu.idatt2016.v233.SmartMat.service.RecipeService;
import ntnu.idatt2016.v233.SmartMat.service.WeeklyMenuService;
@AllArgsConstructor
......@@ -17,6 +19,7 @@ import ntnu.idatt2016.v233.SmartMat.service.WeeklyMenuService;
@RequestMapping("/api/weeklymenu")
public class WeeklyMenuController {
/*
private WeeklyMenuService weeklyMenuService;
@GetMapping("/{fridgeId}")
......@@ -29,5 +32,19 @@ public class WeeklyMenuController {
return ResponseEntity.ok(weeklyMenu);
}
}
*/
final private RecipeService recipeService;
@GetMapping("/{fridgeId}")
public ResponseEntity<Object> compareWeeklyMenuAndRecipeProducts(@PathVariable("fridgeId") Integer fridgeId) {
List<RecipeWithMatchCount> weeklyMenuDetails = recipeService.getWeeklyMenu(fridgeId);
if (weeklyMenuDetails.isEmpty()) {
return ResponseEntity.notFound().build();
} else {
return ResponseEntity.ok(weeklyMenuDetails);
}
}
}
......@@ -12,15 +12,11 @@ import lombok.NoArgsConstructor;
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RecipeDetails {
public class RecipeFridgeMatch {
private Integer recipeId;
private String recipeName;
private String recipeDescription;
private long ean;
private String productName;
private String productDescription;
private boolean inFridge;
}
private String recipeImage;
}
\ No newline at end of file
package ntnu.idatt2016.v233.SmartMat.dto.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* This class represents a response for a weekly menu.
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RecipeWithMatchCount {
private RecipeDetails recipeDetails;
private int matchCount;
}
\ No newline at end of file
......@@ -23,25 +23,19 @@ public interface RecipeRepository extends JpaRepository<Recipe, Long> {
List<Recipe> findAllByName(String name);
@Query( value = """
SELECT r.recipe_id, r.recipe_name,r.recipe_description,r.image_url, COUNT(fp.ean) as product_count
FROM recipe r
LEFT JOIN recipe_product rp ON r.recipe_id = rp.recipe_id
LEFT JOIN fridge_product fp ON rp.ean = fp.ean AND fp.fridge_id = :fridgeId
GROUP BY r.recipe_id, r.recipe_name
ORDER BY product_count DESC
LIMIT 5;
select p2.item_name, f.fridge_id
from fridge f
inner join fridge_product fp on f.fridge_id = fp.fridge_id and f.fridge_id = :fridgeId
inner join product p2 on p2.ean = fp.ean
""", nativeQuery = true)
List<Object[]> findWeeklyMenu(@Param("fridgeId") long fridgeId);
List<Object[]> findWeeklyMenu(long fridgeId);
@Query( value = """
SELECT r.recipe_id, r.recipe_name, r.recipe_description, p.ean, p.item_name, p.description as product_description,
CASE WHEN fp.fridge_id IS NOT NULL THEN TRUE ELSE FALSE END as in_fridge
FROM recipe AS r
JOIN recipe_product AS rp ON r.recipe_id = rp.recipe_id
JOIN product AS p ON rp.ean = p.ean
LEFT JOIN fridge_product AS fp ON p.ean = fp.ean AND fp.fridge_id = :fridgeId
WHERE r.recipe_id = :recipeId ;
SELECT r.recipe_id, r.recipe_name, r.recipe_description, r.image_url, p.item_name
FROM recipe r
inner JOIN recipe_product rp ON r.recipe_id = rp.recipe_id
inner join product p on rp.ean = p.ean
""" , nativeQuery = true)
List<Object[]> findRecipeWithMatchingProductsInFridge(long fridgeId, long recipeId);
List<Object[]> findRecipeProductsWithName();
}
package ntnu.idatt2016.v233.SmartMat.service;
import ntnu.idatt2016.v233.SmartMat.dto.response.RecipeFridgeMatch;
import ntnu.idatt2016.v233.SmartMat.dto.response.RecipeDetails;
import ntnu.idatt2016.v233.SmartMat.dto.response.RecipeWithMatchCount;
import ntnu.idatt2016.v233.SmartMat.entity.Recipe;
import ntnu.idatt2016.v233.SmartMat.entity.user.User;
import ntnu.idatt2016.v233.SmartMat.repository.RecipeRepository;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
......@@ -110,25 +114,6 @@ public class RecipeService {
recipeRepository.save(recipe);
}
public List<RecipeFridgeMatch> getRecipeWithFridgeProductMatch(long fridgeId, long recipeId) {
List<Object[]> rawData = recipeRepository.findRecipeWithMatchingProductsInFridge(fridgeId, recipeId);
List<RecipeFridgeMatch> result = rawData.stream()
.map(row -> new RecipeFridgeMatch(
(Integer) row[0],
(String) row[1],
(String) row[2],
(Long) row[3],
(String) row[4],
(String) row[5],
(Boolean) row[6]
))
.collect(Collectors.toList());
return result;
}
/**
* Adds a recipe to a users favorites
* @param recipeId id of the recipe
......@@ -180,4 +165,55 @@ public class RecipeService {
return ResponseEntity.ok("Recipe deleted from favorites");
}
}
public List<RecipeWithMatchCount> getWeeklyMenu(Integer fridgeId) {
// Get the results from both repository methods
List<Object[]> weeklyMenu = recipeRepository.findWeeklyMenu(fridgeId);
List<Object[]> recipeProducts = recipeRepository.findRecipeProductsWithName();
// Prepare a map to store RecipeDetails with their match count
Map<RecipeDetails, Integer> recipeMatchCountMap = new HashMap<>();
// Compare the item_name on both lists
for (Object[] menuRow : weeklyMenu) {
String menuRowItemName = (String) menuRow[0];
for (Object[] recipeProductRow : recipeProducts) {
String recipeProductRowItemName = (String) recipeProductRow[4];
List<String> recipeProductWords = Arrays.asList(recipeProductRowItemName.split("\\s+"));
boolean allWordsContained = recipeProductWords.stream()
.allMatch(word -> menuRowItemName.contains(word));
if (allWordsContained) {
Integer recipeId = ((Integer) recipeProductRow[0]).intValue();
String recipeName = (String) recipeProductRow[1];
String recipeDescription = (String) recipeProductRow[2];
String recipeImage = (String) recipeProductRow[3];
RecipeDetails recipeDetails = new RecipeDetails(recipeId, recipeName, recipeDescription, recipeImage);
recipeMatchCountMap.put(recipeDetails, recipeMatchCountMap.getOrDefault(recipeDetails, 0) + 1);
}
}
}
// Get a list of unique RecipeDetails from recipeProducts
List<RecipeDetails> uniqueRecipeDetails = recipeProducts.stream()
.map(row -> new RecipeDetails(((Integer) row[0]).intValue(), (String) row[1], (String) row[2], (String) row[3]))
.distinct()
.collect(Collectors.toList());
// Convert the map to a list of RecipeWithMatchCount
List<RecipeWithMatchCount> commonRecipes = recipeMatchCountMap.entrySet().stream()
.map(entry -> new RecipeWithMatchCount(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
// Add additional recipes from uniqueRecipeDetails with a count of 0 if the list has less than 5 recipes
for (RecipeDetails recipeDetails : uniqueRecipeDetails) {
if (commonRecipes.size() < 5 && !recipeMatchCountMap.containsKey(recipeDetails)) {
commonRecipes.add(new RecipeWithMatchCount(recipeDetails, 0));
}
}
return commonRecipes;
}
}
\ No newline at end of file
package ntnu.idatt2016.v233.SmartMat.controller;
import ntnu.idatt2016.v233.SmartMat.dto.response.RecipeDetails;
import ntnu.idatt2016.v233.SmartMat.dto.response.RecipeWithMatchCount;
import ntnu.idatt2016.v233.SmartMat.dto.response.WeeklyMenuResponse;
import ntnu.idatt2016.v233.SmartMat.service.RecipeService;
import ntnu.idatt2016.v233.SmartMat.service.WeeklyMenuService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
......@@ -23,6 +26,9 @@ public class WeeklyMenuControllerTest {
@InjectMocks
private WeeklyMenuController weeklyMenuController;
@Mock
private RecipeService recipeService;
@Mock
private WeeklyMenuService weeklyMenuService;
......@@ -48,10 +54,15 @@ public class WeeklyMenuControllerTest {
@Test
public void getWeeklyMenu_found() {
long fridgeId = 1L;
when(weeklyMenuService.getWeeklyMenu(fridgeId)).thenReturn(weeklyMenu);
Integer fridgeId = 1;
List<RecipeWithMatchCount> weeklyMenu = List.of(
new RecipeWithMatchCount(new RecipeDetails(1, "Recipe 1", "Description 1", "ImageURL 1"), 3),
new RecipeWithMatchCount(new RecipeDetails(2, "Recipe 2", "Description 2", "ImageURL 2"), 1)
);
when(recipeService.getWeeklyMenu(fridgeId)).thenReturn(weeklyMenu);
ResponseEntity<List<WeeklyMenuResponse>> response = weeklyMenuController.getWeeklyMenu(fridgeId);
ResponseEntity<Object> response = weeklyMenuController.compareWeeklyMenuAndRecipeProducts(fridgeId);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(weeklyMenu, response.getBody());
......@@ -59,10 +70,10 @@ public class WeeklyMenuControllerTest {
@Test
public void getWeeklyMenu_notFound() {
long fridgeId = 1L;
when(weeklyMenuService.getWeeklyMenu(fridgeId)).thenReturn(new ArrayList<>());
Integer fridgeId = 1;
when(recipeService.getWeeklyMenu(fridgeId)).thenReturn(new ArrayList<>());
ResponseEntity<List<WeeklyMenuResponse>> response = weeklyMenuController.getWeeklyMenu(fridgeId);
ResponseEntity<Object> response = weeklyMenuController.compareWeeklyMenuAndRecipeProducts(fridgeId);
assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment