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
9 changes: 8 additions & 1 deletion src/docs/asciidoc/posts.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@
operation::post-controller-test/create-post[snippets='http-request,curl-request,request-headers,request-fields,http-response']

[[게시글-상세-조회]]
=== 게시글 상세 조회 (미구현)
=== `GET` 게시글 상세 조회

operation::post-controller-test/find-post[snippets='http-request,curl-request,path-parameters,http-response,response-fields']

[[사진-투표-현황-조회]]
=== `GET` 사진 투표 현황 조회

operation::post-controller-test/find-vote-status[snippets='http-request,curl-request,request-headers,path-parameters,http-response,response-fields']

[[게시글-목록-조회]]

[[내가-작성한-게시글-조회]]
=== `GET` 내가 작성한 게시글 조회

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class HttpLoggingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
if (request.getRequestURI().startsWith("/docs")) {
if (request.getRequestURI().startsWith("/docs") || request.getRequestURI().startsWith("/h2-console")) {
chain.doFilter(request, response);
return;
}
Expand Down
62 changes: 43 additions & 19 deletions src/main/java/com/swyp8team2/post/application/PostService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@
import com.swyp8team2.post.domain.PostRepository;
import com.swyp8team2.post.presentation.dto.CreatePostRequest;
import com.swyp8team2.post.presentation.dto.PostResponse;
import com.swyp8team2.post.presentation.dto.PostImageVoteStatusResponse;
import com.swyp8team2.post.presentation.dto.SimplePostResponse;
import com.swyp8team2.post.presentation.dto.VoteResponseDto;
import com.swyp8team2.post.presentation.dto.PostImageResponse;
import com.swyp8team2.user.domain.User;
import com.swyp8team2.user.domain.UserRepository;
import com.swyp8team2.vote.domain.Vote;
import com.swyp8team2.vote.domain.VoteRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

@Service
@Transactional(readOnly = true)
Expand All @@ -47,43 +48,47 @@ public Long create(Long userId, CreatePostRequest request) {

private List<PostImage> createPostImages(CreatePostRequest request) {
PostImageNameGenerator nameGenerator = new PostImageNameGenerator();
return request.votes().stream()
return request.images().stream()
.map(voteRequestDto -> PostImage.create(
nameGenerator.generate(),
voteRequestDto.imageFileId()
)).toList();
}

public PostResponse findById(Long postId) {
public PostResponse findById(Long userId, Long postId) {
Post post = postRepository.findById(postId)
.orElseThrow(() -> new BadRequestException(ErrorCode.POST_NOT_FOUND));
User user = userRepository.findById(post.getUserId())
User author = userRepository.findById(post.getUserId())
.orElseThrow(() -> new BadRequestException(ErrorCode.USER_NOT_FOUND));
List<PostImageResponse> votes = createPostImageResponse(userId, postId, post);
return PostResponse.of(post, author, votes);
}

private List<PostImageResponse> createPostImageResponse(Long userId, Long postId, Post post) {
List<PostImage> images = post.getImages();
List<VoteResponseDto> votes = images.stream()
.map(image -> createVoteResponseDto(image, images))
return images.stream()
.map(image -> createVoteResponseDto(image, userId, postId))
.toList();
return PostResponse.of(post, user, votes);
}

private VoteResponseDto createVoteResponseDto(PostImage image, List<PostImage> images) {
private PostImageResponse createVoteResponseDto(PostImage image, Long userId, Long postId) {
ImageFile imageFile = imageFileRepository.findById(image.getImageFileId())
.orElseThrow(() -> new InternalServerException(ErrorCode.IMAGE_FILE_NOT_FOUND));
return new VoteResponseDto(
boolean voted = Objects.nonNull(userId) && getVoted(image, userId, postId);
return new PostImageResponse(
image.getId(),
image.getName(),
imageFile.getImageUrl(),
image.getVoteCount(),
ratioCalculator.calculateRatio(getTotalVoteCount(images), image.getVoteCount()),
false //TODO: implement
voted
);
}

private int getTotalVoteCount(List<PostImage> images) {
int totalVoteCount = 0;
for (PostImage image : images) {
totalVoteCount += image.getVoteCount();
}
return totalVoteCount;
private Boolean getVoted(PostImage image, Long userId, Long postId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new BadRequestException(ErrorCode.USER_NOT_FOUND));
return voteRepository.findByUserSeqAndPostId(user.getSeq(), postId)
.map(vote -> vote.getPostImageId().equals(image.getId()))
.orElse(false);
}

public CursorBasePaginatedResponse<SimplePostResponse> findMyPosts(Long userId, Long cursor, int size) {
Expand All @@ -107,4 +112,23 @@ public CursorBasePaginatedResponse<SimplePostResponse> findVotedPosts(Long userI
Slice<Post> postSlice = postRepository.findByIdIn(postIds, cursor, PageRequest.ofSize(size));
return CursorBasePaginatedResponse.of(postSlice.map(this::createSimplePostResponse));
}

public List<PostImageVoteStatusResponse> findPostStatus(Long postId) {
Post post = postRepository.findById(postId)
.orElseThrow(() -> new BadRequestException(ErrorCode.POST_NOT_FOUND));
int totalVoteCount = getTotalVoteCount(post.getImages());
return post.getImages().stream()
.map(image -> {
String ratio = ratioCalculator.calculate(image.getVoteCount(), totalVoteCount);
return new PostImageVoteStatusResponse(image.getName(), image.getVoteCount(), ratio);
}).toList();
}

private int getTotalVoteCount(List<PostImage> images) {
int totalVoteCount = 0;
for (PostImage image : images) {
totalVoteCount += image.getVoteCount();
}
return totalVoteCount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@Component
public class RatioCalculator {

public String calculateRatio(int totalVoteCount, int voteCount) {
public String calculate(int totalVoteCount, int voteCount) {
if (totalVoteCount == 0) {
return "0.0";
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/swyp8team2/post/domain/Post.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void vote(Long imageId) {
PostImage image = images.stream()
.filter(postImage -> postImage.getId().equals(imageId))
.findFirst()
.orElseThrow(() -> new InternalServerException(ErrorCode.POST_IMAGE_NOT_FOUND));
.orElseThrow(() -> new BadRequestException(ErrorCode.POST_IMAGE_NOT_FOUND));
image.increaseVoteCount();
}

Expand Down
28 changes: 24 additions & 4 deletions src/main/java/com/swyp8team2/post/presentation/PostController.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import com.swyp8team2.post.application.PostService;
import com.swyp8team2.post.presentation.dto.AuthorDto;
import com.swyp8team2.post.presentation.dto.CreatePostRequest;
import com.swyp8team2.post.presentation.dto.PostImageVoteStatusResponse;
import com.swyp8team2.post.presentation.dto.PostResponse;
import com.swyp8team2.post.presentation.dto.SimplePostResponse;
import com.swyp8team2.post.presentation.dto.VoteResponseDto;
import com.swyp8team2.post.presentation.dto.PostImageResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import lombok.RequiredArgsConstructor;
Expand All @@ -24,6 +25,7 @@

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@RestController
@RequiredArgsConstructor
Expand All @@ -41,7 +43,25 @@ public ResponseEntity<Void> createPost(
return ResponseEntity.ok().build();
}

@GetMapping("/{shareUrl}")
@GetMapping("/{postId}")
public ResponseEntity<PostResponse> findPost(
@PathVariable("postId") Long postId,
@AuthenticationPrincipal UserInfo userInfo
) {
Long userId = Optional.ofNullable(userInfo)
.map(UserInfo::userId)
.orElse(null);
return ResponseEntity.ok(postService.findById(userId, postId));
}

@GetMapping("/{postId}/status")
public ResponseEntity<List<PostImageVoteStatusResponse>> findVoteStatus(
@PathVariable("postId") Long postId
) {
return ResponseEntity.ok(postService.findPostStatus(postId));
}

// @GetMapping("/{shareUrl}")
public ResponseEntity<PostResponse> findPost(@PathVariable("shareUrl") String shareUrl) {
return ResponseEntity.ok(new PostResponse(
1L,
Expand All @@ -52,8 +72,8 @@ public ResponseEntity<PostResponse> findPost(@PathVariable("shareUrl") String sh
),
"description",
List.of(
new VoteResponseDto(1L, "https://image.photopic.site/1", 3, "60.0", true),
new VoteResponseDto(2L, "https://image.photopic.site/2", 2, "40.0", false)
new PostImageResponse(1L, "뽀또A", "https://image.photopic.site/1", true),
new PostImageResponse(2L, "뽀또B", "https://image.photopic.site/2", false)
),
"https://photopic.site/shareurl",
LocalDateTime.of(2025, 2, 13, 12, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

import java.util.List;

Expand All @@ -11,6 +10,6 @@ public record CreatePostRequest(
String description,

@Valid @NotNull
List<VoteRequestDto> votes
List<PostImageRequestDto> images
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import jakarta.validation.constraints.NotNull;

public record VoteRequestDto(
public record PostImageRequestDto(
@NotNull
Long imageFileId
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package com.swyp8team2.post.presentation.dto;

public record VoteResponseDto(
public record PostImageResponse(
Long id,
String imageName,
String imageUrl,
int voteCount,
String voteRatio,
boolean voted
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.swyp8team2.post.presentation.dto;

public record PostImageVoteStatusResponse(
String imageName,
int voteCount,
String voteRatio
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ public record PostResponse(
Long id,
AuthorDto author,
String description,
List<VoteResponseDto> votes,
List<PostImageResponse> images,
String shareUrl,
LocalDateTime createdAt
) {
public static PostResponse of(Post post, User user, List<VoteResponseDto> votes) {
public static PostResponse of(Post post, User user, List<PostImageResponse> images) {
return new PostResponse(
post.getId(),
AuthorDto.of(user),
post.getDescription(),
votes,
images,
post.getShareUrl(),
post.getCreatedAt()
);
Expand Down
Loading