Add UserQuizCycle and apply

This commit is contained in:
MangKyu
2021-12-20 22:18:41 +09:00
parent d5ba0a3c0f
commit c4adec5c5e
8 changed files with 172 additions and 29 deletions

View File

@@ -3,6 +3,7 @@ package com.mangkyu.employment.interview.app.user.entity;
import com.mangkyu.employment.interview.app.common.entity.BaseEntity;
import com.mangkyu.employment.interview.app.quiz.enums.QuizLevel;
import com.mangkyu.employment.interview.app.solvedquiz.entity.SolvedQuiz;
import com.mangkyu.employment.interview.app.user.enums.UserQuizCycle;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@@ -27,6 +28,10 @@ public class User extends BaseEntity {
@Enumerated(EnumType.STRING)
private QuizLevel quizLevel;
@Builder.Default
@Enumerated(EnumType.STRING)
private UserQuizCycle userQuizCycle = UserQuizCycle.REGULAR_INTERVALS;
@Builder.Default
private Integer quizSize = DEFAULT_QUIZ_SIZE;

View File

@@ -0,0 +1,16 @@
package com.mangkyu.employment.interview.app.user.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum UserQuizCycle {
DAILY("Quiz Everyday"),
REGULAR_INTERVALS("Quiz Regular Intervals"),
;
private final String desc;
}

View File

@@ -1,12 +1,13 @@
package com.mangkyu.employment.interview.app.user.repository;
import com.mangkyu.employment.interview.app.user.entity.User;
import com.mangkyu.employment.interview.app.user.enums.UserQuizCycle;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface UserRepository extends JpaRepository <User, Long> {
List<User> findAllByIsEnableTrue();
List<User> findAllByIsEnableTrueAndUserQuizCycleIs(final UserQuizCycle userQuizCycle);
}

View File

@@ -2,6 +2,7 @@ package com.mangkyu.employment.interview.app.user.service;
import com.mangkyu.employment.interview.app.user.dto.AddUserRequest;
import com.mangkyu.employment.interview.app.user.entity.User;
import com.mangkyu.employment.interview.app.user.enums.UserQuizCycle;
import com.mangkyu.employment.interview.app.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.modelmapper.ModelMapper;
@@ -30,7 +31,7 @@ public class UserService {
userRepository.save(user);
}
public List<User> getEnabledUserList() {
return userRepository.findAllByIsEnableTrue();
public List<User> getEnabledUserList(final UserQuizCycle userQuizCycle) {
return userRepository.findAllByIsEnableTrueAndUserQuizCycleIs(userQuizCycle);
}
}

View File

@@ -6,6 +6,7 @@ import com.mangkyu.employment.interview.app.quiz.entity.Quiz;
import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import com.mangkyu.employment.interview.app.solvedquiz.service.SolvedQuizService;
import com.mangkyu.employment.interview.app.user.entity.User;
import com.mangkyu.employment.interview.app.user.enums.UserQuizCycle;
import com.mangkyu.employment.interview.app.user.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -33,22 +34,35 @@ public class SendQuizCronJob {
// @Scheduled(cron = "*/30 * * * * *") // every 30 seconds
@Scheduled(cron = "0 0 01 * * 1,4") // every Monday, Thursday at 1am
@Transactional
public void sendQuizMailEveryWeek() {
final List<User> userList = userService.getEnabledUserList();
public void sendQuizMailEveryMondayAndThursday1AM() {
final List<User> userList = userService.getEnabledUserList(UserQuizCycle.REGULAR_INTERVALS);
for (final User user : userList) {
final List<Quiz> unsolvedQuizList = quizService.getUnsolvedQuizList(user.getId(), user.getQuizLevel());
final boolean isLastMail = isLastMail(unsolvedQuizList, user.getQuizSize());
final List<Quiz> randomQuizList = quizService.getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
if (isLastMail) {
userService.disableUser(user);
}
mailService.sendMail(user.getEmail(), randomQuizList, isLastMail);
solvedQuizService.addSolvedQuizList(user, randomQuizList);
sendUnsolvedQuizForUser(user);
}
}
@Scheduled(cron = "0 0 01 * * *") // everyday at 1am
@Transactional
public void sendQuizMailEveryDay1AM() {
final List<User> userList = userService.getEnabledUserList(UserQuizCycle.DAILY);
for (final User user : userList) {
sendUnsolvedQuizForUser(user);
}
}
private void sendUnsolvedQuizForUser(final User user) {
final List<Quiz> unsolvedQuizList = quizService.getUnsolvedQuizList(user.getId(), user.getQuizLevel());
final boolean isLastMail = isLastMail(unsolvedQuizList, user.getQuizSize());
final List<Quiz> randomQuizList = quizService.getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
if (isLastMail) {
userService.disableUser(user);
}
mailService.sendMail(user.getEmail(), randomQuizList, isLastMail);
solvedQuizService.addSolvedQuizList(user, randomQuizList);
}
private boolean isLastMail(final List<Quiz> quizList, final Integer quizSize) {
return quizList.size() <= quizSize;
}

View File

@@ -2,6 +2,7 @@ package com.mangkyu.employment.interview.app.user.repository;
import com.mangkyu.employment.interview.app.quiz.enums.QuizLevel;
import com.mangkyu.employment.interview.app.user.entity.User;
import com.mangkyu.employment.interview.app.user.enums.UserQuizCycle;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
@@ -16,6 +17,28 @@ class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
public void selectUserListByCycle() {
// given
final User user = User.builder()
.email("minkyu@test.com")
.quizLevel(QuizLevel.JUNIOR)
.userQuizCycle(UserQuizCycle.DAILY)
.build();
final User savedUser = userRepository.save(user);
userRepository.save(savedUser);
// when
final List<User> dailyResult = userRepository.findAllByIsEnableTrueAndUserQuizCycleIs(UserQuizCycle.DAILY);
final List<User> regularResult = userRepository.findAllByIsEnableTrueAndUserQuizCycleIs(UserQuizCycle.REGULAR_INTERVALS);
// then
assertThat(dailyResult.size()).isOne();
assertThat(regularResult.size()).isZero();
}
@Test
public void insertUser() {
// given
@@ -40,6 +63,7 @@ class UserRepositoryTest {
final User user = User.builder()
.email("minkyu@test.com")
.quizLevel(QuizLevel.JUNIOR)
.userQuizCycle(UserQuizCycle.REGULAR_INTERVALS)
.build();
final User savedUser = userRepository.save(user);
@@ -47,7 +71,7 @@ class UserRepositoryTest {
userRepository.save(savedUser);
// when
final List<User> result = userRepository.findAllByIsEnableTrue();
final List<User> result = userRepository.findAllByIsEnableTrueAndUserQuizCycleIs(UserQuizCycle.REGULAR_INTERVALS);
// then
assertThat(result.size()).isZero();

View File

@@ -3,6 +3,7 @@ package com.mangkyu.employment.interview.app.user.service;
import com.mangkyu.employment.interview.app.quiz.enums.QuizLevel;
import com.mangkyu.employment.interview.app.user.dto.AddUserRequest;
import com.mangkyu.employment.interview.app.user.entity.User;
import com.mangkyu.employment.interview.app.user.enums.UserQuizCycle;
import com.mangkyu.employment.interview.app.user.repository.UserRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -31,6 +32,8 @@ class UserServiceTest {
@Spy
private ModelMapper modelMapper;
private final UserQuizCycle userQuizCycle = UserQuizCycle.DAILY;
@BeforeEach
public void init() {
modelMapper.getConfiguration()
@@ -70,16 +73,16 @@ class UserServiceTest {
public void getEnabledUserListSuccess() {
// given
final List<User> enabledUserList = Arrays.asList(user(true), user(true));
doReturn(enabledUserList).when(userRepository).findAllByIsEnableTrue();
doReturn(enabledUserList).when(userRepository).findAllByIsEnableTrueAndUserQuizCycleIs(userQuizCycle);
// when
final List<User> result = target.getEnabledUserList();
final List<User> result = target.getEnabledUserList(userQuizCycle);
// then
assertThat(result.size()).isEqualTo(enabledUserList.size());
// verify
verify(userRepository, times(1)).findAllByIsEnableTrue();
verify(userRepository, times(1)).findAllByIsEnableTrueAndUserQuizCycleIs(userQuizCycle);
}
private User user(final boolean isEnable) {

View File

@@ -6,6 +6,7 @@ import com.mangkyu.employment.interview.app.quiz.enums.QuizLevel;
import com.mangkyu.employment.interview.app.quiz.service.QuizService;
import com.mangkyu.employment.interview.app.solvedquiz.service.SolvedQuizService;
import com.mangkyu.employment.interview.app.user.entity.User;
import com.mangkyu.employment.interview.app.user.enums.UserQuizCycle;
import com.mangkyu.employment.interview.app.user.service.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -50,34 +51,34 @@ class SendQuizCronJobTest {
}
@Test
public void sendQuizMailEveryWeekSuccess_UserNotExists() {
public void sendQuizMailDaily_UserNotExists() {
// given
doReturn(Collections.emptyList())
.when(userService)
.getEnabledUserList();
.getEnabledUserList(UserQuizCycle.DAILY);
// when
target.sendQuizMailEveryWeek();
target.sendQuizMailEveryDay1AM();
// then
// verify
verify(quizService, times(0)).getUnsolvedQuizList(user.getId(), user.getQuizLevel());
verify(quizService, times(0)).getRandomQuizListUnderLimit(anyList(), user.getQuizSize());
verify(quizService, times(0)).getRandomQuizListUnderLimit(anyList(), anyInt());
verify(userService, times(0)).disableUser(user);
verify(mailService, times(0)).sendMail(anyString(), anyList(), anyBoolean());
verify(solvedQuizService, times(0)).addSolvedQuizList(any(User.class), anyList());
}
@Test
public void sendQuizMailEveryWeekSuccess_NotLastMail() {
public void sendQuizMailDaily_NotLastMail() {
// given
final List<Quiz> unsolvedQuizList = quizList(5);
final List<Quiz> randomQuizList = unsolvedQuizList.subList(0, 3);
doReturn(userList)
.when(userService)
.getEnabledUserList();
.getEnabledUserList(UserQuizCycle.DAILY);
doReturn(unsolvedQuizList)
.when(quizService)
.getUnsolvedQuizList(user.getId(), user.getQuizLevel());
@@ -86,7 +87,7 @@ class SendQuizCronJobTest {
.getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
// when
target.sendQuizMailEveryWeek();
target.sendQuizMailEveryDay1AM();
// then
@@ -99,14 +100,14 @@ class SendQuizCronJobTest {
}
@Test
public void sendQuizMailEveryWeekSuccess_LastMail() {
public void sendQuizMailDaily_LastMail() {
// given
final List<Quiz> unsolvedQuizList = quizList(3);
final List<Quiz> randomQuizList = unsolvedQuizList.subList(0, 3);
doReturn(userList)
.when(userService)
.getEnabledUserList();
.getEnabledUserList(UserQuizCycle.DAILY);
doReturn(unsolvedQuizList)
.when(quizService)
.getUnsolvedQuizList(user.getId(), user.getQuizLevel());
@@ -115,7 +116,85 @@ class SendQuizCronJobTest {
.getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
// when
target.sendQuizMailEveryWeek();
target.sendQuizMailEveryDay1AM();
// then
// verify
verify(quizService, times(1)).getUnsolvedQuizList(user.getId(), user.getQuizLevel());
verify(quizService, times(1)).getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
verify(userService, times(1)).disableUser(user);
verify(mailService, times(1)).sendMail(user.getEmail(), randomQuizList, true);
verify(solvedQuizService, times(1)).addSolvedQuizList(user, randomQuizList);
}
@Test
public void sendQuizMailRegulary_UserNotExists() {
// given
doReturn(Collections.emptyList())
.when(userService)
.getEnabledUserList(UserQuizCycle.REGULAR_INTERVALS);
// when
target.sendQuizMailEveryMondayAndThursday1AM();
// then
// verify
verify(quizService, times(0)).getUnsolvedQuizList(user.getId(), user.getQuizLevel());
verify(quizService, times(0)).getRandomQuizListUnderLimit(anyList(), anyInt());
verify(userService, times(0)).disableUser(user);
verify(mailService, times(0)).sendMail(anyString(), anyList(), anyBoolean());
verify(solvedQuizService, times(0)).addSolvedQuizList(any(User.class), anyList());
}
@Test
public void sendQuizMailRegulary_NotLastMail() {
// given
final List<Quiz> unsolvedQuizList = quizList(5);
final List<Quiz> randomQuizList = unsolvedQuizList.subList(0, 3);
doReturn(userList)
.when(userService)
.getEnabledUserList(UserQuizCycle.REGULAR_INTERVALS);
doReturn(unsolvedQuizList)
.when(quizService)
.getUnsolvedQuizList(user.getId(), user.getQuizLevel());
doReturn(randomQuizList)
.when(quizService)
.getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
// when
target.sendQuizMailEveryMondayAndThursday1AM();
// then
// verify
verify(quizService, times(1)).getUnsolvedQuizList(user.getId(), user.getQuizLevel());
verify(quizService, times(1)).getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
verify(userService, times(0)).disableUser(user);
verify(mailService, times(1)).sendMail(user.getEmail(), randomQuizList, false);
verify(solvedQuizService, times(1)).addSolvedQuizList(user, randomQuizList);
}
@Test
public void sendQuizMailRegulary_LastMail() {
// given
final List<Quiz> unsolvedQuizList = quizList(3);
final List<Quiz> randomQuizList = unsolvedQuizList.subList(0, 3);
doReturn(userList)
.when(userService)
.getEnabledUserList(UserQuizCycle.REGULAR_INTERVALS);
doReturn(unsolvedQuizList)
.when(quizService)
.getUnsolvedQuizList(user.getId(), user.getQuizLevel());
doReturn(randomQuizList)
.when(quizService)
.getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
// when
target.sendQuizMailEveryMondayAndThursday1AM();
// then