Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ public void deletePost(
public ResponseEntity<Page<PostResponse>> getPosts(
@RequestParam UUID boardId,
@RequestParam(defaultValue = "0") int pageNumber,
@RequestParam(defaultValue = "20") int pageSize) {
return ResponseEntity.ok(postService.getPosts(boardId, pageNumber, pageSize));
@RequestParam(defaultValue = "20") int pageSize,
@AuthenticationPrincipal CustomUserDetails customUserDetails) {
UUID userId = customUserDetails.getUserId();
return ResponseEntity.ok(postService.getPosts(boardId, userId, pageNumber, pageSize));
}

// 게시글 검색
Expand All @@ -114,8 +116,10 @@ public ResponseEntity<Page<PostResponse>> searchPosts(
@RequestParam UUID boardId,
@RequestParam String keyword,
@RequestParam(defaultValue = "0") int pageNumber,
@RequestParam(defaultValue = "20") int pageSize) {
return ResponseEntity.ok(postService.searchPosts(boardId, keyword, pageNumber, pageSize));
@RequestParam(defaultValue = "20") int pageSize,
@AuthenticationPrincipal CustomUserDetails customUserDetails) {
UUID userId = customUserDetails.getUserId();
return ResponseEntity.ok(postService.searchPosts(boardId, userId, keyword, pageNumber, pageSize));
}

// 게시물 상세 조회
Expand All @@ -129,8 +133,10 @@ public ResponseEntity<Page<PostResponse>> searchPosts(
public ResponseEntity<PostResponse> getPostDetail(
@PathVariable UUID postId,
@RequestParam(defaultValue = "0") int commentPageNumber,
@RequestParam(defaultValue = "20") int commentPageSize) {
PostResponse response = postService.getPostDetail(postId, commentPageNumber, commentPageSize);
@RequestParam(defaultValue = "20") int commentPageSize,
@AuthenticationPrincipal CustomUserDetails customUserDetails) {
UUID userId = customUserDetails.getUserId();
PostResponse response = postService.getPostDetail(postId, userId, commentPageNumber, commentPageSize);
return ResponseEntity.ok(response);
}

Expand All @@ -149,7 +155,7 @@ public ResponseEntity<Void> createBoard(
return ResponseEntity.ok().build();
}

// 게시판 생성
// 최상위 게시판 목록 조회
@Operation(
summary = "부모 게시판 목록 조회",
description = "최상위 부모 게시판들의 목록을 조회합니다."
Expand All @@ -161,7 +167,7 @@ public ResponseEntity<List<BoardResponse>> getParentBoards(
}


// 게시판 생성
// 하위 게시판 목록 조회
@Operation(
summary = "하위 게시판 목록 조회",
description = "하위 게시판 목록을 조회합니다."
Expand All @@ -172,7 +178,7 @@ public ResponseEntity<List<BoardResponse>> getChildBoards(
return ResponseEntity.ok(postService.getChildBoards());
}

// 게시글 삭제
// 게시판 삭제
@Operation(
summary = "게시판 삭제",
description = "게시판 ID를 통해 게시판을 삭제합니다."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class PostResponse {
private Integer bookmarkCount;
private Integer likeCount;
private Integer commentCount;
private Boolean isLiked;
private Boolean isBookmarked;
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
private Page<CommentResponse> comments;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,23 @@ public interface PostService {
void deletePost(UUID postId, UUID userId);

// 게시물 조회
Page<PostResponse> getPosts(UUID boardId, int pageNumber, int pageSize);
Page<PostResponse> getPosts(UUID boardId, UUID userId, int pageNumber, int pageSize);

// 게시물 검색
Page<PostResponse> searchPosts(UUID boardId, String keyword, int pageNumber, int pageSize);
Page<PostResponse> searchPosts(UUID boardId, UUID userId, String keyword, int pageNumber, int pageSize);

// 게시물 상세 조회
PostResponse getPostDetail(UUID postId, int pageNumber, int pageSize);
PostResponse getPostDetail(UUID postId, UUID userId, int pageNumber, int pageSize);

// 게시판 생성
void createBoard(BoardRequest request, UUID userId);

// 부모 게시판 목록 조회
List<BoardResponse> getParentBoards();

// 하위 게시판 목록 조회
List<BoardResponse> getChildBoards();

// 게시판 삭제
void deleteBoard(UUID boardId, UUID boardUserId);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package org.sejongisc.backend.board.service;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.sejongisc.backend.board.dto.BoardRequest;
Expand All @@ -24,7 +21,6 @@
import org.sejongisc.backend.board.repository.PostBookmarkRepository;
import org.sejongisc.backend.board.repository.PostLikeRepository;
import org.sejongisc.backend.board.repository.PostRepository;
import org.sejongisc.backend.board.repository.projection.PostIdUserIdProjection;
import org.sejongisc.backend.common.exception.CustomException;
import org.sejongisc.backend.common.exception.ErrorCode;
import org.sejongisc.backend.user.dao.UserRepository;
Expand Down Expand Up @@ -175,6 +171,8 @@ public void deletePost(UUID postId, UUID userId) {
postRepository.delete(post);
}

// 게시판 삭제
@Override
@Transactional
public void deleteBoard(UUID boardId, UUID boardUserId) {
User user = userRepository.findById(boardUserId).orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
Expand All @@ -200,7 +198,7 @@ public void deleteBoard(UUID boardId, UUID boardUserId) {
// 게시물 조회 (해당 게시판의 게시물)
@Override
@Transactional(readOnly = true)
public Page<PostResponse> getPosts(UUID boardId, int pageNumber, int pageSize) {
public Page<PostResponse> getPosts(UUID boardId, UUID userId, int pageNumber, int pageSize) {
Pageable pageable = PageRequest.of(
pageNumber,
pageSize,
Expand All @@ -211,16 +209,20 @@ public Page<PostResponse> getPosts(UUID boardId, int pageNumber, int pageSize) {
Board board = boardRepository.findById(boardId)
.orElseThrow(() -> new CustomException(ErrorCode.BOARD_NOT_FOUND));

// 유저 조회 (좋아요/북마크 여부 확인용)
User user = userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

// 해당 게시판의 게시물 조회
Page<Post> posts = postRepository.findAllByBoard(board, pageable);

return posts.map(this::mapToPostResponse);
return posts.map(post -> mapToPostResponse(post, user));
}

// 게시물 검색 (제목/내용)
@Override
@Transactional(readOnly = true)
public Page<PostResponse> searchPosts(UUID boardId, String keyword, int pageNumber, int pageSize) {
public Page<PostResponse> searchPosts(UUID boardId, UUID userId, String keyword, int pageNumber, int pageSize) {
Pageable pageable = PageRequest.of(
pageNumber,
pageSize,
Expand All @@ -235,13 +237,17 @@ public Page<PostResponse> searchPosts(UUID boardId, String keyword, int pageNumb
Page<Post> posts = postRepository.searchByBoardAndKeyword(
board, keyword, pageable);

return posts.map(this::mapToPostResponse);
// 유저 조회
User user = userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

return posts.map(post -> mapToPostResponse(post, user));
}

// 게시물 상세 조회
@Override
@Transactional(readOnly = true)
public PostResponse getPostDetail(UUID postId, int pageNumber, int pageSize) {
public PostResponse getPostDetail(UUID postId, UUID userId, int pageNumber, int pageSize) {
// 게시물 조회
Post post = postRepository.findById(postId)
.orElseThrow(() -> new CustomException(ErrorCode.POST_NOT_FOUND));
Expand Down Expand Up @@ -277,18 +283,11 @@ public PostResponse getPostDetail(UUID postId, int pageNumber, int pageSize) {
.map(PostAttachmentResponse::of)
.toList();

// PostResponse DTO를 직접 빌드하여 반환
return PostResponse.builder()
.postId(post.getPostId())
.board(BoardResponse.from(post.getBoard()))
.user(UserInfoResponse.from(post.getUser()))
.title(post.getTitle())
.content(post.getContent())
.bookmarkCount(post.getBookmarkCount())
.likeCount(post.getLikeCount())
.commentCount(post.getCommentCount())
.createdDate(post.getCreatedDate())
.updatedDate(post.getUpdatedDate())
// 유저 조회
User user = userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));

return getCommonPostBuilder(post, user)
.comments(commentResponses)
.attachments(attachmentResponses)
.build();
Expand Down Expand Up @@ -341,11 +340,11 @@ public List<BoardResponse> getChildBoards() {
List<Board> childBoards = boardRepository.findAllByParentBoardIsNotNull();

return childBoards.stream()
.map(BoardResponse::from)
.toList();
.map(BoardResponse::from)
.toList();
}

private PostResponse mapToPostResponse(Post post) {
private PostResponse.PostResponseBuilder getCommonPostBuilder(Post post, User user) {
return PostResponse.builder()
.postId(post.getPostId())
.user(UserInfoResponse.from(post.getUser()))
Expand All @@ -357,6 +356,12 @@ private PostResponse mapToPostResponse(Post post) {
.commentCount(post.getCommentCount())
.createdDate(post.getCreatedDate())
.updatedDate(post.getUpdatedDate())
.isLiked(postLikeRepository.existsByUserUserIdAndPostPostId(user.getUserId(), post.getPostId()))
.isBookmarked(postBookmarkRepository.existsByUserUserIdAndPostPostId(user.getUserId(), post.getPostId()));
}

private PostResponse mapToPostResponse(Post post, User user) {
return getCommonPostBuilder(post, user)
.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import org.sejongisc.backend.common.exception.CustomException;
import org.sejongisc.backend.common.exception.ErrorCode;
import org.sejongisc.backend.user.dao.UserRepository;
import org.sejongisc.backend.user.entity.Role; // Role Enum import 필요
import org.sejongisc.backend.user.entity.Role;
import org.sejongisc.backend.user.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand Down Expand Up @@ -92,7 +92,7 @@ void setUp() {
.userId(userId)
.email("test@example.com")
.name("Tester")
.role(Role.TEAM_MEMBER) // 또는 Role.USER (프로젝트 Enum 정의에 맞게)
.role(Role.TEAM_MEMBER) // 실제 프로젝트 Enum에 맞게 설정
.build();

mockParentBoard = Board.builder()
Expand All @@ -106,7 +106,7 @@ void setUp() {
.boardId(boardId)
.boardName("Child Board")
.parentBoard(mockParentBoard)
.createdBy(mockUser) // BoardResponse.from 호출 시 필요
.createdBy(mockUser)
.build();

mockPost = Post.builder()
Expand Down Expand Up @@ -245,19 +245,25 @@ void getPosts_Success() {

// Mocking
when(boardRepository.findById(boardId)).thenReturn(Optional.of(mockBoard));
when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser)); // userId 조회 추가
when(postRepository.findAllByBoard(mockBoard, pageable)).thenReturn(postPage);

// 좋아요/북마크 Mocking (mapToPostResponse에서 호출됨)
when(postLikeRepository.existsByUserUserIdAndPostPostId(userId, postId)).thenReturn(true);
when(postBookmarkRepository.existsByUserUserIdAndPostPostId(userId, postId)).thenReturn(false);

// when
// 여기서 mapToPostResponse 내부적으로 UserInfoResponse.from(), BoardResponse.from()이 호출됨
// mockUser에 Role 정보가 없으면 NPE 발생 가능 (setUp에서 처리함)
Page<PostResponse> result = postService.getPosts(boardId, page, size);
Page<PostResponse> result = postService.getPosts(boardId, userId, page, size);

// then
assertThat(result.getTotalElements()).isEqualTo(1);
assertThat(result.getContent().get(0).getPostId()).isEqualTo(postId);
// DTO 변환 확인
assertThat(result.getContent().get(0).getUser().getName()).isEqualTo(mockUser.getName());
assertThat(result.getContent().get(0).getBoard().getBoardName()).isEqualTo(mockBoard.getBoardName());
// 좋아요/북마크 상태 확인
assertThat(result.getContent().get(0).getIsLiked()).isTrue();
assertThat(result.getContent().get(0).getIsBookmarked()).isFalse();
}

@Test
Expand All @@ -272,15 +278,15 @@ void getPostDetail_Success_WithReplies() {
Comment parentComment = Comment.builder()
.commentId(UUID.randomUUID())
.post(mockPost)
.user(mockUser) // 댓글 작성자 필요 (DTO 변환 위해)
.user(mockUser)
.content("부모댓글1")
.parentComment(null)
.build();

Comment childComment = Comment.builder()
.commentId(UUID.randomUUID())
.post(mockPost)
.user(mockUser) // 댓글 작성자 필요
.user(mockUser)
.content("대댓글1")
.parentComment(parentComment)
.build();
Expand All @@ -289,20 +295,29 @@ void getPostDetail_Success_WithReplies() {

// Mocking
when(postRepository.findById(postId)).thenReturn(Optional.of(mockPost));
// 1. 부모 댓글(parentComment == null) 조회 Mocking
when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser)); // userId 조회 추가

// 댓글 조회 Mocking
when(commentRepository.findAllByPostPostIdAndParentCommentIsNull(postId, commentPageable))
.thenReturn(parentCommentPage);
// 2. 자식 댓글 조회 Mocking
when(commentRepository.findByParentComment(parentComment)).thenReturn(List.of(childComment));
// 3. 첨부파일 조회 Mocking

// 첨부파일 조회 Mocking
when(postAttachmentRepository.findAllByPostPostId(postId)).thenReturn(Collections.emptyList());

// 좋아요/북마크 Mocking (공통 빌더에서 호출됨)
when(postLikeRepository.existsByUserUserIdAndPostPostId(userId, postId)).thenReturn(true);
when(postBookmarkRepository.existsByUserUserIdAndPostPostId(userId, postId)).thenReturn(true);

// when
PostResponse result = postService.getPostDetail(postId, page, size);
PostResponse result = postService.getPostDetail(postId, userId, page, size);

// then
assertThat(result).isNotNull();
assertThat(result.getPostId()).isEqualTo(postId);
assertThat(result.getIsLiked()).isTrue();
assertThat(result.getIsBookmarked()).isTrue();

// 댓글 검증
Page<CommentResponse> commentPage = result.getComments();
Expand Down