-
Notifications
You must be signed in to change notification settings - Fork 8
refactor: application 도메인 리팩터링 #330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
996a535
2a9064e
addad78
2abc401
bcb31a3
d647870
b6cf6e9
6465be0
f140a3b
ea0c1f3
96e9c62
81e4c30
716639f
d2744da
95bc774
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,10 +6,8 @@ | |
| import com.example.solidconnection.application.dto.ApplicationsResponse; | ||
| import com.example.solidconnection.application.dto.UniversityApplicantsResponse; | ||
| import com.example.solidconnection.application.repository.ApplicationRepository; | ||
| import com.example.solidconnection.cache.annotation.ThunderingHerdCaching; | ||
| import com.example.solidconnection.common.exception.CustomException; | ||
| import com.example.solidconnection.siteuser.domain.SiteUser; | ||
| import com.example.solidconnection.university.domain.University; | ||
| import com.example.solidconnection.university.domain.UniversityInfoForApply; | ||
| import com.example.solidconnection.university.repository.UniversityInfoForApplyRepository; | ||
| import com.example.solidconnection.university.repository.custom.UniversityFilterRepositoryImpl; | ||
|
|
@@ -18,12 +16,9 @@ | |
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
| import java.util.function.Function; | ||
| import java.util.*; | ||
|
nayonsoso marked this conversation as resolved.
Outdated
|
||
| import java.util.stream.Collectors; | ||
| import java.util.stream.Stream; | ||
|
|
||
| import static com.example.solidconnection.common.exception.ErrorCode.APPLICATION_NOT_APPROVED; | ||
|
|
||
|
|
@@ -38,97 +33,97 @@ public class ApplicationQueryService { | |
| @Value("${university.term}") | ||
| public String term; | ||
|
|
||
| /* | ||
| * 다른 지원자들의 성적을 조회한다. | ||
| * - 유저가 다른 지원자들을 볼 수 있는지 검증한다. | ||
| * - 지역과 키워드를 통해 대학을 필터링한다. | ||
| * - 지역은 영어 대문자로 받는다 e.g. ASIA | ||
| * - 1지망, 2지망 지원자들을 조회한다. | ||
| * */ | ||
| @Transactional(readOnly = true) | ||
| // todo: 임시로 단일 키로 캐시 적용. 추후 캐싱 전략 재검토 필요. | ||
| @ThunderingHerdCaching(key = "applications:all", cacheManager = "customCacheManager", ttlSec = 86400) | ||
| public ApplicationsResponse getApplicants(SiteUser siteUser, String regionCode, String keyword) { | ||
| // 국가와 키워드와 지역을 통해 대학을 필터링한다. | ||
| List<University> universities | ||
| = universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword)); | ||
|
|
||
| // 1지망, 2지망, 3지망 지원자들을 조회한다. | ||
| List<UniversityApplicantsResponse> firstChoiceApplicants = getFirstChoiceApplicants(universities, siteUser, term); | ||
| List<UniversityApplicantsResponse> secondChoiceApplicants = getSecondChoiceApplicants(universities, siteUser, term); | ||
| List<UniversityApplicantsResponse> thirdChoiceApplicants = getThirdChoiceApplicants(universities, siteUser, term); | ||
| return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants, thirdChoiceApplicants); | ||
| // 1. 대학 ID 필터링 (regionCode, keyword) | ||
| List<Long> universityIds = universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword)); | ||
| if (universityIds.isEmpty()) return new ApplicationsResponse(List.of(), List.of(), List.of()); | ||
|
nayonsoso marked this conversation as resolved.
Outdated
|
||
|
|
||
| // 2. 조건에 맞는 모든 Application 한 번에 조회 | ||
| List<Application> applications = applicationRepository.findApplicationsForChoices(universityIds, VerifyStatus.APPROVED, term); | ||
|
|
||
| // 3. 대학정보 조회 | ||
| List<UniversityInfoForApply> universityInfos = universityInfoForApplyRepository.findByIdsWithUniversityAndLocation(universityIds); | ||
|
nayonsoso marked this conversation as resolved.
Outdated
|
||
|
|
||
| // 4. 지원서 분류 및 DTO 변환 | ||
| return classifyApplicationsByChoice(universityInfos, applications, siteUser); | ||
| } | ||
|
|
||
| @Transactional(readOnly = true) | ||
| public ApplicationsResponse getApplicantsByUserApplications(SiteUser siteUser) { | ||
| Application userLatestApplication = applicationRepository.getApplicationBySiteUserAndTerm(siteUser, term); | ||
| List<University> userAppliedUniversities = Arrays.asList( | ||
| Optional.ofNullable(userLatestApplication.getFirstChoiceUniversity()) | ||
| .map(UniversityInfoForApply::getUniversity) | ||
| .orElse(null), | ||
| Optional.ofNullable(userLatestApplication.getSecondChoiceUniversity()) | ||
| .map(UniversityInfoForApply::getUniversity) | ||
| .orElse(null), | ||
| Optional.ofNullable(userLatestApplication.getThirdChoiceUniversity()) | ||
| .map(UniversityInfoForApply::getUniversity) | ||
| .orElse(null) | ||
| ).stream() | ||
|
|
||
| List<Long> universityIds = Stream.of( | ||
| userLatestApplication.getFirstChoiceUniversityApplyInfoId(), | ||
| userLatestApplication.getSecondChoiceUniversityApplyInfoId(), | ||
| userLatestApplication.getThirdChoiceUniversityApplyInfoId() | ||
| ) | ||
| .filter(Objects::nonNull) | ||
| .collect(Collectors.toList()); | ||
|
|
||
| List<UniversityApplicantsResponse> firstChoiceApplicants = getFirstChoiceApplicants(userAppliedUniversities, siteUser, term); | ||
| List<UniversityApplicantsResponse> secondChoiceApplicants = getSecondChoiceApplicants(userAppliedUniversities, siteUser, term); | ||
| List<UniversityApplicantsResponse> thirdChoiceApplicants = getThirdChoiceApplicants(userAppliedUniversities, siteUser, term); | ||
| if (universityIds.isEmpty()) { | ||
| return new ApplicationsResponse(List.of(), List.of(), List.of()); | ||
| } | ||
|
|
||
| List<Application> applications = applicationRepository.findApplicationsForChoices(universityIds, VerifyStatus.APPROVED, term); | ||
| List<UniversityInfoForApply> universityInfos = universityInfoForApplyRepository.findByIdsWithUniversityAndLocation(universityIds); | ||
|
|
||
| return classifyApplicationsByChoice(universityInfos, applications, siteUser); | ||
| } | ||
|
|
||
| private ApplicationsResponse classifyApplicationsByChoice( | ||
| List<UniversityInfoForApply> universityInfos, | ||
|
nayonsoso marked this conversation as resolved.
Outdated
|
||
| List<Application> applications, | ||
| SiteUser siteUser) { | ||
|
|
||
| Map<Long, List<Application>> firstChoiceMap = new HashMap<>(); | ||
|
nayonsoso marked this conversation as resolved.
Outdated
|
||
| Map<Long, List<Application>> secondChoiceMap = new HashMap<>(); | ||
| Map<Long, List<Application>> thirdChoiceMap = new HashMap<>(); | ||
|
|
||
| for (Application a : applications) { | ||
| if (a.getFirstChoiceUniversityApplyInfoId() != null) { | ||
| firstChoiceMap.computeIfAbsent(a.getFirstChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); | ||
| } | ||
| if (a.getSecondChoiceUniversityApplyInfoId() != null) { | ||
| secondChoiceMap.computeIfAbsent(a.getSecondChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); | ||
| } | ||
| if (a.getThirdChoiceUniversityApplyInfoId() != null) { | ||
| thirdChoiceMap.computeIfAbsent(a.getThirdChoiceUniversityApplyInfoId(), k -> new ArrayList<>()).add(a); | ||
| } | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a 말고 application으로 그냥 명확히 하는 건 어떤가요? 똑같은 것을 first, second, third냐에 따라만 다르게 호출하니 함수로 빼도 좋을 거 같네요!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반영했습니다! |
||
| List<UniversityApplicantsResponse> firstChoiceApplicants = universityInfos.stream() | ||
| .map(uia -> UniversityApplicantsResponse.of( | ||
| uia, | ||
| firstChoiceMap.getOrDefault(uia.getId(), List.of()).stream() | ||
| .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) | ||
| .toList())) | ||
| .toList(); | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기도 함수로 빼도 좋을 거 같네요!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분도 반영했습니다! |
||
| List<UniversityApplicantsResponse> secondChoiceApplicants = universityInfos.stream() | ||
| .map(uia -> UniversityApplicantsResponse.of( | ||
| uia, | ||
| secondChoiceMap.getOrDefault(uia.getId(), List.of()).stream() | ||
| .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) | ||
| .toList())) | ||
| .toList(); | ||
|
|
||
| List<UniversityApplicantsResponse> thirdChoiceApplicants = universityInfos.stream() | ||
| .map(uia -> UniversityApplicantsResponse.of( | ||
| uia, | ||
| thirdChoiceMap.getOrDefault(uia.getId(), List.of()).stream() | ||
| .map(ap -> ApplicantResponse.of(ap, Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) | ||
| .toList())) | ||
| .toList(); | ||
|
|
||
| return new ApplicationsResponse(firstChoiceApplicants, secondChoiceApplicants, thirdChoiceApplicants); | ||
| } | ||
|
|
||
| // 학기별로 상태가 관리된다. | ||
| // 금학기에 지원이력이 있는 사용자만 지원정보를 확인할 수 있도록 한다. | ||
| @Transactional(readOnly = true) | ||
| public void validateSiteUserCanViewApplicants(SiteUser siteUser) { | ||
| VerifyStatus verifyStatus = applicationRepository.getApplicationBySiteUserAndTerm(siteUser, term).getVerifyStatus(); | ||
| if (verifyStatus != VerifyStatus.APPROVED) { | ||
| throw new CustomException(APPLICATION_NOT_APPROVED); | ||
| } | ||
| } | ||
|
|
||
| private List<UniversityApplicantsResponse> getFirstChoiceApplicants(List<University> universities, SiteUser siteUser, String term) { | ||
| return getApplicantsByChoice( | ||
| universities, | ||
| siteUser, | ||
| uia -> applicationRepository.findAllByFirstChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse(uia, VerifyStatus.APPROVED, term) | ||
| ); | ||
| } | ||
|
|
||
| private List<UniversityApplicantsResponse> getSecondChoiceApplicants(List<University> universities, SiteUser siteUser, String term) { | ||
| return getApplicantsByChoice( | ||
| universities, | ||
| siteUser, | ||
| uia -> applicationRepository.findAllBySecondChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse(uia, VerifyStatus.APPROVED, term) | ||
| ); | ||
| } | ||
|
|
||
| private List<UniversityApplicantsResponse> getThirdChoiceApplicants(List<University> universities, SiteUser siteUser, String term) { | ||
| return getApplicantsByChoice( | ||
| universities, | ||
| siteUser, | ||
| uia -> applicationRepository.findAllByThirdChoiceUniversityAndVerifyStatusAndTermAndIsDeleteFalse(uia, VerifyStatus.APPROVED, term) | ||
| ); | ||
| } | ||
|
|
||
| private List<UniversityApplicantsResponse> getApplicantsByChoice( | ||
| List<University> searchedUniversities, | ||
| SiteUser siteUser, | ||
| Function<UniversityInfoForApply, List<Application>> findApplicationsByChoice) { | ||
| return universityInfoForApplyRepository.findByUniversitiesAndTerm(searchedUniversities, term).stream() | ||
| .map(universityInfoForApply -> UniversityApplicantsResponse.of( | ||
| universityInfoForApply, | ||
| findApplicationsByChoice.apply(universityInfoForApply).stream() | ||
| .map(ap -> ApplicantResponse.of( | ||
| ap, | ||
| Objects.equals(siteUser.getId(), ap.getSiteUser().getId()))) | ||
| .toList())) | ||
| .toList(); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.