Compare commits

...

11 Commits

16 changed files with 821 additions and 511 deletions

View File

@ -1,15 +1,15 @@
package com.interplug.qcast.biz.commCode;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.interplug.qcast.biz.commCode.dto.CodeReq;
import com.interplug.qcast.biz.commCode.dto.CodeRes;
import com.interplug.qcast.biz.commCode.dto.CommCodeRes;
import com.interplug.qcast.biz.commCode.dto.DetailCodeRequest;
import com.interplug.qcast.biz.commCode.dto.HeadCodeRequest;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@ -53,17 +53,11 @@ public class CommCodeService {
public List<CommCodeRes> selectQcastCommCode() {
List<CodeRes> result = commCodeMapper.selectQcastCommCode();
List<CommCodeRes> commCodeList = new ArrayList<>();
result.forEach(
cr -> {
commCodeList.add(
CommCodeRes.builder()
.clHeadCd(cr.getClHeadCd())
.clCode(cr.getClCode())
.clCodeNm(cr.getClCodeNm())
.clCodeJp(cr.getClCodeJp())
.clPriority(cr.getClPriority())
.build());
});
result.forEach(cr -> {
commCodeList.add(CommCodeRes.builder().clHeadCd(cr.getClHeadCd()).clCode(cr.getClCode())
.clCodeNm(cr.getClCodeNm()).clCodeJp(cr.getClCodeJp()).clPriority(cr.getClPriority())
.clRefChr1(cr.getClRefChr1()).clRefChr2(cr.getClRefChr2()).build());
});
return commCodeList;
}

View File

@ -11,4 +11,6 @@ public class CommCodeRes {
private String clCodeNm;
private String clCodeJp;
private Integer clPriority;
private String clRefChr1;
private String clRefChr2;
}

View File

@ -74,6 +74,9 @@ public class ItemRequest {
@Schema(description = "아이템 변경 여부")
private String itemChangeFlg;
@Schema(description = "대표 케이블 여부")
private String dispCableFlg;
@Schema(description = "PC 아이템 ID")
private String pcItemId;

View File

@ -68,6 +68,9 @@ public class ItemResponse {
@Schema(description = "아이템 변경 여부")
private String itemChangeFlg;
@Schema(description = "대표 케이블 여부")
private String dispCableFlg;
@Schema(description = "W")
private String pnowW;

View File

@ -1,6 +1,7 @@
package com.interplug.qcast.biz.master.dto.pcs.connoption;
import com.interplug.qcast.biz.master.dto.pcs.ApiPcsConnResponse;
import com.interplug.qcast.biz.master.dto.pcs.ApiPcsOptionResponse;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Getter;
@ -28,4 +29,7 @@ public class ApiPcsConnOptionPcsItemResponse {
@Schema(description = "연결함목록")
private List<ApiPcsConnResponse> connList;
@Schema(description = "옵션목록(모니터선택)")
private List<ApiPcsOptionResponse> optionList;
}

View File

@ -1,6 +1,7 @@
package com.interplug.qcast.biz.master.dto.pcs.voltagestepup;
import com.interplug.qcast.biz.master.dto.pcs.ApiPcsConnResponse;
import com.interplug.qcast.biz.master.dto.pcs.ApiPcsOptionResponse;
import com.interplug.qcast.biz.master.dto.pcs.ApiPcsSerQtyDto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
@ -32,4 +33,7 @@ public class ApiPcsVoltageStepUpPcsItemResponse {
@Schema(description = "연결함목록")
private List<ApiPcsConnResponse> connList;
@Schema(description = "옵션목록(모니터선택)")
private List<ApiPcsOptionResponse> optionList;
}

View File

@ -1,11 +1,28 @@
package com.interplug.qcast.biz.object;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.RandomStringUtils;
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.UriComponentsBuilder;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.interplug.qcast.biz.canvasStatus.CanvasStatusService;
import com.interplug.qcast.biz.canvasStatus.dto.CanvasStatus;
import com.interplug.qcast.biz.canvasStatus.dto.CanvasStatusCopyRequest;
import com.interplug.qcast.biz.estimate.EstimateMapper;
import com.interplug.qcast.biz.estimate.dto.*;
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.ItemRequest;
import com.interplug.qcast.biz.estimate.dto.ItemResponse;
import com.interplug.qcast.biz.object.dto.ObjectRequest;
import com.interplug.qcast.biz.object.dto.ObjectResponse;
import com.interplug.qcast.biz.object.dto.PlanReqRequest;
@ -21,18 +38,8 @@ import com.interplug.qcast.config.Exception.QcastException;
import com.interplug.qcast.config.message.Messages;
import com.interplug.qcast.util.InterfaceQsp;
import io.micrometer.common.util.StringUtils;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
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.UriComponentsBuilder;
@Slf4j
@Service
@ -40,7 +47,8 @@ import org.springframework.web.util.UriComponentsBuilder;
public class ObjectService {
private final InterfaceQsp interfaceQsp;
@Autowired Messages message;
@Autowired
Messages message;
@Value("${file.ini.root.path}")
private String baseDirPath;
@ -54,7 +62,8 @@ public class ObjectService {
private final StoreFavoriteService storeFavoriteService;
@Autowired private CanvasStatusService canvasStatusService;
@Autowired
private CanvasStatusService canvasStatusService;
/**
* 도도부현 목록 조회
@ -100,13 +109,11 @@ public class ObjectService {
throws Exception {
// Validation
if (StringUtils.isEmpty(saleStoreId)) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
if (StringUtils.isEmpty(userId)) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
@ -129,17 +136,15 @@ public class ObjectService {
* @return List<SaleStoreResponse> 하위 판매점 목록
* @throws Exception
*/
public List<SaleStoreResponse> selectSaleStoreList(
String saleStoreId, String firstFlg, String userId) throws Exception {
public List<SaleStoreResponse> selectSaleStoreList(String saleStoreId, String firstFlg,
String userId) throws Exception {
// Validation
if (StringUtils.isEmpty(saleStoreId)) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
if (StringUtils.isEmpty(userId)) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
@ -170,8 +175,7 @@ public class ObjectService {
*/
public List<ObjectResponse> selectObjectMainList(ObjectRequest objectRequest) throws Exception {
if (StringUtils.isEmpty(objectRequest.getSaleStoreId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
@ -187,8 +191,7 @@ public class ObjectService {
*/
public List<ObjectResponse> selectObjectList(ObjectRequest objectRequest) throws Exception {
if (StringUtils.isEmpty(objectRequest.getSaleStoreId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
@ -240,13 +243,11 @@ public class ObjectService {
if (!roofCheckDatas.contains(
arrOrgRoofMaterialIdMultis[i] + "_" + arrOrgConstructSpecificationMultis[i])) {
roofMaterialIdMultis +=
StringUtils.isEmpty(roofMaterialIdMultis)
? arrOrgRoofMaterialIdMultis[i]
StringUtils.isEmpty(roofMaterialIdMultis) ? arrOrgRoofMaterialIdMultis[i]
: splitStr + arrOrgRoofMaterialIdMultis[i];
constructSpecificationMultis +=
StringUtils.isEmpty(constructSpecificationMultis)
? arrOrgConstructSpecificationMultis[i]
: splitStr + arrOrgConstructSpecificationMultis[i];
constructSpecificationMultis += StringUtils.isEmpty(constructSpecificationMultis)
? arrOrgConstructSpecificationMultis[i]
: splitStr + arrOrgConstructSpecificationMultis[i];
}
roofCheckDatas +=
@ -297,18 +298,15 @@ public class ObjectService {
// Validation
if (StringUtils.isEmpty(objectRequest.getSaleStoreId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
if (StringUtils.isEmpty(objectRequest.getSaleStoreLevel())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store Level"));
}
if (StringUtils.isEmpty(objectRequest.getUserId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
@ -353,18 +351,12 @@ public class ObjectService {
// 디폴트 Plan 등록
/*
PlanRequest planRequest = new PlanRequest();
planRequest.setObjectNo(objectNo);
planRequest.setRoofKindId("0");
planRequest.setCharger(objectRequest.getReceiveUser());
planRequest.setStatus("1");
planRequest.setDelFlg("0");
planRequest.setNorthArrangement("0");
planRequest.setDiffRoofEnabled("0");
planRequest.setOrderFlg("0");
planRequest.setTempFlg("1");
planRequest.setUserId(objectRequest.getUserId());
result += objectMapper.insertPlan(planRequest);
* PlanRequest planRequest = new PlanRequest(); planRequest.setObjectNo(objectNo);
* planRequest.setRoofKindId("0"); planRequest.setCharger(objectRequest.getReceiveUser());
* planRequest.setStatus("1"); planRequest.setDelFlg("0"); planRequest.setNorthArrangement("0");
* planRequest.setDiffRoofEnabled("0"); planRequest.setOrderFlg("0");
* planRequest.setTempFlg("1"); planRequest.setUserId(objectRequest.getUserId()); result +=
* objectMapper.insertPlan(planRequest);
*/
// 설계의뢰번호 존재 물건번호 업데이트
@ -378,9 +370,8 @@ public class ObjectService {
planReqRequest.setPlanReqNo(objectRequest.getPlanReqNo());
planReqRequest.setObjectNo(objectRequest.getObjectNo());
String strResponse =
interfaceQsp.callApi(
HttpMethod.POST, QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
String strResponse = interfaceQsp.callApi(HttpMethod.POST,
QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
if (!"".equals(strResponse)) {
com.fasterxml.jackson.databind.ObjectMapper om =
new com.fasterxml.jackson.databind.ObjectMapper()
@ -389,8 +380,8 @@ public class ObjectService {
Map<String, Object> map = (Map<String, Object>) response.getResult();
if ("E".equals(String.valueOf(map.get("resultCode")))) {
throw new QcastException(
ErrorCode.INTERNAL_SERVER_ERROR, String.valueOf(map.get("resultMsg")));
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR,
String.valueOf(map.get("resultMsg")));
}
}
}
@ -414,18 +405,15 @@ public class ObjectService {
// Validation
if (StringUtils.isEmpty(objectRequest.getSaleStoreId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
if (StringUtils.isEmpty(objectRequest.getSaleStoreLevel())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store Level"));
}
if (StringUtils.isEmpty(objectRequest.getUserId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
@ -447,10 +435,8 @@ public class ObjectService {
objectRequest.setAddresseeCompanyName(
objectRequest.getObjectName() + ' ' + objectRequest.getObjectNameOmit());
objectRequest.setAddresseeCompanyNameOmit(objectRequest.getObjectNameOmit());
objectRequest.setContentsPath(
baseDirPath
+ "\\\\"
+ (tempChgFlg ? objectRequest.getNewObjectNo() : objectRequest.getObjectNo()));
objectRequest.setContentsPath(baseDirPath + "\\\\"
+ (tempChgFlg ? objectRequest.getNewObjectNo() : objectRequest.getObjectNo()));
result += objectMapper.updateObject(objectRequest);
result += objectMapper.updateObjectInfo(objectRequest);
@ -470,9 +456,8 @@ public class ObjectService {
planReqRequest.setPlanReqNo(objectRequest.getPlanReqNo());
planReqRequest.setObjectNo(objectRequest.getNewObjectNo());
String strResponse =
interfaceQsp.callApi(
HttpMethod.POST, QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
String strResponse = interfaceQsp.callApi(HttpMethod.POST,
QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
if (!"".equals(strResponse)) {
com.fasterxml.jackson.databind.ObjectMapper om =
new com.fasterxml.jackson.databind.ObjectMapper()
@ -481,8 +466,8 @@ public class ObjectService {
Map<String, Object> map = (Map<String, Object>) response.getResult();
if ("E".equals(String.valueOf(map.get("resultCode")))) {
throw new QcastException(
ErrorCode.INTERNAL_SERVER_ERROR, String.valueOf(map.get("resultMsg")));
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR,
String.valueOf(map.get("resultMsg")));
}
}
}
@ -490,9 +475,8 @@ public class ObjectService {
}
// 모든 변경 완료 재호출
objectResponse =
objectMapper.selectObjectDetail(
(tempChgFlg ? objectRequest.getNewObjectNo() : objectRequest.getObjectNo()));
objectResponse = objectMapper.selectObjectDetail(
(tempChgFlg ? objectRequest.getNewObjectNo() : objectRequest.getObjectNo()));
return objectResponse;
}
@ -505,13 +489,11 @@ public class ObjectService {
public void updateObjectLastEditDate(ObjectRequest objectRequest) throws Exception {
// Validation
if (StringUtils.isEmpty(objectRequest.getObjectNo())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Object No"));
}
if (StringUtils.isEmpty(objectRequest.getUserId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
@ -536,8 +518,7 @@ public class ObjectService {
// Validation
if (StringUtils.isEmpty(objectRequest.getObjectNo())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Object No"));
}
@ -556,9 +537,8 @@ public class ObjectService {
planReqRequest.setPlanReqNo(objectResponse.getPlanReqNo());
planReqRequest.setDelFlg("1");
String strResponse =
interfaceQsp.callApi(
HttpMethod.POST, QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
String strResponse = interfaceQsp.callApi(HttpMethod.POST,
QSP_API_URL + "/api/planReq/updateObjectNo", planReqRequest);
if (!"".equals(strResponse)) {
com.fasterxml.jackson.databind.ObjectMapper om =
new com.fasterxml.jackson.databind.ObjectMapper()
@ -567,8 +547,8 @@ public class ObjectService {
Map<String, Object> map = (Map<String, Object>) response.getResult();
if ("E".equals(String.valueOf(map.get("resultCode")))) {
throw new QcastException(
ErrorCode.INTERNAL_SERVER_ERROR, String.valueOf(map.get("resultMsg")));
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR,
String.valueOf(map.get("resultMsg")));
}
}
}
@ -594,27 +574,24 @@ public class ObjectService {
// Validation
if (StringUtils.isEmpty(planRequest.getObjectNo())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Object No"));
}
if (StringUtils.isEmpty(planRequest.getUserId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
if ("1".equals(planRequest.getCopyFlg()) && StringUtils.isEmpty(planRequest.getPlanNo())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Plan No"));
}
// Plan 추가 가능 체크
List<PlanResponse> planList = objectMapper.selectPlanList(planRequest);
if (planList.size() > 9) {
throw new QcastException(
ErrorCode.INTERNAL_SERVER_ERROR, message.getMessage("common.message.plan.save.limit"));
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR,
message.getMessage("common.message.plan.save.limit"));
}
try {
@ -639,10 +616,14 @@ public class ObjectService {
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);
}
@ -694,8 +675,8 @@ public class ObjectService {
for (ItemRequest itemRequest : itemList) {
itemRequest.setObjectNo(estimateCopyRequest.getCopyObjectNo());
itemRequest.setPlanNo(estimateCopyRequest.getCopyPlanNo());
itemRequest.setPartAdd(
!org.apache.commons.lang3.StringUtils.isEmpty(itemRequest.getPartAdd())
itemRequest
.setPartAdd(!org.apache.commons.lang3.StringUtils.isEmpty(itemRequest.getPartAdd())
? itemRequest.getPartAdd()
: "0");
itemRequest.setItemChangeFlg(
@ -773,26 +754,23 @@ public class ObjectService {
public void deletePlan(PlanRequest planRequest) throws Exception {
// Validation
if (StringUtils.isEmpty(planRequest.getObjectNo())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Object No"));
}
if (StringUtils.isEmpty(planRequest.getPlanNo())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Plan No"));
}
if (StringUtils.isEmpty(planRequest.getUserId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User ID"));
}
// Plan 삭제 가능 체크
List<PlanResponse> planList = objectMapper.selectPlanList(planRequest);
if (planList.size() < 2) {
throw new QcastException(
ErrorCode.INTERNAL_SERVER_ERROR, message.getMessage("common.message.plan.delete.limit"));
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR,
message.getMessage("common.message.plan.delete.limit"));
}
// Plan 삭제
@ -810,13 +788,11 @@ public class ObjectService {
// Validation
if (StringUtils.isEmpty(planReqRequest.getSaleStoreId())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store ID"));
}
if (StringUtils.isEmpty(planReqRequest.getSaleStoreLevel())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sale Store Level"));
}
@ -824,54 +800,37 @@ public class ObjectService {
/* [1]. QSP API (url + param) Setting */
String encodedSchPlanReqNo =
URLEncoder.encode(
StringUtils.isEmpty(planReqRequest.getSchPlanReqNo())
? ""
: planReqRequest.getSchPlanReqNo(),
StandardCharsets.UTF_8);
String encodedSchTitle =
URLEncoder.encode(
StringUtils.isEmpty(planReqRequest.getSchTitle()) ? "" : planReqRequest.getSchTitle(),
StandardCharsets.UTF_8);
String encodedSchAddress =
URLEncoder.encode(
StringUtils.isEmpty(planReqRequest.getSchAddress())
? ""
: planReqRequest.getSchAddress(),
StandardCharsets.UTF_8);
URLEncoder.encode(StringUtils.isEmpty(planReqRequest.getSchPlanReqNo()) ? ""
: planReqRequest.getSchPlanReqNo(), StandardCharsets.UTF_8);
String encodedSchTitle = URLEncoder.encode(
StringUtils.isEmpty(planReqRequest.getSchTitle()) ? "" : planReqRequest.getSchTitle(),
StandardCharsets.UTF_8);
String encodedSchAddress = URLEncoder.encode(
StringUtils.isEmpty(planReqRequest.getSchAddress()) ? "" : planReqRequest.getSchAddress(),
StandardCharsets.UTF_8);
String encodedSchSaleStoreName =
URLEncoder.encode(
StringUtils.isEmpty(planReqRequest.getSchSaleStoreName())
? ""
: planReqRequest.getSchSaleStoreName(),
StandardCharsets.UTF_8);
URLEncoder.encode(StringUtils.isEmpty(planReqRequest.getSchSaleStoreName()) ? ""
: planReqRequest.getSchSaleStoreName(), StandardCharsets.UTF_8);
String encodedSchPlanReqName =
URLEncoder.encode(
StringUtils.isEmpty(planReqRequest.getSchPlanReqName())
? ""
: planReqRequest.getSchPlanReqName(),
StandardCharsets.UTF_8);
URLEncoder.encode(StringUtils.isEmpty(planReqRequest.getSchPlanReqName()) ? ""
: planReqRequest.getSchPlanReqName(), StandardCharsets.UTF_8);
String url = QSP_API_URL + "/api/planReq/list";
String apiUrl =
UriComponentsBuilder.fromHttpUrl(url)
.queryParam("saleStoreId", planReqRequest.getSaleStoreId())
.queryParam("saleStoreLevel", planReqRequest.getSaleStoreLevel())
.queryParam("schPlanReqNo", encodedSchPlanReqNo)
.queryParam("schTitle", encodedSchTitle)
.queryParam("schAddress", encodedSchAddress)
.queryParam("schSaleStoreName", encodedSchSaleStoreName)
.queryParam("schPlanReqName", encodedSchPlanReqName)
.queryParam("schPlanStatCd", planReqRequest.getSchPlanStatCd())
.queryParam("schDateGbn", planReqRequest.getSchDateGbn())
.queryParam("schStartDt", planReqRequest.getSchStartDt())
.queryParam("schEndDt", planReqRequest.getSchEndDt())
.queryParam("startRow", planReqRequest.getStartRow())
.queryParam("endRow", planReqRequest.getEndRow())
.build()
.toUriString();
String apiUrl = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("saleStoreId", planReqRequest.getSaleStoreId())
.queryParam("saleStoreLevel", planReqRequest.getSaleStoreLevel())
.queryParam("schPlanReqNo", encodedSchPlanReqNo).queryParam("schTitle", encodedSchTitle)
.queryParam("schAddress", encodedSchAddress)
.queryParam("schSaleStoreName", encodedSchSaleStoreName)
.queryParam("schPlanReqName", encodedSchPlanReqName)
.queryParam("schPlanStatCd", planReqRequest.getSchPlanStatCd())
.queryParam("schDateGbn", planReqRequest.getSchDateGbn())
.queryParam("schStartDt", planReqRequest.getSchStartDt())
.queryParam("schEndDt", planReqRequest.getSchEndDt())
.queryParam("startRow", planReqRequest.getStartRow())
.queryParam("endRow", planReqRequest.getEndRow()).build().toUriString();
/* [2]. QSP API CALL -> Response */
String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);

View File

@ -1,17 +1,17 @@
package com.interplug.qcast.biz.pwrGnrSimulation;
import com.interplug.qcast.biz.estimate.dto.EstimateRequest;
import com.interplug.qcast.biz.pwrGnrSimulation.dto.PwrGnrSimGuideResponse;
import com.interplug.qcast.biz.pwrGnrSimulation.dto.PwrGnrSimRequest;
import com.interplug.qcast.biz.pwrGnrSimulation.dto.PwrGnrSimResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@ -36,4 +36,15 @@ public class PwrGnrSimController {
public PwrGnrSimGuideResponse selectPwrGnrSimulationGuideInfo() throws Exception {
return pwrGnrSimService.selectPwrGnrSimulationGuideInfo();
}
@Operation(description = "견적서를 엑셀로 다운로드한다.")
@PostMapping("/excel-download")
@ResponseStatus(HttpStatus.OK)
public void excelDownload(
HttpServletRequest request,
HttpServletResponse response,
@RequestBody EstimateRequest estimateRequest)
throws Exception {
pwrGnrSimService.excelDownload(request, response, estimateRequest);
}
}

View File

@ -2,23 +2,28 @@ package com.interplug.qcast.biz.pwrGnrSimulation;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.interplug.qcast.biz.estimate.dto.*;
import com.interplug.qcast.biz.pwrGnrSimulation.dto.*;
import com.interplug.qcast.config.Exception.ErrorCode;
import com.interplug.qcast.config.Exception.QcastException;
import com.interplug.qcast.config.message.Messages;
import com.interplug.qcast.util.ExcelUtil;
import com.interplug.qcast.util.InterfaceQsp;
import com.interplug.qcast.util.PdfUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
@ -29,6 +34,8 @@ import org.springframework.stereotype.Service;
public class PwrGnrSimService {
private final InterfaceQsp interfaceQsp;
@Autowired Messages message;
@Value("${qsp.url}")
private String qspUrl;
@ -71,19 +78,19 @@ public class PwrGnrSimService {
// 태양 적위
double[] taiyousekii = readValuesFromFile("template/pwrGnrSimulation/taiyousekii.txt");
static double[][] peakcut_by_pcs_data =
double[][] peakcut_by_pcs_data =
readValuesFromFile2("template/pwrGnrSimulation/peakcut_by_pcs_data.txt");
static double[][] tashounen_data_deg0 =
double[][] tashounen_data_deg0 =
readValuesFromFile2("template/pwrGnrSimulation/tashounen_data_deg0.txt");
static double[][] tashounen_data_deg90 =
double[][] tashounen_data_deg90 =
readValuesFromFile2("template/pwrGnrSimulation/tashounen_data_deg90.txt");
static double[][] amp_peakcut_data_deg0 =
double[][] amp_peakcut_data_deg0 =
readValuesFromFile2("template/pwrGnrSimulation/amp_peakcut_data_deg0.txt");
static double[][] amp_peakcut_data_deg90 =
double[][] amp_peakcut_data_deg90 =
readValuesFromFile2("template/pwrGnrSimulation/amp_peakcut_data_deg90.txt");
/**
@ -508,7 +515,7 @@ public class PwrGnrSimService {
}
// 배열 변환 포맷 처리 메서드
private static String[] formatAndPrintArray(double[] doubleArray) {
private String[] formatAndPrintArray(double[] doubleArray) {
return Arrays.stream(doubleArray)
.mapToInt(d -> (int) d) // double -> int 변환
.mapToObj(i -> String.format("%,d", i))
@ -516,7 +523,7 @@ public class PwrGnrSimService {
}
// 설치면의 사면 일사량 계산
public static double[] peakcut(
public double[] peakcut(
int simulationPointNumber,
double koubai,
double houi,
@ -613,7 +620,7 @@ public class PwrGnrSimService {
}
/** 0도 방위 전력 피크 컷을 계산하는 방법 */
private static double computePowerPeakCutDeg0(
private double computePowerPeakCutDeg0(
int simulationPointNumber, double sekisairitsu, double koubai) {
// 0度近似曲線係数
double[] x = {1, 5, 15, 20, 30, 40};
@ -708,7 +715,7 @@ public class PwrGnrSimService {
}
/** 전류 피크 컷(5차) 90도 근사 곡선 계수 */
private static double computeAmpPeakCutDeg90(
private double computeAmpPeakCutDeg90(
int simulationPointNumber, double koubai, double amp_delta) {
// 초기 설정
@ -809,8 +816,7 @@ public class PwrGnrSimService {
}
/** 전류 피크 컷(5차) 0도 근사 곡선 계수 */
private static double computeAmpPeakCutDeg0(
int simulationPointNumber, double koubai, double amp_delta) {
private double computeAmpPeakCutDeg0(int simulationPointNumber, double koubai, double amp_delta) {
double[] x = {5, 15, 20, 30, 40, 50};
double[] z2 = new double[6];
@ -900,7 +906,7 @@ public class PwrGnrSimService {
}
/** 0도 방위 전력 피크 컷을 계산하는 방법 */
private static double computePowerPeakCutDeg90(
private double computePowerPeakCutDeg90(
int simulationPointNumber, double sekisairitsu, double koubai) {
// 데이터 초기화
double[] x = {1, 5, 15, 20, 30, 40};
@ -1187,7 +1193,7 @@ public class PwrGnrSimService {
return shamenNissha;
}
public static double[] readValuesFromFile(String fileName) {
public double[] readValuesFromFile(String fileName) {
List<Double> values = new ArrayList<>();
try (InputStream inputStream =
@ -1210,7 +1216,7 @@ public class PwrGnrSimService {
return values.stream().mapToDouble(Double::doubleValue).toArray();
}
public static String[][] readValuesFromFileString2(String fileName) {
public String[][] readValuesFromFileString2(String fileName) {
List<String[]> values = new ArrayList<>();
StringBuilder sb = new StringBuilder();
@ -1248,7 +1254,7 @@ public class PwrGnrSimService {
return values.toArray(new String[0][]);
}
public static double[][] readValuesFromFile2(String fileName) {
public double[][] readValuesFromFile2(String fileName) {
List<double[]> values = new ArrayList<>();
StringBuilder sb = new StringBuilder();
@ -1306,7 +1312,7 @@ public class PwrGnrSimService {
return guideResponse;
}
public static Document pwrGnrSimPdfHtml(Document doc, PwrGnrSimResponse data)
public Document pwrGnrSimPdfHtml(Document doc, PwrGnrSimResponse data)
throws IOException, QcastException {
String[] pwrGnrSimList = data.getFrcPwrGnrList();
@ -1478,10 +1484,111 @@ public class PwrGnrSimService {
return doc;
}
public static int roundUpAuto(double value) {
public int roundUpAuto(double value) {
int length = (int) Math.log10(value) + 1; // 숫자의 자리수를 계산
int place = (int) Math.pow(10, length - 1); // 자리수에 따른 올림 기준(10, 100, 1000 )
return (int) Math.ceil(value / place) * place;
}
public void excelDownload(
HttpServletRequest request, HttpServletResponse response, EstimateRequest estimateRequest)
throws Exception {
// Validation
if (StringUtils.isEmpty(estimateRequest.getObjectNo())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Object No"));
}
if (StringUtils.isEmpty(estimateRequest.getPlanNo())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Plan No"));
}
try {
EstimateResponse estimateResponse = new EstimateResponse();
estimateResponse.setObjectNo(estimateRequest.getObjectNo());
estimateResponse.setPlanNo(estimateRequest.getPlanNo());
// file Name 명이 없는경우
if (estimateRequest.getFileName() == null || "".equals(estimateRequest.getFileName())) {
estimateRequest.setFileName(
estimateResponse.getObjectNo()
+ "_"
+ new SimpleDateFormat("yyyyMMdd").format(new Date()));
}
// 발전시뮬레이션 계산
PwrGnrSimRequest pwrGnrSimRequest = new PwrGnrSimRequest();
pwrGnrSimRequest.setObjectNo(estimateResponse.getObjectNo());
pwrGnrSimRequest.setPlanNo(estimateResponse.getPlanNo());
PwrGnrSimResponse pwrGnrSimResponse = this.selectPwrGnrSimulation(pwrGnrSimRequest);
pwrGnrSimResponse.setPwrGnrSimType(estimateRequest.getPwrGnrSimType());
// 발전시뮬레이션 타입에 따른 list 셋팅
if ("A".equals(estimateRequest.getPwrGnrSimType())) {
pwrGnrSimResponse.setFrcPwrGnrList(pwrGnrSimResponse.getHatsudenryouAll());
} else if ("B".equals(estimateRequest.getPwrGnrSimType())) {
pwrGnrSimResponse.setFrcPwrGnrList(pwrGnrSimResponse.getHatsudenryouAllSnow());
} else if ("C".equals(estimateRequest.getPwrGnrSimType())) {
pwrGnrSimResponse.setFrcPwrGnrList(pwrGnrSimResponse.getHatsudenryouPeakcutAll());
} else if ("D".equals(estimateRequest.getPwrGnrSimType())) {
pwrGnrSimResponse.setFrcPwrGnrList(pwrGnrSimResponse.getHatsudenryouPeakcutAllSnow());
}
pwrGnrSimResponse.setIntFrcPwrGnrList(
Arrays.stream(pwrGnrSimResponse.getFrcPwrGnrList())
.map(s -> s.replace(",", "")) // , 제거
.mapToInt(Integer::parseInt) // 문자열을 int로 변환
.toArray());
if (pwrGnrSimResponse != null) {
try {
// 발전시뮬레이션 안내사항 조회
PwrGnrSimGuideResponse pwrGnrSimGuideInfo = this.selectPwrGnrSimulationGuideInfo();
if (pwrGnrSimGuideInfo != null) {
pwrGnrSimResponse.setGuideInfo(pwrGnrSimGuideInfo.getData());
}
} catch (Exception e) {
}
}
estimateResponse.setPwrGnrSim(pwrGnrSimResponse);
if ("PDF".equals(estimateRequest.getSchDownload())) { // PDF 다운로드
String[] arrSection = {"div.section3"};
String templateFilePath = "pdf_download_simulation_detail_template.html";
// 템플릿 html 조회
Document doc = PdfUtil.getPdfDoc(request, templateFilePath);
// 발전시뮬레이션 pdf Html 생성
doc = this.pwrGnrSimPdfHtml(doc, pwrGnrSimResponse);
// pdf 다운로드
PdfUtil.pdfDownload(request, response, doc, estimateRequest.getFileName(), null, true);
} else {
String excelTemplateName = "excel_download_simulation_detail_template.xlsx";
ExcelUtil excelUtil = new ExcelUtil();
excelUtil.download(
request,
response,
excelUtil.convertVoToMap(estimateResponse),
null,
estimateRequest.getFileName(),
excelTemplateName);
}
} catch (Exception e) {
e.printStackTrace();
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR);
}
}
}

View File

@ -3,6 +3,7 @@ package com.interplug.qcast.util;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
@ -60,6 +61,7 @@ public class PdfUtil {
* @param doc
* @param pdfFileName 파일명
* @param arrSection 노출 Section
* @param isLandscape 가로/세로 설정
* @throws IOException
*/
public static void pdfDownload(
@ -67,9 +69,13 @@ public class PdfUtil {
HttpServletResponse response,
Document doc,
String pdfFileName,
String[] arrSection)
String[] arrSection,
boolean isLandscape)
throws IOException {
// 가로 세로 설정
PageSize pageSize = isLandscape ? PageSize.A4.rotate() : PageSize.A4;
// 응답에 PDF 설정
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"" + pdfFileName + "\".pdf");
@ -79,6 +85,8 @@ public class PdfUtil {
PdfWriter writer = new PdfWriter(os);
PdfDocument pdfDoc = new PdfDocument(writer)) {
pdfDoc.setDefaultPageSize(pageSize);
// 폰트 설정
ConverterProperties properties = new ConverterProperties();
String fontPath = "template/pdf/BIZUDPGothic-Regular.ttf";
@ -88,7 +96,9 @@ public class PdfUtil {
if (arrSection == null || arrSection.length == 0) {
// HTML 전체를 pdfDoc에 직접 변환
HtmlConverter.convertToPdf(
new ByteArrayInputStream(doc.html().getBytes(StandardCharsets.UTF_8)), os, properties);
new ByteArrayInputStream(doc.html().getBytes(StandardCharsets.UTF_8)),
pdfDoc,
properties);
os.flush();
} else {
// arrSection이 있는 경우 섹션을 개별적으로 변환 병합
@ -108,6 +118,8 @@ public class PdfUtil {
PdfWriter tempWriter = new PdfWriter(tempOutputStream);
PdfDocument tempPdfDoc = new PdfDocument(tempWriter)) {
tempPdfDoc.setDefaultPageSize(pageSize);
HtmlConverter.convertToPdf(
new ByteArrayInputStream(sectionHtml.getBytes(StandardCharsets.UTF_8)),
tempPdfDoc,
@ -161,4 +173,15 @@ public class PdfUtil {
}
return fontProvider;
}
public static void pdfDownload(
HttpServletRequest request,
HttpServletResponse response,
Document doc,
String pdfFileName,
String[] arrSection)
throws IOException {
pdfDownload(request, response, doc, pdfFileName, arrSection, false); // 기본값은 세로
}
}

View File

@ -159,6 +159,8 @@
, CL.CODE_NM AS CL_CODE_NM
, CL.CODE_JP AS CL_CODE_JP
, CL.PRIORITY AS CL_PRIORITY
, CL.REF_CHR1 AS CL_REF_CHR1
, CL.REF_CHR2 AS CL_REF_CHR2
FROM
M_COMM_H (NOLOCK) CH
INNER JOIN

View File

@ -150,13 +150,16 @@
WHEN MI.ITEM_GROUP = 'PC_' AND MI.POWER_COM_FLG = '0' THEN 'STORAGE_BATTERY'
ELSE MI.ITEM_GROUP END AS ITEM_GROUP
, MI.MODULE_FLG
, MI.PKG_MATERIAL_FLG
, MI.FILE_UPLOAD_FLG
, MI.ITEM_CTG_GR
, MII.PKG_MATERIAL_FLG
, MII.FILE_UPLOAD_FLG
, MII.ITEM_CTG_GR
, '0' AS SALE_PRICE
, '0' AS OPEN_FLG
FROM M_PACKAGE_ITEM PI WITH (NOLOCK)
INNER JOIN M_ITEM MI WITH (NOLOCK)
ON PI.ITEM_ID = MI.ITEM_ID
LEFT OUTER JOIN M_ITEM_INFO MII
ON MI.ITEM_ID = MII.ITEM_ID
WHERE PI.PACKAGE_ITEM_ID = #{itemId}
AND MI.DEL_FLG = 0
</select>

View File

@ -269,6 +269,7 @@
, PEI.FILE_UPLOAD_FLG
, PEI.OPEN_FLG
, PEI.ITEM_CHANGE_FLG
, PEI.DISP_CABLE_FLG
, I.PNOW_W
, CASE WHEN I.POWER_COM_FLG = '1' THEN 'PC_'
WHEN I.ITEM_GROUP = 'PC_' AND I.POWER_COM_FLG = '0' THEN 'STORAGE_BATTERY'
@ -821,6 +822,7 @@
, FILE_UPLOAD_FLG
, OPEN_FLG
, ITEM_CHANGE_FLG
, DISP_CABLE_FLG
) VALUES (
#{objectNo}
, #{planNo}
@ -838,6 +840,7 @@
, #{fileUploadFlg}
, #{openFlg}
, #{itemChangeFlg}
, #{dispCableFlg}
)
</insert>

View File

@ -0,0 +1,288 @@
<!doctype html>
<html lang="ja">
<head>
<style>
@media print {
body {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
}
table {
width: 100%;
table-layout: fixed;
font-family: M-Gothic;
font-size: 11px;
border-collapse: collapse;
margin: 0 auto;
line-height: 150%;
color: #333
}
.month-table td {
word-break: break-all;
}
th, td {
padding: 5px 5px 3px;
text-align: center;
font-size: 8px;
border: 1px solid #000
}
th {
background-color: #eee;
font-weight: bold
}
td {
background-color: white
}
.col-20 {
width: 20%
}
.col-15 {
width: 15%
}
.col-10 {
width: 10%
}
.col-13 {
width: 13%
}
body {
max-width: 1040px;
margin: 0 auto
}
.mb20 {
margin-bottom: 20px
}
/* 가이드박스 */
.guide-box {
border: 1px solid #000;
padding: 15px;
}
.guide-content {
white-space: pre-line;
line-height: 1.4;
font-size: 12px;
margin: 0;
}
/* 차트퍼블 */
.chart-wrapper {
width: 100%;
table-layout: fixed;
margin: 20px 0;
height: 324.3px;
}
.chart-wrapper td {
padding: 0;
border: none
}
.chart-wrapper td.y-axis-wrap {
vertical-align: bottom
}
.y-axis {
margin-top: -5px
}
.y-axis td {
font-size: 12px;
line-height: 1;
vertical-align: bottom;
padding: 12.3px 0
}
.y-axis td.zero {
padding-bottom: 0
}
.y-axis td.top {
padding-top: 0
}
.chart-wrapper td.bar-cell {
position: relative;
vertical-align: bottom;
border-bottom: 1px solid #ddd;
background-color: transparent
}
.chart-wrapper td.bar-cell .bar {
position: absolute;
bottom: 0;
left: 13.4px;
width: 18px;
margin: 0 auto
}
.chart-wrapper td.month-cell {
font-size: 11px;
padding-top: 7px
}
.chart-line td {
background-color: transparent;
padding: 18.2px 0;
border-bottom: 1px solid #ddd !important
}
.chart-line td.top {
padding: 1px
}
.chart-wrap {
overflow: hidden;
}
.left-side {
margin-right: 20px;
width: 570px;
float: left;
}
.right-side {
width: 430px;
float: right;
}
.tit {
font-size: 14px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="section3">
<table class="mb20">
<tbody>
<tr>
<th class="col-10">物件番号</th>
<td id="objectNo"></td>
<th class="col-10">作成日</th>
<td class="col-13" id="drawingEstimateCreateDate"></td>
<th class="col-10">都道府県</th>
<td class="col-13" id="prefName"></td>
<th class="col-10">日射量観測地点</th>
<td class="col-13" id="areaName"></td>
</tr>
<tr>
<th class="col-10">システム容量</th>
<td id="capacity"></td>
<th class="col-10">年間予測発電量</th>
<td id="anlFrcsGnrt"></td>
<th class="col-10">積雪条件</th>
<td id="snowfall"></td>
<th class="col-10">風速条件</th>
<td id="standardWindSpeedId"></td>
</tr>
</tbody>
</table>
<div class="chart-wrap">
<div class="left-side">
<div id="pwrGnrChartImg">
<table class="chart-wrapper">
<tbody>
<tr id="htmlX">
<td class="y-axis-wrap">
<table class="y-axis">
<tbody id="htmlY">
</tbody>
</table>
</td>
</tr>
<tr>
<td class="month-cell"></td>
<td class="month-cell">1月</td>
<td class="month-cell">2月</td>
<td class="month-cell">3月</td>
<td class="month-cell">4月</td>
<td class="month-cell">5月</td>
<td class="month-cell">6月</td>
<td class="month-cell">7月</td>
<td class="month-cell">8月</td>
<td class="month-cell">9月</td>
<td class="month-cell">10月</td>
<td class="month-cell">11月</td>
<td class="month-cell">12月</td>
</tr>
</tbody>
</table>
</div>
<div class="tit">
● 予測発電量kWh
</div>
<table class="mb20 month-table">
<thead>
<tr>
<th>1月</th>
<th>2月</th>
<th>3月</th>
<th>4月</th>
<th>5月</th>
<th>6月</th>
<th>7月</th>
<th>8月</th>
<th>9月</th>
<th>10月</th>
<th>11月</th>
<th>12月</th>
<th>合計</th>
</tr>
</thead>
<tbody>
<tr id="frcPwrGnrList_detail">
</tr>
</tbody>
</table>
</div>
<div class="right-side">
<table class="mb20">
<thead>
<tr>
<th class="col-15">屋根面</th>
<th class="col-15">傾斜角度</th>
<th class="col-15">方位角(度)</th>
<th>太陽電池モジュール</th>
<th class="col-15">枚数(枚)</th>
</tr>
</thead>
<tbody id="roofModuleList_detail">
</tbody>
</table>
<table class="mb20">
<thead>
<tr>
<th>パワーコンディショナー</th>
<th class="col-20"></th>
</tr>
</thead>
<tbody id="pcsList_detail">
</tbody>
</table>
</div>
</div>
<div class="tit">
● Hanwha Japan 年間発電量シミュレーション案内事項
</div>
<div class="guide-box">
<pre class="guide-content" id="guideInfo"></pre>
</div>
</div>
</body>
</html>