diff --git a/src/main/java/flab/nutridiary/commom/generic/Nutrition.java b/src/main/java/flab/nutridiary/commom/generic/Nutrition.java index aa3e1be..a706d81 100644 --- a/src/main/java/flab/nutridiary/commom/generic/Nutrition.java +++ b/src/main/java/flab/nutridiary/commom/generic/Nutrition.java @@ -72,6 +72,15 @@ private BigDecimal stripIfNecessary(BigDecimal value) { return strippedValue.scale() <= 0 ? strippedValue.setScale(0) : strippedValue; } + public static Nutrition empty() { + return Nutrition.builder() + .calories(BigDecimal.ZERO) + .carbohydrate(BigDecimal.ZERO) + .protein(BigDecimal.ZERO) + .fat(BigDecimal.ZERO) + .build(); + } + public static Nutrition of(BigDecimal calories, BigDecimal carbohydrate, BigDecimal protein, BigDecimal fat) { return Nutrition.builder(). calories(calories). diff --git a/src/main/java/flab/nutridiary/diary/controller/DiaryController.java b/src/main/java/flab/nutridiary/diary/controller/DiaryController.java index 6a70c55..4f79176 100644 --- a/src/main/java/flab/nutridiary/diary/controller/DiaryController.java +++ b/src/main/java/flab/nutridiary/diary/controller/DiaryController.java @@ -1,23 +1,26 @@ package flab.nutridiary.diary.controller; import flab.nutridiary.commom.dto.ApiResponse; -import flab.nutridiary.diary.dto.AddDiaryRecordRequest; -import flab.nutridiary.diary.dto.DiaryRegisterRequest; -import flab.nutridiary.diary.dto.DiarySavedResponse; +import flab.nutridiary.diary.dto.request.AddDiaryRecordRequest; +import flab.nutridiary.diary.dto.request.DiaryRegisterRequest; +import flab.nutridiary.diary.dto.response.DiarySavedResponse; +import flab.nutridiary.diary.dto.response.query.DiaryRecordWithProduct; import flab.nutridiary.diary.service.AddDiaryRecordService; import flab.nutridiary.diary.service.DiaryRegisterService; +import flab.nutridiary.diary.service.DiarySearchService; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.util.List; @RequiredArgsConstructor @RestController public class DiaryController { private final DiaryRegisterService diaryRegisterService; private final AddDiaryRecordService addDiaryRecordService; + private final DiarySearchService diarySearchService; @PostMapping("/diary/new") public ApiResponse createDiary(@Valid @RequestBody DiaryRegisterRequest diaryRegisterRequest) { @@ -29,4 +32,10 @@ public ApiResponse addDiaryRecord(@Valid @RequestBody AddDia @PathVariable Long diaryId) { return ApiResponse.success(addDiaryRecordService.addDiaryRecord(addDiaryRecordRequest, diaryId)); } + + @GetMapping("/diary") + public ApiResponse> getDiary(@RequestParam(name = "diaryDate") LocalDate diaryDate) { + Long memberId = 1L; + return ApiResponse.success(diarySearchService.getDiary(memberId, diaryDate)); + } } diff --git a/src/main/java/flab/nutridiary/diary/dto/AddDiaryRecordRequest.java b/src/main/java/flab/nutridiary/diary/dto/request/AddDiaryRecordRequest.java similarity index 97% rename from src/main/java/flab/nutridiary/diary/dto/AddDiaryRecordRequest.java rename to src/main/java/flab/nutridiary/diary/dto/request/AddDiaryRecordRequest.java index 857acaf..d442200 100644 --- a/src/main/java/flab/nutridiary/diary/dto/AddDiaryRecordRequest.java +++ b/src/main/java/flab/nutridiary/diary/dto/request/AddDiaryRecordRequest.java @@ -1,4 +1,4 @@ -package flab.nutridiary.diary.dto; +package flab.nutridiary.diary.dto.request; import flab.nutridiary.commom.validation.EnumValidator; import flab.nutridiary.diary.domain.MealType; diff --git a/src/main/java/flab/nutridiary/diary/dto/DiaryRegisterRequest.java b/src/main/java/flab/nutridiary/diary/dto/request/DiaryRegisterRequest.java similarity index 96% rename from src/main/java/flab/nutridiary/diary/dto/DiaryRegisterRequest.java rename to src/main/java/flab/nutridiary/diary/dto/request/DiaryRegisterRequest.java index eba5f7e..200a9c1 100644 --- a/src/main/java/flab/nutridiary/diary/dto/DiaryRegisterRequest.java +++ b/src/main/java/flab/nutridiary/diary/dto/request/DiaryRegisterRequest.java @@ -1,4 +1,4 @@ -package flab.nutridiary.diary.dto; +package flab.nutridiary.diary.dto.request; import flab.nutridiary.commom.validation.EnumValidator; import flab.nutridiary.diary.domain.MealType; diff --git a/src/main/java/flab/nutridiary/diary/dto/DiarySavedResponse.java b/src/main/java/flab/nutridiary/diary/dto/response/DiarySavedResponse.java similarity index 87% rename from src/main/java/flab/nutridiary/diary/dto/DiarySavedResponse.java rename to src/main/java/flab/nutridiary/diary/dto/response/DiarySavedResponse.java index f39db04..7d42e2f 100644 --- a/src/main/java/flab/nutridiary/diary/dto/DiarySavedResponse.java +++ b/src/main/java/flab/nutridiary/diary/dto/response/DiarySavedResponse.java @@ -1,4 +1,4 @@ -package flab.nutridiary.diary.dto; +package flab.nutridiary.diary.dto.response; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/flab/nutridiary/diary/dto/response/query/DiaryRecordWithProduct.java b/src/main/java/flab/nutridiary/diary/dto/response/query/DiaryRecordWithProduct.java new file mode 100644 index 0000000..6a7f6aa --- /dev/null +++ b/src/main/java/flab/nutridiary/diary/dto/response/query/DiaryRecordWithProduct.java @@ -0,0 +1,26 @@ +package flab.nutridiary.diary.dto.response.query; + +import flab.nutridiary.commom.generic.Nutrition; +import flab.nutridiary.diary.domain.MealType; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@EqualsAndHashCode(exclude = {"diaryId", "diaryRecordId"}) +@Builder +@RequiredArgsConstructor +@ToString +@Getter +public class DiaryRecordWithProduct { + private final Long diaryId; + private final Long memberId; + private final LocalDate diaryDate; + private final Long diaryRecordId; + private final MealType mealType; + private final String productName; + private final String productCorp; + private final BigDecimal quantity; + private final String clientChoiceServingUnitDescription; + private final Nutrition calculatedNutrition; +} diff --git a/src/main/java/flab/nutridiary/diary/repository/DiaryRepositoryImpl.java b/src/main/java/flab/nutridiary/diary/repository/DiaryRepositoryImpl.java index c49bfe8..52ffb30 100644 --- a/src/main/java/flab/nutridiary/diary/repository/DiaryRepositoryImpl.java +++ b/src/main/java/flab/nutridiary/diary/repository/DiaryRepositoryImpl.java @@ -10,7 +10,6 @@ @Repository @RequiredArgsConstructor public class DiaryRepositoryImpl implements DiaryRepository{ - private final DiaryCrudRepository diaryCrudRepository; @Override diff --git a/src/main/java/flab/nutridiary/diary/repository/DiarySearchRepository.java b/src/main/java/flab/nutridiary/diary/repository/DiarySearchRepository.java new file mode 100644 index 0000000..0e22cbc --- /dev/null +++ b/src/main/java/flab/nutridiary/diary/repository/DiarySearchRepository.java @@ -0,0 +1,10 @@ +package flab.nutridiary.diary.repository; + +import flab.nutridiary.diary.dto.response.query.DiaryRecordWithProduct; + +import java.time.LocalDate; +import java.util.List; + +public interface DiarySearchRepository { + List findDiaryWithProductAllByMemberIdAndDiaryDate(Long memberId, LocalDate diaryDate); +} diff --git a/src/main/java/flab/nutridiary/diary/repository/query/DiaryRecordWithProductRowMapper.java b/src/main/java/flab/nutridiary/diary/repository/query/DiaryRecordWithProductRowMapper.java new file mode 100644 index 0000000..35118b9 --- /dev/null +++ b/src/main/java/flab/nutridiary/diary/repository/query/DiaryRecordWithProductRowMapper.java @@ -0,0 +1,44 @@ +package flab.nutridiary.diary.repository.query; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import flab.nutridiary.commom.exception.SystemException; +import flab.nutridiary.commom.generic.Nutrition; +import flab.nutridiary.diary.domain.MealType; +import flab.nutridiary.diary.dto.response.query.DiaryRecordWithProduct; +import lombok.RequiredArgsConstructor; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@RequiredArgsConstructor +@Component +public class DiaryRecordWithProductRowMapper implements RowMapper { + private final ObjectMapper objectMapper; + + @Override + public DiaryRecordWithProduct mapRow(ResultSet rs, int rowNum) throws SQLException { + return DiaryRecordWithProduct.builder() + .diaryId(rs.getLong("diary_id")) + .memberId(rs.getLong("member_id")) + .diaryDate(rs.getDate("diary_date").toLocalDate()) + .diaryRecordId(rs.getLong("diary_record_id")) + .mealType(MealType.valueOf(rs.getString("meal_type"))) + .productName(rs.getString("product_name")) + .productCorp(rs.getString("product_corp")) + .quantity(rs.getBigDecimal("quantity")) + .clientChoiceServingUnitDescription(rs.getString("client_choice_serving_unit_description")) + .calculatedNutrition(getNutritionFromJsonString(rs.getString("calculated_nutrition"))) + .build(); + } + + private Nutrition getNutritionFromJsonString(String jsonString) { + try { + return objectMapper.readValue(jsonString, Nutrition.class); + } catch (JsonProcessingException e) { + throw new SystemException("Nutrition 객체 매핑 중 오류가 발생했습니다."); + } + } +} diff --git a/src/main/java/flab/nutridiary/diary/repository/query/JdbcTemplateDiarySearchRepository.java b/src/main/java/flab/nutridiary/diary/repository/query/JdbcTemplateDiarySearchRepository.java new file mode 100644 index 0000000..0c6c668 --- /dev/null +++ b/src/main/java/flab/nutridiary/diary/repository/query/JdbcTemplateDiarySearchRepository.java @@ -0,0 +1,36 @@ +package flab.nutridiary.diary.repository.query; + +import flab.nutridiary.diary.dto.response.query.DiaryRecordWithProduct; +import flab.nutridiary.diary.repository.DiarySearchRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class JdbcTemplateDiarySearchRepository implements DiarySearchRepository { + private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; + private final DiaryRecordWithProductRowMapper diaryRecordWithProductRowMapper; + + @Override + public List findDiaryWithProductAllByMemberIdAndDiaryDate(Long memberId, LocalDate diaryDate) { + String sql = "SELECT " + + "d.diary_id, d.member_id, d.diary_date, " + + "dr.diary_record_id, dr.meal_type, dr.quantity, dr.client_choice_serving_unit_description, dr.calculated_nutrition, " + + "p.product_id, p.product_name, p.product_corp " + + "FROM diary d " + + "JOIN diary_record dr ON d.diary_id = dr.diary_id " + + "JOIN product p ON dr.product_id = p.product_id " + + "WHERE d.member_id = :memberId AND d.diary_date = :diaryDate"; + + MapSqlParameterSource parameters = new MapSqlParameterSource() + .addValue("memberId", memberId) + .addValue("diaryDate", diaryDate); + + return namedParameterJdbcTemplate.query(sql, parameters, diaryRecordWithProductRowMapper); + } +} diff --git a/src/main/java/flab/nutridiary/diary/service/AddDiaryRecordService.java b/src/main/java/flab/nutridiary/diary/service/AddDiaryRecordService.java index 51c52d1..330a9d2 100644 --- a/src/main/java/flab/nutridiary/diary/service/AddDiaryRecordService.java +++ b/src/main/java/flab/nutridiary/diary/service/AddDiaryRecordService.java @@ -5,8 +5,8 @@ import flab.nutridiary.diary.domain.DiaryRecord; import flab.nutridiary.diary.domain.NutritionCalculator; import flab.nutridiary.diary.domain.ProductIntakeInfo; -import flab.nutridiary.diary.dto.AddDiaryRecordRequest; -import flab.nutridiary.diary.dto.DiarySavedResponse; +import flab.nutridiary.diary.dto.request.AddDiaryRecordRequest; +import flab.nutridiary.diary.dto.response.DiarySavedResponse; import flab.nutridiary.diary.repository.DiaryRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/flab/nutridiary/diary/service/DiaryRegisterService.java b/src/main/java/flab/nutridiary/diary/service/DiaryRegisterService.java index 8327c80..550f2f3 100644 --- a/src/main/java/flab/nutridiary/diary/service/DiaryRegisterService.java +++ b/src/main/java/flab/nutridiary/diary/service/DiaryRegisterService.java @@ -1,8 +1,8 @@ package flab.nutridiary.diary.service; import flab.nutridiary.diary.domain.*; -import flab.nutridiary.diary.dto.DiaryRegisterRequest; -import flab.nutridiary.diary.dto.DiarySavedResponse; +import flab.nutridiary.diary.dto.request.DiaryRegisterRequest; +import flab.nutridiary.diary.dto.response.DiarySavedResponse; import flab.nutridiary.diary.repository.DiaryRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/flab/nutridiary/diary/service/DiarySearchService.java b/src/main/java/flab/nutridiary/diary/service/DiarySearchService.java new file mode 100644 index 0000000..06633f9 --- /dev/null +++ b/src/main/java/flab/nutridiary/diary/service/DiarySearchService.java @@ -0,0 +1,22 @@ +package flab.nutridiary.diary.service; + +import flab.nutridiary.diary.dto.response.query.DiaryRecordWithProduct; +import flab.nutridiary.diary.repository.DiarySearchRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.util.List; + +@Transactional +@Service +@RequiredArgsConstructor +public class DiarySearchService { + private final DiarySearchRepository diarySearchRepository; + + @Transactional(readOnly = true) + public List getDiary(Long memberId, LocalDate diaryDate) { + return diarySearchRepository.findDiaryWithProductAllByMemberIdAndDiaryDate(memberId, diaryDate); + } +} diff --git a/src/main/java/flab/nutridiary/diary/service/ProductIntakeInfoMapper.java b/src/main/java/flab/nutridiary/diary/service/ProductIntakeInfoMapper.java index a87784f..7d3d52b 100644 --- a/src/main/java/flab/nutridiary/diary/service/ProductIntakeInfoMapper.java +++ b/src/main/java/flab/nutridiary/diary/service/ProductIntakeInfoMapper.java @@ -1,7 +1,7 @@ package flab.nutridiary.diary.service; import flab.nutridiary.diary.domain.ProductIntakeInfo; -import flab.nutridiary.diary.dto.DiaryRegisterRequest; +import flab.nutridiary.diary.dto.request.DiaryRegisterRequest; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/flab/nutridiary/product/repository/ProductCrudRepository.java b/src/main/java/flab/nutridiary/product/repository/ProductCrudRepository.java index 6c22016..8d4547a 100644 --- a/src/main/java/flab/nutridiary/product/repository/ProductCrudRepository.java +++ b/src/main/java/flab/nutridiary/product/repository/ProductCrudRepository.java @@ -1,11 +1,8 @@ package flab.nutridiary.product.repository; import flab.nutridiary.product.domain.Product; -import org.springframework.data.jdbc.repository.query.Query; import org.springframework.data.repository.CrudRepository; public interface ProductCrudRepository extends CrudRepository { - - @Query("select count(*) from product where product_normalized_name = :normalizedName") - Integer isExistDuplicatedProductByNormalizedName(String normalizedName); + int countByProductNormalizedName(String normalizedName); } diff --git a/src/main/java/flab/nutridiary/product/repository/ProductRepositoryImpl.java b/src/main/java/flab/nutridiary/product/repository/ProductRepositoryImpl.java index ba0d6bc..3ea14d5 100644 --- a/src/main/java/flab/nutridiary/product/repository/ProductRepositoryImpl.java +++ b/src/main/java/flab/nutridiary/product/repository/ProductRepositoryImpl.java @@ -25,6 +25,6 @@ public Optional findById(Long id) { @Override public Boolean isExistDuplicatedProductByNormalizedName(String normalizedName) { - return productCrudRepository.isExistDuplicatedProductByNormalizedName(normalizedName) > 0; + return productCrudRepository.countByProductNormalizedName(normalizedName) > 0; } } diff --git a/src/test/java/flab/nutridiary/diary/controller/DiaryControllerTest.java b/src/test/java/flab/nutridiary/diary/controller/DiaryControllerTest.java index f1095ad..20fbb3c 100644 --- a/src/test/java/flab/nutridiary/diary/controller/DiaryControllerTest.java +++ b/src/test/java/flab/nutridiary/diary/controller/DiaryControllerTest.java @@ -2,15 +2,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import flab.nutridiary.commom.generic.Nutrition; -import flab.nutridiary.product.domain.ServingUnit; -import flab.nutridiary.diary.domain.Diary; -import flab.nutridiary.diary.domain.DiaryRecord; -import flab.nutridiary.diary.domain.MealType; -import flab.nutridiary.diary.dto.AddDiaryRecordRequest; -import flab.nutridiary.diary.dto.DiaryRegisterRequest; +import flab.nutridiary.diary.domain.*; +import flab.nutridiary.diary.dto.request.AddDiaryRecordRequest; +import flab.nutridiary.diary.dto.request.DiaryRegisterRequest; import flab.nutridiary.diary.repository.DiaryRepository; import flab.nutridiary.product.domain.NutritionFacts; import flab.nutridiary.product.domain.Product; +import flab.nutridiary.product.domain.ServingUnit; import flab.nutridiary.product.repository.ProductRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -28,6 +26,7 @@ import java.util.List; import static java.math.BigDecimal.valueOf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -40,32 +39,43 @@ class DiaryControllerTest { @Autowired private MockMvc mockMvc; @Autowired + private NutritionCalculator nutritionCalculator; + @Autowired private ProductRepository productRepository; @Autowired private DiaryRepository diaryRepository; @Autowired private ObjectMapper objectMapper; - private Long savedProductId; + private List savedProductIds = new ArrayList<>(); @BeforeEach void init() { - // given - NutritionFacts nutritionFacts = NutritionFacts.builder() - .nutritionPerOneServingUnit(Nutrition.of(valueOf(50), valueOf(5), valueOf(10), valueOf(15))) - .allowedProductServingUnits( - new ArrayList<>(List.of( - ServingUnit.asOneServingUnit("개"), - ServingUnit.ofGram(BigDecimal.ONE, valueOf(50))))) - .build(); - - Product product = Product.builder() + Product product1 = Product.builder() .productName("사과") .productCorp("사과회사") - .nutritionFacts(nutritionFacts) + .nutritionFacts(NutritionFacts.builder() + .nutritionPerOneServingUnit(Nutrition.of(valueOf(50), valueOf(5), valueOf(10), valueOf(15))) + .allowedProductServingUnits( + new ArrayList<>(List.of( + ServingUnit.asOneServingUnit("개"), + ServingUnit.ofGram(BigDecimal.ONE, valueOf(50))))) + .build()) .build(); - savedProductId = productRepository.save(product).getId(); + Product product2 = Product.builder() + .productName("바나나") + .productCorp("바나나회사") + .nutritionFacts(NutritionFacts.builder() + .nutritionPerOneServingUnit(Nutrition.of(valueOf(250), valueOf(20), valueOf(20), valueOf(15))) + .allowedProductServingUnits( + new ArrayList<>(List.of( + ServingUnit.asOneServingUnit("컵"), + ServingUnit.ofGram(BigDecimal.ONE, valueOf(150))))) + .build()) + .build(); + savedProductIds.add(productRepository.save(product1).getId()); + savedProductIds.add(productRepository.save(product2).getId()); } @@ -73,7 +83,7 @@ void init() { @Test void createDiary() throws Exception { // given - DiaryRegisterRequest diaryRegisterRequest = new DiaryRegisterRequest(savedProductId, "BREAKFAST", valueOf(1), "gram", LocalDate.of(2024, 8, 10)); + DiaryRegisterRequest diaryRegisterRequest = new DiaryRegisterRequest(savedProductIds.getFirst(), "BREAKFAST", valueOf(1), "gram", LocalDate.of(2024, 8, 10)); // when then mockMvc.perform( @@ -93,7 +103,7 @@ void addDiaryRecord() throws Exception { // given Diary diary = new Diary(LocalDate.of(2024, 8, 10), DiaryRecord.builder() - .productId(savedProductId) + .productId(savedProductIds.getFirst()) .mealType(MealType.BREAKFAST) .quantity(valueOf(1)) .clientChoiceServingUnitDescription("컵") @@ -101,7 +111,7 @@ void addDiaryRecord() throws Exception { .build()); Long diaryId = diaryRepository.save(diary).getId(); - AddDiaryRecordRequest addDiaryRecordRequest = new AddDiaryRecordRequest(savedProductId, "BREAKFAST", BigDecimal.valueOf(10), "gram"); + AddDiaryRecordRequest addDiaryRecordRequest = new AddDiaryRecordRequest(savedProductIds.getFirst(), "BREAKFAST", BigDecimal.valueOf(10), "gram"); // when then mockMvc.perform( @@ -119,7 +129,7 @@ void addDiaryRecord() throws Exception { @Test void addDiaryRecordWithInvalidServingUnit() throws Exception { // given - DiaryRegisterRequest diaryRegisterRequest = new DiaryRegisterRequest(savedProductId, "BREAKFAST", valueOf(1), "InvalidServingUnit", LocalDate.of(2024, 8, 10)); + DiaryRegisterRequest diaryRegisterRequest = new DiaryRegisterRequest(savedProductIds.getFirst(), "BREAKFAST", valueOf(1), "InvalidServingUnit", LocalDate.of(2024, 8, 10)); // when then mockMvc.perform( @@ -137,7 +147,7 @@ void addDiaryRecordWithInvalidServingUnit() throws Exception { @Test void mealType() throws Exception { // given - DiaryRegisterRequest diaryRegisterRequest = new DiaryRegisterRequest(savedProductId, "WRONG", valueOf(1), "gram", LocalDate.of(2024, 8, 10)); + DiaryRegisterRequest diaryRegisterRequest = new DiaryRegisterRequest(savedProductIds.getFirst(), "WRONG", valueOf(1), "gram", LocalDate.of(2024, 8, 10)); // when then mockMvc.perform( @@ -150,4 +160,49 @@ void mealType() throws Exception { .andExpect(jsonPath("$.message").value("유효성 검사에 실패했습니다.")) .andExpect(jsonPath("$.data.mealType").value("올바른 식사 타입을 입력해주세요.")); } + + @DisplayName("다이어리 조회 테스트") + @Test + void getDiary() throws Exception { + // given + Diary diary = Diary.builder() + .diaryDate(LocalDate.of(2024, 8, 10)) + .diaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(0)) + .mealType("BREAKFAST") + .clientChoiceServingUnitDescription("개") + .quantity(valueOf(2)) + .build(), + nutritionCalculator)) + .build(); + diary.addDiaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(1)) + .mealType("BREAKFAST") + .clientChoiceServingUnitDescription("컵") + .quantity(valueOf(2)) + .build(), + nutritionCalculator)); + diary.addDiaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(0)) + .mealType("LUNCH") + .clientChoiceServingUnitDescription("gram") + .quantity(valueOf(200)) + .build(), + nutritionCalculator)); + Long diaryId = diaryRepository.save(diary).getId(); + + // when then + mockMvc.perform( + get("/diary") + .param("diaryDate", "2024-08-10") + .contentType("application/json")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.statusCode").value(2001)) + .andExpect(jsonPath("$.message").value("OK")) + .andExpect(jsonPath("$.data[0].diaryId").value(diaryId)) + .andExpect(jsonPath("$.data[0].diaryDate").value("2024-08-10")); + } } \ No newline at end of file diff --git a/src/test/java/flab/nutridiary/diary/repository/DiaryRepositoryTest.java b/src/test/java/flab/nutridiary/diary/repository/DiaryRepositoryTest.java index f86b3c7..4172cea 100644 --- a/src/test/java/flab/nutridiary/diary/repository/DiaryRepositoryTest.java +++ b/src/test/java/flab/nutridiary/diary/repository/DiaryRepositoryTest.java @@ -4,6 +4,11 @@ import flab.nutridiary.diary.domain.Diary; import flab.nutridiary.diary.domain.DiaryRecord; import flab.nutridiary.diary.domain.MealType; +import flab.nutridiary.product.domain.NutritionFacts; +import flab.nutridiary.product.domain.Product; +import flab.nutridiary.product.domain.ServingUnit; +import flab.nutridiary.product.repository.ProductRepository; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -11,7 +16,10 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import static java.math.BigDecimal.ONE; @@ -22,15 +30,45 @@ @Transactional @SpringBootTest class DiaryRepositoryTest { - @Autowired private DiaryRepository diaryRepository; - + @Autowired + private ProductRepository productRepository; + private List savedProductIds = new ArrayList<>(); private Long memberId = 1L; + @BeforeEach + void init() { + Product product1 = Product.builder() + .productName("사과") + .productCorp("사과회사") + .nutritionFacts(NutritionFacts.builder() + .nutritionPerOneServingUnit(Nutrition.of(valueOf(50), valueOf(5), valueOf(10), valueOf(15))) + .allowedProductServingUnits( + new ArrayList<>(List.of( + ServingUnit.asOneServingUnit("개"), + ServingUnit.ofGram(BigDecimal.ONE, valueOf(50))))) + .build()) + .build(); + + Product product2 = Product.builder() + .productName("바나나") + .productCorp("바나나회사") + .nutritionFacts(NutritionFacts.builder() + .nutritionPerOneServingUnit(Nutrition.of(valueOf(250), valueOf(20), valueOf(20), valueOf(15))) + .allowedProductServingUnits( + new ArrayList<>(List.of( + ServingUnit.asOneServingUnit("컵"), + ServingUnit.ofGram(BigDecimal.ONE, valueOf(150))))) + .build()) + .build(); + savedProductIds.add(productRepository.save(product1).getId()); + savedProductIds.add(productRepository.save(product2).getId()); + } + @DisplayName("Diary를 저장한다.") @Test - void savd() throws Exception { + void save() throws Exception { // given LocalDate date = LocalDate.of(2024, 8, 1); Nutrition calculatedNutrition = Nutrition.of(valueOf(100), valueOf(10), valueOf(20), valueOf(30)); @@ -55,7 +93,6 @@ void savd() throws Exception { @DisplayName("memberId 와 date 로 사용자 Diary 를 조회한다.") @Test void findByMemberIdAndDiaryDate() throws Exception { - // given LocalDate date = LocalDate.of(2024, 8, 1); Nutrition calculatedNutrition = Nutrition.of(valueOf(100), valueOf(10), valueOf(20), valueOf(30)); diff --git a/src/test/java/flab/nutridiary/diary/repository/DiarySearchRepositoryTest.java b/src/test/java/flab/nutridiary/diary/repository/DiarySearchRepositoryTest.java new file mode 100644 index 0000000..641d0ef --- /dev/null +++ b/src/test/java/flab/nutridiary/diary/repository/DiarySearchRepositoryTest.java @@ -0,0 +1,117 @@ +package flab.nutridiary.diary.repository; + +import flab.nutridiary.commom.generic.Nutrition; +import flab.nutridiary.diary.domain.*; +import flab.nutridiary.diary.dto.response.query.DiaryRecordWithProduct; +import flab.nutridiary.product.domain.NutritionFacts; +import flab.nutridiary.product.domain.Product; +import flab.nutridiary.product.domain.ServingUnit; +import flab.nutridiary.product.repository.ProductRepository; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +import static java.math.BigDecimal.valueOf; + +@ActiveProfiles("test") +@Transactional +@SpringBootTest +class DiarySearchRepositoryTest { + @Autowired + private NutritionCalculator nutritionCalculator; + @Autowired + private DiarySearchRepository diarySearchRepository; + @Autowired + private DiaryRepository diaryRepository; + @Autowired + private ProductRepository productRepository; + private List savedProductIds = new ArrayList<>(); + private Long memberId = 1L; + + @BeforeEach + void init() { + Product product1 = Product.builder() + .productName("사과") + .productCorp("사과회사") + .nutritionFacts(NutritionFacts.builder() + .nutritionPerOneServingUnit(Nutrition.of(valueOf(50), valueOf(5), valueOf(10), valueOf(15))) + .allowedProductServingUnits( + new ArrayList<>(List.of( + ServingUnit.asOneServingUnit("개"), + ServingUnit.ofGram(BigDecimal.ONE, valueOf(50))))) + .build()) + .build(); + + Product product2 = Product.builder() + .productName("바나나") + .productCorp("바나나회사") + .nutritionFacts(NutritionFacts.builder() + .nutritionPerOneServingUnit(Nutrition.of(valueOf(250), valueOf(20), valueOf(20), valueOf(15))) + .allowedProductServingUnits( + new ArrayList<>(List.of( + ServingUnit.asOneServingUnit("컵"), + ServingUnit.ofGram(BigDecimal.ONE, valueOf(150))))) + .build()) + .build(); + savedProductIds.add(productRepository.save(product1).getId()); + savedProductIds.add(productRepository.save(product2).getId()); + } + + @DisplayName("memberId와 date로 DiaryRecordWithProduct 리스트를 조회한다.") + @Test + void findDiaryWithProductsByMemberIdAndDiaryDate() throws Exception { + // given + Diary diary = Diary.builder() + .diaryDate(LocalDate.of(2024, 8, 10)) + .diaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(0)) + .mealType("BREAKFAST") + .clientChoiceServingUnitDescription("개") + .quantity(valueOf(2)) + .build(), + nutritionCalculator)) + .build(); + diary.addDiaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(1)) + .mealType("BREAKFAST") + .clientChoiceServingUnitDescription("컵") + .quantity(valueOf(2)) + .build(), + nutritionCalculator)); + diary.addDiaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(0)) + .mealType("LUNCH") + .clientChoiceServingUnitDescription("gram") + .quantity(valueOf(200)) + .build(), + nutritionCalculator)); + Long diaryId = diaryRepository.save(diary).getId(); + + // when + List results = diarySearchRepository.findDiaryWithProductAllByMemberIdAndDiaryDate(memberId, LocalDate.of(2024, 8, 10)); + + // then + List expectedResults = List.of( + new DiaryRecordWithProduct(1L, 1L, LocalDate.of(2024, 8, 10), 1L, MealType.BREAKFAST, "사과", "사과회사", valueOf(2), "개", Nutrition.of(valueOf(100), valueOf(10), valueOf(20), valueOf(30))), + new DiaryRecordWithProduct(1L, 1L, LocalDate.of(2024, 8, 10), 2L, MealType.LUNCH, "사과", "사과회사", valueOf(200), "gram", Nutrition.of(valueOf(200), valueOf(20), valueOf(40), valueOf(60))), + new DiaryRecordWithProduct(1L, 1L, LocalDate.of(2024, 8, 10), 3L, MealType.BREAKFAST, "바나나", "바나나회사", valueOf(2), "컵", Nutrition.of(valueOf(500), valueOf(40), valueOf(40), valueOf(30))) + ); + + Assertions.assertThat(results).containsExactlyInAnyOrderElementsOf(expectedResults); + } + + +} \ No newline at end of file diff --git a/src/test/java/flab/nutridiary/diary/service/DiaryRegisterServiceTest.java b/src/test/java/flab/nutridiary/diary/service/DiaryRegisterServiceTest.java index ef2f37b..b812cb5 100644 --- a/src/test/java/flab/nutridiary/diary/service/DiaryRegisterServiceTest.java +++ b/src/test/java/flab/nutridiary/diary/service/DiaryRegisterServiceTest.java @@ -6,9 +6,9 @@ import flab.nutridiary.diary.domain.Diary; import flab.nutridiary.diary.domain.DiaryRecord; import flab.nutridiary.diary.domain.MealType; -import flab.nutridiary.diary.dto.AddDiaryRecordRequest; -import flab.nutridiary.diary.dto.DiaryRegisterRequest; -import flab.nutridiary.diary.dto.DiarySavedResponse; +import flab.nutridiary.diary.dto.request.AddDiaryRecordRequest; +import flab.nutridiary.diary.dto.request.DiaryRegisterRequest; +import flab.nutridiary.diary.dto.response.DiarySavedResponse; import flab.nutridiary.diary.repository.DiaryRepository; import flab.nutridiary.product.domain.NutritionFacts; import flab.nutridiary.product.domain.Product; diff --git a/src/test/java/flab/nutridiary/diary/service/DiarySearchServiceTest.java b/src/test/java/flab/nutridiary/diary/service/DiarySearchServiceTest.java new file mode 100644 index 0000000..f74b0b8 --- /dev/null +++ b/src/test/java/flab/nutridiary/diary/service/DiarySearchServiceTest.java @@ -0,0 +1,120 @@ +package flab.nutridiary.diary.service; + +import flab.nutridiary.commom.generic.Nutrition; +import flab.nutridiary.diary.domain.*; +import flab.nutridiary.diary.dto.response.query.DiaryRecordWithProduct; +import flab.nutridiary.diary.repository.DiaryRepository; +import flab.nutridiary.product.domain.NutritionFacts; +import flab.nutridiary.product.domain.Product; +import flab.nutridiary.product.domain.ServingUnit; +import flab.nutridiary.product.repository.ProductRepository; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +import static java.math.BigDecimal.valueOf; + +@ActiveProfiles("test") +@Transactional +@SpringBootTest +class DiarySearchServiceTest { + @Autowired + private NutritionCalculator nutritionCalculator; + @Autowired + private DiaryRepository diaryRepository; + @Autowired + private DiarySearchService diarySearchService; + @Autowired + private ProductRepository productRepository; + private List savedProductIds = new ArrayList<>(); + + @BeforeEach + void init() { + // product + Product product1 = Product.builder() + .productName("사과") + .productCorp("사과회사") + .nutritionFacts(NutritionFacts.builder() + .nutritionPerOneServingUnit(Nutrition.of(valueOf(50), valueOf(5), valueOf(10), valueOf(15))) + .allowedProductServingUnits( + new ArrayList<>(List.of( + ServingUnit.asOneServingUnit("개"), + ServingUnit.ofGram(BigDecimal.ONE, valueOf(50))))) + .build()) + .build(); + + Product product2 = Product.builder() + .productName("바나나") + .productCorp("바나나회사") + .nutritionFacts(NutritionFacts.builder() + .nutritionPerOneServingUnit(Nutrition.of(valueOf(250), valueOf(20), valueOf(20), valueOf(15))) + .allowedProductServingUnits( + new ArrayList<>(List.of( + ServingUnit.asOneServingUnit("컵"), + ServingUnit.ofGram(BigDecimal.ONE, valueOf(150))))) + .build()) + .build(); + savedProductIds.add(productRepository.save(product1).getId()); + savedProductIds.add(productRepository.save(product2).getId()); + + // diary + Diary diary = Diary.builder() + .diaryDate(LocalDate.of(2024, 8, 10)) + .diaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(0)) + .mealType("BREAKFAST") + .clientChoiceServingUnitDescription("개") + .quantity(valueOf(2)) + .build(), + nutritionCalculator)) + .build(); + diary.addDiaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(1)) + .mealType("BREAKFAST") + .clientChoiceServingUnitDescription("컵") + .quantity(valueOf(2)) + .build(), + nutritionCalculator)); + diary.addDiaryRecord(DiaryRecord.of( + ProductIntakeInfo.builder() + .productId(savedProductIds.get(0)) + .mealType("LUNCH") + .clientChoiceServingUnitDescription("gram") + .quantity(valueOf(200)) + .build(), + nutritionCalculator)); + diaryRepository.save(diary); + } + + @DisplayName("memberId와 date로 DiaryRecordWithProduct 리스트를 조회한다.") + @Test + void getDiary() throws Exception { + // given + Long memberId = 1L; + LocalDate date = LocalDate.of(2024, 8, 10); + + //when + List results = diarySearchService.getDiary(memberId, date); + + // then + List expectedResults = List.of( + new DiaryRecordWithProduct(1L, 1L, LocalDate.of(2024, 8, 10), 1L, MealType.BREAKFAST, "사과", "사과회사", valueOf(2), "개", Nutrition.of(valueOf(100), valueOf(10), valueOf(20), valueOf(30))), + new DiaryRecordWithProduct(1L, 1L, LocalDate.of(2024, 8, 10), 2L, MealType.LUNCH, "사과", "사과회사", valueOf(200), "gram", Nutrition.of(valueOf(200), valueOf(20), valueOf(40), valueOf(60))), + new DiaryRecordWithProduct(1L, 1L, LocalDate.of(2024, 8, 10), 3L, MealType.BREAKFAST, "바나나", "바나나회사", valueOf(2), "컵", Nutrition.of(valueOf(500), valueOf(40), valueOf(40), valueOf(30))) + ); + + Assertions.assertThat(results).containsExactlyInAnyOrderElementsOf(expectedResults); + } +} \ No newline at end of file diff --git a/src/test/java/flab/nutridiary/diary/service/ProductIntakeInfoMapperTest.java b/src/test/java/flab/nutridiary/diary/service/ProductIntakeInfoMapperTest.java index 937abdb..ffd69dc 100644 --- a/src/test/java/flab/nutridiary/diary/service/ProductIntakeInfoMapperTest.java +++ b/src/test/java/flab/nutridiary/diary/service/ProductIntakeInfoMapperTest.java @@ -2,7 +2,7 @@ import flab.nutridiary.diary.domain.MealType; import flab.nutridiary.diary.domain.ProductIntakeInfo; -import flab.nutridiary.diary.dto.DiaryRegisterRequest; +import flab.nutridiary.diary.dto.request.DiaryRegisterRequest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test;