diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/ApplicantStateUpdateEventListener.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/ApplicantStateUpdateEventListener.java index 3c78ce1a..28c397f5 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/ApplicantStateUpdateEventListener.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/aggregate/ApplicantStateUpdateEventListener.java @@ -34,7 +34,7 @@ public String handle(ApplicantStateUpdateEvent event){ } answerAdaptor.save(answer); - return answer.getApplicantState().getPassState(); + return answer.getApplicantStateOrDefault().getPassState(); } } 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 fbea6002..fe047b58 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,6 +1,7 @@ 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.PASS_STATE_KEY; import com.econovation.recruit.api.applicant.command.CreateAnswerCommand; import com.econovation.recruit.api.applicant.docs.CreateApplicantExceptionDocs; @@ -20,6 +21,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import java.time.LocalDateTime; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; @@ -146,10 +148,12 @@ public ResponseEntity sendEmail(@RequestBody EmailSendDto emailSendDto) { @Operation(summary = "지원자의 합/불 상태를 변경합니다.") @PatchMapping("/applicants/{applicant-id}/state") - public ResponseEntity updateStatus(@PathVariable("applicant-id") String applicantId, + public ResponseEntity> updateStatus(@PathVariable("applicant-id") String applicantId, @RequestParam("afterState") String afterState){ // commandGateway.send(new UpdateApplicantStateCommand(applicantId, afterState)); String state = applicantCommandUseCase.execute(applicantId, afterState); - return new ResponseEntity(state,HttpStatus.OK); + Map response = new HashMap<>(); + response.put(PASS_STATE_KEY, state); + return new ResponseEntity(response,HttpStatus.OK); } } diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantStateUpdateEventHandler.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantStateUpdateEventHandler.java index ae145454..281a1cde 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantStateUpdateEventHandler.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantStateUpdateEventHandler.java @@ -3,17 +3,11 @@ import com.econovation.recruit.api.applicant.state.support.PeriodCalculator; 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.event.domainevent.ApplicantStateEvents; import com.econovation.recruitdomain.domains.applicant.event.domainevent.ApplicantStateModifyEvent; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.event.TransactionPhase; -import org.springframework.transaction.event.TransactionalEventListener; @Component @RequiredArgsConstructor @@ -31,6 +25,8 @@ public class ApplicantStateUpdateEventHandler { public String handle(ApplicantStateModifyEvent event){ MongoAnswer answer = answerAdaptor.findById(event.getApplicantId()).get(); ApplicantStateEvents command = event.getEvent(); + boolean result = answer.stateEmptyCheckAndInit(); + log.error(String.format("validate : %s", (result ? "새로운 state 초기화" : "state 초기화 하지 않고 변경"))); switch (command) { case PASS: answer.pass(periodCalculator.execute()); @@ -41,7 +37,7 @@ public String handle(ApplicantStateModifyEvent event){ } answerAdaptor.save(answer); - return answer.getApplicantState().getPassState(); + return answer.getApplicantStateOrDefault().getPassState(); } } 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 index 1e52c0c1..32524319 100644 --- 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 @@ -29,8 +29,22 @@ public class AnswerCommandService implements ApplicantCommandUseCase { @Transactional public UUID execute(Map qna) { UUID id = UUID.randomUUID(); - ApplicantState nonPassed = new ApplicantState(); - MongoAnswer answer = MongoAnswer.builder().id(id.toString()).qna(qna).year(year).applicantState(nonPassed).build(); + execute(qna, id); + return id; + } + + @Override + @Transactional + public String execute(String applicantId, String afterState) { + ApplicantStateModifyEvent stateModifyEventEvents = + ApplicantStateModifyEvent.of(applicantId, afterState); + return applicantStateUpdateEventHandler.handle(stateModifyEventEvents); // 동기로 처리 + } + + @Override + public UUID execute(Map qna, UUID id) { + ApplicantState nonProcessed = new ApplicantState(); + MongoAnswer answer = MongoAnswer.builder().id(id.toString()).qna(qna).year(year).applicantState(nonProcessed).build(); // 학번으로 중복 체크 // validateRegisterApplicant(qna); answerAdaptor.save(answer); @@ -42,14 +56,6 @@ public UUID execute(Map qna) { ApplicantRegisterEvent applicantRegisterEvent = ApplicantRegisterEvent.of(answer.getId(), name, hopeField, email); Events.raise(applicantRegisterEvent); - return id; - } - - @Override - @Transactional - public String execute(String applicantId, String afterState) { - ApplicantStateModifyEvent stateModifyEventEvents = - ApplicantStateModifyEvent.of(applicantId, afterState); - return applicantStateUpdateEventHandler.handle(stateModifyEventEvents); // 동기로 처리 + return null; } } 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 1bef0ded..7f7805fb 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 @@ -19,6 +19,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import static com.econovation.recruitcommon.consts.RecruitStatic.PASS_STATE_KEY; + @Service @RequiredArgsConstructor public class ApplicantService implements ApplicantQueryUseCase { @@ -46,6 +48,7 @@ public Map execute(String answerId) { public AnswersResponseDto execute(Integer year, Integer page, String sortType) { PageInfo pageInfo = getPageInfo(year, page); List result = answerAdaptor.findByYear(year, page); + result.forEach(answer -> answer.getQna().put(PASS_STATE_KEY, answer.getApplicantStateOrDefault())); sortHelper.sort(result, sortType); List> sortedResult = result.stream().map(MongoAnswer::getQna).toList(); @@ -104,6 +107,7 @@ public Map> findAllApplicantVo(List fields) @Override public AnswersResponseDto search(Integer page, String searchKeyword) { List answers = answerAdaptor.findBySearchKeyword(page, searchKeyword); + answers.forEach(answer -> answer.getQna().put(PASS_STATE_KEY, answer.getApplicantStateOrDefault())); return AnswersResponseDto.of( answers.stream().map(MongoAnswer::getQna).toList(), new PageInfo(answers.size(), page)); diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantCommandUseCase.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantCommandUseCase.java index 3c2e4e39..52b53fd2 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantCommandUseCase.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/usecase/ApplicantCommandUseCase.java @@ -9,4 +9,6 @@ public interface ApplicantCommandUseCase { UUID execute(Map blocks); String execute(String applicantId, String state); + + UUID execute(Map blocks, UUID id); } 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 03e3290a..c64523a3 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 @@ -73,7 +73,7 @@ public List getByNavigationId(Integer navigationId, Intege Map stateByAnswerIdMap = mongoAnswers.stream() .collect(Collectors.toMap(MongoAnswer::getId, - answer -> answer.getApplicantState()!=null ? answer.getApplicantState() : new ApplicantState())); + MongoAnswer::getApplicantStateOrDefault)); List cards = cardLoadPort.findAll(); diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/utils/ApplicantStateCheck.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/utils/ApplicantStateCheck.java new file mode 100644 index 00000000..fbad39a9 --- /dev/null +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/utils/ApplicantStateCheck.java @@ -0,0 +1,47 @@ +package com.econovation.recruit.utils; + +import com.econovation.recruit.api.applicant.usecase.ApplicantCommandUseCase; +import com.econovation.recruit.api.applicant.usecase.ApplicantQueryUseCase; +import com.econovation.recruitdomain.domains.applicant.adaptor.AnswerAdaptor; +import com.econovation.recruitdomain.domains.applicant.domain.MongoAnswer; +import io.vavr.concurrent.Future; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +@Component +@RequiredArgsConstructor +@Slf4j +public class ApplicantStateCheck implements ApplicationRunner { + + private final AnswerAdaptor answerAdaptor; + + @PostConstruct + public void init() throws IOException, SQLException { + // init.sql 파일을 읽어와서 실행합니다. + log.info("MongoDB Applicant State 체크를 시작합니다."); + } + + @Override + public void run(ApplicationArguments args) throws Exception { + try { + List answers = answerAdaptor.findAll().stream().filter(answer -> answer.getApplicantState()==null).toList(); + answers.forEach(MongoAnswer::stateEmptyCheckAndInit); + answerAdaptor.saveAll(answers); + log.info("MongoDB Applicant State Check를 완료했습니다."); + } catch (Exception e){ + e.printStackTrace(); + log.error("MongoDB Applicant State Check를 실패했습니다."); + } + } +} diff --git a/server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/domain/MongoAnswer.java b/server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/domain/MongoAnswer.java index abd8b24a..922212e8 100644 --- a/server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/domain/MongoAnswer.java +++ b/server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/domain/MongoAnswer.java @@ -47,6 +47,19 @@ public void nonPass(PeriodStates period){ this.applicantState.nonPass(period); } + public boolean stateEmptyCheckAndInit(){ + if(this.applicantState==null) { + this.applicantState = new ApplicantState(); + return true; + } + return false; + } + + public ApplicantState getApplicantStateOrDefault(){ + if(this.applicantState==null) return new ApplicantState(); + return this.applicantState; + } + public MongoAnswer(String id, Integer year, Map qna) { this.id = id; this.year = year; diff --git a/server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/event/domainevent/ApplicantStateEvents.java b/server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/event/domainevent/ApplicantStateEvents.java index 62ef1e59..a5391644 100644 --- a/server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/event/domainevent/ApplicantStateEvents.java +++ b/server/Recruit-Domain/src/main/java/com/econovation/recruitdomain/domains/applicant/event/domainevent/ApplicantStateEvents.java @@ -22,6 +22,6 @@ public static ApplicantStateEvents find(String event){ return Arrays.stream(ApplicantStateEvents.values()) .filter(e -> e.getEvent().equals(event)) .findFirst() - .orElseThrow(ApplicantWrongStateException::new); + .orElseThrow(()->ApplicantWrongStateException.wrongStatusException); } }