1+ package com .neeis .neeis .domain .counsel .controller ;
2+
3+ import com .neeis .neeis .domain .counsel .service .CounselPdfService ;
4+ import com .neeis .neeis .domain .counsel .service .CounselService ;
5+ import com .neeis .neeis .global .jwt .CustomUserDetails ;
6+ import io .swagger .v3 .oas .annotations .Operation ;
7+ import io .swagger .v3 .oas .annotations .Parameter ;
8+ import io .swagger .v3 .oas .annotations .responses .ApiResponse ;
9+ import io .swagger .v3 .oas .annotations .responses .ApiResponses ;
10+ import io .swagger .v3 .oas .annotations .tags .Tag ;
11+ import lombok .RequiredArgsConstructor ;
12+ import lombok .extern .slf4j .Slf4j ;
13+ import org .springframework .http .HttpHeaders ;
14+ import org .springframework .http .MediaType ;
15+ import org .springframework .http .ResponseEntity ;
16+ import org .springframework .security .core .annotation .AuthenticationPrincipal ;
17+ import org .springframework .web .bind .annotation .*;
18+
19+ import java .time .LocalDateTime ;
20+ import java .time .format .DateTimeFormatter ;
21+
22+ /**
23+ * ์๋ด ๋ณด๊ณ ์ PDF API ์ปจํธ๋กค๋ฌ
24+ *
25+ * ๊ธฐ์กด CounselService๋ฅผ ํตํด ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ด ๋ฐ์ดํฐ๋ฅผ PDF๋ก ์์ฑํฉ๋๋ค.
26+ */
27+ @ Slf4j
28+ @ RestController
29+ @ RequestMapping ("/reports/counsels" )
30+ @ RequiredArgsConstructor
31+ @ Tag (name = "์๋ด PDF" , description = "์๋ด ๋ณด๊ณ ์ PDF ์์ฑ API" )
32+ public class CounselPdfController {
33+
34+ // โ
CounselService ์ฌ์ฉ (CounselPdfService ๋์ )
35+ private final CounselPdfService counselPdfService ;
36+
37+ @ GetMapping ("/{counselId}/pdf" )
38+ @ Operation (summary = "๊ฐ๋ณ ์๋ด PDF ์์ฑ" , description = "ํน์ ์๋ด์ ๋ํ PDF ๋ณด๊ณ ์๋ฅผ ์์ฑํฉ๋๋ค." )
39+ @ ApiResponses ({
40+ @ ApiResponse (responseCode = "200" , description = "PDF ์์ฑ ์ฑ๊ณต" ),
41+ @ ApiResponse (responseCode = "403" , description = "์ ๊ทผ ๊ถํ ์์" ),
42+ @ ApiResponse (responseCode = "404" , description = "์๋ด์ ์ฐพ์ ์ ์์" )
43+ })
44+ public ResponseEntity <byte []> generateSingleCounselPdf (
45+ @ Parameter (description = "์๋ด ID" , required = true )
46+ @ PathVariable Long counselId ,
47+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
48+
49+ log .info ("๊ฐ๋ณ ์๋ด PDF ์์ฑ ์์ฒญ - ์ฌ์ฉ์: {}, ์๋ดID: {}" , userDetails .getUsername (), counselId );
50+
51+ try {
52+ // CounselService๋ฅผ ํตํด PDF ์์ฑ (์ค์ ๋ฐ์ดํฐ ์ฌ์ฉ)
53+ byte [] pdfBytes = counselPdfService .generateSingleCounselPdf (userDetails .getUsername (), counselId );
54+
55+ // ํ์ผ๋ช
์์ฑ (์๋ดID_๋ ์ง.pdf)
56+ String filename = String .format ("counsel_report_%d_%s.pdf" ,
57+ counselId ,
58+ LocalDateTime .now ().format (DateTimeFormatter .ofPattern ("yyyyMMdd_HHmmss" )));
59+
60+ // HTTP ์๋ต ํค๋ ์ค์
61+ HttpHeaders headers = createPdfHeaders (filename , pdfBytes .length );
62+
63+ log .info ("๊ฐ๋ณ ์๋ด PDF ์์ฑ ์๋ฃ - ํ์ผ๋ช
: {}, ํฌ๊ธฐ: {} bytes" , filename , pdfBytes .length );
64+
65+ return ResponseEntity .ok ()
66+ .headers (headers )
67+ .body (pdfBytes );
68+
69+ } catch (Exception e ) {
70+ log .error ("๊ฐ๋ณ ์๋ด PDF ์์ฑ ์คํจ - ์๋ดID: {}, ์ค๋ฅ: {}" , counselId , e .getMessage (), e );
71+ throw e ;
72+ }
73+ }
74+
75+ @ GetMapping ("/students/{studentId}/history/pdf" )
76+ @ Operation (summary = "ํ์๋ณ ์๋ด ์ด๋ ฅ PDF ์์ฑ" , description = "ํน์ ํ์์ ๋ชจ๋ ์๋ด ์ด๋ ฅ์ PDF๋ก ์์ฑํฉ๋๋ค." )
77+ @ ApiResponses ({
78+ @ ApiResponse (responseCode = "200" , description = "PDF ์์ฑ ์ฑ๊ณต" ),
79+ @ ApiResponse (responseCode = "403" , description = "์ ๊ทผ ๊ถํ ์์" ),
80+ @ ApiResponse (responseCode = "404" , description = "์๋ด ์ด๋ ฅ์ ์ฐพ์ ์ ์์" )
81+ })
82+ public ResponseEntity <byte []> generateStudentCounselHistoryPdf (
83+ @ Parameter (description = "ํ์ ID" , required = true )
84+ @ PathVariable Long studentId ,
85+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
86+
87+ log .info ("ํ์ ์๋ด ์ด๋ ฅ PDF ์์ฑ ์์ฒญ - ์ฌ์ฉ์: {}, ํ์ID: {}" , userDetails .getUsername (), studentId );
88+
89+ try {
90+ // CounselService๋ฅผ ํตํด PDF ์์ฑ (์ค์ ๋ฐ์ดํฐ ์ฌ์ฉ)
91+ byte [] pdfBytes = counselPdfService .generateStudentCounselHistoryPdf (userDetails .getUsername (), studentId );
92+
93+ // ํ์ผ๋ช
์์ฑ (student_counsel_history_ํ์ID_๋ ์ง.pdf)
94+ String filename = String .format ("student_counsel_history_%d_%s.pdf" ,
95+ studentId ,
96+ LocalDateTime .now ().format (DateTimeFormatter .ofPattern ("yyyyMMdd_HHmmss" )));
97+
98+ // HTTP ์๋ต ํค๋ ์ค์
99+ HttpHeaders headers = createPdfHeaders (filename , pdfBytes .length );
100+
101+ log .info ("ํ์ ์๋ด ์ด๋ ฅ PDF ์์ฑ ์๋ฃ - ํ์ผ๋ช
: {}, ํฌ๊ธฐ: {} bytes" , filename , pdfBytes .length );
102+
103+ return ResponseEntity .ok ()
104+ .headers (headers )
105+ .body (pdfBytes );
106+
107+ } catch (Exception e ) {
108+ log .error ("ํ์ ์๋ด ์ด๋ ฅ PDF ์์ฑ ์คํจ - ํ์ID: {}, ์ค๋ฅ: {}" , studentId , e .getMessage (), e );
109+ throw e ;
110+ }
111+ }
112+
113+ /**
114+ * PDF ์๋ต์ ์ํ HTTP ํค๋ ์์ฑ
115+ */
116+ private HttpHeaders createPdfHeaders (String filename , int contentLength ) {
117+ HttpHeaders headers = new HttpHeaders ();
118+ headers .setContentType (MediaType .APPLICATION_PDF );
119+ headers .setContentDispositionFormData ("attachment" , filename );
120+ headers .setContentLength (contentLength );
121+ headers .add ("Cache-Control" , "no-cache, no-store, must-revalidate" );
122+ headers .add ("Pragma" , "no-cache" );
123+ headers .add ("Expires" , "0" );
124+ return headers ;
125+ }
126+ }
0 commit comments