Skip to content

Commit

Permalink
[NAYB-109] refactor: 회원의 등급 업데이트 로직 리팩토링
Browse files Browse the repository at this point in the history
[NAYB-109] refactor: 회원의 등급 업데이트 로직 리팩토링
  • Loading branch information
hseong3243 authored Sep 19, 2023
2 parents f8914bd + 968f244 commit f5db0b7
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -18,12 +17,10 @@ public interface UserRepository extends JpaRepository<User, Long> {

@Query("select o.user.userId as userId, count(o) as orderCount from Order o"
+ " where o.createdAt between :start and :end"
+ " group by o.user.userId"
+ " order by o.user.userId asc")
+ " group by o.user.userId")
List<UserOrderCount> getUserOrderCount(
@Param("start") LocalDateTime start,
@Param("end") LocalDateTime end,
Pageable pageable);
@Param("end") LocalDateTime end);

@Modifying
@Query("update User u set u.userGrade = :userGrade"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.prgrms.nabmart.domain.user.scheduler;

import com.prgrms.nabmart.domain.user.service.GradeService;
import lombok.RequiredArgsConstructor;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
@EnableSchedulerLock(defaultLockAtMostFor = "PT60S")
public class GradeScheduler {

private final GradeService gradeService;

@Async
@Scheduled(cron = "0 0 5 1 * *")
@SchedulerLock(name = "Update_User_Grade", lockAtLeastFor = "PT10S")
public void updateUserGradeScheduler() {
gradeService.updateUserGrade();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,35 @@
import com.prgrms.nabmart.domain.user.UserGrade;
import com.prgrms.nabmart.domain.user.repository.UserRepository;
import com.prgrms.nabmart.domain.user.repository.response.UserOrderCount;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
@EnableSchedulerLock(defaultLockAtMostFor = "PT60S")
public class GradeService {

private static final int ONE = 1;
private static final int PAGE_SIZE = 1000;

private final UserRepository userRepository;
private final EntityManager entityManager;

@Async
@Scheduled(cron = "0 0 5 1 * *")
@SchedulerLock(name = "Update_User_Grade", lockAtLeastFor = "PT10S")
@Transactional
public void updateUserGrade() {
long totalUserCount = userRepository.count();
long totalPage = totalUserCount / PAGE_SIZE;
LocalDateTime startTimeOfPreviousMonth = getStartTimeOfPreviousMonth();
LocalDateTime lastTimeOfPreviousMonth = getEndTimeOfPreviousMonth();

for (int page = 0; page <= totalPage; page++) {
PageRequest pageRequest = PageRequest.of(page, PAGE_SIZE);
List<UserOrderCount> userOrderCounts = userRepository.getUserOrderCount(
startTimeOfPreviousMonth,
lastTimeOfPreviousMonth,
pageRequest);
Map<UserGrade, List<UserOrderCount>> userGradeGroup = groupByUserGrade(userOrderCounts);
userGradeGroup.forEach(((userGrade, userOrderCountGroup) ->
userRepository.updateUserGrade(userGrade, extractUserIds(userOrderCountGroup))));

entityManager.clear();
}
List<UserOrderCount> userOrderCounts = userRepository.getUserOrderCount(
startTimeOfPreviousMonth,
lastTimeOfPreviousMonth);
Map<UserGrade, List<UserOrderCount>> userGradeGroup = groupByUserGrade(userOrderCounts);
userGradeGroup.forEach(((userGrade, userOrderCountGroup) ->
userRepository.updateUserGrade(userGrade, extractUserIds(userOrderCountGroup))));
}

private LocalDateTime getStartTimeOfPreviousMonth() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.context.annotation.Import;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

@DataJpaTest
@Import({JpaAuditingConfig.class, TestQueryDslConfig.class})
Expand Down Expand Up @@ -77,7 +75,6 @@ private Order createOrder(User user) {
@DisplayName("getUserOrderCount 메서드 실행 시")
class GetUserOrderCountTest {

Pageable pageable = PageRequest.of(0, 5);
LocalDateTime now = LocalDateTime.now();
LocalDateTime start = now.minusDays(1);
LocalDateTime end = now.plusDays(1);
Expand All @@ -91,7 +88,7 @@ void successWhenOneUserWithFiveOrder() {

//when
List<UserOrderCount> userOrderCounts
= userRepository.getUserOrderCount(start, end, pageable);
= userRepository.getUserOrderCount(start, end);

//then
assertThat(userOrderCounts).hasSize(1);
Expand All @@ -109,7 +106,7 @@ void successWhenTwoUserWithTenAndFiveOrder() {

//when
List<UserOrderCount> userOrderCounts
= userRepository.getUserOrderCount(start, end, pageable);
= userRepository.getUserOrderCount(start, end);

//then
assertThat(userOrderCounts).hasSize(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import static org.mockito.Mockito.times;

import com.prgrms.nabmart.domain.user.User;
import com.prgrms.nabmart.domain.user.repository.response.UserOrderCount;
import com.prgrms.nabmart.domain.user.repository.UserRepository;
import com.prgrms.nabmart.domain.user.repository.response.UserOrderCount;
import com.prgrms.nabmart.domain.user.support.UserFixture;
import jakarta.persistence.EntityManager;
import java.util.ArrayList;
Expand All @@ -19,7 +19,6 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.PageImpl;
import org.springframework.test.util.ReflectionTestUtils;

@ExtendWith(MockitoExtension.class)
Expand Down Expand Up @@ -77,12 +76,11 @@ void success() {
UserOrderCount vipCount = createUserOrderCount(users.get(1).getUserId(), 5);
UserOrderCount vvipCount = createUserOrderCount(users.get(2).getUserId(), 10);
UserOrderCount rvipCount = createUserOrderCount(users.get(3).getUserId(), 20);
List<UserOrderCount> userOrderCounters = List.of(normalCount, vipCount, vvipCount,
rvipCount);

PageImpl<UserOrderCount> givenResult = new PageImpl<>(
List.of(normalCount, vipCount, vvipCount, rvipCount));
given(userRepository.count()).willReturn(4L);
given(userRepository.getUserOrderCount(any(), any(), any())).willReturn(
givenResult.getContent());
given(userRepository.getUserOrderCount(any(), any())).willReturn(
userOrderCounters);

//when
gradeService.updateUserGrade();
Expand Down

0 comments on commit f5db0b7

Please sign in to comment.