Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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 com.moplus.moplus_server.global.error.exception.ProblemSetToggleException;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
Expand Down Expand Up @@ -74,14 +75,17 @@ public void deleteProblemSet() {

public void toggleConfirm(List<Problem> problems) {
if (this.confirmStatus == ProblemSetConfirmStatus.NOT_CONFIRMED) {
if (problems.isEmpty()) {
throw new InvalidValueException(ErrorCode.EMPTY_PROBLEMS_ERROR);
}
List<String> invalidProblemIds = problems.stream()
.filter(problem -> !problem.isValid())
.map(Problem::getProblemCustomId)
.toList();
if (!invalidProblemIds.isEmpty()) {
String message = ErrorCode.INVALID_CONFIRM_PROBLEM.getMessage() +
String.join("번 ", invalidProblemIds) + "번";
throw new InvalidValueException(message, ErrorCode.INVALID_CONFIRM_PROBLEM);
throw new ProblemSetToggleException(message);
}
}
this.confirmStatus = this.confirmStatus.toggle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.moplus.moplus_server.domain.problemset.domain.ProblemSet;
import com.moplus.moplus_server.domain.problemset.domain.ProblemSetConfirmStatus;
import com.moplus.moplus_server.global.error.exception.ErrorCode;
import com.moplus.moplus_server.global.error.exception.InvalidValueException;
import com.moplus.moplus_server.global.error.exception.NotFoundException;
import org.springframework.data.jpa.repository.JpaRepository;

Expand All @@ -12,11 +13,15 @@ default ProblemSet findByIdElseThrow(Long problemSetId) {
return findById(problemSetId).orElseThrow(() -> new NotFoundException(ErrorCode.PROBLEM_SET_NOT_FOUND));
}

default void existsConfirmedActiveByIdElseThrow(Long problemSetId) {
if (!existsByIdAndIsDeletedFalseAndConfirmStatus(problemSetId, ProblemSetConfirmStatus.CONFIRMED)) {
throw new NotFoundException(ErrorCode.PROBLEM_SET_NOT_FOUND);
default void validatePublishableProblemSet(Long problemSetId) {
ProblemSet problemSet = findByIdElseThrow(problemSetId);

if (problemSet.isDeleted()) {
throw new InvalidValueException(ErrorCode.PROBLEM_SET_DELETED);
}
}

boolean existsByIdAndIsDeletedFalseAndConfirmStatus(Long problemSetId, ProblemSetConfirmStatus confirmStatus);
if (!ProblemSetConfirmStatus.CONFIRMED.equals(problemSet.getConfirmStatus())) {
throw new NotFoundException(ErrorCode.PROBLEM_SET_NOT_CONFIRMED);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public List<ProblemSetSearchGetResponse> search(String problemSetTitle, String p
.from(problemSet)
.leftJoin(problem).on(problem.id.in(problemSet.problemIds)) // 문제 세트 내 포함된 문항과 조인
.where(
problemSet.isDeleted.isFalse(),
containsProblemSetTitle(problemSetTitle),
containsProblemTitle(problemTitle)
)
Expand All @@ -50,6 +51,7 @@ public List<ProblemSetSearchGetResponse> confirmSearch(String problemSetTitle, S
.from(problemSet)
.leftJoin(problem).on(problem.id.in(problemSet.problemIds)) // 문제 세트 내 포함된 문항과 조인
.where(
problemSet.isDeleted.isFalse(),
problemSet.confirmStatus.eq(CONFIRMED),
containsProblemSetTitle(problemSetTitle),
containsProblemTitle(problemTitle)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository;
import com.moplus.moplus_server.domain.publish.domain.Publish;
import com.moplus.moplus_server.domain.publish.repository.PublishRepository;
import com.moplus.moplus_server.global.error.exception.BusinessException;
import com.moplus.moplus_server.global.error.exception.ErrorCode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -29,8 +31,10 @@ public class ProblemSetGetService {

@Transactional(readOnly = true)
public ProblemSetGetResponse getProblemSet(Long problemSetId) {

ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId);
if (problemSet.isDeleted()) {
throw new BusinessException(ErrorCode.DELETE_PROBLEM_SET_GET_ERROR);
}
List<LocalDate> publishedDates = publishRepository.findByProblemSetId(problemSetId).stream()
.map(Publish::getPublishedDate)
.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository;
import com.moplus.moplus_server.domain.publish.domain.Publish;
import com.moplus.moplus_server.domain.publish.repository.PublishRepository;
import com.moplus.moplus_server.global.error.exception.BusinessException;
import com.moplus.moplus_server.global.error.exception.ErrorCode;
import com.moplus.moplus_server.global.error.exception.InvalidValueException;
import java.util.ArrayList;
Expand All @@ -35,7 +36,9 @@ public void reorderProblems(Long problemSetId, ProblemReorderRequest request) {
@Transactional
public void updateProblemSet(Long problemSetId, ProblemSetUpdateRequest request) {
ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId);

if (problemSet.isDeleted()) {
throw new BusinessException(ErrorCode.DELETE_PROBLEM_SET_UPDATE_ERROR);
}
// 빈 문항 유효성 검증
if (request.problemIds().isEmpty()) {
throw new InvalidValueException(ErrorCode.EMPTY_PROBLEMS_ERROR);
Expand All @@ -49,6 +52,9 @@ public void updateProblemSet(Long problemSetId, ProblemSetUpdateRequest request)
@Transactional
public ProblemSetConfirmStatus toggleConfirmProblemSet(Long problemSetId) {
ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId);
if (problemSet.isDeleted()) {
throw new BusinessException(ErrorCode.DELETE_PROBLEM_SET_TOGGLE_ERROR);
}
List<Publish> publishes = publishRepository.findByProblemSetId(problemSetId);
if (!publishes.isEmpty()) {
throw new InvalidValueException(ErrorCode.ALREADY_PUBLISHED_ERROR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public Publish(LocalDate publishedDate, Long problemSetId) {

public void validatePublishedDate() {
// 발행 시점 다음날부터 발행 가능
if (this.publishedDate.isBefore(LocalDate.now().plusDays(1))) {
if (this.publishedDate.isBefore(LocalDate.now())) {
throw new InvalidValueException(ErrorCode.INVALID_DATE_ERROR);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package com.moplus.moplus_server.domain.publish.dto.response;

import com.moplus.moplus_server.domain.publish.domain.Publish;
import java.time.LocalDate;
import lombok.Builder;

@Builder
public record PublishMonthGetResponse(
Long publishId,
int day,
LocalDate date,
PublishProblemSetResponse problemSetInfo
) {
public static PublishMonthGetResponse of(Publish publish, PublishProblemSetResponse problemSetInfos) {
return PublishMonthGetResponse.builder()
.publishId(publish.getId())
.day(publish.getPublishedDate().getDayOfMonth())
.date(publish.getPublishedDate())
.problemSetInfo(problemSetInfos)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class PublishSaveService {

@Transactional
public Long createPublish(PublishPostRequest request) {
problemSetRepository.existsConfirmedActiveByIdElseThrow(request.problemSetId());
problemSetRepository.validatePublishableProblemSet(request.problemSetId());
Publish publish = request.toEntity();
// 발행날짜 유효성 검사
publish.validatePublishedDate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,16 @@ private ErrorResponse(final ErrorCode code) {
this.status = code.getStatus();
}

private ErrorResponse(final String message, final HttpStatus status) {
this.message = message;
this.status = status;
}

public static ErrorResponse from(final ErrorCode code) {
return new ErrorResponse(code);
}

public static ErrorResponse from(final String message, final HttpStatus status) {
return new ErrorResponse(message, status);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.moplus.moplus_server.global.error.exception.BusinessException;
import com.moplus.moplus_server.global.error.exception.ErrorCode;
import com.moplus.moplus_server.global.error.exception.InvalidValueException;
import com.moplus.moplus_server.global.error.exception.NotFoundException;
import com.moplus.moplus_server.global.error.exception.ProblemSetToggleException;
import com.moplus.moplus_server.global.security.exception.JwtInvalidException;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -78,4 +80,13 @@ protected ResponseEntity<ErrorResponse> handleJwtInvalidException(final JwtInval

return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED);
}

@ExceptionHandler(ProblemSetToggleException.class)
protected ResponseEntity<ErrorResponse> handleProblemSetToggleException(final ProblemSetToggleException exception) {
log.error("handleProblemSetToggleException", exception);

final ErrorResponse response = ErrorResponse.from(exception.getMessage(), HttpStatus.BAD_REQUEST);

return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,18 @@ public enum ErrorCode {
//문항세트
PROBLEM_SET_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 문항세트를 찾을 수 없습니다"),
EMPTY_PROBLEMS_ERROR(HttpStatus.BAD_REQUEST, "적어도 1개의 문항을 등록해주세요"),
DELETE_PROBLEM_SET_GET_ERROR(HttpStatus.BAD_REQUEST, "삭제된 세트 문항은 조회할 수 없습니다."),
DELETE_PROBLEM_SET_UPDATE_ERROR(HttpStatus.BAD_REQUEST, "삭제된 세트 문항은 수정할 수 없습니다."),
DELETE_PROBLEM_SET_TOGGLE_ERROR(HttpStatus.BAD_REQUEST, "삭제된 세트 문항은 컨펌을 토글할 수 없습니다."),

// 발행
INVALID_MONTH_ERROR(HttpStatus.BAD_REQUEST, "유효하지 않은 월입니다."),
INVALID_DATE_ERROR(HttpStatus.BAD_REQUEST, "오늘 이후 날짜에만 발행이 가능합니다."),
PUBLISH_NOT_FOUND(HttpStatus.NOT_FOUND, "발행 정보를 찾을 수 없습니다"),
CANNOT_DELETE_PAST_PUBLISH(HttpStatus.BAD_REQUEST, "이미 지난 발행건은 삭제할 수 없습니다."),
ALREADY_PUBLISHED_ERROR(HttpStatus.BAD_REQUEST, "이미 발행된 문항세트는 컨펌해제할 수 없습니다."),
PROBLEM_SET_DELETED(HttpStatus.BAD_REQUEST, "삭제된 문항세트는 발행할 수 없습니다"),
PROBLEM_SET_NOT_CONFIRMED(HttpStatus.BAD_REQUEST, "컨펌되지 않은 문항세트는 발행할 수 없습니다"),
;


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.moplus.moplus_server.global.error.exception;

public class ProblemSetToggleException extends RuntimeException {
public ProblemSetToggleException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
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 com.moplus.moplus_server.global.error.exception.ProblemSetToggleException;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -124,7 +125,7 @@ void setUp() {

// when & then
assertThatThrownBy(() -> problemSetUpdateService.toggleConfirmProblemSet(problemSetId))
.isInstanceOf(InvalidValueException.class)
.isInstanceOf(ProblemSetToggleException.class)
.hasMessageContaining("24052001004번") // 메시지에 포함된 ID 확인
.hasMessageContaining(ErrorCode.INVALID_CONFIRM_PROBLEM.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,17 @@ void setUp() {
void 월별_발행_조회_테스트() {
// given
publishSaveService.createPublish(new PublishPostRequest(
LocalDate.of(2025, 3, 10),
1L
));

publishSaveService.createPublish(new PublishPostRequest(
LocalDate.of(2025, 3, 15),
LocalDate.now(),
1L
));

// when
List<PublishMonthGetResponse> publishList = publishGetService.getPublishMonth(2025, 3);
List<PublishMonthGetResponse> publishList = publishGetService.getPublishMonth(LocalDate.now().getYear(), LocalDate.now().getMonthValue());

// then
assertThat(publishList).hasSize(2);
assertThat(publishList.get(0).day()).isEqualTo(10);
assertThat(publishList).hasSize(1);
assertThat(publishList.get(0).date()).isEqualTo(LocalDate.now());
assertThat(publishList.get(0).problemSetInfo().title()).isEqualTo("2025년 5월 고2 모의고사 문제 세트");
assertThat(publishList.get(1).day()).isEqualTo(15);
}

@Test
Expand All @@ -112,15 +106,12 @@ void setUp() {
}

@Test
void 오늘날짜_또는_과거날짜로_발행_시_예외_테스트() {
void 과거날짜로_발행_시_예외_테스트() {
// given
LocalDate today = LocalDate.now();
LocalDate pastDate = today.minusDays(1);

// when & then (createPublish에서 예외 발생하도록)
assertThatThrownBy(() -> publishSaveService.createPublish(new PublishPostRequest(today, 1L)))
.isInstanceOf(InvalidValueException.class)
.hasMessageContaining(ErrorCode.INVALID_DATE_ERROR.getMessage());

assertThatThrownBy(() -> publishSaveService.createPublish(new PublishPostRequest(pastDate, 1L)))
.isInstanceOf(InvalidValueException.class)
Expand Down