From 553ae098b0af6fd2fca70c9c657a2bcbe53f134e Mon Sep 17 00:00:00 2001 From: BlackBean99 <54030889+BlackBean99@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:14:39 +0900 Subject: [PATCH] =?UTF-8?q?[BE-48]=20Answer=20Read/Write=20CQRS=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20(axon)=20#149=20(#154)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] : CQRS Mongo Async and Command * [feat]: Query CQRS Refactoring ( JPA -> MoongoDB ) * [refactor]: remove unused entity and repository * [feat]: Axon update query logging level disabled --- server/.gradle/7.6.1/checksums/checksums.lock | Bin 17 -> 17 bytes .../executionHistory/executionHistory.bin | Bin 8094814 -> 9188529 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .../.gradle/7.6.1/fileHashes/fileHashes.bin | Bin 260569 -> 262569 bytes .../.gradle/7.6.1/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../7.6.1/fileHashes/resourceHashesCache.bin | Bin 244367 -> 244401 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes server/.gradle/file-system.probe | Bin 8 -> 8 bytes .../applicant/aggregate/AnswerAggregate.java | 46 ++++ .../aggregate/AnswerCreatedEventListener.java | 27 +++ .../command/CreateAnswerCommand.java | 20 ++ .../controller/AnswerController.java | 42 ---- .../controller/ApplicantController.java | 92 ++++---- .../docs/CreateApplicantExceptionDocs.java | 7 + .../docs/ReadApplicantExceptionDocs.java | 13 ++ .../api/applicant/dto/AnswersResponseDto.java | 18 ++ ...icantRegisterEventConfirmEmailHandler.java | 2 +- .../api/applicant/query/AnswerQuery.java | 12 + .../applicant/query/AnswersByYearQuery.java | 11 + .../queryhandler/AnswerQueryHandler.java | 30 +++ .../service/AnswerCommandService.java | 68 ++++++ .../applicant/service/AnswerMongoService.java | 39 ---- .../api/applicant/service/AnswerService.java | 163 -------------- .../applicant/service/ApplicantService.java | 211 +++++++++++------- .../applicant/service/QuestionService.java | 3 +- .../applicant/service/TimeTableService.java | 70 ++---- .../applicant/usecase/AnswerLoadUseCase.java | 25 --- ...Case.java => ApplicantCommandUseCase.java} | 5 +- .../ApplicantMongoRegisterUseCase.java | 9 - .../usecase/ApplicantQueryUseCase.java | 29 +++ .../usecase/ApplicantRegisterUseCase.java | 11 - .../card/controller/BoardRestController.java | 16 +- .../recruit/api/card/service/CardService.java | 17 +- .../api/record/service/RecordService.java | 6 +- .../ApplicantRegisterEventHandler.java | 2 +- .../recruit/utils/AnswerMongoDBMigration.java | 13 +- .../recruit/utils/vo/PageInfo.java | 37 +++ .../src/main/resources/application.yml | 6 +- .../recruitcommon/annotation/TimeTrace.java | 10 + .../recruitcommon/aspect/TimeTraceAspect.java | 29 +++ server/Recruit-Domain/build.gradle | 6 + .../recruitdomain/config/AxonConfig.java | 24 ++ .../applicant/adaptor/AnswerAdaptor.java | 55 ++--- .../domain/AnswerMongoDBRepository.java | 10 - .../domain/AnswerMongoRepository.java | 5 + .../applicant/domain/AnswerRepository.java | 23 -- .../domains/applicant/domain/MongoAnswer.java | 8 +- .../applicant/domain/MongoAnswerAdaptor.java | 24 +- .../aggregateevent/AnswerCreatedEvent.java | 13 ++ .../ApplicantRegisterEvent.java | 2 +- .../exception/ApplicantErrorCode.java | 1 + .../ApplicantWrongPositionException.java | 11 + .../src/main/resources/application-domain.yml | 22 +- server/docker-compose.yml | 22 +- 54 files changed, 713 insertions(+), 602 deletions(-) create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/AnswerAggregate.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/AnswerCreatedEventListener.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/command/CreateAnswerCommand.java delete mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/AnswerController.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/docs/ReadApplicantExceptionDocs.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/dto/AnswersResponseDto.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/AnswerQuery.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/AnswersByYearQuery.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/queryhandler/AnswerQueryHandler.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerCommandService.java delete mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerMongoService.java delete mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerService.java delete mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/AnswerLoadUseCase.java rename server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/{ApplicantMongoLoadUseCase.java => ApplicantCommandUseCase.java} (56%) delete mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantMongoRegisterUseCase.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantQueryUseCase.java delete mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantRegisterUseCase.java create mode 100644 server/Recruit-Api/src/main/java/com/econovation/recruit/utils/vo/PageInfo.java create mode 100644 server/Recruit-Common/src/main/java/com/econovation/recruitcommon/annotation/TimeTrace.java create mode 100644 server/Recruit-Common/src/main/java/com/econovation/recruitcommon/aspect/TimeTraceAspect.java create mode 100644 server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/config/AxonConfig.java delete mode 100644 server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/domain/AnswerMongoDBRepository.java create mode 100644 server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/domain/AnswerMongoRepository.java delete mode 100644 server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/domain/AnswerRepository.java create mode 100644 server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/event/aggregateevent/AnswerCreatedEvent.java rename server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/event/{ => domainevent}/ApplicantRegisterEvent.java (90%) create mode 100644 server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/exception/ApplicantWrongPositionException.java diff --git a/server/.gradle/7.6.1/checksums/checksums.lock b/server/.gradle/7.6.1/checksums/checksums.lock index eeaf46d6ff0ffa821ecd4583fc82a2e3489e8ac5..018b6cfb8d74bf3d280a22b113ea0e926b33f4db 100644 GIT binary patch literal 17 VcmZRsJW-uwYrD0Q0SuV7001z?1b_el literal 17 VcmZRsJW-uwYrD0Q0Sp+Q0st`e1h4=A diff --git a/server/.gradle/7.6.1/executionHistory/executionHistory.bin b/server/.gradle/7.6.1/executionHistory/executionHistory.bin index 310f7056aefff897cd55d25bc49c25f47b3eef68..acf9f7ac262163382b4227cfba43f188b1e8d904 100644 GIT binary patch delta 90637 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 diff --git a/server/.gradle/7.6.1/executionHistory/executionHistory.lock b/server/.gradle/7.6.1/executionHistory/executionHistory.lock index 57e4eac77d702d49935719f03f66456ebaf600ba..0f54dfb5a2ac640dc503686fab3db084c3c9986b 100644 GIT binary patch literal 17 UcmZSnnEFb{yE#yV0SpAB05CEGvj6}9 literal 17 VcmZSnnEFb{yE#yV0Sx$m001!#1dsp# diff --git a/server/.gradle/7.6.1/fileHashes/fileHashes.bin b/server/.gradle/7.6.1/fileHashes/fileHashes.bin index 0bde487058f9a455be9bd70f7cedb80dafbbfbbf..9c98e1ea08928293b22c9e376a407c6d1bec9bda 100644 GIT binary patch delta 3939 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 diff --git a/server/.gradle/7.6.1/fileHashes/fileHashes.lock b/server/.gradle/7.6.1/fileHashes/fileHashes.lock index 420aa00470039ea2e27d62b195af7a1c66edac30..8d7f0d40a2c136b214dfc6a57f9c8c9df899fb7c 100644 GIT binary patch literal 17 UcmZQh3Jcd*uE#0H00teu0Ut2~vH$=8 literal 17 UcmZQh3Jcd*uE#0H00tc?03MnH8vp qna; + // Constructor for creating an AnswerAggregate + @CommandHandler + public AnswerAggregate(CreateAnswerCommand command) { + + apply(new AnswerCreatedEvent(command.getId(), command.getYear(), command.getQna())); + } + + // Event handler for AnswerCreatedEvent + @EventSourcingHandler + public void on(AnswerCreatedEvent event) { + this.id = event.getId(); + this.year = event.getYear(); + this.qna = event.getQna(); + } + + public static AnswerAggregate from(MongoAnswer answer) { + return new AnswerAggregate(answer.getId(), answer.getYear(), answer.getQna()); + } +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/AnswerCreatedEventListener.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/AnswerCreatedEventListener.java new file mode 100644 index 00000000..fec01490 --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/AnswerCreatedEventListener.java @@ -0,0 +1,27 @@ +package com.econovation.recruit.api.applicant.aggregate; + +import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswer; +import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswerAdaptor; +import com.econovation.recruitdomain.domains.applicant.event.aggregateevent.AnswerCreatedEvent; +import lombok.RequiredArgsConstructor; +import org.axonframework.eventhandling.EventHandler; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class AnswerCreatedEventListener { + private final MongoAnswerAdaptor answerAdaptor; + + @EventHandler + public void handle(AnswerCreatedEvent event) { + MongoAnswer answer = + MongoAnswer.builder() + .id(event.getId()) + .year(event.getYear()) + .qna(event.getQna()) + .build(); + answerAdaptor.save(answer); + + // email 전송 event처리 + } +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/command/CreateAnswerCommand.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/command/CreateAnswerCommand.java new file mode 100644 index 00000000..9e57a99e --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/command/CreateAnswerCommand.java @@ -0,0 +1,20 @@ +package com.econovation.recruit.api.applicant.command; + +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.axonframework.modelling.command.TargetAggregateIdentifier; + +@AllArgsConstructor +@ToString +@Data +@NoArgsConstructor +@Getter +public class CreateAnswerCommand { + @TargetAggregateIdentifier private String id; + private Integer year; + private Map qna; +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/AnswerController.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/AnswerController.java deleted file mode 100644 index 99b1dd71..00000000 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/AnswerController.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.econovation.recruit.api.applicant.controller; - -import com.econovation.recruit.api.applicant.docs.CreateApplicantExceptionDocs; -import com.econovation.recruit.api.applicant.usecase.ApplicantMongoLoadUseCase; -import com.econovation.recruit.api.applicant.usecase.ApplicantMongoRegisterUseCase; -import com.econovation.recruitcommon.annotation.ApiErrorExceptionsExample; -import com.econovation.recruitcommon.annotation.XssProtected; -import io.swagger.v3.oas.annotations.Operation; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/api/v1") -@RequiredArgsConstructor -public class AnswerController { - private final ApplicantMongoRegisterUseCase applicantMongoRegisterUseCase; - private final ApplicantMongoLoadUseCase applicantMongoLoadUseCase; - - @Operation(summary = "지원자가 지원서를 작성합니다.", description = "반환 값은 생성된 지원자의 ID입니다.") - @ApiErrorExceptionsExample(CreateApplicantExceptionDocs.class) - @XssProtected - @PostMapping("/register") - public ResponseEntity registerMongoApplicant(@RequestBody Map qna) { - applicantMongoRegisterUseCase.execute(qna); - return new ResponseEntity<>(HttpStatus.OK); - } - - @Operation(summary = "지원자 id로 지원서를 조회합니다.") - @GetMapping("/applicants/mongo/{applicant-id}") - public ResponseEntity> getApplicantById( - @PathVariable(value = "applicant-id") String applicantId) { - return new ResponseEntity<>(applicantMongoLoadUseCase.execute(applicantId), HttpStatus.OK); - } -} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/ApplicantController.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/ApplicantController.java index 38bbdf70..d5d19ee7 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/ApplicantController.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/controller/ApplicantController.java @@ -1,22 +1,19 @@ package com.econovation.recruit.api.applicant.controller; import static com.econovation.recruitcommon.consts.RecruitStatic.APPLICANT_SUCCESS_REGISTER_MESSAGE; -import static com.econovation.recruitcommon.consts.RecruitStatic.QUESTION_SUCCESS_REGISTER_MESSAGE; +import com.econovation.recruit.api.applicant.command.CreateAnswerCommand; import com.econovation.recruit.api.applicant.docs.CreateApplicantExceptionDocs; -import com.econovation.recruit.api.applicant.usecase.AnswerLoadUseCase; -import com.econovation.recruit.api.applicant.usecase.ApplicantRegisterUseCase; -import com.econovation.recruit.api.applicant.usecase.QuestionRegisterUseCase; +import com.econovation.recruit.api.applicant.dto.AnswersResponseDto; +import com.econovation.recruit.api.applicant.usecase.ApplicantQueryUseCase; import com.econovation.recruit.api.applicant.usecase.TimeTableLoadUseCase; import com.econovation.recruit.api.applicant.usecase.TimeTableRegisterUseCase; import com.econovation.recruitcommon.annotation.ApiErrorExceptionsExample; +import com.econovation.recruitcommon.annotation.TimeTrace; import com.econovation.recruitcommon.annotation.XssProtected; -import com.econovation.recruitdomain.domains.applicant.dto.BlockRequestDto; import com.econovation.recruitdomain.domains.applicant.dto.TimeTableVo; import com.econovation.recruitdomain.domains.applicant.exception.ApplicantOutOfDateException; -import com.econovation.recruitdomain.domains.dto.ApplicantPaginationResponseDto; import com.econovation.recruitdomain.domains.dto.EmailSendDto; -import com.econovation.recruitdomain.domains.dto.QuestionRequestDto; import com.econovation.recruitdomain.domains.timetable.domain.TimeTable; import com.econovation.recruitinfrastructure.apache.CommonsEmailSender; import io.swagger.v3.oas.annotations.Operation; @@ -27,9 +24,9 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import javax.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.axonframework.commandhandling.gateway.CommandGateway; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -45,23 +42,48 @@ @Slf4j @Tag(name = "[1.0]. 지원서 API", description = "지원서 관련 API") public class ApplicantController { - private final ApplicantRegisterUseCase applicantRegisterUseCase; private final TimeTableRegisterUseCase timeTableRegisterUseCase; private final TimeTableLoadUseCase timeTableLoadUseCase; - private final QuestionRegisterUseCase questionRegisterUseCase; - private final AnswerLoadUseCase answerLoadUseCase; + private final ApplicantQueryUseCase applicantQueryUseCase; private final CommonsEmailSender commonsEmailSender; + private final CommandGateway commandGateway; @Operation(summary = "지원자가 지원서를 작성합니다.", description = "반환 값은 생성된 지원자의 ID입니다.") @ApiErrorExceptionsExample(CreateApplicantExceptionDocs.class) @XssProtected @PostMapping("/applicants") - public ResponseEntity registerApplicant( - @RequestBody @Valid List blockElements) { - // validateOutdated(); - UUID applicantId = applicantRegisterUseCase.execute(blockElements); - return new ResponseEntity<>(applicantId, HttpStatus.OK); + @TimeTrace + public ResponseEntity registerMongoApplicant(@RequestBody Map qna) { + // validateOutdated(); + commandGateway.send(new CreateAnswerCommand(UUID.randomUUID().toString(), 21, qna)); + return new ResponseEntity<>(APPLICANT_SUCCESS_REGISTER_MESSAGE, HttpStatus.OK); + } + + @Operation(summary = "지원자 id로 지원서를 조회합니다.") + @TimeTrace + @ApiErrorExceptionsExample(CreateApplicantExceptionDocs.class) + @GetMapping("/applicants/{applicant-id}") + public ResponseEntity> getApplicantById( + @PathVariable(value = "applicant-id") String applicantId) { + return new ResponseEntity<>(applicantQueryUseCase.execute(applicantId), HttpStatus.OK); + } + + @Operation(summary = "지원자 기수로 지원서를 조회합니다. / page는 1부터 시작합니다.") + @TimeTrace + @GetMapping("/page/{page}/year/{year}/applicants") + public ResponseEntity getApplicantsByYear( + @PathVariable(value = "year") Integer year, + @PathVariable(value = "page") Integer page) { + return new ResponseEntity<>(applicantQueryUseCase.execute(year, page), HttpStatus.OK); + } + + @Operation(summary = "모든 지원자의 지원서를 조회합니다.") + @TimeTrace + @GetMapping("/applicants") + public ResponseEntity>> getApplicants() { + return new ResponseEntity<>(applicantQueryUseCase.execute(), HttpStatus.OK); } + // ------------------------------ private void validateOutdated() { // 현재 한국 시간 가져오기 @@ -80,46 +102,19 @@ private void validateOutdated() { } } - @Operation(summary = "지원자 id로 지원서를 조회합니다.") - @GetMapping("/applicants/{applicant-id}") - public ResponseEntity> getApplicantById( - @PathVariable(value = "applicant-id") String applicantId) { - return new ResponseEntity<>(answerLoadUseCase.execute(applicantId), HttpStatus.OK); - } - - @Operation(summary = "모든 지원자의 지원서를 조회합니다.") - @GetMapping("/applicants") - public ResponseEntity>> getApplicants() { - return new ResponseEntity<>(answerLoadUseCase.execute(), HttpStatus.OK); - } - - @Operation(summary = "모든 지원자의 지원서를 페이지 단위로(1페이지당 8개) 조회합니다.") - @GetMapping("/page/{page}/applicants") - public ResponseEntity getApplicantsByPage( - // TODO 정렬 기준 추가 - @PathVariable(value = "page") Integer page) { - return new ResponseEntity<>(answerLoadUseCase.execute(page), HttpStatus.OK); - } - @Operation(summary = "지원자가 면접 가능 시간을 작성합니다.") @ApiErrorExceptionsExample(CreateApplicantExceptionDocs.class) + @TimeTrace @PostMapping("/applicants/{applicant-id}/timetables") public ResponseEntity registerApplicantTimeTable( - @PathVariable(value = "applicant-id") UUID applicantId, + @PathVariable(value = "applicant-id") String applicantId, @RequestBody List startTimes) { - timeTableRegisterUseCase.execute(applicantId.toString(), startTimes); + timeTableRegisterUseCase.execute(applicantId, startTimes); return new ResponseEntity<>(APPLICANT_SUCCESS_REGISTER_MESSAGE, HttpStatus.OK); } - @Operation(summary = "면접관이 면접 질문을 추가합니다.") - @PostMapping("/questions") - public ResponseEntity registerInterviewQuestion( - @RequestBody List questions) { - questionRegisterUseCase.execute(questions); - return new ResponseEntity<>(QUESTION_SUCCESS_REGISTER_MESSAGE, HttpStatus.OK); - } - @Operation(summary = "모든 면접 가능 시간을 조회합니다.") + @TimeTrace @GetMapping("/timetables") public ResponseEntity>>> getTimeTables() { return new ResponseEntity(timeTableLoadUseCase.findAll(), HttpStatus.OK); @@ -127,6 +122,7 @@ public ResponseEntity>>> getTimeTables() { @Operation(summary = "지원자의 면접 가능 시간을 조회합니다.") @GetMapping("/applicants/{applicant-id}/timetables") + @TimeTrace public ResponseEntity> getTimeTables( @PathVariable(name = "applicant-id") String applicantId) { List timeTableDto = timeTableLoadUseCase.getTimeTableByApplicantId(applicantId); @@ -134,6 +130,7 @@ public ResponseEntity> getTimeTables( } @Operation(summary = "면접 가능 시간마다 일치하는 지원자의 정보(희망분야, 이름)를 조회합니다.") + @TimeTrace @GetMapping("/timetables/applicants") public ResponseEntity>> getApplicantsByTimeTable() { return new ResponseEntity( @@ -141,6 +138,7 @@ public ResponseEntity>> getApplicantsByTimeTable() { } @Operation(summary = "지원서 제출한 html을 email 로 전송합니다.") + @TimeTrace @PostMapping("/applicants/mail") public ResponseEntity sendEmail(@RequestBody EmailSendDto emailSendDto) { commonsEmailSender.send(emailSendDto.getEmail(), emailSendDto.getApplicantId()); diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/docs/CreateApplicantExceptionDocs.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/docs/CreateApplicantExceptionDocs.java index 0c90f1cb..ca61062d 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/docs/CreateApplicantExceptionDocs.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/docs/CreateApplicantExceptionDocs.java @@ -5,9 +5,16 @@ import com.econovation.recruitcommon.exception.RecruitCodeException; import com.econovation.recruitcommon.interfaces.SwaggerExampleExceptions; import com.econovation.recruitdomain.domains.applicant.exception.ApplicantDuplicateSubmitException; +import com.econovation.recruitdomain.domains.applicant.exception.ApplicantWrongPositionException; @ExceptionDoc public class CreateApplicantExceptionDocs implements SwaggerExampleExceptions { @ExplainError("지원서를 중복으로 제출했을 경우") public RecruitCodeException 지원서_중복_제출 = ApplicantDuplicateSubmitException.EXCEPTION; + + @ExplainError("지원서를 잘못된 포지션으로 제출했을 경우") + public RecruitCodeException 지원서_지원_포지션_오류 = ApplicantWrongPositionException.EXCEPTION; + + @ExplainError("지원서를 중복으로 제출했을 경우") + public RecruitCodeException 지원서_중복_제출_예외 = ApplicantDuplicateSubmitException.EXCEPTION; } diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/docs/ReadApplicantExceptionDocs.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/docs/ReadApplicantExceptionDocs.java new file mode 100644 index 00000000..68eeccac --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/docs/ReadApplicantExceptionDocs.java @@ -0,0 +1,13 @@ +package com.econovation.recruit.api.applicant.docs; + +import com.econovation.recruitcommon.annotation.ExceptionDoc; +import com.econovation.recruitcommon.annotation.ExplainError; +import com.econovation.recruitcommon.exception.RecruitCodeException; +import com.econovation.recruitcommon.interfaces.SwaggerExampleExceptions; +import com.econovation.recruitdomain.domains.applicant.exception.ApplicantDuplicateSubmitException; + +@ExceptionDoc +public class ReadApplicantExceptionDocs implements SwaggerExampleExceptions { + @ExplainError("지원서를 중복으로 제출했을 경우") + public RecruitCodeException 지원서_중복_제출_예외 = ApplicantDuplicateSubmitException.EXCEPTION; +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/dto/AnswersResponseDto.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/dto/AnswersResponseDto.java new file mode 100644 index 00000000..82652b29 --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/dto/AnswersResponseDto.java @@ -0,0 +1,18 @@ +package com.econovation.recruit.api.applicant.dto; + +import com.econovation.recruit.utils.vo.PageInfo; +import java.util.List; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class AnswersResponseDto { + private PageInfo pageInfo; + private List> answers; + + public static AnswersResponseDto of(List> list, PageInfo pageInfo) { + return new AnswersResponseDto(pageInfo, list); + } +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantRegisterEventConfirmEmailHandler.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantRegisterEventConfirmEmailHandler.java index 0e9e5d51..6aae477f 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantRegisterEventConfirmEmailHandler.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantRegisterEventConfirmEmailHandler.java @@ -1,7 +1,7 @@ package com.econovation.recruit.api.applicant.handler; import com.econovation.recruit.api.user.helper.NcpMailHelper; -import com.econovation.recruitdomain.domains.applicant.event.ApplicantRegisterEvent; +import com.econovation.recruitdomain.domains.applicant.event.domainevent.ApplicantRegisterEvent; import com.econovation.recruitinfrastructure.apache.CommonsEmailSender; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/AnswerQuery.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/AnswerQuery.java new file mode 100644 index 00000000..39ce20fc --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/AnswerQuery.java @@ -0,0 +1,12 @@ +package com.econovation.recruit.api.applicant.query; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AnswerQuery { + private String answerId; +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/AnswersByYearQuery.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/AnswersByYearQuery.java new file mode 100644 index 00000000..9dc66099 --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/AnswersByYearQuery.java @@ -0,0 +1,11 @@ +package com.econovation.recruit.api.applicant.query; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class AnswersByYearQuery { + private Integer year; + private Integer page; +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/queryhandler/AnswerQueryHandler.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/queryhandler/AnswerQueryHandler.java new file mode 100644 index 00000000..dcd9068f --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/query/queryhandler/AnswerQueryHandler.java @@ -0,0 +1,30 @@ +package com.econovation.recruit.api.applicant.query.queryhandler; + +import com.econovation.recruit.api.applicant.aggregate.AnswerAggregate; +import com.econovation.recruit.api.applicant.query.AnswerQuery; +import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswer; +import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswerAdaptor; +import lombok.RequiredArgsConstructor; +import org.axonframework.queryhandling.QueryHandler; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class AnswerQueryHandler { + private final MongoAnswerAdaptor answerAdaptor; + + @QueryHandler + public AnswerAggregate handle(AnswerQuery query) { + MongoAnswer result = + answerAdaptor + .findById(query.getAnswerId()) + .fold( + (exception) -> { + throw exception; + }, + (answer) -> { + return answer; + }); + return new AnswerAggregate(result.getId(), result.getYear(), result.getQna()); + } +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerCommandService.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerCommandService.java new file mode 100644 index 00000000..5c273b24 --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerCommandService.java @@ -0,0 +1,68 @@ +package com.econovation.recruit.api.applicant.service; + +import com.econovation.recruit.api.applicant.usecase.ApplicantCommandUseCase; +import com.econovation.recruitcommon.exception.RecruitCodeException; +import com.econovation.recruitdomain.common.aop.domainEvent.Events; +import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswer; +import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswerAdaptor; +import com.econovation.recruitdomain.domains.applicant.event.domainevent.ApplicantRegisterEvent; +import com.econovation.recruitdomain.domains.applicant.exception.ApplicantDuplicateSubmitException; +import com.econovation.recruitdomain.domains.applicant.exception.ApplicantWrongPositionException; +import io.vavr.collection.Seq; +import io.vavr.control.Validation; +import java.util.Map; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AnswerCommandService implements ApplicantCommandUseCase { + private final MongoAnswerAdaptor answerAdaptor; + + @Value("${econovation.year}") + private Integer year; + + @Override + public UUID execute(Map qna) { + UUID id = UUID.randomUUID(); + MongoAnswer answer = MongoAnswer.builder().id(id.toString()).qna(qna).year(year).build(); + // 학번으로 중복 체크 + validateRegisterApplicant(qna); + answerAdaptor.save(answer); + + String name = qna.get("name").toString(); + String hopeField = qna.get("field").toString(); + String email = qna.get("email").toString(); + + ApplicantRegisterEvent applicantRegisterEvent = + ApplicantRegisterEvent.of(answer.getId(), name, hopeField, email); + Events.raise(applicantRegisterEvent); + return id; + } + + private Validation, Map> validateRegisterApplicant( + Map qna) { + return Validation.combine(validateDuplicateSudentId(qna), validateIsRightPosition(qna)) + .ap((a, b) -> qna); + } + + private Validation validateIsRightPosition( + Map qna) { + String field = qna.get("field").toString(); + if (field.equals("기획자") || field.equals("개발자") || field.equals("디자이너")) { + return Validation.valid(qna); + } + throw ApplicantWrongPositionException.EXCEPTION; + } + + private Validation> validateDuplicateSudentId( + Map qna) { + String studentId = qna.get("classOf").toString(); + if (answerAdaptor.existsByAnswer(studentId, year)) { + throw ApplicantDuplicateSubmitException.EXCEPTION; + } + return Validation.valid(qna); + } +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerMongoService.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerMongoService.java deleted file mode 100644 index 86f2d0b3..00000000 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerMongoService.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.econovation.recruit.api.applicant.service; - -import com.econovation.recruit.api.applicant.usecase.ApplicantMongoLoadUseCase; -import com.econovation.recruit.api.applicant.usecase.ApplicantMongoRegisterUseCase; -import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswer; -import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswerAdaptor; -import java.util.Map; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class AnswerMongoService - implements ApplicantMongoRegisterUseCase, ApplicantMongoLoadUseCase { - private final MongoAnswerAdaptor answerAdaptor; - - @Value("${econovation.year}") - private Integer year; - - @Override - public void execute(Map qna) { - MongoAnswer answer = MongoAnswer.builder().qna(qna).year(year).build(); - answerAdaptor.save(answer); - } - - @Override - public Map execute(String applicantId) { - return answerAdaptor - .findById(applicantId) - .fold( - (exception) -> { - throw exception; - }, - (answer) -> { - return answer.getQna(); - }); - } -} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerService.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerService.java deleted file mode 100644 index 0faa80a9..00000000 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/AnswerService.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.econovation.recruit.api.applicant.service; - -import static com.econovation.recruitcommon.consts.RecruitStatic.COUNTS_PER_PAGE; - -import com.econovation.recruit.api.applicant.usecase.AnswerLoadUseCase; -import com.econovation.recruitcommon.exception.OutOfIndexException; -import com.econovation.recruitdomain.domains.applicant.adaptor.AnswerAdaptor; -import com.econovation.recruitdomain.domains.applicant.domain.Answer; -import com.econovation.recruitdomain.domains.dto.ApplicantPaginationResponseDto; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class AnswerService implements AnswerLoadUseCase { - private final AnswerAdaptor answerAdaptor; - - @Override - public Map execute(String applicantId) { - List answers = answerAdaptor.findByAnswerId(applicantId); - HashMap collect = - answers.stream() - .collect( - Collectors.toMap( - answer -> answer.getQuestion().getName(), - Answer::getAnswer, - (existing, replacement) -> existing, - LinkedHashMap::new)); - - LinkedHashMap result = new LinkedHashMap<>(); - result.put("id", applicantId); - result.putAll(collect); - - return result; - } - - @Override - public List> execute(List fields) { - List answers = answerAdaptor.findAll(); - return splitByAnswersInApplicantId(fields, answers); - } - - @Override - public Map> findAllApplicantVo(List fields) { - List answers = answerAdaptor.findAll(); - if (answers.isEmpty()) { - return Collections.emptyMap(); - } - return answers.stream() - .filter(answer -> fields.contains(answer.getQuestion().getName())) - .collect( - Collectors.groupingBy( - Answer::getApplicantId, - Collectors.toMap( - answer -> answer.getQuestion().getName(), - Answer::getAnswer, - (existing, replacement) -> existing, - HashMap::new))); - } - - private List> splitByAnswersInApplicantId( - List fields, List answers) { - return answers.stream() - .collect( - Collectors.groupingBy( - Answer::getApplicantId, - Collectors.toMap( - answer -> answer.getQuestion().getName(), - Answer::getAnswer, - (existing, replacement) -> existing, - HashMap::new))) - .entrySet() - .stream() - .map( - entry -> { - HashMap map = new HashMap<>(); - map.put("id", entry.getKey()); - fields.forEach( - field -> { - if (entry.getValue().containsKey(field)) { - map.put(field, entry.getValue().get(field)); - } else { - map.put(field, ""); - } - }); - return map; - }) - .collect(Collectors.toList()); - } - - private List> splitByAnswersInApplicantId(List answers) { - // First, group the answers by applicant ID - Map> grouped = - answers.stream().collect(Collectors.groupingBy(Answer::getApplicantId)); - - // ApplicantId (지원자) 별로 그룹화 한 후에 CreatedAt으로 오름차순 정렬하여 Map을 생성한다 - return grouped.entrySet().stream() - .sorted( - Comparator.comparing( - e -> - e.getValue().stream() - .max(Comparator.comparing(Answer::getCreatedAt)) - .get() - .getCreatedAt())) - .map( - entry -> { - LinkedHashMap map = new LinkedHashMap<>(); - map.put("id", entry.getKey()); - entry.getValue() - .forEach( - answer -> - map.put( - answer.getQuestion().getName(), - answer.getAnswer())); - return map; - }) - .collect(Collectors.toList()); - } - - @Override - public List> execute(List fields, List applicantIds) { - List answers = answerAdaptor.findByAnswerIds(applicantIds); - return splitByAnswersInApplicantId(fields, answers); - } - - @Override - public List> execute() { - List answers = answerAdaptor.findAll(); - return splitByAnswersInApplicantId(answers); - } - - @Override - public ApplicantPaginationResponseDto execute(Integer page) { - if (page < 1) throw OutOfIndexException.EXCEPTION; - List answers = answerAdaptor.findAll(); - - List> results = splitByAnswersInApplicantId(answers); - Integer maxPage = results.size() / COUNTS_PER_PAGE; - results = - results.stream() - .skip((page - 1) * COUNTS_PER_PAGE) - .limit(COUNTS_PER_PAGE) - .collect(Collectors.toList()); - // maxPage - return ApplicantPaginationResponseDto.builder() - .applicants(results) - .maxPage(maxPage + 1) - .build(); - } - - @Override - public Map execute(String applicantId, List fields) { - List answers = answerAdaptor.findByAnswerId(applicantId); - return splitByAnswersInApplicantId(fields, answers).get(0); - } -} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/ApplicantService.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/ApplicantService.java index 05fb0037..88820d2d 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/ApplicantService.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/ApplicantService.java @@ -1,103 +1,148 @@ package com.econovation.recruit.api.applicant.service; -import com.econovation.recruit.api.applicant.usecase.ApplicantRegisterUseCase; -import com.econovation.recruitcommon.utils.Result; -import com.econovation.recruitdomain.common.aop.domainEvent.Events; +import com.econovation.recruit.api.applicant.aggregate.AnswerAggregate; +import com.econovation.recruit.api.applicant.dto.AnswersResponseDto; +import com.econovation.recruit.api.applicant.query.AnswerQuery; +import com.econovation.recruit.api.applicant.usecase.ApplicantQueryUseCase; +import com.econovation.recruit.utils.vo.PageInfo; import com.econovation.recruitdomain.domains.applicant.adaptor.AnswerAdaptor; -import com.econovation.recruitdomain.domains.applicant.adaptor.QuestionAdaptor; -import com.econovation.recruitdomain.domains.applicant.domain.Answer; -import com.econovation.recruitdomain.domains.applicant.domain.Question; -import com.econovation.recruitdomain.domains.applicant.dto.BlockRequestDto; -import com.econovation.recruitdomain.domains.applicant.event.ApplicantRegisterEvent; -import com.econovation.recruitdomain.domains.applicant.exception.AnswerEmptyFieldException; -import com.econovation.recruitdomain.domains.applicant.exception.ApplicantDuplicateSubmitException; -import com.econovation.recruitdomain.domains.applicant.exception.QuestionNotFoundException; +import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswer; +import java.util.Collections; +import java.util.HashMap; import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; +import java.util.Map; import lombok.RequiredArgsConstructor; +import org.axonframework.messaging.responsetypes.ResponseTypes; +import org.axonframework.queryhandling.QueryGateway; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor -public class ApplicantService implements ApplicantRegisterUseCase { - private final QuestionAdaptor questionAdaptor; +public class ApplicantService implements ApplicantQueryUseCase { private final AnswerAdaptor answerAdaptor; + private final QueryGateway queryGateway; + + @Value("${econovation.year}") + private Integer year; + + @Transactional(readOnly = true) + public Map execute(String answerId) { + Map qna = + queryGateway + .query( + new AnswerQuery(answerId), + ResponseTypes.instanceOf(AnswerAggregate.class)) + .join() + .getQna(); + qna.put("id", answerId); + return qna; + } + + @Transactional(readOnly = true) + public AnswersResponseDto execute(Integer year, Integer page) { + long totalCount = answerAdaptor.getTotalCountByYear(year); + PageInfo pageInfo = new PageInfo(totalCount, page); + List> qnas = + answerAdaptor.findByYear(year, page).stream().map(MongoAnswer::getQna).toList(); + return AnswersResponseDto.of(qnas, pageInfo); + } + + @Override + public List> execute(List fields, Integer year, Integer page) { + AnswersResponseDto execute = execute(year, page); + return splitByAnswerFilteredByFields(fields, execute.getAnswers()); + } @Override - @Transactional - public UUID execute(List blocks) { - List questions = questionAdaptor.findAll(); - UUID applicantId = UUID.randomUUID(); + public Map> findAllApplicantVo(List fields) { + List answers = answerAdaptor.findAll(); + Map> result = new HashMap<>(); + if (answers.isEmpty()) { + return Collections.emptyMap(); + } + answers.stream() + .forEach( + answer -> { + Map map = new HashMap<>(); + fields.forEach( + field -> { + if (answer.getQna().containsKey(field)) { + map.put(field, answer.getQna().get(field)); + } + }); + result.put(answer.getId(), map); + }); + return result; + } - List results = - blocks.stream() - .map( - block -> { - Result matchingQuestionResult = - questions.stream() - .filter( - question -> - question.getName() - .equals( - block - .getName())) - .findFirst() - .map(Result::success) - .orElseThrow( - () -> - QuestionNotFoundException - .EXCEPTION); - return matchingQuestionResult - .map( - question -> - Answer.builder() - .question(question) - .answer(block.getAnswer()) - .applicantId( - applicantId.toString()) - .build()) - .getValue(); - }) - .collect(Collectors.toList()); - // classOf 가 기존에 존재하면 중복된 지원자 입니다. - String studentId = - results.stream() - .filter(answer -> answer.getQuestion().getName().equals("classOf")) - .findFirst() - .get() - .getAnswer(); + private List> splitByAnswerFilteredByFields( + List fields, List> answers) { + return answers.stream() + .map( + answer -> { + Map map = new HashMap<>(); + fields.forEach( + field -> { + if (answer.containsKey(field)) { + map.put(field, answer.get(field)); + } else { + map.put(field, ""); + } + }); + return map; + }) + .toList(); + } - // 이미 제출한 학생은 중복 지원자입니다. (학번으로 검증) - if (answerAdaptor.findByAnswer(studentId) != null) - throw ApplicantDuplicateSubmitException.EXCEPTION; + private List> splitByAnswers( + List fields, List answers) { + return answers.stream() + .map( + answer -> { + Map map = new HashMap<>(); + map.put("id", answer.getId()); + fields.forEach( + field -> { + if (answer.getQna().containsKey(field)) { + map.put(field, answer.getQna().get(field).toString()); + } + }); + return map; + }) + .toList(); + } - // Result 를 save 하게 된다. - answerAdaptor.saveAll(results); + @Override + public List> execute() { + List answers = answerAdaptor.findAll(); + return answers.stream() + .map( + answer -> { + Map map = new HashMap<>(); + map.put("id", answer.getId()); + map.putAll(answer.getQna()); + return map; + }) + .toList(); + } - String hopeField = - results.stream() - .filter(answer -> answer.getQuestion().getName().equals("field")) - .findFirst() - .map(Answer::getAnswer) - .orElseThrow(() -> AnswerEmptyFieldException.EXCEPTION); + @Override + public Map execute(String applicantId, List fields) { + AnswerAggregate join = + queryGateway + .query( + new AnswerQuery(applicantId), + ResponseTypes.instanceOf(AnswerAggregate.class)) + .join(); + MongoAnswer mongoAnswer = new MongoAnswer(join.getId(), join.getYear(), join.getQna()); + return splitByAnswers(fields, List.of(mongoAnswer)).get(0); + } - String name = - results.stream() - .filter(answer -> answer.getQuestion().getName().equals("name")) - .findFirst() - .map(Answer::getAnswer) - .orElseThrow(() -> AnswerEmptyFieldException.EXCEPTION); - String email = - results.stream() - .filter(answer -> answer.getQuestion().getName().equals("email")) - .findFirst() - .map(Answer::getAnswer) - .orElseThrow(() -> AnswerEmptyFieldException.EXCEPTION); - ApplicantRegisterEvent applicantRegisterEvent = - ApplicantRegisterEvent.of(applicantId.toString(), name, hopeField, email); - Events.raise(applicantRegisterEvent); - return applicantId; + @Override + public List> execute(List fields, Integer page) { + List byYear = answerAdaptor.findByYear(year, page); + return splitByAnswers(fields, byYear); } } diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/QuestionService.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/QuestionService.java index 77c78044..27e6f9d2 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/QuestionService.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/QuestionService.java @@ -5,7 +5,6 @@ import com.econovation.recruitdomain.domains.applicant.domain.Question; import com.econovation.recruitdomain.domains.dto.QuestionRequestDto; import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -42,7 +41,7 @@ public void execute(List questions) { .name(question.getName()) .parentId(question.getParentId()) .build()) - .collect(Collectors.toList()); + .toList(); questionAdaptor.saveAll(filteredQuestions); } } diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/TimeTableService.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/TimeTableService.java index c5628d90..e2c7983a 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/TimeTableService.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/service/TimeTableService.java @@ -2,6 +2,7 @@ import static com.econovation.recruitcommon.consts.RecruitStatic.TIMETABLE_APPLICANT_FIELD; +import com.econovation.recruit.api.applicant.usecase.ApplicantQueryUseCase; import com.econovation.recruit.api.applicant.usecase.TimeTableLoadUseCase; import com.econovation.recruit.api.applicant.usecase.TimeTableRegisterUseCase; import com.econovation.recruitdomain.domains.applicant.dto.TimeTableVo; @@ -9,7 +10,6 @@ import com.econovation.recruitdomain.domains.timetable.exception.TimeTableNotFoundException; import com.econovation.recruitdomain.out.TimeTableLoadPort; import com.econovation.recruitdomain.out.TimeTableRecordPort; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -23,7 +23,7 @@ public class TimeTableService implements TimeTableRegisterUseCase, TimeTableLoadUseCase { private final TimeTableLoadPort timeTableLoadPort; private final TimeTableRecordPort timeTableRecordPort; - private final AnswerService answerService; + private final ApplicantQueryUseCase applicantQueryUseCase; @Override @Transactional(readOnly = true) @@ -46,7 +46,7 @@ public List>> findAll() { entry -> { return Map.of(entry.getKey(), entry.getValue()); }) - .collect(Collectors.toList()); + .toList(); } @Override @@ -55,9 +55,7 @@ public List getTimeTableByApplicantId(String applicantId) { List timeTableByApplicantId = timeTableLoadPort.getTimeTableByApplicantId(applicantId); if (!timeTableByApplicantId.isEmpty()) { - return timeTableByApplicantId.stream() - .map(TimeTable::getStartTime) - .collect(Collectors.toList()); + return timeTableByApplicantId.stream().map(TimeTable::getStartTime).toList(); } throw TimeTableNotFoundException.EXCEPTION; } @@ -66,51 +64,27 @@ public List getTimeTableByApplicantId(String applicantId) { @Transactional(readOnly = true) public Map> findAllSimpleApplicantWithTimeTable() { List timeTables = timeTableLoadPort.findAll(); - Map> allApplicantVo = - answerService.findAllApplicantVo(TIMETABLE_APPLICANT_FIELD); + Map> allApplicantVo = + applicantQueryUseCase.findAllApplicantVo(TIMETABLE_APPLICANT_FIELD); // SimpleApplicant : {applicantId : {name(이름), field(지원분야) } - Map> collect = - timeTables.stream() - .collect( - Collectors.groupingBy( - TimeTable::getStartTime, - Collectors.mapping( - timeTable -> { - return "[" - + allApplicantVo - .get(timeTable.getApplicantId()) - .get("field") - + "] : " - + allApplicantVo - .get(timeTable.getApplicantId()) - .get("name"); - }, - Collectors.toList()))); - return collect; + return timeTables.stream() + .collect( + Collectors.groupingBy( + TimeTable::getStartTime, + Collectors.mapping( + timeTable -> { + return "[" + + allApplicantVo + .get(timeTable.getApplicantId()) + .get("field") + + "] : " + + allApplicantVo + .get(timeTable.getApplicantId()) + .get("name"); + }, + Collectors.toList()))); } - /* private List toList(HashMap param) { - List chunkTimeTable = new LinkedList<>(); - Gson gson = new Gson(); - // JsonParser Deprecated -> JsonParser static import 변경 - JsonElement startTime = JsonParser.parseString(param.get("startTime").toString()); - JsonElement endTime = JsonParser.parseString(param.get("endTime").toString()); - JsonElement day = JsonParser.parseString(param.get("day").toString()); - // JsonElement -> List으로 파싱 - - List startTimes = - gson.fromJson(startTime, (new TypeToken>() {}).getType()); - List endTimes = - gson.fromJson(endTime, (new TypeToken>() {}).getType()); - List days = gson.fromJson(day, (new TypeToken>() {}).getType()); - - for (int i = 0; i < startTimes.size(); i++) { - chunkTimeTable.add( - new TimeTableInsertDto(startTimes.get(i))); - } - return chunkTimeTable; - }*/ - @Override public void execute(String applicantId, List startTimes) { List timeTableList = new LinkedList<>(); diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/AnswerLoadUseCase.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/AnswerLoadUseCase.java deleted file mode 100644 index b5dd765d..00000000 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/AnswerLoadUseCase.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.econovation.recruit.api.applicant.usecase; - -import com.econovation.recruitcommon.annotation.UseCase; -import com.econovation.recruitdomain.domains.dto.ApplicantPaginationResponseDto; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@UseCase -public interface AnswerLoadUseCase { - Map execute(String applicantId); - - List> execute(List fields, List applicantIds); - - List> execute(); - - ApplicantPaginationResponseDto execute(Integer page); - // List> execute(Integer page, String sortType); - - Map execute(String applicantId, List fields); - - List> execute(List fields); - - Map> findAllApplicantVo(List fields); -} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantMongoLoadUseCase.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantCommandUseCase.java similarity index 56% rename from server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantMongoLoadUseCase.java rename to server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantCommandUseCase.java index 38c2bdda..eb69f371 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantMongoLoadUseCase.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantCommandUseCase.java @@ -2,8 +2,9 @@ import com.econovation.recruitcommon.annotation.UseCase; import java.util.Map; +import java.util.UUID; @UseCase -public interface ApplicantMongoLoadUseCase { - Map execute(String applicantId); +public interface ApplicantCommandUseCase { + UUID execute(Map blocks); } diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantMongoRegisterUseCase.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantMongoRegisterUseCase.java deleted file mode 100644 index af780b2c..00000000 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantMongoRegisterUseCase.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.econovation.recruit.api.applicant.usecase; - -import com.econovation.recruitcommon.annotation.UseCase; -import java.util.Map; - -@UseCase -public interface ApplicantMongoRegisterUseCase { - void execute(Map blocks); -} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantQueryUseCase.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantQueryUseCase.java new file mode 100644 index 00000000..2ef30e18 --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantQueryUseCase.java @@ -0,0 +1,29 @@ +package com.econovation.recruit.api.applicant.usecase; + +import com.econovation.recruit.api.applicant.dto.AnswersResponseDto; +import com.econovation.recruitcommon.annotation.UseCase; +import java.util.List; +import java.util.Map; + +@UseCase +public interface ApplicantQueryUseCase { + // clear + Map execute(String applicantId); + + AnswersResponseDto execute(Integer year, Integer page); + // List> execute(List fields, List applicantIds); + + List> execute(); + + // ApplicantPaginationResponseDto execute(Integer page); + + // List> execute(Integer page, String sortType); + + Map execute(String applicantId, List fields); + + List> execute(List fields, Integer page); + + List> execute(List fields, Integer year, Integer page); + + Map> findAllApplicantVo(List fields); +} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantRegisterUseCase.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantRegisterUseCase.java deleted file mode 100644 index 20c73970..00000000 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantRegisterUseCase.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.econovation.recruit.api.applicant.usecase; - -import com.econovation.recruitcommon.annotation.UseCase; -import com.econovation.recruitdomain.domains.applicant.dto.BlockRequestDto; -import java.util.List; -import java.util.UUID; - -@UseCase -public interface ApplicantRegisterUseCase { - UUID execute(List blocks); -} diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/card/controller/BoardRestController.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/card/controller/BoardRestController.java index 5bef396a..7bcd6366 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/card/controller/BoardRestController.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/card/controller/BoardRestController.java @@ -2,7 +2,7 @@ import static com.econovation.recruitcommon.consts.RecruitStatic.*; -import com.econovation.recruit.api.applicant.usecase.AnswerLoadUseCase; +import com.econovation.recruit.api.applicant.usecase.ApplicantQueryUseCase; import com.econovation.recruit.api.card.docs.CreateBoardExceptionDocs; import com.econovation.recruit.api.card.docs.CreateColumnsExceptionDocs; import com.econovation.recruit.api.card.docs.CreateNavigationExceptionDocs; @@ -54,7 +54,7 @@ public class BoardRestController { private final CardRegisterUseCase cardRegisterUseCase; private final CardLoadUseCase cardLoadUseCase; private final NavigationUseCase navigationUseCase; - private final AnswerLoadUseCase answerLoadUseCase; + private final ApplicantQueryUseCase answerQueryUseCase; // ---------- Navigation ---------- @Operation(summary = "네비게이션 바 생성", description = "카드 생성 전에 네비게이션 바를 생성하셔야 합니다.") @ApiErrorExceptionsExample(value = CreateNavigationExceptionDocs.class) @@ -174,10 +174,10 @@ public ResponseEntity> getBoardByNavigationId( @Operation(summary = "지원서 조회(원하는 field) 만 조회", description = "원하는 field만(리스트) 조회합니다.") @ApiErrorExceptionsExample(FindBoardExceptionDocs.class) - @PostMapping("/boards") - public ResponseEntity>> getBoardByNavigationId( - @RequestBody List fields) { - return new ResponseEntity<>(answerLoadUseCase.execute(fields), HttpStatus.OK); + @PostMapping("/page/{page}/boards") + public ResponseEntity>> getBoardByNavigationId( + @PathVariable(name = "page") Integer page, @RequestBody List fields) { + return new ResponseEntity<>(answerQueryUseCase.execute(fields, page), HttpStatus.OK); } @Operation( @@ -185,10 +185,10 @@ public ResponseEntity>> getBoardByNavigationId( description = "특정 지원자에 대하여 원하는 field만(리스트) 조회합니다.") @ApiErrorExceptionsExample(FindBoardExceptionDocs.class) @PostMapping("/boards/{applicant-id}") - public ResponseEntity> getBoardByNavigationId( + public ResponseEntity> getBoardByNavigationId( @PathVariable(name = "applicant-id") String applicantId, @RequestBody List fields) { - return new ResponseEntity<>(answerLoadUseCase.execute(applicantId, fields), HttpStatus.OK); + return new ResponseEntity<>(answerQueryUseCase.execute(applicantId, fields), HttpStatus.OK); } @Operation(summary = "카드 삭제", description = "업무 카드를 삭제합니다(지원서 삭제는 불가합니다.)") diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/card/service/CardService.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/card/service/CardService.java index 9d48fadd..7b22d50a 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/card/service/CardService.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/card/service/CardService.java @@ -1,6 +1,6 @@ package com.econovation.recruit.api.card.service; -import com.econovation.recruit.api.applicant.usecase.AnswerLoadUseCase; +import com.econovation.recruit.api.applicant.usecase.ApplicantQueryUseCase; import com.econovation.recruit.api.card.usecase.BoardLoadUseCase; import com.econovation.recruit.api.card.usecase.BoardRegisterUseCase; import com.econovation.recruit.api.card.usecase.CardLoadUseCase; @@ -23,7 +23,6 @@ import com.econovation.recruitdomain.out.CardLoadPort; import com.econovation.recruitdomain.out.CardRecordPort; import com.econovation.recruitdomain.out.LabelLoadPort; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -40,7 +39,7 @@ public class CardService implements CardRegisterUseCase, CardLoadUseCase { private final BoardRegisterUseCase boardRegisterUseCase; private final BoardLoadUseCase boardLoadUseCase; private final ColumnsUseCase columnsUseCase; - private final AnswerLoadUseCase answerLoadPort; + private final ApplicantQueryUseCase applicantQueryUseCase; private final LabelLoadPort labelLoadPort; @Override @@ -69,8 +68,8 @@ public List getByNavigationId(Integer navigationId) { List result = new LinkedList<>(); // key : applicantId - Map> answers = - answerLoadPort.findAllApplicantVo(List.of("field1", "field2", "major")); + Map> answers = + applicantQueryUseCase.findAllApplicantVo(List.of("field1", "field2", "major")); List