diff --git a/server/.gradle/7.6.1/executionHistory/executionHistory.bin b/server/.gradle/7.6.1/executionHistory/executionHistory.bin index acf9f7ac..56267e20 100644 Binary files a/server/.gradle/7.6.1/executionHistory/executionHistory.bin and b/server/.gradle/7.6.1/executionHistory/executionHistory.bin differ diff --git a/server/.gradle/7.6.1/executionHistory/executionHistory.lock b/server/.gradle/7.6.1/executionHistory/executionHistory.lock index 0f54dfb5..169b5f93 100644 Binary files a/server/.gradle/7.6.1/executionHistory/executionHistory.lock and b/server/.gradle/7.6.1/executionHistory/executionHistory.lock differ diff --git a/server/.gradle/7.6.1/fileHashes/fileHashes.bin b/server/.gradle/7.6.1/fileHashes/fileHashes.bin index 9c98e1ea..23db0517 100644 Binary files a/server/.gradle/7.6.1/fileHashes/fileHashes.bin and b/server/.gradle/7.6.1/fileHashes/fileHashes.bin differ diff --git a/server/.gradle/7.6.1/fileHashes/fileHashes.lock b/server/.gradle/7.6.1/fileHashes/fileHashes.lock index 8d7f0d40..7f4eb5ca 100644 Binary files a/server/.gradle/7.6.1/fileHashes/fileHashes.lock and b/server/.gradle/7.6.1/fileHashes/fileHashes.lock differ diff --git a/server/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/server/.gradle/buildOutputCleanup/buildOutputCleanup.lock index c3903b50..da432b16 100644 Binary files a/server/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/server/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/server/.gradle/file-system.probe b/server/.gradle/file-system.probe index 239692fd..faccfe43 100644 Binary files a/server/.gradle/file-system.probe and b/server/.gradle/file-system.probe differ 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 index fec01490..3cf22ad1 100644 --- 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 @@ -1,27 +1,81 @@ package com.econovation.recruit.api.applicant.aggregate; +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.aggregateevent.AnswerCreatedEvent; +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 lombok.RequiredArgsConstructor; import org.axonframework.eventhandling.EventHandler; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; @Component @RequiredArgsConstructor public class AnswerCreatedEventListener { private final MongoAnswerAdaptor answerAdaptor; + @Value("${econovation.year}") + private Integer year; + @EventHandler + @Transactional public void handle(AnswerCreatedEvent event) { + Map qna = event.getQna(); MongoAnswer answer = MongoAnswer.builder() .id(event.getId()) .year(event.getYear()) .qna(event.getQna()) .build(); + // 학번으로 중복 체크 + validateRegisterApplicant(qna); + answerAdaptor.save(answer); + String name = qna.get("name").toString().replace("\"", ""); + ; + String hopeField = qna.get("field").toString().replace("\"", ""); + ; + String email = qna.get("email").toString().replace("\"", ""); + ; + // email 전송 event처리 + ApplicantRegisterEvent applicantRegisterEvent = + ApplicantRegisterEvent.of(answer.getId(), name, hopeField, email); + Events.raise(applicantRegisterEvent); + } + + 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().replace("\"", ""); + ; + 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().replace("\"", ""); + ; + 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/handler/ApplicantRegisterEventConfirmEmailHandler.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/applicant/handler/ApplicantRegisterEventConfirmEmailHandler.java index 6aae477f..8295d291 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,6 +1,5 @@ package com.econovation.recruit.api.applicant.handler; -import com.econovation.recruit.api.user.helper.NcpMailHelper; import com.econovation.recruitdomain.domains.applicant.event.domainevent.ApplicantRegisterEvent; import com.econovation.recruitinfrastructure.apache.CommonsEmailSender; import lombok.RequiredArgsConstructor; @@ -16,7 +15,6 @@ @RequiredArgsConstructor @Slf4j public class ApplicantRegisterEventConfirmEmailHandler { - private final NcpMailHelper ncpMailHelper; private final CommonsEmailSender commonsEmailSender; @Async @@ -25,9 +23,9 @@ public class ApplicantRegisterEventConfirmEmailHandler { phase = TransactionPhase.AFTER_COMMIT) @Transactional(propagation = Propagation.REQUIRES_NEW) public void handle(ApplicantRegisterEvent applicantRegistEvent) { - log.info("%s님의 지원서가 접수되었습니다.", applicantRegistEvent.getUserName()); - String email = applicantRegistEvent.getEmail().replace("\"", ""); - commonsEmailSender.send(email, applicantRegistEvent.getApplicantId()); + log.info(applicantRegistEvent.getUserName() + "님의 지원서가 접수되었습니다."); + commonsEmailSender.send( + applicantRegistEvent.getEmail(), applicantRegistEvent.getApplicantId()); } private String generateConfirmRegisterEmailBody(String userName) { 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 5c273b24..64da625c 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 @@ -1,20 +1,16 @@ 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; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -25,11 +21,12 @@ public class AnswerCommandService implements ApplicantCommandUseCase { private Integer year; @Override + @Transactional public UUID execute(Map qna) { UUID id = UUID.randomUUID(); MongoAnswer answer = MongoAnswer.builder().id(id.toString()).qna(qna).year(year).build(); - // 학번으로 중복 체크 - validateRegisterApplicant(qna); + // 학번으로 중복 체크 + // validateRegisterApplicant(qna); answerAdaptor.save(answer); String name = qna.get("name").toString(); @@ -41,28 +38,4 @@ public UUID execute(Map qna) { 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/slack/handler/ApplicantRegisterEventHandler.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/slack/handler/ApplicantSlackSendAndCardRegisterEventHandler.java similarity index 83% rename from server/Recruit-Api/src/main/java/com/econovation/recruit/api/slack/handler/ApplicantRegisterEventHandler.java rename to server/Recruit-Api/src/main/java/com/econovation/recruit/api/slack/handler/ApplicantSlackSendAndCardRegisterEventHandler.java index 5c341b39..53a32a5e 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/api/slack/handler/ApplicantRegisterEventHandler.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/api/slack/handler/ApplicantSlackSendAndCardRegisterEventHandler.java @@ -18,7 +18,7 @@ @Component @RequiredArgsConstructor @Slf4j -public class ApplicantRegisterEventHandler { +public class ApplicantSlackSendAndCardRegisterEventHandler { private final SlackMessageProvider slackMessageProvider; private final SlackProperties slackProperties; private final CardAdaptor cardAdaptor; @@ -45,7 +45,10 @@ public void handle(ApplicantRegisterEvent applicantRegistEvent) { private String generateApplicantRegisterMessage(ApplicantRegisterEvent applicantRegistEvent) { return String.format( - ":clapping: 지원자가 등록되었습니다.:clapping:\n" + ":drum_with_drumsticks:두둥-탁 -!\n" + + ":space_invader::black_small_square::space_invader::black_small_square::space_invader::black_small_square::space_invader::black_small_square::space_invader::black_small_square:\n" + + ":sparkles::eyes:새로운 지원자 등장:eyes::sparkles:\n" + + ":black_small_square::space_invader::black_small_square::space_invader::black_small_square::space_invader::black_small_square::space_invader::black_small_square::space_invader:\n" + ":chikorita: 지원자 이름: %s\n" + ":chikorita:희망 분야: %s", applicantRegistEvent.getUserName(), applicantRegistEvent.getHopeField()); diff --git a/server/Recruit-Api/src/main/java/com/econovation/recruit/utils/DataInit.java b/server/Recruit-Api/src/main/java/com/econovation/recruit/utils/DataInit.java index 211e9d35..ec7ebca1 100644 --- a/server/Recruit-Api/src/main/java/com/econovation/recruit/utils/DataInit.java +++ b/server/Recruit-Api/src/main/java/com/econovation/recruit/utils/DataInit.java @@ -11,6 +11,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ScriptUtils; import org.springframework.security.crypto.password.PasswordEncoder; @@ -18,7 +19,7 @@ // @Component @RequiredArgsConstructor @Slf4j -// @ConditionalOnProperty(name = "data.init.disabled", havingValue = "false", matchIfMissing = true) +@ConditionalOnProperty(name = "data.init.disabled", havingValue = "false", matchIfMissing = true) public class DataInit { private final DataSource dataSource; private final InterviewerRecordPort interviewerRecordPort; diff --git a/server/Recruit-Api/src/main/resources/application.yml b/server/Recruit-Api/src/main/resources/application.yml index 450ffc87..a6a01bcf 100644 --- a/server/Recruit-Api/src/main/resources/application.yml +++ b/server/Recruit-Api/src/main/resources/application.yml @@ -22,6 +22,11 @@ throttle: auth: blacklist: prefix: ${JWT_BLACKLIST_PREFIX:BlackList_AccessToken_} +notification: + email: + enabled: ${NOTIFICATION_EMAIL_ENABLED:true} + slack: + enabled: ${NOTIFICATION_SLACK_ENABLED:true} login: page: url: ${LOGIN_PAGE_URL:http://localhost:8080/login} diff --git a/server/Recruit-Infrastructure/src/main/java/com/econovation/recruitinfrastructure/apache/CommonsEmailSender.java b/server/Recruit-Infrastructure/src/main/java/com/econovation/recruitinfrastructure/apache/CommonsEmailSender.java index 4c514b0a..f4e9e5f8 100644 --- a/server/Recruit-Infrastructure/src/main/java/com/econovation/recruitinfrastructure/apache/CommonsEmailSender.java +++ b/server/Recruit-Infrastructure/src/main/java/com/econovation/recruitinfrastructure/apache/CommonsEmailSender.java @@ -4,6 +4,7 @@ import org.apache.commons.mail.EmailException; import org.apache.commons.mail.HtmlEmail; import org.apache.commons.mail.SimpleEmail; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component @@ -11,6 +12,9 @@ public class CommonsEmailSender { private final CommonsEmailProperties commonsEmailProperties; + @Value("${econovation.year}") + private Integer year; + public void send(String toEmail, String name, String contents) { SimpleEmail email = new SimpleEmail(); email.setCharset("euc-kr"); @@ -29,7 +33,7 @@ public void send(String toEmail, String name, String contents) { email.setContent(contents, "text/html; charset=euc-kr"); email.send(); } catch (EmailException e) { - throw new RuntimeException(e); + throw new IllegalArgumentException(e); } } @@ -51,13 +55,15 @@ public void send(String toEmail, String applicantId) { email.setHtmlMsg(generateHtml(applicantId)); email.send(); } catch (EmailException e) { - throw new RuntimeException(e); + throw new IllegalArgumentException(e); } } private String generateHtml(String applicantId) { String html = - " Econovation Recruit
\"econo-3d-logo\"

신입모집 지원 완료!

에코노베이션 26기 지원서가 정상적으로 업로드 되었습니다
서류 합격 결과는 9월 19일에 개인 메일으로 공지 될 예정입니다.
여기에서 지원서를 확인하실 수 있습니다.
지원해주셔서 감사합니다.
"; + " Econovation Recruit
\"econo-3d-logo\"

신입모집 지원 완료!

에코노베이션 " + + year + + "기 지원서가 정상적으로 업로드 되었습니다
서류 합격 결과는 9월 19일에 개인 메일으로 공지 될 예정입니다.
여기에서 지원서를 확인하실 수 있습니다.
지원해주셔서 감사합니다.
"; return html.replace("%APPLICANT_ID%", applicantId); } } diff --git a/server/Recruit-Infrastructure/src/main/resources/application-infrastructure.yml b/server/Recruit-Infrastructure/src/main/resources/application-infrastructure.yml index 344d5b08..e6c206c2 100644 --- a/server/Recruit-Infrastructure/src/main/resources/application-infrastructure.yml +++ b/server/Recruit-Infrastructure/src/main/resources/application-infrastructure.yml @@ -12,7 +12,7 @@ ncp: access-key: ${NCP_ACCESS_KEY} secret-key: ${NCP_SECRET_KEY} sender-address: ${NCP_SENDER_ADDRESS:} - send-url: ${NCP_MAIL_URL:https://mail.apigw.gov-ntruss.com} + send-url: ${NCP_MAIL_URL:https://mail.apigw.gov-ntruss. com} commons: email: host: ${COMMONS_EMAIL_HOST:smtp.naver.com} diff --git a/server/docker-compose.yml b/server/docker-compose.yml index 4fd9dc09..94ad08e6 100644 --- a/server/docker-compose.yml +++ b/server/docker-compose.yml @@ -1,15 +1,20 @@ version: "3.7" services: redis: - image: "redis:alpine" + image: redis:alpine + hostname: redis + container_name: redis network_mode: "host" + axon-server: image: axoniq/axonserver:4.6.11 container_name: axon-server restart: unless-stopped + network_mode: "host" ports: - "8024:8024" - "8124:8124" + backend: image: blackbean99/econo-recruit:latest restart: unless-stopped @@ -20,5 +25,5 @@ services: environment: - TZ=Asia/Seoul depends_on: - - axon-server - - redis \ No newline at end of file + - redis + - axon-server \ No newline at end of file