Skip to content

Commit be72209

Browse files
authored
Merge pull request #13 from SWOnCampus/refactor/#4-convert-report-pdf
컨설팅 결과 PDF로 변환
2 parents a22ea82 + 9b4940e commit be72209

File tree

8 files changed

+97
-52
lines changed

8 files changed

+97
-52
lines changed

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ dependencies {
4646
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
4747
// flying saucer
4848
implementation 'org.xhtmlrenderer:flying-saucer-pdf:9.9.1'
49+
// markdown
50+
implementation 'org.commonmark:commonmark:0.21.0'
4951
// postgre
5052
implementation 'org.postgresql:postgresql:42.7.4'
5153
runtimeOnly 'org.postgresql:postgresql'

src/main/java/com/swOnCampus/AIPlatform/AiPlatformApplication.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
})
1616
public class AiPlatformApplication {
1717

18-
public static void main(String[] args) {
19-
SpringApplication.run(AiPlatformApplication.class, args);
20-
}
18+
public static void main(String[] args) {
19+
SpringApplication.run(AiPlatformApplication.class, args);
20+
}
2121

2222
}
Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
package com.swOnCampus.AIPlatform.domain.report.service;
22

3-
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingSummaryRequest;
3+
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingResponse;
44

55
public interface ReportService {
66

7-
/**
8-
* 리포팅 요약된 내용을 html로 변환 하여 pdf를 생성하는 메서드
9-
*
10-
* @param request : 리포팅 요약 데이터를 담은 request 객체
11-
* @return : 생성된 PDF 파일의 바이트 배열
12-
*/
13-
byte[] createReportingSummaryPdf(ReportingSummaryRequest request);
14-
}
7+
ReportingResponse createReportingPdf(Long memberId, Long companyId);
8+
}

src/main/java/com/swOnCampus/AIPlatform/domain/report/service/ReportServiceImpl.java

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package com.swOnCampus.AIPlatform.domain.report.service;
22

33
import com.lowagie.text.pdf.BaseFont;
4-
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingSummaryRequest;
4+
import com.swOnCampus.AIPlatform.domain.consulting.entity.Consulting;
5+
import com.swOnCampus.AIPlatform.domain.consulting.exception.ConsultingErrorCode;
6+
import com.swOnCampus.AIPlatform.domain.consulting.repository.ConsultingRepository;
7+
import com.swOnCampus.AIPlatform.domain.report.exception.ReportErrorCode;
8+
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingResponse;
59
import com.swOnCampus.AIPlatform.global.exception.GlobalException;
610
import java.io.ByteArrayOutputStream;
11+
import java.util.Base64;
712
import java.util.Map;
8-
9-
import com.swOnCampus.AIPlatform.domain.report.exception.ReportErrorCode;
1013
import lombok.RequiredArgsConstructor;
14+
import org.commonmark.parser.Parser;
15+
import org.commonmark.renderer.html.HtmlRenderer;
1116
import org.springframework.beans.factory.annotation.Value;
1217
import org.springframework.core.io.ClassPathResource;
1318
import org.springframework.stereotype.Service;
@@ -20,19 +25,31 @@
2025
public class ReportServiceImpl implements ReportService {
2126

2227
private final TemplateEngine templateEngine;
28+
private final ConsultingRepository consultingRepository;
2329

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

2733
@Override
28-
public byte[] createReportingSummaryPdf(ReportingSummaryRequest request) {
34+
public ReportingResponse createReportingPdf(Long memberId, Long companyId) {
35+
Consulting consulting = consultingRepository.findByCompanyId(companyId)
36+
.orElseThrow(() -> new GlobalException(ConsultingErrorCode.NOT_EXIST_CONSULTING));
37+
38+
String summaryHtml = consulting.getSummary().replace("\n", "<br />");
39+
String renderedMarkdown = renderMarkdown(summaryHtml);
40+
2941
Map<String, Object> contextVariables = Map.of(
30-
"title", request.title(),
31-
"content", request.content()
42+
"content", renderedMarkdown
3243
);
3344
String html = createHtmlFromTemplate(contextVariables);
45+
byte[] pdfBytes = convertHtmlToPdf(html);
3446

35-
return convertHtmlToPdf(html);
47+
ReportingResponse response = new ReportingResponse(
48+
consulting.getSummary(),
49+
Base64.getEncoder().encodeToString(pdfBytes)
50+
);
51+
52+
return response;
3653
}
3754

3855
private String createHtmlFromTemplate(Map<String, Object> contextVariables) {
@@ -57,12 +74,18 @@ private byte[] convertHtmlToPdf(String html) {
5774
private void setFont(ITextRenderer renderer) {
5875
try {
5976
renderer.getFontResolver().addFont(
60-
new ClassPathResource(fontPath).getURL().toString(),
61-
BaseFont.IDENTITY_H,
62-
BaseFont.EMBEDDED
77+
new ClassPathResource(fontPath).getURL().toString(),
78+
BaseFont.IDENTITY_H,
79+
BaseFont.EMBEDDED
6380
);
6481
} catch (Exception e) {
6582
throw new GlobalException(ReportErrorCode.NOT_FOUND_FONT);
6683
}
6784
}
68-
}
85+
86+
private String renderMarkdown(String markdownText) {
87+
Parser parser = Parser.builder().build();
88+
HtmlRenderer renderer = HtmlRenderer.builder().build();
89+
return renderer.render(parser.parse(markdownText));
90+
}
91+
}
Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,59 @@
11
package com.swOnCampus.AIPlatform.domain.report.web.controller;
22

3+
import com.swOnCampus.AIPlatform.domain.member.entity.Member;
34
import com.swOnCampus.AIPlatform.domain.report.service.ReportService;
4-
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingSummaryRequest;
5+
import com.swOnCampus.AIPlatform.domain.report.web.dto.ReportingResponse;
6+
import com.swOnCampus.AIPlatform.global.annotation.LoginMember;
7+
import com.swOnCampus.AIPlatform.global.response.ApiResponse;
8+
import io.swagger.v3.oas.annotations.Operation;
9+
import io.swagger.v3.oas.annotations.media.Content;
10+
import io.swagger.v3.oas.annotations.media.Schema;
11+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
12+
import io.swagger.v3.oas.annotations.tags.Tag;
513
import lombok.RequiredArgsConstructor;
6-
import org.springframework.http.MediaType;
14+
import org.springframework.http.HttpStatus;
715
import org.springframework.http.ResponseEntity;
8-
import org.springframework.ui.Model;
916
import org.springframework.web.bind.annotation.GetMapping;
1017
import org.springframework.web.bind.annotation.RequestMapping;
18+
import org.springframework.web.bind.annotation.RequestParam;
1119
import org.springframework.web.bind.annotation.RestController;
1220

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

1827
private final ReportService reportService;
1928

29+
@Operation(summary = "컨설팅 PDF API 요청", description = "컨설팅 결과 PDF 생성 API 요청")
30+
@ApiResponses(value = {
31+
@io.swagger.v3.oas.annotations.responses.ApiResponse(
32+
responseCode = "COMMON200",
33+
description = "요청 성공",
34+
content = {
35+
@Content(
36+
schema = @Schema(
37+
implementation = ReportingResponse.class
38+
)
39+
)
40+
}
41+
)
42+
})
2043
@GetMapping()
21-
public ResponseEntity<byte[]> createReportingSummaryPdf(Model model) {
22-
model.addAttribute("title", "리포팅 요약");
23-
model.addAttribute("content", "내용");
44+
public ResponseEntity<ApiResponse<?>> createReportingPdf(
45+
@LoginMember Member member,
46+
@RequestParam Long companyId // 채팅방 id
47+
) {
48+
ReportingResponse reportingResponse = reportService.createReportingPdf(
49+
member.getMemberId(), companyId);
2450

25-
ReportingSummaryRequest request = ReportingSummaryRequest.builder()
26-
.title(model.getAttribute("title").toString())
27-
.content(model.getAttribute("content").toString())
28-
.build();
51+
ApiResponse<ReportingResponse> response = ApiResponse.createSuccess(
52+
HttpStatus.OK.value(),
53+
reportingResponse,
54+
"PDF 파일이 생성되었습니다."
55+
);
2956

30-
byte[] pdfData = reportService.createReportingSummaryPdf(request);
31-
32-
return ResponseEntity.ok()
33-
.contentType(MediaType.APPLICATION_PDF)
34-
.body(pdfData);
57+
return ResponseEntity.ok(response);
3558
}
36-
}
59+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.swOnCampus.AIPlatform.domain.report.web.dto;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.Builder;
5+
6+
@Builder
7+
public record ReportingResponse(
8+
@Schema(description = "컨설팅 요약 내용", example = "컨설팅 요약")
9+
String summary,
10+
@Schema(description = "컨설팅 전체 내용 PDF 파일의 Base64 인코딩 데이터", example = "byte")
11+
String pdf
12+
) {
13+
14+
}

src/main/java/com/swOnCampus/AIPlatform/domain/report/web/dto/ReportingSummaryRequest.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/main/resources/template/reporting-summary-template.html renamed to src/main/resources/templates/reporting-summary-template.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</style>
1717
</head>
1818
<body>
19-
<h1 th:text="${title}"></h1>
20-
<p th:text="${content}"></p>
19+
<h1>컨설팅 결과</h1>
20+
<p th:utext="${content}"></p>
2121
</body>
2222
</html>

0 commit comments

Comments
 (0)