3025 lines
126 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.interplug.qcast.biz.estimate;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import com.interplug.qcast.biz.canvaspopupstatus.CanvasPopupStatusService;
import com.interplug.qcast.biz.canvaspopupstatus.dto.CanvasPopupStatus;
import com.interplug.qcast.biz.pwrGnrSimulation.dto.PwrGnrSimRoofResponse;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jxls.util.Util;
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.web.util.HtmlUtils;
import org.springframework.web.util.UriComponentsBuilder;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.interplug.qcast.biz.canvasStatus.CanvasStatusService;
import com.interplug.qcast.biz.canvasStatus.dto.CanvasStatusCopyRequest;
import com.interplug.qcast.biz.estimate.dto.EstimateApiResponse;
import com.interplug.qcast.biz.estimate.dto.EstimateCopyRequest;
import com.interplug.qcast.biz.estimate.dto.EstimateRequest;
import com.interplug.qcast.biz.estimate.dto.EstimateResponse;
import com.interplug.qcast.biz.estimate.dto.EstimateSendRequest;
import com.interplug.qcast.biz.estimate.dto.EstimateSendResponse;
import com.interplug.qcast.biz.estimate.dto.ItemRequest;
import com.interplug.qcast.biz.estimate.dto.ItemResponse;
import com.interplug.qcast.biz.estimate.dto.NoteRequest;
import com.interplug.qcast.biz.estimate.dto.NoteResponse;
import com.interplug.qcast.biz.estimate.dto.PlanSyncResponse;
import com.interplug.qcast.biz.estimate.dto.PriceRequest;
import com.interplug.qcast.biz.estimate.dto.RoofInfoResponse;
import com.interplug.qcast.biz.estimate.dto.RoofRequest;
import com.interplug.qcast.biz.estimate.dto.RoofResponse;
import com.interplug.qcast.biz.file.FileMapper;
import com.interplug.qcast.biz.file.dto.FileRequest;
import com.interplug.qcast.biz.file.dto.FileResponse;
import com.interplug.qcast.biz.object.ObjectMapper;
import com.interplug.qcast.biz.object.dto.ObjectRequest;
import com.interplug.qcast.biz.object.dto.ObjectResponse;
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 jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
@RequiredArgsConstructor
public class EstimateService {
private final InterfaceQsp interfaceQsp;
@Autowired
Messages message;
@Value("${file.ini.root.path}")
private String baseDirPath;
@Value("${file.ini.drawing.img.path}")
private String drawingDirPath;
@Value("${qsp.url}")
private String QSP_API_URL;
@Value("${front.url}")
private String frontUrl;
private final ObjectMapper objectMapper;
private final EstimateMapper estimateMapper;
private final FileMapper fileMapper;
@Autowired
private CanvasStatusService canvasStatusService;
@Autowired
private PwrGnrSimService pwrGnrSimService;
@Autowired
private CanvasPopupStatusService canvasPopupStatusService;
/**
* QSP 1차점 price 관리 목록 조회
*
* @param priceRequest 1차점 price 관련 정보
* @return PriceResponse 1차점 price 목록
* @throws Exception
*/
public EstimateApiResponse selectStorePriceList(PriceRequest priceRequest) throws Exception {
// Validation
if (StringUtils.isEmpty(priceRequest.getSaleStoreId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
if (StringUtils.isEmpty(priceRequest.getSapSalesStoreCd())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sap Sale Store Code"));
}
if (StringUtils.isEmpty(priceRequest.getDocTpCd())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Estimate Type"));
}
EstimateApiResponse response = null;
/* [1]. QSP API (url + param) Setting */
String url = QSP_API_URL + "/api/price/storePriceList";
String apiUrl = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("saleStoreId", priceRequest.getSaleStoreId())
.queryParam("sapSalesStoreCd", priceRequest.getSapSalesStoreCd())
.queryParam("docTpCd", priceRequest.getDocTpCd()).build().toUriString();
/* [2]. QSP API CALL -> Response */
String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);
if (!"".equals(strResponse)) {
com.fasterxml.jackson.databind.ObjectMapper om =
new com.fasterxml.jackson.databind.ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
response = om.readValue(strResponse, EstimateApiResponse.class);
} else {
// [msg] No data
throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
}
return response;
}
/**
* QSP 아이템 가격 목록 조회
*
* @param priceRequest QSP 관련 아이템 목록 정보
* @return PriceResponse QSP 아이템 가격 목록
* @throws Exception
*/
public EstimateApiResponse selectItemPriceList(PriceRequest priceRequest) throws Exception {
// Validation
if (StringUtils.isEmpty(priceRequest.getSaleStoreId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
if (StringUtils.isEmpty(priceRequest.getSapSalesStoreCd())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sap Sale Store Code"));
}
if (StringUtils.isEmpty(priceRequest.getPriceCd())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Price Code"));
}
EstimateApiResponse response = null;
/* [1]. QSP API CALL -> Response */
String strResponse = interfaceQsp.callApi(HttpMethod.POST,
QSP_API_URL + "/api//price/storePriceItemList", priceRequest);
if (!"".equals(strResponse)) {
com.fasterxml.jackson.databind.ObjectMapper om =
new com.fasterxml.jackson.databind.ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
response = om.readValue(strResponse, EstimateApiResponse.class);
} else {
// [msg] No data
throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
}
return response;
}
/**
* 견적 특이사항 타이틀 목록 조회
*
* @param noteRequest 견적 특이사항 조회 정보
* @return List<NoteResponse> 견적 특이사항 목록
* @throws Exception
*/
public List<NoteResponse> selectSpecialNoteTitleList(NoteRequest noteRequest) throws Exception {
return estimateMapper.selectEstimateNoteTitleList(noteRequest);
}
/**
* 견적 특이사항 목록 조회
*
* @param noteRequest 견적 특이사항 조회 정보
* @return List<NoteResponse> 견적 특이사항 목록
* @throws Exception
*/
public List<NoteResponse> selectSpecialNoteList(NoteRequest noteRequest) throws Exception {
return estimateMapper.selectEstimateNoteList(noteRequest);
}
/**
* 견적서 상세 조회
*
* @param objectNo 물건번호
* @param planNo 플랜번호
* @return EstimateResponse 견적서 상세 정보
* @throws Exception
*/
public EstimateResponse selectEstimateDetail(String objectNo, String planNo) throws Exception {
// Validation
if (StringUtils.isEmpty(objectNo)) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Object No"));
}
if (StringUtils.isEmpty(planNo)) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Plan No"));
}
String splitStr = "";
EstimateRequest estimateRequest = new EstimateRequest();
estimateRequest.setObjectNo(objectNo);
estimateRequest.setPlanNo(planNo);
// 견적서 상세 조회
EstimateResponse response = estimateMapper.selectEstimateDetail(estimateRequest);
if (response == null) {
throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
} else {
// Plan에서 지붕재, 시공방법 동일 데이타 중복 제거
String roofCheckDatas = "";
String roofMaterialIdMultis = "";
String constructSpecificationMultis = "";
String orgRoofMaterialIdMultis = response.getRoofMaterialIdMulti();
String orgConstructSpecificationMultis = response.getConstructSpecificationMulti();
if (!StringUtils.isEmpty(orgRoofMaterialIdMultis)
&& !StringUtils.isEmpty(orgConstructSpecificationMultis)) {
String[] arrOrgRoofMaterialIdMultis = orgRoofMaterialIdMultis.split(splitStr);
String[] arrOrgConstructSpecificationMultis =
orgConstructSpecificationMultis.split(splitStr);
if (arrOrgRoofMaterialIdMultis.length == arrOrgConstructSpecificationMultis.length) {
for (int i = 0; i < arrOrgRoofMaterialIdMultis.length; i++) {
if (!roofCheckDatas.contains(
arrOrgRoofMaterialIdMultis[i] + "_" + arrOrgConstructSpecificationMultis[i])) {
roofMaterialIdMultis +=
StringUtils.isEmpty(roofMaterialIdMultis) ? arrOrgRoofMaterialIdMultis[i]
: splitStr + arrOrgRoofMaterialIdMultis[i];
constructSpecificationMultis += StringUtils.isEmpty(constructSpecificationMultis)
? arrOrgConstructSpecificationMultis[i]
: splitStr + arrOrgConstructSpecificationMultis[i];
}
roofCheckDatas +=
arrOrgRoofMaterialIdMultis[i] + "_" + arrOrgConstructSpecificationMultis[i];
}
if (!StringUtils.isEmpty(roofMaterialIdMultis)) {
response.setRoofMaterialIdMulti(roofMaterialIdMultis);
}
if (!StringUtils.isEmpty(roofMaterialIdMultis)) {
response.setConstructSpecificationMulti(constructSpecificationMultis);
}
}
}
// 아이템 목록 조회
List<ItemResponse> estimateItemList = estimateMapper.selectEstimateItemList(estimateRequest);
response.setItemList(estimateItemList);
// 총 합산금액 계산
this.selectTotalPriceInfo(response, estimateItemList, "");
// 첨부파일 목록 조회
FileRequest fileDeleteReq = new FileRequest();
fileDeleteReq.setObjectNo(objectNo);
fileDeleteReq.setCategory("10");
fileDeleteReq.setPlanNo(planNo);
List<FileResponse> fileList = fileMapper.selectFileList(fileDeleteReq);
response.setFileList(fileList);
}
return response;
}
/**
* 견적서 저장
*
* @param estimateRequest 견적서 저장 정보
* @throws Exception
*/
public void insertEstimate(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"));
}
if (StringUtils.isEmpty(estimateRequest.getSaleStoreId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
if (StringUtils.isEmpty(estimateRequest.getUserId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
String splitStr = "";
List<RoofRequest> orgRoofList = new ArrayList<RoofRequest>();
List<RoofRequest> roofList = new ArrayList<RoofRequest>();
List<ItemRequest> circuitItemList = estimateRequest.getCircuitItemList();
List<ItemRequest> itemList = estimateRequest.getItemList();
estimateRequest.setTempFlg("0");
try {
// 도면 작성일 경우에만 지붕재 데이터를 셋팅
if ("1".equals(estimateRequest.getDrawingFlg())) {
// [1]. 견적서 기본셋팅
// 플랜정보 조회 (임시저장여부 가져오기)
EstimateResponse estimateResponse = estimateMapper.selectEstimateDetail(estimateRequest);
estimateRequest.setEstimateType("YJOD");
estimateRequest.setPriceCd("UNIT_PRICE");
estimateRequest.setTempFlg("0".equals(estimateResponse.getTempFlg()) ? "0" : "1");
// 물건정보 조회 후 데이터 축출
ObjectResponse objectResponse =
objectMapper.selectObjectDetail(estimateRequest.getObjectNo());
if (objectResponse != null) {
estimateRequest
.setWeatherPoint(objectResponse.getPrefName() + " - " + objectResponse.getAreaName());
estimateRequest.setCharger(objectResponse.getReceiveUser());
}
// [2]. 지붕재 관련 데이터 셋팅
orgRoofList = estimateRequest.getRoofSurfaceList();
for (RoofRequest roofRequest : orgRoofList) {
if (!roofRequest.getModuleList().isEmpty()) { // 빈 배열은 지붕재 데이타에서 제거
roofList.add(roofRequest);
}
}
// 지붕재 시공사양 ID
String constructSpecifications = "";
// 지붕재 아이템 ID
String roofMaterialIds = "";
// 지붕재 공법 ID
String supportMethodIds = "";
// 지붕재 아이템명
String roofMaterialIdMultis = "";
// 지붕재 공법명
String supportMethodIdMultis = "";
// 지붕재 시공사양명
String constructSpecificationMultis = "";
// 가대 메이커명
String supportMeakers = "";
for (RoofRequest roofRequest : roofList) {
if (!StringUtils.isEmpty(roofRequest.getRoofMaterialId())) {
roofMaterialIds += !StringUtils.isEmpty(roofMaterialIds) ? splitStr : "";
roofMaterialIds += roofRequest.getRoofMaterialId();
}
if (!StringUtils.isEmpty(roofRequest.getSupportMethodId())) {
supportMethodIds += !StringUtils.isEmpty(supportMethodIds) ? splitStr : "";
supportMethodIds += roofRequest.getSupportMethodId();
}
if (!StringUtils.isEmpty(roofRequest.getConstructSpecification())) {
constructSpecifications +=
!StringUtils.isEmpty(constructSpecifications) ? splitStr : "";
constructSpecifications += roofRequest.getConstructSpecification();
}
if (!StringUtils.isEmpty(roofRequest.getRoofMaterialIdMulti())) {
roofMaterialIdMultis += !StringUtils.isEmpty(roofMaterialIdMultis) ? splitStr : "";
roofMaterialIdMultis += roofRequest.getRoofMaterialIdMulti();
}
if (!StringUtils.isEmpty(roofRequest.getSupportMethodIdMulti())) {
supportMethodIdMultis += !StringUtils.isEmpty(supportMethodIdMultis) ? splitStr : "";
supportMethodIdMultis += roofRequest.getSupportMethodIdMulti();
}
if (!StringUtils.isEmpty(roofRequest.getConstructSpecificationMulti())) {
constructSpecificationMultis +=
!StringUtils.isEmpty(constructSpecificationMultis) ? splitStr : "";
constructSpecificationMultis += roofRequest.getConstructSpecificationMulti();
}
if (!StringUtils.isEmpty(roofRequest.getSupportMeaker())) {
supportMeakers += !StringUtils.isEmpty(supportMeakers) ? splitStr : "";
supportMeakers += roofRequest.getSupportMeaker();
}
}
// 지붕재 관련 데이터 셋팅
estimateRequest.setRoofMaterialId(roofMaterialIds);
estimateRequest.setSupportMethodId(supportMethodIds);
estimateRequest.setConstructSpecification(constructSpecifications);
estimateRequest.setRoofMaterialIdMulti(roofMaterialIdMultis);
estimateRequest.setSupportMethodIdMulti(supportMethodIdMultis);
estimateRequest.setConstructSpecificationMulti(constructSpecificationMultis);
estimateRequest.setSupportMeaker(supportMeakers);
// [3]. 아이템 관련 데이터 셋팅
String[] arrItemId = new String[itemList.size()];
int i = 0;
for (ItemRequest itemRequest : itemList) {
arrItemId[i++] = itemRequest.getItemId();
}
estimateRequest.setArrItemId(arrItemId);
// 아이템의 마스터 정보 및 정가 정보 조회
List<ItemResponse> itemResponseList = estimateMapper.selectItemMasterList(estimateRequest);
// BOM 정보 목록
List<ItemRequest> estimateBomList = new ArrayList<ItemRequest>();
int j = 1;
for (ItemRequest itemRequest : itemList) {
int dispOrder = 100 * j++;
itemRequest.setDispOrder(String.valueOf(dispOrder));
for (ItemResponse itemResponse : itemResponseList) {
if (itemRequest.getItemId().equals(itemResponse.getItemId())) {
itemRequest.setItemNo(itemResponse.getItemNo());
itemRequest.setItemName(itemResponse.getItemName());
itemRequest.setUnit(itemResponse.getUnit());
itemRequest.setPnowW(itemResponse.getPnowW());
itemRequest.setSpecification(itemResponse.getPnowW());
itemRequest.setUnitPrice(itemResponse.getSalePrice());
itemRequest.setSalePrice(itemResponse.getSalePrice());
itemRequest.setFileUploadFlg(itemResponse.getFileUploadFlg());
itemRequest.setPkgMaterialFlg(itemResponse.getPkgMaterialFlg());
itemRequest.setOpenFlg(itemResponse.getOpenFlg());
itemRequest.setUnitOpenFlg(itemResponse.getUnitOpenFlg());
itemRequest.setDispCableFlg("CABLE_".equals(itemResponse.getItemGroup()) ? "1" : "0");
itemRequest.setItemGroup(itemResponse.getItemGroup());
itemRequest.setItemCtgGr(itemResponse.getItemCtgGr());
itemRequest.setPartAdd("0");
itemRequest.setDelFlg("0");
break;
}
}
itemRequest.setNorthModuleYn(itemRequest.getNorthModuleYn());
// 아이템 BOM Header인 경우 컴포넌트 등록 처리
if ("ERLA".equals(itemRequest.getItemCtgGr())) {
List<ItemResponse> itemBomList =
estimateMapper.selectItemMasterBomList(itemRequest.getItemId());
int k = 1;
for (ItemResponse itemResponse : itemBomList) {
ItemRequest bomItem = new ItemRequest();
bomItem.setPaDispOrder(String.valueOf(dispOrder));
bomItem.setDispOrder(String.valueOf(dispOrder + k++));
bomItem.setItemId(itemResponse.getItemId());
bomItem.setItemNo(itemResponse.getItemNo());
bomItem.setItemName(itemResponse.getItemName());
bomItem.setUnit(itemResponse.getUnit());
bomItem.setPnowW(itemResponse.getPnowW());
bomItem.setSpecification(itemResponse.getPnowW());
bomItem.setAmount(String.valueOf(Integer.parseInt(itemResponse.getBomAmount())
* Integer.parseInt(itemRequest.getAmount())));
bomItem.setBomAmount(itemResponse.getBomAmount());
bomItem.setUnitPrice(itemResponse.getSalePrice());
bomItem.setSalePrice(itemResponse.getSalePrice());
bomItem.setFileUploadFlg(itemResponse.getFileUploadFlg());
bomItem.setPkgMaterialFlg(itemResponse.getPkgMaterialFlg());
bomItem.setOpenFlg("0");
bomItem.setUnitOpenFlg("0");
bomItem.setDispCableFlg("0");
bomItem.setItemGroup(itemResponse.getItemGroup());
bomItem.setItemCtgGr(itemResponse.getItemCtgGr());
bomItem.setPartAdd("0");
bomItem.setDelFlg("0");
estimateBomList.add(bomItem);
}
}
}
System.out.print("itemRequest");
// BOM 컴포넌트 추가
itemList.addAll(estimateBomList);
// [4]. 견적특이사항 관련 데이터 셋팅
NoteRequest noteRequest = new NoteRequest();
noteRequest.setArrItemId(arrItemId);
noteRequest.setSchSpnTypeCd("COMM");
List<NoteResponse> noteList = estimateMapper.selectEstimateNoteList(noteRequest);
noteRequest.setSchSpnTypeCd("PROD");
List<NoteResponse> noteItemList = estimateMapper.selectEstimateNoteItemList(noteRequest);
// 견적특이사항 코드
String estimateOptions = "";
for (NoteResponse noteResponse : noteList) {
if ("ATTR001".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR001"; // 공통 필수체크
} else if ("ATTR002".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR002"; // YJOD 필수체크
} else if ("ATTR003".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR003"; // 출력제어시간 기본 체크
} else if ("ATTR004".equals(noteResponse.getCode())
&& "1".equals(estimateRequest.getNorthArrangement())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR004"; // 북면설치 체크
} else if ("ATTR005".equals(noteResponse.getCode())
&& "1".equals(objectResponse != null ? objectResponse.getSaltAreaFlg() : "")) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR005"; // 염해지역 체크
} else if ("ATTR006"
.equals(objectResponse != null ? objectResponse.getColdRegionFlg() : "")
&& "1".equals(estimateRequest.getNorthArrangement())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR006"; // 적설지역 체크
} else if ("ATTR007".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR007"; // 지붕재치수, 레이아웃 기본 체크
} else if ("ATTR008".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR008"; // 별도비용 기본 체크
} else if ("ATTR009".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR009"; // 과적재 기본 체크
}
}
for (NoteResponse noteResponse : noteItemList) {
if (estimateOptions.indexOf(noteResponse.getCode()) < 0) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += noteResponse.getCode();
}
}
estimateRequest.setEstimateOption(estimateOptions);
// 아이템별 특이사항 코드 체크
for (ItemRequest itemRequest : itemList) {
String specialNoteCd = "";
for (NoteResponse noteResponse : noteItemList) {
if (itemRequest.getItemId().equals(noteResponse.getItemId())) {
specialNoteCd += !StringUtils.isEmpty(specialNoteCd) ? splitStr : "";
specialNoteCd += noteResponse.getCode();
}
}
itemRequest.setSpecialNoteCd(specialNoteCd);
}
// 첨부파일 초기화
FileRequest fileRequest = new FileRequest();
fileRequest.setObjectNo(estimateRequest.getObjectNo());
fileRequest.setPlanNo(estimateRequest.getPlanNo());
fileRequest.setUserId(estimateRequest.getUserId());
fileMapper.deleteFile(fileRequest);
}
// 아이템 목록 필수 값 체크
BigDecimal capacity = BigDecimal.ZERO;
String moduleModel = "";
String pcTypeNo = "";
for (ItemRequest itemRequest : itemList) {
if (!"1".equals(itemRequest.getDelFlg())) {
if (StringUtils.isEmpty(itemRequest.getDispOrder())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Display Order"));
}
if (StringUtils.isEmpty(itemRequest.getItemId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Item ID"));
}
if (StringUtils.isEmpty(itemRequest.getAmount())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Item Amount"));
}
// 수량
BigDecimal amount = new BigDecimal(
StringUtils.isEmpty(itemRequest.getAmount()) ? "0" : itemRequest.getAmount());
// 아이템용량
BigDecimal pnowW = new BigDecimal(
StringUtils.isEmpty(itemRequest.getPnowW()) ? "0" : itemRequest.getPnowW());
// 모듈/PC 체크
if ("MODULE_".equals(itemRequest.getItemGroup())) {
moduleModel += !StringUtils.isEmpty(moduleModel) ? splitStr : "";
moduleModel += itemRequest.getItemNo();
capacity = capacity.add(amount.multiply(pnowW));
} else if ("PC_".equals(itemRequest.getItemGroup())) {
pcTypeNo += !StringUtils.isEmpty(pcTypeNo) ? splitStr : "";
pcTypeNo += itemRequest.getItemNo();
} else if ("STORAGE_BATTERY".equals(itemRequest.getItemGroup())) {
pcTypeNo += !StringUtils.isEmpty(pcTypeNo) ? splitStr : "";
pcTypeNo += itemRequest.getItemNo();
}
}
}
estimateRequest.setCapacity(String.valueOf(capacity));
estimateRequest.setModuleModel(moduleModel);
estimateRequest.setPcTypeNo(pcTypeNo);
// 물건정보 수정
if (!StringUtils.isEmpty(estimateRequest.getObjectName())
|| !StringUtils.isEmpty(estimateRequest.getObjectNameOmit())) {
estimateMapper.updateObject(estimateRequest);
}
if (!StringUtils.isEmpty(estimateRequest.getSurfaceType())
|| !StringUtils.isEmpty(estimateRequest.getSetupHeight())
|| !StringUtils.isEmpty(estimateRequest.getStandardWindSpeedId())
|| !StringUtils.isEmpty(estimateRequest.getSnowfall())) {
estimateMapper.updateObjectInfo(estimateRequest);
}
// 견적서 정보 수정
estimateRequest.setPriceCd(
!StringUtils.isEmpty(estimateRequest.getPriceCd()) ? estimateRequest.getPriceCd()
: "UNIT_PRICE");
estimateMapper.updateEstimate(estimateRequest);
estimateMapper.updateEstimateInfo(estimateRequest);
// 도면 작성일 경우에만 지붕면, 도면 아이템 데이터 초기화 후 저장
if ("1".equals(estimateRequest.getDrawingFlg())) {
// 견적서 지붕면/아이템 및 PC 회로구성도 제거
estimateMapper.deleteEstimateRoofList(estimateRequest);
estimateMapper.deleteEstimateRoofItemList(estimateRequest);
estimateMapper.deleteEstimateCircuitItemList(estimateRequest);
// 견적서 지붕면/아이템 신규 추가
List<ItemRequest> allModuleList = new ArrayList<ItemRequest>();
for (RoofRequest roofRequest : roofList) {
roofRequest.setObjectNo(estimateRequest.getObjectNo());
roofRequest.setPlanNo(estimateRequest.getPlanNo());
roofRequest.setUserId(estimateRequest.getUserId());
estimateMapper.insertEstimateRoof(roofRequest);
List<ItemRequest> moduleList = roofRequest.getModuleList();
List<ItemRequest> roofItemList = new ArrayList<ItemRequest>();
// 동일 모듈, PCS 아이템 묶기
for (ItemRequest itemRequest : moduleList) {
boolean overLap = false;
for (ItemRequest data : roofItemList) {
if (itemRequest.getItemId().equals(data.getItemId())
&& itemRequest.getPcItemId().equals(data.getPcItemId())) {
data.setAmount(String.valueOf(Integer.parseInt(data.getAmount()) + 1)); // 데이터 존재하면
// 카운팅 + 1
overLap = true;
break;
}
}
if (!overLap) {
itemRequest.setAmount("1");
roofItemList.add(itemRequest);
}
allModuleList.add(itemRequest);
}
for (ItemRequest itemRequest : roofItemList) {
itemRequest.setRoofSurfaceId(roofRequest.getRoofSurfaceId());
itemRequest.setObjectNo(estimateRequest.getObjectNo());
itemRequest.setPlanNo(estimateRequest.getPlanNo());
// 선택한 PCS 아이템이 다른 경우
for (ItemRequest itemObj : itemList) {
if(itemObj.getQcastCustPrdId() != null && itemObj.getQcastCustPrdId().equals(itemRequest.getPcItemId())) {
itemRequest.setQcastCustPrdId(itemObj.getItemId());
}
if(itemObj.getItemId().equals(itemRequest.getItemId())) {
itemRequest.setNorthModuleYn(itemObj.getNorthModuleYn());
}
}
estimateMapper.insertEstimateRoofItem(itemRequest);
}
}
// 견적서 PCS 아이템 회로 구성
List<ItemRequest> circuitPcsItemList =
this.getPcsCircuitList(circuitItemList, allModuleList);
// 견적서 회로구성 아이템 신규 추가
for (ItemRequest circuitItemRequest : circuitPcsItemList) {
circuitItemRequest.setObjectNo(estimateRequest.getObjectNo());
circuitItemRequest.setPlanNo(estimateRequest.getPlanNo());
if (!StringUtils.isEmpty(circuitItemRequest.getCircuitCfg())) {
estimateMapper.insertEstimateCircuitItem(circuitItemRequest);
}
}
// 견적서 도면 아이템 제거
estimateMapper.deleteEstimateDrawingItemList(estimateRequest);
// 견적서 도면 아이템 등록
for (ItemRequest itemRequest : itemList) {
itemRequest.setObjectNo(estimateRequest.getObjectNo());
itemRequest.setPlanNo(estimateRequest.getPlanNo());
itemRequest.setAmount(
!StringUtils.isEmpty(itemRequest.getAmount()) ? itemRequest.getAmount() : "0");
itemRequest.setUserId(estimateRequest.getUserId());
// BOM 컴포넌트는 제외하고 등록
if (StringUtils.isEmpty(itemRequest.getPaDispOrder())) {
estimateMapper.insertEstimateDrawingItem(itemRequest);
}
}
}
// 견적서 모든 아이템 제거
estimateMapper.deleteEstimateItemList(estimateRequest);
estimateMapper.deleteEstimateInfoItemList(estimateRequest);
// 견적서 아이템 신규 추가
String hisNo = estimateMapper.selectEstimateItemHisNo(estimateRequest); // 아이템 히스토리 번호 조회
for (ItemRequest itemRequest : itemList) {
itemRequest.setHisNo(hisNo);
itemRequest.setObjectNo(estimateRequest.getObjectNo());
itemRequest.setPlanNo(estimateRequest.getPlanNo());
itemRequest.setAmount(
!StringUtils.isEmpty(itemRequest.getAmount()) ? itemRequest.getAmount() : "0");
itemRequest.setSalePrice(
!StringUtils.isEmpty(itemRequest.getSalePrice()) ? itemRequest.getSalePrice() : "0");
itemRequest.setBomAmount(
!StringUtils.isEmpty(itemRequest.getBomAmount()) ? itemRequest.getBomAmount() : "0");
itemRequest.setPartAdd(
!StringUtils.isEmpty(itemRequest.getPartAdd()) ? itemRequest.getPartAdd() : "0");
itemRequest.setOpenFlg(
!StringUtils.isEmpty(itemRequest.getOpenFlg()) ? itemRequest.getOpenFlg() : "0");
itemRequest.setUnitOpenFlg(
!StringUtils.isEmpty(itemRequest.getUnitOpenFlg()) ? itemRequest.getUnitOpenFlg() : "0");
itemRequest.setItemChangeFlg(
!StringUtils.isEmpty(itemRequest.getItemChangeFlg()) ? itemRequest.getItemChangeFlg()
: "0");
itemRequest.setDispCableFlg(
!StringUtils.isEmpty(itemRequest.getDispCableFlg()) ? itemRequest.getDispCableFlg()
: "0");
itemRequest.setUserId(estimateRequest.getUserId());
estimateMapper.insertEstimateItemHis(itemRequest);
if (!"1".equals(itemRequest.getDelFlg())) {
estimateMapper.insertEstimateItem(itemRequest);
estimateMapper.insertEstimateInfoItem(itemRequest);
}
}
// 첨부파일 처리
if (estimateRequest.getFileList() != null) {
for (FileRequest fileRequest : estimateRequest.getFileList()) {
fileRequest.setUserId(estimateRequest.getUserId());
fileMapper.insertFile(fileRequest);
fileMapper.insertFileInfo(fileRequest);
}
}
if (estimateRequest.getDeleteFileList() != null) {
for (FileRequest fileRequest : estimateRequest.getDeleteFileList()) {
fileRequest.setUserId(estimateRequest.getUserId());
fileMapper.deleteFile(fileRequest);
}
}
// 임시저장 상태에서는 인터페이스 막도록 처리
if ("0".equals(estimateRequest.getTempFlg())) {
// QSP Q.CAST SEND API
List<EstimateSendResponse> resultList = new ArrayList<EstimateSendResponse>();
resultList = this.sendEstimateApi(estimateRequest);
// API에서 받은 문서번호 업데이트
for (EstimateSendResponse result : resultList) {
estimateRequest.setObjectNo(result.getObjectNo());
estimateRequest.setPlanNo(result.getPlanNo());
estimateRequest.setDocNo(result.getDocNo());
estimateRequest.setSyncFlg(result.getSyncFlg());
estimateMapper.updateEstimateApi(estimateRequest);
}
}
} catch (Exception e) {
e.printStackTrace();
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
}
}
/**
* 견적서 복사
*
* @param estimateCopyRequest 견적서 복사 정보
* @return EstimateResponse 견적서 복사 후 상세 정보
* @throws Exception
*/
public EstimateResponse insertEstimateCopy(EstimateCopyRequest estimateCopyRequest)
throws Exception {
// Validation
if (StringUtils.isEmpty(estimateCopyRequest.getObjectNo())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Object No"));
}
if (StringUtils.isEmpty(estimateCopyRequest.getPlanNo())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Plan No"));
}
if (StringUtils.isEmpty(estimateCopyRequest.getUserId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
// 응답 객체
EstimateResponse response = new EstimateResponse();
try {
ObjectRequest objectRequest = new ObjectRequest();
objectRequest.setSaleStoreId(estimateCopyRequest.getCopySaleStoreId());
objectRequest
.setReceiveUser(StringUtils.defaultString(estimateCopyRequest.getCopyReceiveUser()));
objectRequest.setDelFlg("1");
objectRequest.setOrgDelFlg("0");
objectRequest.setTempFlg("0");
objectRequest.setTempDelFlg("0");
objectRequest.setUserId(estimateCopyRequest.getUserId());
// [1]. 신규 물건번호 생성
objectMapper.insertObjectNo(objectRequest);
objectRequest.setObjectNo(estimateCopyRequest.getObjectNo());
objectRequest.setCopyObjectNo(objectMapper.selectObjectNo(objectRequest));
// [2]. 물건정보 복사
objectRequest.setContentsPath(baseDirPath + "\\\\" + objectRequest.getCopyObjectNo());
objectMapper.insertObjectCopy(objectRequest);
objectMapper.insertObjectInfoCopy(objectRequest);
objectRequest.setObjectNo(objectRequest.getCopyObjectNo());
objectMapper.updateObjectDelivery(objectRequest);
// [3]. 아이템 관련 데이터 셋팅 (복사 시 정가 셋팅)
EstimateRequest estimateRequest = new EstimateRequest();
estimateRequest.setObjectNo(estimateCopyRequest.getObjectNo());
estimateRequest.setPlanNo(estimateCopyRequest.getPlanNo());
List<ItemRequest> itemList = new ArrayList<ItemRequest>();
List<ItemResponse> estimateItemList = estimateMapper.selectEstimateItemList(estimateRequest);
for (ItemResponse itemResponse : estimateItemList) {
ItemRequest itemRequest = new ItemRequest();
itemRequest.setDispOrder(itemResponse.getDispOrder());
itemRequest.setPaDispOrder(itemResponse.getPaDispOrder());
itemRequest.setItemId(itemResponse.getItemId());
itemRequest.setItemNo(itemResponse.getItemNo());
itemRequest.setItemName(itemResponse.getItemName());
itemRequest.setUnit(itemResponse.getUnit());
itemRequest.setAmount(itemResponse.getAmount());
itemRequest.setBomAmount(itemResponse.getBomAmount());
itemRequest.setSpecialNoteCd(itemResponse.getSpecialNoteCd());
itemRequest.setItemChangeFlg("0");
itemRequest.setDispCableFlg(itemResponse.getDispCableFlg());
itemList.add(itemRequest);
}
if (!itemList.isEmpty()) {
String[] arrItemId = new String[itemList.size()];
int i = 0;
for (ItemRequest itemRequest : itemList) {
arrItemId[i++] = itemRequest.getItemId();
}
estimateRequest.setArrItemId(arrItemId);
// 아이템의 마스터 정보 및 정가 정보 조회
List<ItemResponse> itemResponseList = estimateMapper.selectItemMasterList(estimateRequest);
for (ItemRequest itemRequest : itemList) {
for (ItemResponse itemResponse : itemResponseList) {
if (itemRequest.getItemId().equals(itemResponse.getItemId())) {
itemRequest.setItemNo(itemResponse.getItemNo());
itemRequest.setItemName(itemResponse.getItemName());
itemRequest.setUnit(itemResponse.getUnit());
itemRequest.setPnowW(itemResponse.getPnowW());
itemRequest.setSpecification(itemResponse.getPnowW());
itemRequest.setUnitPrice(itemResponse.getSalePrice());
itemRequest.setSalePrice(itemResponse.getSalePrice());
itemRequest.setPkgMaterialFlg(itemResponse.getPkgMaterialFlg());
itemRequest.setFileUploadFlg(itemResponse.getFileUploadFlg());
itemRequest.setItemGroup(itemResponse.getItemGroup());
itemRequest.setOpenFlg(itemResponse.getOpenFlg());
itemRequest.setUnitOpenFlg(itemResponse.getUnitOpenFlg());
break;
}
}
}
}
// [4]. 견적서 복사
estimateCopyRequest.setCopyObjectNo(objectRequest.getObjectNo());
estimateCopyRequest.setCopyPlanNo("1");
estimateCopyRequest.setCopyReceiveUser(objectRequest.getReceiveUser()); //담당자
estimateMapper.insertEstimateCopy(estimateCopyRequest);
estimateMapper.insertEstimateInfoCopy(estimateCopyRequest);
estimateMapper.insertCanvasPopupStatusCopy(estimateCopyRequest);
// [5]. 견적서 아이템 복사
for (ItemRequest itemRequest : itemList) {
itemRequest.setObjectNo(estimateCopyRequest.getCopyObjectNo());
itemRequest.setPlanNo(estimateCopyRequest.getCopyPlanNo());
itemRequest.setPartAdd(
!StringUtils.isEmpty(itemRequest.getPartAdd()) ? itemRequest.getPartAdd() : "0");
itemRequest.setItemChangeFlg(
!StringUtils.isEmpty(itemRequest.getItemChangeFlg()) ? itemRequest.getItemChangeFlg()
: "0");
itemRequest.setUserId(estimateCopyRequest.getUserId());
estimateMapper.insertEstimateItem(itemRequest);
estimateMapper.insertEstimateInfoItem(itemRequest);
}
// [6]. 견적서 지붕면 및 도면 초기 데이터 복사
// 견적서 지붕면 복사
estimateMapper.insertEstimateRoofCopy(estimateCopyRequest);
// 견적서 지붕면 아이템 복사
estimateMapper.insertEstimateRoofItemCopy(estimateCopyRequest);
// 견적서 지붕면 회로구성 아이템 복사
estimateMapper.insertEstimateCircuitItemCopy(estimateCopyRequest);
// 도면 초기 데이타 복사(초기화 위해 필요)
estimateMapper.insertEstimateDrawingItemCopy(estimateCopyRequest);
// [7]. 견적서 도면 복사
CanvasStatusCopyRequest cs = new CanvasStatusCopyRequest();
cs.setOriginObjectNo(estimateCopyRequest.getObjectNo());
cs.setOriginPlanNo(estimateCopyRequest.getPlanNo());
cs.setObjectNo(estimateCopyRequest.getCopyObjectNo());
cs.setPlanNo(estimateCopyRequest.getCopyPlanNo());
cs.setUserId(estimateCopyRequest.getUserId());
canvasStatusService.copyCanvasStatus(cs, true);
} catch (Exception e) {
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
}
// [9]. 최종 생성 물건번호 리턴
response.setObjectNo(estimateCopyRequest.getCopyObjectNo());
response.setPlanNo(estimateCopyRequest.getCopyPlanNo());
return response;
}
/**
* 견적서 초기화
*
* @param estimateRequest
* @return EstimateResponse 견적서 초기화 후 상세 정보
* @throws Exception
*/
public EstimateResponse updateEstimateReset(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"));
}
if (StringUtils.isEmpty(estimateRequest.getUserId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
// 견적서 상세 조회
EstimateResponse estimateResponse = estimateMapper.selectEstimateDetail(estimateRequest);
if (estimateResponse == null) {
throw new QcastException(ErrorCode.NOT_FOUND,
message.getMessage("common.message.required.data", "Estimate Info"));
}
// 응답 객체
EstimateResponse response = new EstimateResponse();
String splitStr = "";
try {
// [1]. 견적서 기본셋팅
estimateRequest.setEstimateType("YJOD");
estimateRequest.setPriceCd("UNIT_PRICE");
estimateRequest.setTempFlg("0".equals(estimateResponse.getTempFlg()) ? "0" : "1");
// 물건정보 조회 후 데이터 축출
ObjectResponse objectResponse =
objectMapper.selectObjectDetail(estimateRequest.getObjectNo());
if (objectResponse != null) {
estimateRequest
.setWeatherPoint(objectResponse.getPrefName() + " - " + objectResponse.getAreaName());
estimateRequest.setCharger(objectResponse.getReceiveUser());
}
// [2] 도면에서 저장된 아이템 목록 조회
List<ItemResponse> estimateItemList =
estimateMapper.selectEstimateDrawingItemList(estimateRequest);
List<ItemRequest> itemList = new ArrayList<ItemRequest>();
for (ItemResponse itemResponse : estimateItemList) {
ItemRequest itemRequest = new ItemRequest();
itemRequest.setObjectNo(itemResponse.getObjectNo());
itemRequest.setPlanNo(itemResponse.getPlanNo());
itemRequest.setItemId(itemResponse.getItemId());
itemRequest.setAmount(itemResponse.getAmount());
itemList.add(itemRequest);
}
// [3]. 아이템 관련 데이터 셋팅
String[] arrItemId = new String[itemList.size()];
int i = 0;
for (ItemRequest itemRequest : itemList) {
arrItemId[i++] = itemRequest.getItemId();
}
estimateRequest.setArrItemId(arrItemId);
// 아이템의 마스터 정보 및 정가 정보 조회
List<ItemResponse> itemResponseList = estimateMapper.selectItemMasterList(estimateRequest);
// BOM 정보 목록
List<ItemRequest> estimateBomList = new ArrayList<ItemRequest>();
int j = 1;
for (ItemRequest itemRequest : itemList) {
int dispOrder = 100 * j++;
itemRequest.setDispOrder(String.valueOf(dispOrder));
for (ItemResponse itemResponse : itemResponseList) {
if (itemRequest.getItemId().equals(itemResponse.getItemId())) {
itemRequest.setItemNo(itemResponse.getItemNo());
itemRequest.setItemName(itemResponse.getItemName());
itemRequest.setUnit(itemResponse.getUnit());
itemRequest.setPnowW(itemResponse.getPnowW());
itemRequest.setSpecification(itemResponse.getPnowW());
itemRequest.setUnitPrice(itemResponse.getSalePrice());
itemRequest.setSalePrice(itemResponse.getSalePrice());
itemRequest.setFileUploadFlg(itemResponse.getFileUploadFlg());
itemRequest.setPkgMaterialFlg(itemResponse.getPkgMaterialFlg());
itemRequest.setOpenFlg(itemResponse.getOpenFlg());
itemRequest.setUnitOpenFlg(itemResponse.getUnitOpenFlg());
itemRequest.setDispCableFlg("CABLE_".equals(itemResponse.getItemGroup()) ? "1" : "0");
itemRequest.setItemGroup(itemResponse.getItemGroup());
itemRequest.setItemCtgGr(itemResponse.getItemCtgGr());
itemRequest.setPartAdd("0");
itemRequest.setDelFlg("0");
break;
}
}
// 아이템 BOM Header인 경우 컴포넌트 등록 처리
if ("ERLA".equals(itemRequest.getItemCtgGr())) {
List<ItemResponse> itemBomList =
estimateMapper.selectItemMasterBomList(itemRequest.getItemId());
int k = 1;
for (ItemResponse itemResponse : itemBomList) {
ItemRequest bomItem = new ItemRequest();
bomItem.setPaDispOrder(String.valueOf(dispOrder));
bomItem.setDispOrder(String.valueOf(dispOrder + k++));
bomItem.setItemId(itemResponse.getItemId());
bomItem.setItemNo(itemResponse.getItemNo());
bomItem.setItemName(itemResponse.getItemName());
bomItem.setUnit(itemResponse.getUnit());
bomItem.setPnowW(itemResponse.getPnowW());
bomItem.setSpecification(itemResponse.getPnowW());
bomItem.setAmount(String.valueOf(Integer.parseInt(itemResponse.getBomAmount())
* Integer.parseInt(itemRequest.getAmount())));
bomItem.setBomAmount(itemResponse.getBomAmount());
bomItem.setUnitPrice(itemResponse.getSalePrice());
bomItem.setSalePrice(itemResponse.getSalePrice());
bomItem.setFileUploadFlg(itemResponse.getFileUploadFlg());
bomItem.setPkgMaterialFlg(itemResponse.getPkgMaterialFlg());
bomItem.setOpenFlg("0");
bomItem.setUnitOpenFlg("0");
bomItem.setDispCableFlg("0");
bomItem.setItemGroup(itemResponse.getItemGroup());
bomItem.setItemCtgGr(itemResponse.getItemCtgGr());
bomItem.setPartAdd("0");
bomItem.setDelFlg("0");
estimateBomList.add(bomItem);
}
}
}
// BOM 컴포넌트 추가
itemList.addAll(estimateBomList);
// [4]. 견적특이사항 관련 데이터 셋팅
NoteRequest noteRequest = new NoteRequest();
noteRequest.setArrItemId(arrItemId);
noteRequest.setSchSpnTypeCd("COMM");
List<NoteResponse> noteList = estimateMapper.selectEstimateNoteList(noteRequest);
noteRequest.setSchSpnTypeCd("PROD");
List<NoteResponse> noteItemList = estimateMapper.selectEstimateNoteItemList(noteRequest);
// 견적특이사항 코드
String estimateOptions = "";
for (NoteResponse noteResponse : noteList) {
if ("ATTR001".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR001"; // 공통 필수체크
} else if ("ATTR002".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR002"; // YJOD 필수체크
} else if ("ATTR003".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR003"; // 출력제어시간 기본 체크
} else if ("ATTR004".equals(noteResponse.getCode())
&& "1".equals(estimateRequest.getNorthArrangement())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR004"; // 북면설치 체크
} else if ("ATTR005".equals(noteResponse.getCode())
&& "1".equals(objectResponse != null ? objectResponse.getSaltAreaFlg() : "")) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR005"; // 염해지역 체크
} else if ("ATTR006".equals(objectResponse != null ? objectResponse.getColdRegionFlg() : "")
&& "1".equals(estimateRequest.getNorthArrangement())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR006"; // 적설지역 체크
} else if ("ATTR007".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR007"; // 지붕재치수, 레이아웃 기본 체크
} else if ("ATTR008".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR008"; // 별도비용 기본 체크
} else if ("ATTR009".equals(noteResponse.getCode())) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += "ATTR009"; // 과적재 기본 체크
}
}
for (NoteResponse noteResponse : noteItemList) {
if (estimateOptions.indexOf(noteResponse.getCode()) < 0) {
estimateOptions += !StringUtils.isEmpty(estimateOptions) ? splitStr : "";
estimateOptions += noteResponse.getCode();
}
}
estimateRequest.setEstimateOption(estimateOptions);
// 아이템별 특이사항 코드 체크
for (ItemRequest itemRequest : itemList) {
String specialNoteCd = "";
for (NoteResponse noteResponse : noteItemList) {
if (itemRequest.getItemId().equals(noteResponse.getItemId())) {
specialNoteCd += !StringUtils.isEmpty(specialNoteCd) ? splitStr : "";
specialNoteCd += noteResponse.getCode();
}
}
itemRequest.setSpecialNoteCd(specialNoteCd);
}
// 첨부파일 초기화
FileRequest fileRequest = new FileRequest();
fileRequest.setObjectNo(estimateRequest.getObjectNo());
fileRequest.setPlanNo(estimateRequest.getPlanNo());
fileRequest.setUserId(estimateRequest.getUserId());
fileMapper.deleteFile(fileRequest);
// 아이템 목록 필수 값 체크
BigDecimal capacity = BigDecimal.ZERO;
String moduleModel = "";
String pcTypeNo = "";
for (ItemRequest itemRequest : itemList) {
if (StringUtils.isEmpty(itemRequest.getDispOrder())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Display Order"));
}
if (StringUtils.isEmpty(itemRequest.getItemId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Item ID"));
}
if (StringUtils.isEmpty(itemRequest.getAmount())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Item Amount"));
}
// 수량
BigDecimal amount = new BigDecimal(
StringUtils.isEmpty(itemRequest.getAmount()) ? "0" : itemRequest.getAmount());
// 아이템용량
BigDecimal pnowW = new BigDecimal(
StringUtils.isEmpty(itemRequest.getPnowW()) ? "0" : itemRequest.getPnowW());
// 모듈/PC 체크
if ("MODULE_".equals(itemRequest.getItemGroup())) {
moduleModel += !StringUtils.isEmpty(moduleModel) ? splitStr : "";
moduleModel += itemRequest.getItemNo();
capacity = capacity.add(amount.multiply(pnowW));
} else if ("PC_".equals(itemRequest.getItemGroup())) {
pcTypeNo += !StringUtils.isEmpty(pcTypeNo) ? splitStr : "";
pcTypeNo += itemRequest.getItemNo();
}
}
estimateRequest.setCapacity(String.valueOf(capacity));
estimateRequest.setModuleModel(moduleModel);
estimateRequest.setPcTypeNo(pcTypeNo);
// 견적서 정보 초기화
estimateMapper.updateEstimateReset(estimateRequest);
estimateMapper.updateEstimateInfoReset(estimateRequest);
// 견적서 모든 아이템 제거
estimateMapper.deleteEstimateItemList(estimateRequest);
estimateMapper.deleteEstimateInfoItemList(estimateRequest);
// 견적서 아이템 신규 추가
String hisNo = estimateMapper.selectEstimateItemHisNo(estimateRequest); // 아이템 히스토리 번호 조회
for (ItemRequest itemRequest : itemList) {
itemRequest.setHisNo(hisNo);
itemRequest.setObjectNo(estimateRequest.getObjectNo());
itemRequest.setPlanNo(estimateRequest.getPlanNo());
itemRequest.setAmount(
!StringUtils.isEmpty(itemRequest.getAmount()) ? itemRequest.getAmount() : "0");
itemRequest.setSalePrice(
!StringUtils.isEmpty(itemRequest.getSalePrice()) ? itemRequest.getSalePrice() : "0");
itemRequest.setBomAmount(
!StringUtils.isEmpty(itemRequest.getBomAmount()) ? itemRequest.getBomAmount() : "0");
itemRequest.setPartAdd(
!StringUtils.isEmpty(itemRequest.getPartAdd()) ? itemRequest.getPartAdd() : "0");
itemRequest.setOpenFlg(
!StringUtils.isEmpty(itemRequest.getOpenFlg()) ? itemRequest.getOpenFlg() : "0");
itemRequest.setUnitOpenFlg(
!StringUtils.isEmpty(itemRequest.getUnitOpenFlg()) ? itemRequest.getUnitOpenFlg() : "0");
itemRequest.setItemChangeFlg(
!StringUtils.isEmpty(itemRequest.getItemChangeFlg()) ? itemRequest.getItemChangeFlg()
: "0");
itemRequest.setUserId(estimateRequest.getUserId());
estimateMapper.insertEstimateItemHis(itemRequest);
if (!"1".equals(itemRequest.getDelFlg())) {
estimateMapper.insertEstimateItem(itemRequest);
estimateMapper.insertEstimateInfoItem(itemRequest);
}
}
// 임시저장 상태에서는 인터페이스 막도록 처리
if ("0".equals(estimateRequest.getTempFlg())) {
// QSP Q.CAST SEND API
List<EstimateSendResponse> resultList = new ArrayList<EstimateSendResponse>();
resultList = this.sendEstimateApi(estimateRequest);
// API에서 받은 문서번호 업데이트
for (EstimateSendResponse result : resultList) {
estimateRequest.setObjectNo(result.getObjectNo());
estimateRequest.setPlanNo(result.getPlanNo());
estimateRequest.setDocNo(result.getDocNo());
estimateRequest.setSyncFlg(result.getSyncFlg());
estimateMapper.updateEstimateApi(estimateRequest);
}
}
} catch (Exception e) {
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
}
// [4]. 물건번호 리턴
response.setObjectNo(estimateRequest.getObjectNo());
response.setPlanNo(estimateRequest.getPlanNo());
return response;
}
/**
* 견적서 잠금처리
*
* @param estimateRequest
* @throws Exception
*/
public void updateEstimateLock(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"));
}
if (StringUtils.isEmpty(estimateRequest.getLockFlg())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Lock Flag"));
}
if (StringUtils.isEmpty(estimateRequest.getUserId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
try {
estimateMapper.updateEstimateLock(estimateRequest);
estimateMapper.updateEstimateLastEditDate(estimateRequest);
} catch (Exception e) {
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
}
}
/**
* 견적서 엑셀 다운로드
*
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param estimateRequest 견적서 엑셀 다운로드 요청 정보
* @throws Exception
*/
public void excelDownload(HttpServletRequest request, HttpServletResponse response,
EstimateRequest estimateRequest) throws Exception {
EstimateResponse estimateResponse = new EstimateResponse();
String splitStr = "";
// 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 = estimateMapper.selectEstimatePdfDetail(estimateRequest);
// 1차점이 2차점 견적서를 만들어 준 경우 - 2차점 사용자가 다운받을 시 무조건 정가로만 표시
String userId = estimateRequest.getUserId();
String storeLvl = estimateRequest.getStoreLvl();
if (storeLvl != null && !storeLvl.equals("1")) {
if (!Objects.equals(estimateResponse.getCreateSaleStoreId(), userId)) {
estimateRequest.setSchUnitPriceFlg("1");
}
}
// file Name 명이 없는경우
if (estimateRequest.getFileName() == null || "".equals(estimateRequest.getFileName())) {
estimateRequest.setFileName(estimateResponse.getObjectNo() + "_"
+ new SimpleDateFormat("yyyyMMdd").format(new Date()));
}
if ("1".equals(estimateRequest.getSchDisplayFlg())) {
estimateResponse.setCustSaleStoreName(estimateResponse.getObjectName());
estimateResponse.setCustOmit(estimateResponse.getObjectNameOmit());
} else {
estimateResponse.setCustOmit("様邸");
}
// 견적서 잠금 처리 (최종 수정일 업데이트)
estimateRequest.setLockFlg("1");
estimateMapper.updateEstimateLock(estimateRequest);
estimateMapper.updateEstimateLastEditDate(estimateRequest);
// 견적서 특이사항 조회
List<NoteResponse> noteList = new ArrayList<NoteResponse>();
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);
}
// 지붕면 목록 조회
RoofInfoResponse roofInfoResponse = new RoofInfoResponse();
List<RoofResponse> roofList = estimateMapper.selectEstimateRoofList(estimateRequest);
List<ItemResponse> circuitItemList =
estimateMapper.selectEstimateCircuitItemList(estimateRequest);
estimateRequest.setSchItemGroup("MODULE_");
List<RoofResponse> roofVolList = estimateMapper.selectEstimateRoofVolList(estimateRequest);
BigDecimal moduleTotAmount = BigDecimal.ZERO;
BigDecimal moduleTotVolKw = BigDecimal.ZERO;
for (RoofResponse roofVol : roofVolList) {
BigDecimal amount =
new BigDecimal(StringUtils.isEmpty(roofVol.getAmount()) ? "0" : roofVol.getAmount());
BigDecimal vol =
new BigDecimal(StringUtils.isEmpty(roofVol.getVolKw()) ? "0" : roofVol.getVolKw());
String classTypeName = "";
if ("0".equals(roofVol.getClassType())) {
classTypeName = roofVol.getSlope() + "";
} else {
classTypeName = roofVol.getAngle() + "º";
}
roofVol.setClassTypeName(classTypeName);
moduleTotAmount = moduleTotAmount.add(amount);
moduleTotVolKw = moduleTotVolKw.add(vol);
}
roofInfoResponse.setModuleTotAmount(String.valueOf(moduleTotAmount));
roofInfoResponse.setModuleTotVolKw(String.valueOf(moduleTotVolKw));
roofInfoResponse.setRoofList(roofList);
roofInfoResponse.setCircuitItemList(circuitItemList);
roofInfoResponse.setRoofVolList(roofVolList);
// 인증용량 구하기 (지붕면마다 모듈과 각각의 PCS의 총 용량을 서로 비교해 낮은쪽 용량으로 합산)
roofInfoResponse.setCertVolKw(estimateMapper.selectEstimateRoofCertVolKw(estimateRequest));
//방위값
CanvasPopupStatus cps = canvasPopupStatusService.selectCanvasPopupStatus(estimateResponse.getObjectNo(), Integer.parseInt(estimateResponse.getPlanNo()), "1");
String popupStatus = cps.getPopupStatus();
ExcelUtil excelUtil = new ExcelUtil();
try {
com.fasterxml.jackson.databind.ObjectMapper jsonMapper =
new com.fasterxml.jackson.databind.ObjectMapper();
com.fasterxml.jackson.databind.JsonNode jsonNode = jsonMapper.readTree(popupStatus);
// 특정 키의 값을 가져오기
String compasDeg = jsonNode.get("compasDeg").toString();
double degreeValue = Double.parseDouble(compasDeg.replace("\"", ""));
// 각도 매핑 함수 호출
String mappedDegree = excelUtil.mapCompassDegree(degreeValue);
try {
// classpath에서 리소스 파일을 읽어옵니다
String imagePath = "/img/compass/" + mappedDegree + ".png";
InputStream imageInputStream = getClass().getResourceAsStream(imagePath);
if (imageInputStream != null) {
byte[] degImg = Util.toByteArray(imageInputStream);
roofInfoResponse.setCompasDegImg(degImg);
imageInputStream.close();
} else {
log.warn("Compass image not found: {}", imagePath);
}
} catch (IOException e) {
log.error("Error reading compass image: {}", e.getMessage(), e);
}
roofInfoResponse.setCompasDeg(compasDeg);
} catch (Exception e) {
log.error("JSON 파싱 오류: ", e);
}
estimateResponse.setRoofInfo(roofInfoResponse);
// 아이템 목록 조회
List<ItemResponse> estimateItemList = estimateMapper.selectEstimateItemList(estimateRequest);
// 총 합산금액 계산
this.selectTotalPriceInfo(estimateResponse, estimateItemList,
estimateRequest.getSchUnitPriceFlg());
boolean isPdfDownload = "PDF".equals(estimateRequest.getSchDownload());
int j = 1;
for (ItemResponse itemResponse : estimateItemList) {
itemResponse.setNo(String.valueOf(j++));
// itemName 디코딩 및 HTML Unescape 처리
String itemName = itemResponse.getItemName();
if (StringUtils.isNotEmpty(itemName)) {
try {
// 1. URL 디코딩 (% 처리)
if (itemName.contains("%")) {
itemName = URLDecoder.decode(itemName, StandardCharsets.UTF_8);
}
// 2. HTML Unescape 처리 (&가 포함된 경우만)
// &amp;amp;Phi;1 -> &amp;Phi;1 -> Φ1 순차적으로 복원
if (itemName.contains("&")) {
String prevName;
do {
prevName = itemName;
itemName = HtmlUtils.htmlUnescape(itemName);
} while (!prevName.equals(itemName) && itemName.contains("&"));
}
// 3. 엑셀/PDF 폰트(MS PGothic, BIZUDPGothic) 미지원 특수문자 치환
// Ⓡ(U+24C7) 등 Enclosed Alphanumerics는 일본어 폰트가 지원하므로 깨지지 않음
itemName = itemName
.replace("\u00AE", "\u24C7") // ® → Ⓡ
.replace("\u2122", "(TM)") // ™ → (TM)
.replace("\u00A9", "(C)") // © → (C)
.replace("\u2013", "-") // (en dash) → -
.replace("\u2014", "-") // — (em dash) → -
.replace("\u2018", "'") // ' → '
.replace("\u2019", "'") // ' → '
.replace("\u201C", "\"") // " → "
.replace("\u201D", "\"") // " → "
.replace("\u2026", "..."); // … → ...
itemResponse.setItemName(itemName);
} catch (Exception e) {
log.warn("Excel itemName processing failed: {}", itemName);
}
}
// 문자열 통화로 변환 처리 (PDF 전용)
if (isPdfDownload) {
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())
&& (!StringUtils.isEmpty(itemResponse.getPaDispOrder())
|| !"1".equals(itemResponse.getPkgMaterialFlg()))) {
itemResponse.setSalePrice("");
itemResponse.setSaleTotPrice("");
}
// 886 Excel, PDF에 OPEN_FLG = 1은 단가필드에 OPEN 텍스트로 보여주도록
if ("1".equals(itemResponse.getOpenFlg())) {
itemResponse.setSalePrice("OPEN");
itemResponse.setSaleTotPrice("OPEN");
}
String nullChk = StringUtils.isEmpty(itemResponse.getSalePrice()) ? "0" : itemResponse.getSalePrice();
if ("1".equals(itemResponse.getUnitOpenFlg()) && "1".equals(estimateRequest.getSchUnitPriceFlg())){
itemResponse.setSalePrice("OPEN");
itemResponse.setSaleTotPrice("OPEN");
}
}
// 합산 문자열 통화로 변환 처리
estimateResponse.setPkgYn("YJSS".equals(estimateResponse.getEstimateType()) ? "Y" : "N");
estimateResponse
.setPkgNo("YJSS".equals(estimateResponse.getEstimateType()) ? String.valueOf(j++) : "");
if (isPdfDownload) {
if ("YJSS".equals(estimateResponse.getEstimateType())) {
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())));
}
// 발전시뮬레이션 계산
PwrGnrSimRequest pwrGnrSimRequest = new PwrGnrSimRequest();
pwrGnrSimRequest.setObjectNo(estimateResponse.getObjectNo());
pwrGnrSimRequest.setPlanNo(estimateResponse.getPlanNo());
PwrGnrSimResponse pwrGnrSimResponse =
pwrGnrSimService.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 =
pwrGnrSimService.selectPwrGnrSimulationGuideInfo();
if (pwrGnrSimGuideInfo != null) {
pwrGnrSimResponse.setGuideInfo(pwrGnrSimGuideInfo.getData());
}
} catch (Exception e) {
log.error(e.toString());
}
}
estimateResponse.setPwrGnrSim(pwrGnrSimResponse);
// 도면 이미지 셋팅
String baseDrawingImgName = estimateRequest.getObjectNo() + "_" + estimateRequest.getPlanNo();
// 셀범위용 이미지 (기존 이미지명 유지: _1.png, _2.png)
URL url = new URL(drawingDirPath + File.separator + baseDrawingImgName + "_1.png");
byte[] drawingImg1 = loadDrawingImage(url);
if (drawingImg1 != null) {
estimateResponse.setDrawingImg1(drawingImg1);
}
log.debug("url1 ::: {}", url);
URL url2 = new URL(drawingDirPath + File.separator + baseDrawingImgName + "_2.png");
byte[] drawingImg2 = loadDrawingImage(url2);
if (drawingImg2 != null) {
estimateResponse.setDrawingImg2(drawingImg2);
}
log.debug("url2 ::: {}", url2);
// 풀사이즈 이미지 (P1, P2 시트용: _1_full.png, _2_full.png)
URL urlFull1 = new URL(drawingDirPath + File.separator + baseDrawingImgName + "_1_full.png");
byte[] drawingImg1Full = loadDrawingImage(urlFull1);
if (drawingImg1Full != null) {
estimateResponse.setDrawingImg1Full(drawingImg1Full);
} else {
// full 이미지가 없으면 기존 이미지로 폴백
estimateResponse.setDrawingImg1Full(drawingImg1);
}
URL urlFull2 = new URL(drawingDirPath + File.separator + baseDrawingImgName + "_2_full.png");
byte[] drawingImg2Full = loadDrawingImage(urlFull2);
if (drawingImg2Full != null) {
estimateResponse.setDrawingImg2Full(drawingImg2Full);
} else {
estimateResponse.setDrawingImg2Full(drawingImg2);
}
//userId 에 따른 영업점 주소, 전화, fax 정보 조회
if(estimateRequest.getSaleStoreId() != null && "T01".equals(estimateRequest.getSaleStoreId())){
String strResponse = interfaceQsp.callApi(HttpMethod.GET,
QSP_API_URL + "/api/admin/userDetail?loginId="+estimateRequest.getUserId(), null);
if (!"".equals(strResponse)) {
com.fasterxml.jackson.databind.ObjectMapper om =
new com.fasterxml.jackson.databind.ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
EstimateApiResponse estimateApiResponse = om.readValue(strResponse, EstimateApiResponse.class);
// API 응답 데이터 존재 여부 확인 및 안전한 데이터 추출
if (estimateApiResponse != null && estimateApiResponse.getData() != null) {
try {
// API 응답 데이터를 Map으로 변환하여 필요한 정보 추출
@SuppressWarnings("unchecked")
Map<String, Object> userData = (Map<String, Object>) estimateApiResponse.getData();
if (!userData.isEmpty()) {
//영업점 주소 확인 및 설정
Object salesOfficeAddr = userData.get("salesOfficeAddr");
if (salesOfficeAddr != null &&
!StringUtils.isEmpty(salesOfficeAddr.toString().trim())) {
estimateResponse.setZipNo("");
estimateResponse.setAddress(salesOfficeAddr.toString().replaceAll("\n", "<br>"));
}
//영업점 전화 확인 및 설정
Object salesOfficeTel = userData.get("salesOfficeTel");
if (salesOfficeTel != null &&
!StringUtils.isEmpty(salesOfficeTel.toString().trim())) {
estimateResponse.setTel(salesOfficeTel.toString());
}
//영업점 팩스 확인 및 설정
Object salesOfficeFax = userData.get("salesOfficeFax");
if (salesOfficeFax != null &&
!StringUtils.isEmpty(salesOfficeFax.toString().trim())) {
estimateResponse.setFax(salesOfficeFax.toString());
}
}
} catch (ClassCastException e) {
log.warn("API 응답 데이터 형변환 실패: {}", e.getMessage());
}
}
} else {
log.warn("common.message.required.data", "User Detail");
}
}
if ("PDF".equals(estimateRequest.getSchDownload())) { // PDF 다운로드
String[] arrSection = new String[6];
int iSection = 0;
String templateFilePath = "pdf_download_quotation_detail_template.html";
// 템플릿 html 조회
Document doc = PdfUtil.getPdfDoc(request, templateFilePath);
// 견적서 상세 pdf Html 생성
doc = this.estimatePdfHtml(doc, estimateResponse, estimateItemList);
// 발전시뮬레이션 pdf Html 생성
doc = pwrGnrSimService.pwrGnrSimPdfHtml(doc, pwrGnrSimResponse);
// SchDrawingFlg (1 : 견적서,2 : 발전시뮬레이션, 3 : 도면, 4 : 가대)
// ex) 1|2|3|4
if (!StringUtils.isEmpty(estimateRequest.getSchDrawingFlg())) {
if (estimateRequest.getSchDrawingFlg().indexOf("1") > -1) {
arrSection[iSection] = "div.section1";
iSection++;
arrSection[iSection] = "div.section2";
iSection++;
}
if (estimateRequest.getSchDrawingFlg().indexOf("2") > -1) {
arrSection[iSection] = "div.section3"; // 발전시뮬레이션
iSection++;
}
if (estimateRequest.getSchDrawingFlg().indexOf("3") > -1) {
arrSection[iSection] = "div.section4"; // 도면
iSection++;
arrSection[iSection] = "div.section5"; // 도면
iSection++;
}
if (estimateRequest.getSchDrawingFlg().indexOf("4") > -1) {
arrSection[iSection] = "div.section6";
iSection++;
}
}
// 섹션별 방향 설정 (이미지가 들어가는 섹션은 가로)
java.util.Map<String, Boolean> sectionOrientation = new java.util.HashMap<>();
sectionOrientation.put("div.section3", true); // 발전시뮬레이션 - 가로
sectionOrientation.put("div.section4", true); // 도면 - 가로
sectionOrientation.put("div.section5", true); // 도면 - 가로
// pdf 다운로드
PdfUtil.pdfDownload(request, response, doc, estimateRequest.getFileName(), arrSection, false, sectionOrientation);
} else {
Workbook workbook = null;
String excelTemplateNam = "excel_download_quotation_detail_template.xlsx";
// itemGroup이 "STAND_"가 아닌 항목들만 필터링하여 새로운 리스트 생성
List<ItemResponse> estimateItemList15 = estimateItemList.stream()
.filter(item -> !"STAND_".equals(item.getItemGroup()))
.collect(Collectors.toList());
// itemGroup이 "STAND_"인 항목들만 필터링하여 새로운 리스트 생성
List<ItemResponse> estimateItemListS15 = estimateItemList.stream()
.filter(item -> "STAND_".equals(item.getItemGroup()))
.collect(Collectors.toList());
if(estimateItemListS15.size() < 16) {
// 15개 미만인 경우, 나머지 아이템을 빈 값으로 채움
for (int k = estimateItemListS15.size(); k < 15; k++) {
ItemResponse emptyItem = new ItemResponse();
estimateItemListS15.add(emptyItem);
}
}else {
// 15개 이상인 경우, 15개로 자름
estimateItemListS15 = estimateItemListS15.subList(0, 14);
}
estimateResponse.setEstimateItemListS15(estimateItemListS15);
if(estimateItemList15.size() < 16) {
// 15개 미만인 경우, 나머지 아이템을 빈 값으로 채움
for (int k = estimateItemList15.size(); k < 15; k++) {
ItemResponse emptyItem = new ItemResponse();
emptyItem.setNo(String.valueOf(k + 1));
estimateItemList15.add(emptyItem);
}
}else {
// 15개 이상인 경우, 15개로 자름
estimateItemList15 = estimateItemList15.subList(0, 14);
}
estimateResponse.setEstimateItemList15(estimateItemList15);
List<ItemResponse> circuitItemList11 = estimateResponse.getRoofInfo().getCircuitItemList();
if (circuitItemList11 != null && circuitItemList11.size() < 12){
// 12개 미만인 경우, 나머지 아이템을 빈 값으로 채움
for (int k = circuitItemList11.size(); k < 11; k++) {
ItemResponse emptyItem = new ItemResponse();
circuitItemList11.add(emptyItem);
}
}else {
// 12개 이상인 경우, 12개로 자름
circuitItemList11 = circuitItemList11.subList(0, 11);
}
estimateResponse.setCircuitItemList11(circuitItemList11);
// 지붕면 목록에서 8개로 자름
List<PwrGnrSimRoofResponse> roofModuleList8 = estimateResponse.getPwrGnrSim().getRoofModuleList();
if (roofModuleList8 != null && roofModuleList8.size() < 9) {
// 9개 미만인 경우, 나머지 아이템을 빈 값으로 채움
for (int k = roofModuleList8.size(); k < 8; k++) {
PwrGnrSimRoofResponse emptyRoof = new PwrGnrSimRoofResponse();
roofModuleList8.add(emptyRoof);
}
}else {
// 9개 이상인 경우, 9개로 자름
roofModuleList8 = roofModuleList8.subList(0, 8);
}
estimateResponse.setRoofModuleList8(roofModuleList8);
//pcs list 3개
List<PwrGnrSimRoofResponse> pcsList3 = estimateResponse.getPwrGnrSim().getPcsList();
if (pcsList3 != null && pcsList3.size() < 4) {
// 4개 미만인 경우, 나머지 아이템을 빈 값으로 채움
for (int k = pcsList3.size(); k < 4; k++) {
PwrGnrSimRoofResponse emptyPcs = new PwrGnrSimRoofResponse();
pcsList3.add(emptyPcs);
}
} else {
// 4개 이상인 경우, 4개로 자름
pcsList3 = pcsList3.subList(0, 3);
}
estimateResponse.setPcsList3(pcsList3);
excelUtil = new ExcelUtil();
Map<String, Object> excelData = excelUtil.convertVoToMap(estimateResponse);
List<Map<String, Object>> excelList = excelUtil.convertListToMap(estimateItemList);
coerceExcelDataNumberFields(excelData);
coerceExcelItemNumberFields(excelList);
putExcelItemList(excelData, "itemList", estimateResponse.getItemList());
putExcelItemList(excelData, "estimateItemList15", estimateResponse.getEstimateItemList15());
putExcelItemList(excelData, "estimateItemListS15", estimateResponse.getEstimateItemListS15());
putExcelItemList(excelData, "circuitItemList11", estimateResponse.getCircuitItemList11());
putExcelRoofList(excelData, "roofModuleList8", estimateResponse.getRoofModuleList8());
putExcelRoofList(excelData, "pcsList3", estimateResponse.getPcsList3());
byte[] excelBytes =
excelUtil.download(request, response, excelData, excelList, excelTemplateNam);
if (excelBytes == null || excelBytes.length == 0) {
throw new RuntimeException("Excel template processing returned empty result. Template: " + excelTemplateNam);
}
InputStream in = new ByteArrayInputStream(excelBytes);
workbook = WorkbookFactory.create(in); // JXLS POI 엑셀로 재변환
// SchDrawingFlg (1 : 견적서,2 : 발전시뮬레이션, 3 : 도면, 4 : 가대)
// ex) 1|2|3|4
if (!StringUtils.isEmpty(estimateRequest.getSchDrawingFlg())) {
if (estimateRequest.getSchDrawingFlg().indexOf("1") < 0) {
safeRemoveSheet(workbook, "見積書");
safeRemoveSheet(workbook, "特異事項");
}
if (estimateRequest.getSchDrawingFlg().indexOf("2") < 0) {
safeRemoveSheet(workbook, "発電シミュレーション");
}
if (estimateRequest.getSchDrawingFlg().indexOf("3") < 0) {
safeRemoveSheet(workbook, "割付図・系統図");
safeRemoveSheet(workbook, "架台図");
safeRemoveSheet(workbook, "P1");
safeRemoveSheet(workbook, "P2");
}
safeRemoveSheet(workbook, "特異事項");
}
// 추후 개발 (가대중량표)
if (estimateRequest.getSchDrawingFlg().indexOf("4") < 0) {
safeRemoveSheet(workbook, "重量算出シート");
safeRemoveSheet(workbook, "特異事項");
}
if ("EXCEL2".equals(estimateRequest.getSchDownload())) {
safeRemoveSheet(workbook, "見積書");
safeRemoveSheet(workbook, "特異事項");
safeRemoveSheet(workbook, "発電シミュレーション");
safeRemoveSheet(workbook, "割付図・系統図");
safeRemoveSheet(workbook, "架台図");
safeRemoveSheet(workbook, "重量算出シート");
safeRemoveSheet(workbook, "P1");
safeRemoveSheet(workbook, "P2");
}else{
safeRemoveSheet(workbook,"見積書.");
safeRemoveSheet(workbook, "特異事項");
}
applyExcelNumberFormat(workbook);
// applyExcelFixedNumberFormat(workbook, Arrays.asList("H25", "C12"), "#,##0.00");
// applyExcelFixedNumberFormat(workbook, Arrays.asList("X32", "I44"), "#,##0.00");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
workbook.write(byteArrayOutputStream);
excelBytes = byteArrayOutputStream.toByteArray();
response.setHeader("Content-Disposition",
"attachment; filename=\"" + estimateRequest.getFileName() + ".xlsx\"");
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.getOutputStream().write(excelBytes);
}
} catch (Exception e) {
log.error("Failed to excelDownload estimate. Request: {}", request, e);
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
}
}
/**
* 아이템 목록을 통한 견적서 가격 자동계산
*
* @param estimateResponse 견적서 정보
* @param itemList 아이템 정보 목록
* @param unitPriceFlg 가격 표시 코드
* @throws Exception
*/
public void selectTotalPriceInfo(EstimateResponse estimateResponse, List<ItemResponse> itemList,
String unitPriceFlg) throws Exception {
BigDecimal totAmount = BigDecimal.ZERO;
BigDecimal totVol = BigDecimal.ZERO;
BigDecimal pkgTotPrice = BigDecimal.ZERO;
BigDecimal supplyPrice = BigDecimal.ZERO;
BigDecimal vatPrice = BigDecimal.ZERO;
BigDecimal totPrice = BigDecimal.ZERO;
String estimateType = estimateResponse.getEstimateType();
// 주택패키지 단가
BigDecimal pkgAsp = new BigDecimal(
StringUtils.isEmpty(estimateResponse.getPkgAsp()) ? "0" : estimateResponse.getPkgAsp());
for (ItemResponse itemResponse : itemList) {
// 수량
BigDecimal amount = new BigDecimal(
StringUtils.isEmpty(itemResponse.getAmount()) ? "0" : itemResponse.getAmount());
// 판매가
BigDecimal salePrice = BigDecimal.ZERO;
if ("1".equals(unitPriceFlg)) {
salePrice = new BigDecimal(
StringUtils.isEmpty(itemResponse.getUnitPrice()) ? "0" : itemResponse.getUnitPrice());
itemResponse.setSalePrice(String.valueOf(salePrice));
} else {
salePrice = new BigDecimal(
StringUtils.isEmpty(itemResponse.getSalePrice()) ? "0" : itemResponse.getSalePrice());
}
// 아이템용량
BigDecimal pnowW = new BigDecimal(
StringUtils.isEmpty(itemResponse.getPnowW()) ? "0" : itemResponse.getPnowW());
// 아이템 단가 합산
itemResponse.setSaleTotPrice(String.valueOf(salePrice.multiply(amount)));
// 컴포넌트는 제외하고 계산
if (StringUtils.isEmpty(itemResponse.getPaDispOrder())) {
// YJSS인 경우 (PKG 단가 * 모듈용량) + 패키지 제외상품 총 합산
// YJOD인 경우 모든 아이템의 총 합산
if ("YJSS".equals(estimateType)) {
if ("1".equals(itemResponse.getModuleFlg())) {
totVol = totVol.add(pnowW.multiply(amount));
}
if ("1".equals(itemResponse.getPkgMaterialFlg())) { // 패키지 제외상품 여부(1)
supplyPrice = supplyPrice.add(salePrice.multiply(amount));
}
} else {
if ("1".equals(itemResponse.getModuleFlg())) {
totVol = totVol.add(pnowW.multiply(amount));
}
supplyPrice = supplyPrice.add(salePrice.multiply(amount));
}
}
// 주문수량 더하기
totAmount = totAmount.add(amount);
}
if ("YJSS".equals(estimateType)) {
pkgTotPrice = pkgAsp.multiply(totVol);
pkgTotPrice = pkgTotPrice.setScale(0, BigDecimal.ROUND_HALF_UP);
supplyPrice = supplyPrice.add(pkgTotPrice);
}
// 부가세 계산 (10프로)
vatPrice = supplyPrice.multiply(new BigDecimal("0.1"));
// 총 가격 합산 (공급가 + 부가세)
totPrice = totPrice.add(supplyPrice.add(vatPrice));
estimateResponse.setPkgTotPrice(String.valueOf(pkgTotPrice));
estimateResponse.setTotAmount(String.valueOf(totAmount.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)));
}
private static final Set<String> EXCEL_ITEM_NUMBER_FIELDS = new HashSet<>(
Arrays.asList("amount", "bomAmount", "salePrice", "unitPrice", "saleTotPrice", "grossWt", "pnowW"));
private static final Set<String> EXCEL_DATA_NUMBER_FIELDS = new HashSet<>(
Arrays.asList("pkgAsp", "totAmount", "totVol", "totVolKw", "pkgTotPrice",
"supplyPrice", "vatPrice", "totPrice"));
private static final Set<String> EXCEL_ROOF_NUMBER_FIELDS = new HashSet<>(
Arrays.asList("amount", "totSpecification", "specification", "cnvEff",
"amp", "tempLoss", "tempCoeff"));
private static void coerceExcelItemNumberFields(List<Map<String, Object>> list) {
if (list == null) {
return;
}
for (Map<String, Object> row : list) {
coerceExcelNumberFields(row, EXCEL_ITEM_NUMBER_FIELDS);
}
}
private static void coerceExcelDataNumberFields(Map<String, Object> map) {
coerceExcelNumberFields(map, EXCEL_DATA_NUMBER_FIELDS);
coerceExcelScale(map, "totVol", 2);
}
private static void coerceExcelRoofNumberFields(List<Map<String, Object>> list) {
if (list == null) {
return;
}
for (Map<String, Object> row : list) {
coerceExcelNumberFields(row, EXCEL_ROOF_NUMBER_FIELDS);
}
}
private static void coerceExcelNumberFields(Map<String, Object> map, Set<String> fields) {
if (map == null || fields == null) {
return;
}
for (String key : fields) {
if (!map.containsKey(key)) {
continue;
}
Object value = map.get(key);
Object parsed = parseExcelNumber(value);
map.put(key, parsed);
}
}
private static Object parseExcelNumber(Object value) {
if (value == null) {
return null;
}
if (value instanceof Number) {
return value;
}
if (!(value instanceof String)) {
return value;
}
String raw = ((String) value).trim();
if (raw.isEmpty()) {
return value;
}
String normalized = raw.replace(",", "");
if (!normalized.matches("[-+]?\\d+(\\.\\d+)?")) {
return value;
}
try {
return new BigDecimal(normalized);
} catch (NumberFormatException e) {
return value;
}
}
private static void coerceExcelScale(Map<String, Object> map, String key, int scale) {
if (map == null || key == null) {
return;
}
Object value = map.get(key);
Object parsed = parseExcelNumber(value);
if (!(parsed instanceof Number)) {
return;
}
BigDecimal decimal;
if (parsed instanceof BigDecimal) {
decimal = (BigDecimal) parsed;
} else {
decimal = new BigDecimal(parsed.toString());
}
map.put(key, decimal.setScale(scale, RoundingMode.HALF_UP));
}
private static void putExcelItemList(Map<String, Object> excelData, String key,
List<ItemResponse> items) {
if (excelData == null || items == null) {
return;
}
List<Map<String, Object>> list = ExcelUtil.convertListToMap(items);
coerceExcelItemNumberFields(list);
excelData.put(key, list);
}
private static void putExcelRoofList(Map<String, Object> excelData, String key,
List<PwrGnrSimRoofResponse> items) {
if (excelData == null || items == null) {
return;
}
List<Map<String, Object>> list = ExcelUtil.convertListToMap(items);
coerceExcelRoofNumberFields(list);
excelData.put(key, list);
}
private static void applyExcelNumberFormat(Workbook workbook) {
if (workbook == null) {
return;
}
DataFormat dataFormat = workbook.createDataFormat();
short numberFormat = dataFormat.getFormat("#,##0.###");
Map<Short, CellStyle> styleCache = new HashMap<>();
for (int s = 0; s < workbook.getNumberOfSheets(); s++) {
Sheet sheet = workbook.getSheetAt(s);
if (sheet == null) {
continue;
}
for (Row row : sheet) {
for (Cell cell : row) {
CellType cellType = cell.getCellType();
CellStyle style = cell.getCellStyle();
boolean isTextFormat = style != null && "@".equals(style.getDataFormatString());
if (cellType == CellType.STRING) {
Object parsed = parseExcelNumber(cell.getStringCellValue());
if (parsed instanceof Number) {
cell.setCellValue(((Number) parsed).doubleValue());
cellType = CellType.NUMERIC;
} else {
continue;
}
}
if (cellType != CellType.NUMERIC) {
continue;
}
if (!isTextFormat) {
continue;
}
short styleIdx = style.getIndex();
CellStyle cached = styleCache.get(styleIdx);
if (cached == null) {
CellStyle newStyle = workbook.createCellStyle();
newStyle.cloneStyleFrom(style);
newStyle.setDataFormat(numberFormat);
styleCache.put(styleIdx, newStyle);
cached = newStyle;
}
cell.setCellStyle(cached);
}
}
}
}
private static void applyExcelFixedNumberFormat(Workbook workbook, List<String> cellRefs,
String formatString) {
if (workbook == null || cellRefs == null || formatString == null) {
return;
}
DataFormat dataFormat = workbook.createDataFormat();
short numberFormat = dataFormat.getFormat(formatString);
Map<Short, CellStyle> styleCache = new HashMap<>();
for (int s = 0; s < workbook.getNumberOfSheets(); s++) {
Sheet sheet = workbook.getSheetAt(s);
if (sheet == null) {
continue;
}
for (String ref : cellRefs) {
int[] rc = parseCellRef(ref);
if (rc == null) {
continue;
}
Row row = sheet.getRow(rc[0]);
if (row == null) {
continue;
}
Cell cell = row.getCell(rc[1]);
if (cell == null) {
continue;
}
CellType cellType = cell.getCellType();
if (cellType == CellType.STRING) {
Object parsed = parseExcelNumber(cell.getStringCellValue());
if (parsed instanceof Number) {
cell.setCellValue(((Number) parsed).doubleValue());
cellType = CellType.NUMERIC;
}
}
if (cellType != CellType.NUMERIC) {
continue;
}
CellStyle style = cell.getCellStyle();
if (style == null) {
style = workbook.createCellStyle();
}
short styleIdx = style.getIndex();
CellStyle cached = styleCache.get(styleIdx);
if (cached == null) {
CellStyle newStyle = workbook.createCellStyle();
newStyle.cloneStyleFrom(style);
newStyle.setDataFormat(numberFormat);
styleCache.put(styleIdx, newStyle);
cached = newStyle;
}
cell.setCellStyle(cached);
}
}
}
private static int[] parseCellRef(String ref) {
if (ref == null || ref.isEmpty()) {
return null;
}
int i = 0;
int col = 0;
while (i < ref.length()) {
char c = ref.charAt(i);
if (c < 'A' || c > 'Z') {
break;
}
col = col * 26 + (c - 'A' + 1);
i++;
}
if (i == 0 || i >= ref.length()) {
return null;
}
int row;
try {
row = Integer.parseInt(ref.substring(i));
} catch (NumberFormatException e) {
return null;
}
return new int[] {row - 1, col - 1};
}
/**
* QSP Q.CAST 견적서 전송 API
*
* @param estimateRequest 견적서 요청 정보
* @return String 문서번호
* @throws Exception
*/
public List<EstimateSendResponse> sendEstimateApi(EstimateRequest estimateRequest)
throws Exception {
EstimateSendRequest estimateSendRequest = new EstimateSendRequest();
List<EstimateSendResponse> quoteList = new ArrayList<EstimateSendResponse>();
String docNo = "";
try {
// 견적서 상세 조회
EstimateSendResponse estimateSendResponse =
estimateMapper.selectEstimateApiDetail(estimateRequest);
if (estimateSendResponse == null) {
throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
} else {
String constructSpecification =
estimateMapper.selectEstimateConstructSpecification(estimateRequest);
estimateSendResponse.setSaveType("3");
estimateSendResponse.setSyncFlg("0");
estimateSendResponse.setConstructSpecification(
!StringUtils.isEmpty(constructSpecification) ? constructSpecification : "");
estimateSendResponse.setDelFlg("1".equals(estimateSendResponse.getDelFlg()) ? "Y" : "N");
// 아이템 목록 조회
estimateRequest.setSchBomNotExist("1");
List<ItemResponse> estimateItemList =
estimateMapper.selectEstimateItemList(estimateRequest);
estimateSendResponse.setItemList(estimateItemList);
// 첨부파일 목록 조회
FileRequest fileDeleteReq = new FileRequest();
fileDeleteReq.setObjectNo(estimateRequest.getObjectNo());
fileDeleteReq.setPlanNo(estimateRequest.getPlanNo());
fileDeleteReq.setCategory("10");
List<FileResponse> fileList = fileMapper.selectFileList(fileDeleteReq);
estimateSendResponse.setFileList(fileList);
quoteList.add(estimateSendResponse);
estimateSendRequest.setQuoteList(quoteList);
// 2차점명
estimateSendResponse.setSecSapSalesStoreCd(estimateRequest.getSecSapSalesStoreCd());
}
EstimateApiResponse response = null;
/* [1]. QSP API CALL -> Response */
String strResponse = interfaceQsp.callApi(HttpMethod.POST,
QSP_API_URL + "/api/order/qcastQuotationSave", estimateSendRequest);
if (!"".equals(strResponse)) {
com.fasterxml.jackson.databind.ObjectMapper om =
new com.fasterxml.jackson.databind.ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
response = om.readValue(strResponse, EstimateApiResponse.class);
Map<String, Object> result = (Map<String, Object>) response.getData();
if (result != null) {
List<Map<String, Object>> succList =
(List<Map<String, Object>>) result.get("successList");
for (Map<String, Object> succ : succList) {
if (succ != null) {
for (EstimateSendResponse data : quoteList) {
if (data.getObjectNo().equals(succ.get("objectNo"))
&& data.getPlanNo().equals(succ.get("planNo"))) {
data.setSyncFlg(String.valueOf(succ.get("syncFlg")));
data.setDocNo(String.valueOf(succ.get("docNo")));
}
}
}
}
}
} else {
log.error("sendEstimateApi >>> " + message.getMessage("common.message.no.data"));
}
} catch (Exception e) {
log.error("sendEstimateApi Error >>> " + e.getMessage());
}
return quoteList;
}
/**
* 견적서 PDF HTML 생성
*
* @param doc Document
* @param data 견적서 상세정보
* @param list 견적서 아이템 목록 정보
* @return Document Document
* @throws IOException
* @throws QcastException
*/
public Document estimatePdfHtml(Document doc, EstimateResponse data, List<ItemResponse> list)
throws IOException, QcastException {
Element elm;
// 견적서 상세 정보 설정
elm = doc.getElementById("custSaleStoreName");
elm.text(StringUtils.defaultString(data.getCustSaleStoreName()));
elm = doc.getElementById("custOmit");
elm.text(StringUtils.defaultString(data.getCustOmit()));
elm = doc.getElementById("estimateValidityTerm");
elm.text(StringUtils.defaultString(data.getEstimateValidityTerm()));
elm = doc.getElementById("objectName1");
elm.text(StringUtils.defaultString(data.getObjectName()));
elm = doc.getElementById("objectNameOmit1");
elm.text(StringUtils.defaultString(data.getObjectNameOmit()));
elm = doc.getElementById("objectNo1");
elm.text(StringUtils.defaultString(data.getObjectNo()) + " / "
+ StringUtils.defaultString(data.getPlanNo()));
/*
* elm = doc.getElementById("planNo"); elm.text(StringUtils.defaultString(data.getPlanNo()));
*/
elm = doc.getElementById("estimateDate");
elm.text(StringUtils.defaultString(data.getEstimateDate()));
elm = doc.getElementById("saleStoreName");
elm.text(StringUtils.defaultString(data.getSaleStoreName()));
elm = doc.getElementById("bizNo");
elm.text(StringUtils.defaultString(data.getBizNo()));
elm = doc.getElementById("zipNo");
elm.text("(" + StringUtils.defaultString(data.getZipNo()) + ")");
elm = doc.getElementById("address");
elm.text(StringUtils.defaultString(data.getAddress()));
elm = doc.getElementById("tel");
elm.text(StringUtils.defaultString(data.getTel()));
elm = doc.getElementById("fax");
elm.text(StringUtils.defaultString(data.getFax()));
elm = doc.getElementById("totVolKw1");
elm.text(StringUtils.defaultString(data.getTotVolKw()));
elm = doc.getElementById("totPrice");
elm.text(StringUtils.defaultString(data.getTotPrice()));
StringBuilder sb = new StringBuilder();
for (ItemResponse itemResponse : list) {
sb.append("<tr>");
sb.append(
"<td style='width:60px;'>" + StringUtils.defaultString(itemResponse.getNo()) + "</td>");
sb.append("<td style='width:120px;text-align:left;'>"
+ StringUtils.defaultString(itemResponse.getItemName()) + "</td>");
sb.append("<td style='width:120px;'>" + StringUtils.defaultString(itemResponse.getItemNo())
+ "</td>");
sb.append(
"<td class='hide-column' style='width:80px;text-align:right;'>"
+ StringUtils.defaultString(itemResponse.getSalePrice())
+ "</td>");
sb.append("<td style='width:60px;text-align:right;'>"
+ StringUtils.defaultString(itemResponse.getAmount()) + "</td>");
sb.append(
"<td style='width:60px;'>" + StringUtils.defaultString(itemResponse.getUnit()) + "</td>");
sb.append("<td class='hide-column' style='width:80px;text-align:right;'>"
+ StringUtils.defaultString(itemResponse.getSaleTotPrice()) + "</td>");
sb.append("</tr>");
}
if ("Y".equals(data.getPkgYn())) {
sb.append("<tr>");
sb.append("<td style='width:60px;'>" + StringUtils.defaultString(data.getPkgNo()) + "</td>");
sb.append("<td style='width:120px;text-align:left;'>住宅 PKG</td>");
sb.append("<td style='width:120px;'>-</td>");
sb.append("<td style='width:80px;text-align:right;'>"
+ StringUtils.defaultString(data.getPkgAsp()) + "</td>");
sb.append("<td style='width:60px;text-align:right;'>"
+ StringUtils.defaultString(data.getTotVol()) + "</td>");
sb.append("<td style='width:60px;'>W</td>");
sb.append("<td style='width:80px;text-align:right;'>"
+ StringUtils.defaultString(data.getPkgTotPrice()) + "</td>");
sb.append("</tr>");
}
elm = doc.getElementById("itemList_detail");
elm.before(sb.toString());
elm = doc.getElementById("supplyPrice");
elm.text(StringUtils.defaultString(data.getSupplyPrice()));
elm = doc.getElementById("vatPrice");
elm.text(StringUtils.defaultString(data.getVatPrice()));
elm = doc.getElementById("totPrice1");
elm.text(StringUtils.defaultString(data.getTotPrice()));
if (!StringUtils.isEmpty(data.getRemarks())) {
elm = doc.getElementById("remarks");
elm.text(StringUtils.defaultString(data.getRemarks()));
} else {
elm = doc.getElementById("remarks");
elm.remove();
}
// 견적서 특이사항 목록 설정
// if (data.getNoteList() != null) {
// sb = new StringBuilder();
// for (NoteResponse noteResponse : data.getNoteList()) {
// sb.append("<tr>");
// sb.append("<td style='text-align:left;'>"
// + StringUtils.defaultString(noteResponse.getCodeNm()) + "</td>");
// sb.append("<td style='text-align:left;'>" + StringUtils
// .defaultString(noteResponse.getRemarks()).replaceAll("\r\n|\r|\n", "<br />") + "</td>");
// sb.append("</tr>");
// }
// elm = doc.getElementById("noteList_detail");
// elm.append(sb.toString());
// }
// 도면 설정
elm = doc.getElementById("objectNo4");
elm.text(StringUtils.defaultString(data.getObjectNo()) + " (Plan No : "
+ StringUtils.defaultString(data.getPlanNo()) + ")");
elm = doc.getElementById("objectName");
elm.text(StringUtils.defaultString(data.getObjectName()) + " " + StringUtils.defaultString(data.getObjectNameOmit()));
elm = doc.getElementById("totVolKw");
elm.text(StringUtils.defaultString(data.getTotVolKw()) + " Kw");
elm = doc.getElementById("certVolKw");
elm.text(StringUtils.defaultString(data.getRoofInfo().getCertVolKw()) + " Kw");
elm = doc.getElementById("drawingEstimateCreateDate4");
elm.text(StringUtils.defaultString(data.getDrawingEstimateCreateDate()));
elm = doc.getElementById("prefName4");
elm.text(StringUtils.defaultString(data.getPrefName()));
elm = doc.getElementById("areaName4");
elm.text(StringUtils.defaultString(data.getAreaName()));
elm = doc.getElementById("snowfall4");
elm.text(StringUtils.defaultString(data.getSnowfall()) + " cm");
elm = doc.getElementById("standardWindSpeedName4");
elm.text(StringUtils.defaultString(data.getStandardWindSpeedName()));
// elm = doc.getElementById("deg1");
// elm.text(StringUtils.defaultString(data.getRoofInfo().getCompasDeg())+"°");
// 도면(가대제외 이미지)
if (data.getDrawingImg1() != null) {
elm = doc.getElementById("drawingImg1");
String imgSrc1 = Base64.getEncoder().encodeToString(data.getDrawingImg1());
elm.html("<img src='data:image/png;base64," + imgSrc1 + "' width='100%'/>");
}
if (data.getRoofInfo().getCompasDegImg() != null) {
elm = doc.getElementById("degImg1");
String imgSrc1 = Base64.getEncoder().encodeToString(data.getRoofInfo().getCompasDegImg());
elm.html(
"<img src='data:image/png;base64,"
+ imgSrc1
+ "' width='50'/><div class=\"guide-img-tit\" >"+ StringUtils.defaultString(data.getRoofInfo().getCompasDeg()) + "°</div>");
}
int no = 1;
sb = new StringBuilder();
for (ItemResponse itemResponse : list) {
if (!"STAND_".equals(itemResponse.getItemGroup())) {
sb.append("<tr>");
sb.append("<td>" + (no++) + "</td>");
sb.append("<td style='text-align:left;'>"
+ StringUtils.defaultString(itemResponse.getItemNo()) + "</td>");
sb.append("<td style='text-align:right;'>"
+ StringUtils.defaultString(itemResponse.getAmount()) + "</td>");
sb.append("</tr>");
}
}
elm = doc.getElementById("notStandItemList_detail");
elm.append(sb.toString());
if (data.getRoofInfo().getCircuitItemList() != null) {
no = 1;
sb = new StringBuilder();
for (ItemResponse itemResponse : data.getRoofInfo().getCircuitItemList()) {
sb.append("<tr>");
sb.append("<td>" + (no++) + "</td>");
sb.append(
"<td style='text-align:left;'>" + StringUtils.defaultString(itemResponse.getItemNo())
+ " [" + itemResponse.getCircuitCfg() + "]" + "</td>");
sb.append("</tr>");
}
elm = doc.getElementById("pcsItemList_detail");
elm.append(sb.toString());
}
if (data.getRoofInfo().getRoofVolList() != null) {
sb = new StringBuilder();
for (RoofResponse roofResponse : data.getRoofInfo().getRoofVolList()) {
sb.append("<tr>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getRoofSurface()) + "</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getClassTypeName()) + "</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getAmount()) + "</td>");
sb.append("<td style='text-align:right;'>"
+ StringUtils.defaultString(roofResponse.getVolKw()) + "</td>");
sb.append("</tr>");
}
elm = doc.getElementById("surFaceList_detail");
elm.before(sb.toString());
elm = doc.getElementById("moduleTotAmount");
elm.text(StringUtils.defaultString(data.getRoofInfo().getModuleTotAmount()));
elm = doc.getElementById("moduleTotVolKw");
elm.text(StringUtils.defaultString(data.getRoofInfo().getModuleTotVolKw()));
}
if (data.getRoofInfo().getRoofList() != null) {
sb = new StringBuilder();
for (RoofResponse roofResponse : data.getRoofInfo().getRoofList()) {
sb.append("<tr>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getRoofSurface()) + "</td>");
sb.append("<td style='text-align:left;'>"
+ StringUtils.defaultString(roofResponse.getRoofMaterialName()) + "</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getSlope()) + "寸</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getConstructSpecificationName())
+ "</td>");
sb.append("<td style='text-align:left;'>"
+ StringUtils.defaultString(roofResponse.getSupportMethodName()) + "</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getSurfaceType()) + "</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getSetupHeight()) + "</td>");
sb.append("</tr>");
}
elm = doc.getElementById("surFaceList_detail2");
elm.before(sb.toString());
}
elm = doc.getElementById("objectNo5");
elm.text(StringUtils.defaultString(data.getObjectNo()) + " (Plan No : "
+ StringUtils.defaultString(data.getPlanNo()) + ")");
elm = doc.getElementById("objectName5");
elm.text(StringUtils.defaultString(data.getObjectName()) + " " + StringUtils.defaultString(data.getObjectNameOmit()));
elm = doc.getElementById("totVolKw5");
elm.text(StringUtils.defaultString(data.getTotVolKw()) + " Kw");
elm = doc.getElementById("certVolKw5");
elm.text(StringUtils.defaultString(data.getRoofInfo().getCertVolKw()) + " Kw");
elm = doc.getElementById("drawingEstimateCreateDate5");
elm.text(StringUtils.defaultString(data.getDrawingEstimateCreateDate()));
elm = doc.getElementById("prefName5");
elm.text(StringUtils.defaultString(data.getPrefName()));
elm = doc.getElementById("areaName5");
elm.text(StringUtils.defaultString(data.getAreaName()));
elm = doc.getElementById("snowfall5");
elm.text(StringUtils.defaultString(data.getSnowfall()) + " cm");
elm = doc.getElementById("standardWindSpeedName5");
elm.text(StringUtils.defaultString(data.getStandardWindSpeedName()));
// 도면(가대 이미지)
if (data.getDrawingImg2() != null) {
elm = doc.getElementById("drawingImg2");
String imgSrc2 = Base64.getEncoder().encodeToString(data.getDrawingImg2());
elm.html("<img src='data:image/png;base64," + imgSrc2 + "' width='100%'/>");
}
if (data.getRoofInfo().getCompasDegImg() != null) {
elm = doc.getElementById("degImg2");
String imgSrc2 = Base64.getEncoder().encodeToString(data.getRoofInfo().getCompasDegImg());
elm.html(
"<img src='data:image/png;base64,"
+ imgSrc2
+ "' width='50'/><div class=\"guide-img-tit\" >"+ StringUtils.defaultString(data.getRoofInfo().getCompasDeg()) + "°</div>");
}
no = 1;
sb = new StringBuilder();
for (ItemResponse itemResponse : list) {
if ("STAND_".equals(itemResponse.getItemGroup())) {
sb.append("<tr>");
sb.append("<td>" + (no++) + "</td>");
sb.append("<td style='text-align:left;'>"
+ StringUtils.defaultString(itemResponse.getItemNo()) + "</td>");
sb.append("<td style='text-align:right;'>"
+ StringUtils.defaultString(itemResponse.getAmount()) + "</td>");
sb.append("</tr>");
}
}
elm = doc.getElementById("standItemList_detail");
elm.append(sb.toString());
if (data.getRoofInfo().getRoofList() != null) {
sb = new StringBuilder();
for (RoofResponse roofResponse : data.getRoofInfo().getRoofList()) {
sb.append("<tr>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getRoofSurface()) + "</td>");
sb.append("<td style='text-align:left;'>"
+ StringUtils.defaultString(roofResponse.getRoofMaterialName()) + "</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getSlope()) + "寸</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getConstructSpecificationName())
+ "</td>");
sb.append("<td style='text-align:left;'>"
+ StringUtils.defaultString(roofResponse.getSupportMethodName()) + "</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getSurfaceType()) + "</td>");
sb.append("<td>" + StringUtils.defaultString(roofResponse.getSetupHeight()) + "</td>");
sb.append("</tr>");
}
elm = doc.getElementById("roofList_detail");
elm.before(sb.toString());
}
elm = doc.getElementById("objectNo6");
elm.text(StringUtils.defaultString(data.getObjectNo()) + " (Plan No : "
+ StringUtils.defaultString(data.getPlanNo()) + ")");
elm = doc.getElementById("objectName6");
elm.text(StringUtils.defaultString(data.getObjectName()));
elm = doc.getElementById("objectNameOmit6");
elm.text(StringUtils.defaultString(data.getObjectNameOmit()));
sb = new StringBuilder();
BigDecimal totGrossWt = BigDecimal.ZERO;
for (ItemResponse itemResponse : list) {
String amountStr = StringUtils.defaultString(itemResponse.getAmount());
String grossWtStr = StringUtils.defaultString(itemResponse.getGrossWt());
// 빈 문자열 체크
if (amountStr.isEmpty() || grossWtStr.isEmpty()) {
sb.append("<tr><td colspan=5></td></tr>");
} else {
BigDecimal amount = new BigDecimal(amountStr);
BigDecimal grossWt = new BigDecimal(grossWtStr);
// grossWt가 0보다 큰지 체크
if (grossWt.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal totalWeight = amount.multiply(grossWt);
totGrossWt = totGrossWt.add(totalWeight);
elm = doc.getElementById("totGrossWt");
elm.text(totGrossWt.toString());
sb.append("<tr>");
sb.append("<td style='width:120px;text-align:left;'>")
.append(StringUtils.defaultString(itemResponse.getItemName()))
.append("</td>");
sb.append("<td style='width:120px;'>")
.append(StringUtils.defaultString(itemResponse.getItemNo()))
.append("</td>");
sb.append("<td style='width:60px;text-align:right;'>").append(amountStr).append("</td>");
sb.append("<td style='width:60px;text-align:right;'>").append(totalWeight.toString()).append("</td>");
sb.append("<td style='width:60px;text-align:right;'>").append(grossWtStr).append("</td>");
sb.append("</tr>");
}
}
}
elm = doc.getElementById("weightList_detail");
elm.before(sb.toString());
return doc;
}
/**
* Plan 확정 정보 동기화
*
* @param planSyncList Plan 목록
* @return
* @throws Exception
*/
public int setPlanConfirmSyncSave(List<PlanSyncResponse> planSyncList) throws Exception {
int cnt = 0;
for (PlanSyncResponse planSyncData : planSyncList) {
// Plan 확정 처리
cnt += estimateMapper.updatePlanConfirmSync(planSyncData);
}
return cnt;
}
/**
* QSP Q.CAST 견적서 동기화 실패 목록
*
* @return EstimateSendRequest 견적서 실패 목록
* @throws Exception
*/
public EstimateSendRequest selectEstimateSyncFailList() throws Exception {
EstimateSendRequest estimateSendRequest = new EstimateSendRequest();
List<EstimateSendResponse> quoteList = new ArrayList<EstimateSendResponse>();
String docNo = "";
// 견적서 동기화 실패 목록 조회
List<EstimateSendResponse> estimateSendListResponse =
estimateMapper.selectEstimateApiFailList();
for (EstimateSendResponse estimateSendResponse : estimateSendListResponse) {
EstimateRequest estimateRequest = new EstimateRequest();
estimateRequest.setObjectNo(estimateSendResponse.getObjectNo());
estimateRequest.setPlanNo(estimateSendResponse.getPlanNo());
String constructSpecification =
estimateMapper.selectEstimateConstructSpecification(estimateRequest);
estimateSendResponse.setSaveType("3");
estimateSendResponse.setSyncFlg("0");
estimateSendResponse.setConstructSpecification(
!StringUtils.isEmpty(constructSpecification) ? constructSpecification : "");
estimateSendResponse.setDelFlg("1".equals(estimateSendResponse.getDelFlg()) ? "Y" : "N");
// 아이템 목록 조회
estimateRequest.setSchBomNotExist("1");
List<ItemResponse> estimateItemList = estimateMapper.selectEstimateItemList(estimateRequest);
estimateSendResponse.setItemList(estimateItemList);
// 첨부파일 목록 조회
FileRequest fileDeleteReq = new FileRequest();
fileDeleteReq.setObjectNo(estimateRequest.getObjectNo());
fileDeleteReq.setPlanNo(estimateRequest.getPlanNo());
fileDeleteReq.setCategory("10");
List<FileResponse> fileList = fileMapper.selectFileList(fileDeleteReq);
estimateSendResponse.setFileList(fileList);
quoteList.add(estimateSendResponse);
estimateSendRequest.setQuoteList(quoteList);
}
return estimateSendRequest;
}
/**
* 견적서 정보 QSP 동기화
*
* @param planSyncList Plan 목록
* @return
* @throws Exception
*/
public int setEstimateSyncSave(List<PlanSyncResponse> planSyncList) throws Exception {
int cnt = 0;
for (PlanSyncResponse planSyncData : planSyncList) {
EstimateRequest estimateRequest = new EstimateRequest();
estimateRequest.setObjectNo(planSyncData.getObjectNo());
estimateRequest.setPlanNo(planSyncData.getPlanNo());
estimateRequest.setDocNo(planSyncData.getDocNo());
estimateRequest.setSyncFlg(planSyncData.getSyncFlg());
estimateRequest.setUserId("system");
// 견적서 동기화 여부 처리
cnt += estimateMapper.updateEstimateApi(estimateRequest);
}
return cnt;
}
/**
* PC 회로 구성도 설정
*
* @param pcsItemList
* @param moduleList
* @return
*/
private List<ItemRequest> getPcsCircuitList(List<ItemRequest> pcsItemList,
List<ItemRequest> moduleList) {
if (pcsItemList != null && pcsItemList.size() > 0) {
for (ItemRequest itemRequest : moduleList) {
itemRequest
.setCircuit(itemRequest.getCircuit().replaceAll("\\(", "").replaceAll("\\)", ""));
}
if (pcsItemList.size() == 1) {
pcsItemList.get(0).setCircuitCfg(this.getPcsCircuitCtg(moduleList));
} else {
if (moduleList != null && moduleList.size() > 0) {
int j = 1;
for (ItemRequest data : pcsItemList) {
String val = String.valueOf(j);
List<ItemRequest> resultList = moduleList.stream()
.filter(t -> StringUtils.equals(val, t.getCircuit().split("-")[0]))
.collect(Collectors.toList());
data.setCircuitCfg(this.getPcsCircuitCtg(resultList));
j++;
}
}
}
}
return pcsItemList;
}
/**
* PC 회로구성도 조회
*
* @param circuitList
* @return
*/
private String getPcsCircuitCtg(List<ItemRequest> circuitList) {
String circuitCfg = "";
if (circuitList != null && circuitList.size() > 0) {
// ArrayList 생성 변환
ArrayList<String> list = new ArrayList<String>();
for (ItemRequest pcsSerItemReq : circuitList) {
list.add(pcsSerItemReq.getCircuit());
}
// ArrayList 회로 중복수 오름차순 정렬
Set<String> set = new HashSet<String>(list);
List<String> setList = new ArrayList<>(set);
Collections.sort(setList, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int first = Integer.parseInt(o1.split("-")[0]);
int second = Integer.parseInt(o2.split("-")[0]);
return second > first ? -1 : second < first ? 1 : 0; // 오름차순 정렬
}
});
for (String str : setList) {
if (!StringUtils.isEmpty(circuitCfg))
circuitCfg += ", ";
circuitCfg += Collections.frequency(list, str);
}
}
return circuitCfg;
}
public EstimateApiResponse selectAgencyCustList(PriceRequest priceRequest) throws Exception {
// Validation
if (StringUtils.isEmpty(priceRequest.getSapSalesStoreCd())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sap Sale Store Code"));
}
EstimateApiResponse response = null;
/* [1]. QSP API (url + param) Setting */
String url = QSP_API_URL + "/api/master/agencyCustList";
String apiUrl = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("sapSalesStoreCd", priceRequest.getSapSalesStoreCd()).build().toUriString();
/* [2]. QSP API CALL -> Response */
String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);
if (!"".equals(strResponse)) {
com.fasterxml.jackson.databind.ObjectMapper om =
new com.fasterxml.jackson.databind.ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
response = om.readValue(strResponse, EstimateApiResponse.class);
} else {
// [msg] No data
throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
}
return response;
}
/**
* 견적서 삭제 (복사이후 배치면 저장)
* @param estimateRequest
* @throws Exception
*/
public void deleteEstimate(EstimateRequest estimateRequest) throws Exception{
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"));
}
if (StringUtils.isEmpty(estimateRequest.getUserId())) {
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
try {
// T_PLAN
int cnt = estimateMapper.updateEstimateInit(estimateRequest);
// T_PLAN_INFO
int cnt2 = estimateMapper.updateEstimateInfoInit(estimateRequest);
// 견적서 모든 아이템 제거
int cnt3 = estimateMapper.deleteEstimateItemList(estimateRequest);
int cnt4 = estimateMapper.deleteEstimateInfoItemList(estimateRequest);
} catch (Exception e) {
log.error("Failed to delete estimate. Request: {}", estimateRequest, e);
throw e; // 예외를 재던지기하여 상위 계층에서도 예외를 처리할 수 있도록 함
}
}
/**
* 워크북에서 시트를 안전하게 제거하는 헬퍼 메소드
* 시트가 존재하지 않으면 무시함
*
* @param workbook 워크북
* @param sheetName 제거할 시트명
*/
private void safeRemoveSheet(Workbook workbook, String sheetName) {
int sheetIndex = workbook.getSheetIndex(sheetName);
if (sheetIndex >= 0) {
workbook.removeSheetAt(sheetIndex);
}
}
private byte[] loadDrawingImage(URL url) {
try {
URLConnection connection = url.openConnection();
if (connection instanceof HttpURLConnection) {
HttpURLConnection httpConnection = (HttpURLConnection) connection;
if (httpConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
}
try (InputStream imageInputStream = connection.getInputStream()) {
return Util.toByteArray(imageInputStream);
}
} catch (Exception e) {
log.warn("Failed to load drawing image. url={}", url, e);
return null;
}
}
}