From 8241bbd1377d076af00c946db1b07b4b94c18e91 Mon Sep 17 00:00:00 2001 From: yangjiae12 Date: Wed, 15 Jul 2026 17:27:05 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=EC=B6=94=EC=B2=9C=20=EC=BD=94?= =?UTF-8?q?=EC=8A=A4=20=EC=88=98=EC=A0=95=20API=20=EB=B0=8F=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20DTO=20=EA=B0=9C=EC=84=A0=20#52?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/controller/CourseController.java | 10 +-- .../course/dto/request/CourseReqDTO.java | 40 ++++++++++-- .../course/dto/response/CourseResDTO.java | 4 +- .../backend/domain/course/entity/Course.java | 28 ++++++++ .../repository/CourseHashtagRepository.java | 7 ++ .../repository/CourseItemRepository.java | 7 ++ .../domain/course/service/CourseService.java | 4 +- .../course/service/CourseServiceImpl.java | 65 +++++++++++++++++-- 8 files changed, 144 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java b/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java index c027ded..92219ad 100644 --- a/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java +++ b/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java @@ -46,22 +46,22 @@ public class CourseController { ) @Operation(summary = "추천 코스 등록", description = "추천 코스를 등록합니다.") @PostMapping - public ApiResponse createCourse( + public ApiResponse createCourse( @Valid @RequestBody CourseReqDTO.CourseCreateReq request ) { - CourseResDTO.CourseCreateRes response = courseService.createCourse(request); + CourseResDTO.CourseIdRes response = courseService.createCourse(request); return ApiResponse.onSuccess(SuccessCode.CREATED, response); } @Operation(summary = "추천 코스 수정", description = "추천 코스를 수정합니다.") @PatchMapping("/{courseId}") - public ApiResponse updateCourse( + public ApiResponse updateCourse( @Parameter(description = "코스 ID", example = "15") @PathVariable Long courseId, - @Valid @RequestBody CourseReqDTO.CourseCreateReq request + @Valid @RequestBody CourseReqDTO.CourseUpdateReq request ) { - CourseResDTO.CourseCreateRes response = courseService.updateCourse(courseId, request); + CourseResDTO.CourseIdRes response = courseService.updateCourse(courseId, request); return ApiResponse.onSuccess(SuccessCode.OK, response); } diff --git a/src/main/java/com/yeogido/backend/domain/course/dto/request/CourseReqDTO.java b/src/main/java/com/yeogido/backend/domain/course/dto/request/CourseReqDTO.java index fff4604..e49e0db 100644 --- a/src/main/java/com/yeogido/backend/domain/course/dto/request/CourseReqDTO.java +++ b/src/main/java/com/yeogido/backend/domain/course/dto/request/CourseReqDTO.java @@ -63,7 +63,40 @@ public record CourseCreateReq( @Valid @NotEmpty(message = "코스 구성 항목은 최소 1개 이상 필요합니다.") @Schema(description = "코스 구성 항목") - List courseItems + List<@NotNull(message = "코스 구성 항목이 올바르지 않습니다.") CourseItemCreateReq> courseItems + ) { } + + @Schema(name = "CourseUpdateRequest", description = "추천 코스 수정 요청") + public record CourseUpdateReq( + + @Schema(description = "코스 제목", example = "부산 야경 여행") + String title, + + @Schema(description = "코스 설명", example = "부산의 야경과 축제를 함께 즐길 수 있는 코스입니다.") + String description, + + @Schema(description = "여행 기간", example = "DAY_TRIP") + DurationType durationType, + + @Schema(description = "이동 수단", example = "CAR") + TransportType transportType, + + @Schema(description = "동행 유형", example = "FRIEND") + CompanionType companionType, + + @Schema(description = "대표 이미지 S3 key", example = "courses/thumbnail/abcd1234.jpg") + String thumbnailKey, + + @Schema(description = "해시태그 ID 목록", example = "[1, 3, 5]") + @Size( + max = 5, + message = "해시태그는 5개 이하로 선택할 수 있습니다." + ) + List<@NotNull(message = "유효하지 않은 해시태그입니다.") Long> hashtagIds, + + @Valid + @Schema(description = "코스 구성 항목") + List<@NotNull(message = "코스 구성 항목이 올바르지 않습니다.") CourseItemCreateReq> courseItems ) { } @Schema(name = "CourseItemCreateRequest", description = "추천 코스 구성 항목 등록 요청") @@ -74,12 +107,9 @@ public record CourseItemCreateReq( Integer order, @NotNull(message = "코스 항목 타입은 필수입니다") - @Schema(description = "코스 항목 타입. PLACE인 경우 placeId와 imageKey를 사용하고, CONTENT인 경우 contentId를 사용합니다.", example = "PLACE") + @Schema(description = "PLACE인 경우 externalPlaceId, categoryGroupCode, name, roadAddress(또는 lotAddress), latitude, longitude, imageKey를 사용하고, CONTENT인 경우 contentId를 사용합니다.", example = "PLACE") CourseItemType type, - @Schema(description = "장소 ID. type=PLACE인 경우 사용합니다.", example = "1") - Long placeId, - @Schema(description = "콘텐츠 ID. type=CONTENT인 경우 사용합니다.", example = "10") Long contentId, diff --git a/src/main/java/com/yeogido/backend/domain/course/dto/response/CourseResDTO.java b/src/main/java/com/yeogido/backend/domain/course/dto/response/CourseResDTO.java index 177d549..3b39efa 100644 --- a/src/main/java/com/yeogido/backend/domain/course/dto/response/CourseResDTO.java +++ b/src/main/java/com/yeogido/backend/domain/course/dto/response/CourseResDTO.java @@ -13,8 +13,8 @@ public class CourseResDTO { - @Schema(name = "CourseCreateResponse", description = "추천 코스 등록 응답") - public record CourseCreateRes( + @Schema(name = "CourseIdResponse", description = "추천 코스 ID 응답") + public record CourseIdRes( @Schema(description = "코스 ID", example = "15") Long courseId diff --git a/src/main/java/com/yeogido/backend/domain/course/entity/Course.java b/src/main/java/com/yeogido/backend/domain/course/entity/Course.java index fedb9e0..70b3021 100644 --- a/src/main/java/com/yeogido/backend/domain/course/entity/Course.java +++ b/src/main/java/com/yeogido/backend/domain/course/entity/Course.java @@ -76,4 +76,32 @@ public class Course extends BaseEntity { @Column(name = "deleted_at") private LocalDateTime deletedAt; + + public void update( + String title, + String description, + DurationType durationType, + TransportType transportType, + CompanionType companionType, + String thumbnailKey + ) { + if (title != null) { + this.title = title; + } + if (description != null) { + this.description = description; + } + if (durationType != null) { + this.durationType = durationType; + } + if (transportType != null) { + this.transportType = transportType; + } + if (companionType != null) { + this.companionType = companionType; + } + if (thumbnailKey != null) { + this.thumbnailKey = thumbnailKey; + } + } } diff --git a/src/main/java/com/yeogido/backend/domain/course/repository/CourseHashtagRepository.java b/src/main/java/com/yeogido/backend/domain/course/repository/CourseHashtagRepository.java index 535e097..372c7d0 100644 --- a/src/main/java/com/yeogido/backend/domain/course/repository/CourseHashtagRepository.java +++ b/src/main/java/com/yeogido/backend/domain/course/repository/CourseHashtagRepository.java @@ -2,6 +2,13 @@ import com.yeogido.backend.domain.course.entity.CourseHashtag; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface CourseHashtagRepository extends JpaRepository { + + @Modifying + @Query("delete from CourseHashtag ch where ch.course.id = :courseId") + void deleteAllByCourseId(@Param("courseId") Long courseId); } diff --git a/src/main/java/com/yeogido/backend/domain/course/repository/CourseItemRepository.java b/src/main/java/com/yeogido/backend/domain/course/repository/CourseItemRepository.java index ab60b8f..e5fd390 100644 --- a/src/main/java/com/yeogido/backend/domain/course/repository/CourseItemRepository.java +++ b/src/main/java/com/yeogido/backend/domain/course/repository/CourseItemRepository.java @@ -2,6 +2,13 @@ import com.yeogido.backend.domain.course.entity.CourseItem; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface CourseItemRepository extends JpaRepository { + + @Modifying + @Query("delete from CourseItem ci where ci.course.id = :courseId") + void deleteAllByCourseId(@Param("courseId") Long courseId); } diff --git a/src/main/java/com/yeogido/backend/domain/course/service/CourseService.java b/src/main/java/com/yeogido/backend/domain/course/service/CourseService.java index 39e5860..79364f8 100644 --- a/src/main/java/com/yeogido/backend/domain/course/service/CourseService.java +++ b/src/main/java/com/yeogido/backend/domain/course/service/CourseService.java @@ -8,9 +8,9 @@ public interface CourseService { - CourseResDTO.CourseCreateRes createCourse(CourseReqDTO.CourseCreateReq request); + CourseResDTO.CourseIdRes createCourse(CourseReqDTO.CourseCreateReq request); - CourseResDTO.CourseCreateRes updateCourse(Long courseId, CourseReqDTO.CourseCreateReq request); + CourseResDTO.CourseIdRes updateCourse(Long courseId, CourseReqDTO.CourseUpdateReq request); CursorResponse getCourses(CourseReqDTO.CourseListReq request); diff --git a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java index b30b0be..1e83f40 100644 --- a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java +++ b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java @@ -31,7 +31,6 @@ import com.yeogido.backend.domain.region.entity.Region; import com.yeogido.backend.domain.region.exception.RegionErrorCode; import com.yeogido.backend.domain.region.repository.RegionRepository; -import com.yeogido.backend.domain.region.service.RegionService; import com.yeogido.backend.domain.user.entity.User; import com.yeogido.backend.domain.user.repository.UserRepository; import com.yeogido.backend.global.common.response.CursorResponse; @@ -69,7 +68,7 @@ public class CourseServiceImpl implements CourseService { @Override @Transactional - public CourseResDTO.CourseCreateRes createCourse(CourseReqDTO.CourseCreateReq request) { + public CourseResDTO.CourseIdRes createCourse(CourseReqDTO.CourseCreateReq request) { validateCourseCreateRequest(request); User user = getCurrentUser(); @@ -79,13 +78,36 @@ public CourseResDTO.CourseCreateRes createCourse(CourseReqDTO.CourseCreateReq re saveCourseHashtags(course, request.hashtagIds()); saveCourseItems(course, request.courseItems()); - return new CourseResDTO.CourseCreateRes(course.getId()); + return new CourseResDTO.CourseIdRes(course.getId()); } @Override - public CourseResDTO.CourseCreateRes updateCourse(Long courseId, CourseReqDTO.CourseCreateReq request) { - // TODO: 추천 코스 수정 로직 구현 - return new CourseResDTO.CourseCreateRes(15L); + @Transactional + public CourseResDTO.CourseIdRes updateCourse(Long courseId, CourseReqDTO.CourseUpdateReq request) { + Course course = getActiveCourse(courseId); + User user = getCurrentUser(); + + validateCourseAuthor(course, user); + validateCourseUpdateRequest(request); + + course.update( + request.title(), + request.description(), + request.durationType(), + request.transportType(), + request.companionType(), + request.thumbnailKey() + ); + + if (request.hashtagIds() != null) { + replaceCourseHashtags(course, request.hashtagIds()); + } + + if (request.courseItems() != null) { + replaceCourseItems(course, request.courseItems()); + } + + return new CourseResDTO.CourseIdRes(course.getId()); } @Override @@ -226,11 +248,27 @@ private Region getRegion(Long regionId) { .orElseThrow(() -> new GeneralException(RegionErrorCode.REGION_NOT_FOUND)); } + private void validateCourseAuthor(Course course, User user) { + if (course.getUser() == null || !Objects.equals(course.getUser().getId(), user.getId())) { + throw new GeneralException(GeneralErrorCode.FORBIDDEN); + } + } + private void validateCourseCreateRequest(CourseReqDTO.CourseCreateReq request) { validateHashtags(request.hashtagIds()); validateCourseItems(request.courseItems()); } + private void validateCourseUpdateRequest(CourseReqDTO.CourseUpdateReq request) { + if (request.hashtagIds() != null) { + validateHashtags(request.hashtagIds()); + } + + if (request.courseItems() != null) { + validateCourseItems(request.courseItems()); + } + } + private void validateHashtags(List hashtagIds) { if (new HashSet<>(hashtagIds).size() != hashtagIds.size()) { throw new GeneralException(CourseErrorCode.DUPLICATE_HASHTAG); @@ -279,7 +317,6 @@ private void validatePlaceItem(CourseReqDTO.CourseItemCreateReq item) { private void validateContentItem(CourseReqDTO.CourseItemCreateReq item) { if (item.contentId() == null - || item.placeId() != null || StringUtils.hasText(item.externalPlaceId()) || StringUtils.hasText(item.categoryGroupCode()) || StringUtils.hasText(item.name()) @@ -307,6 +344,13 @@ private void saveCourseHashtags(Course course, List hashtagIds) { courseHashtagRepository.saveAll(courseHashtags); } + private void replaceCourseHashtags(Course course, List hashtagIds) { + courseHashtagRepository.deleteAllByCourseId(course.getId()); + courseHashtagRepository.flush(); + + saveCourseHashtags(course, hashtagIds); + } + private void saveCourseItems(Course course, List courseItems) { Map placeMap = placeService.getPlaceMap(courseItems); Map contentMap = getContentMap(courseItems); @@ -329,6 +373,13 @@ private void saveCourseItems(Course course, List courseItems) { + courseItemRepository.deleteAllByCourseId(course.getId()); + courseItemRepository.flush(); + + saveCourseItems(course, courseItems); + } + private Map getContentMap(List courseItems) { Set contentIds = courseItems.stream() .filter(item -> item.type() == CourseItemType.CONTENT) From 6b0a35970b39491b844a7c1cea6d2af5bae3c245 Mon Sep 17 00:00:00 2001 From: yangjiae12 Date: Wed, 15 Jul 2026 17:29:28 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EC=B6=94=EC=B2=9C=20=EC=BD=94?= =?UTF-8?q?=EC=8A=A4=20=EC=88=98=EC=A0=95=20=EA=B6=8C=ED=95=9C=20=EC=A0=95?= =?UTF-8?q?=EC=B1=85=20=EC=A0=81=EC=9A=A9=20#52?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/service/CourseServiceImpl.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java index 1e83f40..0ef1cfc 100644 --- a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java +++ b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java @@ -32,6 +32,7 @@ import com.yeogido.backend.domain.region.exception.RegionErrorCode; import com.yeogido.backend.domain.region.repository.RegionRepository; import com.yeogido.backend.domain.user.entity.User; +import com.yeogido.backend.domain.user.enums.UserRole; import com.yeogido.backend.domain.user.repository.UserRepository; import com.yeogido.backend.global.common.response.CursorResponse; import com.yeogido.backend.global.exception.GeneralErrorCode; @@ -87,7 +88,7 @@ public CourseResDTO.CourseIdRes updateCourse(Long courseId, CourseReqDTO.CourseU Course course = getActiveCourse(courseId); User user = getCurrentUser(); - validateCourseAuthor(course, user); + validateCourseAuthority(course, user); validateCourseUpdateRequest(request); course.update( @@ -248,9 +249,22 @@ private Region getRegion(Long regionId) { .orElseThrow(() -> new GeneralException(RegionErrorCode.REGION_NOT_FOUND)); } - private void validateCourseAuthor(Course course, User user) { - if (course.getUser() == null || !Objects.equals(course.getUser().getId(), user.getId())) { - throw new GeneralException(GeneralErrorCode.FORBIDDEN); + private void validateCourseAuthority(Course course, User user) { + switch (course.getCourseType()) { + case OFFICIAL -> { + if (user.getRole() != UserRole.ADMIN) { + throw new GeneralException(GeneralErrorCode.FORBIDDEN); + } + } + + case LOCAL -> { + if (course.getUser() == null || + !Objects.equals(course.getUser().getId(), user.getId())) { + throw new GeneralException(GeneralErrorCode.FORBIDDEN); + } + } + + default -> throw new GeneralException(GeneralErrorCode.FORBIDDEN); } } From 6a9eb6195887d4ce389f1623e82f86e048aeeb40 Mon Sep 17 00:00:00 2001 From: yangjiae12 Date: Wed, 15 Jul 2026 22:27:17 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EC=B6=94=EC=B2=9C=20=EC=BD=94?= =?UTF-8?q?=EC=8A=A4=20=EC=82=AD=EC=A0=9C=20API=20=EA=B5=AC=ED=98=84=20#52?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/course/controller/CourseController.java | 11 +++++++++++ .../yeogido/backend/domain/course/entity/Course.java | 4 ++++ .../backend/domain/course/service/CourseService.java | 2 ++ .../domain/course/service/CourseServiceImpl.java | 11 +++++++++++ 4 files changed, 28 insertions(+) diff --git a/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java b/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java index 92219ad..e7a8348 100644 --- a/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java +++ b/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java @@ -66,6 +66,17 @@ public ApiResponse updateCourse( return ApiResponse.onSuccess(SuccessCode.OK, response); } + @Operation(summary = "추천 코스 삭제", description = "추천 코스를 삭제합니다.") + @DeleteMapping("/{courseId}") + public ApiResponse deleteCourse( + @Parameter(description = "코스 ID", example = "15") + @PathVariable Long courseId + ) { + courseService.deleteCourse(courseId); + + return ApiResponse.onSuccess(SuccessCode.NO_CONTENT); + } + @Operation(summary = "추천 코스 목록 조회", description = "추천 코스 목록을 조회합니다.") @GetMapping public ApiResponse> getCourses( diff --git a/src/main/java/com/yeogido/backend/domain/course/entity/Course.java b/src/main/java/com/yeogido/backend/domain/course/entity/Course.java index 70b3021..2bb3832 100644 --- a/src/main/java/com/yeogido/backend/domain/course/entity/Course.java +++ b/src/main/java/com/yeogido/backend/domain/course/entity/Course.java @@ -104,4 +104,8 @@ public void update( this.thumbnailKey = thumbnailKey; } } + + public void delete() { + this.deletedAt = LocalDateTime.now(); + } } diff --git a/src/main/java/com/yeogido/backend/domain/course/service/CourseService.java b/src/main/java/com/yeogido/backend/domain/course/service/CourseService.java index 79364f8..0d28179 100644 --- a/src/main/java/com/yeogido/backend/domain/course/service/CourseService.java +++ b/src/main/java/com/yeogido/backend/domain/course/service/CourseService.java @@ -12,6 +12,8 @@ public interface CourseService { CourseResDTO.CourseIdRes updateCourse(Long courseId, CourseReqDTO.CourseUpdateReq request); + void deleteCourse(Long courseId); + CursorResponse getCourses(CourseReqDTO.CourseListReq request); List getPopularCourses(CourseReqDTO.CoursePopularReq request); diff --git a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java index 0ef1cfc..db08664 100644 --- a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java +++ b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java @@ -111,6 +111,17 @@ public CourseResDTO.CourseIdRes updateCourse(Long courseId, CourseReqDTO.CourseU return new CourseResDTO.CourseIdRes(course.getId()); } + @Override + @Transactional + public void deleteCourse(Long courseId) { + Course course = getActiveCourse(courseId); + User user = getCurrentUser(); + + validateCourseAuthority(course, user); + + course.delete(); + } + @Override public CursorResponse getCourses(CourseReqDTO.CourseListReq request) { // TODO: 추천 코스 조회 로직 구현 From ec4b4726dc1f577550db14a4f565b9593a3650e5 Mon Sep 17 00:00:00 2001 From: yangjiae12 Date: Thu, 16 Jul 2026 01:48:17 +0900 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20=EC=B6=94=EC=B2=9C=20=EC=BD=94?= =?UTF-8?q?=EC=8A=A4=20=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20#52?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/course/service/CourseServiceImpl.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java index db08664..6be0722 100644 --- a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java +++ b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java @@ -371,8 +371,6 @@ private void saveCourseHashtags(Course course, List hashtagIds) { private void replaceCourseHashtags(Course course, List hashtagIds) { courseHashtagRepository.deleteAllByCourseId(course.getId()); - courseHashtagRepository.flush(); - saveCourseHashtags(course, hashtagIds); } @@ -400,8 +398,6 @@ private void saveCourseItems(Course course, List courseItems) { courseItemRepository.deleteAllByCourseId(course.getId()); - courseItemRepository.flush(); - saveCourseItems(course, courseItems); } From f9d7d69303613e20eec8ecdd43686b8a0a026be8 Mon Sep 17 00:00:00 2001 From: yangjiae12 Date: Thu, 16 Jul 2026 01:48:28 +0900 Subject: [PATCH 5/6] =?UTF-8?q?docs:=20=EC=B6=94=EC=B2=9C=20=EC=BD=94?= =?UTF-8?q?=EC=8A=A4=20=EC=88=98=EC=A0=95=20API=20=EC=98=88=EC=8B=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20#52?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/controller/CourseController.java | 11 ++++- .../global/swagger/SwaggerExamples.java | 40 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java b/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java index e7a8348..3398a81 100644 --- a/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java +++ b/src/main/java/com/yeogido/backend/domain/course/controller/CourseController.java @@ -54,6 +54,15 @@ public ApiResponse createCourse( return ApiResponse.onSuccess(SuccessCode.CREATED, response); } + @io.swagger.v3.oas.annotations.parameters.RequestBody( + required = true, + content = @Content( + examples = @ExampleObject( + name = "추천 코스 수정 예시", + value = SwaggerExamples.COURSE_UPDATE + ) + ) + ) @Operation(summary = "추천 코스 수정", description = "추천 코스를 수정합니다.") @PatchMapping("/{courseId}") public ApiResponse updateCourse( @@ -74,7 +83,7 @@ public ApiResponse deleteCourse( ) { courseService.deleteCourse(courseId); - return ApiResponse.onSuccess(SuccessCode.NO_CONTENT); + return ApiResponse.onSuccess(SuccessCode.OK); } @Operation(summary = "추천 코스 목록 조회", description = "추천 코스 목록을 조회합니다.") diff --git a/src/main/java/com/yeogido/backend/global/swagger/SwaggerExamples.java b/src/main/java/com/yeogido/backend/global/swagger/SwaggerExamples.java index cc04cab..f530723 100644 --- a/src/main/java/com/yeogido/backend/global/swagger/SwaggerExamples.java +++ b/src/main/java/com/yeogido/backend/global/swagger/SwaggerExamples.java @@ -36,4 +36,44 @@ private SwaggerExamples() { ] } """; + + public static final String COURSE_UPDATE = """ + { + "title": "부산 감성 여행 코스", + "description": "광안리와 해운대를 중심으로 감성 카페와 야경을 즐기는 코스입니다.", + "thumbnailKey": "courses/thumbnail/busan-emotion.jpg", + "hashtagIds": [2, 4, 6], + "courseItems": [ + { + "order": 1, + "type": "PLACE", + "externalPlaceId": "654321", + "categoryGroupCode": "CE7", + "name": "흰여울문화마을", + "roadAddress": "부산 영도구 흰여울길 379", + "lotAddress": "부산 영도구 영선동4가", + "latitude": 35.078961, + "longitude": 129.045771, + "imageKey": "courses/place/huinnyeoul.jpg" + }, + { + "order": 2, + "type": "CONTENT", + "contentId": 8 + }, + { + "order": 3, + "type": "PLACE", + "externalPlaceId": "987654", + "categoryGroupCode": "AT4", + "name": "해운대해수욕장", + "roadAddress": "부산 해운대구 해운대해변로 264", + "lotAddress": "부산 해운대구 우동", + "latitude": 35.158698, + "longitude": 129.160384, + "imageKey": null + } + ] + } + """; } \ No newline at end of file From 64638db8c792a29d8e2b3b98f30f13fdd608363e Mon Sep 17 00:00:00 2001 From: yangjiae12 Date: Thu, 16 Jul 2026 01:55:52 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20=EC=B6=94=EC=B2=9C=20=EC=BD=94?= =?UTF-8?q?=EC=8A=A4=20=EC=97=AC=ED=96=89=20=EC=9B=94=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20#52?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/converter/CourseConverter.java | 2 ++ .../course/dto/request/CourseReqDTO.java | 24 +++++++++++++++++++ .../backend/domain/course/entity/Course.java | 8 +++++++ .../course/service/CourseServiceImpl.java | 2 ++ .../global/swagger/SwaggerExamples.java | 6 ++++- 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/yeogido/backend/domain/course/converter/CourseConverter.java b/src/main/java/com/yeogido/backend/domain/course/converter/CourseConverter.java index 944ec75..c864c8f 100644 --- a/src/main/java/com/yeogido/backend/domain/course/converter/CourseConverter.java +++ b/src/main/java/com/yeogido/backend/domain/course/converter/CourseConverter.java @@ -29,6 +29,8 @@ public static Course toCourse(CourseReqDTO.CourseCreateReq request, User user, R .durationType(request.durationType()) .transportType(request.transportType()) .companionType(request.companionType()) + .monthStart(request.monthStart()) + .monthEnd(request.monthEnd()) .thumbnailKey(request.thumbnailKey()) .build(); } diff --git a/src/main/java/com/yeogido/backend/domain/course/dto/request/CourseReqDTO.java b/src/main/java/com/yeogido/backend/domain/course/dto/request/CourseReqDTO.java index e49e0db..5caeefb 100644 --- a/src/main/java/com/yeogido/backend/domain/course/dto/request/CourseReqDTO.java +++ b/src/main/java/com/yeogido/backend/domain/course/dto/request/CourseReqDTO.java @@ -10,6 +10,8 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.DecimalMax; import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -47,6 +49,18 @@ public record CourseCreateReq( @Schema(description = "동행 유형", example = "FRIEND") CompanionType companionType, + @NotNull(message = "여행 시작 월은 필수입니다") + @Min(value = 1, message = "여행 시작 월은 1 이상이어야 합니다") + @Max(value = 12, message = "여행 시작 월은 12 이하이어야 합니다") + @Schema(description = "여행 시작 월", example = "4") + Integer monthStart, + + @NotNull(message = "여행 종료 월은 필수입니다") + @Min(value = 1, message = "여행 종료 월은 1 이상이어야 합니다") + @Max(value = 12, message = "여행 종료 월은 12 이하이어야 합니다") + @Schema(description = "여행 종료 월", example = "10") + Integer monthEnd, + @Schema(description = "대표 이미지 S3 key", example = "courses/thumbnail/abcd1234.jpg") @NotBlank(message = "대표 이미지는 필수입니다") String thumbnailKey, @@ -84,6 +98,16 @@ public record CourseUpdateReq( @Schema(description = "동행 유형", example = "FRIEND") CompanionType companionType, + @Min(value = 1, message = "여행 시작 월은 1 이상이어야 합니다") + @Max(value = 12, message = "여행 시작 월은 12 이하이어야 합니다") + @Schema(description = "여행 시작 월", example = "5") + Integer monthStart, + + @Min(value = 1, message = "여행 종료 월은 1 이상이어야 합니다") + @Max(value = 12, message = "여행 종료 월은 12 이하이어야 합니다") + @Schema(description = "여행 종료 월", example = "9") + Integer monthEnd, + @Schema(description = "대표 이미지 S3 key", example = "courses/thumbnail/abcd1234.jpg") String thumbnailKey, diff --git a/src/main/java/com/yeogido/backend/domain/course/entity/Course.java b/src/main/java/com/yeogido/backend/domain/course/entity/Course.java index 2bb3832..526b1ea 100644 --- a/src/main/java/com/yeogido/backend/domain/course/entity/Course.java +++ b/src/main/java/com/yeogido/backend/domain/course/entity/Course.java @@ -83,6 +83,8 @@ public void update( DurationType durationType, TransportType transportType, CompanionType companionType, + Integer monthStart, + Integer monthEnd, String thumbnailKey ) { if (title != null) { @@ -100,6 +102,12 @@ public void update( if (companionType != null) { this.companionType = companionType; } + if (monthStart != null) { + this.monthStart = monthStart; + } + if (monthEnd != null) { + this.monthEnd = monthEnd; + } if (thumbnailKey != null) { this.thumbnailKey = thumbnailKey; } diff --git a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java index 6be0722..65e4bfc 100644 --- a/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java +++ b/src/main/java/com/yeogido/backend/domain/course/service/CourseServiceImpl.java @@ -97,6 +97,8 @@ public CourseResDTO.CourseIdRes updateCourse(Long courseId, CourseReqDTO.CourseU request.durationType(), request.transportType(), request.companionType(), + request.monthStart(), + request.monthEnd(), request.thumbnailKey() ); diff --git a/src/main/java/com/yeogido/backend/global/swagger/SwaggerExamples.java b/src/main/java/com/yeogido/backend/global/swagger/SwaggerExamples.java index f530723..422c31a 100644 --- a/src/main/java/com/yeogido/backend/global/swagger/SwaggerExamples.java +++ b/src/main/java/com/yeogido/backend/global/swagger/SwaggerExamples.java @@ -13,6 +13,8 @@ private SwaggerExamples() { "durationType": "DAY_TRIP", "transportType": "CAR", "companionType": "FRIEND", + "monthStart": 4, + "monthEnd": 10, "thumbnailKey": "courses/thumbnail/abcd1234.jpg", "hashtagIds": [1, 3], "courseItems": [ @@ -41,6 +43,8 @@ private SwaggerExamples() { { "title": "부산 감성 여행 코스", "description": "광안리와 해운대를 중심으로 감성 카페와 야경을 즐기는 코스입니다.", + "monthStart": 5, + "monthEnd": 9, "thumbnailKey": "courses/thumbnail/busan-emotion.jpg", "hashtagIds": [2, 4, 6], "courseItems": [ @@ -76,4 +80,4 @@ private SwaggerExamples() { ] } """; -} \ No newline at end of file +}