Add DayOfWeek on user

This commit is contained in:
MangKyu
2021-12-24 20:55:46 +09:00
parent 1ff3e9a54b
commit 625b222a71
10 changed files with 91 additions and 142 deletions

View File

@@ -1,7 +1,6 @@
package com.mangkyu.employment.interview.app.user.dto;
import com.mangkyu.employment.interview.app.quiz.enums.QuizLevel;
import com.mangkyu.employment.interview.app.user.enums.UserQuizCycle;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@@ -10,7 +9,10 @@ import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.DayOfWeek;
import java.util.Set;
import static com.mangkyu.employment.interview.app.quiz.constants.QuizConstants.*;
@@ -30,6 +32,6 @@ public class AddUserRequest {
@Range(min = MINIMUM_QUIZ_SIZE, max = MAXIMUM_QUIZ_SIZE)
private final Integer quizSize = DEFAULT_QUIZ_SIZE;
@NotNull
private final UserQuizCycle userQuizCycle;
@NotEmpty
private final Set<DayOfWeek> quizDaySet;
}

View File

@@ -3,15 +3,16 @@ 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;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.DayOfWeek;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static com.mangkyu.employment.interview.app.quiz.constants.QuizConstants.DEFAULT_QUIZ_SIZE;
@@ -29,9 +30,10 @@ public class User extends BaseEntity {
@Enumerated(EnumType.STRING)
private QuizLevel quizLevel;
@Builder.Default
@ElementCollection(targetClass = DayOfWeek.class)
@CollectionTable
@Enumerated(EnumType.STRING)
private UserQuizCycle userQuizCycle = UserQuizCycle.REGULAR_INTERVALS;
private Set<DayOfWeek> quizDaySet;
@Builder.Default
private Integer quizSize = DEFAULT_QUIZ_SIZE;

View File

@@ -1,16 +0,0 @@
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,13 +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.time.DayOfWeek;
import java.util.List;
public interface UserRepository extends JpaRepository <User, Long> {
List<User> findAllByIsEnableTrueAndUserQuizCycleIs(final UserQuizCycle userQuizCycle);
List<User> findAllByIsEnableTrueAndQuizDaySetIs(final DayOfWeek dayOfWeek);
}

View File

@@ -2,13 +2,13 @@ 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;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.DayOfWeek;
import java.util.List;
@Service
@@ -31,7 +31,7 @@ public class UserService {
userRepository.save(user);
}
public List<User> getEnabledUserList(final UserQuizCycle userQuizCycle) {
return userRepository.findAllByIsEnableTrueAndUserQuizCycleIs(userQuizCycle);
public List<User> getEnabledUserList(final DayOfWeek dayOfWeek) {
return userRepository.findAllByIsEnableTrueAndQuizDaySetIs(dayOfWeek);
}
}

View File

@@ -1,12 +1,10 @@
package com.mangkyu.employment.interview.cron;
import com.mangkyu.employment.interview.app.mail.service.MailService;
import com.mangkyu.employment.interview.app.quiz.constants.QuizConstants;
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;
@@ -14,6 +12,7 @@ import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
@Component
@@ -31,20 +30,10 @@ public class SendQuizCronJob {
* https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/support/CronExpression.html
*/
// @Scheduled(cron = "*/30 * * * * *") // every 30 seconds
@Scheduled(cron = "0 0 01 * * 1,4") // every Monday, Thursday at 1am
@Scheduled(cron = "0 0 1 * * ?")
@Transactional
public void sendQuizMailEveryMondayAndThursday1AM() {
final List<User> userList = userService.getEnabledUserList(UserQuizCycle.REGULAR_INTERVALS);
for (final User user : userList) {
sendUnsolvedQuizForUser(user);
}
}
@Scheduled(cron = "0 0 01 * * *") // everyday at 1am
@Transactional
public void sendQuizMailEveryDay1AM() {
final List<User> userList = userService.getEnabledUserList(UserQuizCycle.DAILY);
public void sendQuizMail() {
final List<User> userList = userService.getEnabledUserList(LocalDate.now().getDayOfWeek());
for (final User user : userList) {
sendUnsolvedQuizForUser(user);
}

View File

@@ -3,7 +3,6 @@ package com.mangkyu.employment.interview.app.user.controller;
import com.google.gson.Gson;
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.enums.UserQuizCycle;
import com.mangkyu.employment.interview.app.user.service.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -17,6 +16,10 @@ import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.time.DayOfWeek;
import java.util.HashSet;
import java.util.Set;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ExtendWith(MockitoExtension.class)
@@ -94,12 +97,37 @@ class UserControllerTest {
}
@Test
public void addUserSuccess() throws Exception {
public void addUserFail_QuizDaySetIsEmpty() throws Exception {
// given
final AddUserRequest addUserRequest = AddUserRequest.builder()
.email("whalsrb1226@gmail.com")
.quizLevel(QuizLevel.NEW)
.build();
// when
final ResultActions result = mockMvc.perform(
MockMvcRequestBuilders.post("/user")
.content(new Gson().toJson(addUserRequest))
.contentType(MediaType.APPLICATION_JSON)
);
// then
result.andExpect(status().isBadRequest());
}
@Test
public void addUserSuccess() throws Exception {
// given
final Set<DayOfWeek> quizDaySet = new HashSet<>();
quizDaySet.add(DayOfWeek.MONDAY);
quizDaySet.add(DayOfWeek.WEDNESDAY);
quizDaySet.add(DayOfWeek.FRIDAY);
final AddUserRequest addUserRequest = AddUserRequest.builder()
.email("whalsrb1226@gmail.com")
.quizLevel(QuizLevel.JUNIOR)
.userQuizCycle(UserQuizCycle.DAILY)
.quizDaySet(quizDaySet)
.build();
// when

View File

@@ -2,12 +2,12 @@ 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;
import java.util.List;
import java.time.DayOfWeek;
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat;
@@ -21,18 +21,24 @@ class UserRepositoryTest {
@Test
public void selectUserListByCycle() {
// given
final Set<DayOfWeek> quizDaySet = new HashSet<>();
quizDaySet.add(DayOfWeek.MONDAY);
quizDaySet.add(DayOfWeek.WEDNESDAY);
quizDaySet.add(DayOfWeek.FRIDAY);
final User user = User.builder()
.email("minkyu@test.com")
.quizLevel(QuizLevel.JUNIOR)
.userQuizCycle(UserQuizCycle.DAILY)
.quizSize(5)
.quizDaySet(quizDaySet)
.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);
final List<User> dailyResult = userRepository.findAllByIsEnableTrueAndQuizDaySetIs(DayOfWeek.MONDAY);
final List<User> regularResult = userRepository.findAllByIsEnableTrueAndQuizDaySetIs(DayOfWeek.THURSDAY);
// then
assertThat(dailyResult.size()).isOne();
@@ -60,10 +66,15 @@ class UserRepositoryTest {
@Test
public void updateUserDisabled() {
// given
final Set<DayOfWeek> quizDaySet = new HashSet<>();
quizDaySet.add(DayOfWeek.MONDAY);
quizDaySet.add(DayOfWeek.WEDNESDAY);
quizDaySet.add(DayOfWeek.FRIDAY);
final User user = User.builder()
.email("minkyu@test.com")
.quizLevel(QuizLevel.JUNIOR)
.userQuizCycle(UserQuizCycle.REGULAR_INTERVALS)
.quizDaySet(quizDaySet)
.build();
final User savedUser = userRepository.save(user);
@@ -71,7 +82,7 @@ class UserRepositoryTest {
userRepository.save(savedUser);
// when
final List<User> result = userRepository.findAllByIsEnableTrueAndUserQuizCycleIs(UserQuizCycle.REGULAR_INTERVALS);
final List<User> result = userRepository.findAllByIsEnableTrueAndQuizDaySetIs(DayOfWeek.MONDAY);
// then
assertThat(result.size()).isZero();

View File

@@ -3,7 +3,6 @@ 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;
@@ -15,8 +14,11 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.modelmapper.ModelMapper;
import org.modelmapper.config.Configuration;
import java.time.DayOfWeek;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
@@ -32,7 +34,7 @@ class UserServiceTest {
@Spy
private ModelMapper modelMapper;
private final UserQuizCycle userQuizCycle = UserQuizCycle.DAILY;
private final DayOfWeek dayOfWeek = DayOfWeek.MONDAY;
@BeforeEach
public void init() {
@@ -44,9 +46,15 @@ class UserServiceTest {
@Test
public void addUserSuccess() {
// given
final Set<DayOfWeek> quizDaySet = new HashSet<>();
quizDaySet.add(DayOfWeek.MONDAY);
quizDaySet.add(DayOfWeek.WEDNESDAY);
quizDaySet.add(DayOfWeek.SATURDAY);
final AddUserRequest addUserRequest = AddUserRequest.builder()
.email("whalsrb1226@gmail.com")
.quizLevel(QuizLevel.JUNIOR)
.quizDaySet(quizDaySet)
.build();
// when
@@ -73,16 +81,16 @@ class UserServiceTest {
public void getEnabledUserListSuccess() {
// given
final List<User> enabledUserList = Arrays.asList(user(true), user(true));
doReturn(enabledUserList).when(userRepository).findAllByIsEnableTrueAndUserQuizCycleIs(userQuizCycle);
doReturn(enabledUserList).when(userRepository).findAllByIsEnableTrueAndQuizDaySetIs(dayOfWeek);
// when
final List<User> result = target.getEnabledUserList(userQuizCycle);
final List<User> result = target.getEnabledUserList(dayOfWeek);
// then
assertThat(result.size()).isEqualTo(enabledUserList.size());
// verify
verify(userRepository, times(1)).findAllByIsEnableTrueAndUserQuizCycleIs(userQuizCycle);
verify(userRepository, times(1)).findAllByIsEnableTrueAndQuizDaySetIs(dayOfWeek);
}
private User user(final boolean isEnable) {

View File

@@ -6,7 +6,6 @@ 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;
@@ -15,6 +14,8 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -38,6 +39,7 @@ class SendQuizCronJobTest {
private User user;
private List<User> userList;
private DayOfWeek dayOfWeek;
@BeforeEach
public void init() {
@@ -48,6 +50,7 @@ class SendQuizCronJobTest {
.build();
userList = Collections.singletonList(user);
dayOfWeek = LocalDate.now().getDayOfWeek();
}
@Test
@@ -55,10 +58,10 @@ class SendQuizCronJobTest {
// given
doReturn(Collections.emptyList())
.when(userService)
.getEnabledUserList(UserQuizCycle.DAILY);
.getEnabledUserList(dayOfWeek);
// when
target.sendQuizMailEveryDay1AM();
target.sendQuizMail();
// then
@@ -78,7 +81,7 @@ class SendQuizCronJobTest {
doReturn(userList)
.when(userService)
.getEnabledUserList(UserQuizCycle.DAILY);
.getEnabledUserList(dayOfWeek);
doReturn(unsolvedQuizList)
.when(quizService)
.getUnsolvedQuizList(user.getId(), user.getQuizLevel());
@@ -87,7 +90,7 @@ class SendQuizCronJobTest {
.getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
// when
target.sendQuizMailEveryDay1AM();
target.sendQuizMail();
// then
@@ -107,7 +110,7 @@ class SendQuizCronJobTest {
doReturn(userList)
.when(userService)
.getEnabledUserList(UserQuizCycle.DAILY);
.getEnabledUserList(dayOfWeek);
doReturn(unsolvedQuizList)
.when(quizService)
.getUnsolvedQuizList(user.getId(), user.getQuizLevel());
@@ -116,85 +119,7 @@ class SendQuizCronJobTest {
.getRandomQuizListUnderLimit(unsolvedQuizList, user.getQuizSize());
// when
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();
target.sendQuizMail();
// then