package com.interplug.qcast.biz.object; import com.fasterxml.jackson.databind.DeserializationFeature; import com.interplug.qcast.biz.object.dto.ObjectRequest; import com.interplug.qcast.biz.object.dto.ObjectResponse; import com.interplug.qcast.biz.object.dto.PlanReqRequest; import com.interplug.qcast.biz.object.dto.PlanReqResponse; import com.interplug.qcast.biz.object.dto.PlanRequest; import com.interplug.qcast.biz.object.dto.PlanResponse; import com.interplug.qcast.biz.object.dto.PrefResponse; import com.interplug.qcast.biz.object.dto.SaleStoreResponse; import com.interplug.qcast.biz.object.dto.UploadRequest; import com.interplug.qcast.biz.object.dto.UploadResponse; import com.interplug.qcast.biz.object.dto.WindSpeedResponse; import com.interplug.qcast.biz.storeFavorite.StoreFavoriteService; import com.interplug.qcast.biz.storeFavorite.dto.StoreFavoriteRequest; import com.interplug.qcast.biz.storeFavorite.dto.StoreFavoriteResponse; import com.interplug.qcast.config.Exception.ErrorCode; import com.interplug.qcast.config.Exception.QcastException; import com.interplug.qcast.config.message.Messages; import com.interplug.qcast.util.InterfaceQsp; import io.micrometer.common.util.StringUtils; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URLConnection; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Comparator; import java.util.List; import java.util.Map; 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.util.FileCopyUtils; import org.springframework.web.util.UriComponentsBuilder; @Slf4j @Service @RequiredArgsConstructor public class ObjectService { private final InterfaceQsp interfaceQsp; @Autowired Messages message; @Value("${file.ini.root.path}") private String baseDirPath; @Value("${qsp.url}") private String QSP_API_URL; private final ObjectMapper objectMapper; private final StoreFavoriteService storeFavoriteService; public List selectPrefList() throws Exception { return objectMapper.selectPrefList(); } public List selectPrefAreaList(String prefId) throws Exception { return objectMapper.selectPrefAreaList(prefId); } public List selectWindSpeedList(String city) throws Exception { return objectMapper.selectWindSpeedList(city); } public List selectFirstSaleStoreList(String saleStoreId, String userId) throws Exception { // [0]. 판매점 목록 조회 List storeList = new ArrayList(); if ("T01".equals(saleStoreId)) { storeList = objectMapper.selectSaleStoreFirstList(); // [1]. 판매점 목록 조회 결과 if (storeList.size() > 0) { StoreFavoriteRequest storeFavoriteReq = new StoreFavoriteRequest(); storeFavoriteReq.setUserId(userId); // [2]. 사용자 판매점 즐겨찾기 목록 조회 (QSP -> QCAST) StoreFavoriteResponse storeFavoriteRes = new StoreFavoriteResponse(); storeFavoriteRes = storeFavoriteService.getStoreFavoriteList(storeFavoriteReq); List> data = (List>) storeFavoriteRes.getData(); Map result = (Map) storeFavoriteRes.getResult(); // [3]. 판매점 목록 중, 즐겨찾기 판매점에 해당하는 경우 정렬 기준 셋팅 if ("S".equals(result.get("resultCode"))) { if (data.size() > 0) { for (SaleStoreResponse saleStore : storeList) { String storeId = saleStore.getSaleStoreId(); saleStore.setPriority("B"); for (Map storeFavorite : data) { String favStoreId = (String) storeFavorite.get("storeId"); if (storeId.equals(favStoreId)) { saleStore.setPriority("A" + (String) storeFavorite.get("priority")); break; } } } // [4]. 정렬 기준 sort (오름차순) storeList.sort(Comparator.comparing(SaleStoreResponse::getPriority)); } } else { throw new QcastException( ErrorCode.INTERNAL_SERVER_ERROR, (String) result.get("resultMsg")); } } } return storeList; } public List selectSaleStoreList(String saleStoreId, String firstFlg) throws Exception { // [0]. 판매점 목록 조회 List storeList = new ArrayList(); storeList = objectMapper.selectSaleStoreList(saleStoreId, firstFlg); return storeList; } public SaleStoreResponse selectSaleStoreInfo(String saleStoreId) throws Exception { return objectMapper.selectSaleStoreInfo(saleStoreId); } public List selectObjectList(ObjectRequest objectRequest) throws Exception { return objectMapper.selectObjectList(objectRequest); } public ObjectResponse selectObjectDetail(String objectNo) throws Exception { // object 상세 정보 조회 ObjectResponse objectResponse = objectMapper.selectObjectDetail(objectNo); if (objectResponse != null) { // Plan 목록 조회 PlanRequest planRequest = new PlanRequest(); planRequest.setObjectNo(objectNo); List planList = objectMapper.selectPlanList(planRequest); objectResponse.setPlanList(planList); } return objectResponse; } public ObjectResponse insertObject(ObjectRequest objectRequest) throws Exception { int result = 0; String objectNo = ""; // Validation if (StringUtils.isEmpty(objectRequest.getSaleStoreId())) { 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, message.getMessage("common.message.required.data", "Sale Store Level")); } // 물건번호 등록/조회 if ("0".equals(objectRequest.getTempFlg())) { objectRequest.setDelFlg("0"); objectRequest.setTempFlg("0"); objectRequest.setTempDelFlg("0"); result += objectMapper.insertObjectNo(objectRequest); objectNo = objectMapper.selectObjectNo(objectRequest); } else if ("1".equals(objectRequest.getTempFlg())) { objectRequest.setDelFlg("1"); objectRequest.setTempFlg("1"); objectRequest.setTempDelFlg("0"); // 임시저장인 경우 임시 물건번호 생성 yyyymmddhh24missSSS_랜덤문자 3개 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); Calendar dateTime = Calendar.getInstance(); objectNo = sdf.format(dateTime.getTime()); objectNo = "T" + objectNo.substring(2) + RandomStringUtils.randomAlphanumeric(3); objectNo = objectNo.toUpperCase(); } objectRequest.setObjectNo(objectNo); // 물건정보 등록 objectRequest.setAddress( objectRequest.getPrefName() + ((!StringUtils.isEmpty(objectRequest.getAddress())) ? objectRequest.getAddress() : "")); objectRequest.setAddresseeCompanyName( objectRequest.getObjectName() + ' ' + objectRequest.getObjectNameOmit()); objectRequest.setAddresseeCompanyNameOmit(objectRequest.getObjectNameOmit()); objectRequest.setContentsPath(baseDirPath + "\\\\" + objectRequest.getObjectNo()); result += objectMapper.insertObject(objectRequest); result += objectMapper.updateObjectDelivery(objectRequest); // 디폴트 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.setUserId(objectRequest.getUserId()); result += objectMapper.insertPlan(planRequest); // 플랜번호 존재 시 물건번호 업데이트 if ("0".equals(objectRequest.getTempFlg()) && !StringUtils.isEmpty(objectRequest.getPlanReqNo())) { PlanReqResponse response = null; PlanReqRequest planReqRequest = new PlanReqRequest(); planReqRequest.setSaleStoreId(objectRequest.getSaleStoreId()); planReqRequest.setSaleStoreLevel(objectRequest.getSaleStoreLevel()); planReqRequest.setPlanReqNo(objectRequest.getPlanReqNo()); planReqRequest.setObjectNo(objectRequest.getObjectNo()); 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() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); response = om.readValue(strResponse, PlanReqResponse.class); Map map = (Map) response.getResult(); if ("E".equals(String.valueOf(map.get("resultCode")))) { throw new QcastException( ErrorCode.INTERNAL_SERVER_ERROR, String.valueOf(map.get("resultMsg"))); } } } // 결과 데이터 리턴 ObjectResponse objectResponse = new ObjectResponse(); objectResponse.setObjectNo(objectNo); objectResponse.setPlanNo(planRequest.getPlanNo()); return objectResponse; } public ObjectResponse updateObject(ObjectRequest objectRequest) throws Exception { int result = 0; boolean tempChgFlg = false; // Validation if (StringUtils.isEmpty(objectRequest.getSaleStoreId())) { 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, message.getMessage("common.message.required.data", "Sale Store Level")); } // object 상세 정보 조회 ObjectResponse objectResponse = objectMapper.selectObjectDetail(objectRequest.getObjectNo()); if (objectResponse != null) { // 임시저장에서 저장상태 바뀌었는지 확인 if ("1".equals(objectResponse.getTempFlg()) && "0".equals(objectRequest.getTempFlg())) { tempChgFlg = true; result += objectMapper.insertObjectNo(objectRequest); objectRequest.setNewObjectNo(objectMapper.selectObjectNo(objectRequest)); } // 물건정보 수정 objectRequest.setAddress( objectRequest.getPrefName() + ((!StringUtils.isEmpty(objectRequest.getAddress())) ? objectRequest.getAddress() : "")); objectRequest.setAddresseeCompanyName( objectRequest.getObjectName() + ' ' + objectRequest.getObjectNameOmit()); objectRequest.setAddresseeCompanyNameOmit(objectRequest.getObjectNameOmit()); objectRequest.setContentsPath( baseDirPath + "\\\\" + (tempChgFlg ? objectRequest.getNewObjectNo() : objectRequest.getObjectNo())); result += objectMapper.updateObject(objectRequest); // 임시저장에서 저장상태로 돌리기 if (tempChgFlg) { objectMapper.updateObjectNoChange(objectRequest); objectMapper.updatePlanObjectNoChange(objectRequest); // 플랜번호 존재 시 물건번호 업데이트 if (!StringUtils.isEmpty(objectRequest.getPlanReqNo())) { PlanReqResponse response = null; PlanReqRequest planReqRequest = new PlanReqRequest(); planReqRequest.setSaleStoreId(objectRequest.getSaleStoreId()); planReqRequest.setSaleStoreLevel(objectRequest.getSaleStoreLevel()); planReqRequest.setPlanReqNo(objectRequest.getPlanReqNo()); planReqRequest.setObjectNo(objectRequest.getNewObjectNo()); 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() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); response = om.readValue(strResponse, PlanReqResponse.class); Map map = (Map) response.getResult(); if ("E".equals(String.valueOf(map.get("resultCode")))) { throw new QcastException( ErrorCode.INTERNAL_SERVER_ERROR, String.valueOf(map.get("resultMsg"))); } } } } } // 모든 변경 완료 후 재호출 objectResponse = objectMapper.selectObjectDetail( (tempChgFlg ? objectRequest.getNewObjectNo() : objectRequest.getObjectNo())); return objectResponse; } public int deleteObject(ObjectRequest objectRequest) throws Exception { int result = 0; // Validation if (StringUtils.isEmpty(objectRequest.getObjectNo())) { throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Object No")); } // 물건정보 삭제 result = objectMapper.deleteObject(objectRequest); return result; } public String insertPlan(PlanRequest planRequest) throws Exception { // Validation if (StringUtils.isEmpty(planRequest.getObjectNo())) { throw new QcastException( ErrorCode.INVALID_INPUT_VALUE, message.getMessage("common.message.required.data", "Object No")); } // 추가 Plan 등록 planRequest.setRoofKindId("0"); planRequest.setStatus("1"); planRequest.setDelFlg("0"); planRequest.setNorthArrangement("0"); planRequest.setDiffRoofEnabled("0"); planRequest.setOrderFlg("0"); objectMapper.insertPlan(planRequest); return planRequest.getPlanNo(); } public void deletePlan(PlanRequest planRequest) throws Exception { // Plan 삭제 objectMapper.deletePlan(planRequest); } public PlanReqResponse selectPlanReqList(PlanReqRequest planReqRequest) throws Exception { // Validation if (StringUtils.isEmpty(planReqRequest.getSaleStoreId())) { 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, message.getMessage("common.message.required.data", "Sale Store Level")); } PlanReqResponse response = null; /* [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); String encodedSchSaleStoreName = URLEncoder.encode( StringUtils.isEmpty(planReqRequest.getSchSaleStoreName()) ? "" : planReqRequest.getSchSaleStoreName(), StandardCharsets.UTF_8); String encodedSchPlanReqName = 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(); /* [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, PlanReqResponse.class); } else { // [msg] No data throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data")); } return response; } public void fileDownload( HttpServletRequest request, HttpServletResponse response, UploadRequest uploadRequest) throws Exception { InputStream inputStream = null; try { // 첨부파일 조회 UploadResponse uploadResponse = objectMapper.selectUpload(uploadRequest); if (uploadResponse != null) { // 첨부파일 물리적 경로 String filePath = baseDirPath + File.separator + uploadResponse.getObjectNo() + File.separator + uploadResponse.getFaileName(); File file = new File(filePath); if (file.exists()) { // 파일 변환 타입 String mimeType = URLConnection.guessContentTypeFromName(file.getName()); if (mimeType == null) { mimeType = "application/octet-stream"; } // 소스 파일 명 String srcFileName = uploadResponse.getFaileName(); srcFileName = URLEncoder.encode(srcFileName, "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-Transfer-Encoding", "binary;"); response.setHeader("Pragma", "no-cache;"); response.setHeader("Expires", "-1;"); response.setHeader("Content-Disposition", "attachment; filename=\"" + srcFileName + "\""); response.setContentType(mimeType); response.setContentLength((int) file.length()); inputStream = new BufferedInputStream(new FileInputStream(file)); FileCopyUtils.copy(inputStream, response.getOutputStream()); } else { throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR); } } else { throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR); } } catch (Exception e) { throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR); } finally { if (inputStream != null) { inputStream.close(); } } } }