diff --git a/.gitignore b/.gitignore index 7dbfa83c..38944b87 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,4 @@ out/ .vscode/ ### Setting File ### -src/main/resources/application.yml \ No newline at end of file +src/main/resources/** \ No newline at end of file diff --git a/src/main/java/com/bbteam/budgetbuddies/common/BaseEntity.java b/src/main/java/com/bbteam/budgetbuddies/common/BaseEntity.java index b66eef77..b8e40e17 100644 --- a/src/main/java/com/bbteam/budgetbuddies/common/BaseEntity.java +++ b/src/main/java/com/bbteam/budgetbuddies/common/BaseEntity.java @@ -21,6 +21,7 @@ @AllArgsConstructor @SuperBuilder @SoftDelete // boolean 타입의 deleted 필드가 추가 +@Getter public abstract class BaseEntity { @Id diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/repository/ConsumptionGoalRepository.java b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/repository/ConsumptionGoalRepository.java index 40ee25d7..972a8c7c 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/repository/ConsumptionGoalRepository.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/repository/ConsumptionGoalRepository.java @@ -30,7 +30,7 @@ Optional findConsumptionGoalByUserAndCategoryAndGoalMonth(User LocalDate goalMonth); @Query("SELECT cg FROM ConsumptionGoal cg JOIN cg.category c WHERE c.id = :categoryId AND cg.goalMonth " - + "BETWEEN :startOfWeek AND :endOfWeek ORDER BY cg.consumeAmount DESC") + + "BETWEEN :startOfWeek AND :endOfWeek ORDER BY cg.consumeAmount DESC limit 1") Optional findTopConsumptionByCategoryIdAndCurrentWeek(@Param("categoryId") Long categoryId, @Param("startOfWeek") LocalDate startOfWeek, @Param("endOfWeek") LocalDate endOfWeek); } \ No newline at end of file diff --git a/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/repository/ConsumptionGoalRepositoryTest.java b/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/repository/ConsumptionGoalRepositoryTest.java index 571f5189..13deca84 100644 --- a/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/repository/ConsumptionGoalRepositoryTest.java +++ b/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/repository/ConsumptionGoalRepositoryTest.java @@ -4,6 +4,7 @@ import java.time.LocalDate; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,6 +17,7 @@ import com.bbteam.budgetbuddies.domain.consumptiongoal.entity.ConsumptionGoal; import com.bbteam.budgetbuddies.domain.user.entity.User; import com.bbteam.budgetbuddies.domain.user.repository.UserRepository; +import com.bbteam.budgetbuddies.enums.Gender; @DisplayName("ConsumptionGoal 레포지토리 테스트의 ") @DataJpaTest @@ -63,7 +65,8 @@ void findConsumptionGoalByUserIdAndGoalMonth_Success() { setUnselectedConsumptionGoal(mainUser, goalMonth, defaultCategory); // when - List result = consumptionGoalRepository.findConsumptionGoalByUserIdAndGoalMonth(mainUser.getId(), + List result = consumptionGoalRepository.findConsumptionGoalByUserIdAndGoalMonth( + mainUser.getId(), goalMonth); // then @@ -71,6 +74,98 @@ void findConsumptionGoalByUserIdAndGoalMonth_Success() { .isEqualTo(List.of(defaultCategoryConsumptionGoal, userCategoryConsumptionGoal)); } + @Test + @DisplayName("또래 나이와 성별 정보를 통해 GoalConsumption 조회 성공") + void findTopCategoriesAndGoalAmount_Success() { + //given + User mainUser = userRepository.save( + User.builder() + .email("email") + .age(24) + .name("name") + .gender(Gender.MALE) + .phoneNumber("010-1234-5678") + .build()); + + Category defaultCategory = categoryRepository.save( + Category.builder().name("디폴트 카테고리").user(null).isDefault(true).build()); + + LocalDate goalMonth = LocalDate.of(2024, 07, 01); + + ConsumptionGoal defaultCategoryConsumptionGoal = consumptionGoalRepository.save(ConsumptionGoal.builder() + .goalAmount(1L) + .consumeAmount(1L) + .user(mainUser) + .goalMonth(goalMonth) + .category(defaultCategory) + .build()); + + // when + int top = 4; + int peerAgeStart = 23; + int peerAgeEnd = 25; + Gender peerGender = Gender.MALE; + + List result = consumptionGoalRepository.findTopCategoriesAndGoalAmount( + top, peerAgeStart, peerAgeEnd, peerGender); + + // then + ConsumptionGoal resultGoal = result.get(0); + assertThat(resultGoal.getGoalAmount()).isEqualTo(1L); + assertThat(resultGoal.getConsumeAmount()).isEqualTo(1L); + assertThat(resultGoal.getUser().getAge()).isEqualTo(24); + assertThat(resultGoal.getCategory().getName()).isEqualTo("디폴트 카테고리"); + assertThat(resultGoal.getUser().getGender()).isEqualTo(Gender.MALE); + } + + @Test + @DisplayName("또래들이 가장 큰 목표로 세운 카테고리와 그 카테고리에서 이번 주의 소비 목표 조회 성공") + void findTopConsumptionByCategoryIdAndCurrentWeek_Success() { + // given + LocalDate startOfWeek = LocalDate.of(2024, 7, 1); // 월요일 + LocalDate endOfWeek = LocalDate.of(2024, 7, 7); // 일요일 + + User mainUser = userRepository.save(User.builder() + .email("email") + .age(24) + .name("name") + .gender(Gender.MALE) + .phoneNumber("010-1234-5678") + .build()); + + Category category = categoryRepository.save(Category.builder() + .name("Test Category") + .user(mainUser) + .isDefault(false) + .build()); + + ConsumptionGoal goal1 = consumptionGoalRepository.save(ConsumptionGoal.builder() + .goalAmount(5000L) + .consumeAmount(2000L) + .user(mainUser) + .category(category) + .goalMonth(startOfWeek) + .build()); + + ConsumptionGoal goal2 = consumptionGoalRepository.save(ConsumptionGoal.builder() + .goalAmount(3000L) + .consumeAmount(1500L) + .user(mainUser) + .category(category) + .goalMonth(startOfWeek) + .build()); + + // when + Optional result = consumptionGoalRepository.findTopConsumptionByCategoryIdAndCurrentWeek( + category.getId(), startOfWeek, endOfWeek); + + // then + ConsumptionGoal topGoal = result.get(); + assertThat(topGoal.getConsumeAmount()).isEqualTo(2000L); + assertThat(topGoal.getGoalAmount()).isEqualTo(5000L); + assertThat(topGoal.getCategory().getId()).isEqualTo(category.getId()); + } + private void setUnselectedConsumptionGoal(User mainUser, LocalDate goalMonth, Category defaultCategory) { User otherUser = userRepository.save( User.builder().email("email2").age(24).name("name2").phoneNumber("010-1567-5678").build()); diff --git a/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceTest.java b/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceTest.java index 261e25f9..ca282360 100644 --- a/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceTest.java +++ b/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceTest.java @@ -1,10 +1,14 @@ package com.bbteam.budgetbuddies.domain.consumptiongoal.service; import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.BDDMockito.*; +import java.time.DayOfWeek; import java.time.LocalDate; +import java.time.temporal.TemporalAdjusters; import java.util.List; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.Random; @@ -21,14 +25,18 @@ import com.bbteam.budgetbuddies.domain.category.entity.Category; import com.bbteam.budgetbuddies.domain.category.repository.CategoryRepository; import com.bbteam.budgetbuddies.domain.consumptiongoal.converter.ConsumptionGoalConverter; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionAnalysisResponseDTO; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionGoalListRequestDto; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionGoalRequestDto; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionGoalResponseDto; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionGoalResponseListDto; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.PeerInfoResponseDTO; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.TopGoalCategoryResponseDTO; import com.bbteam.budgetbuddies.domain.consumptiongoal.entity.ConsumptionGoal; import com.bbteam.budgetbuddies.domain.consumptiongoal.repository.ConsumptionGoalRepository; import com.bbteam.budgetbuddies.domain.user.entity.User; import com.bbteam.budgetbuddies.domain.user.repository.UserRepository; +import com.bbteam.budgetbuddies.enums.Gender; @DisplayName("ConsumptionGoalImpl 서비스 테스트의 ") @ExtendWith(MockitoExtension.class) @@ -54,7 +62,7 @@ void setUp() { int randomDay = random.nextInt(30) + 1; goalMonthRandomDay = LocalDate.of(GOAL_MONTH.getYear(), GOAL_MONTH.getMonth(), randomDay); - user = Mockito.spy(User.builder().email("email").age(24).name("name").phoneNumber("010-1234-5678").build()); + user = Mockito.spy(User.builder().email("email").age(24).name("name").gender(Gender.MALE).phoneNumber("010-1234-5678").build()); given(user.getId()).willReturn(-1L); given(userRepository.findById(user.getId())).willReturn(Optional.ofNullable(user)); } @@ -207,20 +215,17 @@ void updateConsumptionGoal_Success() { return goalsToSave; }); - List expected = List.of( - ConsumptionGoalResponseDto.builder() - .goalAmount(defaultGoalAmount) - .consumeAmount(defaultCategoryGoal.getConsumeAmount()) - .categoryName(defaultCategory.getName()) - .categoryId(defaultCategory.getId()) - .build(), - ConsumptionGoalResponseDto.builder() - .goalAmount(userGoalAmount) - .consumeAmount(0L) - .categoryName(userCategory.getName()) - .categoryId(userCategory.getId()) - .build() - ); + List expected = List.of(ConsumptionGoalResponseDto.builder() + .goalAmount(defaultGoalAmount) + .consumeAmount(defaultCategoryGoal.getConsumeAmount()) + .categoryName(defaultCategory.getName()) + .categoryId(defaultCategory.getId()) + .build(), ConsumptionGoalResponseDto.builder() + .goalAmount(userGoalAmount) + .consumeAmount(0L) + .categoryName(userCategory.getName()) + .categoryId(userCategory.getId()) + .build()); // when ConsumptionGoalResponseListDto result = consumptionGoalService.updateConsumptionGoals(user.getId(), request); @@ -228,4 +233,143 @@ void updateConsumptionGoal_Success() { // then assertThat(result.getConsumptionGoalList()).usingRecursiveComparison().isEqualTo(expected); } + + @Test + @DisplayName("getPeerInfo : 또래 나이와 성별 정보를 통해 PeerInfo 조회 성공") + void getPeerInfo_Success() { + // given + when(userRepository.findById(user.getId())).thenReturn(Optional.of(user)); + + // when + int peerAgeStart = 23; + int peerAgeEnd = 25; + String peerGender = "MALE"; + + PeerInfoResponseDTO result = consumptionGoalService.getPeerInfo(user.getId(), peerAgeStart, peerAgeEnd, + peerGender); + + // then + assertThat(result).isNotNull(); + assertThat(result.getPeerAgeStart()).isEqualTo(peerAgeStart); + assertThat(result.getPeerAgeEnd()).isEqualTo(peerAgeEnd); + assertThat(result.getPeerGender()).isEqualTo("MALE"); + } + + @Test + @DisplayName("getPeerInfo : 유저를 찾을 수 없음") + void getPeerInfo_UserNotFound() { + // given + when(userRepository.findById(user.getId())).thenReturn(Optional.empty()); + + // when + int peerAgeStart = 23; + int peerAgeEnd = 25; + String peerGender = "MALE"; + + // then + assertThrows(NoSuchElementException.class, () -> { + consumptionGoalService.getPeerInfo(user.getId(), peerAgeStart, peerAgeEnd, peerGender); + }); + } + + @Test + @DisplayName("getTopCategoryAndConsumptionAmount : 가장 큰 계획 카테고리와 이번 주 소비 금액 조회 성공") + void getTopCategoryAndConsumptionAmount_Success() { + // given + Category defaultCategory = Mockito.spy(Category.builder().name("디폴트 카테고리").user(null).isDefault(true).build()); + given(defaultCategory.getId()).willReturn(-1L); + + ConsumptionGoal topConsumptionGoal = ConsumptionGoal.builder() + .goalAmount(5000L) + .consumeAmount(3000L) + .user(user) + .category(defaultCategory) + .goalMonth(goalMonthRandomDay) + .build(); + + ConsumptionGoal currentWeekConsumptionGoal = ConsumptionGoal.builder() + .goalAmount(5000L) + .consumeAmount(2000L) + .user(user) + .category(defaultCategory) + .goalMonth(goalMonthRandomDay) + .build(); + + LocalDate startOfWeek = goalMonthRandomDay.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + LocalDate endOfWeek = goalMonthRandomDay.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); + + given(userRepository.findById(user.getId())).willReturn(Optional.of(user)); + given(consumptionGoalRepository.findTopCategoriesAndGoalAmount(1, 23, 25, Gender.MALE)) + .willReturn(List.of(topConsumptionGoal)); + given(consumptionGoalRepository.findTopConsumptionByCategoryIdAndCurrentWeek( + defaultCategory.getId(), startOfWeek, endOfWeek)) + .willReturn(Optional.of(currentWeekConsumptionGoal)); + + // when + ConsumptionAnalysisResponseDTO result = consumptionGoalService.getTopCategoryAndConsumptionAmount(user.getId()); + + // then + assertThat(result.getGoalCategory()).isEqualTo(defaultCategory.getName()); + assertThat(result.getCurrentWeekConsumptionAmount()).isEqualTo(currentWeekConsumptionGoal.getConsumeAmount()); + } + + @Test + @DisplayName("getTopGoalCategories : 또래들이 세운 가장 큰 목표 카테고리 조회 top 4 성공") + void getTopGoalCategories_Success() { + // given + Category defaultCategory = Mockito.spy(Category.builder().name("디폴트 카테고리").user(null).isDefault(true).build()); + Category defaultCategory2 = Mockito.spy(Category.builder().name("디폴트 카테고리2").user(null).isDefault(true).build()); + Category defaultCategory3 = Mockito.spy(Category.builder().name("디폴트 카테고리3").user(null).isDefault(true).build()); + Category defaultCategory4 = Mockito.spy(Category.builder().name("디폴트 카테고리4").user(null).isDefault(true).build()); + + ConsumptionGoal topConsumptionGoal1 = ConsumptionGoal.builder() + .goalAmount(5000L) + .consumeAmount(3000L) + .user(user) + .category(defaultCategory) + .goalMonth(goalMonthRandomDay) + .build(); + + ConsumptionGoal topConsumptionGoal2 = ConsumptionGoal.builder() + .goalAmount(6000L) + .consumeAmount(3000L) + .user(user) + .category(defaultCategory2) + .goalMonth(goalMonthRandomDay) + .build(); + + ConsumptionGoal topConsumptionGoal3 = ConsumptionGoal.builder() + .goalAmount(7000L) + .consumeAmount(3000L) + .user(user) + .category(defaultCategory3) + .goalMonth(goalMonthRandomDay) + .build(); + + ConsumptionGoal topConsumptionGoal4 = ConsumptionGoal.builder() + .goalAmount(8000L) + .consumeAmount(3000L) + .user(user) + .category(defaultCategory4) + .goalMonth(goalMonthRandomDay) + .build(); + + given(userRepository.findById(user.getId())).willReturn(Optional.of(user)); + given(consumptionGoalRepository.findTopCategoriesAndGoalAmount(4, 23, 25, Gender.MALE)) + .willReturn(List.of(topConsumptionGoal1, topConsumptionGoal2, topConsumptionGoal3, topConsumptionGoal4)); + + // when + List result = consumptionGoalService.getTopGoalCategories(4, user.getId(), 0, 0, "none"); + + // then + assertThat(result).hasSize(4); + assertThat(result.get(0).getCategoryName()).isEqualTo(defaultCategory.getName()); + assertThat(result.get(0).getGoalAmount()).isEqualTo(topConsumptionGoal1.getGoalAmount()); + assertThat(result.get(1).getCategoryName()).isEqualTo(defaultCategory2.getName()); + assertThat(result.get(1).getGoalAmount()).isEqualTo(topConsumptionGoal2.getGoalAmount()); + assertThat(result.get(2).getCategoryName()).isEqualTo(defaultCategory3.getName()); + assertThat(result.get(2).getGoalAmount()).isEqualTo(topConsumptionGoal3.getGoalAmount()); + assertThat(result.get(3).getCategoryName()).isEqualTo(defaultCategory4.getName()); + assertThat(result.get(3).getGoalAmount()).isEqualTo(topConsumptionGoal4.getGoalAmount()); + } } \ No newline at end of file diff --git a/src/test/java/com/bbteam/budgetbuddies/domain/discountinfo/repository/DiscountInfoRepositoryTest.java b/src/test/java/com/bbteam/budgetbuddies/domain/discountinfo/repository/DiscountInfoRepositoryTest.java index 467f624a..84cf5776 100644 --- a/src/test/java/com/bbteam/budgetbuddies/domain/discountinfo/repository/DiscountInfoRepositoryTest.java +++ b/src/test/java/com/bbteam/budgetbuddies/domain/discountinfo/repository/DiscountInfoRepositoryTest.java @@ -2,6 +2,8 @@ import com.bbteam.budgetbuddies.domain.discountinfo.entity.DiscountInfo; import jakarta.transaction.Transactional; + +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -11,6 +13,7 @@ import org.springframework.data.domain.PageRequest; import java.time.LocalDate; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat;