Compare commits
No commits in common. "6b78b6e5c0d8989fe7e1d72f7abff86b864b9b68" and "ccd92b1a7423fea395af677c0a3230c35f1c2ce4" have entirely different histories.
6b78b6e5c0
...
ccd92b1a74
@ -87,14 +87,6 @@ public class EstimateController {
|
||||
estimateService.updateEstimateLock(estimateRequest);
|
||||
}
|
||||
|
||||
// 2026-06-30: 회로 유닛별 접속용량(CONN_VOL_W)만 갱신 (기존 데이터 백필용)
|
||||
@Operation(description = "견적서 회로 유닛별 접속용량(CONN_VOL_W)만 갱신한다.")
|
||||
@PostMapping("/update-conn-vol")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public int updateEstimateConnVol(@RequestBody EstimateRequest estimateRequest) throws Exception {
|
||||
return estimateService.updateEstimateConnVol(estimateRequest);
|
||||
}
|
||||
|
||||
@Operation(description = "견적서를 엑셀로 다운로드한다.")
|
||||
@PostMapping("/excel-download")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
|
||||
@ -93,9 +93,6 @@ public interface EstimateMapper {
|
||||
// 견적서 지붕면 회로구성 아이템 등록
|
||||
public int insertEstimateCircuitItem(ItemRequest itemRequest);
|
||||
|
||||
// 2026-06-30: 회로 유닛별 접속용량(CONN_VOL_W)만 비파괴 갱신 (기존 데이터 백필용)
|
||||
public int updateEstimateCircuitConnVol(ItemRequest itemRequest);
|
||||
|
||||
// 견적서 도면 아이템 등록
|
||||
public int insertEstimateDrawingItem(ItemRequest itemRequest);
|
||||
|
||||
|
||||
@ -2870,61 +2870,6 @@ public class EstimateService {
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2026-06-30: 기존 견적서의 회로 유닛별 접속용량(CONN_VOL_W) 백필 전용 API.
|
||||
*
|
||||
* <p>전체 저장(insertEstimate) 없이 T_PART_CIRCUIT_ITEM_ESTIMATE 의 CONN_VOL_W 만 비파괴 UPDATE 한다.
|
||||
* 프론트가 재구성한 모듈별 circuit("1-2")·specification 과 PCS 목록을 받아, 저장 시점과 동일한
|
||||
* 규칙(getPcsCircuitList)으로 유닛별 W 합을 계산해 CIRCUIT_NO 순서대로 갱신한다.
|
||||
* 동일 PCS 모델 다중 유닛은 ITEM_ID 가 같아 ITEM_ID 로 못 나누므로, 저장 당시와 동일한
|
||||
* 순차 CIRCUIT_NO(빈 회로 스킵 포함)로 매칭한다.
|
||||
*
|
||||
* @param estimateRequest objectNo, planNo, roofSurfaceList(모듈), circuitItemList(PCS) 필요
|
||||
* @return 갱신된 회로 행 수
|
||||
*/
|
||||
public int updateEstimateConnVol(EstimateRequest estimateRequest) throws Exception {
|
||||
if (StringUtils.isEmpty(estimateRequest.getObjectNo())) {
|
||||
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
|
||||
message.getMessage("common.message.required.data", "Object No"));
|
||||
}
|
||||
if (StringUtils.isEmpty(estimateRequest.getPlanNo())) {
|
||||
throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
|
||||
message.getMessage("common.message.required.data", "Plan No"));
|
||||
}
|
||||
|
||||
List<ItemRequest> circuitItemList = estimateRequest.getCircuitItemList();
|
||||
List<RoofRequest> roofSurfaceList = estimateRequest.getRoofSurfaceList();
|
||||
|
||||
List<ItemRequest> allModuleList = new ArrayList<ItemRequest>();
|
||||
if (roofSurfaceList != null) {
|
||||
for (RoofRequest roofRequest : roofSurfaceList) {
|
||||
if (roofRequest.getModuleList() != null) {
|
||||
allModuleList.addAll(roofRequest.getModuleList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 저장 시점과 동일 규칙으로 유닛별 CONN_VOL_W(+CIRCUIT_CFG) 계산
|
||||
List<ItemRequest> circuitPcsItemList = this.getPcsCircuitList(circuitItemList, allModuleList);
|
||||
|
||||
int updated = 0;
|
||||
int circuitNo = 0;
|
||||
if (circuitPcsItemList != null) {
|
||||
for (ItemRequest circuitItemRequest : circuitPcsItemList) {
|
||||
// insertEstimateCircuitItem 과 동일하게 빈 회로는 저장되지 않았으므로 CIRCUIT_NO 도 증가시키지 않음
|
||||
if (StringUtils.isEmpty(circuitItemRequest.getCircuitCfg())) {
|
||||
continue;
|
||||
}
|
||||
circuitNo++;
|
||||
circuitItemRequest.setObjectNo(estimateRequest.getObjectNo());
|
||||
circuitItemRequest.setPlanNo(estimateRequest.getPlanNo());
|
||||
circuitItemRequest.setCircuitNo(String.valueOf(circuitNo));
|
||||
updated += estimateMapper.updateEstimateCircuitConnVol(circuitItemRequest);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* PC 회로 구성도 설정
|
||||
*
|
||||
@ -2935,67 +2880,32 @@ public class EstimateService {
|
||||
private List<ItemRequest> getPcsCircuitList(List<ItemRequest> pcsItemList,
|
||||
List<ItemRequest> moduleList) {
|
||||
|
||||
if (pcsItemList == null || pcsItemList.isEmpty()) {
|
||||
return pcsItemList;
|
||||
}
|
||||
if (pcsItemList != null && pcsItemList.size() > 0) {
|
||||
|
||||
// circuit 괄호 제거 (예: "(1-1)" -> "1-1")
|
||||
if (moduleList != null) {
|
||||
for (ItemRequest module : moduleList) {
|
||||
if (module.getCircuit() != null) {
|
||||
module.setCircuit(module.getCircuit().replaceAll("\\(", "").replaceAll("\\)", ""));
|
||||
for (ItemRequest itemRequest : moduleList) {
|
||||
itemRequest
|
||||
.setCircuit(itemRequest.getCircuit().replaceAll("\\(", "").replaceAll("\\)", ""));
|
||||
}
|
||||
|
||||
if (pcsItemList.size() == 1) {
|
||||
pcsItemList.get(0).setCircuitCfg(this.getPcsCircuitCtg(moduleList));
|
||||
} else {
|
||||
if (moduleList != null && moduleList.size() > 0) {
|
||||
int j = 1;
|
||||
for (ItemRequest data : pcsItemList) {
|
||||
String val = String.valueOf(j);
|
||||
|
||||
List<ItemRequest> resultList = moduleList.stream()
|
||||
.filter(t -> StringUtils.equals(val, t.getCircuit().split("-")[0]))
|
||||
.collect(Collectors.toList());
|
||||
data.setCircuitCfg(this.getPcsCircuitCtg(resultList));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 단일 PCS: 모든 모듈이 그 유닛에 접속
|
||||
if (pcsItemList.size() == 1) {
|
||||
pcsItemList.get(0).setCircuitCfg(this.getPcsCircuitCtg(moduleList));
|
||||
// 2026-06-30: 유닛별 접속용량(W) 저장 — 동일 PCS 모델이 여러 유닛일 때 위치기반 추정으로 못 푸는 인증용량을 정확히 계산하기 위함
|
||||
pcsItemList.get(0).setConnVolW(this.sumModuleSpecW(moduleList));
|
||||
return pcsItemList;
|
||||
}
|
||||
|
||||
if (moduleList == null || moduleList.isEmpty()) {
|
||||
return new ArrayList<ItemRequest>();
|
||||
}
|
||||
|
||||
// 2026-06-30 보강: 다중 PCS 의 유닛 판별을 circuit 첫 숫자 기준으로.
|
||||
// pcsItemList 개수(paralQty 로 과다 펼침 등)나 순서 흔들림에 비의존 —
|
||||
// 실제 존재하는 유닛 index 만큼만 결과 행을 만들고, 유닛 u 의 PCS = pcsItemList[u-1] 로 매칭한다.
|
||||
java.util.TreeSet<Integer> unitKeys = new java.util.TreeSet<Integer>();
|
||||
for (ItemRequest module : moduleList) {
|
||||
String circuit = module.getCircuit();
|
||||
if (!StringUtils.isEmpty(circuit)) {
|
||||
try {
|
||||
unitKeys.add(Integer.parseInt(circuit.split("-")[0].trim()));
|
||||
} catch (NumberFormatException e) {
|
||||
// 숫자가 아닌 circuit 은 유닛 판별에서 제외
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<ItemRequest> resultPcsList = new ArrayList<ItemRequest>();
|
||||
for (Integer unit : unitKeys) {
|
||||
String unitStr = String.valueOf(unit);
|
||||
List<ItemRequest> unitModules = moduleList.stream()
|
||||
.filter(t -> !StringUtils.isEmpty(t.getCircuit())
|
||||
&& StringUtils.equals(unitStr, t.getCircuit().split("-")[0].trim()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 유닛 index(1-based) 로 PCS 선택. 범위를 벗어나면 마지막 PCS 로 방어적 폴백
|
||||
int idx = unit - 1;
|
||||
ItemRequest pcs = (idx >= 0 && idx < pcsItemList.size())
|
||||
? pcsItemList.get(idx)
|
||||
: pcsItemList.get(pcsItemList.size() - 1);
|
||||
|
||||
pcs.setCircuitCfg(this.getPcsCircuitCtg(unitModules));
|
||||
// 2026-06-30: 이 유닛(circuit 첫 숫자=unit)에 배선된 모듈 W 합 = 접속용량
|
||||
pcs.setConnVolW(this.sumModuleSpecW(unitModules));
|
||||
resultPcsList.add(pcs);
|
||||
}
|
||||
|
||||
return resultPcsList;
|
||||
return pcsItemList;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3038,34 +2948,6 @@ public class EstimateService {
|
||||
return circuitCfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2026-06-30: PCS 유닛별 접속용량(W) 합산
|
||||
*
|
||||
* <p>유닛에 배선된 모듈들의 specification(=모듈 W, 인증 쿼리가 CAST(SPECIFICATION AS FLOAT)로 쓰는 값) 합.
|
||||
* CIRCUIT_CFG 는 회로별 '개수'만 남기고 모듈 타입(435/270 W)을 버리므로, 동일 PCS 모델이 여러 유닛일 때
|
||||
* 위치기반으로는 유닛별 접속용량을 복원할 수 없다. 그래서 모듈 W가 살아있는 저장 시점에 직접 합산해 보관한다.
|
||||
*
|
||||
* @param moduleList 한 PCS 유닛에 배선된 모듈 목록(모듈 1장 = 1 entry)
|
||||
* @return W 합 문자열(모듈 없음이면 null)
|
||||
*/
|
||||
private String sumModuleSpecW(List<ItemRequest> moduleList) {
|
||||
if (moduleList == null || moduleList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
java.math.BigDecimal sum = java.math.BigDecimal.ZERO;
|
||||
for (ItemRequest module : moduleList) {
|
||||
String spec = module.getSpecification();
|
||||
if (!StringUtils.isEmpty(spec)) {
|
||||
try {
|
||||
sum = sum.add(new java.math.BigDecimal(spec.trim()));
|
||||
} catch (NumberFormatException e) {
|
||||
// 숫자가 아닌 specification 은 접속용량 합산에서 제외
|
||||
}
|
||||
}
|
||||
}
|
||||
return sum.toPlainString();
|
||||
}
|
||||
|
||||
public EstimateApiResponse selectAgencyCustList(PriceRequest priceRequest) throws Exception {
|
||||
// Validation
|
||||
|
||||
|
||||
@ -92,10 +92,6 @@ public class ItemRequest {
|
||||
@Schema(description = "W")
|
||||
private String pnowW;
|
||||
|
||||
// 2026-06-30: PCS 유닛별 접속용량(W) — 저장 시점에 유닛에 배선된 모듈 W 합. 인증용량 계산 시 PNOW_W 와 MIN 비교에 사용
|
||||
@Schema(description = "PCS 유닛별 접속용량(W)")
|
||||
private String connVolW;
|
||||
|
||||
@Schema(description = "아이템 그룹코드")
|
||||
private String itemGroup;
|
||||
|
||||
|
||||
@ -407,7 +407,6 @@
|
||||
SELECT
|
||||
cie.CIRCUIT_NO, cie.OBJECT_NO, cie.PLAN_NO,
|
||||
cie.ITEM_ID AS CIRCUIT_ITEM_ID, cie.CIRCUIT_CFG,
|
||||
cie.CONN_VOL_W, -- 2026-06-30: 저장 시점 유닛별 접속용량(W). 있으면 위치기반 추정보다 우선 사용(동일 PCS 모델 다중 유닛 대응)
|
||||
(SELECT SUM(CAST(LTRIM(RTRIM(x.X.value('.','VARCHAR(10)'))) AS INT))
|
||||
FROM (SELECT CAST('<X>'+REPLACE(cie.CIRCUIT_CFG,',','</X><X>')+'</X>' AS XML) AS d) t
|
||||
CROSS APPLY t.d.nodes('/X') AS x(X)
|
||||
@ -418,14 +417,11 @@
|
||||
),
|
||||
CC AS (
|
||||
SELECT cs.*,
|
||||
-- 2026-06-30: 누적 윈도우를 PCS(CIRCUIT_ITEM_ID) 내부로 한정 — 회로 위치가 다른 PCS 모듈까지 끌어오던 오배분 차단
|
||||
ISNULL((SELECT SUM(c2.CIRCUIT_SUM) FROM CS c2
|
||||
WHERE c2.OBJECT_NO=cs.OBJECT_NO AND c2.PLAN_NO=cs.PLAN_NO
|
||||
AND c2.CIRCUIT_ITEM_ID = cs.CIRCUIT_ITEM_ID
|
||||
AND c2.CIRCUIT_NO < cs.CIRCUIT_NO), 0) AS CUM_START,
|
||||
ISNULL((SELECT SUM(c2.CIRCUIT_SUM) FROM CS c2
|
||||
WHERE c2.OBJECT_NO=cs.OBJECT_NO AND c2.PLAN_NO=cs.PLAN_NO
|
||||
AND c2.CIRCUIT_ITEM_ID = cs.CIRCUIT_ITEM_ID
|
||||
AND c2.CIRCUIT_NO <= cs.CIRCUIT_NO), 0) AS CUM_END
|
||||
FROM CS cs
|
||||
),
|
||||
@ -434,14 +430,11 @@
|
||||
rie.ROOF_ITEM_NO, rie.ROOF_SURFACE_ID, rie.OBJECT_NO, rie.PLAN_NO,
|
||||
rie.ITEM_ID AS ROOF_ITEM_ID, rie.ITEM_NAME,
|
||||
CAST(rie.SPECIFICATION AS FLOAT) AS SPEC, rie.AMOUNT, rie.PC_ITEM_ID,
|
||||
-- 2026-06-30: 모듈 누적도 PCS(PC_ITEM_ID) 내부로 한정 — 실제 배선된 PCS의 모듈만 누적
|
||||
ISNULL((SELECT SUM(r2.AMOUNT) FROM T_PART_ROOF_ITEM_ESTIMATE r2
|
||||
WHERE r2.OBJECT_NO=rie.OBJECT_NO AND r2.PLAN_NO=rie.PLAN_NO
|
||||
AND r2.PC_ITEM_ID = rie.PC_ITEM_ID
|
||||
AND r2.ROOF_ITEM_NO < rie.ROOF_ITEM_NO), 0) AS CUM_START,
|
||||
ISNULL((SELECT SUM(r2.AMOUNT) FROM T_PART_ROOF_ITEM_ESTIMATE r2
|
||||
WHERE r2.OBJECT_NO=rie.OBJECT_NO AND r2.PLAN_NO=rie.PLAN_NO
|
||||
AND r2.PC_ITEM_ID = rie.PC_ITEM_ID
|
||||
AND r2.ROOF_ITEM_NO <= rie.ROOF_ITEM_NO), 0) AS CUM_END
|
||||
FROM T_PART_ROOF_ITEM_ESTIMATE rie
|
||||
WHERE rie.OBJECT_NO = #{objectNo} AND rie.PLAN_NO = #{planNo}
|
||||
@ -454,9 +447,7 @@
|
||||
CASE WHEN cc.CUM_END < rc.CUM_END THEN cc.CUM_END ELSE rc.CUM_END END
|
||||
- CASE WHEN cc.CUM_START > rc.CUM_START THEN cc.CUM_START ELSE rc.CUM_START END AS ALLOCATED_QTY
|
||||
FROM CC cc
|
||||
-- 2026-06-30: 실제 배선(PCS) 일치 조건 추가 — 회로의 PCS 와 모듈이 배선된 PCS 가 같은 경우만 겹침
|
||||
INNER JOIN RC rc ON cc.OBJECT_NO = rc.OBJECT_NO AND cc.PLAN_NO = rc.PLAN_NO
|
||||
AND cc.CIRCUIT_ITEM_ID = rc.PC_ITEM_ID
|
||||
WHERE cc.CUM_START < rc.CUM_END AND cc.CUM_END > rc.CUM_START
|
||||
),
|
||||
DETAIL AS (
|
||||
@ -466,28 +457,18 @@
|
||||
ROUND(a.SPEC, 3) * a.ALLOCATED_QTY AS SPEC_X_QTY,
|
||||
(SELECT mi.PNOW_W FROM M_ITEM mi WHERE mi.ITEM_ID = a.CIRCUIT_ITEM_ID) AS PNOW_W
|
||||
FROM ALLOC a
|
||||
),
|
||||
POS AS (
|
||||
-- 위치기반(폴백) 유닛별 접속용량 W 합 — CONN_VOL_W 가 없는 기존 데이터에만 사용
|
||||
SELECT CIRCUIT_NO, CIRCUIT_ITEM_ID, SUM(SPEC_X_QTY) AS POS_W
|
||||
FROM DETAIL
|
||||
GROUP BY CIRCUIT_NO, CIRCUIT_ITEM_ID
|
||||
),
|
||||
CIRCUIT_AGG AS (
|
||||
-- 2026-06-30 option B: 저장된 CONN_VOL_W 우선, 없으면(NULL=기존 데이터) 위치기반 POS_W 폴백.
|
||||
-- CS(유닛 목록) 기준으로 LEFT JOIN 하므로 유닛별 1행 보장. 유닛별 MIN(접속용량, PNOW_W) 후 합산.
|
||||
SELECT
|
||||
cs.CIRCUIT_NO, cs.CIRCUIT_ITEM_ID,
|
||||
COALESCE(cs.CONN_VOL_W, pos.POS_W, 0) AS CONN_W,
|
||||
(SELECT mi.PNOW_W FROM M_ITEM mi WHERE mi.ITEM_ID = cs.CIRCUIT_ITEM_ID) AS PNOW_W
|
||||
FROM CS cs
|
||||
LEFT JOIN POS pos
|
||||
ON pos.CIRCUIT_NO = cs.CIRCUIT_NO
|
||||
AND pos.CIRCUIT_ITEM_ID = cs.CIRCUIT_ITEM_ID
|
||||
CIRCUIT_NO, CIRCUIT_ITEM_ID, CIRCUIT_CFG, CIRCUIT_SUM,
|
||||
SUM(SPEC_X_QTY) AS SUM_SPEC_X_QTY, PNOW_W,
|
||||
CASE WHEN SUM(SPEC_X_QTY) <= PNOW_W THEN SUM(SPEC_X_QTY) ELSE PNOW_W END AS MIN_VALUE
|
||||
FROM DETAIL
|
||||
GROUP BY CIRCUIT_NO, CIRCUIT_ITEM_ID, CIRCUIT_CFG, CIRCUIT_SUM, PNOW_W
|
||||
)
|
||||
|
||||
-- 2026-06-05: SQL 은 W 합만 DECIMAL 로 정확히 반환. kW 변환·3자리 절사(FLOOR)는 모듈용량(totVolKw)과 동일하게 Java BigDecimal 에서 수행 → FLOAT 나눗셈 잔여(5.6899999999999995 / 5.339) 원천 차단
|
||||
SELECT CAST(SUM(CASE WHEN CONN_W <= PNOW_W THEN CONN_W ELSE PNOW_W END) AS DECIMAL(18,3)) AS CERT_VOL_W
|
||||
SELECT CAST(SUM(MIN_VALUE) AS DECIMAL(18,3)) AS CERT_VOL_W
|
||||
FROM CIRCUIT_AGG
|
||||
|
||||
]]>
|
||||
@ -1197,27 +1178,15 @@
|
||||
, PLAN_NO
|
||||
, ITEM_ID
|
||||
, CIRCUIT_CFG
|
||||
, CONN_VOL_W /* 2026-06-30: 유닛별 접속용량(W) — 인증용량 MIN 비교용 */
|
||||
) VALUES (
|
||||
#{circuitNo}
|
||||
, #{objectNo}
|
||||
, #{planNo}
|
||||
, #{itemId}
|
||||
, #{circuitCfg}
|
||||
, #{connVolW}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="updateEstimateCircuitConnVol" parameterType="com.interplug.qcast.biz.estimate.dto.ItemRequest">
|
||||
/* sqlid : com.interplug.qcast.biz.estimate.updateEstimateCircuitConnVol */
|
||||
/* 2026-06-30: 기존 데이터 백필용 — 회로 유닛별 접속용량(CONN_VOL_W)만 비파괴 UPDATE. 동일 PCS 모델 다중 유닛은 ITEM_ID 로 못 나누므로 CIRCUIT_NO 로 매칭 */
|
||||
UPDATE T_PART_CIRCUIT_ITEM_ESTIMATE
|
||||
SET CONN_VOL_W = #{connVolW}
|
||||
WHERE OBJECT_NO = #{objectNo}
|
||||
AND PLAN_NO = #{planNo}
|
||||
AND CIRCUIT_NO = #{circuitNo}
|
||||
</update>
|
||||
|
||||
<delete id="deleteEstimateRoofList" parameterType="com.interplug.qcast.biz.estimate.dto.EstimateRequest">
|
||||
/* sqlid : com.interplug.qcast.biz.estimate.deleteEstimateRoofList */
|
||||
DELETE FROM T_PART_ROOF_ESTIMATE
|
||||
@ -1476,7 +1445,6 @@
|
||||
, PLAN_NO
|
||||
, ITEM_ID
|
||||
, CIRCUIT_CFG
|
||||
, CONN_VOL_W /* 2026-06-30: 복제 시에도 유닛별 접속용량 보존(미보존 시 인증용량이 위치기반 폴백으로 떨어짐) */
|
||||
)
|
||||
SELECT
|
||||
PCIE.CIRCUIT_NO
|
||||
@ -1484,7 +1452,6 @@
|
||||
, #{copyPlanNo} AS PLAN_NO
|
||||
, PCIE.ITEM_ID
|
||||
, PCIE.CIRCUIT_CFG
|
||||
, PCIE.CONN_VOL_W
|
||||
FROM T_PART_CIRCUIT_ITEM_ESTIMATE PCIE WITH (NOLOCK)
|
||||
WHERE PCIE.OBJECT_NO = #{objectNo}
|
||||
AND PCIE.PLAN_NO = #{planNo}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user