From 1c81f013301fb2fc5313f769e4467d30d680fd74 Mon Sep 17 00:00:00 2001 From: eunjungL <62099953+eunjungL@users.noreply.github.com> Date: Fri, 19 Jul 2024 19:48:31 +0900 Subject: [PATCH] =?UTF-8?q?[Feature]=20-=20=EC=97=AC=ED=96=89=20=EA=B3=84?= =?UTF-8?q?=ED=9A=8D=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20(#67)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: MethodArgumentNotValidException handler 추가 * fix: TravelPlan Request에서 order 제거 후 index 사용으로 변경 --- .../exception/GlobalExceptionHandler.java | 17 +++++++++++++++++ .../dto/request/PlanDayCreateRequest.java | 16 ++++++++-------- .../dto/request/PlanPlaceCreateRequest.java | 12 +++++------- .../dto/request/TravelPlanCreateRequest.java | 4 ++++ .../travelplan/service/TravelPlanService.java | 16 ++++++++-------- .../controller/TravelPlanControllerTest.java | 6 ++---- .../service/TravelPlanServiceTest.java | 6 ++---- 7 files changed, 46 insertions(+), 31 deletions(-) diff --git a/backend/src/main/java/woowacourse/touroot/global/exception/GlobalExceptionHandler.java b/backend/src/main/java/woowacourse/touroot/global/exception/GlobalExceptionHandler.java index e8612f41..c8f0872e 100644 --- a/backend/src/main/java/woowacourse/touroot/global/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/woowacourse/touroot/global/exception/GlobalExceptionHandler.java @@ -2,6 +2,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import woowacourse.touroot.global.exception.dto.ExceptionResponse; @@ -13,8 +14,24 @@ public class GlobalExceptionHandler { @ExceptionHandler(BadRequestException.class) public ResponseEntity handleBadRequestException(BadRequestException exception) { log.info("BAD_REQUEST_EXCEPTION :: message = {}", exception.getMessage()); + ExceptionResponse data = new ExceptionResponse(exception.getMessage()); return ResponseEntity.badRequest() .body(data); } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleMethodArgumentNotValidException( + MethodArgumentNotValidException exception + ) { + log.info("METHOD_ARGUMENT_NOT_VALID_EXCEPTION :: message = {}", exception.getMessage()); + + String message = exception.getBindingResult() + .getAllErrors() + .get(0) + .getDefaultMessage(); + ExceptionResponse data = new ExceptionResponse(message); + return ResponseEntity.badRequest() + .body(data); + } } diff --git a/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/PlanDayCreateRequest.java b/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/PlanDayCreateRequest.java index 12aa0ed3..e58229f7 100644 --- a/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/PlanDayCreateRequest.java +++ b/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/PlanDayCreateRequest.java @@ -1,23 +1,23 @@ package woowacourse.touroot.travelplan.dto.request; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Min; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import woowacourse.touroot.travelplan.domain.TravelPlan; import woowacourse.touroot.travelplan.domain.TravelPlanDay; import java.util.List; public record PlanDayCreateRequest( - @Schema(description = "여행 계획 날짜", example = "1") - @NotNull(message = "날짜는 비어있을 수 없습니다.") - @Min(value = 0, message = "날짜는 1 이상이어야 합니다.") - int day, @Schema(description = "여행 장소 정보") - @NotNull(message = "여행 장소 정보는 비어있을 수 없습니다.") List places + @Valid + @Size(min = 1, message = "여행 장소는 한 개 이상이어야 합니다.") + @NotNull(message = "여행 장소 정보는 비어있을 수 없습니다.") + List places ) { - public TravelPlanDay toPlanDay(TravelPlan plan) { - return new TravelPlanDay(day, plan); + public TravelPlanDay toPlanDay(int order, TravelPlan plan) { + return new TravelPlanDay(order, plan); } } diff --git a/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/PlanPlaceCreateRequest.java b/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/PlanPlaceCreateRequest.java index 08cc8dd6..32f16489 100644 --- a/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/PlanPlaceCreateRequest.java +++ b/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/PlanPlaceCreateRequest.java @@ -1,7 +1,7 @@ package woowacourse.touroot.travelplan.dto.request; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Min; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Builder; @@ -15,14 +15,12 @@ public record PlanPlaceCreateRequest( @NotBlank(message = "장소명은 비어있을 수 없습니다.") String placeName, @Schema(description = "여행 장소 설명", example = "신나는 여행 장소") String description, - @Schema(description = "여행 장소 순서", example = "1") - @NotNull - @Min(value = 0, message = "순서는 1 이상이어야 합니다.") - int order, - @NotNull PlanLocationCreateRequest location + @Valid + @NotNull(message = "위치는 비어있을 수 없습니다.") + PlanLocationCreateRequest location ) { - public TravelPlanPlace toPlanPlace(TravelPlanDay day, Place place) { + public TravelPlanPlace toPlanPlace(int order, TravelPlanDay day, Place place) { return new TravelPlanPlace(description, order, day, place); } diff --git a/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/TravelPlanCreateRequest.java b/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/TravelPlanCreateRequest.java index ab988ebb..bf986bc9 100644 --- a/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/TravelPlanCreateRequest.java +++ b/backend/src/main/java/woowacourse/touroot/travelplan/dto/request/TravelPlanCreateRequest.java @@ -1,8 +1,10 @@ package woowacourse.touroot.travelplan.dto.request; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Builder; import woowacourse.touroot.travelplan.domain.TravelPlan; @@ -18,6 +20,8 @@ public record TravelPlanCreateRequest( @NotNull(message = "시작일은 비어있을 수 없습니다.") LocalDate startDate, @Schema(description = "여행 날짜 정보") + @Valid + @Size(min = 1, message = "여행 날짜는 하루 이상 있어야 합니다.") @NotNull(message = "여행 날짜 정보는 비어있을 수 없습니다.") List days ) { diff --git a/backend/src/main/java/woowacourse/touroot/travelplan/service/TravelPlanService.java b/backend/src/main/java/woowacourse/touroot/travelplan/service/TravelPlanService.java index e4ef1623..714facfa 100644 --- a/backend/src/main/java/woowacourse/touroot/travelplan/service/TravelPlanService.java +++ b/backend/src/main/java/woowacourse/touroot/travelplan/service/TravelPlanService.java @@ -38,24 +38,24 @@ public TravelPlanCreateResponse createTravelPlan(TravelPlanCreateRequest request travelPlan.validateStartDate(); TravelPlan savedTravelPlan = travelPlanRepository.save(travelPlan); - createPlanDay(request, savedTravelPlan); + createPlanDay(request.days(), savedTravelPlan); return new TravelPlanCreateResponse(savedTravelPlan.getId()); } - private void createPlanDay(TravelPlanCreateRequest request, TravelPlan savedTravelPlan) { - for (PlanDayCreateRequest dayRequest : request.days()) { - // TODO: order는 배열 index로 변경 - TravelPlanDay travelPlanDay = travelPlanDayRepository.save(dayRequest.toPlanDay(savedTravelPlan)); + private void createPlanDay(List request, TravelPlan savedTravelPlan) { + for (int order = 0; order < request.size(); order++) { + PlanDayCreateRequest dayRequest = request.get(order); + TravelPlanDay travelPlanDay = travelPlanDayRepository.save(dayRequest.toPlanDay(order, savedTravelPlan)); createPlanPlace(dayRequest.places(), travelPlanDay); } } private void createPlanPlace(List request, TravelPlanDay travelPlanDay) { - for (PlanPlaceCreateRequest planRequest : request) { - // TODO: order는 배열 index로 변경 + for (int order = 0; order < request.size(); order++) { + PlanPlaceCreateRequest planRequest = request.get(order); Place place = getPlace(planRequest); - travelPlanPlaceRepository.save(planRequest.toPlanPlace(travelPlanDay, place)); + travelPlanPlaceRepository.save(planRequest.toPlanPlace(order, travelPlanDay, place)); } } diff --git a/backend/src/test/java/woowacourse/touroot/travelplan/controller/TravelPlanControllerTest.java b/backend/src/test/java/woowacourse/touroot/travelplan/controller/TravelPlanControllerTest.java index 9504e570..f5a417e5 100644 --- a/backend/src/test/java/woowacourse/touroot/travelplan/controller/TravelPlanControllerTest.java +++ b/backend/src/test/java/woowacourse/touroot/travelplan/controller/TravelPlanControllerTest.java @@ -49,10 +49,9 @@ void createTravelPlan() { PlanPlaceCreateRequest planPlaceCreateRequest = PlanPlaceCreateRequest.builder() .placeName("잠실한강공원") .description("신나는 여행 장소") - .order(0) .location(locationRequest) .build(); - PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(0, List.of(planPlaceCreateRequest)); + PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(List.of(planPlaceCreateRequest)); TravelPlanCreateRequest request = TravelPlanCreateRequest.builder() .title("신나는 한강 여행") .startDate(LocalDate.MAX) @@ -78,10 +77,9 @@ void createTravelPlanWithInvalidStartDate() { PlanPlaceCreateRequest planPlaceCreateRequest = PlanPlaceCreateRequest.builder() .placeName("잠실한강공원") .description("신나는 여행 장소") - .order(0) .location(locationRequest) .build(); - PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(0, List.of(planPlaceCreateRequest)); + PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(List.of(planPlaceCreateRequest)); TravelPlanCreateRequest request = TravelPlanCreateRequest.builder() .title("신나는 한강 여행") .startDate(LocalDate.MIN) diff --git a/backend/src/test/java/woowacourse/touroot/travelplan/service/TravelPlanServiceTest.java b/backend/src/test/java/woowacourse/touroot/travelplan/service/TravelPlanServiceTest.java index 25bba77e..ccbcb296 100644 --- a/backend/src/test/java/woowacourse/touroot/travelplan/service/TravelPlanServiceTest.java +++ b/backend/src/test/java/woowacourse/touroot/travelplan/service/TravelPlanServiceTest.java @@ -50,10 +50,9 @@ void createTravelPlan() { PlanPlaceCreateRequest planPlaceCreateRequest = PlanPlaceCreateRequest.builder() .placeName("잠실한강공원") .description("신나는 여행 장소") - .order(0) .location(locationRequest) .build(); - PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(0, List.of(planPlaceCreateRequest)); + PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(List.of(planPlaceCreateRequest)); TravelPlanCreateRequest request = TravelPlanCreateRequest.builder() .title("신나는 한강 여행") .startDate(LocalDate.MAX) @@ -75,10 +74,9 @@ void createTravelPlanWithInvalidStartDate() { PlanPlaceCreateRequest planPlaceCreateRequest = PlanPlaceCreateRequest.builder() .placeName("잠실한강공원") .description("신나는 여행 장소") - .order(0) .location(locationRequest) .build(); - PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(0, List.of(planPlaceCreateRequest)); + PlanDayCreateRequest planDayCreateRequest = new PlanDayCreateRequest(List.of(planPlaceCreateRequest)); TravelPlanCreateRequest request = TravelPlanCreateRequest.builder() .title("신나는 한강 여행") .startDate(LocalDate.MIN)