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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.solidconnection.application.controller;

import com.example.solidconnection.application.dto.ApplicationPreviewResponse;
import com.example.solidconnection.application.dto.ApplicationSubmissionResponse;
import com.example.solidconnection.application.dto.ApplicationsResponse;
import com.example.solidconnection.application.dto.ApplyRequest;
Expand Down Expand Up @@ -37,6 +38,14 @@ public ResponseEntity<ApplicationSubmissionResponse> apply(
.body(applicationSubmissionResponse);
}

@GetMapping("/preview")
public ResponseEntity<ApplicationPreviewResponse> getApplicationPreview(
@AuthorizedUser long siteUserId
) {
ApplicationPreviewResponse result = applicationQueryService.getApplicantUniversityPreviews(siteUserId);
return ResponseEntity.ok(result);
}

// @RequireRoleAccess(roles = {Role.ADMIN}) // todo : 추후 어드민 페이지에서 권한 변경 기능 추가 필요
@GetMapping
public ResponseEntity<ApplicationsResponse> getApplicants(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.solidconnection.application.dto;

import java.util.List;

public record ApplicationPreviewResponse(
long totalUniversityCount,
List<ApplicationUniversityPreviewResponse> universities) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.example.solidconnection.application.dto;

import com.example.solidconnection.university.domain.UnivApplyInfo;

public record ApplicationUniversityPreviewResponse(
long id,
String koreanName,
Integer studentCapacity,
String region,
String country,
String logoImageUrl,
String backgroundImageUrl) {

public static ApplicationUniversityPreviewResponse from(UnivApplyInfo univApplyInfo) {
return new ApplicationUniversityPreviewResponse(
univApplyInfo.getId(),
univApplyInfo.getKoreanName(),
univApplyInfo.getStudentCapacity(),
univApplyInfo.getUniversity().getRegion().getKoreanName(),
univApplyInfo.getUniversity().getCountry().getKoreanName(),
univApplyInfo.getUniversity().getLogoImageUrl(),
univApplyInfo.getUniversity().getBackgroundImageUrl()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static com.example.solidconnection.common.exception.ErrorCode.APPLICATION_NOT_FOUND;

import com.example.solidconnection.application.domain.Application;
import com.example.solidconnection.application.dto.ApplicationUniversityPreviewResponse;
import com.example.solidconnection.common.VerifyStatus;
import com.example.solidconnection.common.exception.CustomException;
import java.util.List;
Expand All @@ -29,6 +30,38 @@ List<Application> findAllByUnivApplyInfoIds(
@Param("status") VerifyStatus status,
@Param("termId") long termId);

@Query("""
SELECT new com.example.solidconnection.application.dto.ApplicationUniversityPreviewResponse(
uai.id,
uai.koreanName,
uai.studentCapacity,
region.koreanName,
country.koreanName,
university.logoImageUrl,
university.backgroundImageUrl
)
FROM UnivApplyInfo uai
JOIN uai.university university
JOIN university.region region
JOIN university.country country
WHERE uai.termId = :termId
AND uai.homeUniversity.id = :homeUniversityId
AND EXISTS (
SELECT application.id
FROM Application application
JOIN application.choices choice
WHERE choice.univApplyInfoId = uai.id
AND application.verifyStatus = :status
AND application.termId = :termId
AND application.isDelete = false
)
ORDER BY uai.koreanName
""")
Comment thread
Hexeong marked this conversation as resolved.
List<ApplicationUniversityPreviewResponse> findApplicantUniversityPreviews(
@Param("status") VerifyStatus status,
@Param("termId") long termId,
@Param("homeUniversityId") long homeUniversityId);

Optional<Application> findTopBySiteUserIdAndTermIdAndIsDeleteFalseOrderByIdDesc(long siteUserId, long termId);

default Application getApplicationBySiteUserIdAndTermId(long siteUserId, long termId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import static com.example.solidconnection.common.exception.ErrorCode.APPLICATION_NOT_APPROVED;
import static com.example.solidconnection.common.exception.ErrorCode.CURRENT_TERM_NOT_FOUND;
import static com.example.solidconnection.common.exception.ErrorCode.SCHOOL_EMAIL_NOT_VERIFIED;
import static com.example.solidconnection.common.exception.ErrorCode.USER_NOT_FOUND;

import com.example.solidconnection.application.domain.Application;
import com.example.solidconnection.application.domain.ApplicationChoice;
import com.example.solidconnection.application.dto.ApplicantsResponse;
import com.example.solidconnection.application.dto.ApplicationPreviewResponse;
import com.example.solidconnection.application.dto.ApplicationsResponse;
import com.example.solidconnection.application.repository.ApplicationRepository;
import com.example.solidconnection.common.VerifyStatus;
Expand Down Expand Up @@ -41,6 +43,27 @@ public class ApplicationQueryService {
private final TermRepository termRepository;
private final HomeUniversityRepository homeUniversityRepository;

@Transactional(readOnly = true)
public ApplicationPreviewResponse getApplicantUniversityPreviews(long siteUserId) {
SiteUser siteUser = siteUserRepository.findById(siteUserId)
.orElseThrow(() -> new CustomException(USER_NOT_FOUND));

if (siteUser.getHomeUniversityId() == null) {
throw new CustomException(SCHOOL_EMAIL_NOT_VERIFIED);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

Term term = termRepository.findByIsCurrentTrue()
.orElseThrow(() -> new CustomException(CURRENT_TERM_NOT_FOUND));

return new ApplicationPreviewResponse(
univApplyInfoRepository.countByTermIdAndHomeUniversityId(term.getId(), siteUser.getHomeUniversityId()),
applicationRepository.findApplicantUniversityPreviews(
VerifyStatus.APPROVED,
term.getId(),
siteUser.getHomeUniversityId())
);
}

@Transactional(readOnly = true)
public ApplicationsResponse getApplicants(long siteUserId, String regionCode, String keyword) {
SiteUser siteUser = siteUserRepository.findById(siteUserId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ default UnivApplyInfo getUnivApplyInfoById(Long id) {

boolean existsByHomeUniversityId(Long homeUniversityId);

long countByTermIdAndHomeUniversityId(long termId, long homeUniversityId);

@Query("""
SELECT uai.id
FROM UnivApplyInfo uai
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package com.example.solidconnection.application.service;

import static com.example.solidconnection.common.exception.ErrorCode.SCHOOL_EMAIL_NOT_VERIFIED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.example.solidconnection.application.domain.Application;
import com.example.solidconnection.application.dto.ApplicantResponse;
import com.example.solidconnection.application.dto.ApplicantsResponse;
import com.example.solidconnection.application.dto.ApplicationPreviewResponse;
import com.example.solidconnection.application.dto.ApplicationUniversityPreviewResponse;
import com.example.solidconnection.application.dto.ApplicationsResponse;
import com.example.solidconnection.application.fixture.ApplicationFixture;
import com.example.solidconnection.application.repository.ApplicationRepository;
import com.example.solidconnection.common.VerifyStatus;
import com.example.solidconnection.common.exception.CustomException;
import com.example.solidconnection.location.region.fixture.RegionFixture;
import com.example.solidconnection.score.domain.GpaScore;
import com.example.solidconnection.score.domain.LanguageTestScore;
Expand All @@ -20,7 +25,9 @@
import com.example.solidconnection.term.domain.Term;
import com.example.solidconnection.term.fixture.TermFixture;
import com.example.solidconnection.university.domain.UnivApplyInfo;
import com.example.solidconnection.university.fixture.HomeUniversityFixture;
import com.example.solidconnection.university.fixture.UnivApplyInfoFixture;
import com.example.solidconnection.university.fixture.UnivApplyInfoFixtureBuilder;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -47,6 +54,12 @@ class ApplicationQueryServiceTest {
@Autowired
private UnivApplyInfoFixture univApplyInfoFixture;

@Autowired
private UnivApplyInfoFixtureBuilder univApplyInfoFixtureBuilder;

@Autowired
private HomeUniversityFixture homeUniversityFixture;

@Autowired
private GpaScoreFixture gpaScoreFixture;

Expand Down Expand Up @@ -98,6 +111,114 @@ void setUp() {
서던덴마크대학교_지원_정보 = univApplyInfoFixture.서던덴마크대학교_지원_정보(term.getId());
}

@Nested
Comment thread
Hexeong marked this conversation as resolved.
@DisplayName("지원 현황 미리보기 조회")
class 지원_현황_미리보기_조회_테스트 {

@Test
void 자신의_모교에_속한_지원_대학만_중복_없이_조회한다() {
// given
SiteUser inhaUniversityUser = siteUserFixture.국내_대학_정보_소지_사용자(
괌대학_A_지원_정보.getHomeUniversity().getId());
applicationFixture.지원서(
user1, "nickname1", term.getId(),
gpaScore1.getGpa(), languageTestScore1.getLanguageTest(),
List.of(괌대학_A_지원_정보.getId(), 버지니아공과대학_지원_정보.getId())
);
applicationFixture.지원서(
user2, "nickname2", term.getId(),
gpaScore2.getGpa(), languageTestScore2.getLanguageTest(),
List.of(괌대학_A_지원_정보.getId())
);
UnivApplyInfo 인천대학교_전용_지원_정보 = univApplyInfoFixtureBuilder.univApplyInfo()
.termId(term.getId())
.koreanName("인천대학교 전용 교환 대학")
.university(서던덴마크대학교_지원_정보.getUniversity())
.homeUniversity(homeUniversityFixture.인천대학교())
.create();
applicationFixture.지원서(
user3, "nickname3", term.getId(),
gpaScore3.getGpa(), languageTestScore3.getLanguageTest(),
List.of(인천대학교_전용_지원_정보.getId())
);
Application deletedApplication = applicationFixture.지원서(
user3, "nickname3", term.getId(),
gpaScore3.getGpa(), languageTestScore3.getLanguageTest(),
List.of(서던덴마크대학교_지원_정보.getId())
);
deletedApplication.setIsDeleteTrue();
applicationRepository.save(deletedApplication);
UnivApplyInfo 승인_대기_지원_정보 = univApplyInfoFixtureBuilder.univApplyInfo()
.termId(term.getId())
.koreanName("승인 대기 교환 대학")
.university(서던덴마크대학교_지원_정보.getUniversity())
.homeUniversity(괌대학_A_지원_정보.getHomeUniversity())
.create();
Application pendingApplication = applicationFixture.지원서(
user1, "pending-nickname", term.getId(),
gpaScore1.getGpa(), languageTestScore1.getLanguageTest(),
List.of(승인_대기_지원_정보.getId())
);
pendingApplication.setVerifyStatus(VerifyStatus.PENDING);
applicationRepository.save(pendingApplication);
UnivApplyInfo 승인_거절_지원_정보 = univApplyInfoFixtureBuilder.univApplyInfo()
.termId(term.getId())
.koreanName("승인 거절 교환 대학")
.university(서던덴마크대학교_지원_정보.getUniversity())
.homeUniversity(괌대학_A_지원_정보.getHomeUniversity())
.create();
Application rejectedApplication = applicationFixture.지원서(
user2, "rejected-nickname", term.getId(),
gpaScore2.getGpa(), languageTestScore2.getLanguageTest(),
List.of(승인_거절_지원_정보.getId())
);
rejectedApplication.setVerifyStatus(VerifyStatus.REJECTED);
applicationRepository.save(rejectedApplication);

// when
ApplicationPreviewResponse response = applicationQueryService.getApplicantUniversityPreviews(
inhaUniversityUser.getId());

// then
assertThat(response.totalUniversityCount()).isEqualTo(5);
assertThat(response.universities()).containsExactly(
ApplicationUniversityPreviewResponse.from(괌대학_A_지원_정보),
ApplicationUniversityPreviewResponse.from(버지니아공과대학_지원_정보)
);
}

@Test
void 성적과_지원서를_제출하지_않은_로그인_사용자도_미리보기를_조회할_수_있다() {
// given
SiteUser signedInUserWithoutScores = siteUserFixture.국내_대학_정보_소지_사용자(
괌대학_A_지원_정보.getHomeUniversity().getId());
applicationFixture.지원서(
user2, "nickname2", term.getId(),
gpaScore2.getGpa(), languageTestScore2.getLanguageTest(),
List.of(괌대학_A_지원_정보.getId())
);

// when
ApplicationPreviewResponse response = applicationQueryService.getApplicantUniversityPreviews(
signedInUserWithoutScores.getId());

// then
assertThat(response.totalUniversityCount()).isEqualTo(3);
assertThat(response.universities()).containsExactly(
ApplicationUniversityPreviewResponse.from(괌대학_A_지원_정보)
);
}

@Test
void 모교가_등록되지_않은_사용자는_미리보기를_조회할_수_없다() {
// when
// then
assertThatThrownBy(() -> applicationQueryService.getApplicantUniversityPreviews(user1.getId()))
.isInstanceOf(CustomException.class)
.hasMessage(SCHOOL_EMAIL_NOT_VERIFIED.getMessage());
}
}

@Nested
class 지원자_목록_조회_테스트 {

Expand Down
Loading