From 800453ff6b1c158bd45f6014598f9f1b1735ebfe Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 4 Dec 2025 14:28:30 +0900 Subject: [PATCH] =?UTF-8?q?=ED=98=BC=ED=95=A9=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=ED=9A=8C=EB=A1=9C=20=EB=8C=80=EC=9D=91=20=EC=9E=91=EC=97=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../circuitTrestle/CircuitTrestleSetting.jsx | 29 +++++- .../step/type/PassivityCircuitAllocation.jsx | 94 ++++++++++++++----- src/hooks/useCirCuitTrestle.js | 27 +++++- src/locales/ja.json | 1 + src/locales/ko.json | 1 + 5 files changed, 124 insertions(+), 28 deletions(-) diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index 3827e116..f86a7ead 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -227,11 +227,33 @@ export default function CircuitTrestleSetting({ id }) { return } + const isMultiModule = selectedModules.itemList.length > 1 + + let isAllIndfcs = false + + if (isMultiModule) { + //INDFCS 실내집중, OUTDMULTI 옥외멀티 + // 1. 모듈이 혼합형일 경우 선택한 pcs가 실내집중인 경우 alert + if (selectedModels.length > 0) { + isAllIndfcs = selectedModels.every((model) => model.pcsTpCd === 'INDFCS') + } else { + isAllIndfcs = models.every((model) => model.pcsTpCd === 'INDFCS') + } + } + + if (isAllIndfcs) { + swalFire({ + title: getMessage('module.circuit.indoor.focused.error'), + type: 'alert', + }) + return + } + const params = { ...getOptYn(), useModuleItemList: getUseModuleItemList(), roofSurfaceList: getRoofSurfaceList(), - pcsItemList: getPcsItemList(), + pcsItemList: getPcsItemList(isMultiModule), } // 파워컨디셔너 추천 목록 조회 @@ -292,12 +314,12 @@ export default function CircuitTrestleSetting({ id }) { }) } else { // 회로 구성 가능 여부 체크 - getPcsVoltageChk({ ...params, pcsItemList: getSelectedPcsItemList() }).then((res) => { + getPcsVoltageChk({ ...params, pcsItemList: getSelectedPcsItemList(isMultiModule) }).then((res) => { if (res.resultCode === 'S') { // 회로 구성 가능 여부 체크 통과 시 승압설정 정보 조회 getPcsVoltageStepUpList({ ...params, - pcsItemList: getSelectedPcsItemList(), + pcsItemList: getSelectedPcsItemList(isMultiModule), }).then((res) => { if (res?.result.resultCode === 'S' && res?.data) { setTabNum(2) @@ -523,6 +545,7 @@ export default function CircuitTrestleSetting({ id }) { obj.circuit = null obj.pcsItemId = null obj.circuitNumber = null + obj.pcs = null }) setSelectedModels( JSON.parse(JSON.stringify(selectedModels)).map((model) => { diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index 049efe10..22b0dd16 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -9,7 +9,7 @@ import { moduleStatisticsState } from '@/store/circuitTrestleAtom' import { fontSelector } from '@/store/fontAtom' import { selectedModuleState } from '@/store/selectedModuleOptions' import { circuitNumDisplaySelector } from '@/store/settingAtom' -import { useContext, useEffect, useState } from 'react' +import { useContext, useEffect, useRef, useState } from 'react' import { useRecoilValue } from 'recoil' import { normalizeDigits } from '@/util/input-utils' @@ -32,6 +32,7 @@ export default function PassivityCircuitAllocation(props) { const { header, rows, footer } = useRecoilValue(moduleStatisticsState) const [circuitNumber, setCircuitNumber] = useState(1) const [targetModules, setTargetModules] = useState([]) + const targetModulesRef = useRef([]) const { getPcsManualConfChk } = useMasterController() const isDisplayCircuitNumber = useRecoilValue(circuitNumDisplaySelector) const { setModuleStatisticsData } = useCircuitTrestle() @@ -59,6 +60,10 @@ export default function PassivityCircuitAllocation(props) { } }, []) + useEffect(() => { + targetModulesRef.current = targetModules + }, [targetModules]) + const handleTargetModules = (obj) => { if (!Array.isArray(targetModules)) { setTargetModules([]) @@ -79,6 +84,7 @@ export default function PassivityCircuitAllocation(props) { } const handleCircuitNumberFix = () => { + const pcsTpCd = selectedPcs.pcsTpCd // 실내집중형, 옥외멀티형 let uniqueCircuitNumbers = [ ...new Set( canvas @@ -91,13 +97,13 @@ export default function PassivityCircuitAllocation(props) { const surfaceList = targetModules.map((module) => { return canvas.getObjects().filter((obj) => obj.id === canvas.getObjects().filter((obj) => obj.id === module)[0].surfaceId)[0] }) + let surfaceType = {} + + surfaceList.forEach((surface) => { + surfaceType[`${surface.direction}-${surface.roofMaterial.pitch}`] = surface + }) if (surfaceList.length > 1) { - let surfaceType = {} - - surfaceList.forEach((surface) => { - surfaceType[`${surface.direction}-${surface.roofMaterial.pitch}`] = surface - }) if (Object.keys(surfaceType).length > 1) { swalFire({ text: getMessage('module.circuit.fix.not.same.roof.error'), @@ -107,6 +113,7 @@ export default function PassivityCircuitAllocation(props) { return } } + if (!circuitNumber || circuitNumber === 0) { swalFire({ text: getMessage('module.circuit.minimun.error'), @@ -114,31 +121,65 @@ export default function PassivityCircuitAllocation(props) { icon: 'warning', }) return - } else if (targetModules.length === 0) { + } + + if (targetModules.length === 0) { swalFire({ text: getMessage('module.not.found'), type: 'alert', icon: 'warning', }) return - } else if (selectedModels.length > 1) { - let result = false + } - uniqueCircuitNumbers.forEach((number) => { - if ( - number.split('-')[1] === circuitNumber + ')' && - number.split('-')[0] !== '(' + (selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1) - ) { - result = true - } - }) - if (result) { - swalFire({ - text: getMessage('module.already.exist.error'), - type: 'alert', - icon: 'warning', + switch (pcsTpCd) { + case 'INDFCS': { + const originHaveThisPcsModules = canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.pcs && obj.pcs.id === selectedPcs.id) + // 이미 해당 pcs로 설치된 모듈의 surface의 방향을 구한다. + const originSurfaceList = canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && originHaveThisPcsModules.map((obj) => obj.surfaceId).includes(obj.id)) + + originSurfaceList.concat(originSurfaceList).forEach((surface) => { + surfaceType[`${surface.direction}-${surface.roofMaterial.pitch}`] = surface }) - return + + if (surfaceList.length > 1) { + if (Object.keys(surfaceType).length > 1) { + swalFire({ + text: getMessage('module.circuit.fix.not.same.roof.error'), + type: 'alert', + icon: 'warning', + }) + return + } + } + + break + } + case 'OUTDMULTI': { + if (selectedModels.length > 1) { + let result = false + + uniqueCircuitNumbers.forEach((number) => { + if ( + number.split('-')[1] === circuitNumber + ')' && + number.split('-')[0] !== '(' + (selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1) + ) { + result = true + } + }) + if (result) { + swalFire({ + text: getMessage('module.already.exist.error'), + type: 'alert', + icon: 'warning', + }) + return + } + } } } @@ -189,6 +230,7 @@ export default function PassivityCircuitAllocation(props) { roofSurfaceId: surface.id, roofSurface: surface.direction, roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch, + roofSurfaceNorthYn: surface.direction === 'north' ? 'Y' : 'N', moduleList: surface.modules.map((module) => { return { itemId: module.moduleInfo.itemId, @@ -270,6 +312,12 @@ export default function PassivityCircuitAllocation(props) { return } + targetModules.forEach((module) => { + const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE) + const targetModule = modules.find((obj) => obj.id === module) + targetModule.pcs = selectedPcs + }) + setTargetModules([]) setCircuitNumber(+circuitNumber + 1) setModuleStatisticsData() diff --git a/src/hooks/useCirCuitTrestle.js b/src/hooks/useCirCuitTrestle.js index a35d3c8c..83bb0b84 100644 --- a/src/hooks/useCirCuitTrestle.js +++ b/src/hooks/useCirCuitTrestle.js @@ -42,7 +42,18 @@ export function useCircuitTrestle(executeEffect = false) { } } // PCS 아이템 목록 - const getPcsItemList = () => { + const getPcsItemList = (isMultiModule = false) => { + if (isMultiModule) { + return models + .filter((model) => model.pcsTpCd !== 'INDFCS') + .map((model) => { + return { + itemId: model.itemId, + pcsMkrCd: model.pcsMkrCd, + pcsSerCd: model.pcsSerCd, + } + }) + } return models.map((model) => { return { itemId: model.itemId, @@ -53,7 +64,18 @@ export function useCircuitTrestle(executeEffect = false) { } // 선택된 PCS 아이템 목록 - const getSelectedPcsItemList = () => { + const getSelectedPcsItemList = (isMultiModule = false) => { + if (isMultiModule) { + return selectedModels + .filter((model) => model.pcsTpCd !== 'INDFCS') + .map((model) => { + return { + itemId: model.itemId, + pcsMkrCd: model.pcsMkrCd, + pcsSerCd: model.pcsSerCd, + } + }) + } return selectedModels.map((model) => { return { itemId: model.itemId, @@ -95,6 +117,7 @@ export function useCircuitTrestle(executeEffect = false) { uniqueId: module.id ? module.id : null, } }), + roofSurfaceNorthYn: obj.direction === 'north' ? 'Y' : 'N', } }) .filter((surface) => surface.moduleList.length > 0) diff --git a/src/locales/ja.json b/src/locales/ja.json index db27c2ef..e738ebaa 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1089,6 +1089,7 @@ "module.circuit.minimun.error": "回路番号は1以上の数値を入力してください。", "module.already.exist.error": "回路番号が同じで異なるパワーコンディショナのモジュールがあります。 別の回路番号を設定してください。", "module.circuit.fix.not.same.roof.error": "異なる屋根面のモジュールが選択されています。 モジュールの選択をや直してください。", + "module.circuit.indoor.focused.error": "混合モジュールと屋内集中PCSを組み合わせる場合は、手動回路割り当てのみ対応可能です。", "construction.length.difference": "屋根面工法をすべて選択してください。", "menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。", "batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。", diff --git a/src/locales/ko.json b/src/locales/ko.json index 4f6601cd..bed23c44 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1089,6 +1089,7 @@ "module.circuit.minimun.error": "회로번호는 1 이상입력해주세요.", "module.already.exist.error": "회로번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로번호를 설정하십시오.", "module.circuit.fix.not.same.roof.error": "다른 지붕면의 모듈이 선택되어 있습니다. 모듈 선택을 다시 하세요.", + "module.circuit.indoor.focused.error": "혼합 모듈과 실내 집중형 PCS를 조합하는 경우, 수동 회로 할당만 가능합니다.", "construction.length.difference": "지붕면 공법을 모두 선택하십시오.", "menu.validation.canvas.roof": "패널을 배치하려면 지붕면을 입력해야 합니다.", "batch.object.outside.roof": "오브젝트는 지붕내에 설치해야 합니다.",