diff --git a/apps/fo/app/pages/(with-layout)/processFacility/page.tsx b/apps/fo/app/pages/(with-layout)/processFacility/page.tsx index 87eeffb51..856ab4631 100644 --- a/apps/fo/app/pages/(with-layout)/processFacility/page.tsx +++ b/apps/fo/app/pages/(with-layout)/processFacility/page.tsx @@ -270,8 +270,8 @@ export default function ProcessFacilitySearch() { ref={ref} isAdmin={false} /> -
-
+
+
index !== undefined && cellClick(index)} headName={"처리시설 시설정보"} diff --git a/apps/fo/app/store/sewageOccur/index.tsx b/apps/fo/app/store/sewageOccur/index.tsx index c4da47ca7..7e58f83fe 100644 --- a/apps/fo/app/store/sewageOccur/index.tsx +++ b/apps/fo/app/store/sewageOccur/index.tsx @@ -1,5 +1,5 @@ -import { getFetch, postFetch } from "@/app/components/api"; -// import CalcRainEffect from "@/app/components/common/CalcRainEffect"; +import { getFetch } from "@/app/components/api"; +import CalcRainEffect from "@/app/components/common/CalcRainEffect"; import { roundNumber } from "@/app/components/common/DataForm"; import { OSU_PERCENT } from "../common"; import type { TableUpperProps } from "../dashboard"; @@ -138,33 +138,11 @@ const tempSewageOccurList:modalTableType[] = [] return { data: res.data, count: res.count } }*/ -// const fetchSweageOccurListFlow = async(fcltyCd : string, searchYear : string) => { -// const url = '/fclt/flow/' + fcltyCd + '/' + searchYear; -// const res = await getFetch('fo', url); -// return res; -// } - -// 시설들 유량 정보 조회 -export const fetchSweageOccurListFlow = async (searchYear: string|undefined, fcltCdList: string[]): Promise => { - try { - const res = await postFetch('fo', '/fclt/flow/'+searchYear, fcltCdList); - return res; - } catch (error) { - console.error('시설정보 오수발생량 상세 데이터를 가져오는데 실패했습니다:', error); - return null; - } -}; -// 시설별 물사용량 정보 조회 -export const fetchWtrUsgListFlow = async (searchYear: string|undefined, fcltCdList: string[]): Promise => { - try { - const res = await postFetch('fo', '/fclt/flow/wtrUsg/'+searchYear, fcltCdList); - return res; - } catch (error) { - console.error('시설정보 물사용량 데이터를 가져오는데 실패했습니다:', error); - return null; - } - -}; +const fetchSweageOccurListFlow = async(fcltyCd : string, searchYear : string) => { + const url = '/fclt/flow/' + fcltyCd + '/' + searchYear; + const res = await getFetch('fo', url); + return res; +} /**==================================== * Store - expaort @@ -223,15 +201,15 @@ export const sewageOccurInitState: SewageOccurType = { } // 병렬 처리 제한용 헬퍼 -// async function processInBatches(items, batchSize, callback) { -// const results:any = []; -// for (let i = 0; i < items.length; i += batchSize) { -// const batch = items.slice(i, i + batchSize); -// const batchResults = await Promise.all(batch.map(callback)); -// results.push(...batchResults); -// } -// return results; -// } +async function processInBatches(items, batchSize, callback) { + const results:any = []; + for (let i = 0; i < items.length; i += batchSize) { + const batch = items.slice(i, i + batchSize); + const batchResults = await Promise.all(batch.map(callback)); + results.push(...batchResults); + } + return results; +} export type SewageOccurStore = SewageOccurType & SewageOccurActions; @@ -275,80 +253,53 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { })); } - const fcltylist = facilityInitData.data; // 시설목록 - const fcltCdList : string[] = []; // 시설코드목록 - const sewageOccurPropsList : SewageOccurProps[] = []; // 오수발생량시설목록 - fcltylist.forEach(item => { - fcltCdList.push(item.bscFctCd); - sewageOccurPropsList.push({ - bscFctCd : item.bscFctCd, - sidoNm : item.sido, - sggNm : item.gugun, - lclgvrnmntNm : '', - bscFctNm : item.bscFctNm, - daddr : item.daddr, - fctCpc : parseFloat(item.fctCpc.toString().replace(/,/g, '')), - waterUsage : 0, - swageChangePercent : 0, - estimationSewage : 0, - sewageInputYear : 0, - sewageInputChungchun : 0, - rgnNm : item.rgnNm, - rvbsn : item.rvbsn, - lgbsn : item.lgbsn, - mdmbsn : item.mdmbsn, - msrDt : '', - }); - }); + const fcltylist = facilityInitData.data; - const soccurDetailRes : any = await fetchSweageOccurListFlow(searchYear, fcltCdList); - const wtrUsgRes : any = await fetchWtrUsgListFlow(searchYear, fcltCdList); - const wtrUsgMap : Record = {}; - wtrUsgRes.data.forEach(fclt => { - wtrUsgMap[fclt.bscFctCd] = fclt.wtrUsg; - }); - for (const item of sewageOccurPropsList) { - - const detailList = soccurDetailRes?.data[item.bscFctCd] + const calData = await processInBatches(fcltylist, 20, async (item: SewageOccurProps, index: number) => { + const bscFctCd = item.bscFctCd; + const res = await fetchSweageOccurListFlow(bscFctCd, searchYear).catch(() => { + console.log('Error fetching flow data for facility code:', bscFctCd); + return { data: [], count: 0 }; + }); + item.sidoNm = item.sidoNm || ''; + item.sggNm = item.sggNm || ''; + item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, '')); item.swageChangePercent = 90; - let sumChungcunDay = 0; // 청천일수 - let chungcunSumFlow = 0;// 청천시 하수유입량 - let totWaterUsage = 0; // 연간 하수유입량 - detailList?.forEach(item2 => { - let rainEffectDay = 0; - if (item2.infoRnDay == null) item2.infoRnDay = 0; - if(item2.infoRnDay >= 3) { - rainEffectDay = 2; - }else{ - rainEffectDay--; - } - if(rainEffectDay<0){ //청천시 - chungcunSumFlow += Number(item2.inflAmnt); + let sumChungcunDay = 0; + let chungcunSumFlow = 0; + let totWaterUsage = 0; + + // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) + const rainEffectData = CalcRainEffect(res.data); + + rainEffectData.forEach((item: FlowDataItem) => { + + if(Number(item.rainEffectDay) === 0){ + chungcunSumFlow += Number(item.inflAmnt); sumChungcunDay += 1; } - totWaterUsage += Number(item2.inflAmnt); + totWaterUsage += Number(item.inflAmnt); }); - const count = detailList ? detailList.length : 0; - const avg = count == 0 ? 0 : totWaterUsage / count; // 일평균 유입량 - if(wtrUsgMap && wtrUsgMap[item.bscFctCd]) { - item.waterUsage = wtrUsgMap[item.bscFctCd] ?? 0; - } else {item.waterUsage = parseFloat((avg * 0.65).toFixed(2));} // 물사용량 = 일평균 유입량 * 65% - item.sewageInputYear = parseFloat(avg.toFixed(2)); // 연간 하수유입량(m³/일) - item.sewageInputChungchun = parseFloat((chungcunSumFlow===0?0:(chungcunSumFlow / sumChungcunDay)).toFixed(2)); // 청천시 하수유입량 - item.estimationSewage = parseFloat((item.waterUsage * (item.swageChangePercent/100)).toFixed(2)); // 오수발생량 추정(m³/일) + const avg = res.count == 0 ? 0 : totWaterUsage /res.count; + item.waterUsage = parseFloat((avg * 0.65).toFixed(2)); + item.sewageInputYear = parseFloat(avg.toFixed(2)); + item.sewageInputChungchun = parseFloat((chungcunSumFlow===0?0:(chungcunSumFlow / sumChungcunDay)).toFixed(2)); + item.estimationSewage = parseFloat((item.waterUsage * (item.swageChangePercent/100)).toFixed(2)); // 반올림 처리 ["fctCpc", "waterUsage", "swageChangePercent", "estimationSewage", "sewageInputYear", "sewageInputChungchun"].forEach( (key) => (item[key] = roundNumber(item[key], 0)) ); - } + + return {...item, index:index}; + }); if(pageSize >= 5000){ const excelDownList: ExcelType[] = []; - sewageOccurPropsList.forEach((item: SewageOccurProps) => { + calData.forEach((item: SewageOccurProps) => { excelDownList.push({ 시설코드: item.bscFctCd, 권역: item.rvbsn, @@ -380,7 +331,7 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { ...state, SewageOccur: { ...state.SewageOccur, - sewageOccurList : sewageOccurPropsList, + sewageOccurList : calData, sewageOccurCount : facilityInitData.count, isLoading: false, excelList: [], diff --git a/apps/fo/app/store/underWaterInput/index.tsx b/apps/fo/app/store/underWaterInput/index.tsx index e4c99846e..0624886e9 100644 --- a/apps/fo/app/store/underWaterInput/index.tsx +++ b/apps/fo/app/store/underWaterInput/index.tsx @@ -1,4 +1,4 @@ -import { getFetch, postFetch } from "@/app/components/api"; +import { getFetch } from "@/app/components/api"; import DataForm, { roundNumber } from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps } from "./types"; @@ -203,22 +203,11 @@ const fetchUnderWaterList = async (pageNo: number, pageSize: number, searchYear: //return { data: underWaterList, count: 2 }; }*/ -// const fetchUnderWaterListFlow = async(fcltyCd : string, searchYear : string) => { -// const url = '/fclt/flow/' + fcltyCd + '/' + searchYear; -// const res = await getFetch('fo', url); -// return res; -// } - -// 시설들 유량 정보 조회 -export const fetchDetailListFlow = async (searchYear: string|undefined, fcltCdList: string[]): Promise => { - try { - const res = await postFetch('fo', '/fclt/flow/'+searchYear, fcltCdList); - return res; - } catch (error) { - console.error('시설정보 오수발생량 상세 데이터를 가져오는데 실패했습니다:', error); - return null; - } -}; +const fetchUnderWaterListFlow = async(fcltyCd : string, searchYear : string) => { + const url = '/fclt/flow/' + fcltyCd + '/' + searchYear; + const res = await getFetch('fo', url); + return res; +} /**==================================== * Store - expaort @@ -285,15 +274,15 @@ const dataFormSetting=(item : UnderWaterProps)=> { } // 병렬 처리 제한용 헬퍼 -// async function processInBatches(items, batchSize, callback) { -// const results :any = []; -// for (let i = 0; i < items.length; i += batchSize) { -// const batch = items.slice(i, i + batchSize); -// const batchResults = await Promise.all(batch.map(callback)); -// results.push(...batchResults); -// } -// return results; -// } +async function processInBatches(items, batchSize, callback) { + const results :any = []; + for (let i = 0; i < items.length; i += batchSize) { + const batch = items.slice(i, i + batchSize); + const batchResults = await Promise.all(batch.map(callback)); + results.push(...batchResults); + } + return results; +} export type UnderWaterStore = UnderWaterType & UnderWaterActions; @@ -324,100 +313,68 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy } const fcltylist = facilityInitData.data; - const fcltCdList : string[] = []; // 시설코드목록 - const underWaterPropsList : UnderWaterProps[] = []; // 오수발생량시설목록 - fcltylist.forEach(item => { - fcltCdList.push(item.bscFctCd); - underWaterPropsList.push({ - bscFctCd : item.bscFctCd, - sidoNm : item.sido, - sggNm : item.gugun, - lclgvrnmntNm : '', - bscFctNm : item.bscFctNm, - daddr : item.daddr, - fctCpc : parseFloat(item.fctCpc.toString().replace(/,/g, '')), - inflAmnt : 0, - waterUsage : 0, - underWaterInputYear : 0, - underWaterInputSummer : 0, - underWaterInputWinter : 0, - properYn : '', - infoRnDay : 0, - rgnNm : item.rgnNm, - rvbsn : item.rvbsn, - lgbsn : item.lgbsn, - mdmbsn : item.mdmbsn, - msrDt : '', - }); - }); - - const soccurDetailRes : any = await fetchDetailListFlow(searchYear, fcltCdList); - - for (const item of underWaterPropsList) { - - const detailList = soccurDetailRes?.data[item.bscFctCd] - - let chungcunSumFlow = 0; // 청천유입량 - let sumChungcunDay = 0; // 청천일수 - let sumSummerChungcunDay = 0; // 하절기 청천일수 - let sumSummerChungcunFlow = 0; // 하절기 청천유입량 - let sumWinterChungcunDay = 0; // 동절기 청천일수 - let sumWinterChungcunFlow = 0; // 동절기 청천유입량 - let totWaterUsage = 0; // 연간 하수유입량 - detailList?.forEach(item2 => { - - let rainEffectDay = 0; - if (item2.infoRnDay == null) item2.infoRnDay = 0; - if(item2.infoRnDay >= 3) { - rainEffectDay = 2; - }else{ - rainEffectDay--; - } - if(rainEffectDay<0){ //청천시 - chungcunSumFlow += Number(item2.inflAmnt); - sumChungcunDay += 1; - - if(item2.msrDt.substring(4,6) ==='06' || item2.msrDt.substring(4,6) ==='07' || item2.msrDt.substring(4,6) ==='08'){ - // 하절기 6,7,8월 - sumSummerChungcunDay += 1; - sumSummerChungcunFlow += Number(item2.inflAmnt); //item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0; - }else if(item2.msrDt.substring(4,6) ==='01' || item2.msrDt.substring(4,6) ==='02'){ - // 동절기 1,2월 - sumWinterChungcunDay += 1; - sumWinterChungcunFlow += Number(item2.inflAmnt); //item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0; - } - } - totWaterUsage += Number(item2.inflAmnt); + const calData = await processInBatches(fcltylist, 20, async (item: any, index: number) => { + const bscFctCd = item.bscFctCd; + const res = await fetchUnderWaterListFlow(bscFctCd, searchYear).catch((error) => { + console.log('Error fetching flow data for facility code:', bscFctCd, error); + return { data: [], count: 0 }; // 에러 발생 시 빈 데이터 반환 }); - const count = detailList ? detailList.length : 0; - const avg = count == 0 ? 0 : totWaterUsage / count; // 일평균 유입량 - // 지하수 유입량 추정에는 수용가의 물사용량을 사용할 수 없음 : 청천시의 물사용량을 구하여야 하기 때문임. - // if(wtrUsgMap && wtrUsgMap[item.bscFctCd]) { - // item.waterUsage = wtrUsgMap[item.bscFctCd] ?? 0; - // } else {item.waterUsage = parseFloat((avg * 0.65).toFixed(2));} // 물사용량 = 일평균 유입량 * 65% + item.sidoNm = item.sido || ''; + item.sggNm = item.gugun || ''; + item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, '')); + + let chungcunSumFlow = 0; - const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / sumChungcunDay:0; + let sumSummerChungcunDay = 0; + let sumSummerChungcunFlow = 0; + + let sumWinterChungcunDay = 0; + let sumWinterChungcunFlow = 0; + + const rainEffectData = CalcRainEffect(res.data, 'SUNNY'); + rainEffectData.forEach((flowItem: FlowDataItem) => { + chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + + if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){ + sumSummerChungcunDay += 1; + sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + }else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){ + sumWinterChungcunDay += 1; + sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + } + }); + + let totWaterInflow = 0 + + const rainEffectTot = CalcRainEffect(res.data); + rainEffectTot.forEach((flowItem: FlowDataItem) => { + totWaterInflow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + }); + + + const avg = res.count === 0 ? 0 : totWaterInflow / res.count; + + const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / rainEffectData.length:0; const summerUsage = sumSummerChungcunFlow?sumSummerChungcunFlow / sumSummerChungcunDay:0; const winterUsage = sumWinterChungcunFlow?sumWinterChungcunFlow / sumWinterChungcunDay:0; - + item.inflAmnt = roundNumber(avg, 0); - item.underWaterInputYear = Math.round((usage-(usage*0.65*OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일) - item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*OSU_PERCENT)) * 1) / 1; // 하절기지하수유입량(m³/일) - item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*OSU_PERCENT)) * 1) / 1; // 동절기지하수유입량(m³/일) - item.properYn = Math.round( (Number(usage-(usage*0.65*OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1 ) / 1 > 20?'초과유입':'적정'; // 적정여부 - // 반올림 처리 - // ["fctCpc", "inflAmnt", "underWaterInputYear", "underWaterInputSummer", "underWaterInputWinter"].forEach( - // (key) => (item[key] = roundNumber(item[key], 0)) - // ); - } + item.underWaterInputYear = Math.round((usage-(usage*0.65*OSU_PERCENT)) * 1) / 1; + item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*OSU_PERCENT)) * 1) / 1; + item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*OSU_PERCENT)) * 1) / 1; + item.properYn = Math.round( (Number(usage-(usage*0.65*OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1 ) / 1 > 20?'초과유입':'적정'; + return {...item, index:index}; + }); if(pageSize>= 5000){ const excelDownList: ExcelType[] = []; - underWaterPropsList.forEach((item : any) => { + calData.forEach((item : any) => { dataFormSetting(item) item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, '')); + /* item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || ''; + item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */ excelDownList.push({ 시설코드: item.bscFctCd, 권역: item.rvbsn, @@ -449,7 +406,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy ...state, UnderWater: { ...state.UnderWater, - underWaterList: underWaterPropsList, + underWaterList: calData, underWaterCount: facilityInitData.count, excelList: [], isLoading : false, diff --git a/apps/fo/app/store/underWaterInput/types.tsx b/apps/fo/app/store/underWaterInput/types.tsx index fc0e13bb5..396bd631b 100644 --- a/apps/fo/app/store/underWaterInput/types.tsx +++ b/apps/fo/app/store/underWaterInput/types.tsx @@ -1,23 +1,21 @@ export type UnderWaterProps = { - bscFctCd : string, // 처리구역시설코드 + bscFctCd : string, lclgvrnmntNm : string, - sidoNm : string, // 시도 - sggNm : string, // 시군구 - bscFctNm : string, // 시설명 - daddr : string, // 주소 - fctCpc : number, // 시설용량 - waterUsage : number, // 물사용량(m³/일) - underWaterInputYear : number, // 연간 지하수유입량 추정(m³/일) - underWaterInputSummer : number, // 하절기 지하수유입량 추정(m³/일) - underWaterInputWinter : number, // 동절기 지하수유입량 추정(m³/일) + sidoNm : string, + sggNm : string, + bscFctNm : string, + daddr : string, + fctCpc : number, + underWaterInputYear : number, + underWaterInputSummer : number, + underWaterInputWinter : number, infoRnDay : number, rgnNm : string, rvbsn : string, lgbsn : string, mdmbsn : string, - inflAmnt : number, // 연평균유입하수량(m³/일) - properYn : string | '', // 적정여부 - msrDt : string, // 측정일자 + inflAmnt : number | '', + properYn : string | '', } export interface UnderWaterInterface { bscFctCd : string, diff --git a/apps/wr/app/(without-layout)/stats/hasuStat/page.tsx b/apps/wr/app/(without-layout)/stats/hasuStat/page.tsx index 1d2bf2eb3..dccdd0a41 100644 --- a/apps/wr/app/(without-layout)/stats/hasuStat/page.tsx +++ b/apps/wr/app/(without-layout)/stats/hasuStat/page.tsx @@ -20,7 +20,7 @@ export default function HasuStatPage() { const data = await res.json(); const ip: string = data?.ip || ""; if (didCancel) return; - alert("Client IP:" + ip); + //alert("Client IP:" + ip); const is10 = /^10\./.test(ip); const is172 = /^172\./.test(ip); @@ -29,7 +29,7 @@ export default function HasuStatPage() { // Use location.replace so user can't go back to this page if (is10||is172) { // redirect to internal IP - window.open('http://10.101.163.102:8888/cms/lay1/WS10000014/program.do', '_blank'); + window.open('http://10.101.163.102:8889/cms/lay1/WS10000014/program.do', '_blank'); } else { window.open('https://www.hasudoinfo.or.kr/cms/lay1/WS10000014/program.do', '_blank'); }