Skip to content

Commit

Permalink
Merge pull request #13 from SWOnCampus/refactor/#4-convert-report-pdf
Browse files Browse the repository at this point in the history
컨설팅 결과 PDF로 변환
  • Loading branch information
minahYu authored Nov 26, 2024
2 parents a22ea82 + 9b4940e commit be72209
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 52 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
// flying saucer
implementation 'org.xhtmlrenderer:flying-saucer-pdf:9.9.1'
// markdown
implementation 'org.commonmark:commonmark:0.21.0'
// postgre
implementation 'org.postgresql:postgresql:42.7.4'
runtimeOnly 'org.postgresql:postgresql'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
})
public class AiPlatformApplication {

public static void main(String[] args) {
SpringApplication.run(AiPlatformApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(AiPlatformApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
package com.swOnCampus.AIPlatform.domain.report.service;

import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingSummaryRequest;
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingResponse;

public interface ReportService {

/**
* 리포팅 요약된 내용을 html로 변환 하여 pdf를 생성하는 메서드
*
* @param request : 리포팅 요약 데이터를 담은 request 객체
* @return : 생성된 PDF 파일의 바이트 배열
*/
byte[] createReportingSummaryPdf(ReportingSummaryRequest request);
}
ReportingResponse createReportingPdf(Long memberId, Long companyId);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package com.swOnCampus.AIPlatform.domain.report.service;

import com.lowagie.text.pdf.BaseFont;
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingSummaryRequest;
import com.swOnCampus.AIPlatform.domain.consulting.entity.Consulting;
import com.swOnCampus.AIPlatform.domain.consulting.exception.ConsultingErrorCode;
import com.swOnCampus.AIPlatform.domain.consulting.repository.ConsultingRepository;
import com.swOnCampus.AIPlatform.domain.report.exception.ReportErrorCode;
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingResponse;
import com.swOnCampus.AIPlatform.global.exception.GlobalException;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.Map;

import com.swOnCampus.AIPlatform.domain.report.exception.ReportErrorCode;
import lombok.RequiredArgsConstructor;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
Expand All @@ -20,19 +25,31 @@
public class ReportServiceImpl implements ReportService {

private final TemplateEngine templateEngine;
private final ConsultingRepository consultingRepository;

@Value(value = "${report.font.path}")
private String fontPath;

@Override
public byte[] createReportingSummaryPdf(ReportingSummaryRequest request) {
public ReportingResponse createReportingPdf(Long memberId, Long companyId) {
Consulting consulting = consultingRepository.findByCompanyId(companyId)
.orElseThrow(() -> new GlobalException(ConsultingErrorCode.NOT_EXIST_CONSULTING));

String summaryHtml = consulting.getSummary().replace("\n", "<br />");
String renderedMarkdown = renderMarkdown(summaryHtml);

Map<String, Object> contextVariables = Map.of(
"title", request.title(),
"content", request.content()
"content", renderedMarkdown
);
String html = createHtmlFromTemplate(contextVariables);
byte[] pdfBytes = convertHtmlToPdf(html);

return convertHtmlToPdf(html);
ReportingResponse response = new ReportingResponse(
consulting.getSummary(),
Base64.getEncoder().encodeToString(pdfBytes)
);

return response;
}

private String createHtmlFromTemplate(Map<String, Object> contextVariables) {
Expand All @@ -57,12 +74,18 @@ private byte[] convertHtmlToPdf(String html) {
private void setFont(ITextRenderer renderer) {
try {
renderer.getFontResolver().addFont(
new ClassPathResource(fontPath).getURL().toString(),
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED
new ClassPathResource(fontPath).getURL().toString(),
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED
);
} catch (Exception e) {
throw new GlobalException(ReportErrorCode.NOT_FOUND_FONT);
}
}
}

private String renderMarkdown(String markdownText) {
Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder().build();
return renderer.render(parser.parse(markdownText));
}
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,59 @@
package com.swOnCampus.AIPlatform.domain.report.web.controller;

import com.swOnCampus.AIPlatform.domain.member.entity.Member;
import com.swOnCampus.AIPlatform.domain.report.service.ReportService;
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingSummaryRequest;
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingResponse;
import com.swOnCampus.AIPlatform.global.annotation.LoginMember;
import com.swOnCampus.AIPlatform.global.response.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "컨설팅 PDF 생성 API", description = "컨설팅 결과 PDF 생성 관련 API")
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/report")
public class ReportController {

private final ReportService reportService;

@Operation(summary = "컨설팅 PDF API 요청", description = "컨설팅 결과 PDF 생성 API 요청")
@ApiResponses(value = {
@io.swagger.v3.oas.annotations.responses.ApiResponse(
responseCode = "COMMON200",
description = "요청 성공",
content = {
@Content(
schema = @Schema(
implementation = ReportingResponse.class
)
)
}
)
})
@GetMapping()
public ResponseEntity<byte[]> createReportingSummaryPdf(Model model) {
model.addAttribute("title", "리포팅 요약");
model.addAttribute("content", "내용");
public ResponseEntity<ApiResponse<?>> createReportingPdf(
@LoginMember Member member,
@RequestParam Long companyId // 채팅방 id
) {
ReportingResponse reportingResponse = reportService.createReportingPdf(
member.getMemberId(), companyId);

ReportingSummaryRequest request = ReportingSummaryRequest.builder()
.title(model.getAttribute("title").toString())
.content(model.getAttribute("content").toString())
.build();
ApiResponse<ReportingResponse> response = ApiResponse.createSuccess(
HttpStatus.OK.value(),
reportingResponse,
"PDF 파일이 생성되었습니다."
);

byte[] pdfData = reportService.createReportingSummaryPdf(request);

return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.body(pdfData);
return ResponseEntity.ok(response);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.swOnCampus.AIPlatform.domain.report.web.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;

@Builder
public record ReportingResponse(
@Schema(description = "컨설팅 요약 내용", example = "컨설팅 요약")
String summary,
@Schema(description = "컨설팅 전체 내용 PDF 파일의 Base64 인코딩 데이터", example = "byte")
String pdf
) {

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</style>
</head>
<body>
<h1 th:text="${title}"></h1>
<p th:text="${content}"></p>
<h1>컨설팅 결과</h1>
<p th:utext="${content}"></p>
</body>
</html>

0 comments on commit be72209

Please sign in to comment.