From bf5613270759db597b77ff23082acec8503b85af Mon Sep 17 00:00:00 2001 From: lulyulalla Date: Mon, 9 Jun 2025 14:41:31 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=98=A4=EC=B0=A8=EB=B2=94=EC=9C=84=20?= =?UTF-8?q?=EC=86=8C=EC=88=98=EC=A0=90=204=EC=9E=90=EB=A6=AC=EA=B9=8C?= =?UTF-8?q?=EC=A7=80=20:=20refactor=20:=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20https://github.com/freeMates/FreeMates=5FBackend/is?= =?UTF-8?q?sues/124?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BookmarkController.java | 22 +++++++ .../controller/CourseController.java | 27 +++++++++ .../repository/CoursePlaceRepository.java | 3 +- .../freemates/service/BookmarkService.java | 40 +++++++++++++ .../freemates/service/CourseService.java | 60 +++++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/main/java/jombi/freemates/controller/BookmarkController.java b/src/main/java/jombi/freemates/controller/BookmarkController.java index 0f983ee..d81a194 100644 --- a/src/main/java/jombi/freemates/controller/BookmarkController.java +++ b/src/main/java/jombi/freemates/controller/BookmarkController.java @@ -250,4 +250,26 @@ public ResponseEntity likeBookmark( return ResponseEntity.ok().build(); // 혹은 204 No Content } + @PostMapping(value ="/update/{bookmarkId}", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @ResponseStatus(HttpStatus.CREATED) + 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..c205dae 100644 --- a/src/main/java/jombi/freemates/controller/CourseController.java +++ b/src/main/java/jombi/freemates/controller/CourseController.java @@ -219,7 +219,34 @@ public ResponseEntity likeCourse( courseService.likeCourse(customUserDetails, courseId); return ResponseEntity.ok().build(); } + /** + * 코스 수정 + */ + @PostMapping(value ="/update/{courseId}", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @ResponseStatus(HttpStatus.CREATED) + 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..fdeea64 100644 --- a/src/main/java/jombi/freemates/service/CourseService.java +++ b/src/main/java/jombi/freemates/service/CourseService.java @@ -173,6 +173,66 @@ 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 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()); + + // 기존 CoursePlace 삭제 후 새로 저장 + coursePlaceRepository.deleteAllByCourse(course); + coursePlaceRepository.saveAll(coursePlaceList); + + entityManager.flush(); + } + From de106670e36bb9debafbefe3279b3314cc478de4 Mon Sep 17 00:00:00 2001 From: lulyulalla Date: Mon, 9 Jun 2025 14:52:18 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=98=A4=EC=B0=A8=EB=B2=94=EC=9C=84=20?= =?UTF-8?q?=EC=86=8C=EC=88=98=EC=A0=90=204=EC=9E=90=EB=A6=AC=EA=B9=8C?= =?UTF-8?q?=EC=A7=80=20:=20refactor=20:=20=EB=A7=A4=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20https://github.com/freeMates/FreeMates=5FB?= =?UTF-8?q?ackend/issues/124?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BookmarkController.java | 1 - .../controller/CourseController.java | 1 - .../freemates/service/CourseService.java | 50 ++++++++----------- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/src/main/java/jombi/freemates/controller/BookmarkController.java b/src/main/java/jombi/freemates/controller/BookmarkController.java index d81a194..2359610 100644 --- a/src/main/java/jombi/freemates/controller/BookmarkController.java +++ b/src/main/java/jombi/freemates/controller/BookmarkController.java @@ -252,7 +252,6 @@ public ResponseEntity likeBookmark( @PostMapping(value ="/update/{bookmarkId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ResponseStatus(HttpStatus.CREATED) public ResponseEntity updateBookmark( @AuthenticationPrincipal CustomUserDetails customUserDetails, @PathVariable("bookmarkId") UUID bookmarkId, diff --git a/src/main/java/jombi/freemates/controller/CourseController.java b/src/main/java/jombi/freemates/controller/CourseController.java index c205dae..f0787de 100644 --- a/src/main/java/jombi/freemates/controller/CourseController.java +++ b/src/main/java/jombi/freemates/controller/CourseController.java @@ -224,7 +224,6 @@ public ResponseEntity likeCourse( */ @PostMapping(value ="/update/{courseId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @ResponseStatus(HttpStatus.CREATED) public ResponseEntity updateCourse( @AuthenticationPrincipal CustomUserDetails user, @PathVariable("courseId") UUID courseId, diff --git a/src/main/java/jombi/freemates/service/CourseService.java b/src/main/java/jombi/freemates/service/CourseService.java index fdeea64..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); @@ -210,21 +196,7 @@ public void updateCourse( course.setVisibility(req.getVisibility()); // CoursePlace 업데이트 - 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.deleteAllByCourse(course); @@ -256,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()); + } }