-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GETP-177 feat: 지원한 프로젝트 목록 조회 기능 구현 (#117)
* GETP-177 feat: 내 프로젝트 지원 목록 기능 구현 * GETP-177 test: 내 프로젝트 지원 목록 기능 테스트 작성 * GETP-177 fix: 순환 의존성 해결 및 엔드포인트 수정 * GETP-177 test: 순환 의존성 해결 및 엔드 포인트 수정 후 테스트 작성 --------- Co-authored-by: 신찬규(Shin Changyu) <[email protected]> Co-authored-by: Changyu Shin <[email protected]>
- Loading branch information
1 parent
841b7de
commit 790c677
Showing
12 changed files
with
394 additions
and
19 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
src/main/java/es/princip/getp/domain/project/query/dao/AppliedProjectDao.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package es.princip.getp.domain.project.query.dao; | ||
|
||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
import es.princip.getp.domain.project.query.dto.AppliedProjectCardResponse; | ||
|
||
public interface AppliedProjectDao { | ||
|
||
Page<AppliedProjectCardResponse> findPagedMyAppliedProjects(Pageable pageable, Long memberId); | ||
} |
75 changes: 75 additions & 0 deletions
75
src/main/java/es/princip/getp/domain/project/query/dao/AppliedProjectQueryDslDao.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package es.princip.getp.domain.project.query.dao; | ||
|
||
import com.querydsl.jpa.impl.JPAQuery; | ||
import es.princip.getp.domain.project.command.domain.Project; | ||
import es.princip.getp.domain.project.query.dto.AppliedProjectCardResponse; | ||
import es.princip.getp.infra.support.QueryDslSupport; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static es.princip.getp.domain.people.command.domain.QPeople.people; | ||
import static es.princip.getp.domain.project.command.domain.QProject.project; | ||
import static es.princip.getp.domain.project.command.domain.QProjectApplication.projectApplication; | ||
import static es.princip.getp.domain.project.query.dao.ProjectDaoUtil.toProjectIds; | ||
|
||
@Repository | ||
@RequiredArgsConstructor | ||
public class AppliedProjectQueryDslDao extends QueryDslSupport implements AppliedProjectDao{ | ||
|
||
private final ProjectApplicationDao projectApplicationDao; | ||
|
||
@Override | ||
public Page<AppliedProjectCardResponse> findPagedMyAppliedProjects( | ||
final Pageable pageable, | ||
final Long memberId | ||
) { | ||
final List<Project> projects = getAppliedProjects(pageable, memberId); | ||
final Long[] projectIds = toProjectIds(projects); | ||
final Map<Long, Long> projectApplicationCounts = projectApplicationDao.countByProjectIds(projectIds); | ||
final List<AppliedProjectCardResponse> content = assembleAppliedProjectCardResponse(projects, projectApplicationCounts); | ||
|
||
return applyPagination( | ||
pageable, | ||
content, | ||
countQuery -> getAppliedProjectsCountQuery(memberId) | ||
); | ||
} | ||
|
||
private List<Project> getAppliedProjects( | ||
final Pageable pageable, | ||
final Long memberId | ||
) { | ||
return queryFactory.selectFrom(project) | ||
.join(projectApplication).on(projectApplication.projectId.eq(project.projectId)) | ||
.join(people).on(people.peopleId.eq(projectApplication.applicantId)) | ||
.where(people.memberId.eq(memberId)) | ||
.offset(pageable.getOffset()) | ||
.limit(pageable.getPageSize()) | ||
.fetch(); | ||
} | ||
|
||
private JPAQuery<Long> getAppliedProjectsCountQuery(final Long memberId) { | ||
return queryFactory.select(project.count()) | ||
.from(project) | ||
.join(projectApplication).on(projectApplication.projectId.eq(project.projectId)) | ||
.join(people).on(people.peopleId.eq(projectApplication.applicantId)) | ||
.where(people.memberId.eq(memberId)); | ||
} | ||
|
||
private List<AppliedProjectCardResponse> assembleAppliedProjectCardResponse( | ||
final List<Project> projects, | ||
final Map<Long, Long> projectApplicationCounts | ||
) { | ||
return projects.stream() | ||
.map(project -> AppliedProjectCardResponse.of( | ||
project, | ||
projectApplicationCounts.get(project.getProjectId()) | ||
)) | ||
.toList(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
src/main/java/es/princip/getp/domain/project/query/dto/AppliedProjectCardResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package es.princip.getp.domain.project.query.dto; | ||
|
||
import es.princip.getp.domain.common.domain.Duration; | ||
import es.princip.getp.domain.common.dto.HashtagsResponse; | ||
import es.princip.getp.domain.project.command.domain.Project; | ||
import es.princip.getp.domain.project.command.domain.ProjectStatus; | ||
|
||
public record AppliedProjectCardResponse( | ||
Long projectId, | ||
String title, | ||
Long payment, | ||
Long applicantsCount, | ||
Long estimatedDays, | ||
Duration applicationDuration, | ||
HashtagsResponse hashtags, | ||
String description, | ||
ProjectStatus status | ||
) { | ||
|
||
public static AppliedProjectCardResponse of(final Project project, final Long applicantsCount) { | ||
return new AppliedProjectCardResponse( | ||
project.getProjectId(), | ||
project.getTitle(), | ||
project.getPayment(), | ||
applicantsCount, | ||
project.getEstimatedDuration().days(), | ||
project.getApplicationDuration(), | ||
HashtagsResponse.from(project.getHashtags()), | ||
project.getDescription(), | ||
project.getStatus() | ||
); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
...java/es/princip/getp/domain/project/query/presentation/AppliedProjectQueryController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package es.princip.getp.domain.project.query.presentation; | ||
|
||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import es.princip.getp.domain.project.query.dao.AppliedProjectDao; | ||
import es.princip.getp.domain.project.query.dto.AppliedProjectCardResponse; | ||
import es.princip.getp.infra.dto.response.ApiResponse; | ||
import es.princip.getp.infra.dto.response.ApiResponse.ApiSuccessResult; | ||
import es.princip.getp.infra.dto.response.PageResponse; | ||
import es.princip.getp.infra.security.details.PrincipalDetails; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
import org.springframework.data.domain.Sort; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.data.web.PageableDefault; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.access.prepost.PreAuthorize; | ||
import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
|
||
@RestController | ||
@RequestMapping("/people") | ||
@RequiredArgsConstructor | ||
public class AppliedProjectQueryController { | ||
|
||
private final AppliedProjectDao appliedProjectDao; | ||
|
||
@GetMapping("/me/projects") | ||
@PreAuthorize("hasRole('PEOPLE') and isAuthenticated()") | ||
public ResponseEntity<ApiSuccessResult<PageResponse<AppliedProjectCardResponse>>> getMyAppliedProjects( | ||
@PageableDefault(sort = "projectId", direction = Sort.Direction.DESC) final Pageable pageable, | ||
@AuthenticationPrincipal final PrincipalDetails principalDetails | ||
) { | ||
final Long memberId = principalDetails.getMember().getMemberId(); | ||
final Page<AppliedProjectCardResponse> page = appliedProjectDao.findPagedMyAppliedProjects(pageable, memberId); | ||
final PageResponse<AppliedProjectCardResponse> response = PageResponse.from(page); | ||
return ApiResponse.success(HttpStatus.OK, response); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/test/java/es/princip/getp/domain/common/description/PaginationDescription.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package es.princip.getp.domain.common.description; | ||
|
||
|
||
import org.springframework.restdocs.request.ParameterDescriptor; | ||
|
||
import static es.princip.getp.infra.util.ParameterDescriptorHelper.getDescriptor; | ||
|
||
public class PaginationDescription { | ||
|
||
public static ParameterDescriptor[] description(final int page, final int size, final String sort) { | ||
return new ParameterDescriptor[] { | ||
getDescriptor("page", "페이지 번호", "default", String.valueOf(page)), | ||
getDescriptor("size", "페이지 크기", "default", String.valueOf(size)), | ||
getDescriptor("sort", "정렬 방식", "default", sort) | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
src/test/java/es/princip/getp/domain/project/query/dao/AppliedProjectDaoTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package es.princip.getp.domain.project.query.dao; | ||
|
||
import es.princip.getp.domain.people.query.infra.PeopleDataLoader; | ||
import es.princip.getp.domain.project.query.dto.AppliedProjectCardResponse; | ||
import es.princip.getp.domain.project.query.infra.ProjectApplicationDataLoader; | ||
import es.princip.getp.domain.project.query.infra.ProjectDataLoader; | ||
import es.princip.getp.infra.DataLoader; | ||
import es.princip.getp.infra.support.DaoTest; | ||
import jakarta.persistence.EntityManager; | ||
import jakarta.persistence.PersistenceContext; | ||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.PageRequest; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
import java.util.List; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
public class AppliedProjectDaoTest extends DaoTest { | ||
|
||
private static final int TEST_SIZE = 20; | ||
private static final int PAGE_SIZE = 10; | ||
|
||
@PersistenceContext | ||
private EntityManager entityManager; | ||
|
||
@Autowired | ||
private AppliedProjectDao appliedProjectDao; | ||
|
||
private List<DataLoader> dataLoaders; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
dataLoaders = List.of( | ||
new PeopleDataLoader(entityManager), | ||
new ProjectDataLoader(entityManager), | ||
new ProjectApplicationDataLoader(entityManager) | ||
); | ||
dataLoaders.forEach(dataLoader -> dataLoader.load(TEST_SIZE)); | ||
} | ||
|
||
@AfterEach | ||
void teardown() { | ||
dataLoaders.forEach(DataLoader::teardown); | ||
} | ||
|
||
@Nested | ||
class 지원한_프로젝트_목록_조회 { | ||
|
||
final Pageable pageable = PageRequest.of(0, PAGE_SIZE); | ||
|
||
@Test | ||
void 프로젝트_목록_조회() { | ||
final Page<AppliedProjectCardResponse> response = appliedProjectDao.findPagedMyAppliedProjects( | ||
pageable, | ||
1L | ||
); | ||
|
||
assertThat(response.getContent()).allSatisfy(content -> { | ||
assertThat(content).usingRecursiveComparison().isNotNull(); | ||
}); | ||
assertThat(response.getNumberOfElements()).isGreaterThan(0); | ||
} | ||
} | ||
} |
Oops, something went wrong.