From 3e7d63124e717e4315d327da450de70a9815e7cc Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:45:32 +0900 Subject: [PATCH 01/59] =?UTF-8?q?feat(#79):=20=EC=9B=90=EC=84=9C=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=EC=97=90=20school=5Faddress=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80=20-=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=EC=9D=98=20=EC=B6=9C=EC=8B=A0=20?= =?UTF-8?q?=ED=95=99=EA=B5=90=EC=9D=98=20=EB=8F=84=EB=A1=9C=EB=AA=85=20?= =?UTF-8?q?=EC=A3=BC=EC=86=8C=EB=A5=BC=20=ED=91=9C=EA=B8=B0=ED=95=B4?= =?UTF-8?q?=EC=95=BC=20=ED=95=98=EB=8A=94=EB=8D=B0,=20=EB=8F=84=EB=A1=9C?= =?UTF-8?q?=EB=AA=85=EC=A3=BC=EC=86=8C=EA=B0=80=20=EC=97=86=EC=96=B4?= =?UTF-8?q?=EC=84=9C=20=EC=BB=AC=EB=9F=BC=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/domain/form/domain/value/School.java | 5 ++++- .../form/dto/request/EducationRequest.java | 13 +++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java b/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java index 10125bff..84684803 100644 --- a/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java +++ b/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java @@ -19,10 +19,13 @@ public class School { @Column(name = "school_location", nullable = false, length = 20) private String location; + @Column(name = "school_address", nullable = false, length = 40) + private String address; + @Column(name = "school_code", nullable = false, length = 10) private String code; public boolean isBusan() { return location.equals("부산광역시"); } -} +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java b/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java index c47bd342..838b6a7e 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java @@ -25,15 +25,19 @@ public class EducationRequest { @Size(min = 4, max = 4, message = "4자여야 합니다.") private String graduationYear; - @NotBlank + @NotBlank(message = "필수값입니다.") @Size(max = 20, message = "20자 이하여야 합니다.") private String schoolName; - @NotBlank + @NotBlank(message = "필수값입니다.") @Size(max = 20, message = "20자 이하여야 합니다.") private String schoolLocation; - @NotBlank + @NotBlank(message = "필수값입니다.") + @Size(max = 40, message = "40자 이하여야 합니다.") + private String schoolAddress; + + @NotBlank(message = "필수값입니다.") @Size(min = 7, max = 7, message = "7자여야 합니다.") private String schoolCode; @@ -56,6 +60,7 @@ public Education toValue() { new School( schoolName, schoolLocation, + schoolAddress, schoolCode ), new Teacher( @@ -65,4 +70,4 @@ public Education toValue() { ) ); } -} +} \ No newline at end of file From 09a4ca0def0d7e7784948891dfd01035e394120a Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:46:13 +0900 Subject: [PATCH 02/59] =?UTF-8?q?test(#79):=20FormFixture,=20FormControlle?= =?UTF-8?q?rTest=20-=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=8F=84=20school=5Faddress=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=BC=EC=B6=94=EA=B0=80=EB=A5=BC=20=EB=B0=98=EC=98=81?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/form/FormControllerTest.java | 6 ++++++ .../bamdoliro/maru/shared/fixture/FormFixture.java | 12 ++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java index a01d821e..17720d9a 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java @@ -141,6 +141,9 @@ class FormControllerTest extends RestDocsTestSupport { fieldWithPath("education.schoolLocation") .type(JsonFieldType.STRING) .description("출신 학교 지역"), + fieldWithPath("education.schoolAddress") + .type(JsonFieldType.STRING) + .description("출신 학교 주소지"), fieldWithPath("education.schoolCode") .type(JsonFieldType.STRING) .description("출신 학교 코드"), @@ -753,6 +756,9 @@ class FormControllerTest extends RestDocsTestSupport { fieldWithPath("education.schoolLocation") .type(JsonFieldType.STRING) .description("출신 학교 지역"), + fieldWithPath("education.schoolAddress") + .type(JsonFieldType.STRING) + .description("출신 학교 주소지"), fieldWithPath("education.schoolCode") .type(JsonFieldType.STRING) .description("출신 학교 코드"), diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index d2cb004f..af98c7dd 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -74,7 +74,7 @@ public static Form createForm(FormType type) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -140,7 +140,7 @@ public static Form createRandomForm(User user) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -218,7 +218,7 @@ public static Form createRandomQualificationExaminationForm(User user) { new Education( GraduationType.QUALIFICATION_EXAMINATION, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), null ), new Grade( @@ -289,6 +289,7 @@ public static Form createQualificationExaminationForm(FormType type) { new School( "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003" ), null @@ -328,6 +329,7 @@ public static SubmitFormRequest createFormRequest(FormType type) { "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -369,6 +371,7 @@ public static SubmitFormRequest createQualificationExaminationFormRequest(FormTy "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", null, null, @@ -404,6 +407,7 @@ public static UpdateFormRequest createUpdateFormRequest(FormType type) { "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -549,4 +553,4 @@ public static FormUrlResponse createFormUrlResponse() { createFormUrlVo() ); } -} +} \ No newline at end of file From 1a8bcc1ee4d9952af23d80d864d2ee8837057740 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:58:53 +0900 Subject: [PATCH 03/59] =?UTF-8?q?feat(#79):=20=EC=A0=84=ED=98=95=EB=B3=84?= =?UTF-8?q?=20=EC=A7=80=EC=9B=90=EC=9E=90=20=EC=88=98=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20-=20=EC=96=B4=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EB=B3=84=20=EC=A7=80=EC=9B=90=EC=9E=90=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryNumberOfApplicantsUseCase.java | 35 +++++++ .../form/FormRepositoryCustom.java | 12 ++- .../persistence/form/FormRepositoryImpl.java | 99 ++++++++++++++++++- .../persistence/form/vo/GradeVo.java | 26 +++++ .../form/vo/NumberOfApplicantsVo.java | 17 ++++ .../persistence/form/vo/SchoolStatusVo.java | 18 ++++ .../analysis/AnalysisController.java | 73 ++++++++++++++ .../response/NumberOfApplicantsResponse.java | 20 ++++ 8 files changed, 296 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java new file mode 100644 index 00000000..44d1c73c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java @@ -0,0 +1,35 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@UseCase +public class QueryNumberOfApplicantsUseCase { + private final FormRepository formRepository; + + public List execute() { + List result = formRepository.findTypeAndCountGroupByType() + .stream() + .map(NumberOfApplicantsResponse::new) + .collect(Collectors.toList()); + + List existingTypes = result.stream() + .map(NumberOfApplicantsResponse::getType) + .toList(); + + for (FormType formType: FormType.values()) { + if (!existingTypes.contains(formType)) { + result.add(new NumberOfApplicantsResponse(formType, 0L)); + } + } + + return result; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java index ed7dec7e..3be708e3 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java @@ -2,13 +2,19 @@ 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.infrastructure.persistence.form.vo.NumberOfApplicantsVo; import com.bamdoliro.maru.infrastructure.persistence.form.vo.FormUrlVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.SchoolStatusVo; import java.util.List; public interface FormRepositoryCustom { List
findByStatus(FormStatus status); + List findByType(FormType type); + List findByCategory(FormType.Category category); List findReceivedSpecialForm(); List findReceivedRegularOrSupernumeraryForm(); List findFirstRoundForm(); @@ -17,4 +23,8 @@ public interface FormRepositoryCustom { List findSecondRoundForm(); List findByFormIdList(List idList); List findFormUrlByFormIdList(List idList); -} + List findTypeAndCountGroupByType(); + List findGradeGroupByTypeAndStatus(List round); + List findSchoolByAddress(List round, String keyword); + List findNotBusanSchool(List round); +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java index f78df470..8a6ba607 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java @@ -3,8 +3,7 @@ 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.infrastructure.persistence.form.vo.FormUrlVo; -import com.bamdoliro.maru.infrastructure.persistence.form.vo.QFormUrlVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.*; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @@ -12,6 +11,7 @@ import java.util.List; import java.util.Objects; +import java.util.stream.Stream; import static com.bamdoliro.maru.domain.form.domain.QForm.form; @@ -30,6 +30,26 @@ public List findByStatus(FormStatus status) { .fetch(); } + @Override + public List findByType(FormType type) { + return queryFactory + .selectFrom(form) + .where(eqType(type)) + .orderBy(form.examinationNumber.asc()) + .fetch(); + } + + @Override + public List findByCategory(FormType.Category category) { + List matchingFormTypes = getFormTypesByCategory(category); + + return queryFactory + .selectFrom(form) + .where(form.type.in(matchingFormTypes)) + .orderBy(form.examinationNumber.asc()) + .fetch(); + } + private BooleanExpression eqStatus(FormStatus status) { if (Objects.isNull(status)) { return null; @@ -38,6 +58,20 @@ private BooleanExpression eqStatus(FormStatus status) { return form.status.eq(status); } + private BooleanExpression eqType(FormType type) { + if (Objects.isNull(type)) { + return null; + } + + return form.type.eq(type); + } + + private List getFormTypesByCategory(FormType.Category category) { + return Stream.of(FormType.values()) + .filter(formType -> formType.categoryEquals(category)) + .toList(); + } + @Override public List findReceivedSpecialForm() { return queryFactory @@ -139,4 +173,63 @@ public List findFormUrlByFormIdList(List idList) { .orderBy(form.examinationNumber.asc()) .fetch(); } -} + + @Override + public List findTypeAndCountGroupByType() { + return queryFactory + .select(new QNumberOfApplicantsVo( + form.type, + form.count() + )) + .from(form) + .groupBy(form.type) + .fetch(); + } + + @Override + public List findGradeGroupByTypeAndStatus(List round) { + return queryFactory + .select(new QGradeVo( + form.type.stringValue(), + form.score.firstRoundScore.max(), + form.score.firstRoundScore.min(), + form.score.firstRoundScore.avg(), + form.score.totalScore.max(), + form.score.totalScore.min(), + form.score.totalScore.avg() + )) + .from(form) + .where(form.status.in(round)) + .groupBy(form.type) + .fetch(); + } + + @Override + public List findSchoolByAddress(List round, String keyword) { + return queryFactory + .select(new QSchoolStatusVo( + form.applicant.name, + form.education.school.name, + form.education.school.address + )) + .from(form) + .where(form.education.school.address.contains(keyword) + .or(form.education.school.location.eq(keyword)) + .and(form.status.in(round))) + .fetch(); + } + + @Override + public List findNotBusanSchool(List round) { + return queryFactory + .select(new QSchoolStatusVo( + form.applicant.name, + form.education.school.name, + form.education.school.address + )) + .from(form) + .where(form.education.school.location.eq("부산광역시").not() + .and(form.status.in(round))) + .fetch(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java new file mode 100644 index 00000000..5f531beb --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java @@ -0,0 +1,26 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class GradeVo { + private String type; + private Double firstRoundMax; + private Double firstRoundMin; + private Double firstRoundAvg; + private Double totalMax; + private Double totalMin; + private Double totalAvg; + + @QueryProjection + public GradeVo(String type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { + this.type = type; + this.firstRoundMax = firstRoundMax; + this.firstRoundMin = firstRoundMin; + this.firstRoundAvg = firstRoundAvg; + this.totalMax = totalMax; + this.totalMin = totalMin; + this.totalAvg = totalAvg; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java new file mode 100644 index 00000000..8f9c080c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class NumberOfApplicantsVo { + private FormType type; + private Long count; + + @QueryProjection + public NumberOfApplicantsVo(FormType type, Long count) { + this.type = type; + this.count = count; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java new file mode 100644 index 00000000..4350ba73 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java @@ -0,0 +1,18 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class SchoolStatusVo { + private String applicantName; + private String schoolName; + private String schoolAddress; + + @QueryProjection + public SchoolStatusVo(String applicantName, String schoolName, String schoolAddress) { + this.applicantName = applicantName; + this.schoolName = schoolName; + this.schoolAddress = schoolAddress; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java new file mode 100644 index 00000000..e696ef8c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java @@ -0,0 +1,73 @@ +package com.bamdoliro.maru.presentation.analysis; + +import com.bamdoliro.maru.application.analysis.QueryGenderRatioUseCase; +import com.bamdoliro.maru.application.analysis.QueryNumberOfApplicantsUseCase; +import com.bamdoliro.maru.application.analysis.QueryGradeDistributionUseCase; +import com.bamdoliro.maru.application.analysis.QuerySchoolStatusUseCase; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; +import com.bamdoliro.maru.shared.auth.AuthenticationPrincipal; +import com.bamdoliro.maru.shared.auth.Authority; +import com.bamdoliro.maru.shared.response.CommonResponse; +import com.bamdoliro.maru.shared.response.ListCommonResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RequestMapping("/analysis") +@RestController +public class AnalysisController { + private final QueryNumberOfApplicantsUseCase queryNumberOfApplicantsUseCase; + private final QueryGradeDistributionUseCase queryGradeDistributionUseCase; + private final QueryGenderRatioUseCase queryGenderRatioUseCase; + private final QuerySchoolStatusUseCase querySchoolStatusUseCase; + + @GetMapping("/number-of-applicants") + public ListCommonResponse getNumberOfApplicants( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user + ) { + return CommonResponse.ok( + queryNumberOfApplicantsUseCase.execute() + ); + } + + @GetMapping("/grade-distribution") + public ListCommonResponse getGradeDistribution( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid GradeDistributionRequest request + ) { + return CommonResponse.ok( + queryGradeDistributionUseCase.execute(request) + ); + } + + @GetMapping("/gender-ratio") + public ListCommonResponse getGenderRatio( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid GenderRatioRequest request + ) { + return CommonResponse.ok( + queryGenderRatioUseCase.execute(request) + ); + } + + @GetMapping("/school-status") + public ListCommonResponse getSchoolStatus( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid SchoolStatusRequest request + ) { + return CommonResponse.ok( + querySchoolStatusUseCase.execute(request) + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java new file mode 100644 index 00000000..c46a0da5 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java @@ -0,0 +1,20 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.NumberOfApplicantsVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class NumberOfApplicantsResponse { + private FormType type; + private Long count; + + public NumberOfApplicantsResponse(NumberOfApplicantsVo vo){ + this.type = vo.getType(); + this.count = vo.getCount(); + } +} \ No newline at end of file From 292a7c46e317a2e9835e94844aafed413e2291e6 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:00:13 +0900 Subject: [PATCH 04/59] =?UTF-8?q?feat(#79):=20=EC=84=B1=EC=A0=81=20?= =?UTF-8?q?=EB=B6=84=ED=8F=AC=20=EC=A1=B0=ED=9A=8C=20-=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84=ED=98=95=EB=B3=84=20?= =?UTF-8?q?=ED=95=99=EC=83=9D=EB=93=A4=EC=9D=98=20=EC=B5=9C=EA=B3=A0?= =?UTF-8?q?=EC=A0=90,=20=EC=B5=9C=ED=95=98=EC=A0=90,=20=ED=8F=89=EA=B7=A0?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryGradeDistributionUseCase.java | 22 ++++++++++++++ .../dto/request/GradeDistributionRequest.java | 17 +++++++++++ .../response/GradeDistributionResponse.java | 29 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java new file mode 100644 index 00000000..1bbd45e8 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -0,0 +1,22 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@UseCase +public class QueryGradeDistributionUseCase { + private final FormRepository formRepository; + + public List execute(GradeDistributionRequest request) { + return formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) + .stream() + .map(GradeDistributionResponse::new) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java new file mode 100644 index 00000000..f2828ead --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GradeDistributionRequest { + @NotNull(message = "필수값입니다.") + List statusList; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java new file mode 100644 index 00000000..c4f6d534 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java @@ -0,0 +1,29 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GradeDistributionResponse { + private String type; + private Double firstRoundMax; + private Double firstRoundMin; + private Double firstRoundAvg; + private Double totalMax; + private Double totalMin; + private Double totalAvg; + + public GradeDistributionResponse(GradeVo vo) { + this.type = vo.getType(); + this.firstRoundMax = vo.getFirstRoundMax(); + this.firstRoundMin = vo.getFirstRoundMin(); + this.firstRoundAvg = vo.getFirstRoundAvg(); + this.totalMax = vo.getTotalMax(); + this.totalMin = vo.getTotalMin(); + this.totalAvg = vo.getTotalAvg(); + } +} \ No newline at end of file From 5b55d311e1aa39b225835fc5a138ba2c3b3f9d7d Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:01:29 +0900 Subject: [PATCH 05/59] =?UTF-8?q?feat(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=84=B1=EB=B9=84=20=EB=B6=84=EC=84=9D=20-=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84=ED=98=95=EB=B3=84=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=EB=93=A4=EC=9D=98=20=EC=84=B1?= =?UTF-8?q?=EB=B3=84=EB=B6=84=ED=8F=AC=EB=A5=BC=20=ED=8C=8C=EC=95=85?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=9E=88=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 71 +++++++++++++++++++ .../dto/request/GenderRatioRequest.java | 21 ++++++ .../dto/response/GenderRatioResponse.java | 17 +++++ 3 files changed, 109 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java new file mode 100644 index 00000000..e71a24e2 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -0,0 +1,71 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.Form; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.domain.form.domain.type.Gender; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@UseCase +public class QueryGenderRatioUseCase { + private final FormRepository formRepository; + + public List execute(GenderRatioRequest request) { + List result = new ArrayList<>(); + + List subCategories = new ArrayList<>(); + + if (request.getMainCategory().equals(FormType.Category.REGULAR)) + subCategories.add(FormType.Category.REGULAR); + else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) + subCategories.addAll(List.of(FormType.Category.EQUAL_OPPORTUNITY, FormType.Category.SOCIETY_DIVERSITY)); + else subCategories.add(FormType.Category.SUPERNUMERARY); + + Map> formLists = subCategories.stream() + .collect(Collectors.toMap( + category -> category, + category -> formRepository.findByCategory(category).stream() + .filter(form -> request.getStatusList().contains(form.getStatus())) + .collect(Collectors.toList()) + )); + + for(Map.Entry> entry : formLists.entrySet()) { + FormType.Category category = entry.getKey(); + List formList = entry.getValue(); + + long busanMale = formList.stream().filter(this::isBusan).filter(this::isMale).count(); + long busanFeMale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); + long otherLocationMale = formList.stream().filter(this::isNotBusan).filter(this::isMale).count(); + long otherLocationFemale = formList.stream().filter(this::isNotBusan).filter(this::isFemale).count(); + + result.add(new GenderRatioResponse(category, busanMale, busanFeMale, otherLocationMale, otherLocationFemale)); + } + + return result; + } + + private boolean isBusan(Form form) { + return form.getEducation().getSchool().isBusan(); + } + + private boolean isNotBusan(Form form) { + return !isBusan(form); + } + + private boolean isMale(Form form) { + return form.getApplicant().getGender().equals(Gender.MALE); + } + + private boolean isFemale(Form form) { + return !isMale(form); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java new file mode 100644 index 00000000..6779ea6c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java @@ -0,0 +1,21 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GenderRatioRequest { + @NotNull(message = "필수값입니다.") + private List statusList; + + @NotNull(message = "필수값입니다.") + private FormType.Category mainCategory; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java new file mode 100644 index 00000000..152143c1 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GenderRatioResponse { + private FormType.Category category; + private long busanMale; + private long busanFemale; + private long otherLocationMale; + private long otherLocationFemale; +} \ No newline at end of file From 21a1e0fc45940093c8240134051e18f3b8c66227 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:02:25 +0900 Subject: [PATCH 06/59] =?UTF-8?q?feat(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=B6=9C=EC=8B=A0=20=ED=95=99=EA=B5=90=20=ED=98=84=ED=99=A9?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20-=20=EC=96=B4=EB=93=9C=EB=AF=BC?= =?UTF-8?q?=EC=9D=B4=20=EC=A7=80=EC=9B=90=EC=9E=90=EB=93=A4=EC=9D=98=20?= =?UTF-8?q?=EC=B6=9C=EC=8B=A0=20=ED=95=99=EA=B5=90=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QuerySchoolStatusUseCase.java | 33 +++++++++++++++++++ .../dto/request/SchoolStatusRequest.java | 25 ++++++++++++++ .../dto/response/SchoolStatusResponse.java | 21 ++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java new file mode 100644 index 00000000..883b31d9 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java @@ -0,0 +1,33 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@UseCase +public class QuerySchoolStatusUseCase { + + private final FormRepository formRepository; + + public List execute(SchoolStatusRequest request) { + if (request.getIsBusan()) { + String keyword = "부산광역시"; + keyword += request.getGu() == null ? "" : (" " + request.getGu()); + + return formRepository.findSchoolByAddress(request.getStatusList(), keyword) + .stream() + .map(SchoolStatusResponse::new) + .toList(); + } + + return formRepository.findNotBusanSchool(request.getStatusList()) + .stream() + .map(SchoolStatusResponse::new) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java new file mode 100644 index 00000000..be21084e --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java @@ -0,0 +1,25 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SchoolStatusRequest { + + @NotNull(message = "필수값입니다.") + private List statusList; + + @NotNull(message = "필수값입니다.") + private Boolean isBusan; + + @Nullable + private String gu; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java new file mode 100644 index 00000000..947081c7 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java @@ -0,0 +1,21 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.infrastructure.persistence.form.vo.SchoolStatusVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SchoolStatusResponse { + private String applicantName; + private String schoolName; + private String schoolAddress; + + public SchoolStatusResponse(SchoolStatusVo schoolStatusVo) { + this.applicantName = schoolStatusVo.getApplicantName(); + this.schoolName = schoolStatusVo.getSchoolName(); + this.schoolAddress = schoolStatusVo.getSchoolAddress(); + } +} \ No newline at end of file From 15a0edf59f084b42b75e6da23ad912003b3875a8 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:03:55 +0900 Subject: [PATCH 07/59] =?UTF-8?q?build:=20application.yml=20-=20debug=20-?= =?UTF-8?q?=20debug=20=EB=A1=9C=EA=B7=B8=EA=B0=80=20=EB=84=88=EB=AC=B4=20?= =?UTF-8?q?=EA=B8=B8=EC=96=B4=EC=84=9C=20=EB=B3=B4=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=98=B5=EC=85=98=EC=9D=84=20fal?= =?UTF-8?q?se=EB=A1=9C=20=EB=B0=94=EA=BF=A8=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1e425339..602c8e54 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -78,7 +78,7 @@ spring: activate: on-profile: dev -debug: true +debug: false --- spring: config: @@ -101,7 +101,7 @@ spring: port: 6379 password: bamdoliro -debug: true +debug: false --- spring: config: @@ -135,4 +135,4 @@ spring: port: 6379 password: bamdoliro -debug: true +debug: false From 46b9426fecd353ebc6ad5dc351cd23c91dbeb47d Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:45:32 +0900 Subject: [PATCH 08/59] =?UTF-8?q?feat(#79):=20=EC=9B=90=EC=84=9C=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=EC=97=90=20school=5Faddress=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80=20-=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=EC=9D=98=20=EC=B6=9C=EC=8B=A0=20?= =?UTF-8?q?=ED=95=99=EA=B5=90=EC=9D=98=20=EB=8F=84=EB=A1=9C=EB=AA=85=20?= =?UTF-8?q?=EC=A3=BC=EC=86=8C=EB=A5=BC=20=ED=91=9C=EA=B8=B0=ED=95=B4?= =?UTF-8?q?=EC=95=BC=20=ED=95=98=EB=8A=94=EB=8D=B0,=20=EB=8F=84=EB=A1=9C?= =?UTF-8?q?=EB=AA=85=EC=A3=BC=EC=86=8C=EA=B0=80=20=EC=97=86=EC=96=B4?= =?UTF-8?q?=EC=84=9C=20=EC=BB=AC=EB=9F=BC=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/domain/form/domain/value/School.java | 5 ++++- .../form/dto/request/EducationRequest.java | 13 +++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java b/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java index 10125bff..84684803 100644 --- a/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java +++ b/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java @@ -19,10 +19,13 @@ public class School { @Column(name = "school_location", nullable = false, length = 20) private String location; + @Column(name = "school_address", nullable = false, length = 40) + private String address; + @Column(name = "school_code", nullable = false, length = 10) private String code; public boolean isBusan() { return location.equals("부산광역시"); } -} +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java b/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java index c47bd342..838b6a7e 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java @@ -25,15 +25,19 @@ public class EducationRequest { @Size(min = 4, max = 4, message = "4자여야 합니다.") private String graduationYear; - @NotBlank + @NotBlank(message = "필수값입니다.") @Size(max = 20, message = "20자 이하여야 합니다.") private String schoolName; - @NotBlank + @NotBlank(message = "필수값입니다.") @Size(max = 20, message = "20자 이하여야 합니다.") private String schoolLocation; - @NotBlank + @NotBlank(message = "필수값입니다.") + @Size(max = 40, message = "40자 이하여야 합니다.") + private String schoolAddress; + + @NotBlank(message = "필수값입니다.") @Size(min = 7, max = 7, message = "7자여야 합니다.") private String schoolCode; @@ -56,6 +60,7 @@ public Education toValue() { new School( schoolName, schoolLocation, + schoolAddress, schoolCode ), new Teacher( @@ -65,4 +70,4 @@ public Education toValue() { ) ); } -} +} \ No newline at end of file From 3fb015999ea9845ce79581520819828770c59421 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:46:13 +0900 Subject: [PATCH 09/59] =?UTF-8?q?test(#79):=20FormFixture,=20FormControlle?= =?UTF-8?q?rTest=20-=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=8F=84=20school=5Faddress=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=BC=EC=B6=94=EA=B0=80=EB=A5=BC=20=EB=B0=98=EC=98=81?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/form/FormControllerTest.java | 6 ++++++ .../bamdoliro/maru/shared/fixture/FormFixture.java | 12 ++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java index a01d821e..17720d9a 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java @@ -141,6 +141,9 @@ class FormControllerTest extends RestDocsTestSupport { fieldWithPath("education.schoolLocation") .type(JsonFieldType.STRING) .description("출신 학교 지역"), + fieldWithPath("education.schoolAddress") + .type(JsonFieldType.STRING) + .description("출신 학교 주소지"), fieldWithPath("education.schoolCode") .type(JsonFieldType.STRING) .description("출신 학교 코드"), @@ -753,6 +756,9 @@ class FormControllerTest extends RestDocsTestSupport { fieldWithPath("education.schoolLocation") .type(JsonFieldType.STRING) .description("출신 학교 지역"), + fieldWithPath("education.schoolAddress") + .type(JsonFieldType.STRING) + .description("출신 학교 주소지"), fieldWithPath("education.schoolCode") .type(JsonFieldType.STRING) .description("출신 학교 코드"), diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index d2cb004f..af98c7dd 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -74,7 +74,7 @@ public static Form createForm(FormType type) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -140,7 +140,7 @@ public static Form createRandomForm(User user) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -218,7 +218,7 @@ public static Form createRandomQualificationExaminationForm(User user) { new Education( GraduationType.QUALIFICATION_EXAMINATION, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), null ), new Grade( @@ -289,6 +289,7 @@ public static Form createQualificationExaminationForm(FormType type) { new School( "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003" ), null @@ -328,6 +329,7 @@ public static SubmitFormRequest createFormRequest(FormType type) { "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -369,6 +371,7 @@ public static SubmitFormRequest createQualificationExaminationFormRequest(FormTy "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", null, null, @@ -404,6 +407,7 @@ public static UpdateFormRequest createUpdateFormRequest(FormType type) { "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -549,4 +553,4 @@ public static FormUrlResponse createFormUrlResponse() { createFormUrlVo() ); } -} +} \ No newline at end of file From 3907f2e83b17bd2cde8e504f7f5459c48a659674 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:58:53 +0900 Subject: [PATCH 10/59] =?UTF-8?q?feat(#79):=20=EC=A0=84=ED=98=95=EB=B3=84?= =?UTF-8?q?=20=EC=A7=80=EC=9B=90=EC=9E=90=20=EC=88=98=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20-=20=EC=96=B4=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EB=B3=84=20=EC=A7=80=EC=9B=90=EC=9E=90=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryNumberOfApplicantsUseCase.java | 35 +++++++ .../form/FormRepositoryCustom.java | 12 ++- .../persistence/form/FormRepositoryImpl.java | 99 ++++++++++++++++++- .../persistence/form/vo/GradeVo.java | 26 +++++ .../form/vo/NumberOfApplicantsVo.java | 17 ++++ .../persistence/form/vo/SchoolStatusVo.java | 18 ++++ .../analysis/AnalysisController.java | 73 ++++++++++++++ .../response/NumberOfApplicantsResponse.java | 20 ++++ 8 files changed, 296 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java new file mode 100644 index 00000000..44d1c73c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java @@ -0,0 +1,35 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@UseCase +public class QueryNumberOfApplicantsUseCase { + private final FormRepository formRepository; + + public List execute() { + List result = formRepository.findTypeAndCountGroupByType() + .stream() + .map(NumberOfApplicantsResponse::new) + .collect(Collectors.toList()); + + List existingTypes = result.stream() + .map(NumberOfApplicantsResponse::getType) + .toList(); + + for (FormType formType: FormType.values()) { + if (!existingTypes.contains(formType)) { + result.add(new NumberOfApplicantsResponse(formType, 0L)); + } + } + + return result; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java index ed7dec7e..3be708e3 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java @@ -2,13 +2,19 @@ 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.infrastructure.persistence.form.vo.NumberOfApplicantsVo; import com.bamdoliro.maru.infrastructure.persistence.form.vo.FormUrlVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.SchoolStatusVo; import java.util.List; public interface FormRepositoryCustom { List findByStatus(FormStatus status); + List findByType(FormType type); + List findByCategory(FormType.Category category); List findReceivedSpecialForm(); List findReceivedRegularOrSupernumeraryForm(); List findFirstRoundForm(); @@ -17,4 +23,8 @@ public interface FormRepositoryCustom { List findSecondRoundForm(); List findByFormIdList(List idList); List findFormUrlByFormIdList(List idList); -} + List findTypeAndCountGroupByType(); + List findGradeGroupByTypeAndStatus(List round); + List findSchoolByAddress(List round, String keyword); + List findNotBusanSchool(List round); +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java index f78df470..8a6ba607 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java @@ -3,8 +3,7 @@ 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.infrastructure.persistence.form.vo.FormUrlVo; -import com.bamdoliro.maru.infrastructure.persistence.form.vo.QFormUrlVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.*; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @@ -12,6 +11,7 @@ import java.util.List; import java.util.Objects; +import java.util.stream.Stream; import static com.bamdoliro.maru.domain.form.domain.QForm.form; @@ -30,6 +30,26 @@ public List findByStatus(FormStatus status) { .fetch(); } + @Override + public List findByType(FormType type) { + return queryFactory + .selectFrom(form) + .where(eqType(type)) + .orderBy(form.examinationNumber.asc()) + .fetch(); + } + + @Override + public List findByCategory(FormType.Category category) { + List matchingFormTypes = getFormTypesByCategory(category); + + return queryFactory + .selectFrom(form) + .where(form.type.in(matchingFormTypes)) + .orderBy(form.examinationNumber.asc()) + .fetch(); + } + private BooleanExpression eqStatus(FormStatus status) { if (Objects.isNull(status)) { return null; @@ -38,6 +58,20 @@ private BooleanExpression eqStatus(FormStatus status) { return form.status.eq(status); } + private BooleanExpression eqType(FormType type) { + if (Objects.isNull(type)) { + return null; + } + + return form.type.eq(type); + } + + private List getFormTypesByCategory(FormType.Category category) { + return Stream.of(FormType.values()) + .filter(formType -> formType.categoryEquals(category)) + .toList(); + } + @Override public List findReceivedSpecialForm() { return queryFactory @@ -139,4 +173,63 @@ public List findFormUrlByFormIdList(List idList) { .orderBy(form.examinationNumber.asc()) .fetch(); } -} + + @Override + public List findTypeAndCountGroupByType() { + return queryFactory + .select(new QNumberOfApplicantsVo( + form.type, + form.count() + )) + .from(form) + .groupBy(form.type) + .fetch(); + } + + @Override + public List findGradeGroupByTypeAndStatus(List round) { + return queryFactory + .select(new QGradeVo( + form.type.stringValue(), + form.score.firstRoundScore.max(), + form.score.firstRoundScore.min(), + form.score.firstRoundScore.avg(), + form.score.totalScore.max(), + form.score.totalScore.min(), + form.score.totalScore.avg() + )) + .from(form) + .where(form.status.in(round)) + .groupBy(form.type) + .fetch(); + } + + @Override + public List findSchoolByAddress(List round, String keyword) { + return queryFactory + .select(new QSchoolStatusVo( + form.applicant.name, + form.education.school.name, + form.education.school.address + )) + .from(form) + .where(form.education.school.address.contains(keyword) + .or(form.education.school.location.eq(keyword)) + .and(form.status.in(round))) + .fetch(); + } + + @Override + public List findNotBusanSchool(List round) { + return queryFactory + .select(new QSchoolStatusVo( + form.applicant.name, + form.education.school.name, + form.education.school.address + )) + .from(form) + .where(form.education.school.location.eq("부산광역시").not() + .and(form.status.in(round))) + .fetch(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java new file mode 100644 index 00000000..5f531beb --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java @@ -0,0 +1,26 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class GradeVo { + private String type; + private Double firstRoundMax; + private Double firstRoundMin; + private Double firstRoundAvg; + private Double totalMax; + private Double totalMin; + private Double totalAvg; + + @QueryProjection + public GradeVo(String type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { + this.type = type; + this.firstRoundMax = firstRoundMax; + this.firstRoundMin = firstRoundMin; + this.firstRoundAvg = firstRoundAvg; + this.totalMax = totalMax; + this.totalMin = totalMin; + this.totalAvg = totalAvg; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java new file mode 100644 index 00000000..8f9c080c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class NumberOfApplicantsVo { + private FormType type; + private Long count; + + @QueryProjection + public NumberOfApplicantsVo(FormType type, Long count) { + this.type = type; + this.count = count; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java new file mode 100644 index 00000000..4350ba73 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java @@ -0,0 +1,18 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class SchoolStatusVo { + private String applicantName; + private String schoolName; + private String schoolAddress; + + @QueryProjection + public SchoolStatusVo(String applicantName, String schoolName, String schoolAddress) { + this.applicantName = applicantName; + this.schoolName = schoolName; + this.schoolAddress = schoolAddress; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java new file mode 100644 index 00000000..e696ef8c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java @@ -0,0 +1,73 @@ +package com.bamdoliro.maru.presentation.analysis; + +import com.bamdoliro.maru.application.analysis.QueryGenderRatioUseCase; +import com.bamdoliro.maru.application.analysis.QueryNumberOfApplicantsUseCase; +import com.bamdoliro.maru.application.analysis.QueryGradeDistributionUseCase; +import com.bamdoliro.maru.application.analysis.QuerySchoolStatusUseCase; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; +import com.bamdoliro.maru.shared.auth.AuthenticationPrincipal; +import com.bamdoliro.maru.shared.auth.Authority; +import com.bamdoliro.maru.shared.response.CommonResponse; +import com.bamdoliro.maru.shared.response.ListCommonResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RequestMapping("/analysis") +@RestController +public class AnalysisController { + private final QueryNumberOfApplicantsUseCase queryNumberOfApplicantsUseCase; + private final QueryGradeDistributionUseCase queryGradeDistributionUseCase; + private final QueryGenderRatioUseCase queryGenderRatioUseCase; + private final QuerySchoolStatusUseCase querySchoolStatusUseCase; + + @GetMapping("/number-of-applicants") + public ListCommonResponse getNumberOfApplicants( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user + ) { + return CommonResponse.ok( + queryNumberOfApplicantsUseCase.execute() + ); + } + + @GetMapping("/grade-distribution") + public ListCommonResponse getGradeDistribution( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid GradeDistributionRequest request + ) { + return CommonResponse.ok( + queryGradeDistributionUseCase.execute(request) + ); + } + + @GetMapping("/gender-ratio") + public ListCommonResponse getGenderRatio( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid GenderRatioRequest request + ) { + return CommonResponse.ok( + queryGenderRatioUseCase.execute(request) + ); + } + + @GetMapping("/school-status") + public ListCommonResponse getSchoolStatus( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid SchoolStatusRequest request + ) { + return CommonResponse.ok( + querySchoolStatusUseCase.execute(request) + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java new file mode 100644 index 00000000..c46a0da5 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java @@ -0,0 +1,20 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.NumberOfApplicantsVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class NumberOfApplicantsResponse { + private FormType type; + private Long count; + + public NumberOfApplicantsResponse(NumberOfApplicantsVo vo){ + this.type = vo.getType(); + this.count = vo.getCount(); + } +} \ No newline at end of file From 18b3166a242e976fed452f2ac6373d533f32cef2 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:00:13 +0900 Subject: [PATCH 11/59] =?UTF-8?q?feat(#79):=20=EC=84=B1=EC=A0=81=20?= =?UTF-8?q?=EB=B6=84=ED=8F=AC=20=EC=A1=B0=ED=9A=8C=20-=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84=ED=98=95=EB=B3=84=20?= =?UTF-8?q?=ED=95=99=EC=83=9D=EB=93=A4=EC=9D=98=20=EC=B5=9C=EA=B3=A0?= =?UTF-8?q?=EC=A0=90,=20=EC=B5=9C=ED=95=98=EC=A0=90,=20=ED=8F=89=EA=B7=A0?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryGradeDistributionUseCase.java | 22 ++++++++++++++ .../dto/request/GradeDistributionRequest.java | 17 +++++++++++ .../response/GradeDistributionResponse.java | 29 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java new file mode 100644 index 00000000..1bbd45e8 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -0,0 +1,22 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@UseCase +public class QueryGradeDistributionUseCase { + private final FormRepository formRepository; + + public List execute(GradeDistributionRequest request) { + return formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) + .stream() + .map(GradeDistributionResponse::new) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java new file mode 100644 index 00000000..f2828ead --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GradeDistributionRequest { + @NotNull(message = "필수값입니다.") + List statusList; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java new file mode 100644 index 00000000..c4f6d534 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java @@ -0,0 +1,29 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GradeDistributionResponse { + private String type; + private Double firstRoundMax; + private Double firstRoundMin; + private Double firstRoundAvg; + private Double totalMax; + private Double totalMin; + private Double totalAvg; + + public GradeDistributionResponse(GradeVo vo) { + this.type = vo.getType(); + this.firstRoundMax = vo.getFirstRoundMax(); + this.firstRoundMin = vo.getFirstRoundMin(); + this.firstRoundAvg = vo.getFirstRoundAvg(); + this.totalMax = vo.getTotalMax(); + this.totalMin = vo.getTotalMin(); + this.totalAvg = vo.getTotalAvg(); + } +} \ No newline at end of file From 4f72824ccaf06a1cc88ec7b6951cf21955098dd0 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:01:29 +0900 Subject: [PATCH 12/59] =?UTF-8?q?feat(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=84=B1=EB=B9=84=20=EB=B6=84=EC=84=9D=20-=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84=ED=98=95=EB=B3=84=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=EB=93=A4=EC=9D=98=20=EC=84=B1?= =?UTF-8?q?=EB=B3=84=EB=B6=84=ED=8F=AC=EB=A5=BC=20=ED=8C=8C=EC=95=85?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=9E=88=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 71 +++++++++++++++++++ .../dto/request/GenderRatioRequest.java | 21 ++++++ .../dto/response/GenderRatioResponse.java | 17 +++++ 3 files changed, 109 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java new file mode 100644 index 00000000..e71a24e2 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -0,0 +1,71 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.Form; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.domain.form.domain.type.Gender; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@UseCase +public class QueryGenderRatioUseCase { + private final FormRepository formRepository; + + public List execute(GenderRatioRequest request) { + List result = new ArrayList<>(); + + List subCategories = new ArrayList<>(); + + if (request.getMainCategory().equals(FormType.Category.REGULAR)) + subCategories.add(FormType.Category.REGULAR); + else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) + subCategories.addAll(List.of(FormType.Category.EQUAL_OPPORTUNITY, FormType.Category.SOCIETY_DIVERSITY)); + else subCategories.add(FormType.Category.SUPERNUMERARY); + + Map> formLists = subCategories.stream() + .collect(Collectors.toMap( + category -> category, + category -> formRepository.findByCategory(category).stream() + .filter(form -> request.getStatusList().contains(form.getStatus())) + .collect(Collectors.toList()) + )); + + for(Map.Entry> entry : formLists.entrySet()) { + FormType.Category category = entry.getKey(); + List formList = entry.getValue(); + + long busanMale = formList.stream().filter(this::isBusan).filter(this::isMale).count(); + long busanFeMale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); + long otherLocationMale = formList.stream().filter(this::isNotBusan).filter(this::isMale).count(); + long otherLocationFemale = formList.stream().filter(this::isNotBusan).filter(this::isFemale).count(); + + result.add(new GenderRatioResponse(category, busanMale, busanFeMale, otherLocationMale, otherLocationFemale)); + } + + return result; + } + + private boolean isBusan(Form form) { + return form.getEducation().getSchool().isBusan(); + } + + private boolean isNotBusan(Form form) { + return !isBusan(form); + } + + private boolean isMale(Form form) { + return form.getApplicant().getGender().equals(Gender.MALE); + } + + private boolean isFemale(Form form) { + return !isMale(form); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java new file mode 100644 index 00000000..6779ea6c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java @@ -0,0 +1,21 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GenderRatioRequest { + @NotNull(message = "필수값입니다.") + private List statusList; + + @NotNull(message = "필수값입니다.") + private FormType.Category mainCategory; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java new file mode 100644 index 00000000..152143c1 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GenderRatioResponse { + private FormType.Category category; + private long busanMale; + private long busanFemale; + private long otherLocationMale; + private long otherLocationFemale; +} \ No newline at end of file From aa61c902a4065ac094f6ffd6a8df4767fb53e253 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:02:25 +0900 Subject: [PATCH 13/59] =?UTF-8?q?feat(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=B6=9C=EC=8B=A0=20=ED=95=99=EA=B5=90=20=ED=98=84=ED=99=A9?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20-=20=EC=96=B4=EB=93=9C=EB=AF=BC?= =?UTF-8?q?=EC=9D=B4=20=EC=A7=80=EC=9B=90=EC=9E=90=EB=93=A4=EC=9D=98=20?= =?UTF-8?q?=EC=B6=9C=EC=8B=A0=20=ED=95=99=EA=B5=90=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QuerySchoolStatusUseCase.java | 33 +++++++++++++++++++ .../dto/request/SchoolStatusRequest.java | 25 ++++++++++++++ .../dto/response/SchoolStatusResponse.java | 21 ++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java new file mode 100644 index 00000000..883b31d9 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java @@ -0,0 +1,33 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@UseCase +public class QuerySchoolStatusUseCase { + + private final FormRepository formRepository; + + public List execute(SchoolStatusRequest request) { + if (request.getIsBusan()) { + String keyword = "부산광역시"; + keyword += request.getGu() == null ? "" : (" " + request.getGu()); + + return formRepository.findSchoolByAddress(request.getStatusList(), keyword) + .stream() + .map(SchoolStatusResponse::new) + .toList(); + } + + return formRepository.findNotBusanSchool(request.getStatusList()) + .stream() + .map(SchoolStatusResponse::new) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java new file mode 100644 index 00000000..be21084e --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java @@ -0,0 +1,25 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SchoolStatusRequest { + + @NotNull(message = "필수값입니다.") + private List statusList; + + @NotNull(message = "필수값입니다.") + private Boolean isBusan; + + @Nullable + private String gu; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java new file mode 100644 index 00000000..947081c7 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java @@ -0,0 +1,21 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.infrastructure.persistence.form.vo.SchoolStatusVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SchoolStatusResponse { + private String applicantName; + private String schoolName; + private String schoolAddress; + + public SchoolStatusResponse(SchoolStatusVo schoolStatusVo) { + this.applicantName = schoolStatusVo.getApplicantName(); + this.schoolName = schoolStatusVo.getSchoolName(); + this.schoolAddress = schoolStatusVo.getSchoolAddress(); + } +} \ No newline at end of file From b767c28c280fd4e454e46438fc453d7d7ea8e41c Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:03:55 +0900 Subject: [PATCH 14/59] =?UTF-8?q?build:=20application.yml=20-=20debug=20-?= =?UTF-8?q?=20debug=20=EB=A1=9C=EA=B7=B8=EA=B0=80=20=EB=84=88=EB=AC=B4=20?= =?UTF-8?q?=EA=B8=B8=EC=96=B4=EC=84=9C=20=EB=B3=B4=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=98=B5=EC=85=98=EC=9D=84=20fal?= =?UTF-8?q?se=EB=A1=9C=20=EB=B0=94=EA=BF=A8=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1e425339..602c8e54 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -78,7 +78,7 @@ spring: activate: on-profile: dev -debug: true +debug: false --- spring: config: @@ -101,7 +101,7 @@ spring: port: 6379 password: bamdoliro -debug: true +debug: false --- spring: config: @@ -135,4 +135,4 @@ spring: port: 6379 password: bamdoliro -debug: true +debug: false From 5a90a3658b714253e7bf2b0005c3b65710299c43 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Fri, 14 Jun 2024 23:24:06 +0900 Subject: [PATCH 15/59] =?UTF-8?q?fix(#79):=20=EC=9B=90=EC=84=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?-=20=EC=9B=90=EC=84=9C=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20schoolAd?= =?UTF-8?q?dress=EA=B0=80=20=EB=B3=B4=EC=9D=B4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=96=88=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/form/dto/response/EducationResponse.java | 2 ++ .../java/com/bamdoliro/maru/shared/fixture/FormFixture.java | 1 + 2 files changed, 3 insertions(+) diff --git a/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java b/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java index bb4191da..cbe2e1ca 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java @@ -14,6 +14,7 @@ public class EducationResponse { private String schoolName; private String schoolLocation; private String schoolCode; + private String schoolAddress; private String teacherName; private String teacherPhoneNumber; @@ -22,6 +23,7 @@ public EducationResponse(Education education) { this.graduationYear = education.getGraduationYear(); this.schoolName = education.getSchool().getName(); this.schoolLocation = education.getSchool().getLocation(); + this.schoolAddress = education.getSchool().getAddress(); this.schoolCode = education.getSchool().getCode(); this.teacherName = education.getTeacher().getName(); this.teacherPhoneNumber = education.getTeacher().getPhoneNumber().toString(); diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index af98c7dd..bb0880d4 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -464,6 +464,7 @@ public static FormResponse createFormResponse() { "비전중학교", "경기도", "7631003", + "경기도 용인시 비전구 비전로 1", "나교사", "0519701234" ), From 5bf9d99fd363d22d4413faf134274328c10999a3 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 01:01:55 +0900 Subject: [PATCH 16/59] =?UTF-8?q?perf(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=84=B1=EC=A0=81=20=EB=B6=84=ED=8F=AC=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=200=EC=A0=90=20=ED=91=9C=EC=8B=9C=20-=20=EC=A7=80=EC=9B=90?= =?UTF-8?q?=EC=9E=90=20=EC=88=98=EA=B0=80=20=EC=97=86=EB=8A=94=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EC=9D=80=20=EC=84=B1=EC=A0=81=20=EB=B6=84=ED=8F=AC?= =?UTF-8?q?=EA=B0=80=20=EB=82=98=EC=98=A4=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EA=B2=83=EC=97=90=EC=84=9C=200=EC=9C=BC=EB=A1=9C=20=EB=82=98?= =?UTF-8?q?=EC=98=A4=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=ED=96=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryGradeDistributionUseCase.java | 19 ++++++++++++++++++- .../QueryNumberOfApplicantsUseCase.java | 4 +++- .../persistence/form/FormRepositoryImpl.java | 2 +- .../persistence/form/vo/GradeVo.java | 5 +++-- .../response/GradeDistributionResponse.java | 3 ++- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java index 1bbd45e8..4dedf217 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -1,5 +1,6 @@ package com.bamdoliro.maru.application.analysis; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; @@ -11,12 +12,28 @@ @RequiredArgsConstructor @UseCase public class QueryGradeDistributionUseCase { + private final FormRepository formRepository; public List execute(GradeDistributionRequest request) { - return formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) + List result = new java.util.ArrayList<>(formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) .stream() .map(GradeDistributionResponse::new) + .toList()); + + List existingTypes = result + .stream() + .map(GradeDistributionResponse::getType) .toList(); + +// System.out.println(existingTypes); + + for (FormType formType : FormType.values()) { + if (!existingTypes.contains(formType)) { + result.add(new GradeDistributionResponse(formType, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + } + } + + return result; } } \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java index 44d1c73c..0b5ff0f8 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java @@ -12,6 +12,7 @@ @RequiredArgsConstructor @UseCase public class QueryNumberOfApplicantsUseCase { + private final FormRepository formRepository; public List execute() { @@ -20,7 +21,8 @@ public List execute() { .map(NumberOfApplicantsResponse::new) .collect(Collectors.toList()); - List existingTypes = result.stream() + List existingTypes = result + .stream() .map(NumberOfApplicantsResponse::getType) .toList(); diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java index 8a6ba607..cf1a4621 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java @@ -190,7 +190,7 @@ public List findTypeAndCountGroupByType() { public List findGradeGroupByTypeAndStatus(List round) { return queryFactory .select(new QGradeVo( - form.type.stringValue(), + form.type, form.score.firstRoundScore.max(), form.score.firstRoundScore.min(), form.score.firstRoundScore.avg(), diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java index 5f531beb..41755097 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java @@ -1,11 +1,12 @@ package com.bamdoliro.maru.infrastructure.persistence.form.vo; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.querydsl.core.annotations.QueryProjection; import lombok.Getter; @Getter public class GradeVo { - private String type; + private FormType type; private Double firstRoundMax; private Double firstRoundMin; private Double firstRoundAvg; @@ -14,7 +15,7 @@ public class GradeVo { private Double totalAvg; @QueryProjection - public GradeVo(String type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { + public GradeVo(FormType type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { this.type = type; this.firstRoundMax = firstRoundMax; this.firstRoundMin = firstRoundMin; diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java index c4f6d534..7104a85d 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java @@ -1,5 +1,6 @@ package com.bamdoliro.maru.presentation.analysis.dto.response; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; import lombok.AllArgsConstructor; import lombok.Getter; @@ -9,7 +10,7 @@ @NoArgsConstructor @AllArgsConstructor public class GradeDistributionResponse { - private String type; + private FormType type; private Double firstRoundMax; private Double firstRoundMin; private Double firstRoundAvg; From 5ba936a21cbe2af3ecd57209d758f641f1a21547 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 01:42:56 +0900 Subject: [PATCH 17/59] =?UTF-8?q?refactor(#79):=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/analysis/QueryGradeDistributionUseCase.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java index 4dedf217..21d2ecbb 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -26,8 +26,6 @@ public List execute(GradeDistributionRequest request) .map(GradeDistributionResponse::getType) .toList(); -// System.out.println(existingTypes); - for (FormType formType : FormType.values()) { if (!existingTypes.contains(formType)) { result.add(new GradeDistributionResponse(formType, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); From 19f3a00a6df13e82293b19ef3c0f17e2ca85b0ac Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:39:54 +0900 Subject: [PATCH 18/59] =?UTF-8?q?test(#79):=20AnalysisControllerTest=20-?= =?UTF-8?q?=20=EB=B6=84=EC=84=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/AnalysisControllerTest.java | 260 ++++++++++++++++++ .../maru/shared/fixture/AnalysisFixture.java | 82 ++++++ .../maru/shared/util/ControllerTest.java | 35 ++- .../maru/shared/util/RandomUtil.java | 4 + 4 files changed, 378 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java create mode 100644 src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java new file mode 100644 index 00000000..05040f4f --- /dev/null +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -0,0 +1,260 @@ +package com.bamdoliro.maru.presentation.analysis; + + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.shared.fixture.AnalysisFixture; +import com.bamdoliro.maru.shared.fixture.AuthFixture; +import com.bamdoliro.maru.shared.fixture.UserFixture; +import com.bamdoliro.maru.shared.util.RestDocsTestSupport; +import kotlinx.serialization.json.Json; +import org.junit.jupiter.api.Test; +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import java.util.List; +import java.util.Optional; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class AnalysisControllerTest extends RestDocsTestSupport { + + @Test + void 전형별_지원자수를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + given(queryNumberOfApplicantsUseCase.execute()).willReturn(AnalysisFixture.createNumberOfApplicantsResponse()); + + mockMvc.perform(get("/analysis/number-of-applicants") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders(headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ) + )); + } + + @Test + void _1차_합격자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + )); + System.out.println(AnalysisFixture.createGradeDistributionResponse()); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void _2차_전형자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.FAILED, + FormStatus.PASSED + )); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void 최종_합격자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.PASSED + )); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void 전형별_성비를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GenderRatioRequest request = new GenderRatioRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + FormType.Category.REGULAR); + given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse(FormType.Category.REGULAR)); + + mockMvc.perform(get("/analysis/gender-ratio") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("mainCategory").type(JsonFieldType.STRING).description("메인 카테고리(FormType.Category 참고)") + ) + )); + } + + @Test + void 부산_특정구_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + true, + "사상구"); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } + + @Test + void 부산_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + true, + null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } + + @Test + void 타지역_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + false, + null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } +} \ No newline at end of file diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java new file mode 100644 index 00000000..a3b14774 --- /dev/null +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -0,0 +1,82 @@ +package com.bamdoliro.maru.shared.fixture; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; +import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; + +public class AnalysisFixture { + + public static List createNumberOfApplicantsResponse() { + List responseList = new ArrayList<>(); + for (FormType formType : FormType.values()) { + responseList.add(new NumberOfApplicantsResponse(formType, (long)randomNumber(0, 50))); + } + return responseList; + } + + public static List createGradeDistributionResponse() { + List responseList = new ArrayList<>(); + for (FormType formType : FormType.values()) { + responseList.add(new GradeDistributionResponse(formType, randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0))); + } + return responseList; + } + + public static List createGenderRatioResponse(FormType.Category mainCategory) { + return List.of( + new GenderRatioResponse( + FormType.Category.REGULAR, + randomNumber(0, 30), + randomNumber(0, 15), + randomNumber(0, 30), + randomNumber(0, 15) + ) + ); + } + + public static List createSchoolStatusResponse(Boolean isBusan, String gu) { + if (isBusan) { + if (gu == null) { + return List.of( + new SchoolStatusResponse( + "김밤돌", + "신라중학교", + "부산광역시 사상구 백양대로700번길 35-8" + ), + new SchoolStatusResponse( + "김이로", + "성동중학교", + "부산광역시 남구 남동천로 38" + ), + new SchoolStatusResponse( + "금곰돌", + "가락중학교", + "부산광역시 강서구 가락대로 1405") + ); + } + return List.of( + new SchoolStatusResponse( + "김밤돌", + "신라중학교", + "부산광역시 사상구 백양대로700번길 35-8" + ) + ); + } + return List.of( + new SchoolStatusResponse( + "김밤돌", + "비전중학교", + "경기도 용인시 비전구 비전로 1" + ) + ); + } +} diff --git a/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java b/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java index 96bea802..19f1359c 100644 --- a/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java @@ -1,5 +1,9 @@ package com.bamdoliro.maru.shared.util; +import com.bamdoliro.maru.application.analysis.QueryGenderRatioUseCase; +import com.bamdoliro.maru.application.analysis.QueryGradeDistributionUseCase; +import com.bamdoliro.maru.application.analysis.QueryNumberOfApplicantsUseCase; +import com.bamdoliro.maru.application.analysis.QuerySchoolStatusUseCase; import com.bamdoliro.maru.application.auth.LogInUseCase; import com.bamdoliro.maru.application.auth.LogOutUseCase; import com.bamdoliro.maru.application.auth.RefreshTokenUseCase; @@ -53,6 +57,7 @@ import com.bamdoliro.maru.domain.auth.service.TokenService; import com.bamdoliro.maru.infrastructure.message.SendMessageService; import com.bamdoliro.maru.infrastructure.neis.SearchSchoolService; +import com.bamdoliro.maru.presentation.analysis.AnalysisController; import com.bamdoliro.maru.presentation.auth.AuthController; import com.bamdoliro.maru.presentation.fair.FairController; import com.bamdoliro.maru.presentation.form.DraftFormController; @@ -75,7 +80,17 @@ import org.springframework.test.web.servlet.MockMvc; @Disabled -@WebMvcTest({UserController.class, AuthController.class, SharedController.class, SchoolController.class, QuestionController.class, FormController.class, NoticeController.class, DraftFormController.class, FairController.class, MessageController.class}) +@WebMvcTest({UserController.class, + AuthController.class, + SharedController.class, + SchoolController.class, + QuestionController.class, + FormController.class, + NoticeController.class, + DraftFormController.class, + FairController.class, + MessageController.class, + AnalysisController.class}) public abstract class ControllerTest { @Autowired @@ -232,6 +247,22 @@ public abstract class ControllerTest { @MockBean protected QueryFormUrlUseCase queryFormUrlUseCase; + @MockBean + protected SendMessageUseCase sendMessageUseCase; + + @MockBean + protected QueryNumberOfApplicantsUseCase queryNumberOfApplicantsUseCase; + + @MockBean + protected QueryGradeDistributionUseCase queryGradeDistributionUseCase; + + @MockBean + protected QueryGenderRatioUseCase queryGenderRatioUseCase; + + @MockBean + protected QuerySchoolStatusUseCase querySchoolStatusUseCase; + + @MockBean protected TokenService tokenService; @@ -241,8 +272,6 @@ public abstract class ControllerTest { @MockBean protected SendMessageService sendMessageService; - @MockBean - protected SendMessageUseCase sendMessageUseCase; @MockBean protected JwtProperties jwtProperties; diff --git a/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java b/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java index c1ab939c..76e39edc 100644 --- a/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java +++ b/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java @@ -9,4 +9,8 @@ public static String randomPhoneNumber() { public static int randomNumber(int min, int max) { return (int) ((Math.random() * (max - min)) + min); } + + public static double randomDouble(double min, double max) { + return Math.round(((Math.random() * (max - min)) + min) * 1000.0) / 1000.0; + } } From b02735463eccf4baf51f1acc1a902317b23233cd Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:40:22 +0900 Subject: [PATCH 19/59] =?UTF-8?q?docs(#79):=20analysis.adoc=20-=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/analysis.adoc | 92 +++++++++++++++++++++++++++++++++ src/docs/asciidoc/index.adoc | 2 + 2 files changed, 94 insertions(+) create mode 100644 src/docs/asciidoc/analysis.adoc diff --git a/src/docs/asciidoc/analysis.adoc b/src/docs/asciidoc/analysis.adoc new file mode 100644 index 00000000..8354f760 --- /dev/null +++ b/src/docs/asciidoc/analysis.adoc @@ -0,0 +1,92 @@ +== 분석 Analysis + +=== 전형별 지원자 수 조회 +전형별 지원자들의 수를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/request-headers.adoc[] + +==== 요청 +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/http-request.adoc[] + +==== 응답 +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/http-response.adoc[] + +=== 전형별 성적 분포 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 전형별 성적 분포를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-fields.adoc[] + +==== 요청 + +===== 1차 합격자 +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/http-request.adoc[] + +===== 2차 전형자 +include::{snippets}/analysis-controller-test/_2차_전형자들의_성적_분포를_조회한다/http-request.adoc[] + +===== 최종 합격자 +include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분포를_조회한다/http-request.adoc[] + +==== 응답 + +===== 정상 응답 +include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분포를_조회한다/http-response.adoc[] + +=== 전형별 성비 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 전형별, 지역별 성비를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-fields.adoc[] + +==== 요청 +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-request.adoc[] + +==== 응답 + +===== 정상 응답 +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-response.adoc[] + +=== 전형별 출신학교 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 출신학교를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-fields.adoc[] + +==== 요청 +===== 부산 특정구 출신 +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 부산 출신 +include::{snippets}/analysis-controller-test/부산_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 타지역 출신 +include::{snippets}/analysis-controller-test/타지역_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 응답 +==== 부산 특정구 출신 정상 응답 +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] + +==== 부산 출신 정상 응답 +include::{snippets}/analysis-controller-test/부산_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] + +==== 타지역 출신 정상 응답 +include::{snippets}/analysis-controller-test/타지역_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 4a46528e..d64e5a35 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -27,4 +27,6 @@ include::fair.adoc[] include::message.adoc[] +include::analysis.adoc[] + include::enum.adoc[] From c70c17dfc13e47cf03ed9085cb26a16202c534ad Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:41:28 +0900 Subject: [PATCH 20/59] =?UTF-8?q?refactor(#79):=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/analysis/AnalysisControllerTest.java | 2 -- .../java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java | 1 - 2 files changed, 3 deletions(-) diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java index 05040f4f..ba782869 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -11,7 +11,6 @@ import com.bamdoliro.maru.shared.fixture.AuthFixture; import com.bamdoliro.maru.shared.fixture.UserFixture; import com.bamdoliro.maru.shared.util.RestDocsTestSupport; -import kotlinx.serialization.json.Json; import org.junit.jupiter.api.Test; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; @@ -19,7 +18,6 @@ import org.springframework.restdocs.payload.JsonFieldType; import java.util.List; -import java.util.Optional; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index a3b14774..a405d6b6 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; From 65e6e31c717cee6992cdaa6a39aef473508f4b02 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 23:24:48 +0900 Subject: [PATCH 21/59] =?UTF-8?q?fix(#79):=20SchoolResponse=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20=ED=95=99=EA=B5=90=EB=A5=BC=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=ED=95=A0=20=EB=95=8C=20=ED=95=99=EA=B5=90=EC=9D=98=20?= =?UTF-8?q?=EB=8F=84=EB=A1=9C=EB=AA=85=20=EC=A3=BC=EC=86=8C=EA=B0=80=20?= =?UTF-8?q?=ED=95=A8=EA=BB=98=20=EB=82=98=EC=98=A4=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../neis/SearchSchoolService.java | 1 + .../school/dto/response/SchoolResponse.java | 1 + .../maru/shared/fixture/AnalysisFixture.java | 2 +- .../maru/shared/fixture/FormFixture.java | 16 ++++----- .../maru/shared/fixture/SchoolFixture.java | 34 +++++++++---------- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java b/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java index 1bf2cf34..19acfd86 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java @@ -27,6 +27,7 @@ public List execute(String q) throws JsonProcessingException { .map(s -> SchoolResponse.builder() .name(s.getSchoolName()) .location(s.getLocation()) + .address((s.getAddress())) .code(s.getStandardSchoolCode()) .build()) .toList(); diff --git a/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java b/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java index b9846bfc..0bbf9120 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java @@ -11,5 +11,6 @@ public class SchoolResponse { private String name; private String location; + private String address; private String code; } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index a405d6b6..4c439e51 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -74,7 +74,7 @@ public static List createSchoolStatusResponse(Boolean isBu new SchoolStatusResponse( "김밤돌", "비전중학교", - "경기도 용인시 비전구 비전로 1" + "경기도 비전시 비전구 비전로 1" ) ); } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index bb0880d4..d3637da6 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -74,7 +74,7 @@ public static Form createForm(FormType type) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -140,7 +140,7 @@ public static Form createRandomForm(User user) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -218,7 +218,7 @@ public static Form createRandomQualificationExaminationForm(User user) { new Education( GraduationType.QUALIFICATION_EXAMINATION, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), null ), new Grade( @@ -289,7 +289,7 @@ public static Form createQualificationExaminationForm(FormType type) { new School( "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003" ), null @@ -329,7 +329,7 @@ public static SubmitFormRequest createFormRequest(FormType type) { "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -371,7 +371,7 @@ public static SubmitFormRequest createQualificationExaminationFormRequest(FormTy "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", null, null, @@ -407,7 +407,7 @@ public static UpdateFormRequest createUpdateFormRequest(FormType type) { "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -464,7 +464,7 @@ public static FormResponse createFormResponse() { "비전중학교", "경기도", "7631003", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "나교사", "0519701234" ), diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java index 46d468ea..f329dc87 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java @@ -8,22 +8,22 @@ public class SchoolFixture { public static List createSchoolListResponse() { return List.of( - new SchoolResponse("부산소프트웨어마이스터고등학교", "부산광역시", "7150658") - ); - } + new SchoolResponse("부산소프트웨어마이스터고등학교", "부산광역시", "부산광역시 강서구 가락대로 1393", "7150658") +); +} - public static List createSchoolMaxListResponse() { - return List.of( - new SchoolResponse("비전고등학교", "경기도", "7531109"), - new SchoolResponse("비전중학교", "경기도", "7631003"), - new SchoolResponse("비전초등학교", "경기도", "7631034"), - new SchoolResponse("공동체비전고등학교", "충청남도", "8140222"), - new SchoolResponse("다른비전고등학교", "경상북도", "7531109"), - new SchoolResponse("다른비전중학교", "경기도", "7631003"), - new SchoolResponse("다른비전초등학교", "경상남도", "7631034"), - new SchoolResponse("다른공동체비전고등학교", "충청남도", "8140222"), - new SchoolResponse("또다른비전고등학교", "대구광역시", "7531109"), - new SchoolResponse("또다른비전중학교", "경기도", "7631003") - ); - } +public static List createSchoolMaxListResponse() { +return List.of( +new SchoolResponse("비전고등학교", "경기도", "경기도 비전시 비전구 비전로 2", "7531109"), +new SchoolResponse("비전중학교", "경기도","경기도 비전시 비전구 비전로 1", "7631003"), +new SchoolResponse("비전초등학교", "경기도", "경기도 비전시 비전구 비전로 3", "7631034"), +new SchoolResponse("공동체비전고등학교", "충청남도", "충청남도 비전시 비전구 비전로 1", "8140222"), +new SchoolResponse("다른비전고등학교", "경상북도", "경상북도 비전시 비전구 비전로 1", "7531109"), +new SchoolResponse("다른비전중학교", "경기도", "경기도 비전시 비전구 비전로 4", "7631003"), +new SchoolResponse("다른비전초등학교", "경상남도", "경상남도 비전시 비전구 비전로 1", "7631034"), +new SchoolResponse("다른공동체비전고등학교", "충청남도", "충청남도 비전시 비전구 비전로 2", "8140222"), +new SchoolResponse("또다른비전고등학교", "대구광역시", "대구광역시 비전구 비전로 1", "7531109"), +new SchoolResponse("또다른비전중학교", "경기도", "경기도 비전시 비전구 비전로 5", "7631003") +); +} } From d9bb4ffe24822453a9e213bdffdeac143a042300 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Wed, 19 Jun 2024 03:52:03 +0900 Subject: [PATCH 22/59] =?UTF-8?q?refactor(#79):=20Parameter=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20-=20HTTP=20GET=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=8A=94=20RequestBody=EB=A5=BC=20=EA=B6=8C?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=EB=8B=A4?= =?UTF-8?q?=EB=8A=94=EA=B2=83=EC=9D=84=20=EC=95=8C=EC=95=84=EC=84=9C=20Par?= =?UTF-8?q?ameter=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.=20-=20@ModelAttr?= =?UTF-8?q?ibute=EC=9D=98=20=EC=9E=91=EB=8F=99=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9D=B4=20Setter=EB=A5=BC=20=EC=9D=B4=EC=9A=A9=ED=95=B4=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20=EC=A3=BC=EC=9E=85=ED=95=98=EB=8A=94?= =?UTF-8?q?=EA=B2=83=EC=9D=B4=EC=96=B4=EC=84=9C=20request=20dto=EC=97=90?= =?UTF-8?q?=20setter=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=96=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/analysis.adoc | 12 +- .../analysis/AnalysisController.java | 11 +- .../dto/request/GenderRatioRequest.java | 2 + .../dto/request/GradeDistributionRequest.java | 3 + .../dto/request/SchoolStatusRequest.java | 2 + .../analysis/AnalysisControllerTest.java | 179 +++++++++--------- .../maru/shared/fixture/AnalysisFixture.java | 7 +- 7 files changed, 114 insertions(+), 102 deletions(-) diff --git a/src/docs/asciidoc/analysis.adoc b/src/docs/asciidoc/analysis.adoc index 8354f760..f591d69f 100644 --- a/src/docs/asciidoc/analysis.adoc +++ b/src/docs/asciidoc/analysis.adoc @@ -22,8 +22,8 @@ include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한 ==== Request Header include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/query-parameters.adoc[] ==== 요청 @@ -49,8 +49,8 @@ include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분 ==== Request Header include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/query-parameters.adoc[] ==== 요청 include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-request.adoc[] @@ -68,8 +68,8 @@ include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/ht ==== Request Header include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/query-parameters.adoc[] ==== 요청 ===== 부산 특정구 출신 diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java index e696ef8c..b5305f49 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java @@ -18,10 +18,7 @@ import com.bamdoliro.maru.shared.response.ListCommonResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor @RequestMapping("/analysis") @@ -44,7 +41,7 @@ public ListCommonResponse getNumberOfApplicants( @GetMapping("/grade-distribution") public ListCommonResponse getGradeDistribution( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid GradeDistributionRequest request + @ModelAttribute @Valid GradeDistributionRequest request ) { return CommonResponse.ok( queryGradeDistributionUseCase.execute(request) @@ -54,7 +51,7 @@ public ListCommonResponse getGradeDistribution( @GetMapping("/gender-ratio") public ListCommonResponse getGenderRatio( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid GenderRatioRequest request + @ModelAttribute @Valid GenderRatioRequest request ) { return CommonResponse.ok( queryGenderRatioUseCase.execute(request) @@ -64,7 +61,7 @@ public ListCommonResponse getGenderRatio( @GetMapping("/school-status") public ListCommonResponse getSchoolStatus( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid SchoolStatusRequest request + @ModelAttribute @Valid SchoolStatusRequest request ) { return CommonResponse.ok( querySchoolStatusUseCase.execute(request) diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java index 6779ea6c..e4af7ffa 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java @@ -6,10 +6,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class GenderRatioRequest { diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java index f2828ead..beb0333e 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java @@ -5,13 +5,16 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class GradeDistributionRequest { + @NotNull(message = "필수값입니다.") List statusList; } \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java index be21084e..b1137393 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java @@ -6,10 +6,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class SchoolStatusRequest { diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java index ba782869..36dc3583 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -1,7 +1,6 @@ package com.bamdoliro.maru.presentation.analysis; -import com.bamdoliro.maru.domain.form.domain.type.FormStatus; import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.domain.user.domain.User; import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; @@ -15,16 +14,18 @@ import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import java.util.List; +import java.util.Objects; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -43,7 +44,8 @@ class AnalysisControllerTest extends RestDocsTestSupport { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(restDocs.document( - requestHeaders(headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ) )); } @@ -53,26 +55,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - )); - System.out.println(AnalysisFixture.createGradeDistributionResponse()); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "FIRST_PASSED", "FAILED", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -82,24 +81,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.FAILED, - FormStatus.PASSED - )); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "FAILED", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -109,23 +107,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.PASSED - )); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -135,27 +133,30 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GenderRatioRequest request = new GenderRatioRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - FormType.Category.REGULAR); - given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse(FormType.Category.REGULAR)); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("mainCategory", "REGULAR"); + given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse( + FormType.Category.valueOf(Objects.requireNonNull(multiValueMap.get("mainCategory")).get(0)) + )); mockMvc.perform(get("/analysis/gender-ratio") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("mainCategory").type(JsonFieldType.STRING).description("메인 카테고리(FormType.Category 참고)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("mainCategory") + .description("메인 카테고리(FormType.Category 참고)") ) )); } @@ -165,29 +166,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - true, - "사상구"); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "true"); + multiValueMap.add("gu", "사상구"); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") - .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .params(multiValueMap) + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } @@ -197,29 +200,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - true, - null); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "true"); + multiValueMap.add("gu", null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } @@ -229,29 +234,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - false, - null); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "false"); + multiValueMap.add("gu", null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index 4c439e51..66c9748c 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; @@ -42,9 +43,9 @@ public static List createGenderRatioResponse(FormType.Categ ); } - public static List createSchoolStatusResponse(Boolean isBusan, String gu) { - if (isBusan) { - if (gu == null) { + public static List createSchoolStatusResponse(List isBusan, List gu) { + if (Objects.equals(isBusan.get(0), "true")) { + if (gu.get(0) == null) { return List.of( new SchoolStatusResponse( "김밤돌", From 47cfff72e636cb6ae7dcc1bb73cd37e106fd5106 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 20 Jun 2024 13:15:51 +0900 Subject: [PATCH 23/59] =?UTF-8?q?fix(#79):=20=EC=84=B1=EB=B9=84=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?-=20=ED=8A=B9=EB=B3=84=20=EC=A0=84=ED=98=95=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=ED=96=88=EC=9D=84=20=EB=95=8C=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=ED=84=B0=20=EC=9D=B8=EC=9E=AC=EC=A0=84?= =?UTF-8?q?=ED=98=95=EA=B3=BC=20=EC=A0=95=EC=9B=90=20=EC=99=B8=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EC=9D=B4=20=EB=82=98=EC=98=A4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4=20-=20=ED=8A=B9=EB=A1=80?= =?UTF-8?q?=EC=9E=85=ED=95=99=20=EB=8C=80=EC=83=81=EC=9E=90=EB=A5=BC=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=96=88=EC=9D=84=20=EB=95=8C=20=ED=8A=B9?= =?UTF-8?q?=EB=B3=84=EC=A0=84=ED=98=95=EC=9D=98=20=EC=A0=95=EC=9B=90=20?= =?UTF-8?q?=EC=99=B8=20=EC=A0=84=ED=98=95=EC=9D=B4=20=EB=82=98=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.=20=EA=B5=AD=EA=B0=80?= =?UTF-8?q?=EB=B3=B4=ED=9B=88=EC=9E=90=EB=85=80=EC=99=80=20=ED=8A=B9?= =?UTF-8?q?=EB=A1=80=EC=9E=85=ED=95=99=EC=9D=B4=20=EB=98=91=EA=B0=99?= =?UTF-8?q?=EC=9D=B4=20=EC=A0=95=EC=9B=90=20=EC=99=B8=20=EC=A0=84=ED=98=95?= =?UTF-8?q?=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=A7=8C=20=EC=9E=88?= =?UTF-8?q?=EA=B3=A0=20=EA=B5=AD=EA=B0=80=EB=B3=B4=ED=9B=88=EC=9E=90?= =?UTF-8?q?=EB=85=80=EA=B0=80=20=ED=8A=B9=EB=B3=84=20=EC=A0=84=ED=98=95=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EC=97=90=20=EB=93=A4?= =?UTF-8?q?=EC=96=B4=EC=9E=88=EC=A7=80=20=EC=95=8A=EC=95=84=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EC=A2=80=20=EB=8D=94=EB=9F=AC=EC=9B=8C?= =?UTF-8?q?=EC=A1=8C=EC=8A=B5=EB=8B=88=EB=8B=A4...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 19 ++++++++++++------- .../shared/response/EnumControllerTest.java | 2 +- .../shared/response/SharedController.java | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java index e71a24e2..5af89d3f 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -20,15 +20,14 @@ public class QueryGenderRatioUseCase { private final FormRepository formRepository; public List execute(GenderRatioRequest request) { + FormType.Category mainCategory = request.getMainCategory(); List result = new ArrayList<>(); - List subCategories = new ArrayList<>(); - if (request.getMainCategory().equals(FormType.Category.REGULAR)) + if (mainCategory.equals(FormType.Category.REGULAR)) subCategories.add(FormType.Category.REGULAR); - else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) - subCategories.addAll(List.of(FormType.Category.EQUAL_OPPORTUNITY, FormType.Category.SOCIETY_DIVERSITY)); - else subCategories.add(FormType.Category.SUPERNUMERARY); + else if (mainCategory.equals(FormType.Category.SPECIAL)) + subCategories.addAll(List.of(FormType.Category.MEISTER_TALENT, FormType.Category.SOCIAL_INTEGRATION)); Map> formLists = subCategories.stream() .collect(Collectors.toMap( @@ -38,16 +37,22 @@ else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) .collect(Collectors.toList()) )); + if (mainCategory.equals(FormType.Category.SPECIAL)) { + formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.NATIONAL_VETERANS_EDUCATION)); + } else if(mainCategory.equals(FormType.Category.SUPERNUMERARY)) { + formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.SPECIAL_ADMISSION)); + } + for(Map.Entry> entry : formLists.entrySet()) { FormType.Category category = entry.getKey(); List formList = entry.getValue(); long busanMale = formList.stream().filter(this::isBusan).filter(this::isMale).count(); - long busanFeMale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); + long busanFemale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); long otherLocationMale = formList.stream().filter(this::isNotBusan).filter(this::isMale).count(); long otherLocationFemale = formList.stream().filter(this::isNotBusan).filter(this::isFemale).count(); - result.add(new GenderRatioResponse(category, busanMale, busanFeMale, otherLocationMale, otherLocationFemale)); + result.add(new GenderRatioResponse(category, busanMale, busanFemale, otherLocationMale, otherLocationFemale)); } return result; diff --git a/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java b/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java index 2a383d01..56c80893 100644 --- a/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java @@ -63,7 +63,7 @@ void enums() throws Exception { ), customResponseFields("custom-response", beneathPath("gender").withSubsectionId("gender"), - attributes(key("title").value("GraduationType")), + attributes(key("title").value("Gender")), enumConvertFieldDescriptor((enumDocs.getGender())) ), customResponseFields("custom-response", diff --git a/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java b/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java index b3459002..f2d7d2b0 100644 --- a/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java +++ b/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java @@ -36,7 +36,7 @@ public EnumDocs findEnums() { .certificate(getDocs(Certificate.values())) .formStatus(getDocs(FormStatus.values())) .formType(getDocs(FormType.values())) - .gender(getDocs(GraduationType.values())) + .gender(getDocs(Gender.values())) .graduationType(getDocs(GraduationType.values())) .fairStatus(getDocs(FairStatus.values())) .fairType(getDocs(FairType.values())) From dbaaddddc615177aa75e1417ef31c86b8408226e Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 20 Jun 2024 23:08:34 +0900 Subject: [PATCH 24/59] =?UTF-8?q?perf(#79):=20=EC=A0=95=EC=9B=90=20?= =?UTF-8?q?=EC=99=B8=20=EC=A0=84=ED=98=95=20=EC=A1=B0=ED=9A=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 14 +++++++------- .../maru/domain/form/domain/type/FormType.java | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java index 5af89d3f..008260e8 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -27,7 +27,13 @@ public List execute(GenderRatioRequest request) { if (mainCategory.equals(FormType.Category.REGULAR)) subCategories.add(FormType.Category.REGULAR); else if (mainCategory.equals(FormType.Category.SPECIAL)) - subCategories.addAll(List.of(FormType.Category.MEISTER_TALENT, FormType.Category.SOCIAL_INTEGRATION)); + subCategories.addAll(List.of( + FormType.Category.MEISTER_TALENT, + FormType.Category.SOCIAL_INTEGRATION)); + else if (mainCategory.equals(FormType.Category.SUPERNUMERARY)) + subCategories.addAll(List.of( + FormType.Category.NATIONAL_VETERANS_EDUCATION, + FormType.Category.SPECIAL_ADMISSION)); Map> formLists = subCategories.stream() .collect(Collectors.toMap( @@ -37,12 +43,6 @@ else if (mainCategory.equals(FormType.Category.SPECIAL)) .collect(Collectors.toList()) )); - if (mainCategory.equals(FormType.Category.SPECIAL)) { - formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.NATIONAL_VETERANS_EDUCATION)); - } else if(mainCategory.equals(FormType.Category.SUPERNUMERARY)) { - formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.SPECIAL_ADMISSION)); - } - for(Map.Entry> entry : formLists.entrySet()) { FormType.Category category = entry.getKey(); List formList = entry.getValue(); diff --git a/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java b/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java index 18c9fbfa..fa827815 100644 --- a/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java +++ b/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java @@ -25,8 +25,8 @@ public enum FormType implements EnumProperty { MULTI_CHILDREN("다자녀가정자녀", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY), FARMING_AND_FISHING("농어촌지역출신자", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY), - NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀", Category.SUPERNUMERARY, null, null), - SPECIAL_ADMISSION("특례입학대상자", Category.SUPERNUMERARY, null, null), + NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀", Category.SUPERNUMERARY, Category.NATIONAL_VETERANS_EDUCATION, null), + SPECIAL_ADMISSION("특례입학대상자", Category.SUPERNUMERARY, Category.SPECIAL_ADMISSION, null), ; @@ -46,6 +46,8 @@ public enum Category implements EnumProperty { // Middle Category SOCIAL_INTEGRATION("사회통합전형"), MEISTER_TALENT("마이스터인재전형"), + NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀"), + SPECIAL_ADMISSION("특례입학대상자"), // Sub Category EQUAL_OPPORTUNITY("기회균등전형"), From 4b56e9e6dac3e0ce5eaf2924f1a2d6f227802674 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:45:32 +0900 Subject: [PATCH 25/59] =?UTF-8?q?feat(#79):=20=EC=9B=90=EC=84=9C=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=EC=97=90=20school=5Faddress=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80=20-=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=EC=9D=98=20=EC=B6=9C=EC=8B=A0=20?= =?UTF-8?q?=ED=95=99=EA=B5=90=EC=9D=98=20=EB=8F=84=EB=A1=9C=EB=AA=85=20?= =?UTF-8?q?=EC=A3=BC=EC=86=8C=EB=A5=BC=20=ED=91=9C=EA=B8=B0=ED=95=B4?= =?UTF-8?q?=EC=95=BC=20=ED=95=98=EB=8A=94=EB=8D=B0,=20=EB=8F=84=EB=A1=9C?= =?UTF-8?q?=EB=AA=85=EC=A3=BC=EC=86=8C=EA=B0=80=20=EC=97=86=EC=96=B4?= =?UTF-8?q?=EC=84=9C=20=EC=BB=AC=EB=9F=BC=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/domain/form/domain/value/School.java | 5 ++++- .../form/dto/request/EducationRequest.java | 13 +++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java b/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java index 10125bff..84684803 100644 --- a/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java +++ b/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java @@ -19,10 +19,13 @@ public class School { @Column(name = "school_location", nullable = false, length = 20) private String location; + @Column(name = "school_address", nullable = false, length = 40) + private String address; + @Column(name = "school_code", nullable = false, length = 10) private String code; public boolean isBusan() { return location.equals("부산광역시"); } -} +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java b/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java index c47bd342..838b6a7e 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java @@ -25,15 +25,19 @@ public class EducationRequest { @Size(min = 4, max = 4, message = "4자여야 합니다.") private String graduationYear; - @NotBlank + @NotBlank(message = "필수값입니다.") @Size(max = 20, message = "20자 이하여야 합니다.") private String schoolName; - @NotBlank + @NotBlank(message = "필수값입니다.") @Size(max = 20, message = "20자 이하여야 합니다.") private String schoolLocation; - @NotBlank + @NotBlank(message = "필수값입니다.") + @Size(max = 40, message = "40자 이하여야 합니다.") + private String schoolAddress; + + @NotBlank(message = "필수값입니다.") @Size(min = 7, max = 7, message = "7자여야 합니다.") private String schoolCode; @@ -56,6 +60,7 @@ public Education toValue() { new School( schoolName, schoolLocation, + schoolAddress, schoolCode ), new Teacher( @@ -65,4 +70,4 @@ public Education toValue() { ) ); } -} +} \ No newline at end of file From 88fbd9c66b068be7f655332aec8d39cc8a490675 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:46:13 +0900 Subject: [PATCH 26/59] =?UTF-8?q?test(#79):=20FormFixture,=20FormControlle?= =?UTF-8?q?rTest=20-=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=8F=84=20school=5Faddress=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=BC=EC=B6=94=EA=B0=80=EB=A5=BC=20=EB=B0=98=EC=98=81?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/form/FormControllerTest.java | 6 ++++++ .../bamdoliro/maru/shared/fixture/FormFixture.java | 12 ++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java index a01d821e..17720d9a 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java @@ -141,6 +141,9 @@ class FormControllerTest extends RestDocsTestSupport { fieldWithPath("education.schoolLocation") .type(JsonFieldType.STRING) .description("출신 학교 지역"), + fieldWithPath("education.schoolAddress") + .type(JsonFieldType.STRING) + .description("출신 학교 주소지"), fieldWithPath("education.schoolCode") .type(JsonFieldType.STRING) .description("출신 학교 코드"), @@ -753,6 +756,9 @@ class FormControllerTest extends RestDocsTestSupport { fieldWithPath("education.schoolLocation") .type(JsonFieldType.STRING) .description("출신 학교 지역"), + fieldWithPath("education.schoolAddress") + .type(JsonFieldType.STRING) + .description("출신 학교 주소지"), fieldWithPath("education.schoolCode") .type(JsonFieldType.STRING) .description("출신 학교 코드"), diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index f2d20375..ebba8427 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -74,7 +74,7 @@ public static Form createForm(FormType type) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -140,7 +140,7 @@ public static Form createRandomForm(User user) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -218,7 +218,7 @@ public static Form createRandomQualificationExaminationForm(User user) { new Education( GraduationType.QUALIFICATION_EXAMINATION, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), null ), new Grade( @@ -289,6 +289,7 @@ public static Form createQualificationExaminationForm(FormType type) { new School( "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003" ), null @@ -328,6 +329,7 @@ public static SubmitFormRequest createFormRequest(FormType type) { "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -369,6 +371,7 @@ public static SubmitFormRequest createQualificationExaminationFormRequest(FormTy "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", null, null, @@ -404,6 +407,7 @@ public static UpdateFormRequest createUpdateFormRequest(FormType type) { "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -550,4 +554,4 @@ public static FormUrlResponse createFormUrlResponse() { createFormUrlVo() ); } -} +} \ No newline at end of file From a1c0cc92847e545adf1eea29cd7bed6a608b1d5a Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:58:53 +0900 Subject: [PATCH 27/59] =?UTF-8?q?feat(#79):=20=EC=A0=84=ED=98=95=EB=B3=84?= =?UTF-8?q?=20=EC=A7=80=EC=9B=90=EC=9E=90=20=EC=88=98=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20-=20=EC=96=B4=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EB=B3=84=20=EC=A7=80=EC=9B=90=EC=9E=90=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryNumberOfApplicantsUseCase.java | 35 +++++++ .../form/FormRepositoryCustom.java | 12 ++- .../persistence/form/FormRepositoryImpl.java | 99 ++++++++++++++++++- .../persistence/form/vo/GradeVo.java | 26 +++++ .../form/vo/NumberOfApplicantsVo.java | 17 ++++ .../persistence/form/vo/SchoolStatusVo.java | 18 ++++ .../analysis/AnalysisController.java | 73 ++++++++++++++ .../response/NumberOfApplicantsResponse.java | 20 ++++ 8 files changed, 296 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java new file mode 100644 index 00000000..44d1c73c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java @@ -0,0 +1,35 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@UseCase +public class QueryNumberOfApplicantsUseCase { + private final FormRepository formRepository; + + public List execute() { + List result = formRepository.findTypeAndCountGroupByType() + .stream() + .map(NumberOfApplicantsResponse::new) + .collect(Collectors.toList()); + + List existingTypes = result.stream() + .map(NumberOfApplicantsResponse::getType) + .toList(); + + for (FormType formType: FormType.values()) { + if (!existingTypes.contains(formType)) { + result.add(new NumberOfApplicantsResponse(formType, 0L)); + } + } + + return result; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java index 7c2dd0ab..4f9cbe87 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java @@ -2,13 +2,19 @@ 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.infrastructure.persistence.form.vo.NumberOfApplicantsVo; import com.bamdoliro.maru.infrastructure.persistence.form.vo.FormUrlVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.SchoolStatusVo; import java.util.List; public interface FormRepositoryCustom { List findByStatus(FormStatus status); + List findByType(FormType type); + List findByCategory(FormType.Category category); List findReceivedSpecialForm(); List findReceivedRegularOrSupernumeraryForm(); List findFirstRoundForm(); @@ -18,4 +24,8 @@ public interface FormRepositoryCustom { List findSecondRoundForm(); List findByFormIdList(List idList); List findFormUrlByFormIdList(List idList); -} + List findTypeAndCountGroupByType(); + List findGradeGroupByTypeAndStatus(List round); + List findSchoolByAddress(List round, String keyword); + List findNotBusanSchool(List round); +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java index d8cc004e..36b65a7b 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java @@ -3,8 +3,7 @@ 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.infrastructure.persistence.form.vo.FormUrlVo; -import com.bamdoliro.maru.infrastructure.persistence.form.vo.QFormUrlVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.*; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @@ -12,6 +11,7 @@ import java.util.List; import java.util.Objects; +import java.util.stream.Stream; import static com.bamdoliro.maru.domain.form.domain.QForm.form; @@ -30,6 +30,26 @@ public List findByStatus(FormStatus status) { .fetch(); } + @Override + public List findByType(FormType type) { + return queryFactory + .selectFrom(form) + .where(eqType(type)) + .orderBy(form.examinationNumber.asc()) + .fetch(); + } + + @Override + public List findByCategory(FormType.Category category) { + List matchingFormTypes = getFormTypesByCategory(category); + + return queryFactory + .selectFrom(form) + .where(form.type.in(matchingFormTypes)) + .orderBy(form.examinationNumber.asc()) + .fetch(); + } + private BooleanExpression eqStatus(FormStatus status) { if (Objects.isNull(status)) { return null; @@ -38,6 +58,20 @@ private BooleanExpression eqStatus(FormStatus status) { return form.status.eq(status); } + private BooleanExpression eqType(FormType type) { + if (Objects.isNull(type)) { + return null; + } + + return form.type.eq(type); + } + + private List getFormTypesByCategory(FormType.Category category) { + return Stream.of(FormType.values()) + .filter(formType -> formType.categoryEquals(category)) + .toList(); + } + @Override public List findReceivedSpecialForm() { return queryFactory @@ -151,4 +185,63 @@ public List findFormUrlByFormIdList(List idList) { .orderBy(form.examinationNumber.asc()) .fetch(); } -} + + @Override + public List findTypeAndCountGroupByType() { + return queryFactory + .select(new QNumberOfApplicantsVo( + form.type, + form.count() + )) + .from(form) + .groupBy(form.type) + .fetch(); + } + + @Override + public List findGradeGroupByTypeAndStatus(List round) { + return queryFactory + .select(new QGradeVo( + form.type.stringValue(), + form.score.firstRoundScore.max(), + form.score.firstRoundScore.min(), + form.score.firstRoundScore.avg(), + form.score.totalScore.max(), + form.score.totalScore.min(), + form.score.totalScore.avg() + )) + .from(form) + .where(form.status.in(round)) + .groupBy(form.type) + .fetch(); + } + + @Override + public List findSchoolByAddress(List round, String keyword) { + return queryFactory + .select(new QSchoolStatusVo( + form.applicant.name, + form.education.school.name, + form.education.school.address + )) + .from(form) + .where(form.education.school.address.contains(keyword) + .or(form.education.school.location.eq(keyword)) + .and(form.status.in(round))) + .fetch(); + } + + @Override + public List findNotBusanSchool(List round) { + return queryFactory + .select(new QSchoolStatusVo( + form.applicant.name, + form.education.school.name, + form.education.school.address + )) + .from(form) + .where(form.education.school.location.eq("부산광역시").not() + .and(form.status.in(round))) + .fetch(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java new file mode 100644 index 00000000..5f531beb --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java @@ -0,0 +1,26 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class GradeVo { + private String type; + private Double firstRoundMax; + private Double firstRoundMin; + private Double firstRoundAvg; + private Double totalMax; + private Double totalMin; + private Double totalAvg; + + @QueryProjection + public GradeVo(String type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { + this.type = type; + this.firstRoundMax = firstRoundMax; + this.firstRoundMin = firstRoundMin; + this.firstRoundAvg = firstRoundAvg; + this.totalMax = totalMax; + this.totalMin = totalMin; + this.totalAvg = totalAvg; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java new file mode 100644 index 00000000..8f9c080c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class NumberOfApplicantsVo { + private FormType type; + private Long count; + + @QueryProjection + public NumberOfApplicantsVo(FormType type, Long count) { + this.type = type; + this.count = count; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java new file mode 100644 index 00000000..4350ba73 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java @@ -0,0 +1,18 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class SchoolStatusVo { + private String applicantName; + private String schoolName; + private String schoolAddress; + + @QueryProjection + public SchoolStatusVo(String applicantName, String schoolName, String schoolAddress) { + this.applicantName = applicantName; + this.schoolName = schoolName; + this.schoolAddress = schoolAddress; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java new file mode 100644 index 00000000..e696ef8c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java @@ -0,0 +1,73 @@ +package com.bamdoliro.maru.presentation.analysis; + +import com.bamdoliro.maru.application.analysis.QueryGenderRatioUseCase; +import com.bamdoliro.maru.application.analysis.QueryNumberOfApplicantsUseCase; +import com.bamdoliro.maru.application.analysis.QueryGradeDistributionUseCase; +import com.bamdoliro.maru.application.analysis.QuerySchoolStatusUseCase; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; +import com.bamdoliro.maru.shared.auth.AuthenticationPrincipal; +import com.bamdoliro.maru.shared.auth.Authority; +import com.bamdoliro.maru.shared.response.CommonResponse; +import com.bamdoliro.maru.shared.response.ListCommonResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RequestMapping("/analysis") +@RestController +public class AnalysisController { + private final QueryNumberOfApplicantsUseCase queryNumberOfApplicantsUseCase; + private final QueryGradeDistributionUseCase queryGradeDistributionUseCase; + private final QueryGenderRatioUseCase queryGenderRatioUseCase; + private final QuerySchoolStatusUseCase querySchoolStatusUseCase; + + @GetMapping("/number-of-applicants") + public ListCommonResponse getNumberOfApplicants( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user + ) { + return CommonResponse.ok( + queryNumberOfApplicantsUseCase.execute() + ); + } + + @GetMapping("/grade-distribution") + public ListCommonResponse getGradeDistribution( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid GradeDistributionRequest request + ) { + return CommonResponse.ok( + queryGradeDistributionUseCase.execute(request) + ); + } + + @GetMapping("/gender-ratio") + public ListCommonResponse getGenderRatio( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid GenderRatioRequest request + ) { + return CommonResponse.ok( + queryGenderRatioUseCase.execute(request) + ); + } + + @GetMapping("/school-status") + public ListCommonResponse getSchoolStatus( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid SchoolStatusRequest request + ) { + return CommonResponse.ok( + querySchoolStatusUseCase.execute(request) + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java new file mode 100644 index 00000000..c46a0da5 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java @@ -0,0 +1,20 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.NumberOfApplicantsVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class NumberOfApplicantsResponse { + private FormType type; + private Long count; + + public NumberOfApplicantsResponse(NumberOfApplicantsVo vo){ + this.type = vo.getType(); + this.count = vo.getCount(); + } +} \ No newline at end of file From 1b7d7e38d20d67e92f6de6a353a87c76bfedb4ad Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:00:13 +0900 Subject: [PATCH 28/59] =?UTF-8?q?feat(#79):=20=EC=84=B1=EC=A0=81=20?= =?UTF-8?q?=EB=B6=84=ED=8F=AC=20=EC=A1=B0=ED=9A=8C=20-=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84=ED=98=95=EB=B3=84=20?= =?UTF-8?q?=ED=95=99=EC=83=9D=EB=93=A4=EC=9D=98=20=EC=B5=9C=EA=B3=A0?= =?UTF-8?q?=EC=A0=90,=20=EC=B5=9C=ED=95=98=EC=A0=90,=20=ED=8F=89=EA=B7=A0?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryGradeDistributionUseCase.java | 22 ++++++++++++++ .../dto/request/GradeDistributionRequest.java | 17 +++++++++++ .../response/GradeDistributionResponse.java | 29 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java new file mode 100644 index 00000000..1bbd45e8 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -0,0 +1,22 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@UseCase +public class QueryGradeDistributionUseCase { + private final FormRepository formRepository; + + public List execute(GradeDistributionRequest request) { + return formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) + .stream() + .map(GradeDistributionResponse::new) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java new file mode 100644 index 00000000..f2828ead --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GradeDistributionRequest { + @NotNull(message = "필수값입니다.") + List statusList; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java new file mode 100644 index 00000000..c4f6d534 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java @@ -0,0 +1,29 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GradeDistributionResponse { + private String type; + private Double firstRoundMax; + private Double firstRoundMin; + private Double firstRoundAvg; + private Double totalMax; + private Double totalMin; + private Double totalAvg; + + public GradeDistributionResponse(GradeVo vo) { + this.type = vo.getType(); + this.firstRoundMax = vo.getFirstRoundMax(); + this.firstRoundMin = vo.getFirstRoundMin(); + this.firstRoundAvg = vo.getFirstRoundAvg(); + this.totalMax = vo.getTotalMax(); + this.totalMin = vo.getTotalMin(); + this.totalAvg = vo.getTotalAvg(); + } +} \ No newline at end of file From a9b897c02137f16af69af9a88fee0ab82b62667e Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:01:29 +0900 Subject: [PATCH 29/59] =?UTF-8?q?feat(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=84=B1=EB=B9=84=20=EB=B6=84=EC=84=9D=20-=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84=ED=98=95=EB=B3=84=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=EB=93=A4=EC=9D=98=20=EC=84=B1?= =?UTF-8?q?=EB=B3=84=EB=B6=84=ED=8F=AC=EB=A5=BC=20=ED=8C=8C=EC=95=85?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=9E=88=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 71 +++++++++++++++++++ .../dto/request/GenderRatioRequest.java | 21 ++++++ .../dto/response/GenderRatioResponse.java | 17 +++++ 3 files changed, 109 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java new file mode 100644 index 00000000..e71a24e2 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -0,0 +1,71 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.Form; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.domain.form.domain.type.Gender; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@UseCase +public class QueryGenderRatioUseCase { + private final FormRepository formRepository; + + public List execute(GenderRatioRequest request) { + List result = new ArrayList<>(); + + List subCategories = new ArrayList<>(); + + if (request.getMainCategory().equals(FormType.Category.REGULAR)) + subCategories.add(FormType.Category.REGULAR); + else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) + subCategories.addAll(List.of(FormType.Category.EQUAL_OPPORTUNITY, FormType.Category.SOCIETY_DIVERSITY)); + else subCategories.add(FormType.Category.SUPERNUMERARY); + + Map> formLists = subCategories.stream() + .collect(Collectors.toMap( + category -> category, + category -> formRepository.findByCategory(category).stream() + .filter(form -> request.getStatusList().contains(form.getStatus())) + .collect(Collectors.toList()) + )); + + for(Map.Entry> entry : formLists.entrySet()) { + FormType.Category category = entry.getKey(); + List formList = entry.getValue(); + + long busanMale = formList.stream().filter(this::isBusan).filter(this::isMale).count(); + long busanFeMale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); + long otherLocationMale = formList.stream().filter(this::isNotBusan).filter(this::isMale).count(); + long otherLocationFemale = formList.stream().filter(this::isNotBusan).filter(this::isFemale).count(); + + result.add(new GenderRatioResponse(category, busanMale, busanFeMale, otherLocationMale, otherLocationFemale)); + } + + return result; + } + + private boolean isBusan(Form form) { + return form.getEducation().getSchool().isBusan(); + } + + private boolean isNotBusan(Form form) { + return !isBusan(form); + } + + private boolean isMale(Form form) { + return form.getApplicant().getGender().equals(Gender.MALE); + } + + private boolean isFemale(Form form) { + return !isMale(form); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java new file mode 100644 index 00000000..6779ea6c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java @@ -0,0 +1,21 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GenderRatioRequest { + @NotNull(message = "필수값입니다.") + private List statusList; + + @NotNull(message = "필수값입니다.") + private FormType.Category mainCategory; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java new file mode 100644 index 00000000..152143c1 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GenderRatioResponse { + private FormType.Category category; + private long busanMale; + private long busanFemale; + private long otherLocationMale; + private long otherLocationFemale; +} \ No newline at end of file From 8b8064cabaa40280dec3c2e77b6e692873a44e49 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:02:25 +0900 Subject: [PATCH 30/59] =?UTF-8?q?feat(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=B6=9C=EC=8B=A0=20=ED=95=99=EA=B5=90=20=ED=98=84=ED=99=A9?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20-=20=EC=96=B4=EB=93=9C=EB=AF=BC?= =?UTF-8?q?=EC=9D=B4=20=EC=A7=80=EC=9B=90=EC=9E=90=EB=93=A4=EC=9D=98=20?= =?UTF-8?q?=EC=B6=9C=EC=8B=A0=20=ED=95=99=EA=B5=90=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QuerySchoolStatusUseCase.java | 33 +++++++++++++++++++ .../dto/request/SchoolStatusRequest.java | 25 ++++++++++++++ .../dto/response/SchoolStatusResponse.java | 21 ++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java new file mode 100644 index 00000000..883b31d9 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java @@ -0,0 +1,33 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@UseCase +public class QuerySchoolStatusUseCase { + + private final FormRepository formRepository; + + public List execute(SchoolStatusRequest request) { + if (request.getIsBusan()) { + String keyword = "부산광역시"; + keyword += request.getGu() == null ? "" : (" " + request.getGu()); + + return formRepository.findSchoolByAddress(request.getStatusList(), keyword) + .stream() + .map(SchoolStatusResponse::new) + .toList(); + } + + return formRepository.findNotBusanSchool(request.getStatusList()) + .stream() + .map(SchoolStatusResponse::new) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java new file mode 100644 index 00000000..be21084e --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java @@ -0,0 +1,25 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SchoolStatusRequest { + + @NotNull(message = "필수값입니다.") + private List statusList; + + @NotNull(message = "필수값입니다.") + private Boolean isBusan; + + @Nullable + private String gu; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java new file mode 100644 index 00000000..947081c7 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java @@ -0,0 +1,21 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.infrastructure.persistence.form.vo.SchoolStatusVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SchoolStatusResponse { + private String applicantName; + private String schoolName; + private String schoolAddress; + + public SchoolStatusResponse(SchoolStatusVo schoolStatusVo) { + this.applicantName = schoolStatusVo.getApplicantName(); + this.schoolName = schoolStatusVo.getSchoolName(); + this.schoolAddress = schoolStatusVo.getSchoolAddress(); + } +} \ No newline at end of file From 3ac51e4a67a5e8ab92e04675a3d028aa3e35998a Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:03:55 +0900 Subject: [PATCH 31/59] =?UTF-8?q?build:=20application.yml=20-=20debug=20-?= =?UTF-8?q?=20debug=20=EB=A1=9C=EA=B7=B8=EA=B0=80=20=EB=84=88=EB=AC=B4=20?= =?UTF-8?q?=EA=B8=B8=EC=96=B4=EC=84=9C=20=EB=B3=B4=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=98=B5=EC=85=98=EC=9D=84=20fal?= =?UTF-8?q?se=EB=A1=9C=20=EB=B0=94=EA=BF=A8=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1e425339..602c8e54 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -78,7 +78,7 @@ spring: activate: on-profile: dev -debug: true +debug: false --- spring: config: @@ -101,7 +101,7 @@ spring: port: 6379 password: bamdoliro -debug: true +debug: false --- spring: config: @@ -135,4 +135,4 @@ spring: port: 6379 password: bamdoliro -debug: true +debug: false From 1f34c4d95ae8e1d3c8f9e02856b98d636b9a092c Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Fri, 14 Jun 2024 23:24:06 +0900 Subject: [PATCH 32/59] =?UTF-8?q?fix(#79):=20=EC=9B=90=EC=84=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?-=20=EC=9B=90=EC=84=9C=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20schoolAd?= =?UTF-8?q?dress=EA=B0=80=20=EB=B3=B4=EC=9D=B4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=96=88=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/form/dto/response/EducationResponse.java | 2 ++ .../java/com/bamdoliro/maru/shared/fixture/FormFixture.java | 1 + 2 files changed, 3 insertions(+) diff --git a/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java b/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java index bb4191da..cbe2e1ca 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java @@ -14,6 +14,7 @@ public class EducationResponse { private String schoolName; private String schoolLocation; private String schoolCode; + private String schoolAddress; private String teacherName; private String teacherPhoneNumber; @@ -22,6 +23,7 @@ public EducationResponse(Education education) { this.graduationYear = education.getGraduationYear(); this.schoolName = education.getSchool().getName(); this.schoolLocation = education.getSchool().getLocation(); + this.schoolAddress = education.getSchool().getAddress(); this.schoolCode = education.getSchool().getCode(); this.teacherName = education.getTeacher().getName(); this.teacherPhoneNumber = education.getTeacher().getPhoneNumber().toString(); diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index ebba8427..c4bbb0da 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -465,6 +465,7 @@ public static FormResponse createFormResponse() { "비전중학교", "경기도", "7631003", + "경기도 용인시 비전구 비전로 1", "나교사", "0519701234" ), From 0cac965b9f07966ed9ff5f9ca8371b60e3cc254d Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 01:01:55 +0900 Subject: [PATCH 33/59] =?UTF-8?q?perf(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=84=B1=EC=A0=81=20=EB=B6=84=ED=8F=AC=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=200=EC=A0=90=20=ED=91=9C=EC=8B=9C=20-=20=EC=A7=80=EC=9B=90?= =?UTF-8?q?=EC=9E=90=20=EC=88=98=EA=B0=80=20=EC=97=86=EB=8A=94=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EC=9D=80=20=EC=84=B1=EC=A0=81=20=EB=B6=84=ED=8F=AC?= =?UTF-8?q?=EA=B0=80=20=EB=82=98=EC=98=A4=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EA=B2=83=EC=97=90=EC=84=9C=200=EC=9C=BC=EB=A1=9C=20=EB=82=98?= =?UTF-8?q?=EC=98=A4=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=ED=96=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryGradeDistributionUseCase.java | 19 ++++++++++++++++++- .../QueryNumberOfApplicantsUseCase.java | 4 +++- .../persistence/form/FormRepositoryImpl.java | 2 +- .../persistence/form/vo/GradeVo.java | 5 +++-- .../response/GradeDistributionResponse.java | 3 ++- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java index 1bbd45e8..4dedf217 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -1,5 +1,6 @@ package com.bamdoliro.maru.application.analysis; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; @@ -11,12 +12,28 @@ @RequiredArgsConstructor @UseCase public class QueryGradeDistributionUseCase { + private final FormRepository formRepository; public List execute(GradeDistributionRequest request) { - return formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) + List result = new java.util.ArrayList<>(formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) .stream() .map(GradeDistributionResponse::new) + .toList()); + + List existingTypes = result + .stream() + .map(GradeDistributionResponse::getType) .toList(); + +// System.out.println(existingTypes); + + for (FormType formType : FormType.values()) { + if (!existingTypes.contains(formType)) { + result.add(new GradeDistributionResponse(formType, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + } + } + + return result; } } \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java index 44d1c73c..0b5ff0f8 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java @@ -12,6 +12,7 @@ @RequiredArgsConstructor @UseCase public class QueryNumberOfApplicantsUseCase { + private final FormRepository formRepository; public List execute() { @@ -20,7 +21,8 @@ public List execute() { .map(NumberOfApplicantsResponse::new) .collect(Collectors.toList()); - List existingTypes = result.stream() + List existingTypes = result + .stream() .map(NumberOfApplicantsResponse::getType) .toList(); diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java index 36b65a7b..5a09b03f 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java @@ -202,7 +202,7 @@ public List findTypeAndCountGroupByType() { public List findGradeGroupByTypeAndStatus(List round) { return queryFactory .select(new QGradeVo( - form.type.stringValue(), + form.type, form.score.firstRoundScore.max(), form.score.firstRoundScore.min(), form.score.firstRoundScore.avg(), diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java index 5f531beb..41755097 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java @@ -1,11 +1,12 @@ package com.bamdoliro.maru.infrastructure.persistence.form.vo; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.querydsl.core.annotations.QueryProjection; import lombok.Getter; @Getter public class GradeVo { - private String type; + private FormType type; private Double firstRoundMax; private Double firstRoundMin; private Double firstRoundAvg; @@ -14,7 +15,7 @@ public class GradeVo { private Double totalAvg; @QueryProjection - public GradeVo(String type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { + public GradeVo(FormType type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { this.type = type; this.firstRoundMax = firstRoundMax; this.firstRoundMin = firstRoundMin; diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java index c4f6d534..7104a85d 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java @@ -1,5 +1,6 @@ package com.bamdoliro.maru.presentation.analysis.dto.response; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; import lombok.AllArgsConstructor; import lombok.Getter; @@ -9,7 +10,7 @@ @NoArgsConstructor @AllArgsConstructor public class GradeDistributionResponse { - private String type; + private FormType type; private Double firstRoundMax; private Double firstRoundMin; private Double firstRoundAvg; From 029d2d4869a2c7949b495c5c6b86599d327aa726 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 01:42:56 +0900 Subject: [PATCH 34/59] =?UTF-8?q?refactor(#79):=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/analysis/QueryGradeDistributionUseCase.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java index 4dedf217..21d2ecbb 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -26,8 +26,6 @@ public List execute(GradeDistributionRequest request) .map(GradeDistributionResponse::getType) .toList(); -// System.out.println(existingTypes); - for (FormType formType : FormType.values()) { if (!existingTypes.contains(formType)) { result.add(new GradeDistributionResponse(formType, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); From fa41bc5e7d10250b5a4271e3d4d5596a72a2d2f6 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:39:54 +0900 Subject: [PATCH 35/59] =?UTF-8?q?test(#79):=20AnalysisControllerTest=20-?= =?UTF-8?q?=20=EB=B6=84=EC=84=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/AnalysisControllerTest.java | 260 ++++++++++++++++++ .../maru/shared/fixture/AnalysisFixture.java | 82 ++++++ .../maru/shared/util/ControllerTest.java | 35 ++- .../maru/shared/util/RandomUtil.java | 4 + 4 files changed, 378 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java create mode 100644 src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java new file mode 100644 index 00000000..05040f4f --- /dev/null +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -0,0 +1,260 @@ +package com.bamdoliro.maru.presentation.analysis; + + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.shared.fixture.AnalysisFixture; +import com.bamdoliro.maru.shared.fixture.AuthFixture; +import com.bamdoliro.maru.shared.fixture.UserFixture; +import com.bamdoliro.maru.shared.util.RestDocsTestSupport; +import kotlinx.serialization.json.Json; +import org.junit.jupiter.api.Test; +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import java.util.List; +import java.util.Optional; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class AnalysisControllerTest extends RestDocsTestSupport { + + @Test + void 전형별_지원자수를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + given(queryNumberOfApplicantsUseCase.execute()).willReturn(AnalysisFixture.createNumberOfApplicantsResponse()); + + mockMvc.perform(get("/analysis/number-of-applicants") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders(headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ) + )); + } + + @Test + void _1차_합격자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + )); + System.out.println(AnalysisFixture.createGradeDistributionResponse()); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void _2차_전형자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.FAILED, + FormStatus.PASSED + )); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void 최종_합격자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.PASSED + )); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void 전형별_성비를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GenderRatioRequest request = new GenderRatioRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + FormType.Category.REGULAR); + given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse(FormType.Category.REGULAR)); + + mockMvc.perform(get("/analysis/gender-ratio") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("mainCategory").type(JsonFieldType.STRING).description("메인 카테고리(FormType.Category 참고)") + ) + )); + } + + @Test + void 부산_특정구_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + true, + "사상구"); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } + + @Test + void 부산_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + true, + null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } + + @Test + void 타지역_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + false, + null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } +} \ No newline at end of file diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java new file mode 100644 index 00000000..a3b14774 --- /dev/null +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -0,0 +1,82 @@ +package com.bamdoliro.maru.shared.fixture; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; +import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; + +public class AnalysisFixture { + + public static List createNumberOfApplicantsResponse() { + List responseList = new ArrayList<>(); + for (FormType formType : FormType.values()) { + responseList.add(new NumberOfApplicantsResponse(formType, (long)randomNumber(0, 50))); + } + return responseList; + } + + public static List createGradeDistributionResponse() { + List responseList = new ArrayList<>(); + for (FormType formType : FormType.values()) { + responseList.add(new GradeDistributionResponse(formType, randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0))); + } + return responseList; + } + + public static List createGenderRatioResponse(FormType.Category mainCategory) { + return List.of( + new GenderRatioResponse( + FormType.Category.REGULAR, + randomNumber(0, 30), + randomNumber(0, 15), + randomNumber(0, 30), + randomNumber(0, 15) + ) + ); + } + + public static List createSchoolStatusResponse(Boolean isBusan, String gu) { + if (isBusan) { + if (gu == null) { + return List.of( + new SchoolStatusResponse( + "김밤돌", + "신라중학교", + "부산광역시 사상구 백양대로700번길 35-8" + ), + new SchoolStatusResponse( + "김이로", + "성동중학교", + "부산광역시 남구 남동천로 38" + ), + new SchoolStatusResponse( + "금곰돌", + "가락중학교", + "부산광역시 강서구 가락대로 1405") + ); + } + return List.of( + new SchoolStatusResponse( + "김밤돌", + "신라중학교", + "부산광역시 사상구 백양대로700번길 35-8" + ) + ); + } + return List.of( + new SchoolStatusResponse( + "김밤돌", + "비전중학교", + "경기도 용인시 비전구 비전로 1" + ) + ); + } +} diff --git a/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java b/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java index 96bea802..19f1359c 100644 --- a/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java @@ -1,5 +1,9 @@ package com.bamdoliro.maru.shared.util; +import com.bamdoliro.maru.application.analysis.QueryGenderRatioUseCase; +import com.bamdoliro.maru.application.analysis.QueryGradeDistributionUseCase; +import com.bamdoliro.maru.application.analysis.QueryNumberOfApplicantsUseCase; +import com.bamdoliro.maru.application.analysis.QuerySchoolStatusUseCase; import com.bamdoliro.maru.application.auth.LogInUseCase; import com.bamdoliro.maru.application.auth.LogOutUseCase; import com.bamdoliro.maru.application.auth.RefreshTokenUseCase; @@ -53,6 +57,7 @@ import com.bamdoliro.maru.domain.auth.service.TokenService; import com.bamdoliro.maru.infrastructure.message.SendMessageService; import com.bamdoliro.maru.infrastructure.neis.SearchSchoolService; +import com.bamdoliro.maru.presentation.analysis.AnalysisController; import com.bamdoliro.maru.presentation.auth.AuthController; import com.bamdoliro.maru.presentation.fair.FairController; import com.bamdoliro.maru.presentation.form.DraftFormController; @@ -75,7 +80,17 @@ import org.springframework.test.web.servlet.MockMvc; @Disabled -@WebMvcTest({UserController.class, AuthController.class, SharedController.class, SchoolController.class, QuestionController.class, FormController.class, NoticeController.class, DraftFormController.class, FairController.class, MessageController.class}) +@WebMvcTest({UserController.class, + AuthController.class, + SharedController.class, + SchoolController.class, + QuestionController.class, + FormController.class, + NoticeController.class, + DraftFormController.class, + FairController.class, + MessageController.class, + AnalysisController.class}) public abstract class ControllerTest { @Autowired @@ -232,6 +247,22 @@ public abstract class ControllerTest { @MockBean protected QueryFormUrlUseCase queryFormUrlUseCase; + @MockBean + protected SendMessageUseCase sendMessageUseCase; + + @MockBean + protected QueryNumberOfApplicantsUseCase queryNumberOfApplicantsUseCase; + + @MockBean + protected QueryGradeDistributionUseCase queryGradeDistributionUseCase; + + @MockBean + protected QueryGenderRatioUseCase queryGenderRatioUseCase; + + @MockBean + protected QuerySchoolStatusUseCase querySchoolStatusUseCase; + + @MockBean protected TokenService tokenService; @@ -241,8 +272,6 @@ public abstract class ControllerTest { @MockBean protected SendMessageService sendMessageService; - @MockBean - protected SendMessageUseCase sendMessageUseCase; @MockBean protected JwtProperties jwtProperties; diff --git a/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java b/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java index c1ab939c..76e39edc 100644 --- a/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java +++ b/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java @@ -9,4 +9,8 @@ public static String randomPhoneNumber() { public static int randomNumber(int min, int max) { return (int) ((Math.random() * (max - min)) + min); } + + public static double randomDouble(double min, double max) { + return Math.round(((Math.random() * (max - min)) + min) * 1000.0) / 1000.0; + } } From 51ebfe36e7aaf3f9bf92e5176d590a36ebd033a7 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:40:22 +0900 Subject: [PATCH 36/59] =?UTF-8?q?docs(#79):=20analysis.adoc=20-=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/analysis.adoc | 92 +++++++++++++++++++++++++++++++++ src/docs/asciidoc/index.adoc | 2 + 2 files changed, 94 insertions(+) create mode 100644 src/docs/asciidoc/analysis.adoc diff --git a/src/docs/asciidoc/analysis.adoc b/src/docs/asciidoc/analysis.adoc new file mode 100644 index 00000000..8354f760 --- /dev/null +++ b/src/docs/asciidoc/analysis.adoc @@ -0,0 +1,92 @@ +== 분석 Analysis + +=== 전형별 지원자 수 조회 +전형별 지원자들의 수를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/request-headers.adoc[] + +==== 요청 +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/http-request.adoc[] + +==== 응답 +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/http-response.adoc[] + +=== 전형별 성적 분포 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 전형별 성적 분포를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-fields.adoc[] + +==== 요청 + +===== 1차 합격자 +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/http-request.adoc[] + +===== 2차 전형자 +include::{snippets}/analysis-controller-test/_2차_전형자들의_성적_분포를_조회한다/http-request.adoc[] + +===== 최종 합격자 +include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분포를_조회한다/http-request.adoc[] + +==== 응답 + +===== 정상 응답 +include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분포를_조회한다/http-response.adoc[] + +=== 전형별 성비 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 전형별, 지역별 성비를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-fields.adoc[] + +==== 요청 +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-request.adoc[] + +==== 응답 + +===== 정상 응답 +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-response.adoc[] + +=== 전형별 출신학교 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 출신학교를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-fields.adoc[] + +==== 요청 +===== 부산 특정구 출신 +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 부산 출신 +include::{snippets}/analysis-controller-test/부산_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 타지역 출신 +include::{snippets}/analysis-controller-test/타지역_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 응답 +==== 부산 특정구 출신 정상 응답 +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] + +==== 부산 출신 정상 응답 +include::{snippets}/analysis-controller-test/부산_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] + +==== 타지역 출신 정상 응답 +include::{snippets}/analysis-controller-test/타지역_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 4a46528e..d64e5a35 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -27,4 +27,6 @@ include::fair.adoc[] include::message.adoc[] +include::analysis.adoc[] + include::enum.adoc[] From a07f6826a3c6c5d0606c912476f63e8cadb7b80c Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:41:28 +0900 Subject: [PATCH 37/59] =?UTF-8?q?refactor(#79):=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/analysis/AnalysisControllerTest.java | 2 -- .../java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java | 1 - 2 files changed, 3 deletions(-) diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java index 05040f4f..ba782869 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -11,7 +11,6 @@ import com.bamdoliro.maru.shared.fixture.AuthFixture; import com.bamdoliro.maru.shared.fixture.UserFixture; import com.bamdoliro.maru.shared.util.RestDocsTestSupport; -import kotlinx.serialization.json.Json; import org.junit.jupiter.api.Test; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; @@ -19,7 +18,6 @@ import org.springframework.restdocs.payload.JsonFieldType; import java.util.List; -import java.util.Optional; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index a3b14774..a405d6b6 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; From d3ab871d3c9c21fefe02da7279f6576dc211f390 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 23:24:48 +0900 Subject: [PATCH 38/59] =?UTF-8?q?fix(#79):=20SchoolResponse=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20=ED=95=99=EA=B5=90=EB=A5=BC=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=ED=95=A0=20=EB=95=8C=20=ED=95=99=EA=B5=90=EC=9D=98=20?= =?UTF-8?q?=EB=8F=84=EB=A1=9C=EB=AA=85=20=EC=A3=BC=EC=86=8C=EA=B0=80=20?= =?UTF-8?q?=ED=95=A8=EA=BB=98=20=EB=82=98=EC=98=A4=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../neis/SearchSchoolService.java | 1 + .../school/dto/response/SchoolResponse.java | 1 + .../maru/shared/fixture/AnalysisFixture.java | 2 +- .../maru/shared/fixture/FormFixture.java | 16 ++++----- .../maru/shared/fixture/SchoolFixture.java | 34 +++++++++---------- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java b/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java index 1bf2cf34..19acfd86 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java @@ -27,6 +27,7 @@ public List execute(String q) throws JsonProcessingException { .map(s -> SchoolResponse.builder() .name(s.getSchoolName()) .location(s.getLocation()) + .address((s.getAddress())) .code(s.getStandardSchoolCode()) .build()) .toList(); diff --git a/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java b/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java index b9846bfc..0bbf9120 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java @@ -11,5 +11,6 @@ public class SchoolResponse { private String name; private String location; + private String address; private String code; } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index a405d6b6..4c439e51 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -74,7 +74,7 @@ public static List createSchoolStatusResponse(Boolean isBu new SchoolStatusResponse( "김밤돌", "비전중학교", - "경기도 용인시 비전구 비전로 1" + "경기도 비전시 비전구 비전로 1" ) ); } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index c4bbb0da..356af708 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -74,7 +74,7 @@ public static Form createForm(FormType type) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -140,7 +140,7 @@ public static Form createRandomForm(User user) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -218,7 +218,7 @@ public static Form createRandomQualificationExaminationForm(User user) { new Education( GraduationType.QUALIFICATION_EXAMINATION, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), null ), new Grade( @@ -289,7 +289,7 @@ public static Form createQualificationExaminationForm(FormType type) { new School( "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003" ), null @@ -329,7 +329,7 @@ public static SubmitFormRequest createFormRequest(FormType type) { "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -371,7 +371,7 @@ public static SubmitFormRequest createQualificationExaminationFormRequest(FormTy "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", null, null, @@ -407,7 +407,7 @@ public static UpdateFormRequest createUpdateFormRequest(FormType type) { "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -465,7 +465,7 @@ public static FormResponse createFormResponse() { "비전중학교", "경기도", "7631003", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "나교사", "0519701234" ), diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java index 46d468ea..f329dc87 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java @@ -8,22 +8,22 @@ public class SchoolFixture { public static List createSchoolListResponse() { return List.of( - new SchoolResponse("부산소프트웨어마이스터고등학교", "부산광역시", "7150658") - ); - } + new SchoolResponse("부산소프트웨어마이스터고등학교", "부산광역시", "부산광역시 강서구 가락대로 1393", "7150658") +); +} - public static List createSchoolMaxListResponse() { - return List.of( - new SchoolResponse("비전고등학교", "경기도", "7531109"), - new SchoolResponse("비전중학교", "경기도", "7631003"), - new SchoolResponse("비전초등학교", "경기도", "7631034"), - new SchoolResponse("공동체비전고등학교", "충청남도", "8140222"), - new SchoolResponse("다른비전고등학교", "경상북도", "7531109"), - new SchoolResponse("다른비전중학교", "경기도", "7631003"), - new SchoolResponse("다른비전초등학교", "경상남도", "7631034"), - new SchoolResponse("다른공동체비전고등학교", "충청남도", "8140222"), - new SchoolResponse("또다른비전고등학교", "대구광역시", "7531109"), - new SchoolResponse("또다른비전중학교", "경기도", "7631003") - ); - } +public static List createSchoolMaxListResponse() { +return List.of( +new SchoolResponse("비전고등학교", "경기도", "경기도 비전시 비전구 비전로 2", "7531109"), +new SchoolResponse("비전중학교", "경기도","경기도 비전시 비전구 비전로 1", "7631003"), +new SchoolResponse("비전초등학교", "경기도", "경기도 비전시 비전구 비전로 3", "7631034"), +new SchoolResponse("공동체비전고등학교", "충청남도", "충청남도 비전시 비전구 비전로 1", "8140222"), +new SchoolResponse("다른비전고등학교", "경상북도", "경상북도 비전시 비전구 비전로 1", "7531109"), +new SchoolResponse("다른비전중학교", "경기도", "경기도 비전시 비전구 비전로 4", "7631003"), +new SchoolResponse("다른비전초등학교", "경상남도", "경상남도 비전시 비전구 비전로 1", "7631034"), +new SchoolResponse("다른공동체비전고등학교", "충청남도", "충청남도 비전시 비전구 비전로 2", "8140222"), +new SchoolResponse("또다른비전고등학교", "대구광역시", "대구광역시 비전구 비전로 1", "7531109"), +new SchoolResponse("또다른비전중학교", "경기도", "경기도 비전시 비전구 비전로 5", "7631003") +); +} } From 4706e8205f824b985ceef1d542649ca5e657004e Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Wed, 19 Jun 2024 03:52:03 +0900 Subject: [PATCH 39/59] =?UTF-8?q?refactor(#79):=20Parameter=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20-=20HTTP=20GET=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=8A=94=20RequestBody=EB=A5=BC=20=EA=B6=8C?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=EB=8B=A4?= =?UTF-8?q?=EB=8A=94=EA=B2=83=EC=9D=84=20=EC=95=8C=EC=95=84=EC=84=9C=20Par?= =?UTF-8?q?ameter=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.=20-=20@ModelAttr?= =?UTF-8?q?ibute=EC=9D=98=20=EC=9E=91=EB=8F=99=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9D=B4=20Setter=EB=A5=BC=20=EC=9D=B4=EC=9A=A9=ED=95=B4=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20=EC=A3=BC=EC=9E=85=ED=95=98=EB=8A=94?= =?UTF-8?q?=EA=B2=83=EC=9D=B4=EC=96=B4=EC=84=9C=20request=20dto=EC=97=90?= =?UTF-8?q?=20setter=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=96=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/analysis.adoc | 12 +- .../analysis/AnalysisController.java | 11 +- .../dto/request/GenderRatioRequest.java | 2 + .../dto/request/GradeDistributionRequest.java | 3 + .../dto/request/SchoolStatusRequest.java | 2 + .../analysis/AnalysisControllerTest.java | 179 +++++++++--------- .../maru/shared/fixture/AnalysisFixture.java | 7 +- 7 files changed, 114 insertions(+), 102 deletions(-) diff --git a/src/docs/asciidoc/analysis.adoc b/src/docs/asciidoc/analysis.adoc index 8354f760..f591d69f 100644 --- a/src/docs/asciidoc/analysis.adoc +++ b/src/docs/asciidoc/analysis.adoc @@ -22,8 +22,8 @@ include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한 ==== Request Header include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/query-parameters.adoc[] ==== 요청 @@ -49,8 +49,8 @@ include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분 ==== Request Header include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/query-parameters.adoc[] ==== 요청 include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-request.adoc[] @@ -68,8 +68,8 @@ include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/ht ==== Request Header include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/query-parameters.adoc[] ==== 요청 ===== 부산 특정구 출신 diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java index e696ef8c..b5305f49 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java @@ -18,10 +18,7 @@ import com.bamdoliro.maru.shared.response.ListCommonResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor @RequestMapping("/analysis") @@ -44,7 +41,7 @@ public ListCommonResponse getNumberOfApplicants( @GetMapping("/grade-distribution") public ListCommonResponse getGradeDistribution( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid GradeDistributionRequest request + @ModelAttribute @Valid GradeDistributionRequest request ) { return CommonResponse.ok( queryGradeDistributionUseCase.execute(request) @@ -54,7 +51,7 @@ public ListCommonResponse getGradeDistribution( @GetMapping("/gender-ratio") public ListCommonResponse getGenderRatio( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid GenderRatioRequest request + @ModelAttribute @Valid GenderRatioRequest request ) { return CommonResponse.ok( queryGenderRatioUseCase.execute(request) @@ -64,7 +61,7 @@ public ListCommonResponse getGenderRatio( @GetMapping("/school-status") public ListCommonResponse getSchoolStatus( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid SchoolStatusRequest request + @ModelAttribute @Valid SchoolStatusRequest request ) { return CommonResponse.ok( querySchoolStatusUseCase.execute(request) diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java index 6779ea6c..e4af7ffa 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java @@ -6,10 +6,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class GenderRatioRequest { diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java index f2828ead..beb0333e 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java @@ -5,13 +5,16 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class GradeDistributionRequest { + @NotNull(message = "필수값입니다.") List statusList; } \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java index be21084e..b1137393 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java @@ -6,10 +6,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class SchoolStatusRequest { diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java index ba782869..36dc3583 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -1,7 +1,6 @@ package com.bamdoliro.maru.presentation.analysis; -import com.bamdoliro.maru.domain.form.domain.type.FormStatus; import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.domain.user.domain.User; import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; @@ -15,16 +14,18 @@ import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import java.util.List; +import java.util.Objects; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -43,7 +44,8 @@ class AnalysisControllerTest extends RestDocsTestSupport { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(restDocs.document( - requestHeaders(headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ) )); } @@ -53,26 +55,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - )); - System.out.println(AnalysisFixture.createGradeDistributionResponse()); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "FIRST_PASSED", "FAILED", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -82,24 +81,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.FAILED, - FormStatus.PASSED - )); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "FAILED", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -109,23 +107,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.PASSED - )); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -135,27 +133,30 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GenderRatioRequest request = new GenderRatioRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - FormType.Category.REGULAR); - given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse(FormType.Category.REGULAR)); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("mainCategory", "REGULAR"); + given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse( + FormType.Category.valueOf(Objects.requireNonNull(multiValueMap.get("mainCategory")).get(0)) + )); mockMvc.perform(get("/analysis/gender-ratio") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("mainCategory").type(JsonFieldType.STRING).description("메인 카테고리(FormType.Category 참고)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("mainCategory") + .description("메인 카테고리(FormType.Category 참고)") ) )); } @@ -165,29 +166,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - true, - "사상구"); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "true"); + multiValueMap.add("gu", "사상구"); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") - .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .params(multiValueMap) + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } @@ -197,29 +200,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - true, - null); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "true"); + multiValueMap.add("gu", null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } @@ -229,29 +234,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - false, - null); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "false"); + multiValueMap.add("gu", null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index 4c439e51..66c9748c 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; @@ -42,9 +43,9 @@ public static List createGenderRatioResponse(FormType.Categ ); } - public static List createSchoolStatusResponse(Boolean isBusan, String gu) { - if (isBusan) { - if (gu == null) { + public static List createSchoolStatusResponse(List isBusan, List gu) { + if (Objects.equals(isBusan.get(0), "true")) { + if (gu.get(0) == null) { return List.of( new SchoolStatusResponse( "김밤돌", From 808cbe55dd7f7a47edab204273786008acab1fa2 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 20 Jun 2024 13:15:51 +0900 Subject: [PATCH 40/59] =?UTF-8?q?fix(#79):=20=EC=84=B1=EB=B9=84=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?-=20=ED=8A=B9=EB=B3=84=20=EC=A0=84=ED=98=95=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=ED=96=88=EC=9D=84=20=EB=95=8C=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=ED=84=B0=20=EC=9D=B8=EC=9E=AC=EC=A0=84?= =?UTF-8?q?=ED=98=95=EA=B3=BC=20=EC=A0=95=EC=9B=90=20=EC=99=B8=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EC=9D=B4=20=EB=82=98=EC=98=A4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4=20-=20=ED=8A=B9=EB=A1=80?= =?UTF-8?q?=EC=9E=85=ED=95=99=20=EB=8C=80=EC=83=81=EC=9E=90=EB=A5=BC=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=96=88=EC=9D=84=20=EB=95=8C=20=ED=8A=B9?= =?UTF-8?q?=EB=B3=84=EC=A0=84=ED=98=95=EC=9D=98=20=EC=A0=95=EC=9B=90=20?= =?UTF-8?q?=EC=99=B8=20=EC=A0=84=ED=98=95=EC=9D=B4=20=EB=82=98=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.=20=EA=B5=AD=EA=B0=80?= =?UTF-8?q?=EB=B3=B4=ED=9B=88=EC=9E=90=EB=85=80=EC=99=80=20=ED=8A=B9?= =?UTF-8?q?=EB=A1=80=EC=9E=85=ED=95=99=EC=9D=B4=20=EB=98=91=EA=B0=99?= =?UTF-8?q?=EC=9D=B4=20=EC=A0=95=EC=9B=90=20=EC=99=B8=20=EC=A0=84=ED=98=95?= =?UTF-8?q?=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=A7=8C=20=EC=9E=88?= =?UTF-8?q?=EA=B3=A0=20=EA=B5=AD=EA=B0=80=EB=B3=B4=ED=9B=88=EC=9E=90?= =?UTF-8?q?=EB=85=80=EA=B0=80=20=ED=8A=B9=EB=B3=84=20=EC=A0=84=ED=98=95=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EC=97=90=20=EB=93=A4?= =?UTF-8?q?=EC=96=B4=EC=9E=88=EC=A7=80=20=EC=95=8A=EC=95=84=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EC=A2=80=20=EB=8D=94=EB=9F=AC=EC=9B=8C?= =?UTF-8?q?=EC=A1=8C=EC=8A=B5=EB=8B=88=EB=8B=A4...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 19 ++++++++++++------- .../shared/response/EnumControllerTest.java | 2 +- .../shared/response/SharedController.java | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java index e71a24e2..5af89d3f 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -20,15 +20,14 @@ public class QueryGenderRatioUseCase { private final FormRepository formRepository; public List execute(GenderRatioRequest request) { + FormType.Category mainCategory = request.getMainCategory(); List result = new ArrayList<>(); - List subCategories = new ArrayList<>(); - if (request.getMainCategory().equals(FormType.Category.REGULAR)) + if (mainCategory.equals(FormType.Category.REGULAR)) subCategories.add(FormType.Category.REGULAR); - else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) - subCategories.addAll(List.of(FormType.Category.EQUAL_OPPORTUNITY, FormType.Category.SOCIETY_DIVERSITY)); - else subCategories.add(FormType.Category.SUPERNUMERARY); + else if (mainCategory.equals(FormType.Category.SPECIAL)) + subCategories.addAll(List.of(FormType.Category.MEISTER_TALENT, FormType.Category.SOCIAL_INTEGRATION)); Map> formLists = subCategories.stream() .collect(Collectors.toMap( @@ -38,16 +37,22 @@ else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) .collect(Collectors.toList()) )); + if (mainCategory.equals(FormType.Category.SPECIAL)) { + formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.NATIONAL_VETERANS_EDUCATION)); + } else if(mainCategory.equals(FormType.Category.SUPERNUMERARY)) { + formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.SPECIAL_ADMISSION)); + } + for(Map.Entry> entry : formLists.entrySet()) { FormType.Category category = entry.getKey(); List formList = entry.getValue(); long busanMale = formList.stream().filter(this::isBusan).filter(this::isMale).count(); - long busanFeMale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); + long busanFemale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); long otherLocationMale = formList.stream().filter(this::isNotBusan).filter(this::isMale).count(); long otherLocationFemale = formList.stream().filter(this::isNotBusan).filter(this::isFemale).count(); - result.add(new GenderRatioResponse(category, busanMale, busanFeMale, otherLocationMale, otherLocationFemale)); + result.add(new GenderRatioResponse(category, busanMale, busanFemale, otherLocationMale, otherLocationFemale)); } return result; diff --git a/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java b/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java index 2a383d01..56c80893 100644 --- a/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java @@ -63,7 +63,7 @@ void enums() throws Exception { ), customResponseFields("custom-response", beneathPath("gender").withSubsectionId("gender"), - attributes(key("title").value("GraduationType")), + attributes(key("title").value("Gender")), enumConvertFieldDescriptor((enumDocs.getGender())) ), customResponseFields("custom-response", diff --git a/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java b/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java index b3459002..f2d7d2b0 100644 --- a/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java +++ b/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java @@ -36,7 +36,7 @@ public EnumDocs findEnums() { .certificate(getDocs(Certificate.values())) .formStatus(getDocs(FormStatus.values())) .formType(getDocs(FormType.values())) - .gender(getDocs(GraduationType.values())) + .gender(getDocs(Gender.values())) .graduationType(getDocs(GraduationType.values())) .fairStatus(getDocs(FairStatus.values())) .fairType(getDocs(FairType.values())) From 5aadebd9ed812270db00dba9dca09937be8e60c8 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 20 Jun 2024 23:08:34 +0900 Subject: [PATCH 41/59] =?UTF-8?q?perf(#79):=20=EC=A0=95=EC=9B=90=20?= =?UTF-8?q?=EC=99=B8=20=EC=A0=84=ED=98=95=20=EC=A1=B0=ED=9A=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 14 +++++++------- .../maru/domain/form/domain/type/FormType.java | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java index 5af89d3f..008260e8 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -27,7 +27,13 @@ public List execute(GenderRatioRequest request) { if (mainCategory.equals(FormType.Category.REGULAR)) subCategories.add(FormType.Category.REGULAR); else if (mainCategory.equals(FormType.Category.SPECIAL)) - subCategories.addAll(List.of(FormType.Category.MEISTER_TALENT, FormType.Category.SOCIAL_INTEGRATION)); + subCategories.addAll(List.of( + FormType.Category.MEISTER_TALENT, + FormType.Category.SOCIAL_INTEGRATION)); + else if (mainCategory.equals(FormType.Category.SUPERNUMERARY)) + subCategories.addAll(List.of( + FormType.Category.NATIONAL_VETERANS_EDUCATION, + FormType.Category.SPECIAL_ADMISSION)); Map> formLists = subCategories.stream() .collect(Collectors.toMap( @@ -37,12 +43,6 @@ else if (mainCategory.equals(FormType.Category.SPECIAL)) .collect(Collectors.toList()) )); - if (mainCategory.equals(FormType.Category.SPECIAL)) { - formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.NATIONAL_VETERANS_EDUCATION)); - } else if(mainCategory.equals(FormType.Category.SUPERNUMERARY)) { - formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.SPECIAL_ADMISSION)); - } - for(Map.Entry> entry : formLists.entrySet()) { FormType.Category category = entry.getKey(); List formList = entry.getValue(); diff --git a/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java b/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java index 18c9fbfa..fa827815 100644 --- a/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java +++ b/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java @@ -25,8 +25,8 @@ public enum FormType implements EnumProperty { MULTI_CHILDREN("다자녀가정자녀", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY), FARMING_AND_FISHING("농어촌지역출신자", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY), - NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀", Category.SUPERNUMERARY, null, null), - SPECIAL_ADMISSION("특례입학대상자", Category.SUPERNUMERARY, null, null), + NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀", Category.SUPERNUMERARY, Category.NATIONAL_VETERANS_EDUCATION, null), + SPECIAL_ADMISSION("특례입학대상자", Category.SUPERNUMERARY, Category.SPECIAL_ADMISSION, null), ; @@ -46,6 +46,8 @@ public enum Category implements EnumProperty { // Middle Category SOCIAL_INTEGRATION("사회통합전형"), MEISTER_TALENT("마이스터인재전형"), + NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀"), + SPECIAL_ADMISSION("특례입학대상자"), // Sub Category EQUAL_OPPORTUNITY("기회균등전형"), From 76353f96aaf8a6d5423988ce4b867ff2f16ec218 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:45:32 +0900 Subject: [PATCH 42/59] =?UTF-8?q?feat(#79):=20=EC=9B=90=EC=84=9C=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=EC=97=90=20school=5Faddress=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80=20-=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=EC=9D=98=20=EC=B6=9C=EC=8B=A0=20?= =?UTF-8?q?=ED=95=99=EA=B5=90=EC=9D=98=20=EB=8F=84=EB=A1=9C=EB=AA=85=20?= =?UTF-8?q?=EC=A3=BC=EC=86=8C=EB=A5=BC=20=ED=91=9C=EA=B8=B0=ED=95=B4?= =?UTF-8?q?=EC=95=BC=20=ED=95=98=EB=8A=94=EB=8D=B0,=20=EB=8F=84=EB=A1=9C?= =?UTF-8?q?=EB=AA=85=EC=A3=BC=EC=86=8C=EA=B0=80=20=EC=97=86=EC=96=B4?= =?UTF-8?q?=EC=84=9C=20=EC=BB=AC=EB=9F=BC=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/domain/form/domain/value/School.java | 5 ++++- .../form/dto/request/EducationRequest.java | 13 +++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java b/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java index 10125bff..84684803 100644 --- a/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java +++ b/src/main/java/com/bamdoliro/maru/domain/form/domain/value/School.java @@ -19,10 +19,13 @@ public class School { @Column(name = "school_location", nullable = false, length = 20) private String location; + @Column(name = "school_address", nullable = false, length = 40) + private String address; + @Column(name = "school_code", nullable = false, length = 10) private String code; public boolean isBusan() { return location.equals("부산광역시"); } -} +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java b/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java index c47bd342..838b6a7e 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/form/dto/request/EducationRequest.java @@ -25,15 +25,19 @@ public class EducationRequest { @Size(min = 4, max = 4, message = "4자여야 합니다.") private String graduationYear; - @NotBlank + @NotBlank(message = "필수값입니다.") @Size(max = 20, message = "20자 이하여야 합니다.") private String schoolName; - @NotBlank + @NotBlank(message = "필수값입니다.") @Size(max = 20, message = "20자 이하여야 합니다.") private String schoolLocation; - @NotBlank + @NotBlank(message = "필수값입니다.") + @Size(max = 40, message = "40자 이하여야 합니다.") + private String schoolAddress; + + @NotBlank(message = "필수값입니다.") @Size(min = 7, max = 7, message = "7자여야 합니다.") private String schoolCode; @@ -56,6 +60,7 @@ public Education toValue() { new School( schoolName, schoolLocation, + schoolAddress, schoolCode ), new Teacher( @@ -65,4 +70,4 @@ public Education toValue() { ) ); } -} +} \ No newline at end of file From f4ff219d2953064c96b7ebfdc740f6cc8cafb775 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:46:13 +0900 Subject: [PATCH 43/59] =?UTF-8?q?test(#79):=20FormFixture,=20FormControlle?= =?UTF-8?q?rTest=20-=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=8F=84=20school=5Faddress=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=BC=EC=B6=94=EA=B0=80=EB=A5=BC=20=EB=B0=98=EC=98=81?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/form/FormControllerTest.java | 6 ++++++ .../bamdoliro/maru/shared/fixture/FormFixture.java | 12 ++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java index a01d821e..17720d9a 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/form/FormControllerTest.java @@ -141,6 +141,9 @@ class FormControllerTest extends RestDocsTestSupport { fieldWithPath("education.schoolLocation") .type(JsonFieldType.STRING) .description("출신 학교 지역"), + fieldWithPath("education.schoolAddress") + .type(JsonFieldType.STRING) + .description("출신 학교 주소지"), fieldWithPath("education.schoolCode") .type(JsonFieldType.STRING) .description("출신 학교 코드"), @@ -753,6 +756,9 @@ class FormControllerTest extends RestDocsTestSupport { fieldWithPath("education.schoolLocation") .type(JsonFieldType.STRING) .description("출신 학교 지역"), + fieldWithPath("education.schoolAddress") + .type(JsonFieldType.STRING) + .description("출신 학교 주소지"), fieldWithPath("education.schoolCode") .type(JsonFieldType.STRING) .description("출신 학교 코드"), diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index f2d20375..ebba8427 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -74,7 +74,7 @@ public static Form createForm(FormType type) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -140,7 +140,7 @@ public static Form createRandomForm(User user) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -218,7 +218,7 @@ public static Form createRandomQualificationExaminationForm(User user) { new Education( GraduationType.QUALIFICATION_EXAMINATION, "2021", - new School("비전중학교", "경기도", "7631003"), + new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), null ), new Grade( @@ -289,6 +289,7 @@ public static Form createQualificationExaminationForm(FormType type) { new School( "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003" ), null @@ -328,6 +329,7 @@ public static SubmitFormRequest createFormRequest(FormType type) { "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -369,6 +371,7 @@ public static SubmitFormRequest createQualificationExaminationFormRequest(FormTy "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", null, null, @@ -404,6 +407,7 @@ public static UpdateFormRequest createUpdateFormRequest(FormType type) { "2021", "비전중학교", "경기도", + "경기도 용인시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -550,4 +554,4 @@ public static FormUrlResponse createFormUrlResponse() { createFormUrlVo() ); } -} +} \ No newline at end of file From 87ad37d8d677e1fac26586250137cd734a6e4190 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 11:58:53 +0900 Subject: [PATCH 44/59] =?UTF-8?q?feat(#79):=20=EC=A0=84=ED=98=95=EB=B3=84?= =?UTF-8?q?=20=EC=A7=80=EC=9B=90=EC=9E=90=20=EC=88=98=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20-=20=EC=96=B4=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EB=B3=84=20=EC=A7=80=EC=9B=90=EC=9E=90=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryNumberOfApplicantsUseCase.java | 35 +++++++ .../form/FormRepositoryCustom.java | 12 ++- .../persistence/form/FormRepositoryImpl.java | 99 ++++++++++++++++++- .../persistence/form/vo/GradeVo.java | 26 +++++ .../form/vo/NumberOfApplicantsVo.java | 17 ++++ .../persistence/form/vo/SchoolStatusVo.java | 18 ++++ .../analysis/AnalysisController.java | 73 ++++++++++++++ .../response/NumberOfApplicantsResponse.java | 20 ++++ 8 files changed, 296 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java create mode 100644 src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java new file mode 100644 index 00000000..44d1c73c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java @@ -0,0 +1,35 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@UseCase +public class QueryNumberOfApplicantsUseCase { + private final FormRepository formRepository; + + public List execute() { + List result = formRepository.findTypeAndCountGroupByType() + .stream() + .map(NumberOfApplicantsResponse::new) + .collect(Collectors.toList()); + + List existingTypes = result.stream() + .map(NumberOfApplicantsResponse::getType) + .toList(); + + for (FormType formType: FormType.values()) { + if (!existingTypes.contains(formType)) { + result.add(new NumberOfApplicantsResponse(formType, 0L)); + } + } + + return result; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java index 7c2dd0ab..4f9cbe87 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryCustom.java @@ -2,13 +2,19 @@ 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.infrastructure.persistence.form.vo.NumberOfApplicantsVo; import com.bamdoliro.maru.infrastructure.persistence.form.vo.FormUrlVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.SchoolStatusVo; import java.util.List; public interface FormRepositoryCustom { List findByStatus(FormStatus status); + List findByType(FormType type); + List findByCategory(FormType.Category category); List findReceivedSpecialForm(); List findReceivedRegularOrSupernumeraryForm(); List findFirstRoundForm(); @@ -18,4 +24,8 @@ public interface FormRepositoryCustom { List findSecondRoundForm(); List findByFormIdList(List idList); List findFormUrlByFormIdList(List idList); -} + List findTypeAndCountGroupByType(); + List findGradeGroupByTypeAndStatus(List round); + List findSchoolByAddress(List round, String keyword); + List findNotBusanSchool(List round); +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java index d8cc004e..36b65a7b 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java @@ -3,8 +3,7 @@ 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.infrastructure.persistence.form.vo.FormUrlVo; -import com.bamdoliro.maru.infrastructure.persistence.form.vo.QFormUrlVo; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.*; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; @@ -12,6 +11,7 @@ import java.util.List; import java.util.Objects; +import java.util.stream.Stream; import static com.bamdoliro.maru.domain.form.domain.QForm.form; @@ -30,6 +30,26 @@ public List findByStatus(FormStatus status) { .fetch(); } + @Override + public List findByType(FormType type) { + return queryFactory + .selectFrom(form) + .where(eqType(type)) + .orderBy(form.examinationNumber.asc()) + .fetch(); + } + + @Override + public List findByCategory(FormType.Category category) { + List matchingFormTypes = getFormTypesByCategory(category); + + return queryFactory + .selectFrom(form) + .where(form.type.in(matchingFormTypes)) + .orderBy(form.examinationNumber.asc()) + .fetch(); + } + private BooleanExpression eqStatus(FormStatus status) { if (Objects.isNull(status)) { return null; @@ -38,6 +58,20 @@ private BooleanExpression eqStatus(FormStatus status) { return form.status.eq(status); } + private BooleanExpression eqType(FormType type) { + if (Objects.isNull(type)) { + return null; + } + + return form.type.eq(type); + } + + private List getFormTypesByCategory(FormType.Category category) { + return Stream.of(FormType.values()) + .filter(formType -> formType.categoryEquals(category)) + .toList(); + } + @Override public List findReceivedSpecialForm() { return queryFactory @@ -151,4 +185,63 @@ public List findFormUrlByFormIdList(List idList) { .orderBy(form.examinationNumber.asc()) .fetch(); } -} + + @Override + public List findTypeAndCountGroupByType() { + return queryFactory + .select(new QNumberOfApplicantsVo( + form.type, + form.count() + )) + .from(form) + .groupBy(form.type) + .fetch(); + } + + @Override + public List findGradeGroupByTypeAndStatus(List round) { + return queryFactory + .select(new QGradeVo( + form.type.stringValue(), + form.score.firstRoundScore.max(), + form.score.firstRoundScore.min(), + form.score.firstRoundScore.avg(), + form.score.totalScore.max(), + form.score.totalScore.min(), + form.score.totalScore.avg() + )) + .from(form) + .where(form.status.in(round)) + .groupBy(form.type) + .fetch(); + } + + @Override + public List findSchoolByAddress(List round, String keyword) { + return queryFactory + .select(new QSchoolStatusVo( + form.applicant.name, + form.education.school.name, + form.education.school.address + )) + .from(form) + .where(form.education.school.address.contains(keyword) + .or(form.education.school.location.eq(keyword)) + .and(form.status.in(round))) + .fetch(); + } + + @Override + public List findNotBusanSchool(List round) { + return queryFactory + .select(new QSchoolStatusVo( + form.applicant.name, + form.education.school.name, + form.education.school.address + )) + .from(form) + .where(form.education.school.location.eq("부산광역시").not() + .and(form.status.in(round))) + .fetch(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java new file mode 100644 index 00000000..5f531beb --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java @@ -0,0 +1,26 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class GradeVo { + private String type; + private Double firstRoundMax; + private Double firstRoundMin; + private Double firstRoundAvg; + private Double totalMax; + private Double totalMin; + private Double totalAvg; + + @QueryProjection + public GradeVo(String type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { + this.type = type; + this.firstRoundMax = firstRoundMax; + this.firstRoundMin = firstRoundMin; + this.firstRoundAvg = firstRoundAvg; + this.totalMax = totalMax; + this.totalMin = totalMin; + this.totalAvg = totalAvg; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java new file mode 100644 index 00000000..8f9c080c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/NumberOfApplicantsVo.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class NumberOfApplicantsVo { + private FormType type; + private Long count; + + @QueryProjection + public NumberOfApplicantsVo(FormType type, Long count) { + this.type = type; + this.count = count; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java new file mode 100644 index 00000000..4350ba73 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/SchoolStatusVo.java @@ -0,0 +1,18 @@ +package com.bamdoliro.maru.infrastructure.persistence.form.vo; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class SchoolStatusVo { + private String applicantName; + private String schoolName; + private String schoolAddress; + + @QueryProjection + public SchoolStatusVo(String applicantName, String schoolName, String schoolAddress) { + this.applicantName = applicantName; + this.schoolName = schoolName; + this.schoolAddress = schoolAddress; + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java new file mode 100644 index 00000000..e696ef8c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java @@ -0,0 +1,73 @@ +package com.bamdoliro.maru.presentation.analysis; + +import com.bamdoliro.maru.application.analysis.QueryGenderRatioUseCase; +import com.bamdoliro.maru.application.analysis.QueryNumberOfApplicantsUseCase; +import com.bamdoliro.maru.application.analysis.QueryGradeDistributionUseCase; +import com.bamdoliro.maru.application.analysis.QuerySchoolStatusUseCase; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; +import com.bamdoliro.maru.shared.auth.AuthenticationPrincipal; +import com.bamdoliro.maru.shared.auth.Authority; +import com.bamdoliro.maru.shared.response.CommonResponse; +import com.bamdoliro.maru.shared.response.ListCommonResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RequestMapping("/analysis") +@RestController +public class AnalysisController { + private final QueryNumberOfApplicantsUseCase queryNumberOfApplicantsUseCase; + private final QueryGradeDistributionUseCase queryGradeDistributionUseCase; + private final QueryGenderRatioUseCase queryGenderRatioUseCase; + private final QuerySchoolStatusUseCase querySchoolStatusUseCase; + + @GetMapping("/number-of-applicants") + public ListCommonResponse getNumberOfApplicants( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user + ) { + return CommonResponse.ok( + queryNumberOfApplicantsUseCase.execute() + ); + } + + @GetMapping("/grade-distribution") + public ListCommonResponse getGradeDistribution( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid GradeDistributionRequest request + ) { + return CommonResponse.ok( + queryGradeDistributionUseCase.execute(request) + ); + } + + @GetMapping("/gender-ratio") + public ListCommonResponse getGenderRatio( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid GenderRatioRequest request + ) { + return CommonResponse.ok( + queryGenderRatioUseCase.execute(request) + ); + } + + @GetMapping("/school-status") + public ListCommonResponse getSchoolStatus( + @AuthenticationPrincipal(authority = Authority.ADMIN)User user, + @RequestBody @Valid SchoolStatusRequest request + ) { + return CommonResponse.ok( + querySchoolStatusUseCase.execute(request) + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java new file mode 100644 index 00000000..c46a0da5 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/NumberOfApplicantsResponse.java @@ -0,0 +1,20 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.NumberOfApplicantsVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class NumberOfApplicantsResponse { + private FormType type; + private Long count; + + public NumberOfApplicantsResponse(NumberOfApplicantsVo vo){ + this.type = vo.getType(); + this.count = vo.getCount(); + } +} \ No newline at end of file From 0d52d2a7267232fb45f82307bbb16dc885d09015 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:00:13 +0900 Subject: [PATCH 45/59] =?UTF-8?q?feat(#79):=20=EC=84=B1=EC=A0=81=20?= =?UTF-8?q?=EB=B6=84=ED=8F=AC=20=EC=A1=B0=ED=9A=8C=20-=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84=ED=98=95=EB=B3=84=20?= =?UTF-8?q?=ED=95=99=EC=83=9D=EB=93=A4=EC=9D=98=20=EC=B5=9C=EA=B3=A0?= =?UTF-8?q?=EC=A0=90,=20=EC=B5=9C=ED=95=98=EC=A0=90,=20=ED=8F=89=EA=B7=A0?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryGradeDistributionUseCase.java | 22 ++++++++++++++ .../dto/request/GradeDistributionRequest.java | 17 +++++++++++ .../response/GradeDistributionResponse.java | 29 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java new file mode 100644 index 00000000..1bbd45e8 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -0,0 +1,22 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@UseCase +public class QueryGradeDistributionUseCase { + private final FormRepository formRepository; + + public List execute(GradeDistributionRequest request) { + return formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) + .stream() + .map(GradeDistributionResponse::new) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java new file mode 100644 index 00000000..f2828ead --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GradeDistributionRequest { + @NotNull(message = "필수값입니다.") + List statusList; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java new file mode 100644 index 00000000..c4f6d534 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java @@ -0,0 +1,29 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GradeDistributionResponse { + private String type; + private Double firstRoundMax; + private Double firstRoundMin; + private Double firstRoundAvg; + private Double totalMax; + private Double totalMin; + private Double totalAvg; + + public GradeDistributionResponse(GradeVo vo) { + this.type = vo.getType(); + this.firstRoundMax = vo.getFirstRoundMax(); + this.firstRoundMin = vo.getFirstRoundMin(); + this.firstRoundAvg = vo.getFirstRoundAvg(); + this.totalMax = vo.getTotalMax(); + this.totalMin = vo.getTotalMin(); + this.totalAvg = vo.getTotalAvg(); + } +} \ No newline at end of file From a2ee9733287ac07d448013948fef8ee0723e3748 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:01:29 +0900 Subject: [PATCH 46/59] =?UTF-8?q?feat(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=84=B1=EB=B9=84=20=EB=B6=84=EC=84=9D=20-=20=EC=96=B4?= =?UTF-8?q?=EB=93=9C=EB=AF=BC=EC=9D=B4=20=EC=A0=84=ED=98=95=EB=B3=84=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=EB=93=A4=EC=9D=98=20=EC=84=B1?= =?UTF-8?q?=EB=B3=84=EB=B6=84=ED=8F=AC=EB=A5=BC=20=ED=8C=8C=EC=95=85?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=9E=88=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 71 +++++++++++++++++++ .../dto/request/GenderRatioRequest.java | 21 ++++++ .../dto/response/GenderRatioResponse.java | 17 +++++ 3 files changed, 109 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java new file mode 100644 index 00000000..e71a24e2 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -0,0 +1,71 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.Form; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.domain.form.domain.type.Gender; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@UseCase +public class QueryGenderRatioUseCase { + private final FormRepository formRepository; + + public List execute(GenderRatioRequest request) { + List result = new ArrayList<>(); + + List subCategories = new ArrayList<>(); + + if (request.getMainCategory().equals(FormType.Category.REGULAR)) + subCategories.add(FormType.Category.REGULAR); + else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) + subCategories.addAll(List.of(FormType.Category.EQUAL_OPPORTUNITY, FormType.Category.SOCIETY_DIVERSITY)); + else subCategories.add(FormType.Category.SUPERNUMERARY); + + Map> formLists = subCategories.stream() + .collect(Collectors.toMap( + category -> category, + category -> formRepository.findByCategory(category).stream() + .filter(form -> request.getStatusList().contains(form.getStatus())) + .collect(Collectors.toList()) + )); + + for(Map.Entry> entry : formLists.entrySet()) { + FormType.Category category = entry.getKey(); + List formList = entry.getValue(); + + long busanMale = formList.stream().filter(this::isBusan).filter(this::isMale).count(); + long busanFeMale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); + long otherLocationMale = formList.stream().filter(this::isNotBusan).filter(this::isMale).count(); + long otherLocationFemale = formList.stream().filter(this::isNotBusan).filter(this::isFemale).count(); + + result.add(new GenderRatioResponse(category, busanMale, busanFeMale, otherLocationMale, otherLocationFemale)); + } + + return result; + } + + private boolean isBusan(Form form) { + return form.getEducation().getSchool().isBusan(); + } + + private boolean isNotBusan(Form form) { + return !isBusan(form); + } + + private boolean isMale(Form form) { + return form.getApplicant().getGender().equals(Gender.MALE); + } + + private boolean isFemale(Form form) { + return !isMale(form); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java new file mode 100644 index 00000000..6779ea6c --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java @@ -0,0 +1,21 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GenderRatioRequest { + @NotNull(message = "필수값입니다.") + private List statusList; + + @NotNull(message = "필수값입니다.") + private FormType.Category mainCategory; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java new file mode 100644 index 00000000..152143c1 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GenderRatioResponse.java @@ -0,0 +1,17 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GenderRatioResponse { + private FormType.Category category; + private long busanMale; + private long busanFemale; + private long otherLocationMale; + private long otherLocationFemale; +} \ No newline at end of file From 43759663e891b35513bcc835c7f9b8b13be53963 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:02:25 +0900 Subject: [PATCH 47/59] =?UTF-8?q?feat(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=B6=9C=EC=8B=A0=20=ED=95=99=EA=B5=90=20=ED=98=84=ED=99=A9?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20-=20=EC=96=B4=EB=93=9C=EB=AF=BC?= =?UTF-8?q?=EC=9D=B4=20=EC=A7=80=EC=9B=90=EC=9E=90=EB=93=A4=EC=9D=98=20?= =?UTF-8?q?=EC=B6=9C=EC=8B=A0=20=ED=95=99=EA=B5=90=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QuerySchoolStatusUseCase.java | 33 +++++++++++++++++++ .../dto/request/SchoolStatusRequest.java | 25 ++++++++++++++ .../dto/response/SchoolStatusResponse.java | 21 ++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java create mode 100644 src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java new file mode 100644 index 00000000..883b31d9 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QuerySchoolStatusUseCase.java @@ -0,0 +1,33 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; +import com.bamdoliro.maru.shared.annotation.UseCase; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@UseCase +public class QuerySchoolStatusUseCase { + + private final FormRepository formRepository; + + public List execute(SchoolStatusRequest request) { + if (request.getIsBusan()) { + String keyword = "부산광역시"; + keyword += request.getGu() == null ? "" : (" " + request.getGu()); + + return formRepository.findSchoolByAddress(request.getStatusList(), keyword) + .stream() + .map(SchoolStatusResponse::new) + .toList(); + } + + return formRepository.findNotBusanSchool(request.getStatusList()) + .stream() + .map(SchoolStatusResponse::new) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java new file mode 100644 index 00000000..be21084e --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java @@ -0,0 +1,25 @@ +package com.bamdoliro.maru.presentation.analysis.dto.request; + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SchoolStatusRequest { + + @NotNull(message = "필수값입니다.") + private List statusList; + + @NotNull(message = "필수값입니다.") + private Boolean isBusan; + + @Nullable + private String gu; +} \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java new file mode 100644 index 00000000..947081c7 --- /dev/null +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/SchoolStatusResponse.java @@ -0,0 +1,21 @@ +package com.bamdoliro.maru.presentation.analysis.dto.response; + +import com.bamdoliro.maru.infrastructure.persistence.form.vo.SchoolStatusVo; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SchoolStatusResponse { + private String applicantName; + private String schoolName; + private String schoolAddress; + + public SchoolStatusResponse(SchoolStatusVo schoolStatusVo) { + this.applicantName = schoolStatusVo.getApplicantName(); + this.schoolName = schoolStatusVo.getSchoolName(); + this.schoolAddress = schoolStatusVo.getSchoolAddress(); + } +} \ No newline at end of file From e58c7592f862ebf3422a27f6e6a1a3a1cd164392 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 13 Jun 2024 12:03:55 +0900 Subject: [PATCH 48/59] =?UTF-8?q?build:=20application.yml=20-=20debug=20-?= =?UTF-8?q?=20debug=20=EB=A1=9C=EA=B7=B8=EA=B0=80=20=EB=84=88=EB=AC=B4=20?= =?UTF-8?q?=EA=B8=B8=EC=96=B4=EC=84=9C=20=EB=B3=B4=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=98=B5=EC=85=98=EC=9D=84=20fal?= =?UTF-8?q?se=EB=A1=9C=20=EB=B0=94=EA=BF=A8=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1e425339..602c8e54 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -78,7 +78,7 @@ spring: activate: on-profile: dev -debug: true +debug: false --- spring: config: @@ -101,7 +101,7 @@ spring: port: 6379 password: bamdoliro -debug: true +debug: false --- spring: config: @@ -135,4 +135,4 @@ spring: port: 6379 password: bamdoliro -debug: true +debug: false From 0bc5f0b8061e2d241e3985767be6e05edadff005 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Fri, 14 Jun 2024 23:24:06 +0900 Subject: [PATCH 49/59] =?UTF-8?q?fix(#79):=20=EC=9B=90=EC=84=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?-=20=EC=9B=90=EC=84=9C=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20schoolAd?= =?UTF-8?q?dress=EA=B0=80=20=EB=B3=B4=EC=9D=B4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=96=88=EC=96=B4=EC=9A=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/form/dto/response/EducationResponse.java | 2 ++ .../java/com/bamdoliro/maru/shared/fixture/FormFixture.java | 1 + 2 files changed, 3 insertions(+) diff --git a/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java b/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java index bb4191da..cbe2e1ca 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/form/dto/response/EducationResponse.java @@ -14,6 +14,7 @@ public class EducationResponse { private String schoolName; private String schoolLocation; private String schoolCode; + private String schoolAddress; private String teacherName; private String teacherPhoneNumber; @@ -22,6 +23,7 @@ public EducationResponse(Education education) { this.graduationYear = education.getGraduationYear(); this.schoolName = education.getSchool().getName(); this.schoolLocation = education.getSchool().getLocation(); + this.schoolAddress = education.getSchool().getAddress(); this.schoolCode = education.getSchool().getCode(); this.teacherName = education.getTeacher().getName(); this.teacherPhoneNumber = education.getTeacher().getPhoneNumber().toString(); diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index ebba8427..c4bbb0da 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -465,6 +465,7 @@ public static FormResponse createFormResponse() { "비전중학교", "경기도", "7631003", + "경기도 용인시 비전구 비전로 1", "나교사", "0519701234" ), From fb3af0ca4f1a1350947dd548971896c5d985b0c0 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 01:01:55 +0900 Subject: [PATCH 50/59] =?UTF-8?q?perf(#79):=20=EC=A7=80=EC=9B=90=EC=9E=90?= =?UTF-8?q?=20=EC=84=B1=EC=A0=81=20=EB=B6=84=ED=8F=AC=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=200=EC=A0=90=20=ED=91=9C=EC=8B=9C=20-=20=EC=A7=80=EC=9B=90?= =?UTF-8?q?=EC=9E=90=20=EC=88=98=EA=B0=80=20=EC=97=86=EB=8A=94=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EC=9D=80=20=EC=84=B1=EC=A0=81=20=EB=B6=84=ED=8F=AC?= =?UTF-8?q?=EA=B0=80=20=EB=82=98=EC=98=A4=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EA=B2=83=EC=97=90=EC=84=9C=200=EC=9C=BC=EB=A1=9C=20=EB=82=98?= =?UTF-8?q?=EC=98=A4=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=ED=96=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryGradeDistributionUseCase.java | 19 ++++++++++++++++++- .../QueryNumberOfApplicantsUseCase.java | 4 +++- .../persistence/form/FormRepositoryImpl.java | 2 +- .../persistence/form/vo/GradeVo.java | 5 +++-- .../response/GradeDistributionResponse.java | 3 ++- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java index 1bbd45e8..4dedf217 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -1,5 +1,6 @@ package com.bamdoliro.maru.application.analysis; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; @@ -11,12 +12,28 @@ @RequiredArgsConstructor @UseCase public class QueryGradeDistributionUseCase { + private final FormRepository formRepository; public List execute(GradeDistributionRequest request) { - return formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) + List result = new java.util.ArrayList<>(formRepository.findGradeGroupByTypeAndStatus(request.getStatusList()) .stream() .map(GradeDistributionResponse::new) + .toList()); + + List existingTypes = result + .stream() + .map(GradeDistributionResponse::getType) .toList(); + +// System.out.println(existingTypes); + + for (FormType formType : FormType.values()) { + if (!existingTypes.contains(formType)) { + result.add(new GradeDistributionResponse(formType, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + } + } + + return result; } } \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java index 44d1c73c..0b5ff0f8 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCase.java @@ -12,6 +12,7 @@ @RequiredArgsConstructor @UseCase public class QueryNumberOfApplicantsUseCase { + private final FormRepository formRepository; public List execute() { @@ -20,7 +21,8 @@ public List execute() { .map(NumberOfApplicantsResponse::new) .collect(Collectors.toList()); - List existingTypes = result.stream() + List existingTypes = result + .stream() .map(NumberOfApplicantsResponse::getType) .toList(); diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java index 36b65a7b..5a09b03f 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/FormRepositoryImpl.java @@ -202,7 +202,7 @@ public List findTypeAndCountGroupByType() { public List findGradeGroupByTypeAndStatus(List round) { return queryFactory .select(new QGradeVo( - form.type.stringValue(), + form.type, form.score.firstRoundScore.max(), form.score.firstRoundScore.min(), form.score.firstRoundScore.avg(), diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java index 5f531beb..41755097 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/persistence/form/vo/GradeVo.java @@ -1,11 +1,12 @@ package com.bamdoliro.maru.infrastructure.persistence.form.vo; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.querydsl.core.annotations.QueryProjection; import lombok.Getter; @Getter public class GradeVo { - private String type; + private FormType type; private Double firstRoundMax; private Double firstRoundMin; private Double firstRoundAvg; @@ -14,7 +15,7 @@ public class GradeVo { private Double totalAvg; @QueryProjection - public GradeVo(String type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { + public GradeVo(FormType type, Double firstRoundMax, Double firstRoundMin, Double firstRoundAvg, Double totalMax, Double totalMin, Double totalAvg) { this.type = type; this.firstRoundMax = firstRoundMax; this.firstRoundMin = firstRoundMin; diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java index c4f6d534..7104a85d 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/response/GradeDistributionResponse.java @@ -1,5 +1,6 @@ package com.bamdoliro.maru.presentation.analysis.dto.response; +import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.infrastructure.persistence.form.vo.GradeVo; import lombok.AllArgsConstructor; import lombok.Getter; @@ -9,7 +10,7 @@ @NoArgsConstructor @AllArgsConstructor public class GradeDistributionResponse { - private String type; + private FormType type; private Double firstRoundMax; private Double firstRoundMin; private Double firstRoundAvg; From a867ed8b138244e31b2304f6545f386324199164 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 01:42:56 +0900 Subject: [PATCH 51/59] =?UTF-8?q?refactor(#79):=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/analysis/QueryGradeDistributionUseCase.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java index 4dedf217..21d2ecbb 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGradeDistributionUseCase.java @@ -26,8 +26,6 @@ public List execute(GradeDistributionRequest request) .map(GradeDistributionResponse::getType) .toList(); -// System.out.println(existingTypes); - for (FormType formType : FormType.values()) { if (!existingTypes.contains(formType)) { result.add(new GradeDistributionResponse(formType, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); From 3a31610c1bdbb03d34325b14239e6211cc1a7474 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:39:54 +0900 Subject: [PATCH 52/59] =?UTF-8?q?test(#79):=20AnalysisControllerTest=20-?= =?UTF-8?q?=20=EB=B6=84=EC=84=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/AnalysisControllerTest.java | 260 ++++++++++++++++++ .../maru/shared/fixture/AnalysisFixture.java | 82 ++++++ .../maru/shared/util/ControllerTest.java | 35 ++- .../maru/shared/util/RandomUtil.java | 4 + 4 files changed, 378 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java create mode 100644 src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java new file mode 100644 index 00000000..05040f4f --- /dev/null +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -0,0 +1,260 @@ +package com.bamdoliro.maru.presentation.analysis; + + +import com.bamdoliro.maru.domain.form.domain.type.FormStatus; +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.domain.user.domain.User; +import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.GradeDistributionRequest; +import com.bamdoliro.maru.presentation.analysis.dto.request.SchoolStatusRequest; +import com.bamdoliro.maru.shared.fixture.AnalysisFixture; +import com.bamdoliro.maru.shared.fixture.AuthFixture; +import com.bamdoliro.maru.shared.fixture.UserFixture; +import com.bamdoliro.maru.shared.util.RestDocsTestSupport; +import kotlinx.serialization.json.Json; +import org.junit.jupiter.api.Test; +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; + +import java.util.List; +import java.util.Optional; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class AnalysisControllerTest extends RestDocsTestSupport { + + @Test + void 전형별_지원자수를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + given(queryNumberOfApplicantsUseCase.execute()).willReturn(AnalysisFixture.createNumberOfApplicantsResponse()); + + mockMvc.perform(get("/analysis/number-of-applicants") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders(headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ) + )); + } + + @Test + void _1차_합격자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + )); + System.out.println(AnalysisFixture.createGradeDistributionResponse()); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void _2차_전형자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.FAILED, + FormStatus.PASSED + )); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void 최종_합격자들의_성적_분포를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GradeDistributionRequest request = new GradeDistributionRequest(List.of( + FormStatus.PASSED + )); + given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); + + mockMvc.perform(get("/analysis/grade-distribution") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + ) + )); + } + + @Test + void 전형별_성비를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + GenderRatioRequest request = new GenderRatioRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + FormType.Category.REGULAR); + given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse(FormType.Category.REGULAR)); + + mockMvc.perform(get("/analysis/gender-ratio") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("mainCategory").type(JsonFieldType.STRING).description("메인 카테고리(FormType.Category 참고)") + ) + )); + } + + @Test + void 부산_특정구_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + true, + "사상구"); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } + + @Test + void 부산_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + true, + null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } + + @Test + void 타지역_출신_지원자들의_출신학교_통계를_조회한다() throws Exception { + User user = UserFixture.createAdminUser(); + given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); + given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); + SchoolStatusRequest request = new SchoolStatusRequest(List.of( + FormStatus.FIRST_PASSED, + FormStatus.FAILED, + FormStatus.PASSED + ), + false, + null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + + mockMvc.perform(get("/analysis/school-status") + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(request))) + .andExpect(status().isOk()) + .andDo(restDocs.document( + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + ), + requestFields( + fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + ) + )); + } +} \ No newline at end of file diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java new file mode 100644 index 00000000..a3b14774 --- /dev/null +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -0,0 +1,82 @@ +package com.bamdoliro.maru.shared.fixture; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.presentation.analysis.dto.response.GenderRatioResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.GradeDistributionResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import com.bamdoliro.maru.presentation.analysis.dto.response.SchoolStatusResponse; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; +import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; + +public class AnalysisFixture { + + public static List createNumberOfApplicantsResponse() { + List responseList = new ArrayList<>(); + for (FormType formType : FormType.values()) { + responseList.add(new NumberOfApplicantsResponse(formType, (long)randomNumber(0, 50))); + } + return responseList; + } + + public static List createGradeDistributionResponse() { + List responseList = new ArrayList<>(); + for (FormType formType : FormType.values()) { + responseList.add(new GradeDistributionResponse(formType, randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0), randomDouble(0.0, 240.0))); + } + return responseList; + } + + public static List createGenderRatioResponse(FormType.Category mainCategory) { + return List.of( + new GenderRatioResponse( + FormType.Category.REGULAR, + randomNumber(0, 30), + randomNumber(0, 15), + randomNumber(0, 30), + randomNumber(0, 15) + ) + ); + } + + public static List createSchoolStatusResponse(Boolean isBusan, String gu) { + if (isBusan) { + if (gu == null) { + return List.of( + new SchoolStatusResponse( + "김밤돌", + "신라중학교", + "부산광역시 사상구 백양대로700번길 35-8" + ), + new SchoolStatusResponse( + "김이로", + "성동중학교", + "부산광역시 남구 남동천로 38" + ), + new SchoolStatusResponse( + "금곰돌", + "가락중학교", + "부산광역시 강서구 가락대로 1405") + ); + } + return List.of( + new SchoolStatusResponse( + "김밤돌", + "신라중학교", + "부산광역시 사상구 백양대로700번길 35-8" + ) + ); + } + return List.of( + new SchoolStatusResponse( + "김밤돌", + "비전중학교", + "경기도 용인시 비전구 비전로 1" + ) + ); + } +} diff --git a/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java b/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java index 96bea802..19f1359c 100644 --- a/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/shared/util/ControllerTest.java @@ -1,5 +1,9 @@ package com.bamdoliro.maru.shared.util; +import com.bamdoliro.maru.application.analysis.QueryGenderRatioUseCase; +import com.bamdoliro.maru.application.analysis.QueryGradeDistributionUseCase; +import com.bamdoliro.maru.application.analysis.QueryNumberOfApplicantsUseCase; +import com.bamdoliro.maru.application.analysis.QuerySchoolStatusUseCase; import com.bamdoliro.maru.application.auth.LogInUseCase; import com.bamdoliro.maru.application.auth.LogOutUseCase; import com.bamdoliro.maru.application.auth.RefreshTokenUseCase; @@ -53,6 +57,7 @@ import com.bamdoliro.maru.domain.auth.service.TokenService; import com.bamdoliro.maru.infrastructure.message.SendMessageService; import com.bamdoliro.maru.infrastructure.neis.SearchSchoolService; +import com.bamdoliro.maru.presentation.analysis.AnalysisController; import com.bamdoliro.maru.presentation.auth.AuthController; import com.bamdoliro.maru.presentation.fair.FairController; import com.bamdoliro.maru.presentation.form.DraftFormController; @@ -75,7 +80,17 @@ import org.springframework.test.web.servlet.MockMvc; @Disabled -@WebMvcTest({UserController.class, AuthController.class, SharedController.class, SchoolController.class, QuestionController.class, FormController.class, NoticeController.class, DraftFormController.class, FairController.class, MessageController.class}) +@WebMvcTest({UserController.class, + AuthController.class, + SharedController.class, + SchoolController.class, + QuestionController.class, + FormController.class, + NoticeController.class, + DraftFormController.class, + FairController.class, + MessageController.class, + AnalysisController.class}) public abstract class ControllerTest { @Autowired @@ -232,6 +247,22 @@ public abstract class ControllerTest { @MockBean protected QueryFormUrlUseCase queryFormUrlUseCase; + @MockBean + protected SendMessageUseCase sendMessageUseCase; + + @MockBean + protected QueryNumberOfApplicantsUseCase queryNumberOfApplicantsUseCase; + + @MockBean + protected QueryGradeDistributionUseCase queryGradeDistributionUseCase; + + @MockBean + protected QueryGenderRatioUseCase queryGenderRatioUseCase; + + @MockBean + protected QuerySchoolStatusUseCase querySchoolStatusUseCase; + + @MockBean protected TokenService tokenService; @@ -241,8 +272,6 @@ public abstract class ControllerTest { @MockBean protected SendMessageService sendMessageService; - @MockBean - protected SendMessageUseCase sendMessageUseCase; @MockBean protected JwtProperties jwtProperties; diff --git a/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java b/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java index c1ab939c..76e39edc 100644 --- a/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java +++ b/src/test/java/com/bamdoliro/maru/shared/util/RandomUtil.java @@ -9,4 +9,8 @@ public static String randomPhoneNumber() { public static int randomNumber(int min, int max) { return (int) ((Math.random() * (max - min)) + min); } + + public static double randomDouble(double min, double max) { + return Math.round(((Math.random() * (max - min)) + min) * 1000.0) / 1000.0; + } } From fd4941cae233e14468688565f55aa0e56ff12680 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:40:22 +0900 Subject: [PATCH 53/59] =?UTF-8?q?docs(#79):=20analysis.adoc=20-=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/analysis.adoc | 92 +++++++++++++++++++++++++++++++++ src/docs/asciidoc/index.adoc | 2 + 2 files changed, 94 insertions(+) create mode 100644 src/docs/asciidoc/analysis.adoc diff --git a/src/docs/asciidoc/analysis.adoc b/src/docs/asciidoc/analysis.adoc new file mode 100644 index 00000000..8354f760 --- /dev/null +++ b/src/docs/asciidoc/analysis.adoc @@ -0,0 +1,92 @@ +== 분석 Analysis + +=== 전형별 지원자 수 조회 +전형별 지원자들의 수를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/request-headers.adoc[] + +==== 요청 +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/http-request.adoc[] + +==== 응답 +include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한다/http-response.adoc[] + +=== 전형별 성적 분포 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 전형별 성적 분포를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-fields.adoc[] + +==== 요청 + +===== 1차 합격자 +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/http-request.adoc[] + +===== 2차 전형자 +include::{snippets}/analysis-controller-test/_2차_전형자들의_성적_분포를_조회한다/http-request.adoc[] + +===== 최종 합격자 +include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분포를_조회한다/http-request.adoc[] + +==== 응답 + +===== 정상 응답 +include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분포를_조회한다/http-response.adoc[] + +=== 전형별 성비 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 전형별, 지역별 성비를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-fields.adoc[] + +==== 요청 +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-request.adoc[] + +==== 응답 + +===== 정상 응답 +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-response.adoc[] + +=== 전형별 출신학교 조회 +1차 합격자, 2차 전형자, 최종 합격자들의 출신학교를 조회할 수 있습니다. + +=== 요청 형식 + +==== Request Header +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-headers.adoc[] + +==== Request Body +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-fields.adoc[] + +==== 요청 +===== 부산 특정구 출신 +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 부산 출신 +include::{snippets}/analysis-controller-test/부산_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 타지역 출신 +include::{snippets}/analysis-controller-test/타지역_출신_지원자들의_출신학교_통계를_조회한다/http-request.adoc[] + +==== 응답 +==== 부산 특정구 출신 정상 응답 +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] + +==== 부산 출신 정상 응답 +include::{snippets}/analysis-controller-test/부산_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] + +==== 타지역 출신 정상 응답 +include::{snippets}/analysis-controller-test/타지역_출신_지원자들의_출신학교_통계를_조회한다/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 4a46528e..d64e5a35 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -27,4 +27,6 @@ include::fair.adoc[] include::message.adoc[] +include::analysis.adoc[] + include::enum.adoc[] From e7c2a1275391d4afc249157c5a12e668d1a22182 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 05:41:28 +0900 Subject: [PATCH 54/59] =?UTF-8?q?refactor(#79):=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=EB=AC=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maru/presentation/analysis/AnalysisControllerTest.java | 2 -- .../java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java | 1 - 2 files changed, 3 deletions(-) diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java index 05040f4f..ba782869 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -11,7 +11,6 @@ import com.bamdoliro.maru.shared.fixture.AuthFixture; import com.bamdoliro.maru.shared.fixture.UserFixture; import com.bamdoliro.maru.shared.util.RestDocsTestSupport; -import kotlinx.serialization.json.Json; import org.junit.jupiter.api.Test; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; @@ -19,7 +18,6 @@ import org.springframework.restdocs.payload.JsonFieldType; import java.util.List; -import java.util.Optional; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index a3b14774..a405d6b6 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; From daaa891a8eb9e63411e714e555d1afba759c4c8d Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 17 Jun 2024 23:24:48 +0900 Subject: [PATCH 55/59] =?UTF-8?q?fix(#79):=20SchoolResponse=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20=ED=95=99=EA=B5=90=EB=A5=BC=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=ED=95=A0=20=EB=95=8C=20=ED=95=99=EA=B5=90=EC=9D=98=20?= =?UTF-8?q?=EB=8F=84=EB=A1=9C=EB=AA=85=20=EC=A3=BC=EC=86=8C=EA=B0=80=20?= =?UTF-8?q?=ED=95=A8=EA=BB=98=20=EB=82=98=EC=98=A4=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../neis/SearchSchoolService.java | 1 + .../school/dto/response/SchoolResponse.java | 1 + .../maru/shared/fixture/AnalysisFixture.java | 2 +- .../maru/shared/fixture/FormFixture.java | 16 ++++----- .../maru/shared/fixture/SchoolFixture.java | 34 +++++++++---------- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java b/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java index 1bf2cf34..19acfd86 100644 --- a/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java +++ b/src/main/java/com/bamdoliro/maru/infrastructure/neis/SearchSchoolService.java @@ -27,6 +27,7 @@ public List execute(String q) throws JsonProcessingException { .map(s -> SchoolResponse.builder() .name(s.getSchoolName()) .location(s.getLocation()) + .address((s.getAddress())) .code(s.getStandardSchoolCode()) .build()) .toList(); diff --git a/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java b/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java index b9846bfc..0bbf9120 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java +++ b/src/main/java/com/bamdoliro/maru/presentation/school/dto/response/SchoolResponse.java @@ -11,5 +11,6 @@ public class SchoolResponse { private String name; private String location; + private String address; private String code; } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index a405d6b6..4c439e51 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -74,7 +74,7 @@ public static List createSchoolStatusResponse(Boolean isBu new SchoolStatusResponse( "김밤돌", "비전중학교", - "경기도 용인시 비전구 비전로 1" + "경기도 비전시 비전구 비전로 1" ) ); } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java index c4bbb0da..356af708 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/FormFixture.java @@ -74,7 +74,7 @@ public static Form createForm(FormType type) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -140,7 +140,7 @@ public static Form createRandomForm(User user) { new Education( GraduationType.EXPECTED, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), new Teacher("나교사", new PhoneNumber("0519701234"), new PhoneNumber("01012344321")) ), new Grade( @@ -218,7 +218,7 @@ public static Form createRandomQualificationExaminationForm(User user) { new Education( GraduationType.QUALIFICATION_EXAMINATION, "2021", - new School("비전중학교", "경기도", "경기도 용인시 비전구 비전로 1", "7631003"), + new School("비전중학교", "경기도", "경기도 비전시 비전구 비전로 1", "7631003"), null ), new Grade( @@ -289,7 +289,7 @@ public static Form createQualificationExaminationForm(FormType type) { new School( "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003" ), null @@ -329,7 +329,7 @@ public static SubmitFormRequest createFormRequest(FormType type) { "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -371,7 +371,7 @@ public static SubmitFormRequest createQualificationExaminationFormRequest(FormTy "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", null, null, @@ -407,7 +407,7 @@ public static UpdateFormRequest createUpdateFormRequest(FormType type) { "2021", "비전중학교", "경기도", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "7631003", "나교사", "0519701234", @@ -465,7 +465,7 @@ public static FormResponse createFormResponse() { "비전중학교", "경기도", "7631003", - "경기도 용인시 비전구 비전로 1", + "경기도 비전시 비전구 비전로 1", "나교사", "0519701234" ), diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java index 46d468ea..f329dc87 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/SchoolFixture.java @@ -8,22 +8,22 @@ public class SchoolFixture { public static List createSchoolListResponse() { return List.of( - new SchoolResponse("부산소프트웨어마이스터고등학교", "부산광역시", "7150658") - ); - } + new SchoolResponse("부산소프트웨어마이스터고등학교", "부산광역시", "부산광역시 강서구 가락대로 1393", "7150658") +); +} - public static List createSchoolMaxListResponse() { - return List.of( - new SchoolResponse("비전고등학교", "경기도", "7531109"), - new SchoolResponse("비전중학교", "경기도", "7631003"), - new SchoolResponse("비전초등학교", "경기도", "7631034"), - new SchoolResponse("공동체비전고등학교", "충청남도", "8140222"), - new SchoolResponse("다른비전고등학교", "경상북도", "7531109"), - new SchoolResponse("다른비전중학교", "경기도", "7631003"), - new SchoolResponse("다른비전초등학교", "경상남도", "7631034"), - new SchoolResponse("다른공동체비전고등학교", "충청남도", "8140222"), - new SchoolResponse("또다른비전고등학교", "대구광역시", "7531109"), - new SchoolResponse("또다른비전중학교", "경기도", "7631003") - ); - } +public static List createSchoolMaxListResponse() { +return List.of( +new SchoolResponse("비전고등학교", "경기도", "경기도 비전시 비전구 비전로 2", "7531109"), +new SchoolResponse("비전중학교", "경기도","경기도 비전시 비전구 비전로 1", "7631003"), +new SchoolResponse("비전초등학교", "경기도", "경기도 비전시 비전구 비전로 3", "7631034"), +new SchoolResponse("공동체비전고등학교", "충청남도", "충청남도 비전시 비전구 비전로 1", "8140222"), +new SchoolResponse("다른비전고등학교", "경상북도", "경상북도 비전시 비전구 비전로 1", "7531109"), +new SchoolResponse("다른비전중학교", "경기도", "경기도 비전시 비전구 비전로 4", "7631003"), +new SchoolResponse("다른비전초등학교", "경상남도", "경상남도 비전시 비전구 비전로 1", "7631034"), +new SchoolResponse("다른공동체비전고등학교", "충청남도", "충청남도 비전시 비전구 비전로 2", "8140222"), +new SchoolResponse("또다른비전고등학교", "대구광역시", "대구광역시 비전구 비전로 1", "7531109"), +new SchoolResponse("또다른비전중학교", "경기도", "경기도 비전시 비전구 비전로 5", "7631003") +); +} } From a3370be489fd4e1d9c5193830516da45c47353ba Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Wed, 19 Jun 2024 03:52:03 +0900 Subject: [PATCH 56/59] =?UTF-8?q?refactor(#79):=20Parameter=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20-=20HTTP=20GET=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=8A=94=20RequestBody=EB=A5=BC=20=EA=B6=8C?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=EB=8B=A4?= =?UTF-8?q?=EB=8A=94=EA=B2=83=EC=9D=84=20=EC=95=8C=EC=95=84=EC=84=9C=20Par?= =?UTF-8?q?ameter=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.=20-=20@ModelAttr?= =?UTF-8?q?ibute=EC=9D=98=20=EC=9E=91=EB=8F=99=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9D=B4=20Setter=EB=A5=BC=20=EC=9D=B4=EC=9A=A9=ED=95=B4=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20=EC=A3=BC=EC=9E=85=ED=95=98=EB=8A=94?= =?UTF-8?q?=EA=B2=83=EC=9D=B4=EC=96=B4=EC=84=9C=20request=20dto=EC=97=90?= =?UTF-8?q?=20setter=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=96=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/analysis.adoc | 12 +- .../analysis/AnalysisController.java | 11 +- .../dto/request/GenderRatioRequest.java | 2 + .../dto/request/GradeDistributionRequest.java | 3 + .../dto/request/SchoolStatusRequest.java | 2 + .../analysis/AnalysisControllerTest.java | 179 +++++++++--------- .../maru/shared/fixture/AnalysisFixture.java | 7 +- 7 files changed, 114 insertions(+), 102 deletions(-) diff --git a/src/docs/asciidoc/analysis.adoc b/src/docs/asciidoc/analysis.adoc index 8354f760..f591d69f 100644 --- a/src/docs/asciidoc/analysis.adoc +++ b/src/docs/asciidoc/analysis.adoc @@ -22,8 +22,8 @@ include::{snippets}/analysis-controller-test/전형별_지원자수를_조회한 ==== Request Header include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/_1차_합격자들의_성적_분포를_조회한다/query-parameters.adoc[] ==== 요청 @@ -49,8 +49,8 @@ include::{snippets}/analysis-controller-test/최종_합격자들의_성적_분 ==== Request Header include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/query-parameters.adoc[] ==== 요청 include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/http-request.adoc[] @@ -68,8 +68,8 @@ include::{snippets}/analysis-controller-test/전형별_성비를_조회한다/ht ==== Request Header include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-headers.adoc[] -==== Request Body -include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/request-fields.adoc[] +==== Query Parameter +include::{snippets}/analysis-controller-test/부산_특정구_출신_지원자들의_출신학교_통계를_조회한다/query-parameters.adoc[] ==== 요청 ===== 부산 특정구 출신 diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java index e696ef8c..b5305f49 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/AnalysisController.java @@ -18,10 +18,7 @@ import com.bamdoliro.maru.shared.response.ListCommonResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor @RequestMapping("/analysis") @@ -44,7 +41,7 @@ public ListCommonResponse getNumberOfApplicants( @GetMapping("/grade-distribution") public ListCommonResponse getGradeDistribution( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid GradeDistributionRequest request + @ModelAttribute @Valid GradeDistributionRequest request ) { return CommonResponse.ok( queryGradeDistributionUseCase.execute(request) @@ -54,7 +51,7 @@ public ListCommonResponse getGradeDistribution( @GetMapping("/gender-ratio") public ListCommonResponse getGenderRatio( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid GenderRatioRequest request + @ModelAttribute @Valid GenderRatioRequest request ) { return CommonResponse.ok( queryGenderRatioUseCase.execute(request) @@ -64,7 +61,7 @@ public ListCommonResponse getGenderRatio( @GetMapping("/school-status") public ListCommonResponse getSchoolStatus( @AuthenticationPrincipal(authority = Authority.ADMIN)User user, - @RequestBody @Valid SchoolStatusRequest request + @ModelAttribute @Valid SchoolStatusRequest request ) { return CommonResponse.ok( querySchoolStatusUseCase.execute(request) diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java index 6779ea6c..e4af7ffa 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GenderRatioRequest.java @@ -6,10 +6,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class GenderRatioRequest { diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java index f2828ead..beb0333e 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/GradeDistributionRequest.java @@ -5,13 +5,16 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class GradeDistributionRequest { + @NotNull(message = "필수값입니다.") List statusList; } \ No newline at end of file diff --git a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java index be21084e..b1137393 100644 --- a/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java +++ b/src/main/java/com/bamdoliro/maru/presentation/analysis/dto/request/SchoolStatusRequest.java @@ -6,10 +6,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class SchoolStatusRequest { diff --git a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java index ba782869..36dc3583 100644 --- a/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/presentation/analysis/AnalysisControllerTest.java @@ -1,7 +1,6 @@ package com.bamdoliro.maru.presentation.analysis; -import com.bamdoliro.maru.domain.form.domain.type.FormStatus; import com.bamdoliro.maru.domain.form.domain.type.FormType; import com.bamdoliro.maru.domain.user.domain.User; import com.bamdoliro.maru.presentation.analysis.dto.request.GenderRatioRequest; @@ -15,16 +14,18 @@ import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import java.util.List; +import java.util.Objects; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -43,7 +44,8 @@ class AnalysisControllerTest extends RestDocsTestSupport { .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andDo(restDocs.document( - requestHeaders(headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") + requestHeaders( + headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ) )); } @@ -53,26 +55,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - )); - System.out.println(AnalysisFixture.createGradeDistributionResponse()); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "FIRST_PASSED", "FAILED", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -82,24 +81,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.FAILED, - FormStatus.PASSED - )); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "FAILED", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -109,23 +107,23 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GradeDistributionRequest request = new GradeDistributionRequest(List.of( - FormStatus.PASSED - )); given(queryGradeDistributionUseCase.execute(any(GradeDistributionRequest.class))).willReturn(AnalysisFixture.createGradeDistributionResponse()); mockMvc.perform(get("/analysis/grade-distribution") + .param("statusList", "PASSED") .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)") ) )); } @@ -135,27 +133,30 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - GenderRatioRequest request = new GenderRatioRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - FormType.Category.REGULAR); - given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse(FormType.Category.REGULAR)); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("mainCategory", "REGULAR"); + given(queryGenderRatioUseCase.execute(any(GenderRatioRequest.class))).willReturn(AnalysisFixture.createGenderRatioResponse( + FormType.Category.valueOf(Objects.requireNonNull(multiValueMap.get("mainCategory")).get(0)) + )); mockMvc.perform(get("/analysis/gender-ratio") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("mainCategory").type(JsonFieldType.STRING).description("메인 카테고리(FormType.Category 참고)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("mainCategory") + .description("메인 카테고리(FormType.Category 참고)") ) )); } @@ -165,29 +166,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - true, - "사상구"); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "true"); + multiValueMap.add("gu", "사상구"); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") - .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .params(multiValueMap) + .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } @@ -197,29 +200,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - true, - null); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "true"); + multiValueMap.add("gu", null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } @@ -229,29 +234,31 @@ class AnalysisControllerTest extends RestDocsTestSupport { User user = UserFixture.createAdminUser(); given(authenticationArgumentResolver.supportsParameter(any(MethodParameter.class))).willReturn(true); given(authenticationArgumentResolver.resolveArgument(any(), any(), any(), any())).willReturn(user); - SchoolStatusRequest request = new SchoolStatusRequest(List.of( - FormStatus.FIRST_PASSED, - FormStatus.FAILED, - FormStatus.PASSED - ), - false, - null); - given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(request.getIsBusan(), request.getGu())); + MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.put("statusList", List.of("FIRST_PASSED", "FAILED", "PASSED")); + multiValueMap.add("isBusan", "false"); + multiValueMap.add("gu", null); + given(querySchoolStatusUseCase.execute(any(SchoolStatusRequest.class))).willReturn(AnalysisFixture.createSchoolStatusResponse(Objects.requireNonNull(multiValueMap.get("isBusan")), multiValueMap.get("gu"))); mockMvc.perform(get("/analysis/school-status") + .params(multiValueMap) .header(HttpHeaders.AUTHORIZATION, AuthFixture.createAuthHeader()) .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(toJson(request))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(restDocs.document( requestHeaders( headerWithName(HttpHeaders.AUTHORIZATION).description("Bearer token") ), - requestFields( - fieldWithPath("statusList").type(JsonFieldType.ARRAY).description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), - fieldWithPath("isBusan").type(JsonFieldType.BOOLEAN).description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), - fieldWithPath("gu").type(JsonFieldType.STRING).optional().description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") + queryParameters( + parameterWithName("statusList") + .description("조회할 원서 상태 목록(1차 합격자면 FIRST_PASSED, FAILED, PASSED, 2차 전형자면 FAILED, PASSED, 최종 합격자면 PASSED)"), + parameterWithName("isBusan") + .description("부산 지역 학교 검색 여부(true면 부산, false면 부산 외 다른 모든 타지역)"), + parameterWithName("gu") + .description("구(isBusan이 true이고, null인 경우 부산지역 전체 조회)") ) )); } diff --git a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java index 4c439e51..66c9748c 100644 --- a/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java +++ b/src/test/java/com/bamdoliro/maru/shared/fixture/AnalysisFixture.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import static com.bamdoliro.maru.shared.util.RandomUtil.randomDouble; import static com.bamdoliro.maru.shared.util.RandomUtil.randomNumber; @@ -42,9 +43,9 @@ public static List createGenderRatioResponse(FormType.Categ ); } - public static List createSchoolStatusResponse(Boolean isBusan, String gu) { - if (isBusan) { - if (gu == null) { + public static List createSchoolStatusResponse(List isBusan, List gu) { + if (Objects.equals(isBusan.get(0), "true")) { + if (gu.get(0) == null) { return List.of( new SchoolStatusResponse( "김밤돌", From 21a6ae5084b192395808c56764c701499088faad Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 20 Jun 2024 13:15:51 +0900 Subject: [PATCH 57/59] =?UTF-8?q?fix(#79):=20=EC=84=B1=EB=B9=84=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?-=20=ED=8A=B9=EB=B3=84=20=EC=A0=84=ED=98=95=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=ED=96=88=EC=9D=84=20=EB=95=8C=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=ED=84=B0=20=EC=9D=B8=EC=9E=AC=EC=A0=84?= =?UTF-8?q?=ED=98=95=EA=B3=BC=20=EC=A0=95=EC=9B=90=20=EC=99=B8=20=EC=A0=84?= =?UTF-8?q?=ED=98=95=EC=9D=B4=20=EB=82=98=EC=98=A4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4=20-=20=ED=8A=B9=EB=A1=80?= =?UTF-8?q?=EC=9E=85=ED=95=99=20=EB=8C=80=EC=83=81=EC=9E=90=EB=A5=BC=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=96=88=EC=9D=84=20=EB=95=8C=20=ED=8A=B9?= =?UTF-8?q?=EB=B3=84=EC=A0=84=ED=98=95=EC=9D=98=20=EC=A0=95=EC=9B=90=20?= =?UTF-8?q?=EC=99=B8=20=EC=A0=84=ED=98=95=EC=9D=B4=20=EB=82=98=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=EB=A5=BC=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.=20=EA=B5=AD=EA=B0=80?= =?UTF-8?q?=EB=B3=B4=ED=9B=88=EC=9E=90=EB=85=80=EC=99=80=20=ED=8A=B9?= =?UTF-8?q?=EB=A1=80=EC=9E=85=ED=95=99=EC=9D=B4=20=EB=98=91=EA=B0=99?= =?UTF-8?q?=EC=9D=B4=20=EC=A0=95=EC=9B=90=20=EC=99=B8=20=EC=A0=84=ED=98=95?= =?UTF-8?q?=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=A7=8C=20=EC=9E=88?= =?UTF-8?q?=EA=B3=A0=20=EA=B5=AD=EA=B0=80=EB=B3=B4=ED=9B=88=EC=9E=90?= =?UTF-8?q?=EB=85=80=EA=B0=80=20=ED=8A=B9=EB=B3=84=20=EC=A0=84=ED=98=95=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EC=97=90=20=EB=93=A4?= =?UTF-8?q?=EC=96=B4=EC=9E=88=EC=A7=80=20=EC=95=8A=EC=95=84=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EC=A2=80=20=EB=8D=94=EB=9F=AC=EC=9B=8C?= =?UTF-8?q?=EC=A1=8C=EC=8A=B5=EB=8B=88=EB=8B=A4...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 19 ++++++++++++------- .../shared/response/EnumControllerTest.java | 2 +- .../shared/response/SharedController.java | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java index e71a24e2..5af89d3f 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -20,15 +20,14 @@ public class QueryGenderRatioUseCase { private final FormRepository formRepository; public List execute(GenderRatioRequest request) { + FormType.Category mainCategory = request.getMainCategory(); List result = new ArrayList<>(); - List subCategories = new ArrayList<>(); - if (request.getMainCategory().equals(FormType.Category.REGULAR)) + if (mainCategory.equals(FormType.Category.REGULAR)) subCategories.add(FormType.Category.REGULAR); - else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) - subCategories.addAll(List.of(FormType.Category.EQUAL_OPPORTUNITY, FormType.Category.SOCIETY_DIVERSITY)); - else subCategories.add(FormType.Category.SUPERNUMERARY); + else if (mainCategory.equals(FormType.Category.SPECIAL)) + subCategories.addAll(List.of(FormType.Category.MEISTER_TALENT, FormType.Category.SOCIAL_INTEGRATION)); Map> formLists = subCategories.stream() .collect(Collectors.toMap( @@ -38,16 +37,22 @@ else if (request.getMainCategory().equals(FormType.Category.SPECIAL)) .collect(Collectors.toList()) )); + if (mainCategory.equals(FormType.Category.SPECIAL)) { + formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.NATIONAL_VETERANS_EDUCATION)); + } else if(mainCategory.equals(FormType.Category.SUPERNUMERARY)) { + formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.SPECIAL_ADMISSION)); + } + for(Map.Entry> entry : formLists.entrySet()) { FormType.Category category = entry.getKey(); List formList = entry.getValue(); long busanMale = formList.stream().filter(this::isBusan).filter(this::isMale).count(); - long busanFeMale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); + long busanFemale = formList.stream().filter(this::isBusan).filter(this::isFemale).count(); long otherLocationMale = formList.stream().filter(this::isNotBusan).filter(this::isMale).count(); long otherLocationFemale = formList.stream().filter(this::isNotBusan).filter(this::isFemale).count(); - result.add(new GenderRatioResponse(category, busanMale, busanFeMale, otherLocationMale, otherLocationFemale)); + result.add(new GenderRatioResponse(category, busanMale, busanFemale, otherLocationMale, otherLocationFemale)); } return result; diff --git a/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java b/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java index 2a383d01..56c80893 100644 --- a/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java +++ b/src/test/java/com/bamdoliro/maru/shared/response/EnumControllerTest.java @@ -63,7 +63,7 @@ void enums() throws Exception { ), customResponseFields("custom-response", beneathPath("gender").withSubsectionId("gender"), - attributes(key("title").value("GraduationType")), + attributes(key("title").value("Gender")), enumConvertFieldDescriptor((enumDocs.getGender())) ), customResponseFields("custom-response", diff --git a/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java b/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java index b3459002..f2d7d2b0 100644 --- a/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java +++ b/src/test/java/com/bamdoliro/maru/shared/response/SharedController.java @@ -36,7 +36,7 @@ public EnumDocs findEnums() { .certificate(getDocs(Certificate.values())) .formStatus(getDocs(FormStatus.values())) .formType(getDocs(FormType.values())) - .gender(getDocs(GraduationType.values())) + .gender(getDocs(Gender.values())) .graduationType(getDocs(GraduationType.values())) .fairStatus(getDocs(FairStatus.values())) .fairType(getDocs(FairType.values())) From 00002e4543613660e8934e5ec2a92325653780aa Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Thu, 20 Jun 2024 23:08:34 +0900 Subject: [PATCH 58/59] =?UTF-8?q?perf(#79):=20=EC=A0=95=EC=9B=90=20?= =?UTF-8?q?=EC=99=B8=20=EC=A0=84=ED=98=95=20=EC=A1=B0=ED=9A=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis/QueryGenderRatioUseCase.java | 14 +++++++------- .../maru/domain/form/domain/type/FormType.java | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java index 5af89d3f..008260e8 100644 --- a/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java +++ b/src/main/java/com/bamdoliro/maru/application/analysis/QueryGenderRatioUseCase.java @@ -27,7 +27,13 @@ public List execute(GenderRatioRequest request) { if (mainCategory.equals(FormType.Category.REGULAR)) subCategories.add(FormType.Category.REGULAR); else if (mainCategory.equals(FormType.Category.SPECIAL)) - subCategories.addAll(List.of(FormType.Category.MEISTER_TALENT, FormType.Category.SOCIAL_INTEGRATION)); + subCategories.addAll(List.of( + FormType.Category.MEISTER_TALENT, + FormType.Category.SOCIAL_INTEGRATION)); + else if (mainCategory.equals(FormType.Category.SUPERNUMERARY)) + subCategories.addAll(List.of( + FormType.Category.NATIONAL_VETERANS_EDUCATION, + FormType.Category.SPECIAL_ADMISSION)); Map> formLists = subCategories.stream() .collect(Collectors.toMap( @@ -37,12 +43,6 @@ else if (mainCategory.equals(FormType.Category.SPECIAL)) .collect(Collectors.toList()) )); - if (mainCategory.equals(FormType.Category.SPECIAL)) { - formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.NATIONAL_VETERANS_EDUCATION)); - } else if(mainCategory.equals(FormType.Category.SUPERNUMERARY)) { - formLists.put(FormType.Category.SUPERNUMERARY, formRepository.findByType(FormType.SPECIAL_ADMISSION)); - } - for(Map.Entry> entry : formLists.entrySet()) { FormType.Category category = entry.getKey(); List formList = entry.getValue(); diff --git a/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java b/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java index 18c9fbfa..fa827815 100644 --- a/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java +++ b/src/main/java/com/bamdoliro/maru/domain/form/domain/type/FormType.java @@ -25,8 +25,8 @@ public enum FormType implements EnumProperty { MULTI_CHILDREN("다자녀가정자녀", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY), FARMING_AND_FISHING("농어촌지역출신자", Category.SPECIAL, Category.SOCIAL_INTEGRATION, Category.SOCIETY_DIVERSITY), - NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀", Category.SUPERNUMERARY, null, null), - SPECIAL_ADMISSION("특례입학대상자", Category.SUPERNUMERARY, null, null), + NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀", Category.SUPERNUMERARY, Category.NATIONAL_VETERANS_EDUCATION, null), + SPECIAL_ADMISSION("특례입학대상자", Category.SUPERNUMERARY, Category.SPECIAL_ADMISSION, null), ; @@ -46,6 +46,8 @@ public enum Category implements EnumProperty { // Middle Category SOCIAL_INTEGRATION("사회통합전형"), MEISTER_TALENT("마이스터인재전형"), + NATIONAL_VETERANS_EDUCATION("국가보훈대상자 중 교육지원대상자녀"), + SPECIAL_ADMISSION("특례입학대상자"), // Sub Category EQUAL_OPPORTUNITY("기회균등전형"), From 148fc4706e6aefeeca5dc798b1eb7f5bb3de86b3 Mon Sep 17 00:00:00 2001 From: cabbage16 Date: Mon, 8 Jul 2024 18:01:44 +0900 Subject: [PATCH 59/59] =?UTF-8?q?test(#79):=20QueryNumberOfApplicantsUseCa?= =?UTF-8?q?seTest=20QueryNumberOfApplicantsUseCaseTest=EB=A5=BC=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QueryNumberOfApplicantsUseCaseTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/test/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCaseTest.java diff --git a/src/test/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCaseTest.java b/src/test/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCaseTest.java new file mode 100644 index 00000000..6da5b580 --- /dev/null +++ b/src/test/java/com/bamdoliro/maru/application/analysis/QueryNumberOfApplicantsUseCaseTest.java @@ -0,0 +1,52 @@ +package com.bamdoliro.maru.application.analysis; + +import com.bamdoliro.maru.domain.form.domain.type.FormType; +import com.bamdoliro.maru.infrastructure.persistence.form.FormRepository; +import com.bamdoliro.maru.infrastructure.persistence.form.vo.NumberOfApplicantsVo; +import com.bamdoliro.maru.presentation.analysis.dto.response.NumberOfApplicantsResponse; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class QueryNumberOfApplicantsUseCaseTest { + + @InjectMocks + private QueryNumberOfApplicantsUseCase queryNumberOfApplicantsUseCase; + + @Mock + private FormRepository formRepository; + + @Test + void 유저가_전형별_지원자_수를_조회한다() { + // given + List voList = List.of( + new NumberOfApplicantsVo(FormType.REGULAR, 1L), + new NumberOfApplicantsVo(FormType.MEISTER_TALENT, 1L), + new NumberOfApplicantsVo(FormType.NATIONAL_BASIC_LIVING, 1L), + new NumberOfApplicantsVo(FormType.FROM_NORTH_KOREA, 1L), + new NumberOfApplicantsVo(FormType.SPECIAL_ADMISSION, 1L) + ); + given(formRepository.findTypeAndCountGroupByType()).willReturn(voList); + + // when + List responseList = queryNumberOfApplicantsUseCase.execute(); + + // then + assertEquals(responseList.size(), FormType.values().length); + assertEquals(responseList + .stream() + .mapToLong(NumberOfApplicantsResponse::getCount) + .sum(), 5L); + + verify(formRepository, times(1)).findTypeAndCountGroupByType(); + } +} \ No newline at end of file