Skip to content

Commit

Permalink
feat : 내 풀이 목록 기간 별 api 분리 (#216)
Browse files Browse the repository at this point in the history
* feat : 그룹 내 나의 풀이 목록 조회 시, 문제 진행 상태에 따른 api 분리

* test : 그룹 내 나의 풀이 목록 조회 시, 문제 진행 상태에 따른 api 분리 테스트 수정

* feat : 나의 풀이 목록 조회 시, 문제 진행 상태에 따른 api 분리

* test : 나의 풀이 목록 조회 시, 문제 진행 상태에 따른 api 분리 테스트 수정

* refactor : 불필요한 dto 제거
  • Loading branch information
rladmstn authored Nov 26, 2024
1 parent bcf5999 commit 67945ec
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -16,9 +17,8 @@
import com.gamzabat.algohub.common.annotation.AuthedUser;
import com.gamzabat.algohub.exception.RequestException;
import com.gamzabat.algohub.feature.solution.dto.CreateSolutionRequest;
import com.gamzabat.algohub.feature.solution.dto.GetMySolutionListResponse;
import com.gamzabat.algohub.feature.solution.dto.GetMySolutionListWithGroupIdResponse;
import com.gamzabat.algohub.feature.solution.dto.GetSolutionResponse;
import com.gamzabat.algohub.feature.solution.dto.GetSolutionWithGroupIdResponse;
import com.gamzabat.algohub.feature.solution.service.SolutionService;
import com.gamzabat.algohub.feature.user.domain.User;

Expand Down Expand Up @@ -66,31 +66,60 @@ public ResponseEntity<Void> createSolution(@Valid @RequestBody CreateSolutionReq
return ResponseEntity.ok().build();
}

@GetMapping("/groups/{groupId}/my-solutions")
@Operation(summary = "그룹 내 나의 풀이 전체 조회 API", description = "특정 그룹 내에서 제출한 나의 풀이를 모두 조회하는 API")
public ResponseEntity<GetMySolutionListResponse> getMySolutionsInGroup(@AuthedUser User user,
@GetMapping("/groups/{groupId}/my-solutions/in-progress")
@Operation(summary = "그룹 내 진행 중인 나의 풀이 전체 조회 API", description = "특정 그룹 내에서 진행 중인 문제에 대해 제출한 나의 풀이 모두 조회하는 API")
public ResponseEntity<Page<GetSolutionResponse>> getMySolutionsInGroupInProgress(@AuthedUser User user,
@PathVariable Long groupId,
@RequestParam(required = false) Integer problemNumber,
@RequestParam(required = false) String language,
@RequestParam(required = false) String result,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
Pageable pageable = PageRequest.of(page, size);
GetMySolutionListResponse response = solutionService.getMySolutionsInGroup(user,
Page<GetSolutionResponse> response = solutionService.getMySolutionsInGroupInProgress(user,
groupId, problemNumber, language, result, pageable);
return ResponseEntity.ok().body(response);
}

@GetMapping("/users/my-solutions")
@Operation(summary = "내 풀이 전체 조회 API", description = "그룹 상관 없이 나의 풀이 전체를 조회하는 API")
public ResponseEntity<GetMySolutionListWithGroupIdResponse> getMySolutions(@AuthedUser User user,
@GetMapping("/groups/{groupId}/my-solutions/expired")
@Operation(summary = "그룹 내 마감된 나의 풀이 전체 조회 API", description = "특정 그룹 내에서 마감한 문제에 대해 제출한 나의 풀이를 모두 조회하는 API")
public ResponseEntity<Page<GetSolutionResponse>> getMySolutionsInGroupExpired(@AuthedUser User user,
@PathVariable Long groupId,
@RequestParam(required = false) Integer problemNumber,
@RequestParam(required = false) String language,
@RequestParam(required = false) String result,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
Pageable pageable = PageRequest.of(page, size);
Page<GetSolutionResponse> response = solutionService.getMySolutionsInGroupExpired(user,
groupId, problemNumber, language, result, pageable);
return ResponseEntity.ok().body(response);
}

@GetMapping("/users/my-solutions/in-progress")
@Operation(summary = "진행 중인 내 풀이 전체 조회 API", description = "그룹 상관 없이 진행 중인 문제에 대한 나의 풀이 전체를 조회하는 API")
public ResponseEntity<Page<GetSolutionWithGroupIdResponse>> getMySolutionsInProgress(@AuthedUser User user,
@RequestParam(required = false) Integer problemNumber,
@RequestParam(required = false) String language,
@RequestParam(required = false) String result,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
Pageable pageable = PageRequest.of(page, size);
GetMySolutionListWithGroupIdResponse response = solutionService.getMySolutions(user,
Page<GetSolutionWithGroupIdResponse> response = solutionService.getMySolutionsInProgress(user,
problemNumber, language, result, pageable);
return ResponseEntity.ok().body(response);
}

@GetMapping("/users/my-solutions/expired")
@Operation(summary = "마감 된 내 풀이 전체 조회 API", description = "그룹 상관 없이 나의 풀이 전체를 조회하는 API")
public ResponseEntity<Page<GetSolutionWithGroupIdResponse>> getMySolutions(@AuthedUser User user,
@RequestParam(required = false) Integer problemNumber,
@RequestParam(required = false) String language,
@RequestParam(required = false) String result,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
Page<GetSolutionWithGroupIdResponse> response = solutionService.getMySolutionsExpired(user,
problemNumber, language, result, pageable);
return ResponseEntity.ok().body(response);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gamzabat.algohub.constants.BOJResultConstants;
import com.gamzabat.algohub.exception.ProblemValidationException;
Expand All @@ -29,8 +30,6 @@
import com.gamzabat.algohub.feature.problem.repository.ProblemRepository;
import com.gamzabat.algohub.feature.solution.domain.Solution;
import com.gamzabat.algohub.feature.solution.dto.CreateSolutionRequest;
import com.gamzabat.algohub.feature.solution.dto.GetMySolutionListResponse;
import com.gamzabat.algohub.feature.solution.dto.GetMySolutionListWithGroupIdResponse;
import com.gamzabat.algohub.feature.solution.dto.GetSolutionResponse;
import com.gamzabat.algohub.feature.solution.dto.GetSolutionWithGroupIdResponse;
import com.gamzabat.algohub.feature.solution.enums.ProgressCategory;
Expand All @@ -40,13 +39,11 @@
import com.gamzabat.algohub.feature.user.domain.User;
import com.gamzabat.algohub.feature.user.repository.UserRepository;

import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class SolutionService {
private final SolutionRepository solutionRepository;
Expand All @@ -59,6 +56,7 @@ public class SolutionService {
private final RankingService rankingService;
private final RankingUpdateService rankingUpdateService;

@Transactional(readOnly = true)
public Page<GetSolutionResponse> getSolutionList(User user, Long problemId, String nickname,
String language, String result, Pageable pageable) {
Problem problem = problemRepository.findById(problemId)
Expand All @@ -77,6 +75,7 @@ public Page<GetSolutionResponse> getSolutionList(User user, Long problemId, Stri
return solutions.map(this::getGetSolutionResponse);
}

@Transactional(readOnly = true)
public GetSolutionResponse getSolution(User user, Long solutionId) {
Solution solution = solutionRepository.findById(solutionId)
.orElseThrow(() -> new CannotFoundSolutionException("존재하지 않는 풀이 입니다."));
Expand All @@ -90,7 +89,8 @@ public GetSolutionResponse getSolution(User user, Long solutionId) {
}
}

public GetMySolutionListResponse getMySolutionsInGroup(User user, Long groupId, Integer problemNumber,
@Transactional(readOnly = true)
public Page<GetSolutionResponse> getMySolutionsInGroupInProgress(User user, Long groupId, Integer problemNumber,
String language,
String result, Pageable pageable) {
StudyGroup group = studyGroupRepository.findById(groupId)
Expand All @@ -100,29 +100,53 @@ public GetMySolutionListResponse getMySolutionsInGroup(User user, Long groupId,
}

Page<GetSolutionResponse> inProgressSolutions = solutionRepository.findAllFilteredMySolutionsInGroup(user,
group,
problemNumber,
language,
result, ProgressCategory.IN_PROGRESS, pageable).map(this::getGetSolutionResponse);
group, problemNumber, language, result, ProgressCategory.IN_PROGRESS, pageable)
.map(this::getGetSolutionResponse);

log.info("success to get my in-progress solutions in group {}", groupId);
return inProgressSolutions;
}

@Transactional(readOnly = true)
public Page<GetSolutionResponse> getMySolutionsInGroupExpired(User user, Long groupId, Integer problemNumber,
String language,
String result, Pageable pageable) {
StudyGroup group = studyGroupRepository.findById(groupId)
.orElseThrow(() -> new CannotFoundGroupException("존재하지 않는 그룹입니다."));
if (!groupMemberRepository.existsByUserAndStudyGroup(user, group)) {
throw new GroupMemberValidationException(HttpStatus.FORBIDDEN.value(), "참여하지 않은 그룹입니다.");
}

Page<GetSolutionResponse> expiredSolutions = solutionRepository.findAllFilteredMySolutionsInGroup(user, group,
problemNumber, language, result, ProgressCategory.EXPIRED, pageable).map(this::getGetSolutionResponse);

log.info("success to get my solutions in group {}", groupId);
return new GetMySolutionListResponse(inProgressSolutions, expiredSolutions);
log.info("success to get my expired solutions in group {}", groupId);
return expiredSolutions;
}

public GetMySolutionListWithGroupIdResponse getMySolutions(User user, Integer problemNumber, String language,
@Transactional(readOnly = true)
public Page<GetSolutionWithGroupIdResponse> getMySolutionsInProgress(User user, Integer problemNumber,
String language,
String result,
Pageable pageable) {
Page<GetSolutionWithGroupIdResponse> inProgressSolutions = solutionRepository.findAllFilteredMySolutions(user,
problemNumber,
language,
result, ProgressCategory.IN_PROGRESS, pageable).map(this::getGetSolutionWithGroupIdResponse);
log.info("success to get my in-progress solutions.");
return inProgressSolutions;
}

@Transactional(readOnly = true)
public Page<GetSolutionWithGroupIdResponse> getMySolutionsExpired(User user, Integer problemNumber, String language,
String result,
Pageable pageable) {
Page<GetSolutionWithGroupIdResponse> expiredSolutions = solutionRepository.findAllFilteredMySolutions(user,
problemNumber,
language,
result, ProgressCategory.EXPIRED, pageable).map(this::getGetSolutionWithGroupIdResponse);
return new GetMySolutionListWithGroupIdResponse(inProgressSolutions, expiredSolutions);
log.info("success to get my expired solutions.");
return expiredSolutions;
}

private GetSolutionWithGroupIdResponse getGetSolutionWithGroupIdResponse(Solution solution) {
Expand Down Expand Up @@ -150,6 +174,7 @@ private Integer getCorrectCount(Solution solution) {
BOJResultConstants.CORRECT);
}

@Transactional
public void createSolution(CreateSolutionRequest request) {

List<Problem> problems = problemRepository.findAllByNumber(request.problemNumber());
Expand Down
91 changes: 61 additions & 30 deletions src/test/java/com/gamzabat/algohub/service/SolutionServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@
import com.gamzabat.algohub.feature.problem.repository.ProblemRepository;
import com.gamzabat.algohub.feature.solution.domain.Solution;
import com.gamzabat.algohub.feature.solution.dto.CreateSolutionRequest;
import com.gamzabat.algohub.feature.solution.dto.GetMySolutionListResponse;
import com.gamzabat.algohub.feature.solution.dto.GetMySolutionListWithGroupIdResponse;
import com.gamzabat.algohub.feature.solution.dto.GetSolutionResponse;
import com.gamzabat.algohub.feature.solution.dto.GetSolutionWithGroupIdResponse;
import com.gamzabat.algohub.feature.solution.enums.ProgressCategory;
import com.gamzabat.algohub.feature.solution.exception.CannotFoundSolutionException;
import com.gamzabat.algohub.feature.solution.repository.SolutionCommentRepository;
Expand Down Expand Up @@ -473,12 +472,11 @@ void createSolution() {
}

@Test
@DisplayName("그룹 내 나의 풀이 전체 조회 성공 : 문제 필터링")
void getMySolutionsInGroup() {
@DisplayName("그룹 내 진행 중인 나의 풀이 전체 조회 성공 : 문제 필터링")
void getMySolutionsInGroupInProgress() {
// given
Pageable pageable = PageRequest.of(0, 10);
List<Solution> inProgress = new ArrayList<>();
List<Solution> expired = new ArrayList<>();
LocalDateTime fixedDateTime = LocalDateTime.now();

for (int i = 0; i < 5; i++) {
Expand All @@ -491,6 +489,31 @@ void getMySolutionsInGroup() {
.solvedDateTime(fixedDateTime)
.build());
}

Page<Solution> inProgressPages = new PageImpl<>(inProgress, pageable, 10);
when(studyGroupRepository.findById(groupId)).thenReturn(Optional.ofNullable(group));
when(groupMemberRepository.existsByUserAndStudyGroup(user, group)).thenReturn(true);
when(solutionRepository.findAllFilteredMySolutionsInGroup(user, group, problemNumber, null, null,
ProgressCategory.IN_PROGRESS,
pageable)).thenReturn(inProgressPages);
// when
Page<GetSolutionResponse> responses = solutionService.getMySolutionsInGroupInProgress(user, groupId,
problemNumber, null,
null, pageable);
// then
for (int i = 0; i < 5; i++) {
assertThat(responses.getContent().get(i).getNickname()).isEqualTo("nickname1");
assertThat(responses.getContent().get(i).getProblemLevel()).isEqualTo(problem.getLevel());
}
}

@Test
@DisplayName("그룹 내 마감된 나의 풀이 전체 조회 성공 : 문제 필터링")
void getMySolutionsInGroupExpired() {
// given
Pageable pageable = PageRequest.of(0, 10);
List<Solution> expired = new ArrayList<>();
LocalDateTime fixedDateTime = LocalDateTime.now();
for (int i = 0; i < 5; i++) {
expired.add(Solution.builder()
.problem(problem1)
Expand All @@ -502,37 +525,29 @@ void getMySolutionsInGroup() {
.build());
}

Page<Solution> inProgressPages = new PageImpl<>(inProgress, pageable, 10);
Page<Solution> expiredPages = new PageImpl<>(expired, pageable, 10);
when(studyGroupRepository.findById(groupId)).thenReturn(Optional.ofNullable(group));
when(groupMemberRepository.existsByUserAndStudyGroup(user, group)).thenReturn(true);
when(solutionRepository.findAllFilteredMySolutionsInGroup(user, group, problemNumber, null, null,
ProgressCategory.IN_PROGRESS,
pageable)).thenReturn(inProgressPages);
when(solutionRepository.findAllFilteredMySolutionsInGroup(user, group, problemNumber, null, null,
ProgressCategory.EXPIRED,
pageable)).thenReturn(expiredPages);
// when
GetMySolutionListResponse responses = solutionService.getMySolutionsInGroup(user, groupId, problemNumber, null,
Page<GetSolutionResponse> responses = solutionService.getMySolutionsInGroupExpired(user, groupId,
problemNumber, null,
null, pageable);
// then
for (int i = 0; i < 5; i++) {
assertThat(responses.inProgress().getContent().get(i).getNickname()).isEqualTo("nickname1");
assertThat(responses.inProgress().getContent().get(i).getProblemLevel()).isEqualTo(problem.getLevel());
}
for (int i = 0; i < 5; i++) {
assertThat(responses.expired().getContent().get(i).getNickname()).isEqualTo("nickname1");
assertThat(responses.expired().getContent().get(i).getProblemLevel()).isEqualTo(problem1.getLevel());
assertThat(responses.getContent().get(i).getNickname()).isEqualTo("nickname1");
assertThat(responses.getContent().get(i).getProblemLevel()).isEqualTo(problem1.getLevel());
}
}

@Test
@DisplayName("나의 풀이 전체 조회 성공")
void getMySolutions() {
@DisplayName("진행 중인 나의 풀이 전체 조회 성공")
void getMySolutionsInProgress() {
// given
Pageable pageable = PageRequest.of(0, 10);
List<Solution> inProgress = new ArrayList<>();
List<Solution> expired = new ArrayList<>();
LocalDateTime fixedDateTime = LocalDateTime.now();

for (int i = 0; i < 5; i++) {
Expand All @@ -545,6 +560,30 @@ void getMySolutions() {
.solvedDateTime(fixedDateTime)
.build());
}

Page<Solution> inProgressPages = new PageImpl<>(inProgress, pageable, 10);

when(solutionRepository.findAllFilteredMySolutions(user, null, null, null,
ProgressCategory.IN_PROGRESS, pageable)).thenReturn(inProgressPages);
// when
Page<GetSolutionWithGroupIdResponse> responses = solutionService.getMySolutionsInProgress(user, null, null,
null, pageable);
// then
for (int i = 0; i < 5; i++) {
assertThat(responses.getContent().get(i).getNickname()).isEqualTo("nickname1");
assertThat(responses.getContent().get(i).getGroupId()).isEqualTo(
problem.getStudyGroup().getId());
}
}

@Test
@DisplayName("마감 된 나의 풀이 전체 조회 성공")
void getMySolutionsExpired() {
// given
Pageable pageable = PageRequest.of(0, 10);
List<Solution> expired = new ArrayList<>();
LocalDateTime fixedDateTime = LocalDateTime.now();

for (int i = 0; i < 5; i++) {
expired.add(Solution.builder()
.problem(problem2)
Expand All @@ -556,25 +595,17 @@ void getMySolutions() {
.build());
}

Page<Solution> inProgressPages = new PageImpl<>(inProgress, pageable, 10);
Page<Solution> expiredPages = new PageImpl<>(expired, pageable, 10);

when(solutionRepository.findAllFilteredMySolutions(user, null, null, null,
ProgressCategory.IN_PROGRESS, pageable)).thenReturn(inProgressPages);
when(solutionRepository.findAllFilteredMySolutions(user, null, null, null,
ProgressCategory.EXPIRED, pageable)).thenReturn(expiredPages);
// when
GetMySolutionListWithGroupIdResponse responses = solutionService.getMySolutions(user, null, null,
Page<GetSolutionWithGroupIdResponse> responses = solutionService.getMySolutionsExpired(user, null, null,
null, pageable);
// then
for (int i = 0; i < 5; i++) {
assertThat(responses.inProgress().getContent().get(i).getNickname()).isEqualTo("nickname1");
assertThat(responses.inProgress().getContent().get(i).getGroupId()).isEqualTo(
problem.getStudyGroup().getId());
}
for (int i = 0; i < 5; i++) {
assertThat(responses.expired().getContent().get(i).getNickname()).isEqualTo("nickname1");
assertThat(responses.expired().getContent().get(i).getGroupId()).isEqualTo(
assertThat(responses.getContent().get(i).getNickname()).isEqualTo("nickname1");
assertThat(responses.getContent().get(i).getGroupId()).isEqualTo(
problem2.getStudyGroup().getId());
}
}
Expand Down

0 comments on commit 67945ec

Please sign in to comment.