diff --git a/pom.xml b/pom.xml
index 7cd4ac47..91ffd4b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,6 +125,42 @@
ini4j
0.5.4
+
+
+
+ org.apache.poi
+ poi
+ 4.0.1
+
+
+ org.apache.poi
+ poi-ooxml
+ 4.0.1
+
+
+
+
+ org.jxls
+ jxls
+ 2.9.0
+
+
+ org.jxls
+ jxls-poi
+ 2.9.0
+
+
+ net.sf.jxls
+ jxls-core
+ 1.0.6
+
+
+ org.jxls
+ jxls-jexcel
+ 1.0.9
+
+
+
diff --git a/src/main/java/com/interplug/qcast/biz/estimate/EstimateController.java b/src/main/java/com/interplug/qcast/biz/estimate/EstimateController.java
index 269a23e6..2440cd7d 100644
--- a/src/main/java/com/interplug/qcast/biz/estimate/EstimateController.java
+++ b/src/main/java/com/interplug/qcast/biz/estimate/EstimateController.java
@@ -3,6 +3,8 @@ package com.interplug.qcast.biz.estimate;
import com.interplug.qcast.biz.estimate.dto.*;
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 java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -61,4 +63,15 @@ public class EstimateController {
throws Exception {
return estimateService.insertEstimateCopy(estimateRequest);
}
+
+ @Operation(description = "견적서를 엑셀로 다운로드한다.")
+ @PostMapping("/excel-download")
+ @ResponseStatus(HttpStatus.OK)
+ public void excelDownload(
+ HttpServletRequest request,
+ HttpServletResponse response,
+ @RequestBody EstimateRequest estimateRequest)
+ throws Exception {
+ estimateService.excelDownload(request, response, estimateRequest);
+ }
}
diff --git a/src/main/java/com/interplug/qcast/biz/estimate/EstimateMapper.java b/src/main/java/com/interplug/qcast/biz/estimate/EstimateMapper.java
index ec70262b..a1ee000d 100644
--- a/src/main/java/com/interplug/qcast/biz/estimate/EstimateMapper.java
+++ b/src/main/java/com/interplug/qcast/biz/estimate/EstimateMapper.java
@@ -10,6 +10,9 @@ public interface EstimateMapper {
// 견적서 상세 확인
public EstimateResponse selectEstimateDetail(EstimateRequest estimateRequest);
+ // 견적서 PDF 상세 확인
+ public EstimateResponse selectEstimatePdfDetail(EstimateRequest estimateRequest);
+
// 견적서 아이템 목록 조회
public List selectEstimateItemList(EstimateRequest estimateRequest);
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 a34e3aa7..ac89aad2 100644
--- a/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java
+++ b/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java
@@ -12,11 +12,19 @@ import com.interplug.qcast.biz.object.dto.PlanResponse;
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 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;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -36,6 +44,9 @@ public class EstimateService {
@Value("${qsp.url}")
private String QSP_API_URL;
+ @Value("${file.excel.template.path}")
+ private String excelTemplateFilePath;
+
private final ObjectMapper objectMapper;
private final EstimateMapper estimateMapper;
@@ -157,7 +168,7 @@ public class EstimateService {
response.setItemList(estimateItemList);
// 총 합산금액 계산
- this.selectTotalPriceInfo(response);
+ this.selectTotalPriceInfo(response, estimateItemList, "");
// 첨부파일 목록 조회
FileRequest fileDeleteReq = new FileRequest();
@@ -522,7 +533,103 @@ public class EstimateService {
return response;
}
- public void selectTotalPriceInfo(EstimateResponse estimateResponse) throws Exception {
+ public void excelDownload(
+ HttpServletRequest request, HttpServletResponse response, EstimateRequest estimateRequest)
+ throws Exception {
+ ExcelUtil excelUtil = new ExcelUtil();
+ EstimateResponse estimateResponse = new EstimateResponse();
+ String splitStr = "、";
+
+ try {
+ // 견적서 상세 조회
+ estimateResponse = estimateMapper.selectEstimatePdfDetail(estimateRequest);
+
+ if ("1".equals(estimateRequest.getSchDisplayFlg())) {
+ estimateResponse.setCustSaleStoreName(estimateResponse.getObjectName());
+ estimateResponse.setCustOmit(estimateResponse.getObjectNameOmit());
+ } else {
+ estimateResponse.setCustOmit("様邸");
+ }
+
+ // 견적서 특이사항 조회
+ List noteList = new ArrayList();
+ if (!StringUtils.isEmpty(estimateResponse.getEstimateOption())) {
+ String[] arrSpnAttrCd =
+ new String[estimateResponse.getEstimateOption().split(splitStr).length];
+ int i = 0;
+ for (String str : estimateResponse.getEstimateOption().split(splitStr)) {
+ arrSpnAttrCd[i++] = str;
+ }
+
+ NoteRequest noteRequest = new NoteRequest();
+ noteRequest.setArrSpnAttrCd(arrSpnAttrCd);
+ noteList = estimateMapper.selectEstimateNoteList(noteRequest);
+
+ estimateResponse.setNoteList(noteList);
+ }
+
+ // 아이템 목록 조회
+ List estimateItemList = estimateMapper.selectEstimateItemList(estimateRequest);
+
+ // 총 합산금액 계산
+ this.selectTotalPriceInfo(
+ estimateResponse, estimateItemList, estimateRequest.getSchUnitPriceFlg());
+
+ int j = 1;
+ for (ItemResponse itemResponse : estimateItemList) {
+ itemResponse.setNo(String.valueOf(j++));
+
+ // 문자열 통화로 변환 처리
+ itemResponse.setSalePrice(
+ String.format("%1$,.0f", Double.parseDouble(itemResponse.getSalePrice())));
+ itemResponse.setAmount(
+ String.format("%1$,.0f", Double.parseDouble(itemResponse.getAmount())));
+ itemResponse.setSaleTotPrice(
+ String.format("%1$,.0f", Double.parseDouble(itemResponse.getSaleTotPrice())));
+
+ if ("YJSS".equals(estimateResponse.getEstimateType())
+ && !"1".equals(itemResponse.getPkgMaterialFlg())) {
+ itemResponse.setSalePrice("");
+ itemResponse.setSaleTotPrice("");
+ }
+ }
+
+ // 합산 문자열 통화로 변환 처리
+ estimateResponse.setPkgYn("YJSS".equals(estimateResponse.getEstimateType()) ? "Y" : "N");
+ estimateResponse.setPkgNo(
+ "YJSS".equals(estimateResponse.getEstimateType()) ? String.valueOf(j++) : "");
+ estimateResponse.setPkgAsp(
+ String.format("%1$,.0f", Double.parseDouble(estimateResponse.getPkgAsp())));
+ estimateResponse.setTotVol(
+ String.format("%1$,.0f", Double.parseDouble(estimateResponse.getTotVol())));
+ estimateResponse.setPkgTotPrice(
+ String.format("%1$,.0f", Double.parseDouble(estimateResponse.getPkgTotPrice())));
+ estimateResponse.setSupplyPrice(
+ String.format("%1$,.0f", Double.parseDouble(estimateResponse.getSupplyPrice())));
+ estimateResponse.setVatPrice(
+ String.format("%1$,.0f", Double.parseDouble(estimateResponse.getVatPrice())));
+ 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";
+
+ excelUtil.download(
+ request,
+ response,
+ this.convertVoToMap(estimateResponse),
+ this.convertListToMap(estimateItemList),
+ excelFileName,
+ excelTemplatePath);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void selectTotalPriceInfo(
+ EstimateResponse estimateResponse, List itemList, String unitPriceFlg)
+ throws Exception {
BigDecimal totAmount = BigDecimal.ZERO;
BigDecimal totVol = BigDecimal.ZERO;
BigDecimal pkgTotPrice = BigDecimal.ZERO;
@@ -531,7 +638,6 @@ public class EstimateService {
BigDecimal totPrice = BigDecimal.ZERO;
String estimateType = estimateResponse.getEstimateType();
- List itemList = estimateResponse.getItemList();
// 주택패키지 단가
BigDecimal pkgAsp =
@@ -544,9 +650,20 @@ public class EstimateService {
new BigDecimal(
StringUtils.isEmpty(itemResponse.getAmount()) ? "0" : itemResponse.getAmount());
// 판매가
- BigDecimal salePrice =
- new BigDecimal(
- StringUtils.isEmpty(itemResponse.getSalePrice()) ? "0" : itemResponse.getSalePrice());
+ BigDecimal salePrice = BigDecimal.ZERO;
+ if ("1".equals(unitPriceFlg)) {
+ salePrice =
+ new BigDecimal(
+ StringUtils.isEmpty(itemResponse.getUnitPrice())
+ ? "0"
+ : itemResponse.getUnitPrice());
+ } else {
+ salePrice =
+ new BigDecimal(
+ StringUtils.isEmpty(itemResponse.getSalePrice())
+ ? "0"
+ : itemResponse.getSalePrice());
+ }
// 아이템용량
BigDecimal pnowW =
new BigDecimal(
@@ -590,10 +707,55 @@ public class EstimateService {
estimateResponse.setPkgTotPrice(String.valueOf(pkgTotPrice));
estimateResponse.setTotAmount(String.valueOf(totAmount.setScale(0, BigDecimal.ROUND_HALF_UP)));
- estimateResponse.setTotVol(String.valueOf(totVol.setScale(0, BigDecimal.ROUND_HALF_UP)));
+ estimateResponse.setTotVol(String.valueOf(totVol));
+ estimateResponse.setTotVolKw(
+ String.valueOf(
+ totVol.multiply(new BigDecimal("0.001")).setScale(3, BigDecimal.ROUND_FLOOR)));
estimateResponse.setSupplyPrice(
String.valueOf(supplyPrice.setScale(0, BigDecimal.ROUND_HALF_UP)));
estimateResponse.setVatPrice(String.valueOf(vatPrice.setScale(0, BigDecimal.ROUND_HALF_UP)));
estimateResponse.setTotPrice(String.valueOf(totPrice.setScale(0, BigDecimal.ROUND_HALF_UP)));
}
+
+ public Map convertVoToMap(Object vo) {
+ Map result = new HashMap();
+
+ try {
+ BeanInfo info = Introspector.getBeanInfo(vo.getClass());
+ for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
+ Method reader = pd.getReadMethod();
+ if (reader != null) {
+ result.put(pd.getName(), reader.invoke(vo));
+ }
+ }
+ } catch (Exception e) {
+ log.error("convertVoToMap >>> " + e.getMessage());
+ }
+ return result;
+ }
+
+ public static List