Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE-30] 지원서 제출시 PDF 생성 및 발송 #69

Open
wants to merge 3 commits into
base: release
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified server/.gradle/7.6.1/checksums/checksums.lock
Binary file not shown.
Binary file modified server/.gradle/7.6.1/executionHistory/executionHistory.bin
Binary file not shown.
Binary file modified server/.gradle/7.6.1/executionHistory/executionHistory.lock
Binary file not shown.
Binary file modified server/.gradle/7.6.1/fileHashes/fileHashes.bin
Binary file not shown.
Binary file modified server/.gradle/7.6.1/fileHashes/fileHashes.lock
Binary file not shown.
Binary file modified server/.gradle/7.6.1/fileHashes/resourceHashesCache.bin
Binary file not shown.
Binary file modified server/.gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.econovation.recruit.api.applicant.handler;

import com.econovation.recruitdomain.domains.applicant.event.ApplicantRegisterEvent;
import com.econovation.recruitdomain.domains.applicant.helper.ApplicantPdfHelper;
import javax.mail.MessagingException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

@Component
@RequiredArgsConstructor
@Slf4j
public class ApplicantRegisterPdfSendEventHandler {
private final ApplicantPdfHelper applicantPdfHelper;

@Async
@TransactionalEventListener(
classes = ApplicantRegisterEvent.class,
phase = TransactionPhase.AFTER_COMMIT)
@Transactional
public void handle(ApplicantRegisterEvent applicantRegistEvent) throws MessagingException {
// TODO Log 제거 예정
log.info("applicantRegistEvent: " + applicantRegistEvent.toString());
applicantPdfHelper.sendToInterviewers(applicantRegistEvent.getAnswers());
}
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
package com.econovation.recruit.api.slack.handler;
package com.econovation.recruit.api.applicant.handler;

import com.econovation.recruitdomain.domains.applicant.event.ApplicantRegisterEvent;
import com.econovation.recruitinfrastructure.slack.SlackMessageProvider;
import com.econovation.recruitinfrastructure.slack.config.SlackProperties;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

@Component
@RequiredArgsConstructor
@Slf4j
public class ApplicantRegisterEventHandler {
public class ApplicantRegisterSlackEventHandler {
private final SlackMessageProvider slackMessageProvider;
private final SlackProperties slackProperties;

@Async
@TransactionalEventListener(
classes = ApplicantRegisterEvent.class,
phase = TransactionPhase.AFTER_COMMIT)
@Transactional
public void handle(ApplicantRegisterEvent applicantRegistEvent) {
String message = generateApplicantRegisterMessage(applicantRegistEvent);
slackMessageProvider.sendMessage(slackProperties.getChannel(), message);
}

private String generateApplicantRegisterMessage(ApplicantRegisterEvent applicantRegistEvent) {
Map<String, String> answers = applicantRegistEvent.getAnswers();
return String.format(
":clapping: 지원자가 등록되었습니다.:clapping:\n"
+ ":chikorita: 지원자 이름: %s\n"
+ ":chikorita:희망 분야: %s",
applicantRegistEvent.getUserName(), applicantRegistEvent.getHopeField());
answers.get("name"), answers.get("field"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private List<Map<String, String>> splitByAnswersInApplicantId(
.collect(Collectors.toList());
}

private List<Map<String, String>> splitByAnswersInApplicantId(List<Answer> answers) {
public List<Map<String, String>> splitByAnswersInApplicantId(List<Answer> answers) {
return answers.stream()
.collect(
Collectors.groupingBy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@
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.recruitdomain.common.events.applicant.SubmitApplicantEvent;
import com.econovation.recruitdomain.domain.applicant.Applicant;
import com.econovation.recruitdomain.domains.applicant.adaptor.AnswerAdaptor;
import com.econovation.recruitdomain.domains.applicant.adaptor.ApplicantAdaptor;
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.QuestionNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class ApplicantService implements ApplicantRegisterUseCase {
private final QuestionAdaptor questionAdaptor;
private final ApplicantAdaptor applicantAdaptor;
private final AnswerAdaptor answerAdaptor;
private final AnswerService answerService;

@Transactional
@Override
Expand Down Expand Up @@ -64,13 +64,24 @@ public UUID execute(List<BlockRequestDto> blocks) {
.collect(Collectors.toList());
// Result 를 save 하게 된다.
answerAdaptor.saveAll(results);
Events.raise(
SubmitApplicantEvent.of(applicantId, convertToSubmitApplicantEventTitle(results)));
Events.raise(ApplicantRegisterEvent.from(splitByAnswers(results)));
// SubmitApplicantEvent.of(applicantId,
// convertToSubmitApplicantEventTitle(results)));
// TODO: 추가될지 말지 결정해야 함
// applicantRegister(results);
return applicantId;
}

public Map<String, String> splitByAnswers(List<Answer> answers) {
return answers.stream()
.collect(
Collectors.toMap(
answer -> answer.getQuestion().getName(),
Answer::getAnswer,
(existing, replacement) -> existing,
HashMap::new));
}

private String convertToSubmitApplicantEventTitle(List<Answer> results) {
final String HOPE_FIELD_QUESTION_KEY = "hopeField";
final String NAME_QUESTION_KEY = "name";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ public class Answer {
@Column(name = "answer")
private String answer;

// @Column(name = "applicant_id", nullable = false
// , columnDefinition = "BINARY(16)")
// private UUID applicantId;
@Column(name = "applicant_id", nullable = false)
private String applicantId;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.econovation.recruitdomain.domains.applicant.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ApplicantPdfDto {
private String field;
private String field1;
private String field2;
private String name;
private String contacted;
private String classOf;
private String grade;
private String semester;
private String major;
private String doubleMajor;
private String minor;
private String activity;
private String channel;
private String reason;
private String future;
private String experience;
private String experienceTextarea;
private String goal;
private String deep;
private String collaboration;
private String portfolio;
private String fileUrl;
private String fileUrlforPlanner;
private String email;
private String check;
private String personalInformationAgree;
private String personalInformationAgreeForPortfolio;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
@Getter
@RequiredArgsConstructor
public class BlockRequestDto {
// private String type;
private String name;
private String answer;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.econovation.recruitdomain.domains.applicant.event;

import com.econovation.recruitdomain.common.aop.domainEvent.DomainEvent;
import java.util.Map;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
Expand All @@ -9,10 +10,14 @@
@Builder
@ToString
public class ApplicantRegisterEvent extends DomainEvent {
private final String hopeField;
private final String userName;
private final Map<String, String> answers;

public static ApplicantRegisterEvent of(String userName, String hopeField) {
return ApplicantRegisterEvent.builder().hopeField(hopeField).userName(userName).build();
public static ApplicantRegisterEvent from(Map<String, String> answers) {
return ApplicantRegisterEvent.builder().answers(answers).build();
}

@Override
public String toString() {
return "ApplicantRegisterEvent{" + "answers=" + answers + '}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.econovation.recruitdomain.domains.applicant.helper;

import com.econovation.recruitcommon.annotation.Helper;
import com.econovation.recruitdomain.domains.applicant.dto.ApplicantPdfDto;
import com.econovation.recruitinfrastructure.mail.EmailSenderService;
import com.econovation.recruitinfrastructure.pdf.PdfRender;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.istack.ByteArrayDataSource;
import java.time.LocalDateTime;
import java.util.Map;
import javax.mail.IllegalWriteException;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;

@Helper
@RequiredArgsConstructor
public class ApplicantPdfHelper {
private final PdfRender pdfRender;

private final ObjectMapper objectMapper;

private final SpringTemplateEngine templateEngine;
private final EmailSenderService mailSender;

private Context getPdfHtmlContext(ApplicantPdfDto settlementPDFDto) {
Map result = objectMapper.convertValue(settlementPDFDto, Map.class);

Context context = new Context(null, result);
context.setVariable("now", LocalDateTime.now());
return context;
}

public void sendToInterviewers(Map<String, String> answer) throws MessagingException {
ApplicantPdfDto applicantPdfDto = getApplicantPDFDto(answer);
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8");

messageHelper.setFrom("[email protected]");
// messageHelper.setTo(applicantPdfDto.getEmail());
messageHelper.setTo("[email protected]");
messageHelper.setCc("Econovation_Recruit_Team");
messageHelper.setSubject("Econovation 신입모집 지원서");
messageHelper.setText("귀역뛰 ( 귀하의 역량은 뛰어나나... )");
String applicant =
templateEngine.process("applicant", getPdfHtmlContext(applicantPdfDto));
messageHelper.addAttachment(
"Econovation_Recruit_Team_신입모집_지원서.pdf",
new ByteArrayDataSource(
pdfRender.generatePdfFromHtml(applicant).toByteArray(),
"application/pdf"));
mailSender.sendEmail(messageHelper.getMimeMessage());

} catch (Exception e) {
throw new IllegalWriteException("메일발송에 실패하였습니다.");
}
}

private ApplicantPdfDto getApplicantPDFDto(Map<String, String> result) {
return ApplicantPdfDto.builder()
.field(result.get("field"))
.field1(result.get("field1"))
.field2(result.get("field2"))
.name(result.get("name"))
.contacted(result.get("contacted"))
.classOf(result.get("classOf"))
.grade(result.get("grade"))
.semester(result.get("semester"))
.major(result.get("major"))
.doubleMajor(result.get("doubleMajor"))
.minor(result.get("minor"))
.activity(result.get("activity"))
.channel(result.get("channel"))
.reason(result.get("reason"))
.future(result.get("future"))
.experience(result.get("experience"))
.experienceTextarea(result.get("experienceTextarea"))
.goal(result.get("goal"))
.deep(result.get("deep"))
.collaboration(result.get("collaboration"))
.portfolio(result.get("portfolio"))
.fileUrl(result.get("fileUrl"))
.fileUrlforPlanner(result.get("fileUrlforPlanner"))
.email(result.get("email"))
.check(result.get("check"))
.personalInformationAgree(result.get("personalInformationAgree"))
.personalInformationAgreeForPortfolio(
result.get("personalInformationAgreeForPortfolio"))
.build();
}
}
Loading