Skip to content

Commit

Permalink
Merge pull request #186 from teamterning/feat/#185
Browse files Browse the repository at this point in the history
[✨feat/#185]: 공고 조회 페이지네이션 기능 도입 및 서비스 로직 개선
  • Loading branch information
jsoonworld authored Dec 21, 2024
2 parents afb20cd + be616ba commit f56834d
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.terning.terningserver.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
Expand All @@ -26,13 +28,13 @@ public class HomeController implements HomeSwagger {
@GetMapping("/home")
public ResponseEntity<SuccessResponse<HomeAnnouncementsResponseDto>> getAnnouncements(
@AuthenticationPrincipal Long userId,
@RequestParam(value = "sortBy", required = false, defaultValue = "deadlineSoon") String sortBy
){
HomeAnnouncementsResponseDto announcements = homeService.getAnnouncements(userId, sortBy);

@RequestParam(value = "sortBy", required = false, defaultValue = "deadlineSoon") String sortBy,
@PageableDefault(size = 10) Pageable pageable) {
HomeAnnouncementsResponseDto announcements = homeService.getAnnouncements(userId, sortBy, pageable);
return ResponseEntity.ok(SuccessResponse.of(SUCCESS_GET_ANNOUNCEMENTS, announcements));
}


@GetMapping("/home/upcoming")
public ResponseEntity<SuccessResponse<List<UpcomingScrapResponseDto>>> getUpcomingScraps(
@AuthenticationPrincipal Long userId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.terning.terningserver.dto.user.response.HomeAnnouncementsResponseDto;
import org.terning.terningserver.dto.user.response.UpcomingScrapResponseDto;
Expand All @@ -15,7 +16,8 @@ public interface HomeSwagger {
@Operation(summary = "홈화면 > 나에게 딱맞는 인턴 공고 조회", description = "특정 사용자에 필터링 조건에 맞는 인턴 공고 정보를 조회하는 API")
ResponseEntity<SuccessResponse<HomeAnnouncementsResponseDto>> getAnnouncements(
Long userId,
String sortBy
String sortBy,
Pageable pageable
);

@Operation(summary = "홈화면 > 곧 마감인 스크랩 공고 조회", description = "곧 마감인 스크랩 공고를 조회하는 API")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@

@Builder
public record HomeAnnouncementsResponseDto(
int totalCount, // 필터링 된 공고 총 개수
int totalPages,
long totalCount,
boolean hasNext,
List<HomeResponseDto> result
) {
public static HomeAnnouncementsResponseDto of(final int totalCount, final List<HomeResponseDto> announcements){
public static HomeAnnouncementsResponseDto of(
final int totalPages,
final long totalCount,
final boolean hasNext,
final List<HomeResponseDto> announcements) {
return HomeAnnouncementsResponseDto.builder()
.totalPages(totalPages)
.totalCount(totalCount)
.hasNext(hasNext)
.result(announcements)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ public interface InternshipRepositoryCustom {

Page<InternshipAnnouncement> searchInternshipAnnouncement(String keyword, String sortBy, Pageable pageable);

List<Tuple> findFilteredInternshipsWithScrapInfo(User user, String sortBy);

Page<Tuple> findFilteredInternshipsWithScrapInfo(User user, String sortBy, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ private OrderSpecifier createOrderSpecifier(String sortBy) {
}

@Override
public List<Tuple> findFilteredInternshipsWithScrapInfo(User user, String sortBy){
return jpaQueryFactory
.select(internshipAnnouncement, scrap.id, scrap.color) // tuple -> Scrap 정보 한번에 불러오기
public Page<Tuple> findFilteredInternshipsWithScrapInfo(User user, String sortBy, Pageable pageable) {
List<Tuple> content = jpaQueryFactory
.select(internshipAnnouncement, scrap.id, scrap.color)
.from(internshipAnnouncement)
.leftJoin(internshipAnnouncement.scraps, scrap).on(scrap.user.eq(user))
.where(
Expand All @@ -125,9 +125,23 @@ public List<Tuple> findFilteredInternshipsWithScrapInfo(User user, String sortBy
sortAnnouncementsByDeadline().asc(),
getSortOrder(sortBy)
)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

JPAQuery<Long> countQuery = jpaQueryFactory
.select(internshipAnnouncement.count())
.from(internshipAnnouncement)
.where(
getJobTypeFilter(user),
getGraduatingFilter(user),
getWorkingPeriodFilter(user),
getStartDateFilter(user)
);

return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
}

private BooleanExpression getGraduatingFilter(User user){
if(user.getFilter().getGrade() != Grade.SENIOR){
return internshipAnnouncement.isGraduating.isFalse();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.terning.terningserver.service;

import org.springframework.data.domain.Pageable;
import org.terning.terningserver.dto.user.response.HomeAnnouncementsResponseDto;

public interface HomeService {

HomeAnnouncementsResponseDto getAnnouncements(Long userId, String sortBy);
HomeAnnouncementsResponseDto getAnnouncements(Long userId, String sortBy, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.querydsl.core.Tuple;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.terning.terningserver.domain.InternshipAnnouncement;
Expand All @@ -22,47 +24,71 @@
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class HomeServiceImpl implements HomeService{
public class HomeServiceImpl implements HomeService {

private final InternshipRepository internshipRepository;
private final UserRepository userRepository;

@Override
public HomeAnnouncementsResponseDto getAnnouncements(Long userId, String sortBy){
User user = userRepository.findById(userId).orElseThrow(
() -> new CustomException(ErrorMessage.NOT_FOUND_USER_EXCEPTION)
);
public HomeAnnouncementsResponseDto getAnnouncements(Long userId, String sortBy, Pageable pageable) {
User user = getUserById(userId);

// 유저의 필터 정보가 없는 경우
if(user.getFilter() == null){
return HomeAnnouncementsResponseDto.of(0,List.of());
if (user.getFilter() == null) {
return createEmptyResponse();
}

List<Tuple> announcements = internshipRepository.findFilteredInternshipsWithScrapInfo(user, sortBy);
Page<Tuple> pagedAnnouncements = internshipRepository.findFilteredInternshipsWithScrapInfo(user, sortBy, pageable);

// 해당하는 공고가 없는 경우
if(announcements.isEmpty()){
return HomeAnnouncementsResponseDto.of(0, List.of());
if (pagedAnnouncements.isEmpty()) {
return createEmptyResponse();
}

List<HomeResponseDto> responseDtos = announcements.stream()
List<HomeResponseDto> responseDtos = mapToHomeResponseDtos(pagedAnnouncements);

return createResponse(pagedAnnouncements, responseDtos);
}

private User getUserById(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorMessage.NOT_FOUND_USER_EXCEPTION));
}

private HomeAnnouncementsResponseDto createEmptyResponse() {
return HomeAnnouncementsResponseDto.of(0, 0, false, List.of());
}

private List<HomeResponseDto> mapToHomeResponseDtos(Page<Tuple> pagedAnnouncements) {
return pagedAnnouncements.getContent().stream()
.map(tuple -> {
InternshipAnnouncement announcement = tuple.get(internshipAnnouncement);
Long scrapId = tuple.get(scrap.id);
Color color = tuple.get(scrap.color);
boolean isScrapped = (scrapId != null); // 스크랩 여부

// scrap 하지 않은 경우 color는 지정되지 않아야 한다.
String colorValue = (isScrapped && color != null) ? color.getColorValue() : null;
boolean isScrapped = isScrapped(scrapId);
String colorValue = determineColorValue(isScrapped, color);

return HomeResponseDto.of(announcement, isScrapped, colorValue);
})
.toList();

return HomeAnnouncementsResponseDto.of(responseDtos.size(), responseDtos);
}

private boolean isScrapped(Long scrapId) {
return scrapId != null;
}
}

private String determineColorValue(boolean isScrapped, Color color) {
if (isScrapped && color != null) {
return color.getColorValue();
}
return null;
}

private HomeAnnouncementsResponseDto createResponse(Page<Tuple> pagedAnnouncements, List<HomeResponseDto> responseDtos) {
return HomeAnnouncementsResponseDto.of(
pagedAnnouncements.getTotalPages(),
pagedAnnouncements.getTotalElements(),
pagedAnnouncements.hasNext(),
responseDtos
);
}
}

0 comments on commit f56834d

Please sign in to comment.