diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..1588f65
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,24 @@
+---
+name: ๐ Bug Report
+about: ๋ฒ๊ทธ๋ฅผ ๋ณด๊ณ ํฉ๋๋ค
+title: "[Bug] "
+labels: bug
+assignees: ''
+---
+
+## ๐ ๋ฒ๊ทธ ์ค๋ช
+- ๋ฒ๊ทธ์ ๋ํด ๊ฐ๋จํ ์ค๋ช
ํด์ฃผ์ธ์.
+
+## โ
์ฌํ ๋ฐฉ๋ฒ
+- ๋ฒ๊ทธ๋ฅผ ์ฌํํ๋ ค๋ฉด ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฅด์ธ์:
+ 1. [์: ํ์ด์ง ์ด๋ ๊ฒฝ๋ก]
+ 2. [์: ํน์ ๋ฒํผ ํด๋ฆญ]
+ 3. [์: ๊ธฐ๋๋๋ ๊ฒฐ๊ณผ]
+
+## ๐ฅ ํ๊ฒฝ ์ ๋ณด
+- OS: [Windows, macOS, Linux ๋ฑ]
+- Browser: [Chrome, Firefox ๋ฑ]
+- Version: [์ฑ/๋ธ๋ผ์ฐ์ ๋ฒ์ ]
+
+## ๐ธ ์คํฌ๋ฆฐ์ท
+- ๋ฒ๊ทธ๋ฅผ ๋ณด์ฌ์ฃผ๋ ์คํฌ๋ฆฐ์ท์ ์ถ๊ฐํด์ฃผ์ธ์ (ํ์ํ ๊ฒฝ์ฐ).
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..9880a67
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,16 @@
+---
+name: โจ Feature Request
+about: ์๋ก์ด ๊ธฐ๋ฅ์ ์์ฒญํฉ๋๋ค
+title: "[Feature] "
+labels: enhancement
+assignees: ''
+---
+
+## ๐ ๊ธฐ๋ฅ ์ค๋ช
+- ์ถ๊ฐํ๊ณ ์ถ์ ๊ธฐ๋ฅ์ด๋ ๋ณ๊ฒฝ ์ฌํญ์ ๊ฐ๋ตํ ์ค๋ช
ํด์ฃผ์ธ์.
+
+## ๐ค ์ด์
+- ์ด ๊ธฐ๋ฅ์ด ์ ํ์ํ์ง, ์ด๋ค ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋์ง ์ค๋ช
ํด์ฃผ์ธ์.
+
+## ๐ ์ถ๊ฐ ์ ๋ณด
+- ๊ธฐ๋ฅ๊ณผ ๊ด๋ จ๋ ์ฐธ๊ณ ์๋ฃ๋ ์ถ๊ฐ ์ ๋ณด๋ฅผ ํฌํจํด์ฃผ์ธ์.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..3d75a26
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,34 @@
+## ๐ ์์ฝ
+- ์ด Pull Request์ ๋ชฉ์ ๊ณผ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ๊ฐ๋ตํ ์ค๋ช
ํด์ฃผ์ธ์.
+
+## ๐ ๋ณ๊ฒฝ ์ฌํญ
+- ์ด๋ฒ Pull Request์์ ์์
ํ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
+ - [x] ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ ๋๋ ๋ฒ๊ทธ ์์
+ - [x] ์ฝ๋ ๋ฆฌํฉํ ๋ง ๋๋ ์ต์ ํ
+ - [x] ๋ฌธ์ ์
๋ฐ์ดํธ
+
+## ๐ ๊ด๋ จ ์ด์
+- ์ด PR๋ก ํด๊ฒฐ๋๋ ์ด์: #[์ด์ ๋ฒํธ]
+- ๊ด๋ จ๋ ์ด์: #[์ด์ ๋ฒํธ]
+
+## ๐ธ ์คํฌ๋ฆฐ์ท ๋๋ GIF (ํด๋น๋๋ ๊ฒฝ์ฐ)
+- UI ๋ณ๊ฒฝ์ด ์๋ ๊ฒฝ์ฐ ๋ณ๊ฒฝ ์ฌํญ์ ๋ณด์ฌ์ฃผ๋ ์คํฌ๋ฆฐ์ท์ด๋ GIF๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์.
+
+## โ
์ฒดํฌ๋ฆฌ์คํธ
+- [ ] ์ฝ๋๊ฐ ์ ์์ ์ผ๋ก ๋์ํ๋์ง ํ
์คํธํ์ต๋๋ค.
+- [ ] ๊ด๋ จ ๋ฌธ์๋ฅผ ์์ฑํ๊ฑฐ๋ ์
๋ฐ์ดํธํ์ต๋๋ค. (ํด๋น๋๋ ๊ฒฝ์ฐ)
+- [ ] ๋ณ๊ฒฝ ์ฌํญ์ ๋ฐ์ํ ํ
์คํธ ์ฝ๋๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
+- [ ] ๋ชจ๋ ํ
์คํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ํต๊ณผํ์ต๋๋ค.
+
+## ๐ก ํ
์คํธ ๋ฐฉ๋ฒ
+- ๋ณ๊ฒฝ ์ฌํญ์ ํ์ธํ๊ธฐ ์ํ ํ
์คํธ ๋ฐฉ๋ฒ์ ๋จ๊ณ๋ณ๋ก ์์ฑํด์ฃผ์ธ์:
+ 1. ๋ธ๋์น๋ฅผ ๋ก์ปฌ๋ก ๊ฐ์ ธ์ต๋๋ค.
+ 2. ์๋ ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํด ์ ํ๋ฆฌ์ผ์ด์
๋๋ ํ
์คํธ๋ฅผ ์คํํฉ๋๋ค:
+ ```
+ # ์์ ๋ช
๋ น์ด
+ ./run_tests.sh
+ ```
+ 3. ์์ ๋์์ด๋ ์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํฉ๋๋ค.
+
+## ๐ ์ถ๊ฐ ์ฐธ๊ณ ์ฌํญ
+- ์ด PR๊ณผ ๊ด๋ จํด ๋ฆฌ๋ทฐ์ด๊ฐ ์์์ผ ํ ์ถ๊ฐ ๋ด์ฉ์ด ์๋ค๋ฉด ์์ฑํด์ฃผ์ธ์.
diff --git a/refrigerator/.idea/modules/refrigerator.main.iml b/refrigerator/.idea/modules/refrigerator.main.iml
index afc1871..ac8e328 100644
--- a/refrigerator/.idea/modules/refrigerator.main.iml
+++ b/refrigerator/.idea/modules/refrigerator.main.iml
@@ -1,8 +1,21 @@
-
-
+
+
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java
index e530f63..7790098 100644
--- a/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java
+++ b/refrigerator/src/main/java/moja/refrigerator/aggregate/recipe/RecipeIngredient.java
@@ -3,6 +3,7 @@
import jakarta.persistence.*;
import lombok.Data;
import moja.refrigerator.aggregate.ingredient.IngredientManagement;
+import moja.refrigerator.aggregate.ingredient.IngredientMyRefrigerator;
@Data
@Entity
@@ -19,6 +20,7 @@ public class RecipeIngredient {
@JoinColumn(name = "ingredient_management")
@ManyToOne
private IngredientManagement ingredientManagement;
+// private IngredientMyRefrigerator ingredientMyRefrigerator ;
@JoinColumn(name = "recipe")
@ManyToOne
diff --git a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java
index 58807d0..bd4533b 100644
--- a/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java
+++ b/refrigerator/src/main/java/moja/refrigerator/controller/recipe/RecipeController.java
@@ -4,6 +4,7 @@
import moja.refrigerator.dto.recipe.request.RecipeCreateRequest;
import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest;
import moja.refrigerator.dto.recipe.response.RecipeDetailResponse;
+import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse;
import moja.refrigerator.dto.recipe.response.RecipeResponse;
import moja.refrigerator.service.recipe.RecipeService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -52,4 +53,9 @@ public void updateRecipe(
){
recipeService.updateRecipe(request,files);
}
+
+ @GetMapping("/recommend")
+ public List getRecommendedRecipes(@RequestParam Long userPk) {
+ return recipeService.getRecommendedRecipes(userPk);
+ }
}
diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java
new file mode 100644
index 0000000..210e602
--- /dev/null
+++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/RecipeMatchResult.java
@@ -0,0 +1,15 @@
+package moja.refrigerator.dto.recipe;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import moja.refrigerator.aggregate.recipe.Recipe;
+
+@Data
+@AllArgsConstructor
+public class RecipeMatchResult {
+ private Recipe recipe;
+ private boolean matched;
+ private double matchRate;
+ private long remainExpirationDays;
+ private String urgentIngredientName;
+}
\ No newline at end of file
diff --git a/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java
new file mode 100644
index 0000000..dbb6019
--- /dev/null
+++ b/refrigerator/src/main/java/moja/refrigerator/dto/recipe/response/RecipeRecommendResponse.java
@@ -0,0 +1,14 @@
+package moja.refrigerator.dto.recipe.response;
+
+import lombok.Data;
+
+@Data
+public class RecipeRecommendResponse {
+ private long recipePk;
+ private String recipeName;
+ private String recipeContent;
+ private int recipeCookingTime;
+ private double matchRate;
+ private long remainExpirationDays;
+ private String urgentIngredientName;
+}
\ No newline at end of file
diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeIngredientRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeIngredientRepository.java
new file mode 100644
index 0000000..e717f33
--- /dev/null
+++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/RecipeIngredientRepository.java
@@ -0,0 +1,13 @@
+package moja.refrigerator.repository.recipe;
+
+import moja.refrigerator.aggregate.recipe.Recipe;
+import moja.refrigerator.aggregate.recipe.RecipeIngredient;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface RecipeIngredientRepository extends JpaRepository {
+ List findByRecipe(Recipe recipe);
+}
\ No newline at end of file
diff --git a/refrigerator/src/main/java/moja/refrigerator/repository/recipe/ReplacableIngredientRepository.java b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/ReplacableIngredientRepository.java
new file mode 100644
index 0000000..50a497b
--- /dev/null
+++ b/refrigerator/src/main/java/moja/refrigerator/repository/recipe/ReplacableIngredientRepository.java
@@ -0,0 +1,13 @@
+package moja.refrigerator.repository.recipe;
+
+import moja.refrigerator.aggregate.recipe.RecipeIngredient;
+import moja.refrigerator.aggregate.recipe.ReplacableIngredient;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface ReplacableIngredientRepository extends JpaRepository {
+ List findByRecipeIngredient(RecipeIngredient recipeIngredient);
+}
\ No newline at end of file
diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java
index d94057b..7c89c15 100644
--- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java
+++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeService.java
@@ -4,6 +4,7 @@
import moja.refrigerator.dto.recipe.request.RecipeCreateRequest;
import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest;
import moja.refrigerator.dto.recipe.response.RecipeDetailResponse;
+import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse;
import moja.refrigerator.dto.recipe.response.RecipeResponse;
import moja.refrigerator.repository.recipe.RecipeRepository;
import org.springframework.stereotype.Service;
@@ -22,4 +23,5 @@ void updateRecipe(
RecipeUpdateRequest request
,List files
);
+ List getRecommendedRecipes(Long userPk);
}
diff --git a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java
index 3dddc12..9f53d69 100644
--- a/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java
+++ b/refrigerator/src/main/java/moja/refrigerator/service/recipe/RecipeServiceImpl.java
@@ -1,24 +1,19 @@
package moja.refrigerator.service.recipe;
-
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
-import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
-import moja.refrigerator.aggregate.recipe.Recipe;
-import moja.refrigerator.aggregate.recipe.RecipeCategory;
-import moja.refrigerator.aggregate.recipe.RecipeSource;
-import moja.refrigerator.aggregate.recipe.RecipeSourceType;
+import moja.refrigerator.aggregate.ingredient.IngredientMyRefrigerator;
+import moja.refrigerator.aggregate.recipe.*;
import moja.refrigerator.aggregate.user.User;
-import moja.refrigerator.dto.ingredient.response.IngredientResponse;
+import moja.refrigerator.dto.recipe.RecipeMatchResult;
import moja.refrigerator.dto.recipe.request.RecipeCreateRequest;
import moja.refrigerator.dto.recipe.request.RecipeUpdateRequest;
import moja.refrigerator.dto.recipe.response.RecipeDetailResponse;
+import moja.refrigerator.dto.recipe.response.RecipeRecommendResponse;
import moja.refrigerator.dto.recipe.response.RecipeResponse;
-import moja.refrigerator.repository.recipe.RecipeCategoryRepository;
-import moja.refrigerator.repository.recipe.RecipeRepository;
-import moja.refrigerator.repository.recipe.RecipeSourceRepository;
-import moja.refrigerator.repository.recipe.RecipeSourceTypeRepository;
+import moja.refrigerator.repository.ingredient.IngredientMyRefrigeratorRepository;
+import moja.refrigerator.repository.recipe.*;
import moja.refrigerator.repository.user.UserRepository;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
@@ -28,125 +23,117 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
-import java.awt.*;
import java.io.IOException;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
import java.util.stream.Collectors;
@Service
public class RecipeServiceImpl implements RecipeService {
- private RecipeRepository recipeRepository;
- private UserRepository userRepository;
- private RecipeSourceRepository recipeSourceRepository;
- private RecipeCategoryRepository recipeCategoryRepository;
- private ModelMapper mapper;
- private RecipeSourceTypeRepository recipeSourceTypeRepository;
+ private final RecipeRepository recipeRepository;
+ private final UserRepository userRepository;
+ private final RecipeSourceRepository recipeSourceRepository;
+ private final RecipeCategoryRepository recipeCategoryRepository;
+ private final ModelMapper mapper;
+ private final RecipeSourceTypeRepository recipeSourceTypeRepository;
private final AmazonS3Client amazonS3Client;
+ private final IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository;
+ private final RecipeIngredientRepository recipeIngredientRepository;
+ private final ReplacableIngredientRepository replacableIngredientRepository;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
- // ์ด๋ฏธ์ง์ ํ์ฅ์๋ฅผ ํ์ธ, ์ด๋ฅผ ์ด์ฉํด ํ์
์ ๋ถ๋ฅํ๋ค.
- private boolean isImageFile(String fileName) {
- String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
- return List.of("jpg", "jpeg", "png", "gif").contains(extension);
- }
- // ๋์์์ ํ์ฅ์๋ฅผ ํ์ธ, ์ด๋ฅผ ์ด์ฉํด ํ์
์ ๋ถ๋ฅํ๋ค.
- private boolean isVideoFile(String fileName) {
- String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
- return List.of("mp4", "avi", "mov", "wmv").contains(extension);
- }
- // 2๊ฐ์ง ๋์์ ๋ค ์ฐ๋ ์ด์ ๋, ๋๋ค ์๋ ๊ฒฝ์ฐ(ex] exe, java ๋ฑ ์๋ชป๋ ํ์ฅ์๋ฅผ ์ฌ๋ฆด ์ ๋ฉ์์ง๋ฅผ ์ฃผ๊ธฐ ์ํด)
-
@Autowired
public RecipeServiceImpl(
RecipeRepository recipeRepository,
- ModelMapper mapper,
- RecipeSourceRepository recipeSourceRepository,
UserRepository userRepository,
+ RecipeSourceRepository recipeSourceRepository,
RecipeCategoryRepository recipeCategoryRepository,
+ ModelMapper mapper,
RecipeSourceTypeRepository recipeSourceTypeRepository,
- AmazonS3Client amazonS3Client
+ AmazonS3Client amazonS3Client,
+ IngredientMyRefrigeratorRepository ingredientMyRefrigeratorRepository,
+ RecipeIngredientRepository recipeIngredientRepository,
+ ReplacableIngredientRepository replacableIngredientRepository
) {
this.recipeRepository = recipeRepository;
- this.mapper = mapper;
- this.recipeSourceRepository = recipeSourceRepository;
this.userRepository = userRepository;
+ this.recipeSourceRepository = recipeSourceRepository;
this.recipeCategoryRepository = recipeCategoryRepository;
- this.recipeSourceTypeRepository=recipeSourceTypeRepository;
+ this.mapper = mapper;
+ this.recipeSourceTypeRepository = recipeSourceTypeRepository;
this.amazonS3Client = amazonS3Client;
+ this.ingredientMyRefrigeratorRepository = ingredientMyRefrigeratorRepository;
+ this.recipeIngredientRepository = recipeIngredientRepository;
+ this.replacableIngredientRepository = replacableIngredientRepository;
+ }
+
+ private boolean isImageFile(String fileName) {
+ String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
+ return List.of("jpg", "jpeg", "png", "gif").contains(extension);
+ }
+
+ private boolean isVideoFile(String fileName) {
+ String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
+ return List.of("mp4", "avi", "mov", "wmv").contains(extension);
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
- public void createRecipe(RecipeCreateRequest request
- ,List files
- ) {
- Recipe recipe = new Recipe(); // mapper๋ฅผ ํตํ์ธ์์ด ์ ์๋จ. -> ๊ทธ๋ฅ ์ผ์ผ์ด ์ถ๊ฐ.
+ public void createRecipe(RecipeCreateRequest request, List files) {
+ Recipe recipe = new Recipe();
recipe.setRecipeName(request.getRecipeName());
recipe.setRecipeContent(request.getRecipeContent());
recipe.setRecipeDifficulty(request.getRecipeDifficulty());
recipe.setRecipeCookingTime(request.getRecipeCookingTime());
-
-// User ์กฐํ
User user = userRepository.findById(request.getUserPk())
- .orElseThrow(IllegalArgumentException::new);
+ .orElseThrow(IllegalArgumentException::new);
recipe.setUser(user);
-// RecipeCategory
RecipeCategory recipeCategory = recipeCategoryRepository.findById(request.getRecipeCategoryPk())
.orElseThrow(IllegalArgumentException::new);
recipe.setRecipeCategory(recipeCategory);
- //RecipeSource ์ถ๊ฐ๋ถ๋ถ
+
if(files != null && !files.isEmpty()) {
- for(MultipartFile file : files){
- try{// 1. ์์ฑํ ๋ด์ฉ ์ ๋ฆฌ
+ for(MultipartFile file : files) {
+ try {
String recipeSourceFileName = file.getOriginalFilename();
UUID uuid = UUID.randomUUID();
- String recipeSourceServername = uuid+recipeSourceFileName;
+ String recipeSourceServername = uuid + recipeSourceFileName;
+ String recipeSourceSave = "https://" + bucket + "/recipe/" + recipeSourceServername;
- String recipeSourceSave = "https://"+bucket+"/recipe/"+recipeSourceServername;
-
-
- // 2. ์์ฑํ ๋ด์ฉ ์ ์ฅ
RecipeSource recipeSource = new RecipeSource();
recipeSource.setRecipeSourceServername(recipeSourceServername);
recipeSource.setRecipeSourceSave(recipeSourceSave);
recipeSource.setRecipeSourceFileName(recipeSourceFileName);
-
- // 3. ์๋ฃ ํ์
๊ฐ์ ธ์ค๊ธฐ.
-
RecipeSourceType recipeSourceType;
- if(isImageFile(recipeSourceFileName)){
+ if(isImageFile(recipeSourceFileName)) {
recipeSourceType = recipeSourceTypeRepository.findById(1)
.orElseThrow(IllegalArgumentException::new);
- }else if (isVideoFile(recipeSourceFileName)){
+ } else if (isVideoFile(recipeSourceFileName)) {
recipeSourceType = recipeSourceTypeRepository.findById(2)
.orElseThrow(IllegalArgumentException::new);
- }else{
+ } else {
throw new IllegalArgumentException("Unsupported file type");
}
- // ์๋ง์กด ์๋ฒ ์ฌ๋ฆฌ๊ธฐ
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType(file.getContentType());
objectMetadata.setContentLength(file.getSize());
- amazonS3Client.putObject(bucket,recipeSourceServername,file.getInputStream(),objectMetadata);
+ amazonS3Client.putObject(bucket, recipeSourceServername, file.getInputStream(), objectMetadata);
- // ๋ ์ํผ db์ ์ ์ฅ.
recipeSource.setRecipeSourceType(recipeSourceType);
recipeSource.setRecipe(recipe);
recipeSourceRepository.save(recipeSource);
break;
- }catch (IOException e){
+ } catch (IOException e) {
System.out.println(e.getMessage());
}
-
}
}
@@ -154,30 +141,30 @@ public void createRecipe(RecipeCreateRequest request
}
@Override
- public List getAllRecipes(){
+ public List getAllRecipes() {
return recipeRepository.findAll().stream()
.map(recipe -> mapper.map(recipe, RecipeResponse.class))
.collect(Collectors.toList());
}
- public RecipeDetailResponse getRecipe(long id){
- Recipe recipe = recipeRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("recipe not found"));
- RecipeDetailResponse response = mapper.map(recipe,RecipeDetailResponse.class);
- return response;
+ @Override
+ public RecipeDetailResponse getRecipe(long id) {
+ Recipe recipe = recipeRepository.findById(id)
+ .orElseThrow(() -> new IllegalArgumentException("recipe not found"));
+ return mapper.map(recipe, RecipeDetailResponse.class);
}
- @Override
+ @Override
public void deleteRecipe(long recipePk) {
Recipe recipe = recipeRepository.findByRecipePk(recipePk)
.orElseThrow(IllegalArgumentException::new);
List sources = recipe.getRecipeSource();
- if(sources!=null && !sources.isEmpty()){
+ if(sources != null && !sources.isEmpty()) {
for (RecipeSource recipeSource : sources) {
- amazonS3Client.deleteObject( new DeleteObjectRequest(bucket,recipeSource.getRecipeSourceServername()));
+ amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, recipeSource.getRecipeSourceServername()));
}
}
recipeRepository.delete(recipe);
-
}
@Override
@@ -186,7 +173,6 @@ public void updateRecipe(RecipeUpdateRequest request, List files)
Recipe recipe = recipeRepository.findByRecipePk(request.getRecipePk())
.orElseThrow(() -> new IllegalArgumentException("Recipe not found"));
- // ๊ธฐ๋ณธ ํ๋ ์
๋ฐ์ดํธ
if (request.getRecipeName() != null) recipe.setRecipeName(request.getRecipeName());
if (request.getRecipeCookingTime() != 0) recipe.setRecipeCookingTime(request.getRecipeCookingTime());
if (request.getRecipeDifficulty() != 0) recipe.setRecipeDifficulty(request.getRecipeDifficulty());
@@ -195,23 +181,21 @@ public void updateRecipe(RecipeUpdateRequest request, List files)
.orElseThrow(() -> new IllegalArgumentException("Category not found")));
}
- // ๊ธฐ์กด RecipeSource์ ์
๋ก๋๋ ํ์ผ ๋น๊ต
List sources = recipe.getRecipeSource();
List uploadedFileNames = files.stream()
.map(MultipartFile::getOriginalFilename)
.toList();
- // ์ญ์ ํ RecipeSource
List recipeSourcesToDelete = sources.stream()
.filter(source -> !uploadedFileNames.contains(source.getRecipeSourceFileName()))
.toList();
- for (RecipeSource recipeSource : recipeSourcesToDelete) {
+
+ for (RecipeSource recipeSource : recipeSourcesToDelete) {
amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, recipeSource.getRecipeSourceServername()));
- recipe.getRecipeSource().remove(recipeSource); // ๋ถ๋ชจ ์ํฐํฐ์์ ์ฐธ์กฐ ์ ๊ฑฐ
- recipeSourceRepository.delete(recipeSource );
+ recipe.getRecipeSource().remove(recipeSource);
+ recipeSourceRepository.delete(recipeSource);
}
- // ์ถ๊ฐํ ์ ํ์ผ
List existingFileNames = sources.stream()
.map(RecipeSource::getRecipeSourceFileName)
.toList();
@@ -222,7 +206,6 @@ public void updateRecipe(RecipeUpdateRequest request, List files)
for (MultipartFile file : filesToAdd) {
try {
- // ์ RecipeSource ์์ฑ
String recipeSourceFileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
String recipeSourceServername = recipeSourceFileName;
String recipeSourceSave = "https://" + bucket + "/recipe/" + recipeSourceServername;
@@ -256,8 +239,81 @@ public void updateRecipe(RecipeUpdateRequest request, List files)
}
}
- // ์ต์ข
์ ์ฅ
recipeRepository.save(recipe);
}
+
+ @Override
+ public List getRecommendedRecipes(Long userPk) {
+ List userIngredients =
+ ingredientMyRefrigeratorRepository.findByUserUserPk(userPk);
+ List allRecipes = recipeRepository.findAll();
+
+ return allRecipes.stream()
+ .map(recipe -> checkRecipeMatch(recipe, userIngredients))
+ .filter(RecipeMatchResult::isMatched)
+ .map(result -> {
+ RecipeRecommendResponse response = mapper.map(result.getRecipe(), RecipeRecommendResponse.class);
+ response.setMatchRate(result.getMatchRate());
+ response.setRemainExpirationDays(result.getRemainExpirationDays());
+ response.setUrgentIngredientName(result.getUrgentIngredientName());
+ return response;
+ })
+ .sorted(Comparator.comparingLong(RecipeRecommendResponse::getRemainExpirationDays))
+ .collect(Collectors.toList());
+ }
+
+ private RecipeMatchResult checkRecipeMatch(Recipe recipe, List userIngredients) {
+ List recipeIngredients = recipeIngredientRepository.findByRecipe(recipe);
+ LocalDate currentDate = LocalDate.now();
+
+ if (recipeIngredients.isEmpty()) {
+ return new RecipeMatchResult(recipe, false, 0, 0, null);
+ }
+
+ boolean hasAllNecessaryIngredients = true;
+ int matchedCount = 0;
+ long shortestRemainDays = Long.MAX_VALUE;
+ String urgentIngredientName = null;
+
+ for (RecipeIngredient recipeIngredient : recipeIngredients) {
+ boolean hasIngredient = false;
+
+ for (IngredientMyRefrigerator userIngredient : userIngredients) {
+ if (userIngredient.getIngredientManagement().getIngredientManagementPk() ==
+ recipeIngredient.getIngredientManagement().getIngredientManagementPk()) {
+
+ hasIngredient = true;
+ matchedCount++;
+
+ // ๋จ์ ์ผ์ ๊ณ์ฐ
+ LocalDate expirationDate = LocalDate.parse(userIngredient.getExpirationDate());
+ long remainDays = ChronoUnit.DAYS.between(currentDate, expirationDate);
+
+ // ๋ ์งง์ ์ ํต๊ธฐํ ๋ฐ๊ฒฌ์ ์ ๋ณด ์
๋ฐ์ดํธ
+ if (remainDays < shortestRemainDays) {
+ shortestRemainDays = remainDays;
+ urgentIngredientName = userIngredient.getIngredientManagement().getIngredientName();
+ }
+ break;
+ }
+ }
+
+ if (recipeIngredient.isIngredientIsNecessary() && !hasIngredient) {
+ hasAllNecessaryIngredients = false;
+ break;
+ }
+ }
+
+ double matchRate = ((double) matchedCount / recipeIngredients.size()) * 100;
+ boolean isMatched = hasAllNecessaryIngredients && matchRate >= 66;
+
+ return new RecipeMatchResult(
+ recipe,
+ isMatched,
+ matchRate,
+ isMatched ? shortestRemainDays : 0,
+ isMatched ? urgentIngredientName : null
+ );
+ }
}
\ No newline at end of file