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