diff --git a/src/main/java/com/potatocake/everymoment/controller/CommentController.java b/src/main/java/com/potatocake/everymoment/controller/CommentController.java new file mode 100644 index 0000000..f462e1d --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/controller/CommentController.java @@ -0,0 +1,51 @@ +package com.potatocake.everymoment.controller; + +import com.potatocake.everymoment.dto.SuccessResponse; +import com.potatocake.everymoment.dto.request.CommentRequest; +import com.potatocake.everymoment.security.MemberDetails; +import com.potatocake.everymoment.service.CommentService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/api/comments") +public class CommentController { + + private final CommentService commentService; + + //댓글 수정 + @PatchMapping("/{commentId}") + public ResponseEntity> updateComment( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long commentId, + @RequestBody CommentRequest commentRequest) { + Long memberId = memberDetails.getId(); + + commentService.updateComment(memberId, commentId, commentRequest); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); + } + + //댓글 삭제 + @DeleteMapping("/{commentId}") + public ResponseEntity> deleteComment( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long commentId) { + Long memberId = memberDetails.getId(); + + commentService.deleteComment(memberId, commentId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); + } +} diff --git a/src/main/java/com/potatocake/everymoment/controller/DiaryController.java b/src/main/java/com/potatocake/everymoment/controller/DiaryController.java index e149daa..66047a9 100644 --- a/src/main/java/com/potatocake/everymoment/controller/DiaryController.java +++ b/src/main/java/com/potatocake/everymoment/controller/DiaryController.java @@ -1,14 +1,19 @@ package com.potatocake.everymoment.controller; import com.potatocake.everymoment.dto.SuccessResponse; +import com.potatocake.everymoment.dto.request.CommentRequest; import com.potatocake.everymoment.dto.request.DiaryAutoCreateRequest; import com.potatocake.everymoment.dto.request.DiaryFilterRequest; import com.potatocake.everymoment.dto.request.DiaryManualCreateRequest; +import com.potatocake.everymoment.dto.response.CommentsResponse; import com.potatocake.everymoment.dto.response.FriendDiariesResponse; import com.potatocake.everymoment.dto.response.FriendDiaryResponse; +import com.potatocake.everymoment.dto.response.MemberDetailResponse; import com.potatocake.everymoment.dto.response.MyDiariesResponse; import com.potatocake.everymoment.dto.response.MyDiaryResponse; import com.potatocake.everymoment.dto.response.NotificationResponse; +import com.potatocake.everymoment.security.MemberDetails; +import com.potatocake.everymoment.service.CommentService; import com.potatocake.everymoment.service.DiaryService; import com.potatocake.everymoment.service.FriendDiaryService; import java.time.LocalDate; @@ -16,6 +21,7 @@ import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; @@ -33,36 +39,37 @@ public class DiaryController { private final DiaryService diaryService; private final FriendDiaryService friendDiaryService; + private final CommentService commentService; //자동 일기 작성 @PostMapping("/auto") public ResponseEntity> createDiaryAuto( + @AuthenticationPrincipal MemberDetails memberDetails, @RequestBody DiaryAutoCreateRequest diaryAutoCreateRequest) { - NotificationResponse notificationResponse = diaryService.createDiaryAuto(diaryAutoCreateRequest); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(notificationResponse) - .build(); - return ResponseEntity.ok(response); + Long memberId = memberDetails.getId(); + + NotificationResponse response = diaryService.createDiaryAuto(memberId, diaryAutoCreateRequest); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); } //수기 일기 작성 @PostMapping("/manual") public ResponseEntity> createDiaryManual( + @AuthenticationPrincipal MemberDetails memberDetails, @RequestBody DiaryManualCreateRequest diaryManualCreateRequest) { - diaryService.createDiaryManual(diaryManualCreateRequest); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(null) - .build(); - return ResponseEntity.ok(response); + Long memberId = memberDetails.getId(); + diaryService.createDiaryManual(memberId, diaryManualCreateRequest); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); } //내 일기 전체 조회(타임라인) @GetMapping("/my") public ResponseEntity> getMyDiaries( + @AuthenticationPrincipal MemberDetails memberDetails, @RequestParam(required = false) String keyword, @RequestParam(required = false) String emoji, @RequestParam(required = false) Long category, @@ -73,6 +80,7 @@ public ResponseEntity> getMyDiaries( @RequestParam(defaultValue = "0") int key, @RequestParam(defaultValue = "10") int size ) { + Long memberId = memberDetails.getId(); DiaryFilterRequest diaryFilterRequest = DiaryFilterRequest.builder() .keyword(keyword) .emoji(emoji) @@ -85,79 +93,82 @@ public ResponseEntity> getMyDiaries( .size(size) .build(); - MyDiariesResponse myDiariesResponse = diaryService.getMyDiaries(diaryFilterRequest); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(myDiariesResponse) - .build(); - return ResponseEntity.ok(response); + MyDiariesResponse response = diaryService.getMyDiaries(memberId, diaryFilterRequest); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); } //내 일기 상세 조회 - @GetMapping("/my/{id}") - public ResponseEntity> getMyDiary(@PathVariable Long id) { - MyDiaryResponse myDiaryResponse = diaryService.getMyDiary(id); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(myDiaryResponse) - .build(); - return ResponseEntity.ok(response); + @GetMapping("/my/{diaryId}") + public ResponseEntity> getMyDiary( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long diaryId) { + Long memberId = memberDetails.getId(); + + MyDiaryResponse response = diaryService.getMyDiary(memberId, diaryId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); } //일기 수정 - @PatchMapping("/{id}") - public ResponseEntity> updateDiary(@PathVariable Long id, - @RequestBody DiaryManualCreateRequest diaryManualCreateRequest) { - diaryService.updateDiary(id, diaryManualCreateRequest); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(null) - .build(); - return ResponseEntity.ok(response); + @PatchMapping("/{diaryId}") + public ResponseEntity> updateDiary( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long diaryId, + @RequestBody DiaryManualCreateRequest diaryManualCreateRequest) { + Long memberId = memberDetails.getId(); + + diaryService.updateDiary(memberId, diaryId, diaryManualCreateRequest); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); } //일기 삭제 - @DeleteMapping("/{id}") - public ResponseEntity> deleteDiary(@PathVariable Long id) { - diaryService.deleteDiary(id); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(null) - .build(); - return ResponseEntity.ok(response); + @DeleteMapping("/{diaryId}") + public ResponseEntity> deleteDiary( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long diaryId) { + Long memberId = memberDetails.getId(); + + diaryService.deleteDiary(memberId, diaryId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); } //북마크 설정 토글 - @PatchMapping("/{id}/bookmark") - public ResponseEntity> toggleBookmark(@PathVariable Long id) { - diaryService.toggleBookmark(id); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(null) - .build(); - return ResponseEntity.ok(response); + @PatchMapping("/{diaryId}/bookmark") + public ResponseEntity> toggleBookmark( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long diaryId) { + Long memberId = memberDetails.getId(); + + diaryService.toggleBookmark(memberId, diaryId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); } //공개 설정 토글 - @PatchMapping("/{id}/privacy") - public ResponseEntity> togglePrivacy(@PathVariable Long id) { - diaryService.togglePrivacy(id); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(null) - .build(); - return ResponseEntity.ok(response); + @PatchMapping("/{diaryId}/privacy") + public ResponseEntity> togglePrivacy( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long diaryId) { + Long memberId = memberDetails.getId(); + + diaryService.togglePrivacy(memberId, diaryId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); } //전체 친구 일기 조회 @GetMapping("/friend") public ResponseEntity> getFriendDiaries( + @AuthenticationPrincipal MemberDetails memberDetails, @RequestParam(required = false) String keyword, @RequestParam(required = false) String emoji, @RequestParam(required = false) Long category, @@ -168,6 +179,7 @@ public ResponseEntity> getFriendDiaries( @RequestParam(defaultValue = "0") int key, @RequestParam(defaultValue = "10") int size ) { + Long memberId = memberDetails.getId(); DiaryFilterRequest diaryFilterRequest = DiaryFilterRequest.builder() .keyword(keyword) .emoji(emoji) @@ -180,24 +192,49 @@ public ResponseEntity> getFriendDiaries( .size(size) .build(); - FriendDiariesResponse diaries = friendDiaryService.getFriendDiaries(diaryFilterRequest); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(diaries) - .build(); - return ResponseEntity.ok(response); + FriendDiariesResponse response = friendDiaryService.getFriendDiaries(memberId, diaryFilterRequest); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); } //친구 일기 상제 조회 - @GetMapping("/friend/{id}") - public ResponseEntity> getFriendDiary(@PathVariable Long id) { - FriendDiaryResponse diary = friendDiaryService.getFriendDiary(id); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(diary) - .build(); - return ResponseEntity.ok(response); + @GetMapping("/friend/{diaryId}") + public ResponseEntity> getFriendDiary( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long diaryId) { + Long memberId = memberDetails.getId(); + + FriendDiaryResponse response = friendDiaryService.getFriendDiary(memberId, diaryId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); + } + + //댓글 조회 + @GetMapping("/{diaryId}/comments") + public ResponseEntity> getComments( + @PathVariable Long diaryId, + @RequestParam(defaultValue = "0") int key, + @RequestParam(defaultValue = "10") int size + ) { + CommentsResponse response = commentService.getComments(diaryId, key, size); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); + } + + //댓글 작성 + @PostMapping("/{diaryId}/comments") + public ResponseEntity> createComment( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long diaryId, + @RequestBody CommentRequest commentRequest) { + Long memberId = memberDetails.getId(); + + commentService.createComment(memberId, diaryId, commentRequest); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); } } diff --git a/src/main/java/com/potatocake/everymoment/controller/FriendController.java b/src/main/java/com/potatocake/everymoment/controller/FriendController.java index 8fb3f75..79772c9 100644 --- a/src/main/java/com/potatocake/everymoment/controller/FriendController.java +++ b/src/main/java/com/potatocake/everymoment/controller/FriendController.java @@ -3,11 +3,14 @@ import com.potatocake.everymoment.dto.SuccessResponse; import com.potatocake.everymoment.dto.response.FriendListResponse; import com.potatocake.everymoment.dto.response.OneFriendDiariesResponse; +import com.potatocake.everymoment.entity.Member; +import com.potatocake.everymoment.security.MemberDetails; import com.potatocake.everymoment.service.FriendService; import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; @@ -17,7 +20,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("api/friends") +@RequestMapping("/api/friends") public class FriendController { private final FriendService friendService; @@ -26,57 +29,59 @@ public FriendController(FriendService friendService) { } //특정 친구 일기 전체 조회 - @GetMapping("/{id}/diaries") + @GetMapping("/{friendId}/diaries") public ResponseEntity> getOneFriendDiaries( - @PathVariable Long id, + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long friendId, @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, @RequestParam(defaultValue = "0") int key, @RequestParam(defaultValue = "10") int size) { - OneFriendDiariesResponse diaries = friendService.OneFriendDiariesResponse(id, date, key, size); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(diaries) - .build(); - return ResponseEntity.ok(response); + Long memberId = memberDetails.getId(); + + OneFriendDiariesResponse response = friendService.OneFriendDiariesResponse(memberId, friendId, date, key, size); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); } //내 친구 목록 조회 @GetMapping("/friends") public ResponseEntity> getFriendList( + @AuthenticationPrincipal MemberDetails memberDetails, @RequestParam(required = false) String nickname, @RequestParam(defaultValue = "0") int key, @RequestParam(defaultValue = "10") int size) { - FriendListResponse friendList = friendService.getFriendList(nickname, key, size); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(friendList) - .build(); - return ResponseEntity.ok(response); + Long memberId = memberDetails.getId(); + + FriendListResponse response = friendService.getFriendList(memberId, nickname, key, size); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); } //내 친구 삭제 - @DeleteMapping("/{id}") - public ResponseEntity> deleteFriend(@PathVariable Long id) { - friendService.deleteFriend(id); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(null) - .build(); - return ResponseEntity.ok(response); + @DeleteMapping("/{friendId}") + public ResponseEntity> deleteFriend( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long friendId) { + Long memberId = memberDetails.getId(); + + friendService.deleteFriend(memberId, friendId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); } //친한 친구 설정 - @PatchMapping("/{id}/bookmark") - public ResponseEntity> toggleCloseFriend(@PathVariable Long id) { - friendService.toggleCloseFriend(id); - SuccessResponse response = SuccessResponse.builder() - .code(HttpStatus.OK.value()) - .message("success") - .info(null) - .build(); - return ResponseEntity.ok(response); + @PatchMapping("/{friendId}/bookmark") + public ResponseEntity> toggleCloseFriend( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long friendId) { + Long memberId = memberDetails.getId(); + + friendService.toggleCloseFriend(memberId, friendId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); } } diff --git a/src/main/java/com/potatocake/everymoment/controller/NotificationController.java b/src/main/java/com/potatocake/everymoment/controller/NotificationController.java new file mode 100644 index 0000000..e8ce3d9 --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/controller/NotificationController.java @@ -0,0 +1,46 @@ +package com.potatocake.everymoment.controller; + +import com.potatocake.everymoment.dto.SuccessResponse; +import com.potatocake.everymoment.dto.response.NotificationListResponse; +import com.potatocake.everymoment.security.MemberDetails; +import com.potatocake.everymoment.service.NotificationService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/api/notifications") +public class NotificationController { + + private final NotificationService notificationService; + + @GetMapping + public ResponseEntity>> getNotifications( + @AuthenticationPrincipal MemberDetails memberDetails){ + Long memberId = memberDetails.getId(); + + List response = notificationService.getNotifications(memberId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok(response)); + } + + @PatchMapping("/{notificationId}") + public ResponseEntity> updateNotification( + @AuthenticationPrincipal MemberDetails memberDetails, + @PathVariable Long notificationId) { + Long memberId = memberDetails.getId(); + + notificationService.updateNotification(memberId, notificationId); + + return ResponseEntity.ok() + .body(SuccessResponse.ok()); + } +} diff --git a/src/main/java/com/potatocake/everymoment/dto/request/CommentRequest.java b/src/main/java/com/potatocake/everymoment/dto/request/CommentRequest.java new file mode 100644 index 0000000..db0252a --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/dto/request/CommentRequest.java @@ -0,0 +1,8 @@ +package com.potatocake.everymoment.dto.request; + +import lombok.Getter; + +@Getter +public class CommentRequest { + private String content; +} diff --git a/src/main/java/com/potatocake/everymoment/dto/response/CommentFriendResponse.java b/src/main/java/com/potatocake/everymoment/dto/response/CommentFriendResponse.java new file mode 100644 index 0000000..b6f09fc --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/dto/response/CommentFriendResponse.java @@ -0,0 +1,12 @@ +package com.potatocake.everymoment.dto.response; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class CommentFriendResponse { + private Long id; + private String nickname; + private String profileImageUrl; +} diff --git a/src/main/java/com/potatocake/everymoment/dto/response/CommentResponse.java b/src/main/java/com/potatocake/everymoment/dto/response/CommentResponse.java new file mode 100644 index 0000000..7fe835d --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/dto/response/CommentResponse.java @@ -0,0 +1,14 @@ +package com.potatocake.everymoment.dto.response; + +import java.time.LocalDateTime; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class CommentResponse { + private Long id; + private CommentFriendResponse commentFriendResponse; + private String content; + private LocalDateTime createdAt; +} diff --git a/src/main/java/com/potatocake/everymoment/dto/response/CommentsResponse.java b/src/main/java/com/potatocake/everymoment/dto/response/CommentsResponse.java new file mode 100644 index 0000000..160b79c --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/dto/response/CommentsResponse.java @@ -0,0 +1,13 @@ +package com.potatocake.everymoment.dto.response; + +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class CommentsResponse { + private List comments; + private Integer next; +} + diff --git a/src/main/java/com/potatocake/everymoment/dto/response/NotificationListResponse.java b/src/main/java/com/potatocake/everymoment/dto/response/NotificationListResponse.java new file mode 100644 index 0000000..f32770e --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/dto/response/NotificationListResponse.java @@ -0,0 +1,17 @@ +package com.potatocake.everymoment.dto.response; + +import java.time.LocalDateTime; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class NotificationListResponse { + private Long id; + private String content; + private boolean isRead; + private String type; + private Long targetId; + private LocalDateTime createdAt; +} + diff --git a/src/main/java/com/potatocake/everymoment/entity/Comment.java b/src/main/java/com/potatocake/everymoment/entity/Comment.java new file mode 100644 index 0000000..5024398 --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/entity/Comment.java @@ -0,0 +1,43 @@ +package com.potatocake.everymoment.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Getter +@Builder +public class Comment extends BaseTimeEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(nullable = false) + private Diary diary; + + @Lob + private String content; + + public void updateContent(String content) { + if (content != null) { + this.content = content; + } + } +} diff --git a/src/main/java/com/potatocake/everymoment/entity/Diary.java b/src/main/java/com/potatocake/everymoment/entity/Diary.java index a0ae427..a8abca1 100644 --- a/src/main/java/com/potatocake/everymoment/entity/Diary.java +++ b/src/main/java/com/potatocake/everymoment/entity/Diary.java @@ -27,7 +27,7 @@ public class Diary extends BaseTimeEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(nullable = false) - private Member memberId; + private Member member; @Lob private String content; @@ -100,7 +100,7 @@ public void togglePublic() { } public boolean checkOwner(Long memberId) { - return this.memberId.getId().equals(memberId); + return this.member.getId().equals(memberId); } } diff --git a/src/main/java/com/potatocake/everymoment/entity/Notification.java b/src/main/java/com/potatocake/everymoment/entity/Notification.java index 7963a15..184ea96 100644 --- a/src/main/java/com/potatocake/everymoment/entity/Notification.java +++ b/src/main/java/com/potatocake/everymoment/entity/Notification.java @@ -27,7 +27,7 @@ public class Notification extends BaseTimeEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(nullable = false) - private Member memberId; + private Member member; @Column(nullable = false) private String content; @@ -41,4 +41,8 @@ public class Notification extends BaseTimeEntity { @Column(nullable = false) private Long targetId; + + public void updateIsRead() { + this.isRead = true; + } } diff --git a/src/main/java/com/potatocake/everymoment/exception/ErrorCode.java b/src/main/java/com/potatocake/everymoment/exception/ErrorCode.java index 365d29a..19b0d7c 100644 --- a/src/main/java/com/potatocake/everymoment/exception/ErrorCode.java +++ b/src/main/java/com/potatocake/everymoment/exception/ErrorCode.java @@ -23,6 +23,9 @@ public enum ErrorCode { /* Friend */ FRIEND_NOT_FOUND("존재하지 않는 친구입니다.", NOT_FOUND), + /* Notification */ + NOTIFICATION_NOT_FOUND("존재하지 않는 알림입니다.", NOT_FOUND), + /* CategoryService */ ALREADY_EXISTS_CATEGORY("이미 존재하는 카테고리입니다.", CONFLICT), diff --git a/src/main/java/com/potatocake/everymoment/repository/CommentRepository.java b/src/main/java/com/potatocake/everymoment/repository/CommentRepository.java new file mode 100644 index 0000000..8129c6d --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/repository/CommentRepository.java @@ -0,0 +1,10 @@ +package com.potatocake.everymoment.repository; + +import com.potatocake.everymoment.entity.Comment; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentRepository extends JpaRepository { + Page findAllByDiaryId(Long diaryId, Pageable pageable); +} diff --git a/src/main/java/com/potatocake/everymoment/repository/NotificationRepository.java b/src/main/java/com/potatocake/everymoment/repository/NotificationRepository.java index a3a5974..19297a5 100644 --- a/src/main/java/com/potatocake/everymoment/repository/NotificationRepository.java +++ b/src/main/java/com/potatocake/everymoment/repository/NotificationRepository.java @@ -1,7 +1,9 @@ package com.potatocake.everymoment.repository; import com.potatocake.everymoment.entity.Notification; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; public interface NotificationRepository extends JpaRepository { + List findAllByMemberId(Long memberId); } diff --git a/src/main/java/com/potatocake/everymoment/service/CommentService.java b/src/main/java/com/potatocake/everymoment/service/CommentService.java new file mode 100644 index 0000000..b0d7663 --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/service/CommentService.java @@ -0,0 +1,117 @@ +package com.potatocake.everymoment.service; + +import com.potatocake.everymoment.dto.request.CommentRequest; +import com.potatocake.everymoment.dto.response.CommentFriendResponse; +import com.potatocake.everymoment.dto.response.CommentResponse; +import com.potatocake.everymoment.dto.response.CommentsResponse; +import com.potatocake.everymoment.entity.Comment; +import com.potatocake.everymoment.entity.Diary; +import com.potatocake.everymoment.entity.Member; +import com.potatocake.everymoment.exception.ErrorCode; +import com.potatocake.everymoment.exception.GlobalException; +import com.potatocake.everymoment.repository.CommentRepository; +import com.potatocake.everymoment.repository.DiaryRepository; +import com.potatocake.everymoment.repository.MemberRepository; +import com.potatocake.everymoment.security.MemberDetails; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Transactional +@Service +public class CommentService { + + private final CommentRepository commentRepository; + private final DiaryRepository diaryRepository; + private final MemberRepository memberRepository; + + // 댓글 목록 조회 + public CommentsResponse getComments(Long diaryId, int key, int size) { + Pageable pageable = PageRequest.of(key, size); + Page commentPage = commentRepository.findAllByDiaryId(diaryId, pageable); + + List commentResponses = commentPage.getContent().stream() + .map(this::convertToCommentResponseDTO) + .collect(Collectors.toList()); + + Integer nextKey = commentPage.hasNext() ? key + 1 : null; + + return CommentsResponse.builder() + .comments(commentResponses) + .next(nextKey) + .build(); + } + + // 댓글 작성 + public void createComment(Long memberId, Long diaryId, CommentRequest commentRequest) { + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); + + Diary diary = diaryRepository.findById(diaryId) + .orElseThrow(() -> new GlobalException(ErrorCode.DIARY_NOT_FOUND)); + + Comment comment = Comment.builder() + .content(commentRequest.getContent()) + .member(currentMember) + .diary(diary) + .build(); + + commentRepository.save(comment); + } + + // 댓글 수정 + public void updateComment(Long memberId, Long commentId, CommentRequest commentRequest) { + Comment comment = getExistComment(memberId, commentId); + comment.updateContent(commentRequest.getContent()); + } + + // 댓글 삭제 + public void deleteComment(Long memberId, Long commentId) { + Comment comment = getExistComment(memberId, commentId); + commentRepository.delete(comment); + } + + // 로그인한 유저가 쓴 댓글인지 확인하고, 맞을시 댓글 반환 + private Comment getExistComment(Long memberId, Long commentId) { + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); + + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() -> new GlobalException(ErrorCode.COMMENT_NOT_FOUND)); + + if(!Objects.equals(currentMember.getId(), comment.getMember().getId())){ + throw new GlobalException(ErrorCode.COMMENT_NOT_FOUND); + } + + return comment; + } + + // 친구 프로필 DTO 변환 + private CommentFriendResponse convertToCommentFriendResponseDTO(Member member){ + return CommentFriendResponse.builder() + .id(member.getId()) + .nickname(member.getNickname()) + .profileImageUrl(member.getProfileImageUrl()) + .build(); + } + + // 댓글 DTO 변환 + private CommentResponse convertToCommentResponseDTO(Comment comment){ + return CommentResponse.builder() + .id(comment.getId()) + .commentFriendResponse(convertToCommentFriendResponseDTO(comment.getMember())) + .content(comment.getContent()) + .createdAt(comment.getCreateAt()) + .build(); + } +} + diff --git a/src/main/java/com/potatocake/everymoment/service/DiaryService.java b/src/main/java/com/potatocake/everymoment/service/DiaryService.java index e8bf635..8debdc8 100644 --- a/src/main/java/com/potatocake/everymoment/service/DiaryService.java +++ b/src/main/java/com/potatocake/everymoment/service/DiaryService.java @@ -18,6 +18,7 @@ import com.potatocake.everymoment.exception.GlobalException; import com.potatocake.everymoment.repository.DiaryCategoryRepository; import com.potatocake.everymoment.repository.DiaryRepository; +import com.potatocake.everymoment.repository.MemberRepository; import com.potatocake.everymoment.repository.NotificationRepository; import com.potatocake.everymoment.security.MemberDetails; import java.util.ArrayList; @@ -29,6 +30,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.Specification; import org.springframework.security.core.Authentication; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -41,16 +43,16 @@ public class DiaryService { private final DiaryRepository diaryRepository; private final DiaryCategoryRepository diaryCategoryRepository; private final NotificationRepository notificationRepository; + private final MemberRepository memberRepository; // 자동 일기 저장 (LocationPoint, Name, Adress 만 저장) - public NotificationResponse createDiaryAuto(DiaryAutoCreateRequest diaryAutoCreateRequest) { + public NotificationResponse createDiaryAuto(Long memberId, DiaryAutoCreateRequest diaryAutoCreateRequest) { // member 가져옴 - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); Diary diary = Diary.builder() - .memberId(currentMember) + .member(currentMember) .locationPoint(diaryAutoCreateRequest.getLocationPoint().toString()) .locationName(diaryAutoCreateRequest.getLocationName()) .address(diaryAutoCreateRequest.getAddress()) @@ -62,7 +64,7 @@ public NotificationResponse createDiaryAuto(DiaryAutoCreateRequest diaryAutoCrea String content = "현재 " + savedDiary.getLocationName() + "에 머무르고 있어요! 지금 기분은 어떠신가요?"; Notification notification = Notification.builder() - .memberId(currentMember) + .member(currentMember) .content(content) .type("MOOD_CHECK") .targetId(savedDiary.getId()) @@ -83,14 +85,13 @@ public NotificationResponse createDiaryAuto(DiaryAutoCreateRequest diaryAutoCrea } // 수동 일기 작성 - public void createDiaryManual(DiaryManualCreateRequest diaryManualCreateRequest) { + public void createDiaryManual(Long memberId, DiaryManualCreateRequest diaryManualCreateRequest) { // member Id - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); Diary diary = Diary.builder() - .memberId(currentMember) + .member(currentMember) .content(diaryManualCreateRequest.getContent()) .locationPoint(diaryManualCreateRequest.getLocationPoint().toString()) .locationName(diaryManualCreateRequest.getLocationName()) @@ -109,11 +110,10 @@ public void createDiaryManual(DiaryManualCreateRequest diaryManualCreateRequest) // 내 일기 전체 조회 (타임라인) @Transactional(readOnly = true) - public MyDiariesResponse getMyDiaries(DiaryFilterRequest diaryFilterRequest) { + public MyDiariesResponse getMyDiaries(Long memberId, DiaryFilterRequest diaryFilterRequest) { //member 가져옴 - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); Page diaryPage; @@ -133,7 +133,7 @@ public MyDiariesResponse getMyDiaries(DiaryFilterRequest diaryFilterRequest) { // Diary 중에 memberId같은 것 가져옴 List DiaryIdList = diaryCategoryList.stream() - .filter(diaryCategory -> diaryCategory.getDiary().getMemberId() + .filter(diaryCategory -> diaryCategory.getDiary().getMember() .equals(currentMember)) // memberId가 일치하는 경우 필터링 .map(diaryCategory -> diaryCategory.getDiary().getId()) .collect(Collectors.toList()); @@ -158,14 +158,14 @@ public MyDiariesResponse getMyDiaries(DiaryFilterRequest diaryFilterRequest) { // 내 일기 상세 조회 @Transactional(readOnly = true) - public MyDiaryResponse getMyDiary(Long id) { - Diary diary = getExistDiary(id); + public MyDiaryResponse getMyDiary(Long memberId, Long diaryId) { + Diary diary = getExistDiary(memberId, diaryId); return convertToMyDiaryResponseDto(diary); } // 내 일기 수정 - public void updateDiary(Long id, DiaryManualCreateRequest diaryManualCreateRequest) { - Diary existingDiary = getExistDiary(id); + public void updateDiary(Long memberId, Long diaryId, DiaryManualCreateRequest diaryManualCreateRequest) { + Diary existingDiary = getExistDiary(memberId, diaryId); //카테고리 업데이트 //파일 업데이트 @@ -182,33 +182,32 @@ public void updateDiary(Long id, DiaryManualCreateRequest diaryManualCreateReque } // 내 일기 삭제 - public void deleteDiary(Long id) { - Diary existingDiary = getExistDiary(id); + public void deleteDiary(Long memberId, Long diaryId) { + Diary existingDiary = getExistDiary(memberId, diaryId); diaryRepository.delete(existingDiary); } // 내 일기 북마크 설정 - public void toggleBookmark(Long id) { - Diary existingDiary = getExistDiary(id); + public void toggleBookmark(Long memberId, Long diaryId) { + Diary existingDiary = getExistDiary(memberId, diaryId); existingDiary.toggleBookmark(); } // 내 일기 공개 설정 - public void togglePrivacy(Long id) { - Diary existingDiary = getExistDiary(id); + public void togglePrivacy(Long memberId, Long diaryId) { + Diary existingDiary = getExistDiary(memberId, diaryId); existingDiary.togglePublic(); } // 로그인한 유저의 일기가 맞는지 확인 후 일기 반환 - private Diary getExistDiary(Long diaryId) { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); + private Diary getExistDiary(Long memberId, Long diaryId) { + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); Diary diary = diaryRepository.findById(diaryId) .orElseThrow(() -> new GlobalException(ErrorCode.DIARY_NOT_FOUND)); - if (!Objects.equals(currentMember.getId(), diary.getMemberId().getId())) { + if (!Objects.equals(currentMember.getId(), diary.getMember().getId())) { throw new GlobalException(ErrorCode.DIARY_NOT_FOUND); } diff --git a/src/main/java/com/potatocake/everymoment/service/FriendDiaryService.java b/src/main/java/com/potatocake/everymoment/service/FriendDiaryService.java index d6d4ee1..7a8fa74 100644 --- a/src/main/java/com/potatocake/everymoment/service/FriendDiaryService.java +++ b/src/main/java/com/potatocake/everymoment/service/FriendDiaryService.java @@ -15,6 +15,7 @@ import com.potatocake.everymoment.repository.DiaryCategoryRepository; import com.potatocake.everymoment.repository.DiaryRepository; import com.potatocake.everymoment.repository.FriendRepository; +import com.potatocake.everymoment.repository.MemberRepository; import com.potatocake.everymoment.security.MemberDetails; import java.util.ArrayList; import java.util.List; @@ -35,12 +36,12 @@ public class FriendDiaryService { private final DiaryRepository diaryRepository; private final DiaryCategoryRepository diaryCategoryRepository; private final FriendRepository friendRepository; + private final MemberRepository memberRepository; //친구 일기 조회 - public FriendDiariesResponse getFriendDiaries(DiaryFilterRequest diaryFilterRequest) { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); + public FriendDiariesResponse getFriendDiaries(Long memberId, DiaryFilterRequest diaryFilterRequest) { + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); List friends = friendRepository.findAllFriendIdsByMemberId(currentMember); List friendIdList = friends.stream() @@ -63,7 +64,7 @@ public FriendDiariesResponse getFriendDiaries(DiaryFilterRequest diaryFilterRequ // Diary중에 memberId같은 것 가져옴 List filteredDiaryIds = diaryCategories.stream() - .filter(diaryCategory -> friendIdList.contains(diaryCategory.getDiary().getMemberId())) // memberIds 목록에서 필터링 + .filter(diaryCategory -> friendIdList.contains(diaryCategory.getDiary().getMember())) // memberIds 목록에서 필터링 .map(diaryCategory -> diaryCategory.getDiary().getId()) .collect(Collectors.toList()); @@ -87,21 +88,20 @@ public FriendDiariesResponse getFriendDiaries(DiaryFilterRequest diaryFilterRequ } // 친구 다이어리 하나 조회 - public FriendDiaryResponse getFriendDiary(Long id) { - Diary diary = diaryRepository.findById(id) + public FriendDiaryResponse getFriendDiary(Long memberId, Long diaryId) { + Diary diary = diaryRepository.findById(diaryId) .orElseThrow(() -> new IllegalArgumentException("Diary not found")); //글쓴사람이 친구인지 확인 - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); List friends = friendRepository.findAllFriendIdsByMemberId(currentMember); List friendIdList = friends.stream() .map(Member::getId) .collect(Collectors.toList()); - if(!friendIdList.contains(diary.getMemberId())){ + if(!friendIdList.contains(diary.getMember())){ throw new GlobalException(ErrorCode.FRIEND_NOT_FOUND); } //카테고리 찾음 diff --git a/src/main/java/com/potatocake/everymoment/service/FriendService.java b/src/main/java/com/potatocake/everymoment/service/FriendService.java index ba78771..f6b5b88 100644 --- a/src/main/java/com/potatocake/everymoment/service/FriendService.java +++ b/src/main/java/com/potatocake/everymoment/service/FriendService.java @@ -38,22 +38,20 @@ public class FriendService { //특정 친구 일기 조회 @Transactional(readOnly = true) - public OneFriendDiariesResponse OneFriendDiariesResponse(Long id, LocalDate date, int key, int size) { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); + public OneFriendDiariesResponse OneFriendDiariesResponse(Long memberid, Long friendId, LocalDate date, int key, int size) { + Member currentMember = memberRepository.findById(memberid) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); //친구인지 확인 - Member friend = memberRepository.findById(id) + Member friend = memberRepository.findById(friendId) .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); friendRepository.findByMemberIdAndFriendId(currentMember, friend) .orElseThrow(() -> new GlobalException(ErrorCode.FRIEND_NOT_FOUND)); Pageable pageable = PageRequest.of(key, size); - Page diaries = diaryRepository.findAll( - DiarySpecification.filterDiaries(null, null, date, null, null, null) - .and((root, query, builder) -> builder.equal(root.get("memberId").get("id"), id)), pageable); + Page diaries = diaryRepository.findAll(DiarySpecification.filterDiaries(null, null, date, null, null, null) + .and((root, query, builder) -> builder.equal(root.get("memberId").get("id"), friendId)), pageable); List diaryList = diaries.getContent().stream() .map(this::convertToFriendDiariesResponseDTO) @@ -69,10 +67,10 @@ public OneFriendDiariesResponse OneFriendDiariesResponse(Long id, LocalDate date //내 친구 목록 조회 @Transactional(readOnly = true) - public FriendListResponse getFriendList(String nickname, int key, int size) { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); + public FriendListResponse getFriendList(Long memberIdFromController, String nickname, int key, int size) { + Member currentMember = memberRepository.findById(memberIdFromController) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); + Long memberId = currentMember.getId(); Pageable pageable = PageRequest.of(key, size); @@ -95,12 +93,10 @@ public FriendListResponse getFriendList(String nickname, int key, int size) { } // 친구 삭제 - public void deleteFriend(Long id) { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); - - Member friendMember = memberRepository.findById(id) + public void deleteFriend(Long memberId, Long firendId) { + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); + Member friendMember = memberRepository.findById(firendId) .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); Friend friendMine = friendRepository.findByMemberIdAndFriendId(currentMember, friendMember) @@ -113,13 +109,12 @@ public void deleteFriend(Long id) { } // 친한 친구 설정(토글) - public void toggleCloseFriend(Long id) { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - MemberDetails memberDetails = (MemberDetails) authentication.getPrincipal(); - Member currentMember = memberDetails.getMember(); - - Member friendMember = memberRepository.findById(id) + public void toggleCloseFriend(Long memberId, Long friendId) { + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); + Member friendMember = memberRepository.findById(friendId) .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); + Friend friend = friendRepository.findByMemberIdAndFriendId(currentMember, friendMember) .orElseThrow(() -> new GlobalException(ErrorCode.FRIEND_NOT_FOUND)); diff --git a/src/main/java/com/potatocake/everymoment/service/NotificationService.java b/src/main/java/com/potatocake/everymoment/service/NotificationService.java new file mode 100644 index 0000000..e199a24 --- /dev/null +++ b/src/main/java/com/potatocake/everymoment/service/NotificationService.java @@ -0,0 +1,61 @@ +package com.potatocake.everymoment.service; + +import com.potatocake.everymoment.dto.response.NotificationListResponse; +import com.potatocake.everymoment.entity.Member; +import com.potatocake.everymoment.entity.Notification; +import com.potatocake.everymoment.exception.ErrorCode; +import com.potatocake.everymoment.exception.GlobalException; +import com.potatocake.everymoment.repository.MemberRepository; +import com.potatocake.everymoment.repository.NotificationRepository; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Transactional +@Service +public class NotificationService { + + private final NotificationRepository notificationRepository; + private final MemberRepository memberRepository; + + public List getNotifications(Long memberId) { + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); + + List notifications = notificationRepository.findAllByMemberId(currentMember.getId()); + + return notifications.stream() + .map(this::convertToNotificationResponseDTO) + .collect(Collectors.toList()); + } + + public void updateNotification(Long memberId, Long notificationId) { + Member currentMember = memberRepository.findById(memberId) + .orElseThrow(() -> new GlobalException(ErrorCode.MEMBER_NOT_FOUND)); + + Notification notification = notificationRepository.findById(notificationId) + .orElseThrow(() -> new GlobalException(ErrorCode.NOTIFICATION_NOT_FOUND)); + + if(!Objects.equals(currentMember.getId(), notification.getMember().getId())){ + throw new GlobalException(ErrorCode.NOTIFICATION_NOT_FOUND); + } + + notification.updateIsRead(); + } + + // 알림 DTO 변환 + private NotificationListResponse convertToNotificationResponseDTO(Notification notification){ + return NotificationListResponse.builder() + .id(notification.getId()) + .content(notification.getContent()) + .isRead(notification.isRead()) + .type(notification.getType()) + .targetId(notification.getTargetId()) + .createdAt(notification.getCreateAt()) + .build(); + } +}