Merge branch 'dev' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-api into feature/qcast-api-002

This commit is contained in:
changkyu choi 2024-10-29 18:34:22 +09:00
commit 84fca1363f
30 changed files with 1626 additions and 88 deletions

View File

@ -1,8 +1,10 @@
package com.interplug.qcast.biz.displayItem;
import com.interplug.qcast.biz.displayItem.dto.DisplayItemRequest;
import com.interplug.qcast.biz.displayItem.dto.ItemResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
@ -23,4 +25,19 @@ public class DisplayItemController {
throws Exception {
displayItemService.setStoreDisplayItemSave(displayItemRequest);
}
@Operation(description = "제품 목록을 조회한다.")
@GetMapping("/item_list")
@ResponseStatus(HttpStatus.OK)
public List<ItemResponse> getItemList(@RequestParam("saleStoreId") String saleStoreId)
throws Exception {
return displayItemService.getItemList(saleStoreId);
}
@Operation(description = "제품 상세 정보를 조회한다.")
@GetMapping("/item_detail")
@ResponseStatus(HttpStatus.OK)
public ItemResponse getItemDetail(@RequestParam("itemId") String itemId) throws Exception {
return displayItemService.getItemDetail(itemId);
}
}

View File

@ -1,10 +1,17 @@
package com.interplug.qcast.biz.displayItem;
import com.interplug.qcast.biz.displayItem.dto.DisplayItemRequest;
import com.interplug.qcast.biz.displayItem.dto.ItemResponse;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface DisplayItemMapper {
void setStoreDisplayItemSave(DisplayItemRequest displayItemRequest) throws Exception;
List<ItemResponse> getItemList(@Param("saleStoreId") String saleStoreId);
ItemResponse getItemDetail(@Param("itemId") String itemId);
}

View File

@ -1,6 +1,8 @@
package com.interplug.qcast.biz.displayItem;
import com.interplug.qcast.biz.displayItem.dto.DisplayItemRequest;
import com.interplug.qcast.biz.displayItem.dto.ItemResponse;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -15,4 +17,12 @@ public class DisplayItemService {
public void setStoreDisplayItemSave(DisplayItemRequest displayItemRequest) throws Exception {
displayItemMapper.setStoreDisplayItemSave(displayItemRequest);
}
public List<ItemResponse> getItemList(String saleStoreId) {
return displayItemMapper.getItemList(saleStoreId);
}
public ItemResponse getItemDetail(String itemId) {
return displayItemMapper.getItemDetail(itemId);
}
}

View File

@ -0,0 +1,41 @@
package com.interplug.qcast.biz.displayItem.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class ItemResponse {
@Schema(description = "Itme Id")
private String itemId;
@Schema(description = "Item Name")
private String itemName;
@Schema(description = "Goods No")
private String goodsNo;
@Schema(description = "Unit")
private String unit;
@Schema(description = "Specification")
private String specification;
@Schema(description = "pnow_w")
private String pnowW;
@Schema(description = "Item Group")
private String itemGroup;
@Schema(description = "Module Flag")
private String moduleFlg;
@Schema(description = "PKG Material Flag")
private String pkgMaterialFlg;
@Schema(description = "File Upload Flag")
private String fileUploadFlg;
@Schema(description = "Sale Price")
private String salePrice;
}

View File

@ -0,0 +1,52 @@
package com.interplug.qcast.biz.estimate;
import com.interplug.qcast.biz.estimate.dto.EstimateRequest;
import com.interplug.qcast.biz.estimate.dto.EstimateResponse;
import com.interplug.qcast.biz.estimate.dto.PriceRequest;
import com.interplug.qcast.biz.estimate.dto.PriceResponse;
import com.interplug.qcast.biz.object.dto.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@RequestMapping("/api/estimate")
@RequiredArgsConstructor
@Tag(name = "EstimateController", description = "견적서 관련 API")
public class EstimateController {
private final EstimateService estimateService;
@Operation(description = "1차점 가격 관리 목록을 조회한다.")
@GetMapping("/price/store-price-list")
@ResponseStatus(HttpStatus.OK)
public PriceResponse selectStorePriceList(PriceRequest priceRequest) throws Exception {
return estimateService.selectStorePriceList(priceRequest);
}
@Operation(description = "아이템 가격 목록을 조회한다.")
@PostMapping("/price/item-price-list")
@ResponseStatus(HttpStatus.OK)
public PriceResponse selectItemPriceList(@RequestBody PriceRequest priceRequest)
throws Exception {
return estimateService.selectItemPriceList(priceRequest);
}
@Operation(description = "견적서 상세를 조회한다.")
@GetMapping("/{objectNo}/{planNo}/detail")
@ResponseStatus(HttpStatus.OK)
public EstimateResponse selectObjectDetail(
@PathVariable String objectNo, @PathVariable String planNo) throws Exception {
return estimateService.selectEstimateDetail(objectNo, planNo);
}
@Operation(description = "견적서를 저장한다.")
@PostMapping("/save-estimate")
@ResponseStatus(HttpStatus.CREATED)
public void insertObject(@RequestBody EstimateRequest estimateRequest) throws Exception {
estimateService.insertEstimate(estimateRequest);
}
}

View File

@ -0,0 +1,30 @@
package com.interplug.qcast.biz.estimate;
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.*;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EstimateMapper {
// 견적서 상세 확인
public EstimateResponse selectEstimateDetail(EstimateRequest estimateRequest);
// 견적서 아이템 목록 조회
public List<ItemResponse> selectEstimateItemList(EstimateRequest estimateRequest);
// 아이템 마스터 목록 조회
public List<ItemResponse> selectItemMasterList(EstimateRequest estimateRequest);
// 견적서 정보 수정
public int updateEstimate(EstimateRequest estimateRequest);
// 견적서 아이템 등록
public int insertEstimateItem(ItemRequest itemRequest);
// 견적서 아이템 목록 삭제(물리 삭제)
public int deleteEstimateItemList(EstimateRequest estimateRequest);
}

View File

@ -0,0 +1,421 @@
package com.interplug.qcast.biz.estimate;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.interplug.qcast.biz.estimate.dto.*;
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.ObjectResponse;
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 java.math.BigDecimal;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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
@RequiredArgsConstructor
public class EstimateService {
private final InterfaceQsp interfaceQsp;
@Autowired Messages message;
@Value("${qsp.url}")
private String QSP_API_URL;
private final ObjectMapper objectMapper;
private final EstimateMapper estimateMapper;
private final FileMapper fileMapper;
public PriceResponse 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.getDocTpCd())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Estimate Type"));
}
PriceResponse 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("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, PriceResponse.class);
} else {
// [msg] No data
throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
}
return response;
}
public PriceResponse 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"));
}
PriceResponse 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, PriceResponse.class);
} else {
// [msg] No data
throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
}
return response;
}
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"));
}
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 {
// 아이템 목록 조회
List<ItemResponse> itemList = estimateMapper.selectEstimateItemList(estimateRequest);
response.setItemList(itemList);
// 합산금액 계산
this.selectTotalPriceInfo(response);
// 첨부파일 목록 조회
FileRequest fileDeleteReq = new FileRequest();
fileDeleteReq.setObjectNo(objectNo);
fileDeleteReq.setCategory("10");
fileDeleteReq.setPlanNo(planNo);
List<FileResponse> fileList = fileMapper.selectFileList(fileDeleteReq);
response.setFileList(fileList);
}
return response;
}
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.getSapSalesStoreCd())) {
throw new QcastException(
ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "Sap Sale Store Code"));
}
String splitStr = "";
List<ItemRequest> itemList = estimateRequest.getItemList();
// 도면 작성일 경우에만 지붕재 데이터를 셋팅
if ("1".equals(estimateRequest.getDrawingFlg())) {
// [1]. 견적서 기본셋팅
estimateRequest.setEstimateType("YJOD");
estimateRequest.setPriceCd("UNIT_PRICE");
// 물건정보 조회 데이터 축출
ObjectResponse objectResponse =
objectMapper.selectObjectDetail(estimateRequest.getObjectNo());
if (objectResponse != null) {
estimateRequest.setWeatherPoint(
objectResponse.getPrefName() + " - " + objectResponse.getAreaName());
estimateRequest.setCharger(objectResponse.getReceiveUser());
}
// [2]. 지붕재 관련 데이터 셋팅
List<RoofRequest> roofList = estimateRequest.getRoofList();
// 지붕재 아이템 ID
String roofMaterialIds = "";
// 지붕재 공법 ID
String supportMethodIds = "";
// 지붕재 시공사양 ID
String constructSpecifications = "";
// 지붕재 아이템명
String roofMaterialIdMultis = "";
// 지붕재 공법명
String supportMethodIdMultis = "";
// 가대 메이커명
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.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.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);
int j = 1;
for (ItemRequest itemRequest : itemList) {
itemRequest.setDispOrder(String.valueOf(j++));
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.setSalePrice(itemResponse.getSalePrice());
itemRequest.setPkgMaterialFlg(itemResponse.getPkgMaterialFlg());
itemRequest.setItemGroup(itemResponse.getItemGroup());
break;
}
}
}
}
// 아아템 목록 필수 체크
BigDecimal capacity = BigDecimal.ZERO;
String moduleModel = "";
String pcTypeNo = "";
for (ItemRequest itemRequest : itemList) {
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.updateEstimate(estimateRequest);
// 견적서 모든 아이템 제거
estimateMapper.deleteEstimateItemList(estimateRequest);
// 견적서 아이템 신규 추가
for (ItemRequest itemRequest : itemList) {
itemRequest.setObjectNo(estimateRequest.getObjectNo());
itemRequest.setPlanNo(estimateRequest.getPlanNo());
itemRequest.setPartAdd(
!StringUtils.isEmpty(itemRequest.getPartAdd()) ? itemRequest.getPartAdd() : "0");
itemRequest.setItemChangeFlg(
!StringUtils.isEmpty(itemRequest.getItemChangeFlg())
? itemRequest.getItemChangeFlg()
: "0");
itemRequest.setUserId(estimateRequest.getUserId());
estimateMapper.insertEstimateItem(itemRequest);
}
}
public void selectTotalPriceInfo(EstimateResponse estimateResponse) throws Exception {
BigDecimal totAmount = BigDecimal.ZERO;
BigDecimal totVol = BigDecimal.ZERO;
BigDecimal supplyPrice = BigDecimal.ZERO;
BigDecimal vatPrice = BigDecimal.ZERO;
BigDecimal totPrice = BigDecimal.ZERO;
String estimateType = estimateResponse.getEstimateType();
List<ItemResponse> itemList = estimateResponse.getItemList();
// 주택패키지 단가
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 =
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)));
// YJSS인 경우 (PKG 단가 * 모듈용량) + 패키지 제외상품 합산
// YJOD인 경우 모든 아이템의 합산
if ("YJSS".equals(estimateType)) {
if ("1".equals(itemResponse.getPkgMaterialFlg())) { // 패키지 제외상품 여부(1)
supplyPrice = supplyPrice.add(salePrice.multiply(amount));
} else {
if ("1".equals(itemResponse.getModuleFlg())) {
totVol = totVol.add(pnowW.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)) {
supplyPrice.add(pkgAsp.multiply(totVol));
}
// 부가세 계산 (10프로)
vatPrice = supplyPrice.multiply(new BigDecimal("0.01"));
// 가격 합산 (공급가 + 부가세)
totPrice = totPrice.add(supplyPrice.add(vatPrice));
estimateResponse.setTotAmount(String.valueOf(totAmount.setScale(0, BigDecimal.ROUND_HALF_UP)));
estimateResponse.setTotVol(String.valueOf(totVol.setScale(0, BigDecimal.ROUND_HALF_UP)));
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)));
}
}

View File

@ -0,0 +1,153 @@
package com.interplug.qcast.biz.estimate.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Data;
@Data
public class EstimateRequest {
@Schema(description = "물건번호")
private String objectNo;
@Schema(description = "플랜번호")
private String planNo;
@Schema(description = "판매점ID")
private String saleStoreId;
@Schema(description = "SAP 판매점코드")
private String sapSalesStoreCd;
@Schema(description = "시공방법")
private String constructSpecification;
@Schema(description = "설치높이")
private String setupHeight;
@Schema(description = "날씨포인트")
private String weatherPoint;
@Schema(description = "날씨포인트")
private String roofKindId;
@Schema(description = "경사")
private String slope;
@Schema(description = "지붕재 아이템 CLASS ID")
private String roofMaterialClassId;
@Schema(description = "지붕재 아이템 ID")
private String roofMaterialId;
@Schema(description = "가대 설치 ID")
private String supportMethodId;
@Schema(description = "모델")
private String moduleModel;
@Schema(description = "담당자")
private String charger;
@Schema(description = "견적서 유효기간")
private String estimateValidityTerm;
@Schema(description = "결정 플랜")
private String decisionPlan;
@Schema(description = "넘버")
private String number;
@Schema(description = "시스템용량")
private String capacity;
@Schema(description = "강설량")
private String snowfall;
@Schema(description = "표준풍속검사")
private String standardWindSpeedCheck;
@Schema(description = "옵션커버")
private String optionCover;
@Schema(description = "한화여부")
private String hanwfaFlg;
@Schema(description = "기준종류ID")
private String standKindId;
@Schema(description = "기준풍속ID")
private String standardWindSpeedId;
@Schema(description = "가대 메이커")
private String supportMeaker;
@Schema(description = "소비세ID")
private String consumptionTaxId;
@Schema(description = "상태코드")
private String status;
@Schema(description = "사용자아이디")
private String userId;
@Schema(description = "삭제여부")
private String delFlg;
@Schema(description = "파워컨디셔너")
private String pcTypeNo;
@Schema(description = "북면설치여부")
private String northArrangement;
@Schema(description = "지붕재")
private String roofMaterialIdMulti;
@Schema(description = "가대")
private String supportMethodIdMulti;
@Schema(description = "가대 메이커")
private String supportMeakerMulti;
@Schema(description = "다른 지붕재여부")
private String diffRoofEnabled;
@Schema(description = "발주여부")
private String orderFlg;
@Schema(description = "도면저장여부")
private String drawingFlg;
@Schema(description = "견적일")
private String estimateDate;
@Schema(description = "견적서번호")
private String docNo;
@Schema(description = "견적서타입")
private String estimateType;
@Schema(description = "후일자료제출")
private String fileFlg;
@Schema(description = "견적서 특이사항")
private String estimateOption;
@Schema(description = "PKG 단가")
private String pkgAsp;
@Schema(description = "가격코드")
private String priceCd;
@Schema(description = "비고")
private String remarks;
@Schema(description = "아이템번호 목록")
private String[] arrItemId;
// 데이터 목록 관련 정보
@Schema(description = "지붕재 목록")
List<RoofRequest> roofList;
@Schema(description = "아이템 목록")
List<ItemRequest> itemList;
}

View File

@ -0,0 +1,162 @@
package com.interplug.qcast.biz.estimate.dto;
import com.interplug.qcast.biz.file.dto.FileResponse;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Data;
@Data
public class EstimateResponse {
@Schema(description = "물건번호")
private String objectNo;
@Schema(description = "플랜번호")
private String planNo;
@Schema(description = "시공방법")
private String constructSpecification;
@Schema(description = "설치높이")
private String setupHeight;
@Schema(description = "날씨포인트")
private String weatherPoint;
@Schema(description = "날씨포인트")
private String roofKindId;
@Schema(description = "경사")
private String slope;
@Schema(description = "지붕재 아이템 CLASS ID")
private String roofMaterialClassId;
@Schema(description = "지붕재 아이템 ID")
private String roofMaterialId;
@Schema(description = "가대 설치 ID")
private String supportMethodId;
@Schema(description = "모델")
private String moduleModel;
@Schema(description = "담당자")
private String charger;
@Schema(description = "견적서 유효기간")
private String estimateValidityTerm;
@Schema(description = "결정 플랜")
private String decisionPlan;
@Schema(description = "넘버")
private String number;
@Schema(description = "시스템용량")
private String capacity;
@Schema(description = "강설량")
private String snowfall;
@Schema(description = "표준풍속검사")
private String standardWindSpeedCheck;
@Schema(description = "옵션커버")
private String optionCover;
@Schema(description = "한화여부")
private String hanwfaFlg;
@Schema(description = "기준종류ID")
private String standKindId;
@Schema(description = "기준풍속ID")
private String standardWindSpeedId;
@Schema(description = "가대 메이커")
private String supportMeaker;
@Schema(description = "소비세ID")
private String consumptionTaxId;
@Schema(description = "상태코드")
private String status;
@Schema(description = "사용자아이디")
private String userId;
@Schema(description = "삭제여부")
private String delFlg;
@Schema(description = "파워컨디셔너")
private String pcTypeNo;
@Schema(description = "북면설치여부")
private String northArrangement;
@Schema(description = "지붕재")
private String roofMaterialIdMulti;
@Schema(description = "가대")
private String supportMethodIdMulti;
@Schema(description = "가대 메이커")
private String supportMeakerMulti;
@Schema(description = "다른 지붕재여부")
private String diffRoofEnabled;
@Schema(description = "견적일")
private String estimateDate;
@Schema(description = "발주여부")
private String orderFlg;
@Schema(description = "견적서번호")
private String docNo;
@Schema(description = "견적서타입")
private String estimateType;
@Schema(description = "후일자료제출")
private String fileFlg;
@Schema(description = "견적서 특이사항")
private String estimateOption;
@Schema(description = "PKG 단가")
private String pkgAsp;
@Schema(description = "가격코드")
private String priceCd;
// 가격 관련 정보
@Schema(description = "총 수량")
private String totAmount;
@Schema(description = "총 용량")
private String totVol;
@Schema(description = "공급가액")
private String supplyPrice;
@Schema(description = "부가세")
private String vatPrice;
@Schema(description = "총액")
private String totPrice;
// 물건정보 정보
@Schema(description = "물건명")
private String objectName;
@Schema(description = "경칭")
private String objectNameOmit;
// 데이터 목록 관련 정보
@Schema(description = "아이템 목록")
List<ItemResponse> itemList;
@Schema(description = "첨부파일 목록")
List<FileResponse> fileList;
}

View File

@ -0,0 +1,61 @@
package com.interplug.qcast.biz.estimate.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
// @Data
@Getter
@Setter
public class ItemRequest {
@Schema(description = "물건번호")
private String objectNo;
@Schema(description = "플랜번호")
private String planNo;
@Schema(description = "아이템 ID")
private String itemId;
@Schema(description = "정렬순서")
private String dispOrder;
@Schema(description = "아이템 번호")
private String itemNo;
@Schema(description = "아이템명")
private String itemName;
@Schema(description = "단위")
private String unit;
@Schema(description = "용량")
private String specification;
@Schema(description = "수량")
private String amount;
@Schema(description = "변경수량")
private String amountChange;
@Schema(description = "추가구분코드")
private String partAdd;
@Schema(description = "단가")
private String salePrice;
@Schema(description = "PKG 제외상품 여부")
private String pkgMaterialFlg;
@Schema(description = "아이템 변경 여부")
private String itemChangeFlg;
@Schema(description = "W")
private String pnowW;
@Schema(description = "아이템 그룹코드")
private String itemGroup;
@Schema(description = "사용자아이디")
private String userId;
}

View File

@ -0,0 +1,58 @@
package com.interplug.qcast.biz.estimate.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
// @Data
@Getter
@Setter
public class ItemResponse {
@Schema(description = "물건번호")
private String objectNo;
@Schema(description = "플랜번호")
private String planNo;
@Schema(description = "아이템 ID")
private String itemId;
@Schema(description = "아이템 번호")
private String itemNo;
@Schema(description = "아이템명")
private String itemName;
@Schema(description = "단위")
private String unit;
@Schema(description = "용량")
private String specification;
@Schema(description = "수량")
private String amount;
@Schema(description = "단가")
private String salePrice;
@Schema(description = "합산")
private String saleTotPrice;
@Schema(description = "PKG 제외상품 여부")
private String pkgMaterialFlg;
@Schema(description = "아이템 변경 여부")
private String itemChangeFlg;
@Schema(description = "W")
private String pnowW;
@Schema(description = "아이템 그룹코드")
private String itemGroup;
@Schema(description = "파일첨부 필수여부")
private String fileUploadFlg;
@Schema(description = "모듈여부")
private String moduleFlg;
}

View File

@ -0,0 +1,16 @@
package com.interplug.qcast.biz.estimate.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
// @Data
@Getter
@Setter
public class PriceItemRequest {
@Schema(description = "Item ID")
private String itemId;
@Schema(description = "BOM Item ID")
private String bomItemId;
}

View File

@ -0,0 +1,26 @@
package com.interplug.qcast.biz.estimate.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
// @Data
@Getter
@Setter
public class PriceRequest {
@Schema(description = "판매점ID")
private String saleStoreId;
@Schema(description = "SAP 판매점코드")
private String sapSalesStoreCd;
@Schema(description = "견적구분")
private String docTpCd;
@Schema(description = "가격조회코드")
private String priceCd;
@Schema(description = "아이템번호 목록")
private List<PriceItemRequest> itemIdList;
}

View File

@ -0,0 +1,15 @@
package com.interplug.qcast.biz.estimate.dto;
import lombok.Data;
@Data
public class PriceResponse {
/** API response result */
private Object result;
/** API response data */
private Object data;
/** API response data */
private Object data2;
}

View File

@ -0,0 +1,28 @@
package com.interplug.qcast.biz.estimate.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
// @Data
@Getter
@Setter
public class RoofRequest {
@Schema(description = "지붕재 아이템 ID")
private String roofMaterialId;
@Schema(description = "공법 ID")
private String supportMethodId;
@Schema(description = "시공사양 ID")
private String constructSpecification;
@Schema(description = "지붕재 아이템명")
private String roofMaterialIdMulti;
@Schema(description = "공법명")
private String supportMethodIdMulti;
@Schema(description = "가대메이커명")
private String supportMeaker;
}

View File

@ -64,9 +64,9 @@ public class ExcelDownController {
@Operation(description = "과거데이터_보증서발행완료 물건 파일 다운로드 조회")
@PostMapping("/wrnt-isnc-cmpl-file-down")
@ResponseStatus(HttpStatus.OK)
public void warrantyIssuedCmpFileDown(@RequestBody WrntIsncCmplRequest wrntIsncCmplRequest,
HttpServletResponse response) throws Exception {
public void warrantyIssuedCmpFileDown(
@RequestBody WrntIsncCmplRequest wrntIsncCmplRequest, HttpServletResponse response)
throws Exception {
try {
excelDownService.selectWarrantyIssuedCmpFileData(wrntIsncCmplRequest, response);
} catch (Exception e) {

View File

@ -1,8 +1,6 @@
package com.interplug.qcast.biz.excelDown;
import com.interplug.qcast.biz.excelDown.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.ZipFileManager;
import jakarta.servlet.http.HttpServletResponse;
@ -66,9 +64,12 @@ public class ExcelDownService {
}
zipFileManager.createZipFile(response, "Warranty-issued-completed-files", listFile);
} else {
throw new QcastException(
ErrorCode.NOT_FOUND, message.getMessage("common.message.no.dataDown"));
// 데이터가 없을 경우 NO_CONTENT 상태 코드 설정 종료
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
response.getWriter().write(message.getMessage("common.message.no.dataDown"));
response.flushBuffer();
}
}
}

View File

@ -24,5 +24,5 @@ public class UserResponse {
private String pwdInitYn; // Password Init Yn
private String storeLvl; // Store Level
private String groupId; // groupId
private String custCd; // custCd
}

View File

@ -1,15 +1,31 @@
package com.interplug.qcast.biz.object;
import com.interplug.qcast.biz.object.dto.*;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
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.PrefResponse;
import com.interplug.qcast.biz.object.dto.SaleStoreResponse;
import com.interplug.qcast.biz.object.dto.UploadRequest;
import com.interplug.qcast.biz.object.dto.WindSpeedResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@ -17,7 +33,7 @@ import org.springframework.web.bind.annotation.*;
@RequiredArgsConstructor
@Tag(name = "ObjectController", description = "물건정보 관련 API")
public class ObjectController {
// @Autowired private ObjectService objectService;
// @Autowired private ObjectService objectService;
private final ObjectService objectService;
@Operation(description = "물건정보 도도부현을 조회한다.")
@ -44,9 +60,9 @@ public class ObjectController {
@Operation(description = "판매점 목록을 조회한다.")
@GetMapping("/saleStore/{saleStoreId}/list")
@ResponseStatus(HttpStatus.OK)
public List<SaleStoreResponse> selectSaleStoreList(@PathVariable String saleStoreId)
throws Exception {
return objectService.selectSaleStoreList(saleStoreId);
public List<SaleStoreResponse> selectSaleStoreList(@PathVariable String saleStoreId,
String userId) throws Exception {
return objectService.selectSaleStoreList(saleStoreId, userId);
}
@Operation(description = "물건정보 목록을 조회한다.")
@ -115,12 +131,8 @@ public class ObjectController {
@Operation(description = "견적서 파일을 다운로드한다.")
@PostMapping("/file/{objectNo}/{no}")
@ResponseStatus(HttpStatus.OK)
public void fileDownload(
HttpServletRequest request,
HttpServletResponse response,
@PathVariable String objectNo,
@PathVariable String no)
throws Exception {
public void fileDownload(HttpServletRequest request, HttpServletResponse response,
@PathVariable String objectNo, @PathVariable String no) throws Exception {
UploadRequest uploadRequest = new UploadRequest();
uploadRequest.setObjectNo(objectNo);

View File

@ -5,7 +5,7 @@ import java.util.List;
import org.apache.ibatis.annotations.Mapper;
@Mapper
interface ObjectMapper {
public interface ObjectMapper {
// 도도부현 목록 조회
public List<PrefResponse> selectPrefList();

View File

@ -1,14 +1,5 @@
package com.interplug.qcast.biz.object;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.interplug.qcast.biz.object.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.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;
@ -17,11 +8,11 @@ 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;
@ -29,6 +20,30 @@ import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.util.UriComponentsBuilder;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
@ -46,6 +61,8 @@ public class ObjectService {
private final ObjectMapper objectMapper;
private final StoreFavoriteService storeFavoriteService;
public List<PrefResponse> selectPrefList() throws Exception {
return objectMapper.selectPrefList();
}
@ -58,12 +75,54 @@ public class ObjectService {
return objectMapper.selectWindSpeedList(city);
}
public List<SaleStoreResponse> selectSaleStoreList(String saleStoreId) throws Exception {
public List<SaleStoreResponse> selectSaleStoreList(String saleStoreId, String userId)
throws Exception {
// [0]. 판매점 목록 조회
List<SaleStoreResponse> storeList = new ArrayList<SaleStoreResponse>();
if ("T01".equals(saleStoreId)) {
return objectMapper.selectSaleStoreAllList();
storeList = objectMapper.selectSaleStoreAllList();
// [1]. 판매점 목록 조회 결과
if (storeList.size() > 0) {
StoreFavoriteRequest storeFavoriteReq = new StoreFavoriteRequest();
storeFavoriteReq.setUserId(userId);
// [2]. 사용자 판매점 즐겨찾기 목록 조회 (QSP -> QCAST)
StoreFavoriteResponse storeFavoriteRes = new StoreFavoriteResponse();
storeFavoriteRes = storeFavoriteService.getStoreFavoriteList(storeFavoriteReq);
List<Map<String, Object>> data = (List<Map<String, Object>>) storeFavoriteRes.getData();
Map<String, Object> result = (Map<String, Object>) 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<String, Object> storeFavorite : data) {
String favStoreId = (String) storeFavorite.get("storeId");
if (storeId.equals(favStoreId)) {
saleStore.setPriority("A" + (String) storeFavorite.get("priority"));
}
}
}
// [4]. 정렬 기준 sort (오름차순)
storeList.sort(Comparator.comparing(SaleStoreResponse::getPriority));
}
} else {
throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR,
(String) result.get("resultMsg"));
}
}
} else {
return objectMapper.selectSaleStoreList(saleStoreId);
storeList = objectMapper.selectSaleStoreList(saleStoreId);
}
return storeList;
}
public SaleStoreResponse selectSaleStoreInfo(String saleStoreId) throws Exception {
@ -335,6 +394,12 @@ public class ObjectService {
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(),
@ -345,6 +410,7 @@ public class ObjectService {
? ""
: planReqRequest.getSchAddress(),
StandardCharsets.UTF_8);
String encodedSchSaleStoreName =
URLEncoder.encode(
StringUtils.isEmpty(planReqRequest.getSchSaleStoreName())
@ -359,11 +425,12 @@ public class ObjectService {
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", planReqRequest.getSchPlanReqNo())
.queryParam("schPlanReqNo", encodedSchPlanReqNo)
.queryParam("schTitle", encodedSchTitle)
.queryParam("schAddress", encodedSchAddress)
.queryParam("schSaleStoreName", encodedSchSaleStoreName)

View File

@ -43,6 +43,9 @@ public class ObjectResponse {
@Schema(description = "도도부현코드")
private String prefId;
@Schema(description = "도도부현명")
private String prefName;
@Schema(description = "주소")
private String address;

View File

@ -32,4 +32,8 @@ public class SaleStoreResponse {
@Schema(description = "영업사원 메일주소")
private String businessChargerMail;
@Schema(description = "정렬")
private String priority;
}

View File

@ -1,13 +1,20 @@
package com.interplug.qcast.biz.storeFavorite;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.interplug.qcast.biz.storeFavorite.dto.StoreFavoriteRequest;
import com.interplug.qcast.biz.storeFavorite.dto.StoreFavoriteResponse;
import com.interplug.qcast.biz.user.dto.UserResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@ -15,20 +22,30 @@ import org.springframework.web.bind.annotation.*;
@RequiredArgsConstructor
@Tag(name = "StoreFavorite", description = "Store Favorite 관련 API")
public class StoreFavoriteController {
private final StoreFavoriteService storeFavService;
private final StoreFavoriteService storeFavService;
@Operation(description = "Store Favorite 정보를 등록/수정 한다.(동기화)")
@PutMapping("/store-favorite-save")
@ResponseStatus(HttpStatus.OK)
public UserResponse setStoreFavoriteSave(@RequestBody StoreFavoriteRequest req) throws Exception {
UserResponse userResponse = new UserResponse();
@Operation(description = "Store Favorite 정보를 등록/수정 한다.(동기화)")
@PutMapping("/store-favorite-save")
@ResponseStatus(HttpStatus.OK)
public UserResponse setStoreFavoriteSave(@RequestBody StoreFavoriteRequest req) throws Exception {
UserResponse userResponse = new UserResponse();
int resultCnt = storeFavService.setStoreFavoriteSave(req);
int resultCnt = storeFavService.setStoreFavoriteSave(req);
if (resultCnt > 0) userResponse.setCode("200");
else userResponse.setCode("500");
if (resultCnt > 0)
userResponse.setCode("200");
else
userResponse.setCode("500");
return userResponse;
}
return userResponse;
}
}
@Operation(description = "User Store Favorite 목록을 조회한다.")
@GetMapping("/list")
@ResponseStatus(HttpStatus.OK)
public StoreFavoriteResponse getStoreFavoriteList(@ModelAttribute StoreFavoriteRequest req)
throws Exception {
return storeFavService.getStoreFavoriteList(req);
}
}

View File

@ -1,17 +1,64 @@
package com.interplug.qcast.biz.storeFavorite;
import com.interplug.qcast.biz.storeFavorite.dto.StoreFavoriteRequest;
import lombok.RequiredArgsConstructor;
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.fasterxml.jackson.databind.ObjectMapper;
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 lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class StoreFavoriteService {
private final StoreFavoriteMapper storeFavoriteMapper;
private final StoreFavoriteMapper storeFavoriteMapper;
public int setStoreFavoriteSave(StoreFavoriteRequest req) throws Exception {
return storeFavoriteMapper.setStoreFavoriteSave(req);
private final InterfaceQsp interfaceQsp;
@Autowired
Messages message;
@Value("${qsp.url}")
private String QSP_API_URL;
public int setStoreFavoriteSave(StoreFavoriteRequest req) throws Exception {
return storeFavoriteMapper.setStoreFavoriteSave(req);
}
public StoreFavoriteResponse getStoreFavoriteList(StoreFavoriteRequest req) throws Exception {
StoreFavoriteResponse response = null;
/* [0]. Validation Check */
if ("".equals(req.getUserId())) {
// [msg] {0} is required input value.
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
message.getMessage("common.message.required.data", "User Id"));
}
/* [1]. QSP API (url + param) Setting */
String url = QSP_API_URL + "/api/user/storeFavoriteInfoList";
String apiUrl = UriComponentsBuilder.fromHttpUrl(url).queryParam("userId", req.getUserId())
.build().toUriString();
/* [2]. QSP API CALL -> Response */
String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);
if (!"".equals(strResponse)) {
ObjectMapper om =
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
response = om.readValue(strResponse, StoreFavoriteResponse.class);
} else {
// [msg] No data
throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
}
return response;
}
}

View File

@ -0,0 +1,13 @@
package com.interplug.qcast.biz.storeFavorite.dto;
import lombok.Data;
@Data
public class StoreFavoriteResponse {
/** API response result */
private Object result;
/** API response data */
private Object data;
}

View File

@ -1,37 +1,37 @@
package com.interplug.qcast.util;
import com.interplug.qcast.config.message.Messages;
import jakarta.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.interplug.qcast.config.message.Messages;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class ZipFileManager {
@Autowired
Messages message;
@Autowired Messages message;
/**
* zip file을 생성하여 ZipOutputStream를 반환하는 method
*
* @param response HttpServletResponse
* @param strCreateFileName 생성할 file 이름
* @param listFilePath 파일 정보 목록
* @param listFile 파일 정보 목록
*/
public void createZipFile(HttpServletResponse response, String strCreateFileName,
List<Map<String, String>> listFile) throws Exception {
public void createZipFile(
HttpServletResponse response, String strCreateFileName, List<Map<String, String>> listFile)
throws Exception {
// 압축될 파일명이 존재하지 않을 경우
if (strCreateFileName == null || "".equals(strCreateFileName))
throw new IllegalArgumentException(
@ -44,7 +44,27 @@ public class ZipFileManager {
// zip 파일명
String strZipName = strCreateFileName + ".zip";
// response 설정
// 파일이 실제로 존재하는지 확인하기 위해 카운트
int cnt = 0;
for (Map<String, String> mapFile : listFile) {
String strSourceFile = mapFile.get("filename");
Path path = Path.of(strSourceFile);
if (path.toFile().exists()) {
cnt++;
}
}
log.debug("cnt :: " + cnt);
// 파일이 없을 경우 상태 코드와 메시지 설정 종료
if (cnt == 0) {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
response.getWriter().write("No files available for download.");
response.flushBuffer();
return; // 메서드 종료
}
// 파일이 있을 경우에만 ZIP 파일 생성
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=" + strZipName + ";");
response.setStatus(HttpServletResponse.SC_OK);
@ -55,43 +75,32 @@ public class ZipFileManager {
String strSourceFile = mapFile.get("filename");
Path path = Path.of(strSourceFile);
try (FileInputStream fis = new FileInputStream(path.toFile())) {
// 압축될 파일명을 ZipEntry에 담아준다
ZipEntry zipEntry = new ZipEntry(strDirectory + "\\" + path.getFileName().toString());
if (!path.toFile().exists()) {
log.debug("파일 변환 작업중, [ " + strSourceFile + " ] 파일을 찾을 수 없습니다.");
continue; // 파일이 없으면 스킵
}
// 압축될 파일명을 ZipOutputStream 담아준다
try (FileInputStream fis = new FileInputStream(path.toFile())) {
ZipEntry zipEntry = new ZipEntry(strDirectory + "\\" + path.getFileName().toString());
zos.putNextEntry(zipEntry);
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) >= 0) {
zos.write(buffer, 0, length);
}
} catch (FileNotFoundException e) {
// response.setStatus(HttpServletResponse.SC_NOT_FOUND);
// throw new IllegalArgumentException("파일 변환 작업중, [ " + strSourceFile + " ] 파일을 찾을 수
// 없습니다.");
log.debug("파일 변환 작업중, [ " + strSourceFile + " ] 파일을 찾을 수 없습니다.");
} catch (IOException e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
throw new IllegalArgumentException(
"파일 변환 작업중, [ " + strSourceFile + " ] 파일을 다운로드 할 수 없습니다.");
} finally {
// ZipOutputStream 담아둔 압축될 파일명을 flush 시켜준다
zos.flush();
// ZipOutputStream 담아둔 압축될 파일명을 close 시켜준다
zos.closeEntry();
}
}
} catch (Exception e) {
throw e;
} finally {
try {
// response 담아둔 파일을 flush 시켜준다
response.flushBuffer();
} catch (IOException e) {
throw e;
}
}
response.flushBuffer();
}
}

View File

@ -43,4 +43,63 @@
, #{lastEditDatetime}
);
</insert>
<select id="getItemList" parameterType="String" resultType="com.interplug.qcast.biz.displayItem.dto.ItemResponse" >
/* sqlid : com.interplug.qcast.displayItem.getItemList */
SELECT TT.*
FROM (
SELECT /* 전체 목록중 미표시 제품 */
MI.ITEM_ID
, MI.ITEM_NAME
, MI.DISP_ORDER
FROM M_ITEM MI
LEFT OUTER JOIN M_SALES_STORE_DISP_ITEM SSDI
ON MI.ITEM_ID = SSDI.ITEM_ID
AND SSDI.SALE_STORE_ID = #{saleStoreId}
AND SSDI.DISP_TYPE_CD = 'DISP002' /* 미표시 */
AND dbo.fn_fmtdDate(GETDATE(), 'YYYYMMDD') BETWEEN SSDI.START_DATE AND SSDI.END_DATE
WHERE MI.LIMITED_RELEASE_FLG = 0
AND MI.DEL_FLG = 0
AND SSDI.ITEM_ID IS NULL
UNION ALL
SELECT /* 미표시 제품 중 판매점만 표시 */
MI.ITEM_ID
, MI.ITEM_NAME
, MI.DISP_ORDER
FROM M_SALES_STORE_DISP_ITEM SSDI
INNER JOIN M_ITEM MI
ON MI.ITEM_ID = SSDI.ITEM_ID
AND MI.LIMITED_RELEASE_FLG = 1
AND MI.DEL_FLG = 0
WHERE SSDI.SALE_STORE_ID = #{saleStoreId}
AND SSDI.DISP_TYPE_CD = 'DISP001' /* 표시 */
AND dbo.fn_fmtdDate(GETDATE(), 'YYYYMMDD') BETWEEN SSDI.START_DATE AND SSDI.END_DATE
) TT
ORDER BY TT.DISP_ORDER
</select>
<select id="getItemDetail" parameterType="String" resultType="com.interplug.qcast.biz.displayItem.dto.ItemResponse" >
/* sqlid : com.interplug.qcast.displayItem.getItemDetail */
SELECT
MI.ITEM_ID
, MI.ITEM_NAME
, MI.GOODS_NO
, MI.UNIT
, MI.SPECIFICATION
, MI.PNOW_W
, MI.ITEM_GROUP
, MI.MODULE_FLG
, MI.PKG_MATERIAL_FLG
, MI.FILE_UPLOAD_FLG
, ISNULL(MPPM.SALE_PRICE, '0') AS SALE_PRICE
FROM M_ITEM MI
LEFT OUTER JOIN M_PRICE_PATTERN_MONEY MPPM
ON MPPM.PRICE_PATTERN = '510'
AND MI.ITEM_ID = MPPM.ITEM_ID
WHERE MI.DEL_FLG = 0
AND MI.ITEM_ID = #{itemId}
</select>
</mapper>

View File

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.interplug.qcast.biz.estimate.EstimateMapper">
<select id="selectEstimateDetail" parameterType="com.interplug.qcast.biz.estimate.dto.EstimateRequest" resultType="com.interplug.qcast.biz.estimate.dto.EstimateResponse">
/* sqlid : com.interplug.qcast.biz.estimate.selectEstimateDetail */
SELECT
T.OBJECT_NO
, T.PLAN_NO
, T.CONSTRUCT_SPECIFICATION
, T.SETUP_HEIGHT
, T.WEATHER_POINT
, T.ROOF_KIND_ID
, T.SLOPE
, T.ROOF_MATERIAL_CLASS_ID
, T.ROOF_MATERIAL_ID
, T.SUPPORT_METHOD_ID
, T.MODULE_MODEL
, T.CHARGER
, T.ESTIMATE_VALIDITY_TERM
, T.DECISION_PLAN
, T.NUMBER
, T.CAPACITY
, T.SNOWFALL
, T.STANDARD_WIND_SPEED_CHECK
, T.OPTION_COVER
, T.HANWFA_FLG
, T.STAND_KIND_ID
, T.STANDARD_WIND_SPEED_ID
, T.SUPPORT_MEAKER
, T.CONSUMPTION_TAX_ID
, T.STATUS
, T.PC_TYPE_NO
, T.NORTH_ARRANGEMENT
, T.ROOF_MATERIAL_ID_MULTI
, T.SUPPORT_METHOD_ID_MULTI
, T.SUPPORT_MEAKER_MULTI
, T.DIFF_ROOF_ENABLED
, T.ORDER_FLG
, T.ESTIMATE_DATE
, T.DOC_NO
, T.ESTIMATE_TYPE
, T.FILE_FLG
, T.ESTIMATE_OPTION
, T.PKG_ASP
, O.OBJECT_NAME
, O.OBJECT_NAME_OMIT
FROM T_PLAN T WITH (NOLOCK)
INNER JOIN T_OBJECT O WITH (NOLOCK)
ON T.OBJECT_NO = O.OBJECT_NO
WHERE T.OBJECT_NO = #{objectNo}
AND T.PLAN_NO = #{planNo}
AND T.DEL_FLG = '0'
</select>
<select id="selectEstimateItemList" parameterType="com.interplug.qcast.biz.estimate.dto.EstimateRequest" resultType="com.interplug.qcast.biz.estimate.dto.ItemResponse">
/* sqlid : com.interplug.qcast.biz.estimate.selectEstimateItemList */
SELECT
PE.OBJECT_NO
, PE.PLAN_NO
, PE.ITEM_ID
, PE.ITEM_NO
, PE.ITEM_NAME
, PE.UNIT
, PE.SPECIFICATION
, PE.AMOUNT
, PE.SALE_PRICE
, PE.PKG_MATERIAL_FLG
, PE.ITEM_CHANGE_FLG
, I.PNOW_W
, I.FILE_UPLOAD_FLG
, CASE WHEN I.ITEM_GROUP = 'MODULE_' THEN '1' ELSE '0' END AS MODULE_FLG
FROM T_PART_ESTIMATE PE WITH (NOLOCK)
INNER JOIN M_ITEM I WITH (NOLOCK)
ON PE.ITEM_ID = I.ITEM_ID
WHERE PE.OBJECT_NO = #{objectNo}
AND PE.PLAN_NO = #{planNo}
ORDER BY
PE.DISP_ORDER ASC
</select>
<select id="selectItemMasterList" parameterType="com.interplug.qcast.biz.estimate.dto.EstimateRequest" resultType="com.interplug.qcast.biz.estimate.dto.ItemResponse">
/* sqlid : com.interplug.qcast.biz.estimate.selectItemMasterList */
SELECT
I.ITEM_ID
, I.ITEM_NO
, I.ITEM_NAME
, I.UNIT
, I.PNOW_W
, I.ITEM_GROUP
, I.PKG_MATERIAL_FLG
, ISNULL(PPM.SALE_PRICE, '0') AS SALE_PRICE
FROM M_ITEM I WITH (NOLOCK)
LEFT OUTER JOIN M_PRICE_PATTERN_MONEY PPM
ON PPM.PRICE_PATTERN = '510'
AND I.ITEM_ID = PPM.ITEM_ID
WHERE I.ITEM_ID IN
<foreach collection="arrItemId" item="itemId" index="index" separator="," open="(" close=")">
#{itemId}
</foreach>
</select>
<update id="updateEstimate" parameterType="com.interplug.qcast.biz.estimate.dto.EstimateRequest">
/* sqlid : com.interplug.qcast.biz.estimate.updateEstimate */
UPDATE T_PLAN
SET
ESTIMATE_TYPE = #{estimateType}
<choose>
<when test='drawingFlg != null and drawingFlg == "1"'>
, CONSTRUCT_SPECIFICATION = #{constructSpecification}
, SETUP_HEIGHT = #{setupHeight}
, WEATHER_POINT = #{weatherPoint}
, SLOPE = #{slope}
, ROOF_MATERIAL_ID = #{roofMaterialId}
, SUPPORT_METHOD_ID = #{supportMethodId}
, DRAWING_ESTIMATE_CREATE_DATE = GETDATE()
, CHARGER = #{charger}
, ESTIMATE_VALIDITY_TERM = '発行日より1ヶ月'
, SNOWFALL = #{snowfall}
, STANDARD_WIND_SPEED_ID = #{standardWindSpeedId}
, SUPPORT_MEAKER = #{supportMeaker}
, NORTH_ARRANGEMENT = #{northArrangement}
, ROOF_MATERIAL_ID_MULTI = #{roofMaterialIdMulti}
, SUPPORT_METHOD_ID_MULTI = #{supportMethodIdMulti}
, SUPPORT_MEAKER_MULTI = #{supportMeaker}
, ESTIMATE_DATE = CONVERT(NVARCHAR(10), GETDATE(), 121)
, FILE_FLG = '0'
, ESTIMATE_OPTION = NULL
, PKG_ASP = NULL
, PRICE_CD = #{priceCd}
</when>
<otherwise>
, CHARGER = #{charger}
, ESTIMATE_DATE = #{estimateDate}
, FILE_FLG = #{fileFlg}
, ESTIMATE_OPTION = #{estimateOption}
, REMARKS = #{remarks}
, PKG_ASP = #{pkgAsp}
, PRICE_CD = #{priceCd}
</otherwise>
</choose>
, CAPACITY = #{capacity}
, MODULE_MODEL = #{moduleModel}
, PC_TYPE_NO = #{pcTypeNo}
, LAST_EDIT_DATETIME = GETDATE()
, LAST_EDIT_USER = #{userId}
WHERE OBJECT_NO = #{objectNo}
AND PLAN_NO = #{planNo}
</update>
<insert id="insertEstimateItem" parameterType="com.interplug.qcast.biz.estimate.dto.ItemRequest">
/* sqlid : com.interplug.qcast.biz.estimate.insertEstimateItem*/
INSERT INTO T_PART_ESTIMATE
(
OBJECT_NO
, PLAN_NO
, DISP_ORDER
, ITEM_ID
, ITEM_NO
, ITEM_NAME
, UNIT
, SPECIFICATION
, AMOUNT
<if test='amountChange != null and amountChange != ""'>
, AMOUNT_CHANGE
</if>
, PART_ADD
, LAST_EDIT_DATETIME
, LAST_EDIT_USER
, SALE_PRICE
, PKG_MATERIAL_FLG
, ITEM_CHANGE_FLG
) VALUES (
#{objectNo}
, #{planNo}
, #{dispOrder}
, #{itemId}
, #{itemNo}
, #{itemName}
, #{unit}
, #{specification}
, #{amount}
<if test='amountChange != null and amountChange != ""'>
, #{amountChange}
</if>
, #{partAdd}
, GETDATE()
, #{userId}
, #{salePrice}
, #{pkgMaterialFlg}
, #{itemChangeFlg}
)
</insert>
<delete id="deleteEstimateItemList" parameterType="com.interplug.qcast.biz.estimate.dto.EstimateRequest">
/* sqlid : com.interplug.qcast.biz.estimate.deleteEstimateItemList */
DELETE FROM T_PART_ESTIMATE
WHERE OBJECT_NO = #{objectNo}
AND PLAN_NO = #{planNo}
</delete>
</mapper>

View File

@ -261,9 +261,15 @@
, (SELECT NAME FROM M_USER WHERE USER_ID = O.LAST_EDIT_USER) AS LAST_EDIT_USER_NAME
, S.FIRST_AGENT_ID
, S.SALE_STORE_LEVEL
, ISNULL(P.PREF_NAME, '') AS PREF_NAME
, ISNULL(PA.AREA_NAME, '') AS AREA_NAME
FROM T_OBJECT O WITH (NOLOCK)
INNER JOIN M_SALES_STORE S WITH(NOLOCK)
ON O.SALE_STORE_ID = S.SALE_STORE_ID
LEFT OUTER JOIN M_PREFECTURE P
ON O.PREF_ID = P.PREF_ID
LEFT OUTER JOIN M_PREFECTURE_AREA PA
ON O.AREA_ID = PA.AREA_ID
WHERE O.OBJECT_NO = #{objectNo}
AND (O.DEL_FLG = '0' OR (O.TEMP_FLG = '1' AND O.TEMP_DEL_FLG = '0'))
</select>