diff --git a/src/main/java/com/moplus/moplus_server/domain/problem/domain/problem/Problem.java b/src/main/java/com/moplus/moplus_server/domain/problem/domain/problem/Problem.java index b059bf3..e8c7814 100644 --- a/src/main/java/com/moplus/moplus_server/domain/problem/domain/problem/Problem.java +++ b/src/main/java/com/moplus/moplus_server/domain/problem/domain/problem/Problem.java @@ -120,4 +120,15 @@ public void updateChildProblem(List inputChildProblems) { public void deleteChildProblem(List deleteChildProblems) { childProblems.removeIf(childProblem -> deleteChildProblems.contains(childProblem.getId())); } -} + + public boolean isValid() { + return answer != null && !answer.getValue().isEmpty() + && practiceTestId != null + && comment != null && !comment.isEmpty() + && readingTipImageUrl != null && !readingTipImageUrl.isEmpty() + && seniorTipImageUrl != null && !seniorTipImageUrl.isEmpty() + && prescriptionImageUrl != null && !prescriptionImageUrl.isEmpty() + && mainProblemImageUrl != null && !mainProblemImageUrl.isEmpty() + && mainAnalysisImageUrl != null && !mainAnalysisImageUrl.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/controller/ProblemSetController.java b/src/main/java/com/moplus/moplus_server/domain/problemset/controller/ProblemSetController.java new file mode 100644 index 0000000..d101b45 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/controller/ProblemSetController.java @@ -0,0 +1,71 @@ +package com.moplus.moplus_server.domain.problemset.controller; + +import com.moplus.moplus_server.domain.problemset.domain.ProblemSetConfirmStatus; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemReorderRequest; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemSetPostRequest; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemSetUpdateRequest; +import com.moplus.moplus_server.domain.problemset.service.ProblemSetDeleteService; +import com.moplus.moplus_server.domain.problemset.service.ProblemSetSaveService; +import com.moplus.moplus_server.domain.problemset.service.ProblemSetUpdateService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/problemSet") +@RequiredArgsConstructor +public class ProblemSetController { + + private final ProblemSetSaveService problemSetSaveService; + private final ProblemSetUpdateService problemSetUpdateService; + private final ProblemSetDeleteService problemSetDeleteService; + + @PostMapping("") + @Operation(summary = "문항세트 생성", description = "문항세트를 생성합니다. 문항은 요청 순서대로 저장합니다.") + public ResponseEntity createProblemSet( + @RequestBody ProblemSetPostRequest request + ) { + return ResponseEntity.ok(problemSetSaveService.createProblemSet(request)); + } + + @PutMapping("/{problemSetId}/sequence") + @Operation(summary = "세트 문항순서 변경", description = "문항세트 내의 문항 리스트의 순서를 변경합니다.") + public ResponseEntity reorderProblems( + @PathVariable Long problemSetId, + @RequestBody ProblemReorderRequest request) { + problemSetUpdateService.reorderProblems(problemSetId, request); + return ResponseEntity.noContent().build(); + } + + @PutMapping("/{problemSetId}") + @Operation(summary = "문항세트 수정", description = "문항세트의 이름 및 문항 리스트를 수정합니다.") + public ResponseEntity updateProblemSet( + @PathVariable Long problemSetId, + @RequestBody ProblemSetUpdateRequest request + ) { + problemSetUpdateService.updateProblemSet(problemSetId, request); + return ResponseEntity.noContent().build(); + } + + @DeleteMapping("/{problemSetId}") + @Operation(summary = "문항세트 삭제", description = "문항세트를 삭제합니다. (soft delete)") + public ResponseEntity deleteProblemSet( + @PathVariable Long problemSetId + ) { + problemSetDeleteService.deleteProblemSet(problemSetId); + return ResponseEntity.noContent().build(); + } + + @PutMapping("/{problemSetId}/confirm") + @Operation(summary = "문항세트 컨펌 토글", description = "문항세트의 컨펌 상태를 토글합니다.") + public ResponseEntity toggleConfirmProblemSet(@PathVariable Long problemSetId) { + return ResponseEntity.ok(problemSetUpdateService.toggleConfirmProblemSet(problemSetId)); + } +} diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/domain/ProblemSet.java b/src/main/java/com/moplus/moplus_server/domain/problemset/domain/ProblemSet.java new file mode 100644 index 0000000..4b2e7d9 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/domain/ProblemSet.java @@ -0,0 +1,80 @@ +package com.moplus.moplus_server.domain.problemset.domain; + +import com.moplus.moplus_server.domain.problem.domain.problem.Problem; +import com.moplus.moplus_server.domain.problem.domain.problem.ProblemId; +import com.moplus.moplus_server.global.common.BaseEntity; +import com.moplus.moplus_server.global.error.exception.ErrorCode; +import com.moplus.moplus_server.global.error.exception.InvalidValueException; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OrderColumn; +import java.util.ArrayList; +import java.util.List; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class ProblemSet extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "problem_set_id") + Long id; + + private String name; + private boolean isDeleted; + + @Enumerated(EnumType.STRING) + private ProblemSetConfirmStatus confirmStatus; + + @ElementCollection + @CollectionTable(name = "problem_set_problems", joinColumns = @JoinColumn(name = "problem_set_id")) + @Column(name = "problem_id") + @OrderColumn(name = "sequence") + private List problemIds = new ArrayList<>(); + + @Builder + public ProblemSet(String name, List problemIds) { + this.name = name; + this.isDeleted = false; + this.confirmStatus = ProblemSetConfirmStatus.NOT_CONFIRMED; + this.problemIds = problemIds; + } + + public void updateProblemOrder(List newProblems) { + this.problemIds = new ArrayList<>(newProblems); + } + + public void deleteProblemSet() { + this.isDeleted = true; + } + + public void toggleConfirm(List problems) { + if(this.confirmStatus == ProblemSetConfirmStatus.NOT_CONFIRMED){ + // 문항 유효성 검사 + for (Problem problem : problems) { + if (!problem.isValid()) { + throw new InvalidValueException(ErrorCode.INVALID_CONFIRM_PROBLEM); + } + } + } + this.confirmStatus = this.confirmStatus.toggle(); + } + + public void updateProblemSet(String name, List newProblems) { + this.name = name; + this.problemIds = newProblems; + } +} diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/domain/ProblemSetConfirmStatus.java b/src/main/java/com/moplus/moplus_server/domain/problemset/domain/ProblemSetConfirmStatus.java new file mode 100644 index 0000000..e108d26 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/domain/ProblemSetConfirmStatus.java @@ -0,0 +1,9 @@ +package com.moplus.moplus_server.domain.problemset.domain; + +public enum ProblemSetConfirmStatus { + CONFIRMED, + NOT_CONFIRMED; + public ProblemSetConfirmStatus toggle() { + return this == CONFIRMED ? NOT_CONFIRMED : CONFIRMED; + } +} \ No newline at end of file diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemReorderRequest.java b/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemReorderRequest.java new file mode 100644 index 0000000..602b249 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemReorderRequest.java @@ -0,0 +1,8 @@ +package com.moplus.moplus_server.domain.problemset.dto.request; + +import java.util.List; + +public record ProblemReorderRequest( + List newProblems +) { +} diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemSetPostRequest.java b/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemSetPostRequest.java new file mode 100644 index 0000000..0401915 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemSetPostRequest.java @@ -0,0 +1,17 @@ +package com.moplus.moplus_server.domain.problemset.dto.request; + +import com.moplus.moplus_server.domain.problem.domain.problem.ProblemId; +import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import java.util.List; + +public record ProblemSetPostRequest( + String problemSetName, + List problems +) { + public ProblemSet toEntity(List problemIdList) { + return ProblemSet.builder() + .name(this.problemSetName) + .problemIds(problemIdList) + .build(); + } +} diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemSetUpdateRequest.java b/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemSetUpdateRequest.java new file mode 100644 index 0000000..a0e4745 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/dto/request/ProblemSetUpdateRequest.java @@ -0,0 +1,9 @@ +package com.moplus.moplus_server.domain.problemset.dto.request; + +import java.util.List; + +public record ProblemSetUpdateRequest( + String problemSetName, + List problems +) { +} diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetRepository.java b/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetRepository.java new file mode 100644 index 0000000..fff031f --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetRepository.java @@ -0,0 +1,14 @@ +package com.moplus.moplus_server.domain.problemset.repository; + +import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import com.moplus.moplus_server.global.error.exception.ErrorCode; +import com.moplus.moplus_server.global.error.exception.NotFoundException; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProblemSetRepository extends JpaRepository { + + default ProblemSet findByIdElseThrow(Long problemSetId) { + return findById(problemSetId).orElseThrow(() -> new NotFoundException(ErrorCode.PROBLEM_SET_NOT_FOUND)); + } + +} diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetDeleteService.java b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetDeleteService.java new file mode 100644 index 0000000..830d751 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetDeleteService.java @@ -0,0 +1,21 @@ +package com.moplus.moplus_server.domain.problemset.service; + +import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class ProblemSetDeleteService { + + private final ProblemSetRepository problemSetRepository; + + @Transactional + public void deleteProblemSet(Long problemSetId) { + ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId); + problemSet.deleteProblemSet(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetSaveService.java b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetSaveService.java new file mode 100644 index 0000000..3805f6e --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetSaveService.java @@ -0,0 +1,38 @@ +package com.moplus.moplus_server.domain.problemset.service; + +import com.moplus.moplus_server.domain.problem.domain.problem.ProblemId; +import com.moplus.moplus_server.domain.problem.repository.ProblemRepository; +import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemReorderRequest; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemSetPostRequest; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemSetUpdateRequest; +import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class ProblemSetSaveService { + + private final ProblemSetRepository problemSetRepository; + private final ProblemRepository problemRepository; + + @Transactional + public Long createProblemSet(ProblemSetPostRequest request) { + // 문제 ID 리스트를 ProblemId 객체로 변환 + List problemIdList = request.problems().stream() + .map(ProblemId::new) + .toList(); + + // 모든 문항이 DB에 존재하는지 검증 + problemIdList.forEach(problemRepository::findByIdElseThrow); + + // ProblemSet 생성 + ProblemSet problemSet = request.toEntity(problemIdList); + + return problemSetRepository.save(problemSet).getId(); + } +} diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetUpdateService.java b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetUpdateService.java new file mode 100644 index 0000000..fd42a0f --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetUpdateService.java @@ -0,0 +1,63 @@ +package com.moplus.moplus_server.domain.problemset.service; + +import com.moplus.moplus_server.domain.problem.domain.problem.Problem; +import com.moplus.moplus_server.domain.problem.domain.problem.ProblemId; +import com.moplus.moplus_server.domain.problem.repository.ProblemRepository; +import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import com.moplus.moplus_server.domain.problemset.domain.ProblemSetConfirmStatus; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemReorderRequest; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemSetUpdateRequest; +import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; +import com.moplus.moplus_server.global.error.exception.ErrorCode; +import com.moplus.moplus_server.global.error.exception.InvalidValueException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class ProblemSetUpdateService { + + private final ProblemSetRepository problemSetRepository; + private final ProblemRepository problemRepository; + + @Transactional + public void reorderProblems(Long problemSetId, ProblemReorderRequest request) { + ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId); + + // 기존 문항 ID 리스트 업데이트 (순서 반영) + List updatedProblemIds = request.newProblems().stream() + .map(ProblemId::new) + .collect(Collectors.toList()); + + problemSet.updateProblemOrder(updatedProblemIds); + } + + @Transactional + public void updateProblemSet(Long problemSetId, ProblemSetUpdateRequest request) { + ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId); + + // 문항 리스트 검증 + List problemIdList = request.problems().stream() + .map(ProblemId::new) + .collect(Collectors.toList()); + problemIdList.forEach(problemRepository::findByIdElseThrow); + + problemSet.updateProblemSet(request.problemSetName(), problemIdList); + } + + @Transactional + public ProblemSetConfirmStatus toggleConfirmProblemSet(Long problemSetId) { + ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId); + List problems = new ArrayList<>(); + for (ProblemId problemId : problemSet.getProblemIds()) { + Problem problem = problemRepository.findByIdElseThrow(problemId); + problems.add(problem); + } + problemSet.toggleConfirm(problems); + return problemSet.getConfirmStatus(); + } +} diff --git a/src/main/java/com/moplus/moplus_server/domain/publish/domain/Publish.java b/src/main/java/com/moplus/moplus_server/domain/publish/domain/Publish.java new file mode 100644 index 0000000..55a66ab --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/publish/domain/Publish.java @@ -0,0 +1,37 @@ +package com.moplus.moplus_server.domain.publish.domain; + +import com.moplus.moplus_server.global.common.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import java.time.LocalDate; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Publish extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "publish_id") + private Long id; + + @Column(nullable = false) + private LocalDate publishedDate; + + @Column(name = "problem_set_id", nullable = false) + private Long problemSetId; + + @Builder + public Publish(LocalDate publishedDate, Long problemSetId) { + this.publishedDate = publishedDate; + this.problemSetId = problemSetId; + } + +} diff --git a/src/main/java/com/moplus/moplus_server/global/error/exception/ErrorCode.java b/src/main/java/com/moplus/moplus_server/global/error/exception/ErrorCode.java index eb740fd..93516b5 100644 --- a/src/main/java/com/moplus/moplus_server/global/error/exception/ErrorCode.java +++ b/src/main/java/com/moplus/moplus_server/global/error/exception/ErrorCode.java @@ -32,6 +32,7 @@ public enum ErrorCode { PROBLEM_ALREADY_EXIST(HttpStatus.CONFLICT, "해당 문제는 이미 존재합니다"), INVALID_MULTIPLE_CHOICE_ANSWER(HttpStatus.BAD_REQUEST, "객관식 문제의 정답은 1~5 사이의 숫자여야 합니다"), INVALID_SHORT_NUMBER_ANSWER(HttpStatus.BAD_REQUEST, "주관식 문제의 정답은 0~999 사이의 숫자여야 합니다"), + INVALID_CONFIRM_PROBLEM(HttpStatus.BAD_REQUEST, "문항의 모든 요소를 등록해야 컨펌을 완료할 수 있습니다."), //새끼 문항 CHILD_PROBLEM_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 새끼 문제를 찾을 수 없습니다"), @@ -52,6 +53,9 @@ public enum ErrorCode { //회원 MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 회원을 찾을 수 없습니다"), + + //문항세트 + PROBLEM_SET_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 문항세트를 찾을 수 없습니다"), ; diff --git a/src/test/java/com/moplus/moplus_server/domain/problemset/ProblemSetServiceTest.java b/src/test/java/com/moplus/moplus_server/domain/problemset/ProblemSetServiceTest.java new file mode 100644 index 0000000..e7c95ca --- /dev/null +++ b/src/test/java/com/moplus/moplus_server/domain/problemset/ProblemSetServiceTest.java @@ -0,0 +1,142 @@ +package com.moplus.moplus_server.domain.problemset; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import com.moplus.moplus_server.domain.problemset.domain.ProblemSetConfirmStatus; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemReorderRequest; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemSetPostRequest; +import com.moplus.moplus_server.domain.problemset.dto.request.ProblemSetUpdateRequest; +import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; +import com.moplus.moplus_server.domain.problemset.service.ProblemSetSaveService; +import com.moplus.moplus_server.domain.problemset.service.ProblemSetUpdateService; +import com.moplus.moplus_server.global.error.exception.ErrorCode; +import com.moplus.moplus_server.global.error.exception.InvalidValueException; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@ActiveProfiles("h2test") +@Sql({"/insert-problemset.sql"}) +@SpringBootTest +public class ProblemSetServiceTest { + + @Autowired + private ProblemSetSaveService problemSetSaveService; + + @Autowired + private ProblemSetUpdateService problemSetUpdateService; + + @Autowired + private ProblemSetRepository problemSetRepository; + + private ProblemSetPostRequest problemSetPostRequest; + + @BeforeEach + void setUp() { + // 초기 문항 세트 생성 요청 데이터 준비 + problemSetPostRequest = new ProblemSetPostRequest( + "초기 문항세트", + List.of("24052001001", "24052001002", "24052001003") + ); + } + + @Test + void 문항세트_생성_테스트() { + // when + Long problemSetId = problemSetSaveService.createProblemSet(problemSetPostRequest); + + // then + ProblemSet savedProblemSet = problemSetRepository.findById(problemSetId) + .orElseThrow(() -> new IllegalArgumentException("문항세트를 찾을 수 없습니다.")); + + assertThat(savedProblemSet).isNotNull(); + assertThat(savedProblemSet.getName()).isEqualTo("초기 문항세트"); + assertThat(savedProblemSet.getProblemIds()).hasSize(3); + assertThat(savedProblemSet.getProblemIds().get(0).getId()).isEqualTo("24052001001"); + assertThat(savedProblemSet.getProblemIds().get(1).getId()).isEqualTo("24052001002"); + assertThat(savedProblemSet.getProblemIds().get(2).getId()).isEqualTo("24052001003"); + } + + @Test + void 문항세트_문항순서_변경_테스트() { + // given + Long problemSetId = problemSetSaveService.createProblemSet(problemSetPostRequest); + + // when + ProblemReorderRequest reorderRequest = new ProblemReorderRequest( + List.of("24052001003", "24052001001", "24052001002") + ); + problemSetUpdateService.reorderProblems(problemSetId, reorderRequest); + + // then + ProblemSet updatedProblemSet = problemSetRepository.findById(problemSetId) + .orElseThrow(() -> new IllegalArgumentException("문항세트를 찾을 수 없습니다.")); + + assertThat(updatedProblemSet.getProblemIds().get(0).getId()).isEqualTo("24052001003"); + assertThat(updatedProblemSet.getProblemIds().get(1).getId()).isEqualTo("24052001001"); + assertThat(updatedProblemSet.getProblemIds().get(2).getId()).isEqualTo("24052001002"); + } + + @Test + void 문항세트_업데이트_테스트() { + // given + Long problemSetId = problemSetSaveService.createProblemSet(problemSetPostRequest); + + // when + ProblemSetUpdateRequest updateRequest = new ProblemSetUpdateRequest( + "업데이트된 문항세트", + List.of("24052001002", "24052001003") + ); + problemSetUpdateService.updateProblemSet(problemSetId, updateRequest); + + // then + ProblemSet updatedProblemSet = problemSetRepository.findById(problemSetId) + .orElseThrow(() -> new IllegalArgumentException("문항세트를 찾을 수 없습니다.")); + + assertThat(updatedProblemSet.getName()).isEqualTo("업데이트된 문항세트"); + assertThat(updatedProblemSet.getProblemIds()).hasSize(2); + assertThat(updatedProblemSet.getProblemIds().get(0).getId()).isEqualTo("24052001002"); + assertThat(updatedProblemSet.getProblemIds().get(1).getId()).isEqualTo("24052001003"); + } + + @Test + void 문항세트_컨펌_토글_테스트() { + // given + Long problemSetId = problemSetSaveService.createProblemSet(problemSetPostRequest); + + // when + ProblemSetConfirmStatus firstToggleStatus = problemSetUpdateService.toggleConfirmProblemSet(problemSetId); // CONFIRMED + ProblemSetConfirmStatus secondToggleStatus = problemSetUpdateService.toggleConfirmProblemSet(problemSetId); // NOT_CONFIRMED + + // then + assertThat(firstToggleStatus).isEqualTo(ProblemSetConfirmStatus.CONFIRMED); // 첫 번째 호출 후 컨펌 상태 확인 + assertThat(secondToggleStatus).isEqualTo(ProblemSetConfirmStatus.NOT_CONFIRMED); // 두 번째 호출 후 비컨펌 상태 확인 + } + + @Test + void 유효하지_않은_문항이_포함된_문항세트_컨펌_실패_테스트() { + // given + Long problemSetId = problemSetSaveService.createProblemSet(problemSetPostRequest); + + // 유효하지 않은 문항을 포함하도록 설정 (문항 ID가 존재하지 않거나 필수 필드가 누락된 경우) + ProblemSetUpdateRequest invalidUpdateRequest = new ProblemSetUpdateRequest( + "유효하지 않은 문항세트", + List.of("24052001001", "24052001004") + ); + problemSetUpdateService.updateProblemSet(problemSetId, invalidUpdateRequest); + + // when & then + assertThatThrownBy(() -> problemSetUpdateService.toggleConfirmProblemSet(problemSetId)) + .isInstanceOf(InvalidValueException.class) + .hasMessageContaining(ErrorCode.INVALID_CONFIRM_PROBLEM.getMessage()); + } +} \ No newline at end of file diff --git a/src/test/resources/insert-problemset.sql b/src/test/resources/insert-problemset.sql new file mode 100644 index 0000000..6e50eca --- /dev/null +++ b/src/test/resources/insert-problemset.sql @@ -0,0 +1,30 @@ +DELETE FROM problem_concept; +DELETE +FROM child_problem_concept; +DELETE +FROM child_problem; +DELETE FROM problem_set_problems; +DELETE FROM problem_set; +DELETE FROM problem; + +-- problem 데이터 삽입 +INSERT INTO problem (problem_id, practice_test_id, number, answer, comment, main_problem_image_url, + main_analysis_image_url, reading_tip_image_url, senior_tip_image_url, prescription_image_url, + is_published, is_variation) +VALUES ('24052001001', 1, 1, '1', '기존 문제 설명', + 'mainProblem.png', 'mainAnalysis.png', 'readingTip.png', 'seniorTip.png', 'prescription.png', + false, false), + ('24052001002', 1, 2, '2', '문제 2 설명', + 'mainProblem2.png', 'mainAnalysis2.png', 'readingTip2.png', 'seniorTip2.png', 'prescription2.png', + false, false), + ('24052001003', 1, 3, '3', '문제 3 설명', + 'mainProblem3.png', 'mainAnalysis3.png', 'readingTip3.png', 'seniorTip3.png', 'prescription3.png', + false, false); + +-- 유효하지 않은 문제 데이터 삽입 (answer와 mainProblemImageUrl이 NULL) +INSERT INTO problem (problem_id, practice_test_id, number, answer, comment, main_problem_image_url, + main_analysis_image_url, reading_tip_image_url, senior_tip_image_url, prescription_image_url, + is_published, is_variation) +VALUES ('24052001004', 1, 4, '', '유효하지 않은 문제 설명', + '', 'mainAnalysis4.png', 'readingTip4.png', 'seniorTip4.png', 'prescription4.png', + false, false); \ No newline at end of file