Skip to content

Commit

Permalink
Merge pull request #256 from softeerbootcamp-2nd/be-refactor
Browse files Browse the repository at this point in the history
[BE] refactor: PDF/메일 도메인 리팩토링
  • Loading branch information
qsunki authored Aug 27, 2023
2 parents 6b3db84 + bfae9c5 commit fb057aa
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
@Slf4j
public class CarSpecService {

public static final String TRIM = "trim";
private final CarSpecRepository carSpecRepository;

public CarSpecResponse findCarSpecsBySpec(Long engineId, Long bodyId, Long drivingSystemId) {
Expand Down Expand Up @@ -110,7 +111,7 @@ private List<String> getBasicOptionUrls(Long trimId) {
}

public boolean userClickedTrimLog(Long trimId) {
log.info(Markers.append("trim", trimId), "trim");
log.info(Markers.append(TRIM, trimId), TRIM);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
@Slf4j
public class ColorService {

public static final String EXTERIOR_COLOR = "exterior_color";
public static final String INTERIOR_COLOR = "interior_color";
private final TrimExteriorColorRepository trimExteriorColorRepository;
private final TrimInteriorColorRepository trimInteriorColorRepository;

Expand Down Expand Up @@ -128,12 +130,12 @@ private boolean isInteriorColorAvailableForExteriorColor(
}

public boolean userClickedExteriorColorLog(Long exteriorColorId) {
log.info(Markers.append("exterior_color", exteriorColorId), "exterior_color");
log.info(Markers.append(EXTERIOR_COLOR, exteriorColorId), EXTERIOR_COLOR);
return true;
}

public boolean userClickedInteriorColorLog(Long interiorColorId) {
log.info(Markers.append("interior_color", interiorColorId), "interior_color");
log.info(Markers.append(INTERIOR_COLOR, interiorColorId), INTERIOR_COLOR);
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
@Slf4j
public class OptionsService {

public static final String OPTION = "option";
public static final String PACKAGE = "package";
private final OptionsRepository optionsRepository;

private final PackageRepository packageRepository;
Expand Down Expand Up @@ -73,12 +75,12 @@ public List<BasicOptionResponse> findAllBasicOptions(Long carSpecId) {
}

public boolean userClickedOptionLog(Long optionId) {
log.info(Markers.append("option", optionId), "option");
log.info(Markers.append(OPTION, optionId), OPTION);
return true;
}

public boolean userClickedPackageLog(Long optionId) {
log.info(Markers.append("package", optionId), "package");
public boolean userClickedPackageLog(Long packageId) {
log.info(Markers.append(PACKAGE, packageId), PACKAGE);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
import javax.mail.MessagingException;

public interface MailService {
boolean createMessage(String to, String pdfId)
boolean sendMessage(String to, String pdfId)
throws MessagingException, UnsupportedEncodingException;
}
57 changes: 34 additions & 23 deletions src/main/java/com/h1/mycardeepdive/pdf/service/MailServiceImpl.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.h1.mycardeepdive.pdf.service;

import com.h1.mycardeepdive.exception.ErrorType;
import com.h1.mycardeepdive.exception.MyCarDeepDiveException;
import java.io.UnsupportedEncodingException;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.h1.mycardeepdive.exception.ErrorType;
import com.h1.mycardeepdive.exception.MyCarDeepDiveException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -22,47 +21,59 @@
@RequiredArgsConstructor
@Slf4j
public class MailServiceImpl implements MailService {

private static final String BUTTON_IMG =
"https://cdn-icons-png.flaticon.com/512/3154/3154400.png";
private static final String PURCHASE_LINK =
"https://www.hyundai.com/kr/ko/e/vehicles/purchase-consult";
private static final String DOMAIN = "@naver.com";
private static final String EMAIL_SUBJECT = "[현대자동차 MyCarDeepDive] 내차만들기 견적서";
public static final String EMAIL_PERSONAL = "MyCarDeepDive";
public static final String CONTENT_TYPE = "application/pdf";
public static final String PDF_FILE_NAME = "내차만들기견적서.pdf";
public static final String ENCODING = "utf-8";
private final JavaMailSender emailSender;
private final PdfService pdfService;

@Value("${spring.mail.username}")
private String username;

@Override
public boolean createMessage(String to, String pdfId)
public boolean sendMessage(String to, String pdfId)
throws MessagingException, UnsupportedEncodingException {
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
MimeMessageHelper helper = new MimeMessageHelper(message, true, ENCODING);

helper.setTo(to);
message.setSubject("[현대자동차 MyCarDeepDive] 내차만들기 견적서");
message.setSubject(EMAIL_SUBJECT);
helper.setText(renderMailHtml(), true);
helper.setFrom(new InternetAddress(createEmailDomain(username), EMAIL_PERSONAL));

try {
byte[] pdfBytes = pdfService.generatePdf(pdfId);
helper.addAttachment(PDF_FILE_NAME, new ByteArrayResource(pdfBytes), CONTENT_TYPE);
} catch (Exception e) {
throw new MyCarDeepDiveException(HttpStatus.BAD_REQUEST, ErrorType.PDF_CREATE_ERROR);
}
emailSender.send(message);
return true;
}

private String renderMailHtml() {
String msgg = "<div style='margin:100px;'>";
msgg += "<h1> 안녕하세요 </h1>";
msgg += "<h1> 현대자동차 내차만들기 MyCarDeepDive 입니다. </h1>";
msgg += "<br>";
msgg += "<h3> 요청하신 pdf 견적서 파일입니다. </h3>";
String buttonImg = "https://cdn-icons-png.flaticon.com/512/3154/3154400.png";
String link = "https://www.hyundai.com/kr/ko/e/vehicles/purchase-consult";

msgg += "<h2> 차 구매하러 가기 </h2><br>";
msgg += "<a href='" + link + "'>";
msgg += "<img src=" + buttonImg + " width=100px height=auto>";
msgg += "<a href='" + PURCHASE_LINK + "'>";
msgg += "<img src=" + BUTTON_IMG + " width=100px height=auto>";
msgg += "</a>";
msgg += "</div>";
helper.setText(msgg, true);

helper.setFrom(new InternetAddress(username + "@naver.com", "MyCarDeepDive"));
return msgg;
}

try {
byte[] pdfBytes = pdfService.generatePdf(pdfId);
helper.addAttachment(
"내차만들기견적서.pdf", new ByteArrayResource(pdfBytes), "application/pdf");
} catch (Exception e) {
throw new MyCarDeepDiveException(HttpStatus.BAD_REQUEST, ErrorType.PDF_CREATE_ERROR);
}
emailSender.send(message);
return true;
private String createEmailDomain(final String name) {
return name + DOMAIN;
}
}
57 changes: 37 additions & 20 deletions src/main/java/com/h1/mycardeepdive/pdf/service/PdfService.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@
@RequiredArgsConstructor
@Slf4j
public class PdfService {
public static final String PDF_ID = "pdfId";
public static final String MODEL_NAME = "modelName";
public static final String BLANK = " ";
public static final String CAR_IMG_URL = "carImgUrl";
public static final String MODEL_PRICE = "modelPrice";
public static final String MAX_POWER = "maxPower";
public static final String MAX_TORQUE = "maxTorque";
public static final String EXTERIOR_COLOR_NAME = "exteriorColorName";
public static final String EXTERIOR_COLOR_URL = "exteriorColorUrl";
public static final String EXTERIOR_COLOR_PRICE = "exteriorColorPrice";
public static final String INTERIOR_COLOR_NAME = "interiorColorName";
public static final String INTERIOR_COLOR_URL = "interiorColorUrl";
public static final String INTERIOR_COLOR_PRICE = "interiorColorPrice";
public static final String OPTIONS = "options";
public static final String TOTAL_PRICE = "totalPrice";
public static final String TEMPLATE = "template";
public static final String IMAGE_001_PNG = "/image_001.png";
private final SpringTemplateEngine templateEngine;
private final B64ImgReplacedElementFactory b64ImgReplacedElementFactory;
private final PdfRepository pdfRepository;
Expand Down Expand Up @@ -94,7 +111,7 @@ public PdfIdResponse registerPdfId(PdfIdRequest pdfIdRequest) throws Exception {
ErrorType.INVALID_REQUEST_ERROR));
PdfInfo pdfInfo =
PdfInfo.builder()
.car_image_url(exteriorColor.getExteriorImgUrl() + "/image_001.png")
.car_image_url(exteriorColor.getExteriorImgUrl() + IMAGE_001_PNG)
.car_name(carSpec.getCar().getName())
.engine_name(carSpec.getEngine().getName())
.driving_system_name(carSpec.getDrivingSystem().getName())
Expand All @@ -113,15 +130,15 @@ public PdfIdResponse registerPdfId(PdfIdRequest pdfIdRequest) throws Exception {
.build();
pdfInfo = pdfRepository.save(pdfInfo);
byte[] pdfBytes = generatePdf(pdfInfo.getId());
MockMultipartFile pdfMultipartFile = new MockMultipartFile("pdfId", pdfBytes);
MockMultipartFile pdfMultipartFile = new MockMultipartFile(PDF_ID, pdfBytes);
String fileUrl = s3Service.saveFile(pdfMultipartFile, pdfInfo.getId());

pdfInfo.setPdf_url(fileUrl);
pdfRepository.save(pdfInfo);
return new PdfIdResponse(pdfInfo.getId());
}

public PdfUrlResponse findPdf(String pdfId) throws Exception {
public PdfUrlResponse findPdf(String pdfId) {
PdfInfo pdfInfo =
pdfRepository
.findById(pdfId)
Expand Down Expand Up @@ -159,26 +176,26 @@ public byte[] generatePdf(String pdfId) throws Exception {
private String getHtmlContentFromThymeleafTemplate(PdfInfo pdfInfo) {
Context thymeleafContext = new Context();
thymeleafContext.setVariable(
"modelName",
MODEL_NAME,
pdfInfo.getCar_name()
+ " "
+ BLANK
+ pdfInfo.getEngine_name()
+ " "
+ BLANK
+ pdfInfo.getTrim_name()
+ " "
+ BLANK
+ pdfInfo.getBody_name());

thymeleafContext.setVariable("carImgUrl", pdfInfo.getCar_image_url());
thymeleafContext.setVariable("modelPrice", pdfInfo.getBasic_price());
thymeleafContext.setVariable("maxPower", pdfInfo.getMax_power());
thymeleafContext.setVariable("maxTorque", pdfInfo.getMax_torque());
thymeleafContext.setVariable("exteriorColorName", pdfInfo.getExterior_color_name());
thymeleafContext.setVariable("exteriorColorUrl", pdfInfo.getExterior_color_img_url());
thymeleafContext.setVariable("exteriorColorPrice", pdfInfo.getExterior_color_price());
thymeleafContext.setVariable("interiorColorName", pdfInfo.getInterior_color_name());
thymeleafContext.setVariable("interiorColorUrl", pdfInfo.getInterior_color_img_url());
thymeleafContext.setVariable("interiorColorPrice", pdfInfo.getInterior_color_price());
thymeleafContext.setVariable("options", pdfInfo.getOptionList());
thymeleafContext.setVariable(CAR_IMG_URL, pdfInfo.getCar_image_url());
thymeleafContext.setVariable(MODEL_PRICE, pdfInfo.getBasic_price());
thymeleafContext.setVariable(MAX_POWER, pdfInfo.getMax_power());
thymeleafContext.setVariable(MAX_TORQUE, pdfInfo.getMax_torque());
thymeleafContext.setVariable(EXTERIOR_COLOR_NAME, pdfInfo.getExterior_color_name());
thymeleafContext.setVariable(EXTERIOR_COLOR_URL, pdfInfo.getExterior_color_img_url());
thymeleafContext.setVariable(EXTERIOR_COLOR_PRICE, pdfInfo.getExterior_color_price());
thymeleafContext.setVariable(INTERIOR_COLOR_NAME, pdfInfo.getInterior_color_name());
thymeleafContext.setVariable(INTERIOR_COLOR_URL, pdfInfo.getInterior_color_img_url());
thymeleafContext.setVariable(INTERIOR_COLOR_PRICE, pdfInfo.getInterior_color_price());
thymeleafContext.setVariable(OPTIONS, pdfInfo.getOptionList());

long total_price =
pdfInfo.getBasic_price()
Expand All @@ -188,8 +205,8 @@ private String getHtmlContentFromThymeleafTemplate(PdfInfo pdfInfo) {
.mapToLong(SimpleOption::getOption_price)
.sum();

thymeleafContext.setVariable("totalPrice", total_price);
return templateEngine.process("template", thymeleafContext);
thymeleafContext.setVariable(TOTAL_PRICE, total_price);
return templateEngine.process(TEMPLATE, thymeleafContext);
}

private void addFonts(ITextRenderer renderer) throws IOException {
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/h1/mycardeepdive/pdf/service/S3Service.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
@Service
@RequiredArgsConstructor
public class S3Service {
private static final String CLOUDFRONT_PDF_DOMAIN = "pdf.make-my-car.shop/";
public static final String PDF = ".pdf";
private final AmazonS3 amazonS3;

@Value("${cloud.aws.s3.bucket}")
Expand All @@ -21,7 +23,7 @@ public String saveFile(MultipartFile multipartFile, String fileName) throws IOEx
metadata.setContentLength(multipartFile.getSize());
metadata.setContentType(multipartFile.getContentType());

amazonS3.putObject(bucket, fileName + ".pdf", multipartFile.getInputStream(), metadata);
return "pdf.make-my-car.shop/" + fileName + ".pdf";
amazonS3.putObject(bucket, fileName + PDF, multipartFile.getInputStream(), metadata);
return CLOUDFRONT_PDF_DOMAIN + fileName + PDF;
}
}
4 changes: 2 additions & 2 deletions src/main/java/com/h1/mycardeepdive/pdf/ui/PdfController.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public class PdfController {
public ApiResponse<Boolean> sendEmail(
@PathVariable("email") String email, @PathVariable("pdf-id") String pdfId)
throws Exception {
mailService.createMessage(email, pdfId);
return new ApiResponse<>(true);
boolean sendResult = mailService.sendMessage(email, pdfId);
return new ApiResponse<>(sendResult);
}

@PostMapping("/pdfId")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.h1.mycardeepdive.pdf.service;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.lang.reflect.Method;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@SpringBootTest
class MailServiceImplTest {
private static final String BUTTON_IMG =
"https://cdn-icons-png.flaticon.com/512/3154/3154400.png";
private static final String PURCHASE_LINK =
"https://www.hyundai.com/kr/ko/e/vehicles/purchase-consult";
private static final String DOMAIN = "@naver.com";

@Autowired private JavaMailSender emailSender;
@Autowired private PdfService pdfService;
private MailServiceImpl mailService;

@BeforeEach
void setup() {
mailService = new MailServiceImpl(emailSender, pdfService);
}

@Test
@DisplayName("email html 렌더링을 테스트한다.")
public void testRenderMailHtml() {
try {
// given

Method renderMailHtmlMethod = MailServiceImpl.class.getDeclaredMethod("renderMailHtml");
renderMailHtmlMethod.setAccessible(true);

// when
String renderedHtml = (String) renderMailHtmlMethod.invoke(mailService);

// then
String expectedHtml =
"<div style='margin:100px;'>"
+ "<h1> 안녕하세요 </h1>"
+ "<h1> 현대자동차 내차만들기 MyCarDeepDive 입니다. </h1>"
+ "<br>"
+ "<h3> 요청하신 pdf 견적서 파일입니다. </h3>"
+ "<h2> 차 구매하러 가기 </h2><br>"
+ "<a href='"
+ PURCHASE_LINK
+ "'>"
+ "<img src="
+ BUTTON_IMG
+ " width=100px height=auto>"
+ "</a>"
+ "</div>";
assertEquals(expectedHtml, renderedHtml);
} catch (Exception e) {
e.printStackTrace();
}
}

@Test
@DisplayName("이메일 도메인을 생성한다.")
public void createEmailDomainTest() {

try {
// given
String name = "testUser";
MailServiceImpl mailService = new MailServiceImpl(emailSender, pdfService);
Class<?>[] parameterTypes = new Class<?>[] {String.class};
Method renderMailHtmlMethod =
MailServiceImpl.class.getDeclaredMethod("createEmailDomain", parameterTypes);
renderMailHtmlMethod.setAccessible(true);

// when
String createdEmail = (String) renderMailHtmlMethod.invoke(mailService, name);

// then
assertEquals(createdEmail, "[email protected]");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Loading

0 comments on commit fb057aa

Please sign in to comment.