diff --git a/apps/dm/app/(popup-layout)/map/popup/page.tsx b/apps/dm/app/(popup-layout)/map/popup/page.tsx index 6efb4ebef..ea1e4b174 100644 --- a/apps/dm/app/(popup-layout)/map/popup/page.tsx +++ b/apps/dm/app/(popup-layout)/map/popup/page.tsx @@ -99,7 +99,7 @@ const Map = () => { if (feature) { foundFeature = feature; return; - } + } } } }); @@ -132,6 +132,8 @@ const Map = () => { }, { width: 30 } ); + } else { + alert("수요처의 좌표정보를 찾을수 없으므로, 상단 조회조건의 시설명을 입력하여 위치를 조회하시기 바랍니다."); } const formatNumber = (val: any) => { diff --git a/apps/fo/app/components/common/CalcRainEffect.tsx b/apps/fo/app/components/common/CalcRainEffect.tsx index 9a99564e7..beca33f78 100644 --- a/apps/fo/app/components/common/CalcRainEffect.tsx +++ b/apps/fo/app/components/common/CalcRainEffect.tsx @@ -16,7 +16,7 @@ export default function CalcRainEffect(data : any, weather='ALL') { for(let idx = 0; idx < data.length; idx++) { const item = data[idx]; if(item){ - if(item.infoRnDay && Number(item.infoRnDay) >= 3) { + if(item.infoRnDay && Number(item.infoRnDay) >= 3) { // 강우량이 3 이상인 경우 item.rainEffectDay = 1; } else { item.rainEffectDay = 0; @@ -49,11 +49,13 @@ export default function CalcRainEffect(data : any, weather='ALL') { for(let idx = 0; idx < data.length; idx++) { if(data[idx] && data[idx]?.rainEffectDay === 1) { if(idx > 1){ + // 전날 비가 왔고 오늘 강우량 3미만인 경우 전날 강우량이 3이상이면 오늘 toBeInfoRnDay을 전날 강우량으로 설정 if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { data[idx]!.toBeInfoRnDay = data[idx-1]!.infoRnDay; } } if(idx > 2){ + // 전전날 비가 왔고 오늘 강우량 3미만인 경우 전전날 강우량이 3이상이면 오늘 toBeInfoRnDay을 전전날 강우량으로 설정 if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { data[idx]!.toBeInfoRnDay = data[idx-2]!.infoRnDay; } diff --git a/apps/fo/app/page.tsx b/apps/fo/app/page.tsx index 143dfdc90..cf94377eb 100644 --- a/apps/fo/app/page.tsx +++ b/apps/fo/app/page.tsx @@ -11,20 +11,18 @@ export default function Home() { const checkToken = getCookie(AUTH_USER_ID); useEffect(() => { - const hostname = window.location.hostname; - - if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") { - if (!checkToken) { - async function doLogin() { - try { - await LoginApi.login({ userId: "CLEANWATER", password: "gktneh12!@" }); - window.location.href = "/pages/dashboard"; - } catch (err) { - console.error("로그인 실패", err); - } + if (!checkToken) { + async function doLogin() { + try { + await LoginApi.login({ userId: "CLEANWATER", password: "gktneh12!@" }); + location.href = "/pages/dashboard"; + } catch (err) { + console.error("로그인 실패", err); } - doLogin(); - } else router.push("/pages/dashboard"); - } else router.push("/pages/dashboard"); + } + doLogin(); + } else { + router.push("/pages/dashboard"); + } }, []); } \ No newline at end of file diff --git a/apps/fo/app/store/facilityWaterQlty/index.tsx b/apps/fo/app/store/facilityWaterQlty/index.tsx index 86da34144..0eafcfcd0 100644 --- a/apps/fo/app/store/facilityWaterQlty/index.tsx +++ b/apps/fo/app/store/facilityWaterQlty/index.tsx @@ -1,4 +1,4 @@ -import { getFetch } from "@/app/components/api"; +import { getFetch, postFetch } from "@/app/components/api"; import DataForm, { roundNumber } from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; import CalcRainEffect from "@/app/components/common/CalcRainEffect"; @@ -15,6 +15,15 @@ export type { TableUpperProps }; /** * (1) 메인페이지 */ + +// RDII 상세 타입 +export interface FacilityRdiiDetailProps { + msrDt: string, // 측정일 + inflAssctBfrWqltBod: string | '', // 유입연계전수질_BOD(mg/L) + inflAmnt: number | '', // 실제유입량(반류수제거)(m³/일) + infoRnDay: number | string | '', // 강수량 (mm/일) +} + // 시설수질리스트 타입 export interface FacilityWaterQltyProps { bscFctCd: string, @@ -306,6 +315,16 @@ export const fetchFacilityWaterQltyListHist = async (searchYear: string|undefine return null; } }; +// 시설정보 RDII 상세 [{BOD - inflAssctBfrWqltBod, 유입유량 inflAmnt, 강우량 infoRnDay, 측정일 msrDt}] +export const fetchFacilityRdiiDetailList = async (searchYear: string|undefined, swtrmtFcltCdList: string[]): Promise => { + try { + const res = await postFetch('fo', '/rdii/detail/'+searchYear, swtrmtFcltCdList); + return res; + } catch (error) { + console.error('시설정보 RDII 상세 데이터를 가져오는데 실패했습니다:', error); + return null; + } +}; /**==================================== * Store - export diff --git a/apps/fo/app/store/rdi/index.tsx b/apps/fo/app/store/rdi/index.tsx index 6a6d9a1ef..6fd287432 100644 --- a/apps/fo/app/store/rdi/index.tsx +++ b/apps/fo/app/store/rdi/index.tsx @@ -1,9 +1,10 @@ import { getFetch } from "@/app/components/api"; -import CalcRainEffect from "@/app/components/common/CalcRainEffect"; +//import CalcRainEffect from "@/app/components/common/CalcRainEffect"; import DataForm, { roundNumber } from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; -import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty"; -import type { FlowResponse } from "../sewageOccur"; +//import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty"; +import { fetchFacilityRdiiDetailList } from "../facilityWaterQlty"; +//import type { FlowResponse } from "../sewageOccur"; export type { TableUpperProps }; /**==================================== * Store - 타입 @@ -245,15 +246,15 @@ const dataFormSetting=(item : RdiProps)=> { type SetStateFunction = (state: RdiType | ((state: RdiType) => RdiType)) => void; // 병렬 처리 제한용 헬퍼 -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 RdiStore = RdiType & RdiActions; @@ -302,44 +303,30 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio })); } - const data = res.data; - const reData = await processInBatches(data, 15, async (item: any, index: number) => { - const bscFctCd = item.bscFctCd; - const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as FlowResponse; - const calData = CalcRainEffect(res2.data, 'SUNNY'); - let avgChungcunSumFlow = 0; - let chungcunSumFlow = 0; - - calData.forEach((flowItem: any) => { - 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; - } */ - }); - avgChungcunSumFlow = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / calData.length : 0; - item.chungchunFlow = avgChungcunSumFlow; - item.rainCalInflAmnt = Number(avgChungcunSumFlow) + Number(item.rdiiValue); - return {...item, index:index} - }); - const excelDownList: ExcelType[] = []; - const rtnData = reData.map((item: RdiProps) => { + const rtnData = res.data.map((item: RdiProps) => { return { ...item, sido: item.lclgvrnmntNm.split(' ')[0]?.toString() || '', sigungo: item.lclgvrnmntNm.split(' ')[1]?.toString() || '', - inflAmnt: item.inflAmnt?Number(item.inflAmnt).toFixed(1): '' + inflAmnt: item.inflAmnt?Number(item.inflAmnt).toFixed(1): '' // 유입유량 (강우량) } }) - // 청천히 동절기 유입bod를 새로 구하기 위해서 재 호출 + const fcltCdList : string[]= []; + rtnData.forEach(item => { + fcltCdList.push(item.bscFctCd); + }); + + const rdiiDetailListRes : any = await fetchFacilityRdiiDetailList(searchYear, fcltCdList); + console.log(rdiiDetailListRes); + for (const item of rtnData) { - const fcltyCd = item.bscFctCd; - const res: any = await fetchFacilityWaterQltyListHist(searchYear, fcltyCd); + //const fcltyCd = item.bscFctCd; + //const res: any = await fetchFacilityWaterQltyListHist(searchYear, fcltyCd); + //const rdiiDetailList = res.data.wqltObjs; + const rdiiDetailList = rdiiDetailListRes?.data[item.bscFctCd]; + //console.log(rdiiDetailListRes); let rtnWinterInflBod = 0; let rtnSummerBodInfl = 0; @@ -348,50 +335,53 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio let rtnRdiRain = 0; let chungchunFlow = 0; - if (res?.data) { - const clone = (arr: any[]) => arr?.map(v => ({ ...v })) ?? []; - const rtnWqltData = res.data.wqltObjs; - const wqltDataTot = CalcRainEffect(clone(rtnWqltData)); - const wqltDataSunny = CalcRainEffect(clone(rtnWqltData), 'SUNNY'); + if (rdiiDetailList) { - let chungchunInfl = 0; + let chungchunInfl = 0; // 청천시 유입 let chungchunCnt = 0; let minSummerBod = 99999999; let minSummerBodInfl = 99999999; let winterCnt = 0; let winterBodSunny = 0; - let rdiRain = 0; - + let rdiRain = 0; const summerMonth = ['06', '07', '08']; const winterMonth = ['01', '02']; - wqltDataTot.forEach(item2 => { - if(item2.rainEffectDay == 0){ - chungchunCnt ++; - chungchunInfl += Number(item2.inflAmnt); - } - - if(summerMonth.includes(item2.msrDt.toString().replaceAll('-','').substring(4,6))){ - if(Number(item2.infoRnDay)>=3){ + //const clone = (arr: any[]) => arr?.map(v => ({ ...v })) ?? []; + let rainEffectDay = 0; + rdiiDetailList.forEach(item2 => { + + if (item2.infoRnDay == null) item2.infoRnDay = 0; + if(item2.infoRnDay >= 3) { + rainEffectDay = 2; + //강우시 + if(summerMonth.includes(item2.msrDt.toString().replaceAll('-','').substring(4,6))){ + //하절기 const inflBod = Number(item2.inflAssctBfrWqltBod); const infl = Number(item2.inflAmnt); const rain = Number(item2.infoRnDay); if(inflBod < minSummerBod){ - minSummerBodInfl = infl; - minSummerBod = inflBod; - rdiRain = rain; + minSummerBodInfl = infl; // 강우일 하절기 최저 유입 BOD 일때의 유입유량 + minSummerBod = inflBod; // 강우일 하절기 최저 유입 BOD + rdiRain = rain; // 강우일 하절기 최저 유입 BOD 일때의 강우량 } } + }else{ + rainEffectDay--; + } + if(rainEffectDay<0){ + //청천시 + chungchunInfl += item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0; + chungchunCnt ++; + if(winterMonth.includes(item2.msrDt.toString().replaceAll('-','').substring(4,6))){ + winterBodSunny += Number(item2.inflAssctBfrWqltBod); // 동절기 청천시 유입BOD 합계 + winterCnt += 1; + } } }); - - wqltDataSunny.filter(item=>winterMonth.includes(item.msrDt.toString().replaceAll('-','').substring(4,6))).forEach(item2 => { - winterBodSunny += Number(item2.inflAssctBfrWqltBod); - winterCnt += 1; - }); - - minSummerBod = minSummerBod === 99999999 ? 0 : minSummerBod; - minSummerBodInfl = minSummerBodInfl === 99999999 ? 0 : minSummerBodInfl; + + minSummerBod = minSummerBod === 99999999 ? 0 : minSummerBod; // 강우일 최저 유입 BOD + minSummerBodInfl = minSummerBodInfl === 99999999 ? 0 : minSummerBodInfl; // 강우일 최저 유입 BOD일때 유입유량 const roundMinSummerBodInfl = Number(roundNumber(minSummerBodInfl, 0).toString().replaceAll(',','')); const roundMinSummerBod = Number(roundNumber(minSummerBod, 1).toString().replaceAll(',','')); @@ -401,23 +391,24 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio // 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 x ((동절기 청천시 유입BOD - 하절기(6~8월) 중 최저 유입BOD) / (동절기 청천시 유입BOD)) const winMinusSum = winterBodAvg - roundMinSummerBod; - const rdiValue = winMinusSum===0 ? 0 : roundMinSummerBodInfl * (winMinusSum / winterBodAvg ); + const rdiValue = winMinusSum===0 ? 0 : roundMinSummerBodInfl * (winMinusSum / winterBodAvg ); // RDII 추정 - rtnWinterInflBod = winterBodAvg; - rtnSummerBodInfl = minSummerBodInfl; - rtnSummerBod = minSummerBod; - rtnRdiValue = rdiValue; - rtnRdiRain = rdiRain; - chungchunFlow = chungchunInfl == 0? 0 : chungchunInfl / chungchunCnt; + rtnWinterInflBod = winterBodAvg; // 동절기 청천시 유입BOD + rtnSummerBodInfl = minSummerBodInfl; // 하절기(6~8월) 중 최저 유입 BOD일때 유입유량 + rtnSummerBod = minSummerBod; // 하절기(6~8월) 중 최저 유입 BOD + rtnRdiValue = rdiValue; // RDII 추정 + rtnRdiRain = rdiRain; // RDII 추정시 일강수량 + chungchunFlow = chungchunInfl == 0? 0 : chungchunInfl / chungchunCnt; // 청천시 유입하수량 } - item.summerMinBodValue = roundNumber(rtnSummerBod,1); - item.inflAmnt = roundNumber(rtnSummerBodInfl.toString(), 0); - item.winterAvgBodLowRainfall = rtnWinterInflBod?roundNumber(rtnWinterInflBod, 1):0; - item.rdiiValue = rtnRdiValue?roundNumber(rtnRdiValue, 0):0; - item.infoRnDay = roundNumber(rtnRdiRain, 0); - item.chungchunFlow = roundNumber(chungchunFlow, 0); - item.rainCalInflAmnt = roundNumber(Number(item.chungchunFlow.toString().replaceAll(',','')) + Number(item.rdiiValue.toString().replaceAll(',','')), 0) || 0; + item.summerMinBodValue = roundNumber(rtnSummerBod,1); // 하절기강우일최저유입BOD(mg/L) + item.inflAmnt = roundNumber(rtnSummerBodInfl.toString(), 0); // 하절기최저유입BOD유입유량(m³/일) + item.winterAvgBodLowRainfall = rtnWinterInflBod?roundNumber(rtnWinterInflBod, 1):0; // 동절기청천시유입BOD(mg/L) + item.rdiiValue = rtnRdiValue?roundNumber(rtnRdiValue, 0):0; // RDII추정 + item.infoRnDay = roundNumber(rtnRdiRain, 0); // RDII추정시일강수량(mm) + item.chungchunFlow = roundNumber(chungchunFlow, 0); //청천시유입하수량(m³/일) + item.rainCalInflAmnt = roundNumber(Number(item.chungchunFlow.toString().replaceAll(',','')) + + Number(item.rdiiValue.toString().replaceAll(',','')), 0) || 0; // 강우시총추정유입량(m³/일) item.properYn = Number(item.rainCalInflAmnt.toString().replaceAll(',','')) > Number(item.fctCpc.toString().replaceAll(',','')) ? '초과유입' : '적정'; } diff --git a/apps/fo/src/entities/auth/lib/auth-wrapper.tsx b/apps/fo/src/entities/auth/lib/auth-wrapper.tsx index b19772f8f..d3ae23177 100644 --- a/apps/fo/src/entities/auth/lib/auth-wrapper.tsx +++ b/apps/fo/src/entities/auth/lib/auth-wrapper.tsx @@ -1,7 +1,8 @@ "use client"; import { useEffect } from "react"; -import { useRouter, usePathname } from "next/navigation"; +import { useRouter } from "next/navigation"; +//import { usePathname } from "next/navigation"; import { client } from "@/src/shared/api"; import type { IUserInfo } from "@/src/shared/store"; import { useUserStore, getCookie } from "@/src/shared/lib"; @@ -12,7 +13,7 @@ const LOGIN_PAGE_URL = process.env.NEXT_PUBLIC_CM_LOGIN_PAGE_URL || "http://loca const AuthWrapper = ({ children }: { children: React.ReactNode }) => { const router = useRouter(); - const pathname = usePathname(); + //const pathname = usePathname(); const { userInfo, setUserInfo } = useUserStore((state) => state); async function authCheck() { @@ -41,7 +42,7 @@ const AuthWrapper = ({ children }: { children: React.ReactNode }) => { console.error("Token refresh failed:", refreshError); setUserInfo(null); - const hostname = window.location.hostname; + const hostname = location.hostname; // 개발 환경에서는 localhost 도메인 사용 if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "con.mind-one.co.kr") @@ -49,11 +50,11 @@ const AuthWrapper = ({ children }: { children: React.ReactNode }) => { // 운영 환경에서는 서브도메인을 포함한 최상위 도메인 사용 // router.push는 같은 Next.js 앱 내에서만 작동하므로 다른 앱으로 이동할 때는 window.location.href 사용 - if (hostname.includes("hasuon.or.kr")) window.location.href = LOGIN_PAGE_URL; // 세션 만료 시 CM 로그인 페이지로 리다이렉트 + if (hostname.includes("hasuon.or.kr")) location.href = LOGIN_PAGE_URL; // 세션 만료 시 CM 로그인 페이지로 리다이렉트 } } })(); - }, [pathname]); + }, []); return <>{children}; };