From cfa23c72078bc9dfe77189ca9ac3bb4e6d204777 Mon Sep 17 00:00:00 2001 From: sunny Date: Mon, 11 Dec 2023 18:15:46 +0900 Subject: [PATCH 1/2] feat: create course v2 --- .../common/module/convert/CoordinateDto.java | 11 ++++++ .../convert/CoordinatePathConverter.java | 27 +++++++-------- .../course/controller/CourseController.java | 32 +++++++++++++++++ .../dto/request/CourseCreateRequestDtoV2.java | 34 +++++++++++++++++++ .../server/course/service/CourseService.java | 32 +++++++++++++++++ 5 files changed, 122 insertions(+), 14 deletions(-) create mode 100644 src/main/java/org/runnect/server/common/module/convert/CoordinateDto.java create mode 100644 src/main/java/org/runnect/server/course/dto/request/CourseCreateRequestDtoV2.java diff --git a/src/main/java/org/runnect/server/common/module/convert/CoordinateDto.java b/src/main/java/org/runnect/server/common/module/convert/CoordinateDto.java new file mode 100644 index 0000000..1550102 --- /dev/null +++ b/src/main/java/org/runnect/server/common/module/convert/CoordinateDto.java @@ -0,0 +1,11 @@ +package org.runnect.server.common.module.convert; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class CoordinateDto { + private double latitude; + private double longitude; +} diff --git a/src/main/java/org/runnect/server/common/module/convert/CoordinatePathConverter.java b/src/main/java/org/runnect/server/common/module/convert/CoordinatePathConverter.java index d89c2d7..4dfc6fb 100644 --- a/src/main/java/org/runnect/server/common/module/convert/CoordinatePathConverter.java +++ b/src/main/java/org/runnect/server/common/module/convert/CoordinatePathConverter.java @@ -4,20 +4,28 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.PrecisionModel; +import org.runnect.server.common.constant.ErrorStatus; import org.runnect.server.common.exception.BadRequestException; import org.runnect.server.common.exception.BasicException; -import org.runnect.server.common.constant.ErrorStatus; @Slf4j public class CoordinatePathConverter { + public static LineString coorConvertPathV2(List path) { + try { + return getLineString(path); + } catch (Exception e) { + log.warn("course 요청 데이터 값 (path) -> " + path); + log.warn("course 요청 데이터 값의 타입 (path) -> " + path.getClass().getName()); + throw new BadRequestException(ErrorStatus.VALIDATION_COURSE_PATH_EXCEPTION, ErrorStatus.VALIDATION_COURSE_PATH_EXCEPTION.getMessage()); + } + } + public static LineString coorConvertPath(String path) { List coordinateDtos = new ArrayList<>(); @@ -34,8 +42,8 @@ public static LineString coorConvertPath(String path) { return getLineString(coordinateDtos); } catch (Exception e) { - log.info("course 요청 데이터 값 (path) -> " + path); - log.info("course 요청 데이터 값의 타입 (path) -> " + path.getClass().getName()); + log.warn("course 요청 데이터 값 (path) -> " + path); + log.warn("course 요청 데이터 값의 타입 (path) -> " + path.getClass().getName()); throw new BadRequestException(ErrorStatus.VALIDATION_COURSE_PATH_EXCEPTION, ErrorStatus.VALIDATION_COURSE_PATH_EXCEPTION.getMessage()); } } @@ -67,13 +75,4 @@ private static LineString getLineString(List coordinateDtos) { LineString lineString = geometryFactory.createLineString(coordinates); return lineString; } - - @Getter - @AllArgsConstructor - private static class CoordinateDto { - private double latitude; - private double longitude; - } - } - diff --git a/src/main/java/org/runnect/server/course/controller/CourseController.java b/src/main/java/org/runnect/server/course/controller/CourseController.java index 73f749e..1e81217 100644 --- a/src/main/java/org/runnect/server/course/controller/CourseController.java +++ b/src/main/java/org/runnect/server/course/controller/CourseController.java @@ -9,6 +9,7 @@ import org.runnect.server.common.exception.BadRequestException; import org.runnect.server.common.resolver.userId.UserId; import org.runnect.server.course.dto.request.CourseCreateRequestDto; +import org.runnect.server.course.dto.request.CourseCreateRequestDtoV2; import org.runnect.server.course.dto.request.DeleteCoursesRequestDto; import org.runnect.server.course.dto.request.UpdateCourseRequestDto; import org.runnect.server.course.dto.response.CourseCreateResponseDto; @@ -63,6 +64,37 @@ public ApiResponseDto createCourse( courseService.createCourse(userId, courseCreateRequestDto, imageUrl)); } + @PostMapping(value = "/v2", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.CREATED) + public ApiResponseDto createCourseV2( + @UserId Long userId, + @ModelAttribute @Valid final CourseCreateRequestDtoV2 courseCreateRequestDto, + BindingResult bindingResult + ) { + log.info("create course 요청 값"); + log.info("departureAddress : " + courseCreateRequestDto.getDepartureAddress()); + log.info("departureName : " + courseCreateRequestDto.getDepartureName()); + log.info("path : " + courseCreateRequestDto.getPath()); + log.info("distance : " + courseCreateRequestDto.getDistance().toString()); + log.info("image : " + courseCreateRequestDto.getImage().toString()); + if (bindingResult.hasErrors()) { + +// List as = new ArrayList<>(); +// as.add(23.0); +// as.add(11.3); +// List> asd = new ArrayList<>(); +// asd.add(as); +// System.out.println(asd.toString()); + + throw new BadRequestException(ErrorStatus.REQUEST_VALIDATION_EXCEPTION, + bindingResult.getFieldError().getField() + " 필드가 입력되지 않았습니다."); + } + String imageUrl = s3Service.uploadImage(courseCreateRequestDto.getImage(), "course"); + return ApiResponseDto.success(SuccessStatus.CREATE_COURSE_SUCCESS, + courseService.createCourseV2(userId, courseCreateRequestDto, imageUrl)); + } + + @GetMapping("/user") @ResponseStatus(HttpStatus.OK) public ApiResponseDto getCourseByUser(@UserId Long userId) { diff --git a/src/main/java/org/runnect/server/course/dto/request/CourseCreateRequestDtoV2.java b/src/main/java/org/runnect/server/course/dto/request/CourseCreateRequestDtoV2.java new file mode 100644 index 0000000..ba9d797 --- /dev/null +++ b/src/main/java/org/runnect/server/course/dto/request/CourseCreateRequestDtoV2.java @@ -0,0 +1,34 @@ +package org.runnect.server.course.dto.request; + +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.runnect.server.common.module.convert.CoordinateDto; +import org.springframework.web.multipart.MultipartFile; + +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class CourseCreateRequestDtoV2 { + + @NotNull(message = "path는 필수 입력 항목입니다.") + private List path; + + @NotBlank(message = "title은 필수 입력 항목입니다.") + private String title; + + @NotNull(message = "image는 필수 입력 항목입니다.") + private MultipartFile image; + + @NotNull(message = "distance는 필수 입력 항목입니다.") + private Float distance; + + private String departureName; + + @NotBlank(message = "departureAddress는 필수 입력 항목입니다.") + private String departureAddress; +} diff --git a/src/main/java/org/runnect/server/course/service/CourseService.java b/src/main/java/org/runnect/server/course/service/CourseService.java index bc3f38b..f083b23 100644 --- a/src/main/java/org/runnect/server/course/service/CourseService.java +++ b/src/main/java/org/runnect/server/course/service/CourseService.java @@ -12,6 +12,7 @@ import org.runnect.server.common.module.convert.CoordinatePathConverter; import org.runnect.server.common.module.convert.DepartureConverter; import org.runnect.server.course.dto.request.CourseCreateRequestDto; +import org.runnect.server.course.dto.request.CourseCreateRequestDtoV2; import org.runnect.server.course.dto.response.CourseCreateResponseDto; import org.runnect.server.course.dto.response.CourseGetByUserResponseDto; import org.runnect.server.course.dto.response.CourseResponse; @@ -70,6 +71,37 @@ public CourseCreateResponseDto createCourse(Long userId, CourseCreateRequestDto return CourseCreateResponseDto.of(saved.getId(), saved.getCreatedAt()); } + @Transactional + public CourseCreateResponseDto createCourseV2(Long userId, CourseCreateRequestDtoV2 requestDto, + String image) { + RunnectUser user = userRepository.findById(userId) + .orElseThrow(() -> new NotFoundUserException(NOT_FOUND_USER_EXCEPTION, + NOT_FOUND_USER_EXCEPTION.getMessage())); + + LineString path = CoordinatePathConverter.coorConvertPathV2(requestDto.getPath()); + DepartureResponse departureResponse = DepartureConverter.requestConvertDeparture( + requestDto.getDepartureAddress(), requestDto.getDepartureName()); + + Course course = Course.builder() + .runnectUser(user) + .title(requestDto.getTitle()) + .departureRegion(departureResponse.getRegion()) + .departureCity(departureResponse.getCity()) + .departureTown(departureResponse.getTown()) + .departureDetail(departureResponse.getDetail()) + .departureName(departureResponse.getName()) + .distance(requestDto.getDistance()) + .image(image) + .path(path) + .build(); + + Course saved = courseRepository.save(course); + user.updateCreatedCourse(); + userStampService.createStampByUser(user, StampType.c); + + return CourseCreateResponseDto.of(saved.getId(), saved.getCreatedAt()); + } + @Transactional(readOnly = true) public CourseGetByUserResponseDto getCourseByUser(Long userId) { RunnectUser user = userRepository.findById(userId) From e0b20ac752b2437c40d6bc5a629bee75c51bb4c7 Mon Sep 17 00:00:00 2001 From: sunny Date: Mon, 11 Dec 2023 18:47:54 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20request=20dto=EC=99=80=20request=20?= =?UTF-8?q?image=EB=A5=BC=20=EB=B6=84=EB=A6=AC=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/controller/CourseController.java | 22 +++++-------------- .../dto/request/CourseCreateRequestDtoV2.java | 7 ++---- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/runnect/server/course/controller/CourseController.java b/src/main/java/org/runnect/server/course/controller/CourseController.java index 1e81217..8272c70 100644 --- a/src/main/java/org/runnect/server/course/controller/CourseController.java +++ b/src/main/java/org/runnect/server/course/controller/CourseController.java @@ -30,8 +30,10 @@ 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.RequestPart; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; @Slf4j @RestController @@ -64,32 +66,20 @@ public ApiResponseDto createCourse( courseService.createCourse(userId, courseCreateRequestDto, imageUrl)); } - @PostMapping(value = "/v2", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @PostMapping(value = "/v2", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.CREATED) public ApiResponseDto createCourseV2( @UserId Long userId, - @ModelAttribute @Valid final CourseCreateRequestDtoV2 courseCreateRequestDto, - BindingResult bindingResult + @RequestPart @Valid final CourseCreateRequestDtoV2 courseCreateRequestDto, + @RequestPart final MultipartFile image ) { log.info("create course 요청 값"); log.info("departureAddress : " + courseCreateRequestDto.getDepartureAddress()); log.info("departureName : " + courseCreateRequestDto.getDepartureName()); log.info("path : " + courseCreateRequestDto.getPath()); log.info("distance : " + courseCreateRequestDto.getDistance().toString()); - log.info("image : " + courseCreateRequestDto.getImage().toString()); - if (bindingResult.hasErrors()) { - -// List as = new ArrayList<>(); -// as.add(23.0); -// as.add(11.3); -// List> asd = new ArrayList<>(); -// asd.add(as); -// System.out.println(asd.toString()); - throw new BadRequestException(ErrorStatus.REQUEST_VALIDATION_EXCEPTION, - bindingResult.getFieldError().getField() + " 필드가 입력되지 않았습니다."); - } - String imageUrl = s3Service.uploadImage(courseCreateRequestDto.getImage(), "course"); + String imageUrl = s3Service.uploadImage(image, "course"); return ApiResponseDto.success(SuccessStatus.CREATE_COURSE_SUCCESS, courseService.createCourseV2(userId, courseCreateRequestDto, imageUrl)); } diff --git a/src/main/java/org/runnect/server/course/dto/request/CourseCreateRequestDtoV2.java b/src/main/java/org/runnect/server/course/dto/request/CourseCreateRequestDtoV2.java index ba9d797..9e7e128 100644 --- a/src/main/java/org/runnect/server/course/dto/request/CourseCreateRequestDtoV2.java +++ b/src/main/java/org/runnect/server/course/dto/request/CourseCreateRequestDtoV2.java @@ -1,5 +1,6 @@ package org.runnect.server.course.dto.request; +import java.io.Serializable; import java.util.List; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -8,12 +9,11 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.runnect.server.common.module.convert.CoordinateDto; -import org.springframework.web.multipart.MultipartFile; @Getter @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PRIVATE) -public class CourseCreateRequestDtoV2 { +public class CourseCreateRequestDtoV2 implements Serializable { @NotNull(message = "path는 필수 입력 항목입니다.") private List path; @@ -21,9 +21,6 @@ public class CourseCreateRequestDtoV2 { @NotBlank(message = "title은 필수 입력 항목입니다.") private String title; - @NotNull(message = "image는 필수 입력 항목입니다.") - private MultipartFile image; - @NotNull(message = "distance는 필수 입력 항목입니다.") private Float distance;