Skip to content

Commit

Permalink
Feat: 게시글 상세 조회시 생성일자 작성자 등의 추가 정보를 보내주는 기능 구현 (#75)
Browse files Browse the repository at this point in the history
* #74 - feat: 게시글 상세 조회 시 디테일한 정보를 보내준다.

생성일자, 수정일자, 내가 쓴 글인지 등의 정보를 추가함

* #74 - test: 구현한 기능의 테스트 코드 작성
  • Loading branch information
GGHDMS authored Feb 5, 2024
1 parent 6657265 commit 2713518
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
@RequiredArgsConstructor
@RequestMapping("/posts")
public class PostController {
private static final Long DEFAULT_USER_ID = 0L;

private final PostService postService;

Expand Down Expand Up @@ -56,9 +57,13 @@ public ResponseEntity<Void> updatePost(

@GetMapping("/{post-id}")
public ResponseEntity<PostResponse> getPost(
@PathVariable("post-id") Long postId
@PathVariable("post-id") Long postId,
@AuthenticationPrincipal AuthDetails details
) {
return ResponseEntity.ok(PostResponse.from(postService.getPost(postId)));
if (details == null) {
return ResponseEntity.ok(PostResponse.from(postService.getPost(postId, DEFAULT_USER_ID), DEFAULT_USER_ID));
}
return ResponseEntity.ok(PostResponse.from(postService.getPost(postId, details.getId()), details.getId()));
}

@GetMapping("/all")
Expand All @@ -74,7 +79,11 @@ public ResponseEntity<PostListResponse> searchPost(
@PageableDefault(sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable,
@AuthenticationPrincipal AuthDetails details
) {
return ResponseEntity.ok(postService.searchPost(isbn13, pageable, details));
if (details == null) {
return ResponseEntity.ok(postService.searchPost(isbn13, DEFAULT_USER_ID, pageable));
}

return ResponseEntity.ok(postService.searchPost(isbn13, details.getId(), pageable));
}

@GetMapping("/count")
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/cotato/bookitlist/post/dto/PostDetailDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cotato.bookitlist.post.dto;

import java.time.LocalDateTime;

public record PostDetailDto(
Long postId,
Long memberId,
Long bookId,
String title,
String content,
int likeCount,
int viewCount,
LocalDateTime createdAt,
LocalDateTime modifiedAt,
boolean liked
) {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cotato.bookitlist.post.dto.response;

import cotato.bookitlist.post.dto.PostDto;
import cotato.bookitlist.post.dto.PostDetailDto;

import java.time.LocalDateTime;

public record PostResponse(
Long postId,
Expand All @@ -9,18 +11,26 @@ public record PostResponse(
String title,
String content,
int likeCount,
int viewCount
int viewCount,
LocalDateTime createdAt,
LocalDateTime modifiedAt,
boolean liked,
boolean isMine
) {

public static PostResponse from(PostDto dto) {
public static PostResponse from(PostDetailDto dto, Long memberId) {
return new PostResponse(
dto.postId(),
dto.memberId(),
dto.bookId(),
dto.title(),
dto.content(),
dto.likeCount(),
dto.viewCount()
dto.viewCount(),
dto.createdAt(),
dto.modifiedAt(),
dto.liked(),
dto.memberId().equals(memberId)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package cotato.bookitlist.post.repository.querydsl;

import cotato.bookitlist.post.dto.PostDetailDto;
import cotato.bookitlist.post.dto.PostDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.Optional;

public interface PostRepositoryCustom {
Page<PostDto> findWithLikedByIsbn13(String isbn13, Long memberId, Pageable pageable);

Optional<PostDetailDto> findDetailByPostId(Long postId, Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import cotato.bookitlist.post.dto.PostDetailDto;
import cotato.bookitlist.post.dto.PostDto;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;

import java.util.List;
import java.util.Optional;

import static cotato.bookitlist.post.domain.QPost.post;
import static cotato.bookitlist.post.domain.QPostLike.postLike;
Expand Down Expand Up @@ -58,6 +60,33 @@ public Page<PostDto> findWithLikedByIsbn13(String isbn13, Long memberId, Pageabl
return PageableExecutionUtils.getPage(result, pageable, countQuery::fetchOne);
}

@Override
public Optional<PostDetailDto> findDetailByPostId(Long postId, Long memberId) {
return Optional.ofNullable(queryFactory
.select(
Projections.constructor(
PostDetailDto.class,
post.id,
post.member.id,
post.book.id,
post.title,
post.content,
post.likeCount,
post.viewCount,
post.createdAt,
post.modifiedAt,
Expressions.cases()
.when(isLikedByMember(memberId, post.id))
.then(true)
.otherwise(false)
.as("liked")
)
)
.from(post)
.where(post.id.eq(postId))
.fetchOne());
}

private BooleanExpression isLikedByMember(Long memberId, NumberPath<Long> postId) {
return JPAExpressions.selectOne()
.from(postLike)
Expand Down
21 changes: 8 additions & 13 deletions src/main/java/cotato/bookitlist/post/service/PostService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@

import cotato.bookitlist.book.domain.entity.Book;
import cotato.bookitlist.book.repository.BookRepository;
import cotato.bookitlist.config.security.jwt.AuthDetails;
import cotato.bookitlist.member.domain.Member;
import cotato.bookitlist.member.repository.MemberRepository;
import cotato.bookitlist.post.domain.Post;
import cotato.bookitlist.post.dto.PostDto;
import cotato.bookitlist.post.dto.response.PostCountResponse;
import cotato.bookitlist.post.dto.response.PostListResponse;
import cotato.bookitlist.post.dto.PostDetailDto;
import cotato.bookitlist.post.dto.requeset.PostRegisterRequest;
import cotato.bookitlist.post.dto.requeset.PostUpdateRequest;
import cotato.bookitlist.post.dto.response.PostCountResponse;
import cotato.bookitlist.post.dto.response.PostListResponse;
import cotato.bookitlist.post.repository.PostRepository;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -48,9 +47,9 @@ public void updatePost(Long postId, PostUpdateRequest request, Long memberId) {
}

@Transactional(readOnly = true)
public PostDto getPost(Long postId) {
return PostDto.from(postRepository.findById(postId)
.orElseThrow(() -> new EntityNotFoundException("게시글을 찾을 수 없습니다.")));
public PostDetailDto getPost(Long postId, Long memberId) {
return postRepository.findDetailByPostId(postId, memberId)
.orElseThrow(() -> new EntityNotFoundException("게시글을 찾을 수 없습니다."));
}

@Transactional(readOnly = true)
Expand All @@ -59,12 +58,8 @@ public PostListResponse getAllPost(Pageable pageable) {
}

@Transactional(readOnly = true)
public PostListResponse searchPost(String isbn13, Pageable pageable, AuthDetails details) {
if (details == null) {
return PostListResponse.from(postRepository.findByBook_Isbn13(isbn13, pageable));
}

return PostListResponse.fromDto(postRepository.findWithLikedByIsbn13(isbn13, details.getId(), pageable));
public PostListResponse searchPost(String isbn13, Long memberId, Pageable pageable) {
return PostListResponse.fromDto(postRepository.findWithLikedByIsbn13(isbn13, memberId, pageable));
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,34 @@ void givenPostId_whenGettingPost_thenPostResponse() throws Exception {
;
}

@Test
@WithCustomMockUser
@DisplayName("로그인 된 유저가 본인 게시글을 조회한다.")
void givenPostIdWithLogin_whenGettingPost_thenPostResponse() throws Exception {
//given

//when & then
mockMvc.perform(get("/posts/1")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.isMine").value(true))
;
}

@Test
@WithCustomMockUser
@DisplayName("로그인 된 유저가 다른 사람 게시글을 조회한다.")
void givenPostIdWithLogin_whenGettingAnotherPersonPost_thenPostResponse() throws Exception {
//given

//when & then
mockMvc.perform(get("/posts/2")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.isMine").value(false))
;
}

@Test
@DisplayName("없는 게시글 id로 조회하면 에러를 반환한다.")
void givenNonExistedPostId_whenGettingPost_thenErrorResponse() throws Exception {
Expand Down

0 comments on commit 2713518

Please sign in to comment.