Skip to content

Commit e0397dc

Browse files
authored
AIM-73-내가-작성한-게시글-조회 (#67)
* feat: 내가 쓴 게시글 목록 조회 쿼리 구현 * feat: 내가 쓴 게시글 목록 조회 서비스 로직 구현 * feat: 마이페이지 게시글 목록 조회 API 및 후기, 리뷰 목록 api Swagger 명세 추가
1 parent 0eadfe2 commit e0397dc

File tree

3 files changed

+170
-2
lines changed

3 files changed

+170
-2
lines changed

src/main/java/targeter/aim/domain/post/controller/PostController.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.swagger.v3.oas.annotations.Operation;
44
import io.swagger.v3.oas.annotations.Parameter;
5+
import io.swagger.v3.oas.annotations.media.Schema;
56
import io.swagger.v3.oas.annotations.responses.ApiResponse;
67
import io.swagger.v3.oas.annotations.tags.Tag;
78
import jakarta.validation.Valid;
@@ -200,7 +201,13 @@ public void deletePost(
200201
)
201202
public PostDto.PostPageResponse getQnaPosts(
202203
@ModelAttribute @ParameterObject PostDto.ListSearchCondition condition,
203-
@RequestParam(defaultValue = "ALL") String filterType,
204+
@RequestParam(defaultValue = "ALL") @Parameter(
205+
description = "게시글 필터 타입",
206+
example = "ALL",
207+
schema = @Schema(
208+
allowableValues = {"ALL", "SOLO", "VS"}
209+
)
210+
) String filterType,
204211
@PageableDefault(size = 16) @ParameterObject Pageable pageable,
205212
@AuthenticationPrincipal UserDetails userDetails
206213
) {
@@ -215,11 +222,44 @@ public PostDto.PostPageResponse getQnaPosts(
215222
)
216223
public PostDto.PostPageResponse getReviewPosts(
217224
@ModelAttribute @ParameterObject PostDto.ListSearchCondition condition,
218-
@RequestParam(defaultValue = "ALL") String filterType,
225+
@RequestParam(defaultValue = "ALL")
226+
@Parameter(
227+
description = "게시글 필터 타입",
228+
example = "ALL",
229+
schema = @Schema(
230+
allowableValues = {"ALL", "SOLO", "VS"}
231+
)
232+
)String filterType,
219233
@PageableDefault(size = 16) @ParameterObject Pageable pageable,
220234
@AuthenticationPrincipal UserDetails userDetails
221235
) {
222236
return postService.getReviewPosts(condition, userDetails, pageable, filterType);
223237
}
224238

239+
@GetMapping("/me")
240+
@Operation(
241+
summary = "내가 작성한 게시글 목록 조회",
242+
description = "로그안한 사용자가 작성한 게시글을 정렬 조건에 따라 페이지네이션 조회합니다."
243+
)
244+
public PostDto.PostPageResponse getMyPosts(
245+
@RequestParam(defaultValue = "ALL")
246+
@Parameter(
247+
description = "게시글 필터 타입",
248+
example = "ALL",
249+
schema = @Schema(
250+
allowableValues = {"ALL", "VS_RECRUIT", "COMMUNITY"}
251+
)
252+
) String filterType,
253+
@ModelAttribute @ParameterObject PostDto.ListSearchCondition condition,
254+
@PageableDefault(size = 16) @ParameterObject Pageable pageable,
255+
@AuthenticationPrincipal UserDetails userDetails
256+
) {
257+
return postService.getMyPosts(
258+
filterType,
259+
condition,
260+
userDetails,
261+
pageable
262+
);
263+
}
264+
225265
}

src/main/java/targeter/aim/domain/post/repository/PostQueryRepository.java

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ private PostDto.HotPostListResponse mapToHotDto(
466466
.build();
467467
}
468468

469+
// Qna, Review 게시글 목록 조회
469470
public Page<PostDto.PostListResponse> paginateQnaAndReview(
470471
UserDetails userDetails,
471472
Pageable pageable,
@@ -612,4 +613,94 @@ private PostDto.PostListResponse mapToPostListDto(
612613
.build();
613614
}
614615

616+
// 내가 쓴 게시글 목록 조회
617+
public Page<PostDto.PostListResponse> paginateMyPosts(
618+
UserDetails userDetails,
619+
Pageable pageable,
620+
PostSortType sortType,
621+
String keyword,
622+
List<PostType> types
623+
) {
624+
JPAQuery<Tuple> query = buildBaseQueryForMyPosts(
625+
userDetails,
626+
keyword,
627+
types
628+
);
629+
630+
applySorting(query, sortType);
631+
632+
List<Tuple> tuples = query
633+
.offset(pageable.getOffset())
634+
.limit(pageable.getPageSize())
635+
.fetch();
636+
637+
Long total = buildCountQueryForMyPosts(
638+
userDetails,
639+
keyword,
640+
types
641+
).fetchOne();
642+
643+
return new PageImpl<>(
644+
enrichPostListDetails(tuples),
645+
pageable,
646+
total == null ? 0 : total
647+
);
648+
}
649+
650+
private JPAQuery<Tuple> buildBaseQueryForMyPosts(
651+
UserDetails userDetails,
652+
String keyword,
653+
List<PostType> types
654+
) {
655+
JPAQuery<Tuple> query = queryFactory
656+
.select(
657+
post,
658+
JPAExpressions.selectOne()
659+
.from(postLiked)
660+
.where(
661+
postLiked.post.eq(post)
662+
.and(postLiked.user.id.eq(userDetails.getUser().getId()))
663+
).exists(),
664+
JPAExpressions.select(postLiked.count())
665+
.from(postLiked)
666+
.where(postLiked.post.eq(post))
667+
)
668+
.from(post)
669+
.where(
670+
post.user.id.eq(userDetails.getUser().getId()),
671+
types != null ? post.type.in(types) : null
672+
)
673+
.leftJoin(post.user).fetchJoin()
674+
.leftJoin(post.user.tier).fetchJoin()
675+
.leftJoin(post.user.profileImage).fetchJoin();
676+
677+
BooleanExpression keywordPredicate = keywordCondition(keyword);
678+
if (keywordPredicate != null) {
679+
query.where(keywordPredicate);
680+
}
681+
682+
return query;
683+
}
684+
685+
private JPAQuery<Long> buildCountQueryForMyPosts(
686+
UserDetails userDetails,
687+
String keyword,
688+
List<PostType> types
689+
) {
690+
JPAQuery<Long> query = queryFactory
691+
.select(post.count())
692+
.from(post)
693+
.where(
694+
post.user.id.eq(userDetails.getUser().getId()),
695+
types != null ? post.type.in(types) : null
696+
);
697+
698+
BooleanExpression keywordPredicate = keywordCondition(keyword);
699+
if (keywordPredicate != null) {
700+
query.where(keywordPredicate);
701+
}
702+
703+
return query;
704+
}
705+
615706
}

src/main/java/targeter/aim/domain/post/service/PostService.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,4 +493,41 @@ private ChallengeMode parseFilterType(String filterType) {
493493
};
494494
}
495495

496+
@Transactional(readOnly = true)
497+
public PostDto.PostPageResponse getMyPosts(
498+
String filterType,
499+
PostDto.ListSearchCondition condition,
500+
UserDetails userDetails,
501+
Pageable pageable
502+
) {
503+
if (userDetails == null) {
504+
throw new RestException(ErrorCode.AUTH_LOGIN_REQUIRED);
505+
}
506+
507+
PostSortType sortType = parseSortType(condition.getSort());
508+
String keyword = normalizeKeyword(condition.getKeyword());
509+
510+
List<PostType> types;
511+
if (filterType == null || filterType.equals("ALL")) {
512+
types = null;
513+
} else {
514+
types = switch (filterType) {
515+
case "VS_RECRUIT" -> List.of(PostType.VS_RECRUIT);
516+
case "COMMUNITY" -> List.of(PostType.Q_AND_A, PostType.REVIEW);
517+
default -> throw new RestException(ErrorCode.GLOBAL_BAD_REQUEST);
518+
};
519+
}
520+
521+
Page<PostDto.PostListResponse> page =
522+
postQueryRepository.paginateMyPosts(
523+
userDetails,
524+
pageable,
525+
sortType,
526+
keyword,
527+
types
528+
);
529+
530+
return PostDto.PostPageResponse.from(page);
531+
532+
}
496533
}

0 commit comments

Comments
 (0)