견적서 PDF 다운로드
This commit is contained in:
parent
5faedebb8b
commit
124f64ff74
26
pom.xml
26
pom.xml
@ -160,6 +160,32 @@
|
||||
<version>1.0.9</version>
|
||||
</dependency>
|
||||
|
||||
<!--pdf-->
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.18.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>html2pdf</artifactId>
|
||||
<version>4.0.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>kernel</artifactId>
|
||||
<version>7.2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>layout</artifactId>
|
||||
<version>7.2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>io</artifactId>
|
||||
<version>7.2.5</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -18,13 +18,13 @@ 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;
|
||||
@ -32,6 +32,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;
|
||||
@ -693,10 +695,6 @@ public class EstimateService {
|
||||
estimateResponse.setTotPrice(
|
||||
String.format("%1$,.0f", Double.parseDouble(estimateResponse.getTotPrice())));
|
||||
|
||||
String excelFileName = "Quation_Detail";
|
||||
String excelTemplatePath =
|
||||
excelTemplateFilePath + File.separator + "excel_download_quotation_detail_template.xlsx";
|
||||
|
||||
// 발전시뮬레이션 계산
|
||||
PwrGnrSimRequest pwrGnrSimRequest = new PwrGnrSimRequest();
|
||||
pwrGnrSimRequest.setObjectNo(estimateResponse.getObjectNo());
|
||||
@ -714,19 +712,58 @@ public class EstimateService {
|
||||
pwrGnrSimResponse.setGuideInfo(pwrGnrSimGuideInfo.getData());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
estimateResponse.setPwrGnrSim(pwrGnrSimResponse);
|
||||
|
||||
excelUtil.download(
|
||||
request,
|
||||
response,
|
||||
this.convertVoToMap(estimateResponse),
|
||||
this.convertListToMap(estimateItemList),
|
||||
excelFileName,
|
||||
excelTemplatePath);
|
||||
if (true) {
|
||||
String[] arrSection = new String[3]; // TODO Section 갯수 넣기
|
||||
int iSection = 0;
|
||||
|
||||
// PDF 다운로드
|
||||
String templateFilePath = "pdf_download_quotation_detail_template.html";
|
||||
String pdfFileName = "Quation_Detail";
|
||||
|
||||
// 템플릿 html 조회
|
||||
Document doc = PdfUtil.getPdfDoc(request, templateFilePath);
|
||||
Element elm;
|
||||
|
||||
arrSection[iSection] = "div.section1";
|
||||
iSection++;
|
||||
|
||||
elm = doc.getElementsByClass("section2").first();
|
||||
elm.remove();
|
||||
// 1은 나누고 2는 지우고 3은 그리고
|
||||
|
||||
// 발전시뮬레이션 pdf Html 생성
|
||||
if (true) {
|
||||
arrSection[iSection] = "div.section3";
|
||||
iSection++;
|
||||
doc = pwrGnrSimService.pwrGnrSimPdfHtml(doc, pwrGnrSimResponse);
|
||||
} else {
|
||||
elm = doc.getElementsByClass("section3").first();
|
||||
elm.remove();
|
||||
}
|
||||
|
||||
System.err.println(doc.toString());
|
||||
|
||||
// pdf 다운로드
|
||||
PdfUtil.pdfDownload(request, response, doc, pdfFileName, arrSection);
|
||||
|
||||
} else {
|
||||
|
||||
String excelFileName = "Quation_Detail";
|
||||
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();
|
||||
|
||||
@ -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("<tr>");
|
||||
sb.append("<td ")
|
||||
.append(i == 8 ? "class='top'" : "")
|
||||
.append(">")
|
||||
.append(maxValue * i)
|
||||
.append("</td>");
|
||||
sb.append("</tr>");
|
||||
}
|
||||
sb.append("<tr>");
|
||||
sb.append("<td class='zero'>0</td>");
|
||||
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("<td class='bar-cell'>");
|
||||
|
||||
sb2.append("<table class='chart-line' style='border-collapse: collapse;'>")
|
||||
.append("<tbody>")
|
||||
.append("<tr>")
|
||||
.append("<td class='top' style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("<tr>")
|
||||
.append("<td style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("<tr>")
|
||||
.append("<td style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("<tr>")
|
||||
.append("<td style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("<tr>")
|
||||
.append("<td style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("<tr>")
|
||||
.append("<td style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("<tr>")
|
||||
.append("<td style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("<tr>")
|
||||
.append("<td style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("<tr>")
|
||||
.append("<td style='border-bottom: 1px solid #ddd;'></td>")
|
||||
.append("</tr>")
|
||||
.append("</tbody>")
|
||||
.append("</table>");
|
||||
|
||||
sb2.append(
|
||||
"<div class='bar' style='height: "
|
||||
+ scaledValues
|
||||
+ "px; background-color: "
|
||||
+ color[i]
|
||||
+ "'></div>");
|
||||
sb2.append("</td>");
|
||||
}
|
||||
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("<td>" + ObjectUtils.nullSafeToString(data.getFrcPwrGnrList()[i]) + "</td>");
|
||||
}
|
||||
|
||||
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("<tr>");
|
||||
sb.append("<td>" + ObjectUtils.nullSafeToString(listItem.getRoofSurface()) + "</td>");
|
||||
sb.append(
|
||||
"<td>"
|
||||
+ Optional.ofNullable(listItem.getSlope()).orElse("")
|
||||
+ ""
|
||||
+ Optional.ofNullable(listItem.getAngle()).orElse("")
|
||||
+ "</td>");
|
||||
sb.append("<td>" + ObjectUtils.nullSafeToString(listItem.getAzimuth()) + "</td>");
|
||||
sb.append("<td>" + ObjectUtils.nullSafeToString(listItem.getItemNo()) + "</td>");
|
||||
sb.append("<td>" + ObjectUtils.nullSafeToString(listItem.getAmount()) + "</td>");
|
||||
sb.append("</tr>");
|
||||
}
|
||||
|
||||
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("<tr>");
|
||||
sb.append("<td>" + ObjectUtils.nullSafeToString(listItem.getItemNo()) + "</td>");
|
||||
sb.append("<td>" + ObjectUtils.nullSafeToString(listItem.getAmount()) + "</td>");
|
||||
sb.append("</tr>");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<String, Object> map,
|
||||
List<Map<String, Object>> list,
|
||||
String fileName,
|
||||
String templateFilePath)
|
||||
String templateFileName)
|
||||
throws ParsePropertyException, InvalidFormatException {
|
||||
try {
|
||||
InputStream is = new BufferedInputStream(new FileInputStream(templateFilePath));
|
||||
|
||||
String templateFilePath = "template/excel/" + templateFileName;
|
||||
InputStream templateStream =
|
||||
PdfUtil.class.getClassLoader().getResourceAsStream(templateFilePath);
|
||||
|
||||
InputStream is = new BufferedInputStream(templateStream);
|
||||
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".xlsx\"");
|
||||
|
||||
|
||||
151
src/main/java/com/interplug/qcast/util/PdfUtil.java
Normal file
151
src/main/java/com/interplug/qcast/util/PdfUtil.java
Normal file
@ -0,0 +1,151 @@
|
||||
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.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.utils.PdfMerger;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PdfUtil {
|
||||
// HTML 템플릿 파일 경로
|
||||
// @Value("${file.excel.template.path}")
|
||||
// private String excelTemplateFilePath;
|
||||
|
||||
/**
|
||||
* 파일 템플릿 HTML 불러오기
|
||||
*
|
||||
* @param request
|
||||
* @param templateFileName
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Document getPdfDoc(HttpServletRequest request, String templateFileName)
|
||||
throws IOException {
|
||||
|
||||
String templateFilePath = "template/pdf/" + templateFileName;
|
||||
InputStream templateStream =
|
||||
PdfUtil.class.getClassLoader().getResourceAsStream(templateFilePath);
|
||||
|
||||
if (templateStream == null) {
|
||||
throw new FileNotFoundException("Template file not found: " + templateFilePath);
|
||||
}
|
||||
|
||||
Document doc = Jsoup.parse(templateStream, StandardCharsets.UTF_8.name(), "");
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* PDF 다운로드
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param doc
|
||||
* @param pdfFileName 파일명
|
||||
* @param arrSection 노출 Section
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void pdfDownload(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
Document doc,
|
||||
String pdfFileName,
|
||||
String[] arrSection)
|
||||
throws IOException {
|
||||
|
||||
// 응답에 PDF 설정
|
||||
response.setContentType("application/pdf");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + pdfFileName + "\"");
|
||||
|
||||
try (OutputStream os = response.getOutputStream();
|
||||
PdfWriter writer = new PdfWriter(os);
|
||||
PdfDocument pdfDoc = new PdfDocument(writer)) {
|
||||
|
||||
// ConverterProperties 생성
|
||||
ConverterProperties properties = new ConverterProperties();
|
||||
|
||||
// 폰트 설정
|
||||
DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, false);
|
||||
String fontPath = "template/pdf/BIZUDPGothic-Regular.ttf";
|
||||
InputStream fontStream = PdfUtil.class.getClassLoader().getResourceAsStream(fontPath);
|
||||
|
||||
if (fontStream != null) {
|
||||
File tempFontFile = Files.createTempFile("BIZUDPGothic-Regular", ".ttf").toFile();
|
||||
Files.copy(
|
||||
fontStream, tempFontFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||
fontProvider.addFont(tempFontFile.getAbsolutePath());
|
||||
fontStream.close();
|
||||
tempFontFile.deleteOnExit();
|
||||
} else {
|
||||
log.error("폰트 파일을 찾을 수 없습니다: " + fontPath);
|
||||
}
|
||||
properties.setFontProvider(fontProvider);
|
||||
|
||||
// 원본 HTML에서 <head> 내용을 추출
|
||||
String headHtml = doc.select("head").outerHtml(); // <head>의 전체 내용을 가져옵니다.
|
||||
|
||||
PdfMerger merger = new PdfMerger(pdfDoc); // 최종 문서에 병합할 PdfMerger 생성
|
||||
// arrSection의 각 섹션을 PDF에 추가
|
||||
for (String section : arrSection) {
|
||||
if (section != null && !"".equals(section)) {
|
||||
Elements eSections = doc.select(section); // 섹션 선택
|
||||
if (eSections != null && eSections.size() > 0) {
|
||||
for (Element eSection : eSections) {
|
||||
|
||||
String sectionHtml =
|
||||
"<html>" + headHtml + "<body>" + eSection.outerHtml() + "</body></html>";
|
||||
|
||||
// 각 섹션을 임시 PDF 파일에 변환
|
||||
try (ByteArrayOutputStream tempOutputStream = new ByteArrayOutputStream();
|
||||
PdfWriter tempWriter = new PdfWriter(tempOutputStream);
|
||||
PdfDocument tempPdfDoc = new PdfDocument(tempWriter)) {
|
||||
|
||||
HtmlConverter.convertToPdf(
|
||||
new ByteArrayInputStream(sectionHtml.getBytes(StandardCharsets.UTF_8)),
|
||||
tempPdfDoc,
|
||||
properties);
|
||||
|
||||
// tempPdfDoc을 메인 pdfDoc에 병합
|
||||
PdfDocument tempDoc =
|
||||
new PdfDocument(
|
||||
new PdfReader(new ByteArrayInputStream(tempOutputStream.toByteArray())));
|
||||
merger.merge(tempDoc, 1, tempDoc.getNumberOfPages());
|
||||
tempDoc.close();
|
||||
|
||||
// 마지막 섹션이 아닐 경우 새 페이지 추가
|
||||
if (!eSection.equals(eSections.last())) {
|
||||
pdfDoc.addNewPage();
|
||||
}
|
||||
}
|
||||
} // for
|
||||
} // if
|
||||
} // if
|
||||
}
|
||||
pdfDoc.close(); // 전체 PDF 문서 작성이 끝난 후에 한번만 닫기
|
||||
os.flush();
|
||||
} catch (Exception e) {
|
||||
log.error("PDF 생성 중 오류 발생: " + e.getMessage(), e);
|
||||
if (!response.isCommitted()) {
|
||||
response.reset();
|
||||
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "PDF 생성 중 오류가 발생했습니다.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,6 +50,7 @@
|
||||
FROM (
|
||||
SELECT /* 전체 목록중 미표시 제품 */
|
||||
MI.ITEM_ID
|
||||
, MI.ITEM_NO
|
||||
, MI.ITEM_NAME
|
||||
, MI.DISP_ORDER
|
||||
FROM M_ITEM MI
|
||||
@ -66,6 +67,7 @@
|
||||
|
||||
SELECT /* 미표시 제품 중 판매점만 표시 */
|
||||
MI.ITEM_ID
|
||||
, MI.ITEM_NO
|
||||
, MI.ITEM_NAME
|
||||
, MI.DISP_ORDER
|
||||
FROM M_SALES_STORE_DISP_ITEM SSDI
|
||||
@ -84,10 +86,11 @@
|
||||
/* sqlid : com.interplug.qcast.displayItem.getItemDetail */
|
||||
SELECT
|
||||
MI.ITEM_ID
|
||||
, MI.ITEM_NO
|
||||
, MI.ITEM_NAME
|
||||
, MI.GOODS_NO
|
||||
, MI.UNIT
|
||||
, MI.SPECIFICATION
|
||||
, MI.PNOW_W AS SPECIFICATION
|
||||
, MI.PNOW_W
|
||||
, MI.ITEM_GROUP
|
||||
, MI.MODULE_FLG
|
||||
|
||||
Binary file not shown.
BIN
src/main/resources/template/pdf/BIZUDPGothic-Regular.ttf
Normal file
BIN
src/main/resources/template/pdf/BIZUDPGothic-Regular.ttf
Normal file
Binary file not shown.
@ -0,0 +1,255 @@
|
||||
<!doctype html>
|
||||
<html lang="ja">
|
||||
<head>
|
||||
<style>
|
||||
@media print {
|
||||
body {
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
font-family: M-Gothic;
|
||||
font-size: 11px;
|
||||
border-collapse: collapse;
|
||||
margin: 0 auto;
|
||||
line-height: 150%;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 5px 5px 3px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #eee;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.col-20 {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.col-15 {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 740px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.mb20 {
|
||||
margin-bottom: 20px; /* 아래쪽 간격 */
|
||||
}
|
||||
|
||||
.guide-box {
|
||||
border: 1px solid #000;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.guide-content {
|
||||
line-height: 1.4;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 차트 설정 */
|
||||
.chart-wrapper {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
margin: 30px 0;
|
||||
height: 324.3px;
|
||||
}
|
||||
|
||||
.chart-wrapper td {
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.chart-wrapper td.y-axis-wrap {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.y-axis {
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.y-axis td {
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
vertical-align: bottom;
|
||||
padding: 12.3px 0;
|
||||
}
|
||||
|
||||
.y-axis td.zero {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.y-axis td.top {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.chart-wrapper td.bar-cell {
|
||||
position: relative;
|
||||
vertical-align: bottom;
|
||||
border-bottom: 1px solid #ddd;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.chart-wrapper td.bar-cell .bar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 13.4px;
|
||||
width: 30px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.chart-wrapper td.month-cell {
|
||||
font-size: 12px;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
.chart-line {
|
||||
}
|
||||
|
||||
.chart-line td {
|
||||
background-color: transparent;
|
||||
padding: 18.2px 0;
|
||||
border-bottom: 1px solid #ddd !important;
|
||||
}
|
||||
|
||||
.chart-line td.top {
|
||||
padding: 1px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="section1">1111111111</div>
|
||||
<div class="section2">222222222</div>
|
||||
<div class="section3">
|
||||
<table class="mb20">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="col-15">物件番号</th>
|
||||
<td id="objectNo"></td>
|
||||
<th class="col-15">作成日</th>
|
||||
<td id="drawingEstimateCreateDate"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-15">都道府県</th>
|
||||
<td id="prefName"></td>
|
||||
<th class="col-15">日射量観測地点</th>
|
||||
<td id="areaName"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-15">システム容量</th>
|
||||
<td id="capacity"></td>
|
||||
<th class="col-15">年間予測発電量</th>
|
||||
<td id="anlFrcsGnrt"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-15">積雪条件</th>
|
||||
<td id="snowfall"></td>
|
||||
<th class="col-15">風速条件</th>
|
||||
<td id="standardWindSpeedId"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="pwrGnrChartImg">
|
||||
<table class="chart-wrapper">
|
||||
<tbody>
|
||||
<tr id="htmlX">
|
||||
<td class="y-axis-wrap">
|
||||
<table class="y-axis">
|
||||
<tbody id="htmlY">
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="month-cell"></td>
|
||||
<td class="month-cell">1月</td>
|
||||
<td class="month-cell">2月</td>
|
||||
<td class="month-cell">3月</td>
|
||||
<td class="month-cell">4月</td>
|
||||
<td class="month-cell">5月</td>
|
||||
<td class="month-cell">6月</td>
|
||||
<td class="month-cell">7月</td>
|
||||
<td class="month-cell">8月</td>
|
||||
<td class="month-cell">9月</td>
|
||||
<td class="month-cell">10月</td>
|
||||
<td class="month-cell">11月</td>
|
||||
<td class="month-cell">12月</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
● 予測発電量[kWh]
|
||||
</div>
|
||||
<table class="mb20">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>1月</th>
|
||||
<th>2月</th>
|
||||
<th>3月</th>
|
||||
<th>4月</th>
|
||||
<th>5月</th>
|
||||
<th>6月</th>
|
||||
<th>7月</th>
|
||||
<th>8月</th>
|
||||
<th>9月</th>
|
||||
<th>10月</th>
|
||||
<th>11月</th>
|
||||
<th>12月</th>
|
||||
<th>合計</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr id="frcPwrGnrList_detail">
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="mb20">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-15">屋根面</th>
|
||||
<th class="col-15">傾斜角</th>
|
||||
<th class="col-15">方位角(度)</th>
|
||||
<th>太陽電池モジュール</th>
|
||||
<th class="col-15">枚数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="roofModuleList_detail">
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="mb20">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>パワーコンディショナー</th>
|
||||
<th class="col-20">台</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="pcsList_detail">
|
||||
</tbody>
|
||||
</table>
|
||||
<div>
|
||||
● Hanwha Japan 年間発電量シミュレーション案内事項
|
||||
</div>
|
||||
<div class="guide-box">
|
||||
<div class="guide-content" id="guideInfo"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user