diff --git a/pom.xml b/pom.xml
index 91ffd4b2..6e0e6a81 100644
--- a/pom.xml
+++ b/pom.xml
@@ -160,6 +160,32 @@
1.0.9
+
+
+ org.jsoup
+ jsoup
+ 1.18.1
+
+
+ com.itextpdf
+ html2pdf
+ 4.0.3
+
+
+ com.itextpdf
+ kernel
+ 7.2.5
+
+
+ com.itextpdf
+ layout
+ 7.2.5
+
+
+ com.itextpdf
+ io
+ 7.2.5
+
diff --git a/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemResponse.java b/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemResponse.java
index 72814127..1a7dbc1b 100644
--- a/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemResponse.java
+++ b/src/main/java/com/interplug/qcast/biz/displayItem/dto/ItemResponse.java
@@ -9,6 +9,9 @@ public class ItemResponse {
@Schema(description = "Itme Id")
private String itemId;
+ @Schema(description = "Item No")
+ private String itemNo;
+
@Schema(description = "Item Name")
private String itemName;
diff --git a/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java b/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java
index e9cdcc1d..270ac867 100644
--- a/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java
+++ b/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java
@@ -10,18 +10,21 @@ import com.interplug.qcast.biz.object.dto.ObjectResponse;
import com.interplug.qcast.biz.object.dto.PlanRequest;
import com.interplug.qcast.biz.object.dto.PlanResponse;
import com.interplug.qcast.biz.pwrGnrSimulation.PwrGnrSimService;
+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 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 io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
-import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
@@ -30,6 +33,8 @@ import java.util.*;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+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;
@@ -767,13 +772,7 @@ public class EstimateService {
estimateResponse.setTotPrice(
String.format("%1$,.0f", Double.parseDouble(estimateResponse.getTotPrice())));
- String excelFileName =
- "Quation_Detail_" + new SimpleDateFormat("yyyyMMdd").format(new Date());
- String excelTemplatePath =
- excelTemplateFilePath + File.separator + "excel_download_quotation_detail_template.xlsx";
-
// 발전시뮬레이션 계산
- /*
PwrGnrSimRequest pwrGnrSimRequest = new PwrGnrSimRequest();
pwrGnrSimRequest.setObjectNo(estimateResponse.getObjectNo());
pwrGnrSimRequest.setPlanNo(estimateResponse.getPlanNo());
@@ -781,7 +780,6 @@ public class EstimateService {
PwrGnrSimResponse pwrGnrSimResponse =
pwrGnrSimService.selectPwrGnrSimulation(pwrGnrSimRequest);
if (pwrGnrSimResponse != null) {
-
try {
// 발전시뮬레이션 안내사항 조회
PwrGnrSimGuideResponse pwrGnrSimGuideInfo =
@@ -790,21 +788,51 @@ public class EstimateService {
pwrGnrSimResponse.setGuideInfo(pwrGnrSimGuideInfo.getData());
}
} catch (Exception e) {
-
}
}
estimateResponse.setPwrGnrSim(pwrGnrSimResponse);
- */
+ if (true) {
+ String[] arrSection = new String[3]; // TODO Section 갯수 넣기
+ int iSection = 0;
- excelUtil.download(
- request,
- response,
- this.convertVoToMap(estimateResponse),
- this.convertListToMap(estimateItemList),
- excelFileName,
- excelTemplatePath);
+ // PDF 다운로드
+ String pdfFileName =
+ "Quation_Detail_" + new SimpleDateFormat("yyyyMMdd").format(new Date());
+ String templateFilePath = "pdf_download_quotation_detail_template.html";
+
+ // 템플릿 html 조회
+ Document doc = PdfUtil.getPdfDoc(request, templateFilePath);
+ Element elm;
+
+ // 발전시뮬레이션 pdf Html 생성
+ if (true) {
+ arrSection[iSection] = "div.section3";
+ iSection++;
+ doc = pwrGnrSimService.pwrGnrSimPdfHtml(doc, pwrGnrSimResponse);
+ } else {
+ elm = doc.getElementsByClass("section3").first();
+ elm.remove();
+ }
+
+ // pdf 다운로드
+ PdfUtil.pdfDownload(request, response, doc, pdfFileName, arrSection);
+
+ } else {
+
+ String excelFileName =
+ "Quation_Detail_" + new SimpleDateFormat("yyyyMMdd").format(new Date());
+ String excelTemplateNam = "excel_download_quotation_detail_template.xlsx";
+
+ excelUtil.download(
+ request,
+ response,
+ this.convertVoToMap(estimateResponse),
+ this.convertListToMap(estimateItemList),
+ excelFileName,
+ excelTemplateNam);
+ }
} catch (Exception e) {
e.printStackTrace();
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 7a2d1be5..066faf51 100644
--- a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java
+++ b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java
@@ -7,19 +7,24 @@ 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.InterfaceQsp;
+import java.awt.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+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;
+import org.springframework.util.ObjectUtils;
@Slf4j
@Service
@@ -1303,4 +1308,181 @@ public class PwrGnrSimService {
return guideResponse;
}
+
+ public static Document pwrGnrSimPdfHtml(Document doc, PwrGnrSimResponse data)
+ throws IOException, QcastException {
+ Element elm;
+
+ // 상단 요약정보
+ elm = doc.getElementById("objectNo");
+ elm.text(
+ ObjectUtils.nullSafeToString(data.getObjectNo() + " (Plan No : " + data.getPlanNo() + ")"));
+
+ elm = doc.getElementById("drawingEstimateCreateDate");
+ elm.text(ObjectUtils.nullSafeToString(data.getDrawingEstimateCreateDate()));
+
+ elm = doc.getElementById("prefName");
+ elm.text(ObjectUtils.nullSafeToString(data.getPrefName()));
+
+ elm = doc.getElementById("areaName");
+ elm.text(ObjectUtils.nullSafeToString(data.getAreaName()));
+
+ elm = doc.getElementById("capacity");
+ elm.text(ObjectUtils.nullSafeToString(data.getCapacity()));
+
+ elm = doc.getElementById("anlFrcsGnrt");
+ elm.text(ObjectUtils.nullSafeToString(data.getAnlFrcsGnrt()));
+
+ elm = doc.getElementById("snowfall");
+ elm.text(ObjectUtils.nullSafeToString(data.getSnowfall()));
+
+ elm = doc.getElementById("standardWindSpeedId");
+ elm.text(ObjectUtils.nullSafeToString(data.getStandardWindSpeedId()));
+
+ if (data.getFrcPwrGnrList() != null && data.getFrcPwrGnrList().length > 0) {
+
+ int[] onlyData =
+ Arrays.copyOfRange(data.getFrcPwrGnrList(), 0, data.getFrcPwrGnrList().length - 1);
+
+ int referenceValue = 300; // table 높이
+ int orgMaxValue =
+ Arrays.stream(onlyData)
+ .max()
+ .orElseThrow(() -> new QcastException(ErrorCode.INTERNAL_SERVER_ERROR, "배열이 없음"));
+ int maxValue = roundUpAuto(orgMaxValue / 8);
+
+ // chart y축
+ StringBuilder sb = new StringBuilder();
+ for (int i = 8; i >= 1; i--) {
+ sb.append("
");
+ sb.append("| ")
+ .append(maxValue * i)
+ .append(" | ");
+ sb.append("
");
+ }
+ sb.append("");
+ sb.append("| 0 | ");
+ elm = doc.getElementById("htmlY");
+ elm.append(sb.toString());
+
+ // chart 데이터
+ String[] color = {
+ "#B5D4F5", "#FFE899", "#FBC3AB", "#D1D1D1", "#FFE899", "#B5D0F0", "#C1E4B8", "#A3C9EE",
+ "#F7BBA2", "#BEBEBE", "#A8BBE0", "#B5D7A3"
+ };
+ StringBuilder sb2 = new StringBuilder();
+ for (int i = 0; i < onlyData.length; i++) {
+ double scaledValues = ((double) onlyData[i] / (maxValue * 8)) * referenceValue;
+
+ sb2.append("");
+
+ sb2.append("")
+ .append("")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" | ")
+ .append(" ")
+ .append("")
+ .append(" ");
+
+ sb2.append(
+ "");
+ sb2.append(" | ");
+ }
+ System.err.println("htmlx :: " + sb2.toString());
+ elm = doc.getElementById("htmlX");
+ elm.append(sb2.toString());
+ }
+
+ // 예측발전량
+ if (data.getFrcPwrGnrList() != null && data.getFrcPwrGnrList().length > 0) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 13; i++) {
+ sb.append("" + ObjectUtils.nullSafeToString(data.getFrcPwrGnrList()[i]) + " | ");
+ }
+
+ elm = doc.getElementById("frcPwrGnrList_detail");
+ elm.append(sb.toString());
+ }
+
+ // 모듈 list
+ if (data.getRoofModuleList() != null && data.getRoofModuleList().size() > 0) {
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < data.getRoofModuleList().size(); i++) {
+ PwrGnrSimRoofResponse listItem = data.getRoofModuleList().get(i);
+
+ sb.append("
");
+ sb.append("| " + ObjectUtils.nullSafeToString(listItem.getRoofSurface()) + " | ");
+ sb.append(
+ ""
+ + Optional.ofNullable(listItem.getSlope()).orElse("")
+ + ""
+ + Optional.ofNullable(listItem.getAngle()).orElse("")
+ + " | ");
+ sb.append("" + ObjectUtils.nullSafeToString(listItem.getAzimuth()) + " | ");
+ sb.append("" + ObjectUtils.nullSafeToString(listItem.getItemNo()) + " | ");
+ sb.append("" + ObjectUtils.nullSafeToString(listItem.getAmount()) + " | ");
+ sb.append("
");
+ }
+
+ elm = doc.getElementById("roofModuleList_detail");
+ elm.append(sb.toString());
+ }
+
+ // pcs list
+ if (data.getPcsList() != null && data.getPcsList().size() > 0) {
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < data.getPcsList().size(); i++) {
+ PwrGnrSimRoofResponse listItem = data.getPcsList().get(i);
+
+ sb.append("");
+ sb.append("| " + ObjectUtils.nullSafeToString(listItem.getItemNo()) + " | ");
+ sb.append("" + ObjectUtils.nullSafeToString(listItem.getAmount()) + " | ");
+ sb.append("
");
+ }
+
+ elm = doc.getElementById("pcsList_detail");
+ elm.append(sb.toString());
+ }
+
+ return doc;
+ }
+
+ public static int roundUpAuto(double value) {
+ int length = (int) Math.log10(value) + 1; // 숫자의 자리수를 계산
+ int place = (int) Math.pow(10, length - 1); // 자리수에 따른 올림 기준(10, 100, 1000 등)
+
+ return (int) Math.ceil(value / place) * place;
+ }
}
diff --git a/src/main/java/com/interplug/qcast/util/ExcelUtil.java b/src/main/java/com/interplug/qcast/util/ExcelUtil.java
index 66d5b424..90213d47 100644
--- a/src/main/java/com/interplug/qcast/util/ExcelUtil.java
+++ b/src/main/java/com/interplug/qcast/util/ExcelUtil.java
@@ -26,7 +26,9 @@ public class ExcelUtil {
* @param map 엑셀 출력데이터
* @param list 엑셀 출력 목록 데이터
* @param fileName 다운로드 파일명
- * @param templateFilePath 템플릿 파일경로
+ * @param templateFileName
+ * @throws ParsePropertyException
+ * @throws InvalidFormatException
*/
public void download(
HttpServletRequest request,
@@ -34,10 +36,15 @@ public class ExcelUtil {
Map map,
List