diff --git a/src/main/java/jombi/freemates/controller/BookmarkController.java b/src/main/java/jombi/freemates/controller/BookmarkController.java index 0f983ee..2359610 100644 --- a/src/main/java/jombi/freemates/controller/BookmarkController.java +++ b/src/main/java/jombi/freemates/controller/BookmarkController.java @@ -250,4 +250,25 @@ public ResponseEntity likeBookmark( return ResponseEntity.ok().build(); // 혹은 204 No Content } + @PostMapping(value ="/update/{bookmarkId}", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity updateBookmark( + @AuthenticationPrincipal CustomUserDetails customUserDetails, + @PathVariable("bookmarkId") UUID bookmarkId, + @RequestParam String title, + @RequestParam String description, + @RequestParam PinColor pinColor, + @RequestParam Visibility visibility, + @RequestParam(value = "image", required = false) MultipartFile image + ) { + BookmarkRequest req = BookmarkRequest.builder() + .title(title) + .description(description) + .pinColor(pinColor) + .visibility(visibility) + .build(); + bookmarkService.updateBookmark(customUserDetails, bookmarkId, req, image); + return ResponseEntity.ok().build(); + } + } diff --git a/src/main/java/jombi/freemates/controller/CourseController.java b/src/main/java/jombi/freemates/controller/CourseController.java index ab80641..f0787de 100644 --- a/src/main/java/jombi/freemates/controller/CourseController.java +++ b/src/main/java/jombi/freemates/controller/CourseController.java @@ -219,7 +219,33 @@ public ResponseEntity likeCourse( courseService.likeCourse(customUserDetails, courseId); return ResponseEntity.ok().build(); } + /** + * 코스 수정 + */ + @PostMapping(value ="/update/{courseId}", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity updateCourse( + @AuthenticationPrincipal CustomUserDetails user, + @PathVariable("courseId") UUID courseId, + @RequestParam("title") String title, + @RequestParam("description") String description, + @RequestParam("freeTime") Integer freeTime, + @RequestParam("visibility") Visibility visibility, + // placeIds를 여러 개 RquestParam으로 받을 수도 있고, 한 문자열(콤마 구분)로 받을 수도 있음 + @RequestParam("placeIds") List placeIds, + @RequestParam(value = "image", required = false) MultipartFile image + ) { + CourseRequest req = CourseRequest.builder() + .title(title) + .description(description) + .freeTime(freeTime) + .visibility(visibility) + .placeIds(placeIds) + .build(); + courseService.updateCourse(user, courseId, req, image); + return ResponseEntity.ok().build(); + } diff --git a/src/main/java/jombi/freemates/repository/CoursePlaceRepository.java b/src/main/java/jombi/freemates/repository/CoursePlaceRepository.java index dee575f..7dec9b2 100644 --- a/src/main/java/jombi/freemates/repository/CoursePlaceRepository.java +++ b/src/main/java/jombi/freemates/repository/CoursePlaceRepository.java @@ -1,10 +1,11 @@ package jombi.freemates.repository; +import jombi.freemates.model.postgres.Course; import jombi.freemates.model.postgres.CoursePlace; import jombi.freemates.model.postgres.id.CoursePlaceId; import org.springframework.data.jpa.repository.JpaRepository; public interface CoursePlaceRepository extends JpaRepository { - + void deleteAllByCourse(Course course); } diff --git a/src/main/java/jombi/freemates/service/BookmarkService.java b/src/main/java/jombi/freemates/service/BookmarkService.java index 9a18a29..8860b5b 100644 --- a/src/main/java/jombi/freemates/service/BookmarkService.java +++ b/src/main/java/jombi/freemates/service/BookmarkService.java @@ -188,6 +188,46 @@ public void addPlaceToBookmark( bookmarkPlaceRepository.save(bp); } + @Transactional + public void updateBookmark( + CustomUserDetails customUserDetails, + UUID bookmarkId, + BookmarkRequest req, + MultipartFile image + ) { + // 파일이 있으면 저장 후 imageUrl 세팅, 없으면 imageUrl = null + String imageUrl = null; + if (image != null && !image.isEmpty()) { + imageUrl = storage.storeImage(image); + } + + // Member 조회 + Member member = customUserDetails.getMember(); + + // 기존 북마크 조회 + Bookmark bookmark = bookmarkRepository.findById(bookmarkId) + .orElseThrow(() -> new CustomException(ErrorCode.BOOKMARK_NOT_FOUND)); + + // 소유자 검사 + UUID ownerId = bookmark.getMember().getMemberId(); + UUID currentUserId = member.getMemberId(); + if (!ownerId.equals(currentUserId)) { + throw new CustomException(ErrorCode.UNAUTHORIZED); + } + + // 업데이트 + bookmark.setTitle(req.getTitle()); + bookmark.setDescription(req.getDescription()); + bookmark.setPinColor(req.getPinColor()); + bookmark.setVisibility(req.getVisibility()); + bookmark.setImageUrl(imageUrl); // 파일이 없으면 null, 있으면 저장된 경로 + + // DB 저장 + bookmarkRepository.save(bookmark); + } + /** + * Bookmark 엔티티를 BookmarkDto로 변환하는 공통 메서드 + */ public BookmarkDto convertToBookmarkDto(Bookmark bookmark) { diff --git a/src/main/java/jombi/freemates/service/CourseService.java b/src/main/java/jombi/freemates/service/CourseService.java index 5c79781..8378271 100644 --- a/src/main/java/jombi/freemates/service/CourseService.java +++ b/src/main/java/jombi/freemates/service/CourseService.java @@ -82,21 +82,7 @@ public CourseDto createCourse( .build() ); - List placeIds = req.getPlaceIds(); - List coursePlaceList = IntStream.range(0, placeIds.size()) - .mapToObj(idx -> { - UUID placeId = placeIds.get(idx); - Place place = placeRepository.findByPlaceId(placeId) - .orElseThrow(() -> new CustomException(ErrorCode.PLACE_NOT_FOUND)); - CoursePlaceId compositeId = new CoursePlaceId(course.getCourseId(), place.getPlaceId()); - return CoursePlace.builder() - .coursePlaceId(compositeId) - .course(course) - .place(place) - .sequence(idx + 1) - .build(); - }) - .collect(Collectors.toList()); + List coursePlaceList = createCoursePlaceList(course, req.getPlaceIds()); // CoursePlace 한꺼번에 저장 coursePlaceRepository.saveAll(coursePlaceList); @@ -173,6 +159,52 @@ public void likeCourse(CustomUserDetails customUser, UUID courseId) { courseRepository.save(course); } } + @Transactional + public void updateCourse( + CustomUserDetails customUser, + UUID courseId, + CourseRequest req, + MultipartFile image + + ) { + // 회원 확인 + Member member = customUser.getMember(); + if (member == null) { + throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); + } + + // 코스 조회 + Course course = courseRepository.findById(courseId) + .orElseThrow(() -> new CustomException(ErrorCode.COURSE_NOT_FOUND)); + UUID ownerId = course.getMember().getMemberId(); + UUID currentUserId = member.getMemberId(); + if (!ownerId.equals(currentUserId)) { + throw new CustomException(ErrorCode.UNAUTHORIZED); + } + + // 이미지 저장 + String imageUrl = null; + if (image != null && !image.isEmpty()) { + imageUrl = storage.storeImage(image); + course.setImageUrl(imageUrl); + } + + // 코스 정보 업데이트 + course.setTitle(req.getTitle()); + course.setDescription(req.getDescription()); + course.setFreeTime(req.getFreeTime()); + course.setVisibility(req.getVisibility()); + + // CoursePlace 업데이트 + List coursePlaceList = createCoursePlaceList(course, req.getPlaceIds()); + + // 기존 CoursePlace 삭제 후 새로 저장 + coursePlaceRepository.deleteAllByCourse(course); + coursePlaceRepository.saveAll(coursePlaceList); + + entityManager.flush(); + } + @@ -196,4 +228,22 @@ public CourseDto converToCourseDto(Course course) { .likeCount(course.getLikeCount()) .build(); } + + private List createCoursePlaceList(Course course, List placeIds) { + return IntStream.range(0, placeIds.size()) + .mapToObj(idx -> { + UUID placeId = placeIds.get(idx); + Place place = placeRepository.findByPlaceId(placeId) + .orElseThrow(() -> new CustomException(ErrorCode.PLACE_NOT_FOUND)); + CoursePlaceId compositeId = new CoursePlaceId(course.getCourseId(), place.getPlaceId()); + + return CoursePlace.builder() + .coursePlaceId(compositeId) + .course(course) + .place(place) + .sequence(idx + 1) + .build(); + }) + .collect(Collectors.toList()); + } }