diff --git a/apps/fo/app/store/sewageOccur/index.tsx b/apps/fo/app/store/sewageOccur/index.tsx index c41ccaa8f..69d2a4f50 100644 --- a/apps/fo/app/store/sewageOccur/index.tsx +++ b/apps/fo/app/store/sewageOccur/index.tsx @@ -34,12 +34,20 @@ export type SewageOccurProps = { } export type modalTableType = { msrDt: string,waterUsage: number,swageChangePercent: number,estimationSewage: number}; export type SewageOccurDetailProps = { - cnt : number, +cnt : number, sum : number, yr:string, - usege:number + usage:number, // 일평균 유입량 + cntWtrUsg : number, // 물사용량 일자수 + sumWtrUsg : number, // 물사용량 합 + avgWtrUsg:number, // 일평균 물사용량 + monWtrUsg:number, // 월 물사용량 +} +export type WtrUsgYmProps = { + bscFctCd : string, // 처리구역시설코드 + levyYm : string, // 부과년월 + wtrUsg : number, // 월별 물사용량(m³/월) } - // 검색단 const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별']; @@ -121,6 +129,27 @@ const sewageOccurList:SewageOccurProps[] = [] const tempSewageOccurList:modalTableType[] = [] +/** + * yyyymm 형태의 문자열을 받아 해당 월의 일수를 반환 + * @param {string} yyyymm - 예: "202502", "202412" + * @returns {number} 해당 월의 일수 (예: 28, 29, 30, 31) + */ +function getDaysInMonth(yyyymm) { + if (typeof yyyymm !== 'string' || yyyymm.length !== 6) { + throw new Error("입력은 'yyyymm' 형식의 문자열이어야 합니다. 예: '202502'"); + } + + const year = parseInt(yyyymm.slice(0, 4), 10); // "2025" -> 2025 + const month = parseInt(yyyymm.slice(4, 6), 10); // "02" -> 2 + + if (isNaN(year) || isNaN(month) || month < 1 || month > 12) { + throw new Error("유효한 년/월이 아닙니다."); + } + + // Date(year, month, 0) -> 전달의 마지막 날 + // month에 '다음달'을 넣고, 일(day)에 0을 주면 해당 월의 마지막 날짜가 됨 + return new Date(year, month, 0).getDate(); +} /**==================================== * Store - API ====================================*/ @@ -155,15 +184,14 @@ export const fetchSweageOccurListFlow = async (searchYear: string|undefined, fcl } }; // 시설별 물사용량 정보 조회 -export const fetchWtrUsgListFlow = async (searchYear: string|undefined, fcltCdList: string[]): Promise => { +export const fetchWtrUsgYmList = async (searchYear: string|undefined, fcltCdList: string[]): Promise => { try { - const res = await postFetch('fo', '/fclt/flow/wtrUsg/'+searchYear, fcltCdList); + const res = await postFetch('fo', '/fclt/flow/wtrUsgYm/'+searchYear, fcltCdList); return res; } catch (error) { - console.error('시설정보 물사용량 데이터를 가져오는데 실패했습니다:', error); + console.error('시설들 월별 물사용량 데이터를 가져오는데 실패했습니다:', error); return null; } - }; /**==================================== @@ -171,7 +199,7 @@ export const fetchWtrUsgListFlow = async (searchYear: string|undefined, fcltCdLi ====================================*/ export type SewageOccurActions = { searchSewageOccurList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void; - searchSewageOccurDetailList: (bscFctCd: string, searchYear: string, startYearMonth?: string, endYearMonth?: string) => void; + searchSewageOccurDetailList: (bscFctCd: string, searchYear: string, startYm?: string, endYm?: string) => void; } export type SewageOccurType = { @@ -302,14 +330,15 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { }); 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; - }); + const wtrUsgYmRes : any = await fetchWtrUsgYmList(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 detailList = soccurDetailRes?.data[item.bscFctCd]; + const wtrUsgYmList = wtrUsgYmRes?.data[item.bscFctCd]; item.swageChangePercent = 90; let sumChungcunDay = 0; // 청천일수 @@ -331,15 +360,24 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { totWaterUsage += Number(item2.inflAmnt); }); + let wtrUsgYearTotal = 0; // 연간 물사용량 + let wtrUsgYearDays = 0; // 연간 물사용 일수 + wtrUsgYmList?.forEach(item3 => { + const days = getDaysInMonth(item3.levyYm); + wtrUsgYearTotal += Number(item3.wtrUsg); + wtrUsgYearDays += days; + }); + // console.log("totWaterUsage:", totWaterUsage); 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.waterUsage = parseFloat((avg * 0.65).toFixed(2)); // 물사용량 = 일평균 유입량 * 65% + if(wtrUsgYearTotal > 0 && wtrUsgYearDays > 0) { + item.waterUsage = wtrUsgYearDays>0? wtrUsgYearTotal / wtrUsgYearDays: 0; // 일평균 물사용량 + } 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³/일) + item.estimationSewage = parseFloat((item.waterUsage * OSU_PERCENT).toFixed(2)); // 오수발생량 추정(m³/일) if ( item.bscFctCd === '11200PB001R' ) { console.log('chungcunSumFlow:', chungcunSumFlow); console.log('sumChungcunDay:', sumChungcunDay); @@ -476,24 +514,39 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { }); */ }, - searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string, startYearMonth?: string, endYearMonth?: string) => { + searchSewageOccurDetailList: async (bscFctCd: string, searchYear: string, startYm?: string, endYm?: string) => { + const fcltCdList = [bscFctCd]; + const wtrUsgRes : any = await fetchWtrUsgYmList(searchYear, fcltCdList); const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear); const monthData: SewageOccurDetailProps[] = []; let tot = 0, cnt= 0; - if(startYearMonth) { + if(startYm) { res.data = res.data.filter((item: FlowDataItem) => { const month = item.msrDt?.substring(0, 6); - return month >= startYearMonth; + return month >= startYm; }); + if (wtrUsgRes && wtrUsgRes.data && wtrUsgRes.data[bscFctCd]) { + wtrUsgRes.data = wtrUsgRes.data.filter((item: WtrUsgYmProps) => { + const month = item.levyYm?.substring(0, 6); + return month >= startYm; + }); + } } - if(endYearMonth) { + if(endYm) { res.data = res.data.filter((item: FlowDataItem) => { const month = item.msrDt?.substring(0, 6); - return month <= endYearMonth; + return month <= endYm; }); + if (wtrUsgRes && wtrUsgRes.data && wtrUsgRes.data[bscFctCd]) { + wtrUsgRes.data = wtrUsgRes.data.filter((item: WtrUsgYmProps) => { + const month = item.levyYm?.substring(0, 6); + return month <= endYm; + }); + } } + // 유입량 res.data.forEach((item: FlowDataItem) => { const month = item.msrDt?.substring(4, 6); const monthIdx = month ? Number(month) - 1 : -1; @@ -502,12 +555,31 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { monthData[monthIdx].sum += Number(item.inflAmnt); monthData[monthIdx].cnt++; } else { - monthData[monthIdx] = {cnt:1, sum:Number(item.inflAmnt), yr:item.msrDt.substring(0,4), usege:0}; + monthData[monthIdx] = {cnt:1, sum:Number(item.inflAmnt), yr:item.msrDt.substring(0,4) + , usage:0, cntWtrUsg:0, sumWtrUsg:0, avgWtrUsg:0, monWtrUsg:0}; } } tot += Number(item.inflAmnt) cnt++ - }) + }); + + // 물사용량 + let totWtrUsg = 0; + let cntWtrUsg = 0; + if (wtrUsgRes && wtrUsgRes.data && wtrUsgRes.data[bscFctCd]) { + wtrUsgRes.data.forEach((item: WtrUsgYmProps) => { + const month = item.levyYm?.substring(4, 6); + const monthIdx = month ? Number(month) - 1 : -1; + if (monthIdx >= 0) { + if (typeof monthData[monthIdx] === 'object') { + monthData[monthIdx].sumWtrUsg += Number(item.wtrUsg); + monthData[monthIdx].cntWtrUsg += getDaysInMonth(item.levyYm); + } + } + totWtrUsg += Number(item.wtrUsg); + cntWtrUsg += getDaysInMonth(item.levyYm); + }); + } const tableData:modalTableType[] = [] @@ -515,42 +587,44 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { let minWaterUsage = 9999999999; let avgWaterUsage = 0; monthData.forEach((item, index) => { - item.usege = item.sum/item.cnt *0.65 + item.avgWtrUsg = item.sum/item.cnt *0.65; // 일평균 물사용량 = 일평균유입수 * 0.65 + if (item.sumWtrUsg > 0 && item.cntWtrUsg > 0) item.avgWtrUsg = item.sumWtrUsg / item.cntWtrUsg; tableData.push({ msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)), - waterUsage: Math.round(item.usege*1) /1, - swageChangePercent: (Math.round((item.usege/item.usege*OSU_PERCENT) * 100) / 100) * 100, - estimationSewage: Math.round(item.usege*OSU_PERCENT * 1) / 1 + waterUsage: Math.round(item.avgWtrUsg*1) /1, + swageChangePercent: OSU_PERCENT*100,//(Math.round((item.usage/item.usage*OSU_PERCENT) * 100) / 100) * 100, + estimationSewage: Math.round(item.avgWtrUsg*OSU_PERCENT * 1) / 1 }) - if (item.usege > maxWaterUsage) { - maxWaterUsage = item.usege; + if (item.avgWtrUsg > maxWaterUsage) { + maxWaterUsage = item.avgWtrUsg; } - if (item.usege < minWaterUsage) { - minWaterUsage = item.usege; + if (item.avgWtrUsg < minWaterUsage) { + minWaterUsage = item.avgWtrUsg; } }); avgWaterUsage = tot/cnt*0.65 + if (totWtrUsg > 0 && cntWtrUsg > 0) avgWaterUsage = totWtrUsg / cntWtrUsg; const newData= [ { msrDt: '평균', - waterUsage: Math.round(avgWaterUsage*1) /1, - swageChangePercent: 90, - estimationSewage: Math.round(avgWaterUsage*0.9*1) /1, + waterUsage: roundNumber(Math.round(avgWaterUsage*1) /1,0), + swageChangePercent: OSU_PERCENT*100, + estimationSewage: roundNumber(Math.round(avgWaterUsage*OSU_PERCENT*1) /1,0), }, { msrDt: '최대', - waterUsage: Math.round(maxWaterUsage*100) /100, - swageChangePercent: 90, - estimationSewage: Math.round(maxWaterUsage*0.9*1) /1, + waterUsage: roundNumber(Math.round(maxWaterUsage*100) /100,0), + swageChangePercent: OSU_PERCENT*100, + estimationSewage: roundNumber(Math.round(maxWaterUsage*OSU_PERCENT*1) /1, 0), }, { msrDt: '최소', - waterUsage: Math.round(minWaterUsage*100) /100, - swageChangePercent: 90, - estimationSewage: Math.round(minWaterUsage*0.9*1) /1, + waterUsage: roundNumber(Math.round(minWaterUsage*100) /100,0), + swageChangePercent: OSU_PERCENT*100, + estimationSewage: roundNumber(Math.round(minWaterUsage*OSU_PERCENT*1) /1,0), }, ...tableData ] diff --git a/apps/fo/app/store/underWaterInput/index.tsx b/apps/fo/app/store/underWaterInput/index.tsx index f88f2ab8b..c6a2167d8 100644 --- a/apps/fo/app/store/underWaterInput/index.tsx +++ b/apps/fo/app/store/underWaterInput/index.tsx @@ -1,8 +1,8 @@ import { getFetch, postFetch } from "@/app/components/api"; import DataForm, { roundNumber } from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; -import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps } from "./types"; -import CalcRainEffect from "@/app/components/common/CalcRainEffect"; +import type { ExcelType, UnderWaterInputModalProps, UnderWaterProps, WtrUsgYmProps } from "./types"; +// import CalcRainEffect from "@/app/components/common/CalcRainEffect"; import { OSU_PERCENT } from "../common"; import { fetchFacilityListInit } from "../processFacility"; export type { TableUpperProps }; @@ -12,7 +12,13 @@ export type SewageOccurDetailProps = { cnt : number, sum : number, yr:string, - usege:number + usage:number, // 일평균 유입량 + sunnyCnt : number, + sunnyInflAmnt : number, + sunnyAvgInflAmnt : number, // 청천시 일평균 유입량 + cntWtrUsg : number, // 물사용량 일자수 + sumWtrUsg : number, // 물사용량 합 + avgWtrUsg:number, // 일평균 물사용량 } /**==================================== * Store - 타입 @@ -219,6 +225,16 @@ export const fetchDetailListFlow = async (searchYear: string|undefined, fcltCdLi return null; } }; +// 시설들 월별 물사용량 정보 조회 +export const fetchWtrUsgYmList = async (searchYear: string|undefined, fcltCdList: string[]): Promise => { + try { + const res = await postFetch('fo', '/fclt/flow/wtrUsgYm/'+searchYear, fcltCdList); + return res; + } catch (error) { + console.error('시설들 월별 물사용량 데이터를 가져오는데 실패했습니다:', error); + return null; + } +}; /**==================================== * Store - expaort @@ -294,6 +310,27 @@ const dataFormSetting=(item : UnderWaterProps)=> { // } // return results; // } +/** + * yyyymm 형태의 문자열을 받아 해당 월의 일수를 반환 + * @param {string} yyyymm - 예: "202502", "202412" + * @returns {number} 해당 월의 일수 (예: 28, 29, 30, 31) + */ +function getDaysInMonth(yyyymm) { + if (typeof yyyymm !== 'string' || yyyymm.length !== 6) { + throw new Error("입력은 'yyyymm' 형식의 문자열이어야 합니다. 예: '202502'"); + } + + const year = parseInt(yyyymm.slice(0, 4), 10); // "2025" -> 2025 + const month = parseInt(yyyymm.slice(4, 6), 10); // "02" -> 2 + + if (isNaN(year) || isNaN(month) || month < 1 || month > 12) { + throw new Error("유효한 년/월이 아닙니다."); + } + + // Date(year, month, 0) -> 전달의 마지막 날 + // month에 '다음달'을 넣고, 일(day)에 0을 주면 해당 월의 마지막 날짜가 됨 + return new Date(year, month, 0).getDate(); +} export type UnderWaterStore = UnderWaterType & UnderWaterActions; @@ -352,19 +389,28 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy }); const soccurDetailRes : any = await fetchDetailListFlow(searchYear, fcltCdList); + const wtrUsgYmRes : any = await fetchWtrUsgYmList(searchYear, fcltCdList); for (const item of underWaterPropsList) { - const detailList = soccurDetailRes?.data[item.bscFctCd] + const detailList = soccurDetailRes?.data[item.bscFctCd]; + const wtrUsgYmList = wtrUsgYmRes?.data[item.bscFctCd]; let chungcunSumFlow = 0; // 청천유입량 let sumChungcunDay = 0; // 청천일수 let sumSummerChungcunDay = 0; // 하절기 청천일수 let sumSummerChungcunFlow = 0; // 하절기 청천유입량 - let sumWinterChungcunDay = 0; // 동절기 청천일수 let sumWinterChungcunFlow = 0; // 동절기 청천유입량 let totWaterUsage = 0; // 연간 하수유입량 + let totSummerUsage = 0; // 하절기 하수유입량 + let totWinterUsage = 0; // 동절기 하수유입량 + let totSummerDays = 0; // 하절기 일수 + let totWinterDays = 0; // 동절기 일수 + + const summerMonth = ['06', '07', '08']; + const winterMonth = ['01', '02']; + let rainEffectDay = 0; detailList?.forEach(item2 => { @@ -389,28 +435,71 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy } } totWaterUsage += Number(item2.inflAmnt); + if(item2.msrDt.substring(4,6) ==='06' || item2.msrDt.substring(4,6) ==='07' || item2.msrDt.substring(4,6) ==='08'){ + // 하절기 6,7,8월 + totSummerDays += 1; + totSummerUsage += 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월 + totWinterDays += 1; + totWinterUsage += Number(item2.inflAmnt); //item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 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% - - const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / sumChungcunDay: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?'초과유입':'적정'; // 적정여부 + + let wtrUsgYearTotal = 0; // 연간 물사용량 + let summerWtrUsgTot = 0; // 하절기 물사용량 + let winterWtrUsgTot = 0; // 동절기 물사용량 + let wtrUsgYearDays = 0; // 연간 물사용 일수 + let summerWtrUsgDays = 0;// 하절기 물사용 일수 + let winterWtrUsgDays = 0;// 동절기 물사용 일수 + wtrUsgYmList?.forEach(item3 => { + const days = getDaysInMonth(item3.levyYm); + wtrUsgYearTotal += Number(item3.wtrUsg); + wtrUsgYearDays += days; + if(summerMonth.includes(item3.levyYm.slice(-2))){ + summerWtrUsgTot += Number(item3.wtrUsg); + summerWtrUsgDays += days; + }else if(winterMonth.includes(item3.levyYm.slice(-2))){ + winterWtrUsgTot += Number(item3.wtrUsg); + winterWtrUsgDays += days; + } + }); + + if (wtrUsgYearTotal > 0) { // 물사용량이 있는 경우 + const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / sumChungcunDay:0; // 청천시 일평균 유입량 + const summerUsage = sumSummerChungcunFlow?sumSummerChungcunFlow / sumSummerChungcunDay:0; // 하절기 청천시 일평균 유입량 + const winterUsage = sumWinterChungcunFlow?sumWinterChungcunFlow / sumWinterChungcunDay:0; // 동절기 청천시 일평균 유입량 + const wtrUsg = wtrUsgYearDays>0? wtrUsgYearTotal / wtrUsgYearDays: 0; // 일평균 물사용량 + const summerWtrUsg = summerWtrUsgTot?summerWtrUsgTot / summerWtrUsgDays:0; // 하절기 일평균 물사용량 + const winterWtrUsg = winterWtrUsgTot?winterWtrUsgTot / winterWtrUsgDays:0; // 동절기 일평균 물사용량 + + item.inflAmnt = roundNumber(avg, 0); + item.underWaterInputYear = Math.round((usage-(wtrUsg*OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율) + item.underWaterInputSummer = Math.round((summerUsage-(summerWtrUsg*OSU_PERCENT)) * 1) / 1; // 하절기지하수유입량(m³/일) + item.underWaterInputWinter = Math.round((winterUsage-(winterWtrUsg*OSU_PERCENT)) * 1) / 1; // 동절기지하수유입량(m³/일) + item.properYn = Math.round( (Number(usage-(wtrUsg*OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1 ) / 1 > 20?'초과유입':'적정'; // 적정여부 + } else { // 물사용량이 없는 경우, 일평균 유입량으로 물사용량 추정(물사용량 = 유입량*0.65) + const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / sumChungcunDay:0; // 청천시 일평균 유입량 + const summerUsage = sumSummerChungcunFlow?sumSummerChungcunFlow / sumSummerChungcunDay:0; // 하절기 청천시 일평균 유입량 + const winterUsage = sumWinterChungcunFlow?sumWinterChungcunFlow / sumWinterChungcunDay:0; // 동절기 청천시 일평균 유입량 + const wtrUsg = avg * 0.65; // 일평균 물사용량 + const summerWtrUsg = totSummerDays>0? (totSummerUsage / totSummerDays)*0.65:0; // 하절기 일평균 물사용량 + const winterWtrUsg = totWinterDays>0? (totWinterUsage / totWinterDays)*0.65:0; // 동절기 일평균 물사용량 + + item.inflAmnt = roundNumber(avg, 0); + //item.underWaterInputYear = Math.round((usage-(usage*0.65*OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일) + item.underWaterInputYear = Math.round((usage-(wtrUsg*OSU_PERCENT)) * 1) / 1; // 연간지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율) + item.underWaterInputSummer = Math.round((summerUsage-(summerWtrUsg*OSU_PERCENT)) * 1) / 1; // 하절기지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율) + item.underWaterInputWinter = Math.round((winterUsage-(winterWtrUsg*OSU_PERCENT)) * 1) / 1; // 동절기지하수유입량(m³/일) = 청천시 실제유입량 - (물사용량 × 오수전환율) + item.properYn = Math.round( (Number(usage-(wtrUsg*OSU_PERCENT)) / Number(item.inflAmnt)) * 100 * 1 ) / 1 > 20?'초과유입':'적정'; // 적정여부 // 반올림 처리 // ["fctCpc", "inflAmnt", "underWaterInputYear", "underWaterInputSummer", "underWaterInputWinter"].forEach( // (key) => (item[key] = roundNumber(item[key], 0)) // ); + } } if(pageSize>= 5000){ @@ -459,79 +548,148 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy }, unserWaterModal:async (bscFctCd, searchYear, startYm, endYm)=>{ + const fcltCdList = [bscFctCd]; + const wtrUsgRes : any = await fetchWtrUsgYmList(searchYear, fcltCdList); const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear); const monthData: SewageOccurDetailProps[] = []; - - const calData = CalcRainEffect(res.data, 'SUNNY'); - let tot = 0; - let cnt = 0; - - calData.forEach((item: FlowDataItem) => { - const month = item.msrDt?.substring(4, 6); + let tot = 0, cnt = 0; + let sunnyTot = 0, sunnyCnt = 0; + + if(startYm) { + res.data = res.data.filter((item: FlowDataItem) => { + const month = item.msrDt?.substring(0, 6); + return month >= startYm; + }); + if (wtrUsgRes && wtrUsgRes.data && wtrUsgRes.data[bscFctCd]) { + wtrUsgRes.data = wtrUsgRes.data.filter((item: WtrUsgYmProps) => { + const month = item.levyYm?.substring(0, 6); + return month >= startYm; + }); + } + } + if(endYm) { + res.data = res.data.filter((item: FlowDataItem) => { + const month = item.msrDt?.substring(0, 6); + return month <= endYm; + }); + if (wtrUsgRes && wtrUsgRes.data && wtrUsgRes.data[bscFctCd]) { + wtrUsgRes.data = wtrUsgRes.data.filter((item: WtrUsgYmProps) => { + const month = item.levyYm?.substring(0, 6); + return month <= endYm; + }); + } + } + let rainEffectDay = 0; + res.data?.forEach(item2 => { + if (item2.infoRnDay == null || item2.infoRnDay.trim() == 'x') item2.infoRnDay = 0; + if(Number(item2.infoRnDay) >= 3) { + rainEffectDay = 2; + }else{ + rainEffectDay--; + } + + const month = item2.msrDt?.substring(4, 6); const monthIdx = month ? Number(month) - 1 : -1; if (monthIdx >= 0 && (monthIdx>=Number(startYm.substring(4,6))-1 && monthIdx <= Number(endYm.substring(4, 6))-1)) { if (typeof monthData[monthIdx] === 'object') { - monthData[monthIdx].sum += Number(item.inflAmnt); + monthData[monthIdx].sum += Number(item2.inflAmnt); // 유입량 합 monthData[monthIdx].cnt++; } else { - monthData[monthIdx] = {cnt:1, sum:Number(item.inflAmnt), yr:item.msrDt.substring(0,4), usege:0}; + monthData[monthIdx] = {cnt:1, sum:Number(item2.inflAmnt), yr:item2.msrDt.substring(0,4) + , usage:0, sunnyCnt:0, sunnyInflAmnt:0, sunnyAvgInflAmnt: 0, cntWtrUsg:0, sumWtrUsg:0, avgWtrUsg:0}; } - } - + } if(month >= startYm.substring(4, 6) && month <= endYm.substring(4, 6)){ cnt++; - tot += item.inflAmnt && item.inflAmnt !== 'x' ? Number(item.inflAmnt.toString().trim()) : 0; + tot += item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0; + } + if(rainEffectDay<0) { // 청천시 + if (typeof monthData[monthIdx] === 'object') { + monthData[monthIdx].sunnyInflAmnt += Number(item2.inflAmnt); // 청천 유입량 합 + monthData[monthIdx].sunnyCnt++; + }else { + monthData[monthIdx] = {cnt:1, sum:Number(item2.inflAmnt), yr:item2.msrDt.substring(0,4) + , usage:0, sunnyCnt:0, sunnyInflAmnt:0, sunnyAvgInflAmnt: 0, cntWtrUsg:0, sumWtrUsg:0, avgWtrUsg:0}; + } + if (month >= startYm.substring(4, 6) && month <= endYm.substring(4, 6)){ + sunnyCnt++; + sunnyTot += item2.inflAmnt && item2.inflAmnt !== 'x' ? Number(item2.inflAmnt.toString().trim()) : 0; + } } }); + // console.log(monthData); + // 물사용량 + let totWtrUsg = 0; + let cntWtrUsg = 0; + if (wtrUsgRes && wtrUsgRes.data && wtrUsgRes.data[bscFctCd]) { + wtrUsgRes.data.forEach((item: WtrUsgYmProps) => { + const month = item.levyYm?.substring(4, 6); + const monthIdx = month ? Number(month) - 1 : -1; + const days = getDaysInMonth(item.levyYm); + if (monthIdx >= 0) { + if (typeof monthData[monthIdx] === 'object') { + monthData[monthIdx].sumWtrUsg += Number(item.wtrUsg); + monthData[monthIdx].cntWtrUsg += days; + } + } + totWtrUsg += Number(item.wtrUsg); + cntWtrUsg += days; + }); + } + const tableData:UnderWaterInputModalProps[] = [] let maxWaterUsage = 0; let minWaterUsage = 9999999999; let avgWaterUsage = 0; + let maxSunnyInflAmnt = 0; + let minSunnyInflAmnt = 9999999999; + let avgSunnyInflAmnt = 0; monthData.forEach((item, index) => { - item.usege = item.sum/item.cnt + item.usage = item.sum/item.cnt; // 일평균 유입량 + item.avgWtrUsg = item.sum/item.cnt * 0.65; // 일평균 물사용량 + if (item.sumWtrUsg > 0 && item.cntWtrUsg > 0) item.avgWtrUsg = item.sumWtrUsg / item.cntWtrUsg; // 일평균 물사용량 + item.sunnyAvgInflAmnt = item.sunnyInflAmnt / item.sunnyCnt; // 청천 일평균 유입량 tableData.push({ msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)), - realSewageInput:Math.round(item.usege*1) /1, - sewageOccur:Math.round(item.usege*0.65*OSU_PERCENT * 1) / 1, - underWaterInput:Math.round((item.usege-(item.usege*0.65*OSU_PERCENT)) * 1) / 1, + realSewageInput:Math.round(item.sunnyAvgInflAmnt*1) /1, // 청천 실제 하수유입량 + sewageOccur:Math.round(item.avgWtrUsg*OSU_PERCENT * 1) / 1,// 오수발생량 + underWaterInput:Math.round((item.sunnyAvgInflAmnt-(item.avgWtrUsg*OSU_PERCENT)) * 1) / 1, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율) }) - if (item.usege > maxWaterUsage) { - maxWaterUsage = item.usege; - } - - if (item.usege < minWaterUsage) { - minWaterUsage = item.usege; - } - + if (item.avgWtrUsg > maxWaterUsage) maxWaterUsage = item.avgWtrUsg; + if (item.sunnyAvgInflAmnt > maxSunnyInflAmnt) maxSunnyInflAmnt = item.sunnyAvgInflAmnt; + if (item.avgWtrUsg < minWaterUsage) minWaterUsage = item.avgWtrUsg; + if (item.sunnyAvgInflAmnt < minSunnyInflAmnt) minSunnyInflAmnt = item.sunnyAvgInflAmnt; }); if(monthData.length == 0){ - maxWaterUsage = 0; - avgWaterUsage = 0; - minWaterUsage = 0; + maxWaterUsage = 0; minWaterUsage = 0; avgWaterUsage = 0; + maxSunnyInflAmnt = 0; minSunnyInflAmnt = 0; avgSunnyInflAmnt = 0; } - avgWaterUsage = tot/cnt; + avgWaterUsage = cnt>0? tot/cnt * 0.65:0; // 일평균 물사용량 + if (totWtrUsg > 0 && cntWtrUsg > 0) avgWaterUsage = totWtrUsg / cntWtrUsg; // 일평균 물사용량 + avgSunnyInflAmnt = (sunnyCnt>0)?sunnyTot/sunnyCnt:0; // 청천 일평균 유입량 + const newData= [ { msrDt: '평균', - realSewageInput:Math.round(avgWaterUsage*1) /1, - sewageOccur:Math.round(avgWaterUsage*0.65*OSU_PERCENT * 1) / 1, - underWaterInput: Math.round((avgWaterUsage-(avgWaterUsage*0.65*OSU_PERCENT)) * 1) / 1 + realSewageInput:Math.round(avgSunnyInflAmnt*1) /1, // 청천시 실제 하수유입량 + sewageOccur:Math.round(avgWaterUsage*OSU_PERCENT * 1) / 1, // 오수발생량 + underWaterInput: Math.round((avgSunnyInflAmnt-(avgWaterUsage*OSU_PERCENT)) * 1) / 1 // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율) //underWaterInput:Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.8)) * 100) / 100, }, { msrDt: '최대', - realSewageInput: Math.round(maxWaterUsage*1) /1, - sewageOccur: Math.round(maxWaterUsage*0.65*OSU_PERCENT * 1) / 1, - underWaterInput: Math.round((maxWaterUsage-(maxWaterUsage*0.65*OSU_PERCENT)) * 1) / 1, + realSewageInput: Math.round(maxSunnyInflAmnt*1) /1, // 청천시 실제 하수유입량 + sewageOccur: Math.round(maxWaterUsage*OSU_PERCENT * 1) / 1, // 오수발생량 + underWaterInput: Math.round((maxSunnyInflAmnt-(maxWaterUsage*OSU_PERCENT)) * 1) / 1, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율) }, { msrDt: '최소', - realSewageInput: Math.round(minWaterUsage*1) /1, - sewageOccur: Math.round(minWaterUsage*0.65*OSU_PERCENT * 1) / 1, - underWaterInput: Math.round((minWaterUsage-(minWaterUsage*0.65*OSU_PERCENT)) * 1) / 1, + realSewageInput: Math.round(minSunnyInflAmnt*1) /1, // 청천시 실제 하수유입량 + sewageOccur: Math.round(minWaterUsage*OSU_PERCENT * 1) / 1, // 오수발생량 + underWaterInput: Math.round((minSunnyInflAmnt-(minWaterUsage*OSU_PERCENT)) * 1) / 1, // 지하수 유입량 : 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율) }, ...tableData ] diff --git a/apps/fo/app/store/underWaterInput/types.tsx b/apps/fo/app/store/underWaterInput/types.tsx index fc0e13bb5..85be50e8e 100644 --- a/apps/fo/app/store/underWaterInput/types.tsx +++ b/apps/fo/app/store/underWaterInput/types.tsx @@ -19,6 +19,12 @@ export type UnderWaterProps = { properYn : string | '', // 적정여부 msrDt : string, // 측정일자 } + +export type WtrUsgYmProps = { + bscFctCd : string, // 처리구역시설코드 + levyYm : string, // 부과년월 + wtrUsg : number, // 월별 물사용량(m³/월) +} export interface UnderWaterInterface { bscFctCd : string, sidoNm : string,