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 ac2fe37c..46ae852e 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 @@ -1,6 +1,7 @@ package com.bbteam.budgetbuddies.domain.consumptiongoal.repository; import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -24,88 +25,98 @@ public interface ConsumptionGoalRepository extends JpaRepository findConsumptionGoalByUserIdAndGoalMonth(Long userId, LocalDate goalMonth); - Optional findConsumptionGoalByUserAndCategoryAndGoalMonth(User user, Category category, LocalDate goalMonth); + Optional findConsumptionGoalByUserAndCategoryAndGoalMonth(User user, Category category, + LocalDate goalMonth); @Query("SELECT AVG(cg.consumeAmount) FROM ConsumptionGoal cg " + - "JOIN cg.category c " + - "WHERE c.id = :categoryId " + - "AND cg.goalMonth BETWEEN :startOfWeek AND :endOfWeek " + - "AND cg.user.age BETWEEN :peerAgeStart AND :peerAgeEnd " + - "AND cg.user.gender = :peerGender") + "JOIN cg.category c " + + "WHERE c.id = :categoryId " + + "AND cg.deleted = false " + + "AND cg.createdAt BETWEEN :startOfWeek AND :endOfWeek " + + "AND cg.user.age BETWEEN :peerAgeStart AND :peerAgeEnd " + + "AND cg.user.gender = :peerGender") Optional findAvgConsumptionByCategoryIdAndCurrentWeek( - @Param("categoryId") Long categoryId, - @Param("startOfWeek") LocalDate startOfWeek, - @Param("endOfWeek") LocalDate endOfWeek, - @Param("peerAgeStart") int peerAgeStart, - @Param("peerAgeEnd") int peerAgeEnd, - @Param("peerGender") Gender peerGender); + @Param("categoryId") Long categoryId, + @Param("startOfWeek") LocalDateTime startOfWeek, + @Param("endOfWeek") LocalDateTime endOfWeek, + @Param("peerAgeStart") int peerAgeStart, + @Param("peerAgeEnd") int peerAgeEnd, + @Param("peerGender") Gender peerGender); @Query("SELECT new com.bbteam.budgetbuddies.domain.consumptiongoal.dto.AvgConsumptionGoalDto(" + - "cg.category.id, AVG(cg.consumeAmount))" + - "FROM ConsumptionGoal cg " + - "WHERE cg.category.isDefault = true " + - "AND cg.user.age BETWEEN :peerAgeStart AND :peerAgeEnd " + - "AND cg.user.gender = :peerGender " + - "AND cg.goalMonth >= :currentMonth " + - "GROUP BY cg.category.id " + - "ORDER BY AVG(cg.consumeAmount) DESC") + "cg.category.id, AVG(cg.consumeAmount))" + + "FROM ConsumptionGoal cg " + + "WHERE cg.category.isDefault = true " + + "AND cg.deleted = false " + + "AND cg.user.age BETWEEN :peerAgeStart AND :peerAgeEnd " + + "AND cg.user.gender = :peerGender " + + "AND cg.goalMonth >= :currentMonth " + + "GROUP BY cg.category.id " + + "ORDER BY AVG(cg.consumeAmount) DESC") List findAvgConsumptionAmountByCategory( - @Param("peerAgeStart") int peerAgeStart, - @Param("peerAgeEnd") int peerAgeEnd, - @Param("peerGender") Gender peerGender, - @Param("currentMonth") LocalDate currentMonth); + @Param("peerAgeStart") int peerAgeStart, + @Param("peerAgeEnd") int peerAgeEnd, + @Param("peerGender") Gender peerGender, + @Param("currentMonth") LocalDate currentMonth); @Query("SELECT new com.bbteam.budgetbuddies.domain.consumptiongoal.dto.MyConsumptionGoalDto(" + - "cg.category.id, SUM(cg.consumeAmount)) " + - "FROM ConsumptionGoal cg " + - "WHERE cg.category.isDefault = true " + - "AND cg.user.id = :userId " + - "GROUP BY cg.category.id " + - "ORDER BY cg.category.id") + "cg.category.id, SUM(cg.consumeAmount)) " + + "FROM ConsumptionGoal cg " + + "WHERE cg.category.isDefault = true " + + "AND cg.deleted = false " + + "AND cg.user.id = :userId " + + "GROUP BY cg.category.id " + + "ORDER BY cg.category.id") List findAllConsumptionAmountByUserId(@Param("userId") Long userId); @Query("SELECT new com.bbteam.budgetbuddies.domain.consumptiongoal.dto.AvgConsumptionGoalDto(" + - "cg.category.id, AVG(cg.goalAmount))" + - "FROM ConsumptionGoal cg " + - "WHERE cg.category.isDefault = true " + - "AND cg.user.age BETWEEN :peerAgeStart AND :peerAgeEnd " + - "AND cg.user.gender = :peerGender " + - "AND cg.goalMonth >= :currentMonth " + - "GROUP BY cg.category.id " + - "ORDER BY AVG(cg.goalAmount) DESC") + "cg.category.id, AVG(cg.goalAmount))" + + "FROM ConsumptionGoal cg " + + "WHERE cg.category.isDefault = true " + + "AND cg.deleted = false " + + "AND cg.user.age BETWEEN :peerAgeStart AND :peerAgeEnd " + + "AND cg.user.gender = :peerGender " + + "AND cg.goalMonth >= :currentMonth " + + "GROUP BY cg.category.id " + + "ORDER BY AVG(cg.goalAmount) DESC") List findAvgGoalAmountByCategory( - @Param("peerAgeStart") int peerAgeStart, - @Param("peerAgeEnd") int peerAgeEnd, - @Param("peerGender") Gender peerGender, - @Param("currentMonth") LocalDate currentMonth); + @Param("peerAgeStart") int peerAgeStart, + @Param("peerAgeEnd") int peerAgeEnd, + @Param("peerGender") Gender peerGender, + @Param("currentMonth") LocalDate currentMonth); @Query("SELECT new com.bbteam.budgetbuddies.domain.consumptiongoal.dto.MyConsumptionGoalDto(" + - "cg.category.id, SUM(cg.goalAmount)) " + - "FROM ConsumptionGoal cg " + - "WHERE cg.category.isDefault = true " + - "AND cg.user.id = :userId " + - "GROUP BY cg.category.id " + - "ORDER BY cg.category.id") + "cg.category.id, SUM(cg.goalAmount)) " + + "FROM ConsumptionGoal cg " + + "WHERE cg.category.isDefault = true " + + "AND cg.deleted = false " + + "AND cg.user.id = :userId " + + "GROUP BY cg.category.id " + + "ORDER BY cg.category.id") List findAllGoalAmountByUserId(@Param("userId") Long userId); @Query("SELECT new com.bbteam.budgetbuddies.domain.consumptiongoal.dto.CategoryConsumptionCountDto(" + - "cg.category.id, COUNT(cg)) " + - "FROM ConsumptionGoal cg " + - "WHERE cg.category.isDefault = true " + - "AND cg.user.age BETWEEN :peerAgeStart AND :peerAgeEnd " + - "AND cg.user.gender = :peerGender " + - "AND cg.goalMonth >= :currentMonth " + - "GROUP BY cg.category.id " + - "ORDER BY COUNT(cg) DESC") + "cg.category.id, COUNT(cg)) " + + "FROM ConsumptionGoal cg " + + "WHERE cg.category.isDefault = true " + + "AND cg.deleted = false " + + "AND cg.user.age BETWEEN :peerAgeStart AND :peerAgeEnd " + + "AND cg.user.gender = :peerGender " + + "AND cg.goalMonth >= :currentMonth " + + "AND cg.consumeAmount > 0 " + + "GROUP BY cg.category.id " + + "ORDER BY COUNT(cg) DESC") List findTopCategoriesByConsumptionCount( - @Param("peerAgeStart") int peerAgeStart, - @Param("peerAgeEnd") int peerAgeEnd, - @Param("peerGender") Gender peerGender, - @Param("currentMonth") LocalDate currentMonth); + @Param("peerAgeStart") int peerAgeStart, + @Param("peerAgeEnd") int peerAgeEnd, + @Param("peerGender") Gender peerGender, + @Param("currentMonth") LocalDate currentMonth); @Modifying @Query("UPDATE ConsumptionGoal cg SET cg.deleted = TRUE WHERE cg.category.id = :categoryId AND cg.user.id = :userId") void softDeleteByCategoryIdAndUserId(@Param("categoryId") Long categoryId, @Param("userId") Long userId); @Query("SELECT cg FROM ConsumptionGoal cg WHERE cg.category.id = :categoryId AND cg.user.id = :userId AND cg.deleted = FALSE") - Optional findByCategoryIdAndUserId(@Param("categoryId") Long categoryId, @Param("userId") Long userId);} + Optional findByCategoryIdAndUserId(@Param("categoryId") Long categoryId, + @Param("userId") Long userId); +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceImpl.java b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceImpl.java index 4e52e77d..51183197 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceImpl.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceImpl.java @@ -1,7 +1,11 @@ package com.bbteam.budgetbuddies.domain.consumptiongoal.service; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.time.DayOfWeek; import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.Comparator; @@ -103,22 +107,23 @@ public List getAllConsumptionGoalCategories(L Long avgConsumeAmount = avgDto.getAverageAmount(); Long myConsumeAmount = myConsumptionAmountDto.getMyAmount(); + Long roundedAvgConsumeAmount = roundToNearest10(avgConsumeAmount); + long consumeAmountDifference; - if (avgConsumeAmount == 0L) { + if (roundedAvgConsumeAmount == 0L) { consumeAmountDifference = -myConsumeAmount; } else { - consumeAmountDifference = myConsumeAmount - avgConsumeAmount; + consumeAmountDifference = myConsumeAmount - roundedAvgConsumeAmount; } return AllConsumptionCategoryResponseDto.builder() .categoryName(category.getName()) - .avgAmount(avgConsumeAmount) + .avgAmount(roundedAvgConsumeAmount) .amountDifference(consumeAmountDifference) .build(); }) .collect(Collectors.toList()); - } @Override @@ -142,11 +147,17 @@ public ConsumptionAnalysisResponseDto getTopCategoryAndConsumptionAmount(Long us Long topConsumptionGoalCategoryId = avgConsumptionGoalList.get(0).getCategoryId(); + LocalDateTime startOfWeekDateTime = startOfWeek.atStartOfDay(); + LocalDateTime endOfWeekDateTime = endOfWeek.atTime(LocalTime.MAX); + Long currentWeekConsumptionAmount = consumptionGoalRepository - .findAvgConsumptionByCategoryIdAndCurrentWeek(topConsumptionGoalCategoryId, startOfWeek, endOfWeek, + .findAvgConsumptionByCategoryIdAndCurrentWeek(topConsumptionGoalCategoryId, startOfWeekDateTime, + endOfWeekDateTime, peerAgeStart, peerAgeEnd, peerGender) .orElse(0L); + currentWeekConsumptionAmount = roundToNearest10(currentWeekConsumptionAmount); + String topGoalCategory = getCategoryNameById(topConsumptionGoalCategoryId); return consumptionGoalConverter.toTopCategoryAndConsumptionAmount(topGoalCategory, @@ -199,17 +210,18 @@ public List getAllConsumptionCategories(Long Long avgConsumeAmount = avgDto.getAverageAmount(); Long myConsumeAmount = myConsumptionAmountDto.getMyAmount(); - long consumeAmountDifference; + Long roundedAvgConsumeAmount = roundToNearest10(avgConsumeAmount); - if (avgConsumeAmount == 0L) { + long consumeAmountDifference; + if (roundedAvgConsumeAmount == 0L) { consumeAmountDifference = -myConsumeAmount; } else { - consumeAmountDifference = myConsumeAmount - avgConsumeAmount; + consumeAmountDifference = myConsumeAmount - roundedAvgConsumeAmount; } return AllConsumptionCategoryResponseDto.builder() .categoryName(category.getName()) - .avgAmount(avgConsumeAmount) + .avgAmount(roundedAvgConsumeAmount) .amountDifference(consumeAmountDifference) .build(); }) @@ -347,6 +359,16 @@ private String getCategoryNameById(Long categoryId) { return category.getName(); } + private Long roundToNearest10(Long amount) { + if (amount == null) { + return 0L; + } + BigDecimal decimalAmount = BigDecimal.valueOf(amount); + BigDecimal roundedAmount = decimalAmount.divide(BigDecimal.valueOf(10), RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(10)); + return roundedAmount.longValue(); + } + @Override @Transactional public ConsumptionGoalResponseListDto updateConsumptionGoals(Long userId, 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 e7ede59f..07b42d1c 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 @@ -6,6 +6,8 @@ import java.time.DayOfWeek; import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.temporal.TemporalAdjusters; import java.util.List; import java.util.NoSuchElementException; @@ -308,6 +310,9 @@ void getTopCategoryAndConsumptionAmount_Success() { LocalDate startOfWeek = goalMonthRandomDay.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); LocalDate endOfWeek = goalMonthRandomDay.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); + LocalDateTime startOfWeekDateTime = startOfWeek.atStartOfDay(); + LocalDateTime endOfWeekDateTime = endOfWeek.atTime(LocalTime.MAX); + ConsumptionGoal topConsumptionGoal = ConsumptionGoal.builder() .goalAmount(5000L) .consumeAmount(3000L) @@ -338,7 +343,7 @@ void getTopCategoryAndConsumptionAmount_Success() { .willReturn(avgConsumptionGoalList); given(consumptionGoalRepository.findAvgConsumptionByCategoryIdAndCurrentWeek( - defaultCategory.getId(), startOfWeek, endOfWeek, + defaultCategory.getId(), startOfWeekDateTime, endOfWeekDateTime, peerAgeStart, peerAgeEnd, peerGender)) .willReturn(Optional.of(currentWeekConsumptionGoal.getConsumeAmount()));