diff --git a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimController.java b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimController.java index 8015e0a5..4b32092c 100644 --- a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimController.java +++ b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimController.java @@ -1,17 +1,17 @@ package com.interplug.qcast.biz.pwrGnrSimulation; +import com.interplug.qcast.biz.estimate.dto.EstimateRequest; import com.interplug.qcast.biz.pwrGnrSimulation.dto.PwrGnrSimGuideResponse; import com.interplug.qcast.biz.pwrGnrSimulation.dto.PwrGnrSimRequest; import com.interplug.qcast.biz.pwrGnrSimulation.dto.PwrGnrSimResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @Slf4j @RestController @@ -36,4 +36,15 @@ public class PwrGnrSimController { public PwrGnrSimGuideResponse selectPwrGnrSimulationGuideInfo() throws Exception { return pwrGnrSimService.selectPwrGnrSimulationGuideInfo(); } + + @Operation(description = "견적서를 엑셀로 다운로드한다.") + @PostMapping("/excel-download") + @ResponseStatus(HttpStatus.OK) + public void excelDownload( + HttpServletRequest request, + HttpServletResponse response, + @RequestBody EstimateRequest estimateRequest) + throws Exception { + pwrGnrSimService.excelDownload(request, response, estimateRequest); + } } diff --git a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java index 48e3e567..23f89998 100644 --- a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java +++ b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java @@ -2,23 +2,28 @@ package com.interplug.qcast.biz.pwrGnrSimulation; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.interplug.qcast.biz.estimate.dto.*; import com.interplug.qcast.biz.pwrGnrSimulation.dto.*; import com.interplug.qcast.config.Exception.ErrorCode; import com.interplug.qcast.config.Exception.QcastException; +import com.interplug.qcast.config.message.Messages; +import com.interplug.qcast.util.ExcelUtil; import com.interplug.qcast.util.InterfaceQsp; +import com.interplug.qcast.util.PdfUtil; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.*; import java.nio.charset.StandardCharsets; import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; +import java.text.SimpleDateFormat; +import java.util.*; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; @@ -29,6 +34,8 @@ import org.springframework.stereotype.Service; public class PwrGnrSimService { private final InterfaceQsp interfaceQsp; + @Autowired Messages message; + @Value("${qsp.url}") private String qspUrl; @@ -1484,4 +1491,105 @@ public class PwrGnrSimService { return (int) Math.ceil(value / place) * place; } + + public void excelDownload( + HttpServletRequest request, HttpServletResponse response, EstimateRequest estimateRequest) + throws Exception { + + // Validation + if (StringUtils.isEmpty(estimateRequest.getObjectNo())) { + throw new QcastException( + ErrorCode.INVALID_INPUT_VALUE, + message.getMessage("common.message.required.data", "Object No")); + } + if (StringUtils.isEmpty(estimateRequest.getPlanNo())) { + throw new QcastException( + ErrorCode.INVALID_INPUT_VALUE, + message.getMessage("common.message.required.data", "Plan No")); + } + + try { + + EstimateResponse estimateResponse = new EstimateResponse(); + estimateResponse.setObjectNo(estimateRequest.getObjectNo()); + estimateResponse.setPlanNo(estimateRequest.getPlanNo()); + + // file Name 명이 없는경우 + if (estimateRequest.getFileName() == null || "".equals(estimateRequest.getFileName())) { + estimateRequest.setFileName( + estimateResponse.getObjectNo() + + "_" + + new SimpleDateFormat("yyyyMMdd").format(new Date())); + } + + // 발전시뮬레이션 계산 + PwrGnrSimRequest pwrGnrSimRequest = new PwrGnrSimRequest(); + pwrGnrSimRequest.setObjectNo(estimateResponse.getObjectNo()); + pwrGnrSimRequest.setPlanNo(estimateResponse.getPlanNo()); + + PwrGnrSimResponse pwrGnrSimResponse = this.selectPwrGnrSimulation(pwrGnrSimRequest); + pwrGnrSimResponse.setPwrGnrSimType(estimateRequest.getPwrGnrSimType()); + + // 발전시뮬레이션 타입에 따른 list 셋팅 + if ("A".equals(estimateRequest.getPwrGnrSimType())) { + pwrGnrSimResponse.setFrcPwrGnrList(pwrGnrSimResponse.getHatsudenryouAll()); + } else if ("B".equals(estimateRequest.getPwrGnrSimType())) { + pwrGnrSimResponse.setFrcPwrGnrList(pwrGnrSimResponse.getHatsudenryouAllSnow()); + } else if ("C".equals(estimateRequest.getPwrGnrSimType())) { + pwrGnrSimResponse.setFrcPwrGnrList(pwrGnrSimResponse.getHatsudenryouPeakcutAll()); + } else if ("D".equals(estimateRequest.getPwrGnrSimType())) { + pwrGnrSimResponse.setFrcPwrGnrList(pwrGnrSimResponse.getHatsudenryouPeakcutAllSnow()); + } + + pwrGnrSimResponse.setIntFrcPwrGnrList( + Arrays.stream(pwrGnrSimResponse.getFrcPwrGnrList()) + .map(s -> s.replace(",", "")) // , 제거 + .mapToInt(Integer::parseInt) // 문자열을 int로 변환 + .toArray()); + + if (pwrGnrSimResponse != null) { + try { + // 발전시뮬레이션 안내사항 조회 + PwrGnrSimGuideResponse pwrGnrSimGuideInfo = this.selectPwrGnrSimulationGuideInfo(); + if (pwrGnrSimGuideInfo != null) { + pwrGnrSimResponse.setGuideInfo(pwrGnrSimGuideInfo.getData()); + } + } catch (Exception e) { + } + } + + estimateResponse.setPwrGnrSim(pwrGnrSimResponse); + + if ("PDF".equals(estimateRequest.getSchDownload())) { // PDF 다운로드 + String[] arrSection = {"div.section3"}; + String templateFilePath = "pdf_download_simulation_detail_template.html"; + + // 템플릿 html 조회 + Document doc = PdfUtil.getPdfDoc(request, templateFilePath); + + // 발전시뮬레이션 pdf Html 생성 + doc = this.pwrGnrSimPdfHtml(doc, pwrGnrSimResponse); + + // pdf 다운로드 + PdfUtil.pdfDownload(request, response, doc, estimateRequest.getFileName(), null, true); + + } else { + + String excelTemplateName = "excel_download_simulation_detail_template.xlsx"; + + ExcelUtil excelUtil = new ExcelUtil(); + excelUtil.download( + request, + response, + excelUtil.convertVoToMap(estimateResponse), + null, + estimateRequest.getFileName(), + excelTemplateName); + } + + } catch (Exception e) { + e.printStackTrace(); + throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR); + } + } } diff --git a/src/main/java/com/interplug/qcast/util/PdfUtil.java b/src/main/java/com/interplug/qcast/util/PdfUtil.java index 22ae5735..da65672a 100644 --- a/src/main/java/com/interplug/qcast/util/PdfUtil.java +++ b/src/main/java/com/interplug/qcast/util/PdfUtil.java @@ -3,6 +3,7 @@ package com.interplug.qcast.util; import com.itextpdf.html2pdf.ConverterProperties; import com.itextpdf.html2pdf.HtmlConverter; import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider; +import com.itextpdf.kernel.geom.PageSize; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.kernel.pdf.PdfWriter; @@ -60,6 +61,7 @@ public class PdfUtil { * @param doc * @param pdfFileName 파일명 * @param arrSection 노출 Section + * @param isLandscape 가로/세로 설정 * @throws IOException */ public static void pdfDownload( @@ -67,9 +69,13 @@ public class PdfUtil { HttpServletResponse response, Document doc, String pdfFileName, - String[] arrSection) + String[] arrSection, + boolean isLandscape) throws IOException { + // 가로 세로 설정 + PageSize pageSize = isLandscape ? PageSize.A4.rotate() : PageSize.A4; + // 응답에 PDF 설정 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=\"" + pdfFileName + "\".pdf"); @@ -79,6 +85,8 @@ public class PdfUtil { PdfWriter writer = new PdfWriter(os); PdfDocument pdfDoc = new PdfDocument(writer)) { + pdfDoc.setDefaultPageSize(pageSize); + // 폰트 설정 ConverterProperties properties = new ConverterProperties(); String fontPath = "template/pdf/BIZUDPGothic-Regular.ttf"; @@ -88,7 +96,9 @@ public class PdfUtil { if (arrSection == null || arrSection.length == 0) { // HTML 전체를 pdfDoc에 직접 변환 HtmlConverter.convertToPdf( - new ByteArrayInputStream(doc.html().getBytes(StandardCharsets.UTF_8)), os, properties); + new ByteArrayInputStream(doc.html().getBytes(StandardCharsets.UTF_8)), + pdfDoc, + properties); os.flush(); } else { // arrSection이 있는 경우 각 섹션을 개별적으로 변환 후 병합 @@ -108,6 +118,8 @@ public class PdfUtil { PdfWriter tempWriter = new PdfWriter(tempOutputStream); PdfDocument tempPdfDoc = new PdfDocument(tempWriter)) { + tempPdfDoc.setDefaultPageSize(pageSize); + HtmlConverter.convertToPdf( new ByteArrayInputStream(sectionHtml.getBytes(StandardCharsets.UTF_8)), tempPdfDoc, @@ -161,4 +173,15 @@ public class PdfUtil { } return fontProvider; } + + public static void pdfDownload( + HttpServletRequest request, + HttpServletResponse response, + Document doc, + String pdfFileName, + String[] arrSection) + throws IOException { + + pdfDownload(request, response, doc, pdfFileName, arrSection, false); // 기본값은 세로 + } } diff --git a/src/main/resources/template/excel/excel_download_simulation_detail_template.xlsx b/src/main/resources/template/excel/excel_download_simulation_detail_template.xlsx new file mode 100644 index 00000000..bd924070 Binary files /dev/null and b/src/main/resources/template/excel/excel_download_simulation_detail_template.xlsx differ diff --git a/src/main/resources/template/pdf/pdf_download_simulation_detail_template.html b/src/main/resources/template/pdf/pdf_download_simulation_detail_template.html new file mode 100644 index 00000000..ba5e6fcd --- /dev/null +++ b/src/main/resources/template/pdf/pdf_download_simulation_detail_template.html @@ -0,0 +1,494 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
物件番号作成日都道府県日射量観測地点
システム容量年間予測発電量積雪条件風速条件
+
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
1月2月3月4月5月6月7月8月9月10月11月12月
+
+ +
+ ● 予測発電量[kWh] +
+ + + + + + + + + + + + + + + + + + + + + + +
1月2月3月4月5月6月7月8月9月10月11月12月合計
+
+ +
+ + + + + + + + + + + + +
屋根面傾斜角度方位角(度)太陽電池モジュール枚数(枚)
+ + + + + + + + + +
パワーコンディショナー
+
+
+
+ ● Hanwha Japan 年間発電量シミュレーション案内事項 +
+
+

+    
+
+ + \ No newline at end of file