Skip to content
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

[새기능] 최종 합격 자동화 및 점수 순 정렬 #112

Merged
merged 28 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ae24b2a
feat(#98): 최종 합격 여부 결정 API 작성
cabbage16 Jul 9, 2024
8b2ca5a
refactor(#98): 사용되지 않는 import 문 제거
cabbage16 Jul 9, 2024
a8edacc
feat(#98): 최종 합격 여부 결정 API 작성
cabbage16 Jul 9, 2024
0e2e76c
refactor(#98): 사용되지 않는 import 문 제거
cabbage16 Jul 9, 2024
0797fc7
refactor(#98): 예외 이름 수정
cabbage16 Jul 9, 2024
b2a3cc1
perf(#98): 정원 외 전형이 다른 전형과 독립하여 경쟁하도록 수정
cabbage16 Jul 9, 2024
cffae79
test(#98): FormControllerTest 작성
cabbage16 Jul 11, 2024
0b88492
docs(#98): 2차 합격 여부 자동 결정 API 문서 작성
cabbage16 Jul 11, 2024
dec793f
Merge branch 'feat/#98' of https://github.com/Bamdoliro/marubase into…
cabbage16 Jul 11, 2024
b10b6e1
feat(#98): 최종 합격 여부 결정 API 작성
cabbage16 Jul 9, 2024
374fe32
refactor(#98): 사용되지 않는 import 문 제거
cabbage16 Jul 9, 2024
17b47c0
refactor(#98): 예외 이름 수정
cabbage16 Jul 9, 2024
7265cbe
perf(#98): 정원 외 전형이 다른 전형과 독립하여 경쟁하도록 수정
cabbage16 Jul 9, 2024
2b3fba8
test(#98): FormControllerTest 작성
cabbage16 Jul 11, 2024
3e005a9
docs(#98): 2차 합격 여부 자동 결정 API 문서 작성
cabbage16 Jul 11, 2024
4f9d455
feat(#98): 최종 합격 여부 결정 API 작성
cabbage16 Jul 9, 2024
1810c79
refactor(#98): 사용되지 않는 import 문 제거
cabbage16 Jul 9, 2024
0c4d1dd
feat(#98): 원서 전체 조회 정렬 기능 추가
cabbage16 Jul 26, 2024
d89d25c
refactor(#98): 정렬 파라미터 변경
cabbage16 Jul 26, 2024
8f04b8c
test(#98): 정렬 기능 UseCaseTest 추가
cabbage16 Jul 29, 2024
b35dbb8
fix(#98): 1차합격 메서드 삭제
cabbage16 Jul 30, 2024
ac49ba6
perf(#98): 최종점수순 정렬 시 최종 점수가 없는 경우 오류 발생
cabbage16 Jul 30, 2024
dab02cb
fix: Git Conflict 해결
cabbage16 Jul 30, 2024
ad10aab
Merge branch 'feat/#98' of https://github.com/Bamdoliro/marubase into…
cabbage16 Jul 30, 2024
cc6f9b9
refactor: 코드 컨벤션 준수
cabbage16 Jul 30, 2024
9f2088b
Merge branch 'develop' into feat/#98
cabbage16 Aug 5, 2024
2f1b285
fix: FormErrorProperty 콤마 해결
cabbage16 Aug 5, 2024
95dcad5
test(#98): SelectSecondPassUseCaseTest
cabbage16 Sep 3, 2024
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
22 changes: 21 additions & 1 deletion src/docs/asciidoc/form.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -587,4 +587,24 @@ include::{snippets}/form-controller-test/선택한_원서의_원서url을_조회
==== 응답

===== 정상 응답
include::{snippets}/form-controller-test/선택한_원서의_원서url을_조회한다/http-response.adoc[]
include::{snippets}/form-controller-test/선택한_원서의_원서url을_조회한다/http-response.adoc[]



=== 2차 합격 자동 처리

==== 요청 형식

===== Request Header
include::{snippets}/form-controller-test/자동으로_2차_합격_여부를_결정한다/request-headers.adoc[]

==== 요청
include::{snippets}/form-controller-test/자동으로_2차_합격_여부를_결정한다/http-request.adoc[]

==== 응답

===== 정상 응답
include::{snippets}/form-controller-test/자동으로_2차_합격_여부를_결정한다/http-response.adoc[]

===== 최종 점수가 없는 원서가 있을 경우
include::{snippets}/form-controller-test/자동으로_2차_합격_여부를_결정할_때_최종_점수가_없는_원서가_존재하면_에러가_발생한다/http-response.adoc[]
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.bamdoliro.maru.application.form;

import com.bamdoliro.maru.domain.form.domain.Form;
import com.bamdoliro.maru.domain.form.exception.InvalidFromStatusException;
import com.bamdoliro.maru.domain.form.exception.InvalidFormStatusException;
import com.bamdoliro.maru.domain.form.service.FormFacade;
import com.bamdoliro.maru.domain.user.domain.User;
import com.bamdoliro.maru.infrastructure.pdf.GeneratePdfService;
Expand Down Expand Up @@ -48,7 +48,7 @@ public ByteArrayResource execute(User user) {

private void validateFormStatus(Form form) {
if (!form.isFirstPassedNow()) {
throw new InvalidFromStatusException();
throw new InvalidFormStatusException();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.bamdoliro.maru.application.form;

import com.bamdoliro.maru.domain.form.domain.Form;
import com.bamdoliro.maru.domain.form.domain.type.FormStatus;
import com.bamdoliro.maru.domain.form.domain.type.FormType;
import com.bamdoliro.maru.domain.form.exception.MissingTotalScoreException;
import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository;
import com.bamdoliro.maru.presentation.form.dto.response.FormSimpleResponse;
import com.bamdoliro.maru.shared.annotation.UseCase;
import lombok.RequiredArgsConstructor;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
Expand All @@ -17,10 +20,22 @@ public class QueryAllFormUseCase {

private final FormRepository formRepository;

public List<FormSimpleResponse> execute(FormStatus status, FormType.Category category) {
return formRepository.findByStatus(status).stream()
public List<FormSimpleResponse> execute(FormStatus status, FormType.Category category, String sort) {
List<Form> formList = new java.util.ArrayList<>(formRepository.findByStatus(status).stream()
.filter(form -> Objects.isNull(category) || form.getType().categoryEquals(category))
.toList());

if (sort != null && formList.stream().anyMatch(form -> form.getScore().getTotalScore() == null)) {
throw new MissingTotalScoreException();
}
if ("total-score-asc".equals(sort)) {
formList.sort(Comparator.comparing(form -> form.getScore().getTotalScore(), Comparator.naturalOrder()));
} else if ("total-score-desc".equals(sort)) {
formList.sort(Comparator.comparing(form -> form.getScore().getTotalScore(), Comparator.reverseOrder()));
}

return formList.stream()
.map(FormSimpleResponse::new)
.collect(Collectors.toList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository;
import com.bamdoliro.maru.shared.annotation.UseCase;
import com.bamdoliro.maru.shared.constants.FixedNumber;
import com.bamdoliro.maru.shared.variable.AdmissionCapacity;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -34,12 +35,16 @@ public void execute() {
int gap = FixedNumber.MEISTER_TALENT - meisterTalentFormList.size();
regularCount += gap;
meisterTalentCount -= gap;
AdmissionCapacity.regular += gap;
AdmissionCapacity.meisterTalent -= gap;
}

if (socialIntegrationFormList.size() < FixedNumber.SOCIAL_INTEGRATION) {
int gap = FixedNumber.SOCIAL_INTEGRATION - socialIntegrationFormList.size();
regularCount += gap;
socialIntegrationCount -= gap;
AdmissionCapacity.regular += gap;
AdmissionCapacity.socialIntegration -= gap;
}

regularCount = calculateMultiple(regularCount);
Expand Down Expand Up @@ -73,22 +78,29 @@ public void execute() {
}

formRepository.flush();
List<Form> regularOrSupernumeraryFormList = formRepository.findReceivedRegularOrSupernumeraryForm();
List<Form> regularOrSupernumeraryFormList = formRepository.findReceivedRegularForm();

for (Form form : regularOrSupernumeraryFormList) {
if (form.getType().isRegular() && regularCount > 0) {
if (regularCount > 0) {
form.firstPass();
regularCount--;
} else if (
} else {
form.firstFail();
}
}

formRepository.flush();
List<Form> supernumeraryFormList = formRepository.findReceivedSupernumeraryForm();

for (Form form : supernumeraryFormList) {
if (
form.getType().isNationalVeteransEducation() &&
regularCount > 0 &&
nationalVeteransEducationCount > 0
) {
form.firstPass();
nationalVeteransEducationCount--;
} else if (
form.getType().isSpecialAdmission() &&
regularCount > 0 &&
specialAdmissionCount > 0
) {
form.firstPass();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.bamdoliro.maru.application.form;

import com.bamdoliro.maru.domain.form.domain.Form;
import com.bamdoliro.maru.domain.form.domain.type.FormStatus;
import com.bamdoliro.maru.domain.form.domain.type.FormType;
import com.bamdoliro.maru.domain.form.exception.MissingTotalScoreException;
import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository;
import com.bamdoliro.maru.shared.annotation.UseCase;
import com.bamdoliro.maru.shared.constants.FixedNumber;
import com.bamdoliro.maru.shared.variable.AdmissionCapacity;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;

import java.util.List;

@RequiredArgsConstructor
@UseCase
public class SelectSecondPassUseCase {

private final FormRepository formRepository;

@Transactional
public void execute() {
validate();

int regularCount = AdmissionCapacity.regular;
int meisterTalentCount = AdmissionCapacity.meisterTalent;
int socialIntegrationCount = AdmissionCapacity.socialIntegration;
int nationalVeteransEducationCount = FixedNumber.NATIONAL_VETERANS_EDUCATION;
int specialAdmissionCount = FixedNumber.SPECIAL_ADMISSION;
int equalOpportunityCount = (int) Math.round(socialIntegrationCount * 0.5);
int societyDiversityCount = equalOpportunityCount;

List<Form> specialFormList = formRepository.findFirstPassedSpecialForm();
List<Form> meisterTalentFormList = classifyFormsByType(specialFormList, FormType::isMeister);
List<Form> socialIntegrationFormList = classifyFormsByType(specialFormList, FormType::isSocial);

for (Form form : socialIntegrationFormList) {
if (form.getType().isEqualOpportunity() && equalOpportunityCount > 0) {
form.pass();
equalOpportunityCount--;
} else if (form.getType().isSocietyDiversity() && societyDiversityCount > 0) {
form.pass();
societyDiversityCount--;
} else {
form.fail();
}
}

for (Form form : meisterTalentFormList) {
if (meisterTalentCount > 0) {
form.pass();
meisterTalentCount--;
} else {
form.fail();
}
}

formRepository.flush();
List<Form> regularFormList = formRepository.findFirstPassedRegularForm();

for (Form form : regularFormList) {
if (regularCount > 0) {
form.pass();
regularCount--;
} else {
form.fail();
}
}

formRepository.flush();
List<Form> supernumeraryFormList = formRepository.findFirstPassedSupernumeraryForm();

for (Form form : supernumeraryFormList) {
if (form.getType().isNationalVeteransEducation() && nationalVeteransEducationCount > 0) {
form.pass();
nationalVeteransEducationCount--;
} else if (form.getType().isSpecialAdmission() && specialAdmissionCount > 0) {
form.pass();
specialAdmissionCount--;
} else {
form.fail();
}
}
}

private void validate() {
List<Form> firstPassedFormList = formRepository.findByStatus(FormStatus.FIRST_PASSED);
firstPassedFormList.stream()
.filter(form -> form.getScore().getTotalScore() == null)
.forEach(form -> {throw new MissingTotalScoreException();});
}

private List<Form> classifyFormsByType(List<Form> formList, FormTypeFilter filter) {
return formList.stream()
.filter(form -> filter.execute(form.getType()))
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public enum FormType implements EnumProperty {
NATIONAL_VETERANS("국가보훈자녀", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.EQUAL_OPPORTUNITY),
ONE_PARENT("한부모가정", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.EQUAL_OPPORTUNITY),

FROM_NORTH_KOREA("북한이탈주민", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY),
FROM_NORTH_KOREA("북한이탈청소년", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY),
MULTICULTURAL("다문화가정", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY),
TEEN_HOUSEHOLDER("소년소녀가장", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY),
MULTI_CHILDREN("다자녀가정자녀", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import com.bamdoliro.maru.domain.form.exception.error.FormErrorProperty;
import com.bamdoliro.maru.shared.error.MaruException;

public class InvalidFromStatusException extends MaruException {
public class InvalidFormStatusException extends MaruException {

public InvalidFromStatusException() {
public InvalidFormStatusException() {
super(FormErrorProperty.INVALID_FORM_STATUS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.bamdoliro.maru.domain.form.exception;

import com.bamdoliro.maru.domain.form.exception.error.FormErrorProperty;
import com.bamdoliro.maru.shared.error.MaruException;

public class MissingTotalScoreException extends MaruException {
public MissingTotalScoreException() {
super(FormErrorProperty.MISSING_TOTAL_SCORE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.bamdoliro.maru.domain.form.exception;

import com.bamdoliro.maru.domain.form.exception.error.FormErrorProperty;
import com.bamdoliro.maru.shared.error.MaruException;

public class TotalScoreMissingException extends MaruException {
public TotalScoreMissingException() {
super(FormErrorProperty.MISSING_TOTAL_SCORE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public enum FormErrorProperty implements ErrorProperty {
CANNOT_UPDATE_NOT_REJECTED_FORM(HttpStatus.CONFLICT, "반려된 원서만 수정할 수 있습니다."),
INVALID_FORM_STATUS(HttpStatus.CONFLICT, "원서 상태가 유효하지 않습니다."),
INVALID_FILE(HttpStatus.BAD_REQUEST, "잘못된 파일입니다."),
MISSING_TOTAL_SCORE(HttpStatus.PRECONDITION_FAILED, "최종 점수가 입력되지 않은 원서가 존재합니다."),
WRONG_SCORE(HttpStatus.BAD_REQUEST, "점수 범위를 초과했습니다."),
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ public interface FormRepositoryCustom {
List<Form> findByType(FormType type);
List<Form> findByCategory(FormType.Category category);
List<Form> findReceivedSpecialForm();
List<Form> findReceivedRegularOrSupernumeraryForm();
List<Form> findReceivedRegularForm();
List<Form> findReceivedSupernumeraryForm();
List<Form> findFirstPassedSpecialForm();
List<Form> findFirstPassedRegularForm();
List<Form> findFirstPassedSupernumeraryForm();
List<Form> findFirstRoundForm();
List<Form> findMeisterTalentFirstRoundForm();
List<Form> findNotExistsMeisterTalentAndChangedToRegularFirstRoundForm();
Expand Down
Loading
Loading