diff --git a/apps/fo/.env.production b/apps/fo/.env.production index 797328765..a1da344b8 100644 --- a/apps/fo/.env.production +++ b/apps/fo/.env.production @@ -1,31 +1,32 @@ -# NEXT_PUBLIC_SITE_ID = WR -# NEXT_PUBLIC_PORT = 11301 -# NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11301 -# NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 +# NEXT_PUBLIC_SITE_ID = FO +# NEXT_PUBLIC_PORT = 11300 +# NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300 +# NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1 +# #NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 +# NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1 +# NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000 # NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver # NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver # NEXT_PUBLIC_CLAIM_NAME = Authorization # NEXT_PUBLIC_AUTH_USER_ID = token-id # NEXT_PUBLIC_ACCESS_TOKEN = access-token # NEXT_PUBLIC_REFRESH_TOKEN = refresh-token - - +# NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API NEXT_PUBLIC_SITE_ID = FO -NEXT_PUBLIC_PORT = 11300 -NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11300 -NEXT_PUBLIC_SERVER_API_URL = http://con.mind-one.co.kr:11082/api/v1 -#NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 -NEXT_PUBLIC_WR_SERVER_API_URL = http://con.mind-one.co.kr:11080/api/v1 -NEXT_PUBLIC_CS_SERVER_API_URL = http://dev.onasys.co.kr:8000 -#NEXT_PUBLIC_GEOSERVER_URL = http://rsone.iptime.org:10010/geoserver -NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver -NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver +NEXT_PUBLIC_PORT = 3000 +NEXT_PUBLIC_PROXY_HOST = https://fo.hasuon.or.kr +# NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000 +NEXT_PUBLIC_SERVER_API_URL = https://fo.hasuon.or.kr/operation-service/api/v1 +NEXT_PUBLIC_FO_SERVER_API_URL = https://apigateway.hasuon.or.kr/operation-service/api/v1 +NEXT_PUBLIC_CS_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000 +NEXT_PUBLIC_CS_TUS_UPLOAD = /attach-service/api/v1/tus/upload +NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver +NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl NEXT_PUBLIC_CLAIM_NAME = Authorization NEXT_PUBLIC_AUTH_USER_ID = token-id NEXT_PUBLIC_ACCESS_TOKEN = access-token NEXT_PUBLIC_REFRESH_TOKEN = refresh-token -NEXT_PUBLIC_NGII_URL = http://10.98.25.94:18080/openapi/Gettile.do?apiKey=BDE2BEF39DAFEC293AB6730150F222AC -NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api # 개발 서버 API - +NEXT_PUBLIC_WR_SERVER_API_URL = https://fo.hasuon.or.kr/reuse-service/api/v1 +NEXT_PUBLIC_SEWERAGE_API_URL = https://fo.hasuon.or.kr/sewerage-service/api \ No newline at end of file diff --git a/apps/fo/app/components/common/CalcRainEffect.tsx b/apps/fo/app/components/common/CalcRainEffect.tsx new file mode 100644 index 000000000..c35140d83 --- /dev/null +++ b/apps/fo/app/components/common/CalcRainEffect.tsx @@ -0,0 +1,73 @@ +/** + * 강우영향일 계산 로직 + * + * 1.강우영향일 및 강우량을 계산하며 강우량이 3이상이면 강우영향일이며 이후 이틀까지 강우영향일로 포함 + * + * 2.강우영향일이면서 3mm이하의 강우량일 경우에는 강우영향을 준 날의 강우량을 따름 + * @param data + * @param weather (default:ALL), SUNNY, ..etc + * @author jsyang + */ + +export default function CalcRainEffect(data : any, weather='ALL') { + console.log("%c Calculate RainEffect !" , "background:blue;color:white"); + console.log("%c Data Length :"+data.length+" Weather : "+weather , "background:yellow;color:blue"); + // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) + for(let idx = 0; idx < data.length; idx++) { + const item = data[idx]; + if(item){ + if(item.infoRnDay && Number(item.infoRnDay) >= 3) { + item.rainEffectDay = 1; + } else { + item.rainEffectDay = 0; + } + + if(item.infoRnDay == 'x'){ + item.infoRnDay = '0.0'; + item.toBeInfoRnDay = '0.0'; + }else{ + item.infoRnDay = Number(item.infoRnDay).toFixed(1); + item.toBeInfoRnDay = Number(item.infoRnDay).toFixed(1); + } + } + } + + // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 + for(let idx = 0; idx < data.length; idx++) { + if(data[idx]) { + // 하루 전이 강우영향일(3 이상)인 경우 + if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) { + data[idx]!.rainEffectDay = 1; + } + // 이틀 전이 강우영향일(3 이상)인 경우 + if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) { + data[idx]!.rainEffectDay = 1; + } + } + } + + for(let idx = 0; idx < data.length; idx++) { + if(data[idx] && data[idx]?.rainEffectDay === 1) { + if(idx > 1){ + 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){ + 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; + } + } + } + } + + let rtnData : any = []; + if (weather === 'ALL') { + rtnData = data; + } else if (weather === 'SUNNY') { + rtnData = data.filter((item: any) => item.rainEffectDay === 0); + } else { + rtnData = data.filter((item: any) => item.rainEffectDay === 1); + } + return rtnData; +} \ No newline at end of file diff --git a/apps/fo/app/components/common/DataForm.tsx b/apps/fo/app/components/common/DataForm.tsx index c478826f0..48b428e32 100644 --- a/apps/fo/app/components/common/DataForm.tsx +++ b/apps/fo/app/components/common/DataForm.tsx @@ -39,7 +39,7 @@ export default function DataForm({ type, column, item }: DataFormProps) { break; case 'float0': if(value) { - item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1) / 1).split('.').map((part, index) => + item[column] = item[column] = String(value).includes('.')?String(Math.round(parseFloat(value.toString().replace(/,/g, '')) * 1) / 1).split('.').map((part, index) => index === 0 ? part.replace(/\B(?=(\d{3})+(?!\d))/g, ",") : part ).join('.') : String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ","); diff --git a/apps/fo/app/components/common/FacilityTermModalHeader.tsx b/apps/fo/app/components/common/FacilityTermModalHeader.tsx index d856e233f..52cee2ea3 100644 --- a/apps/fo/app/components/common/FacilityTermModalHeader.tsx +++ b/apps/fo/app/components/common/FacilityTermModalHeader.tsx @@ -97,26 +97,27 @@ export default function FacilityTermModalHeader({ const startDateOnly = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()); const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()); const rainEffectDay = (item as T & { rainEffectDay: number }).rainEffectDay; + if(flowPanel === '2'){ - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; + const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 3 && infoRnDay < 10; } else if(flowPanel === '3'){ - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; + const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 10 && infoRnDay < 20; } else if(flowPanel === '4'){ - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; + const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 20 && infoRnDay < 30; } else if(flowPanel === '5'){ - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; + const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 30 && infoRnDay < 40; } else if(flowPanel === '6'){ - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; + const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 40 && infoRnDay < 50; } else if(flowPanel === '7'){ - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; + const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 50 && infoRnDay < 60; } else if(flowPanel === '8'){ - const infoRnDay = (item as T & { infoRnDay: number }).infoRnDay; + const infoRnDay = (item as T & { toBeInfoRnDay: number }).toBeInfoRnDay; return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && infoRnDay >= 60; } else { return (itemDateOnly >= startDateOnly && itemDateOnly <= endDateOnly) && (rainEffectDay ===1); diff --git a/apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/modal/page.tsx b/apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/modal/page.tsx index 94bc28500..c482e8b7c 100644 --- a/apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/modal/page.tsx @@ -69,22 +69,12 @@ export default function DashBoardChartModal({item='', period='', title='',modalD useEffect(() => { if(period === 'year'){ const filteredData: yearProps[] = modalData.map((item) => { - if(waterQlty.trim().includes('T-N') || waterQlty.trim().includes('T-P')){ return { label: item.waterQlty, - 평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')).toFixed(3) : (item.yearAvg || 0), - 최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')).toFixed(3) : (item.yearMax || 0), - 최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')).toFixed(3) : (item.yearMin || 0), + 평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')) : (item.yearAvg || 0), + 최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')) : (item.yearMax || 0), + 최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')) : (item.yearMin || 0), } - } - else{ - return { - label: item.waterQlty, - 평균: typeof item.yearAvg === 'string' ? Number(item.yearAvg.replace(/,/g, '')).toFixed(1) : (item.yearAvg || 0), - 최대: typeof item.yearMax === 'string' ? Number(item.yearMax.replace(/,/g, '')).toFixed(1) : (item.yearMax || 0), - 최소: typeof item.yearMin === 'string' ? Number(item.yearMin.replace(/,/g, '')).toFixed(1) : (item.yearMin || 0), - } - } }) if (item === 'flowRate') { setChartData(filteredData.slice(0,5)); diff --git a/apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/page.tsx b/apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/page.tsx index 85aea5ea6..fa2a97d9e 100644 --- a/apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/page.tsx +++ b/apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/page.tsx @@ -182,7 +182,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: useEffect(() => { operationalStatusList.map((item: { [key: string]: string | number | boolean },index) => { if(index===8 || index===9 || index===10 || index===11 || index===12 || index===13 || index===14 || index===15){ - item['yearAvg'] = Number(item['yearAvg']).toFixed(3); + /* item['yearAvg'] = Number(item['yearAvg']).toFixed(3); item['yearMax'] = item['yearMax']+'%'; item['yearMin'] = item['yearMin']+'%'; item['summerAll'] = item['summerAll']+'%'; @@ -191,7 +191,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}: item['winterAll'] = item['winterAll']+'%'; item['winterSunnyAvg'] = item['winterSunnyAvg']+'%'; item['winterSunnyMax'] = item['winterSunnyMax']+'%'; - item['winterSunnyMin'] = item['winterSunnyMin']+'%'; + item['winterSunnyMin'] = item['winterSunnyMin']+'%'; */ } }); diff --git a/apps/fo/app/pages/(with-layout)/dashboard/maingraph/page.tsx b/apps/fo/app/pages/(with-layout)/dashboard/maingraph/page.tsx index 375cdbbdf..3f193e035 100644 --- a/apps/fo/app/pages/(with-layout)/dashboard/maingraph/page.tsx +++ b/apps/fo/app/pages/(with-layout)/dashboard/maingraph/page.tsx @@ -22,10 +22,12 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili const [chart_tpTp, setChart_tpTp] = useState<{ chartData1: lineChartDataProps[]; chartData2: lineChartDataProps[]; + chartData3: lineChartDataProps[]; }>(); const [chart_tntn, setChart_tntn] = useState<{ chartData1: lineChartDataProps[]; chartData2: lineChartDataProps[]; + chartData3: lineChartDataProps[]; }>(); const [chart_inflBodInflTn, setChart_inflBodInflTn] = useState<{ chartData1: lineChartDataProps[]; @@ -46,6 +48,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili chart_efflTn, chart_inflBod, isLoadingMainGraph, + waterQltyStandartd, } = MainGraph; /** @@ -90,6 +93,10 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili label: '방류T-P', color: colors[1], }, + chartData3: { + label : '법적방류T-P', + color : 'blackdash', + } } satisfies ChartConfig; // 유입T-N-방류T-N @@ -102,6 +109,10 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili label: '방류T-N', color: colors[1], }, + chartData3: { + label : '법적방류T-N', + color : 'blackdash', + } } satisfies ChartConfig; // 유입BOD-유입T-N @@ -139,21 +150,37 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili useEffect(() => { if (!chart_chongInTp || !chart_efflTp) return; + const legalTpData: lineChartDataProps[] = []; + if (waterQltyStandartd){ + chart_inflTn.forEach(item =>{ + legalTpData.push({label : item.label, val:waterQltyStandartd.tp}); + }) + } + const chartTpTpData = { chartData1: chart_chongInTp, - chartData2: chart_efflTp + chartData2: chart_efflTp, + chartData3: legalTpData }; setChart_tpTp(chartTpTpData); - }, [chart_chongInTp, chart_efflTp]); + }, [chart_chongInTp, chart_efflTp, chart_inflTn, waterQltyStandartd]); useEffect(() => { if (!chart_inflTn || !chart_efflTn) return; + const legalTnData: lineChartDataProps[] = []; + if (waterQltyStandartd){ + chart_inflTn.forEach(item =>{ + legalTnData.push({label : item.label, val:waterQltyStandartd.tn}); + }) + } + const chartTntnData = { chartData1: chart_inflTn, - chartData2: chart_efflTn + chartData2: chart_efflTn, + chartData3: legalTnData, }; setChart_tntn(chartTntnData); - }, [chart_inflTn, chart_efflTn]); + }, [chart_inflTn, chart_efflTn, waterQltyStandartd]); useEffect(() => { if (!chart_inflBod || !chart_inflTn) return; @@ -185,21 +212,21 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili - + - + - + @@ -207,7 +234,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili - + @@ -215,7 +242,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili - + @@ -223,7 +250,7 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili - + diff --git a/apps/fo/app/pages/(with-layout)/dashboard/page.tsx b/apps/fo/app/pages/(with-layout)/dashboard/page.tsx index 0903c9229..2003addee 100644 --- a/apps/fo/app/pages/(with-layout)/dashboard/page.tsx +++ b/apps/fo/app/pages/(with-layout)/dashboard/page.tsx @@ -9,6 +9,7 @@ import ProcessFacilitySearch from "./facilityInfo/page"; import DashBoardChart from "./maingraph/page"; import RainManageTab from "./rainManage/page"; import DrainageEquipment from "./drainageEquipment/page"; +import { roundNumber } from "@/app/components/common/DataForm"; const tabList = [ { value: 'facilityInfo', label: '시설정보 및 운영현황' }, @@ -17,6 +18,22 @@ const tabList = [ //{ value: 'drainageEquipment', label: '배수설비 정비현황' } ]; +export const generateYearDates = (searchYear: string) => { + const dates: string[] = []; + const start = new Date(Number(searchYear), 0, 1); // 1월 1일 + const end = new Date(Number(searchYear), 11, 31); // 12월 31일 + + for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) { + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, "0"); + const day = String(d.getDate()).padStart(2, "0"); + + dates.push(`${year}-${month}-${day}`); // YYYY-MM-DD 형식 + } + + return dates; +} + export default function DashBoard() { // 입력값 상태 관리 const { Common, initializeCommonData,searchMainGraph, searchRainManage, searchOperationStatus, OperationStatus, RainManage, MainGraph, PlanFclty } = useFoStore((state) => state); @@ -60,11 +77,11 @@ export default function DashBoard() { const [searchYear, setSearchYear] = useState(selectSearchYear[0]?.val || '0'); // 시설명 const [fcltyList, setFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({ - bscFctCd: '26260PB001R', - bscFctNm: '수영', - fcltyCpc: 452000, - trtFrfNm: '표준활성슬러지법, MLE, MBR', - efflWqltStndrdNm: '500톤 이상(Ⅳ지역)' + bscFctCd: '11000SW001R', + bscFctNm: '난지', + fcltyCpc: 860000, + trtFrfNm: '표준활성슬러지법, MLE, A2O', + efflWqltStndrdNm: '500톤 이상(Ⅲ지역)' }); const [searchFcltyList, setSearchFcltyList] = useState<{bscFctCd: string, bscFctNm: string, fcltyCpc: number | '', trtFrfNm: string | '', efflWqltStndrdNm: string | ''}>({ @@ -79,11 +96,11 @@ export default function DashBoard() { if (!isInit) { initializeCommonData(); setSearchFcltyList({ - bscFctCd: '26260PB001R', - bscFctNm: '수영', - fcltyCpc: 452000, - trtFrfNm: '표준활성슬러지법, MLE, MBR', - efflWqltStndrdNm: '500톤 이상(Ⅳ지역)' + bscFctCd: '11000SW001R', + bscFctNm: '난지', + fcltyCpc: 860000, + trtFrfNm: '표준활성슬러지법, MLE, A2O', + efflWqltStndrdNm: '500톤 이상(Ⅲ지역)' }); } }, [isInit, initializeCommonData]); @@ -190,62 +207,98 @@ export default function DashBoard() { case 'mainGraph': searchMainGraph(searchYear, fcltyList.bscFctCd); + const yearData = generateYearDates(searchYear); + const yearValueData : any = []; + + for (const i in yearData){ + const rowArray: string[] = []; + rowArray.push(yearData[i] ?? ""); + //강수량 + rowArray.push(roundNumber(chart_inflowRain.filter(item=>{return yearData[i] === item.label})[0]?.barVal0?.toString(), 1) || ''); + //유입하수량 + rowArray.push(roundNumber(chart_inflowRain.filter(item=>{return yearData[i] === item.label})[0]?.lineVal1?.toString(), 0) || ''); + //시설용량 + rowArray.push(roundNumber(chart_inflowRain.filter(item=>{return yearData[i] === item.label})[0]?.lineVal0?.toString(), 0) || ''); + //유입BOD + rowArray.push(roundNumber(chart_bodRain.filter(item=>{return yearData[i] === item.label})[0]?.lineVal0?.toString(), 1) || ''); + //유입T-P + rowArray.push(roundNumber(chart_inflTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || ''); + //총인유입T-P + rowArray.push(roundNumber(chart_chongInTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || ''); + //방류T-P + rowArray.push(roundNumber(chart_efflTp.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || ''); + //유입T-N + rowArray.push(roundNumber(chart_inflTn.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || ''); + //방류T-N + rowArray.push(roundNumber(chart_efflTn.filter(item=>{return yearData[i] === item.label})[0]?.val?.toString(), 3) || ''); + + yearValueData.push( + rowArray + ) + } + /* const excelData = [['날짜', '강수량', '유입하수량','시설용량', '유입BOD', '유입T-P', '총인유입T-P', '방류T-P'], */ const sheetParameter = [ { - data: [['날짜', '강수량'],...chart_inflowRain.map((item) => [item.label, item.barVal0])], + data: [['날짜', '강수량', '유입하수량', '시설용량', '유입BOD', '유입T-P','총인유입T-P', '방류T-P', '유입T-N', '방류T-N'],...yearValueData], + headerNum: 1, + headerRange: 'A1:J1', + sheetName: '주요그래프' + } + /* { + data: [['날짜', '강수량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.barVal0, 1)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '강수량' }, { - data: [['날짜', '유입하수량'],...chart_inflowRain.map((item) => [item.label, item.lineVal1])], + data: [['날짜', '유입하수량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.lineVal1, 0)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '유입하수량' }, { - data: [['날짜', '시설용량'],...chart_inflowRain.map((item) => [item.label, item.lineVal0])], + data: [['날짜', '시설용량'],...chart_inflowRain.map((item) => [item.label, roundNumber(item.lineVal0, 0)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '시설용량' }, { - data: [['날짜', '유입BOD'],...chart_bodRain.map((item) => [item.label, item.lineVal0])], + data: [['날짜', '유입BOD'],...chart_bodRain.map((item) => [item.label, roundNumber(item.lineVal0, 1)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '유입BOD' }, { - data: [['날짜', '유입T-P'],...chart_inflTp.map((item) => [item.label, item.val])], + data: [['날짜', '유입T-P'],...chart_inflTp.map((item) => [item.label, roundNumber(item.val, 3)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '유입T-P' }, { - data: [['날짜', '총인유입T-P'],...chart_chongInTp.map((item) => [item.label, item.val])], + data: [['날짜', '총인유입T-P'],...chart_chongInTp.map((item) => [item.label, roundNumber(item.val, 3)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '총인유입T-P' }, { - data: [['날짜', '방류T-P'],...chart_efflTp.map((item) => [item.label, item.val])], + data: [['날짜', '방류T-P'],...chart_efflTp.map((item) => [item.label, roundNumber(item.val, 3)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '방류T-P' }, { - data: [['날짜', '유입T-N'],...chart_inflTn.map((item) => [item.label, item.val])], + data: [['날짜', '유입T-N'],...chart_inflTn.map((item) => [item.label, roundNumber(item.val, 3)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '유입T-N' }, { - data: [['날짜', '방류T-N'],...chart_efflTn.map((item) => [item.label, item.val])], + data: [['날짜', '방류T-N'],...chart_efflTn.map((item) => [item.label, roundNumber(item.val, 3)])], headerNum: 1, headerRange: 'A1:B1', sheetName: '방류T-N' - } + } */ ]; downloadMultipleExcel('주요그래프', sheetParameter); @@ -265,22 +318,22 @@ export default function DashBoard() { const initVal = () => { setFcltyList({ - bscFctCd: '26260PB001R', - bscFctNm: '수영', - fcltyCpc: 452000, - trtFrfNm: '표준활성슬러지법, MLE, MBR', - efflWqltStndrdNm: '500톤 이상(Ⅳ지역)' + bscFctCd: '11000SW001R', + bscFctNm: '난지', + fcltyCpc: 860000, + trtFrfNm: '표준활성슬러지법, MLE, A2O', + efflWqltStndrdNm: '500톤 이상(Ⅲ지역)' }); setSearchFcltyList({ - bscFctCd: '26260PB001R', - bscFctNm: '수영', - fcltyCpc: 452000, - trtFrfNm: '표준활성슬러지법, MLE, MBR', - efflWqltStndrdNm: '500톤 이상(Ⅳ지역)' + bscFctCd: '11000SW001R', + bscFctNm: '난지', + fcltyCpc: 860000, + trtFrfNm: '표준활성슬러지법, MLE, A2O', + efflWqltStndrdNm: '500톤 이상(Ⅲ지역)' }); setSearchYear(selectSearchYear[0]?.val || '0'); - searchFcltyList.bscFctNm = '수영'; + searchFcltyList.bscFctNm = '난지'; setSidoValue('0'); setSigunValue('0'); diff --git a/apps/fo/app/pages/(with-layout)/dashboardMain/page.tsx b/apps/fo/app/pages/(with-layout)/dashboardMain/page.tsx index 71372672a..12bf0763c 100644 --- a/apps/fo/app/pages/(with-layout)/dashboardMain/page.tsx +++ b/apps/fo/app/pages/(with-layout)/dashboardMain/page.tsx @@ -12,7 +12,7 @@ export default function DashBoardFclty({ onFacilityChange, sidoSigun, facilityNm } = Common; // 시설명 - const [bscFctNm, setFcltyName] = useState(facilityNm || '수영'); + const [bscFctNm, setFcltyName] = useState(facilityNm || '난지'); const [bscFctCd, setbscFctCd] = useState('11000SW001R'); const [fcltyCpc, setFcltyCpc] = useState(860000); const [trtFrfNm, setTrtFrfNm] = useState('표준활성슬러지법, MLE, A2O'); diff --git a/apps/fo/app/pages/(with-layout)/facilityPrecipitation/modal/page.tsx b/apps/fo/app/pages/(with-layout)/facilityPrecipitation/modal/page.tsx index 5a8e77dcd..bb430d0ba 100644 --- a/apps/fo/app/pages/(with-layout)/facilityPrecipitation/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/facilityPrecipitation/modal/page.tsx @@ -1,9 +1,11 @@ "use client" +import CalcRainEffect from "@/app/components/common/CalcRainEffect"; +import { roundNumber } from "@/app/components/common/DataForm"; import { useFoStore } from "@/app/store"; import type { PrecipitationPropsDetailProps } from "@/app/store/facilityPrecipitation"; -import { DatePickerRange, UiTable } from "@common/business_components/ui"; +import { DatePickerRange, downloadExcel, UiTable } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; -import { Table, TableCell, TableHead, TableRow } from "@common/components/ui"; +import { Button, Table, TableCell, TableHead, TableRow } from "@common/components/ui"; import { useEffect, useRef, useState } from "react"; type PrecipitationModalProps = { @@ -19,16 +21,17 @@ type DateRange = { } export default function PrecipitationModal(props: PrecipitationModalProps) { - const { PrecipitationDetail } = useFoStore((state) => state); + const { Common, PrecipitationDetail } = useFoStore((state) => state); const { upHeadListPrecipitationDetail } = PrecipitationDetail; - + const { btnClass } = Common; // Refs const startPickerRef = useRef(null); const endPickerRef = useRef(null); // States - const [startDate, setStartDate] = useState(null); - const [endDate, setEndDate] = useState(null); + const [startDate, setStartDate] = useState(new Date()); + const [endDate, setEndDate] = useState(new Date()); + const didInit = useRef(false); const [filteredDetailList, setFilteredDetailList] = useState([]); const [copyDetailList, setCopyDetailList] = useState([]); @@ -113,17 +116,20 @@ export default function PrecipitationModal(props: PrecipitationModalProps) { }; useEffect(() => { + if(didInit.current) return; + if (props.detailList.length > 0) { - const filteredList = props.detailList.filter((item) => - props.facilityCd === item.bscFctCd - ); - - setFilteredDetailList(filteredList); - setCopyDetailList(filteredList); - - if (filteredList.length > 0) { - const firstDateStr = filteredList[0]?.rainDt; - const lastDateStr = filteredList[filteredList.length - 1]?.rainDt; + didInit.current = true; + const filteredList = props.detailList + .map(i => ({ ...i })) // ← 얕은 복제 + .filter((item) => props.facilityCd === item.bscFctCd); + const calcData = CalcRainEffect(filteredList); + + setFilteredDetailList(calcData); + setCopyDetailList(calcData); + if (calcData.length > 0) { + const firstDateStr = calcData[0]?.rainDt; + const lastDateStr = calcData[calcData.length - 1]?.rainDt; if (firstDateStr) { const firstDate = new Date(firstDateStr); @@ -131,7 +137,6 @@ export default function PrecipitationModal(props: PrecipitationModalProps) { setStartDate(firstDate); } } - if (lastDateStr) { const lastDate = new Date(lastDateStr); if (!isNaN(lastDate.getTime())) { @@ -142,8 +147,24 @@ export default function PrecipitationModal(props: PrecipitationModalProps) { } }, [props.detailList, props.facilityCd]); - if (!startDate || !endDate) { - return
로딩 중...
; + const excelDownload = () => { + const totData = getTableData(); + const excelDownList: any[] = []; + if(totData.length > 0){ + totData.forEach((item) => { + excelDownList.push({ + "날짜": item.rainDt, + "강수량(mm/일)": roundNumber(item.infoRnDay, 1), + "강우일(일)": roundNumber(item.rainDay, 0), + "강우영향일(일)": roundNumber(item.rainEffectDay, 0), + }); + }); + } + if (excelDownList && excelDownList.length > 0) { + downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 강수현황', sheetNameArray: ['지하수유입량'], headerRange: 'A1:D1' }); + } else if (totData.length == 0) { + alert('다운받을 데이터가 없습니다.'); + } } return ( @@ -187,6 +208,9 @@ export default function PrecipitationModal(props: PrecipitationModalProps) { + { if (excelList && excelList.length > 0) { @@ -153,14 +153,6 @@ export default function FacilityPrecipitation() { */ // 조회 const searchFacilityPrecipitation = useCallback(({ partValue, regionValue, unitWaterShedValue, middleRegionValue, envPartValue, sidoValue, sigunValue }: ReturnType, pageNo: number, pageCnt:number=20) => { - console.log('partValue : ', partValue); - console.log('regionValue : ', regionValue); - console.log('unitWaterShedValue : ', unitWaterShedValue); - console.log('middleRegionValue : ', middleRegionValue); - console.log('envPartValue : ', envPartValue); - console.log('sidoValue : ', sidoValue); - console.log('sigunValue : ', sigunValue); - let nameCd, partStr switch (partValue) { case 'R': diff --git a/apps/fo/app/pages/(with-layout)/facilityWaterQlty/modal/page.tsx b/apps/fo/app/pages/(with-layout)/facilityWaterQlty/modal/page.tsx index 0362b1ec3..d7cad3367 100644 --- a/apps/fo/app/pages/(with-layout)/facilityWaterQlty/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/facilityWaterQlty/modal/page.tsx @@ -7,6 +7,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import type { ReturnType } from "../../../../components/common/FacilityTermModalHeader"; import FacilityTermModalHeader from "../../../../components/common/FacilityTermModalHeader"; import { HeadMakeColSpan } from "../HeadMakeColSpan"; +import { roundNumber } from "@/app/components/common/DataForm"; type ModalProps ={ fcltyName: string; @@ -74,8 +75,10 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe let maxTpInflWqltBod = 0; let maxTpInflWqltTp = 0; + let maxNoProcessInflAmnt = 0; let maxInfoRnDay = 0; + // 초기값 설정 let minEfflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltBod) : 0; let minEfflWqltTn = filteredData.length > 0 ? parseNumber(filteredData[0]?.efflWqltTn) : 0; @@ -89,9 +92,9 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe let mininflAssctBfrWqltToc = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltToc) : 0; let mininflAssctBfrWqltSs = filteredData.length > 0 ? parseNumber(filteredData[0]?.inflAssctBfrWqltSs) : 0; - let minTpInflWqltBod = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltBod) : 0; - let minTpInflWqltTp = filteredData.length > 0 ? parseNumber(filteredData[0]?.tpInflWqltTp) : 0; - + let minTpInflWqltBod = 99999999; + let minTpInflWqltTp = 99999999; + let minNoProcessInflAmnt = 99999999; let minInfoRnDay = filteredData.length > 0 ? parseNumber(filteredData[0]?.infoRnDay) : 0; let avgEfflWqltBod = 0; @@ -108,6 +111,10 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe let avgTpInflWqltBod = 0; let avgTpInflWqltTp = 0; + let tpInflWqltBodCnt = 0; + let tpInflWqltTpCnt = 0; + let avgNoProcessInflAmnt = 0; + let noProcessInflAmntCnt = 0; let avgInfoRnDay = 0; @@ -117,16 +124,20 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe const efflWqltTp = parseNumber(item.efflWqltTp); const efflWqltToc = parseNumber(item.efflWqltToc); const efflWqltSs = parseNumber(item.efflWqltSs); - const inflAssctBfrWqltBod = parseNumber(item.inflAssctBfrWqltBod); const inflAssctBfrWqltTn = parseNumber(item.inflAssctBfrWqltTn); const inflAssctBfrWqltTp = parseNumber(item.inflAssctBfrWqltTp); const inflAssctBfrWqltToc = parseNumber(item.inflAssctBfrWqltToc); const inflAssctBfrWqltSs = parseNumber(item.inflAssctBfrWqltSs); - const tpInflWqltBod = parseNumber(item.tpInflWqltBod); const tpInflWqltTp = parseNumber(item.tpInflWqltTp); + if(item.tpInflWqltBod != null && item.tpInflWqltBod.trim() != '' && item.tpInflWqltBod != undefined ){ + tpInflWqltBodCnt += 1; + } + if(item.tpInflWqltTp != null && item.tpInflWqltTp.trim() != '' && item.tpInflWqltTp != undefined ){ + tpInflWqltTpCnt += 1; + } const infoRnDay = parseNumber(item.infoRnDay); @@ -159,8 +170,14 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe mininflAssctBfrWqltToc = Math.min(mininflAssctBfrWqltToc, inflAssctBfrWqltToc); mininflAssctBfrWqltSs = Math.min(mininflAssctBfrWqltSs, inflAssctBfrWqltSs); - minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod); - minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp); + if(item.tpInflWqltBod != null && item.tpInflWqltBod.trim() != '' && item.tpInflWqltBod != undefined ){ + minTpInflWqltBod = Math.min(minTpInflWqltBod, tpInflWqltBod); + avgTpInflWqltBod += tpInflWqltBod; + } + if(item.tpInflWqltTp != null && item.tpInflWqltTp.trim() != '' && item.tpInflWqltTp != undefined ){ + minTpInflWqltTp = Math.min(minTpInflWqltTp, tpInflWqltTp); + avgTpInflWqltTp += tpInflWqltTp; + } minInfoRnDay = Math.min(minInfoRnDay, infoRnDay); @@ -176,8 +193,13 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe avginflAssctBfrWqltToc += inflAssctBfrWqltToc; avginflAssctBfrWqltSs += inflAssctBfrWqltSs; - avgTpInflWqltBod += tpInflWqltBod; - avgTpInflWqltTp += tpInflWqltTp; + if(item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined){ + const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',','')); + avgNoProcessInflAmnt += noProcessInflAmnt; + maxNoProcessInflAmnt = Math.max(maxNoProcessInflAmnt, noProcessInflAmnt); + minNoProcessInflAmnt = Math.min(minNoProcessInflAmnt, noProcessInflAmnt); + noProcessInflAmntCnt +=1; + } avgInfoRnDay += infoRnDay; }); @@ -202,9 +224,10 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe sggNm: "", addr: "", fctCpc: 0, + noProcessInflAmnt : roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0), infoRnDay: filteredData.length==0?'0.0':(Math.round(avgInfoRnDay / filteredData.length * 10) / 10).toFixed(1), - tpInflWqltBod: filteredData.length==0?'0.0':(Math.round(avgTpInflWqltBod / filteredData.length * 10) / 10).toFixed(1), - tpInflWqltTp: filteredData.length==0?'0.000':(Math.round(avgTpInflWqltTp / filteredData.length * 1000) / 1000).toFixed(3) + tpInflWqltBod: filteredData.length==0?'0.0':(Math.round(avgTpInflWqltBod / tpInflWqltBodCnt * 10) / 10).toFixed(1), + tpInflWqltTp: filteredData.length==0?'0.000':(Math.round(avgTpInflWqltTp / tpInflWqltTpCnt * 1000) / 1000).toFixed(3) }, { msrDt : '최대', @@ -225,14 +248,15 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe sggNm: "", addr: "", fctCpc: 0, - infoRnDay: 0, + noProcessInflAmnt : roundNumber(maxNoProcessInflAmnt, 0), + infoRnDay: Math.round(maxInfoRnDay * 10) / 10?(Math.round(maxInfoRnDay * 10) / 10).toFixed(1):'0.0', tpInflWqltBod: Math.round(maxTpInflWqltBod * 10) / 10?(Math.round(maxTpInflWqltBod * 10) / 10).toFixed(1):'0.0', tpInflWqltTp: Math.round(maxTpInflWqltTp * 1000) / 1000?(Math.round(maxTpInflWqltTp * 1000) / 1000).toFixed(3):'0.000' }, { msrDt : '최소', - efflWqltBod : Math.round(minEfflWqltBod * 10) / 10?(Math.round(minEfflWqltBod?minEfflWqltBod:0 * 10) / 10).toFixed(1) : '0.0', - efflWqltToc : Math.round(minefflWqltToc * 10) / 10?(Math.round(minefflWqltToc?minefflWqltToc:0 * 10) / 10).toFixed(1) : '0.0', + efflWqltBod : Math.round(minEfflWqltBod * 10) / 10?(Math.round(minEfflWqltBod * 10) / 10).toFixed(1) : '0.0', + efflWqltToc : Math.round(minefflWqltToc * 10) / 10?(Math.round(minefflWqltToc * 10) / 10).toFixed(1) : '0.0', efflWqltSs : Math.round(minEfflWqltSs * 10) / 10?(Math.round(minEfflWqltSs * 10) / 10).toFixed(1) : '0.0', efflWqltTn : Math.round(minEfflWqltTn * 1000) / 1000?(Math.round(minEfflWqltTn * 1000) / 1000).toFixed(3) : '0.000', efflWqltTp : Math.round(minEfflWqltTp * 1000) / 1000?(Math.round(minEfflWqltTp * 1000) / 1000).toFixed(3) : '0.000', @@ -248,12 +272,14 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe sggNm: "", addr: "", fctCpc: 0, - infoRnDay: 0, - tpInflWqltBod: Math.round(minTpInflWqltBod * 10) / 10?'0.0':(Math.round(minTpInflWqltBod * 10) / 10).toFixed(1), - tpInflWqltTp: Math.round(minTpInflWqltTp * 1000) / 1000?'0.000':(Math.round(minTpInflWqltTp * 1000) / 1000).toFixed(3) + noProcessInflAmnt : roundNumber(minNoProcessInflAmnt, 0), + infoRnDay: Math.round(minInfoRnDay * 10) / 10?'0.0':(Math.round(minInfoRnDay * 10) / 10).toFixed(1), + tpInflWqltBod: Math.round(minTpInflWqltBod * 10) / 10 && minTpInflWqltBod != 99999999?(Math.round(minTpInflWqltBod * 10) / 10).toFixed(1):'0.0', + tpInflWqltTp: Math.round(minTpInflWqltTp * 1000) / 1000 && minTpInflWqltTp != 99999999?(Math.round(minTpInflWqltTp * 1000) / 1000).toFixed(3):'0.000' }, ...filteredData ]; + return newFilteredData; } @@ -380,7 +406,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe ref={ref} queryClick={filterData} /> -
+
+
+ ☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​

+ ☞ 음수값 발생시 제외(null, 평균값 산정시 제외)

+
@@ -407,34 +437,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe ref={ref} queryClick={filterData} /> -
- {}} - className="h-[500px]" - boldArray={[0,1,2]} - > - - -
-
- - - - searchList={facilityWaterQltyYearList} - fcltyCd={facilityCd} - fcltyName={fcltyName} - tabName="tab_term_chuncheon" - searchYear={searchYear} - ref={ref} - queryClick={filterData} - /> -
+
+ ☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​

+ ☞ 음수값 발생시 제외(null, 평균값 산정시 제외)

+
+ + + + + searchList={facilityWaterQltyYearList} + fcltyCd={facilityCd} + fcltyName={fcltyName} + tabName="tab_term_chuncheon" + searchYear={searchYear} + ref={ref} + queryClick={filterData} + /> +
+ {}} + className="h-[500px]" + boldArray={[0,1,2]} + > + + +
+
+ ☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​

+ ☞ 음수값 발생시 제외(null, 평균값 산정시 제외)

☞ 청천시 : 강우량이 3mm미만의 날
@@ -464,7 +500,7 @@ export default function WaterQualityModal({fcltyName='', facilityCd='', searchYe ref={ref} queryClick={filterData} /> -
+
+ ☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​

+ ☞ 음수값 발생시 제외(null, 평균값 산정시 제외)

☞ 강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날
diff --git a/apps/fo/app/pages/(with-layout)/facilityWaterQlty/page.tsx b/apps/fo/app/pages/(with-layout)/facilityWaterQlty/page.tsx index 0e215f565..98f5ba57a 100644 --- a/apps/fo/app/pages/(with-layout)/facilityWaterQlty/page.tsx +++ b/apps/fo/app/pages/(with-layout)/facilityWaterQlty/page.tsx @@ -134,7 +134,7 @@ export default function ProcessFacilitySearch() { initializeCommonData(); searchFacilityWaterQltyList(1, 10, selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchFacilityWaterQltyList]); + }, [isInit, initializeCommonData, searchFacilityWaterQltyList, selectSearchYear]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -163,7 +163,6 @@ export default function ProcessFacilitySearch() { }, [searchFcltyQltyList]); const total = facilityWaterQltyCount || 1; - console.log('total : ', total); return ( diff --git a/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx b/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx index 0685f93d6..5a38ad8f0 100644 --- a/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/flowRate/modal/page.tsx @@ -7,6 +7,7 @@ import { Button, TabsContent } from "@common/components/ui"; import { useCallback, useEffect, useRef, useState } from "react"; import type { ReturnType } from "../../../../components/common/FacilityTermModalHeader"; import { roundUp } from "@/app/store/common"; +import { roundNumber } from "@/app/components/common/DataForm"; const tabList = [ { value: 'tab_term_year', label: '연간' }, @@ -59,6 +60,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st let maxreturnAmnt = 0; let maxefflAmnt = 0; let maxinfoRnDay = 0; + let maxNoProcessInflAmnt = 0; // 초기값 설정 let mintotInflAmnt = parseNumber(filteredData[0]?.totInflAmnt); @@ -67,6 +69,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st let minreturnAmnt = parseNumber(filteredData[0]?.returnAmnt); let minefflAmnt = parseNumber(filteredData[0]?.efflAmnt); let mininfoRnDay = parseNumber(filteredData[0]?.infoRnDay && filteredData[0]?.infoRnDay.toString().trim() !== 'x' ? filteredData[0]?.infoRnDay.toString().trim() : 0); + let minNoProcessInflAmnt = 99999999; let avgtotInflAmnt = 0; let avginflAmnt = 0; @@ -74,8 +77,9 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st let avgreturnAmnt = 0; let avgefflAmnt = 0; let avginfoRnDay = 0; - - console.log('filteredData', filteredData); + let avgNoProcessInflAmnt = 0; + let noProcessInflAmntCnt = 0; + filteredData.forEach((item: FlowRateModalInterface) => { const totInflAmnt = parseNumber(item.totInflAmnt); const inflAmnt = parseNumber(item.inflAmnt); @@ -83,6 +87,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st const returnAmnt = parseNumber(item.returnAmnt); const efflAmnt = parseNumber(item.efflAmnt); const infoRnDay = parseNumber(item.infoRnDay && item.infoRnDay.toString().trim() !== 'x' ? item.infoRnDay.toString().trim() : 0); + maxtotInflAmnt = Math.max(maxtotInflAmnt, totInflAmnt); maxinflAmnt = Math.max(maxinflAmnt, inflAmnt); maxsumFlow = Math.max(maxsumFlow, sumFlow); @@ -103,16 +108,25 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st avgreturnAmnt += returnAmnt; avgefflAmnt += efflAmnt; avginfoRnDay += infoRnDay; + + if(item.noProcessInflAmnt && item.noProcessInflAmnt.toString().trim() != '' && item.noProcessInflAmnt != undefined){ + const noProcessInflAmnt = Number(item.noProcessInflAmnt.toString().replaceAll(',','')); + avgNoProcessInflAmnt += noProcessInflAmnt; + maxNoProcessInflAmnt = Math.max(maxNoProcessInflAmnt, noProcessInflAmnt); + minNoProcessInflAmnt = Math.min(minNoProcessInflAmnt, noProcessInflAmnt); + noProcessInflAmntCnt +=1; + } }); const newFilteredData = [ { msrDt: '평균', - totInflAmnt: roundUp((avgtotInflAmnt / filteredData.length), 0), - inflAmnt: roundUp((avginflAmnt / filteredData.length), 0), - sumFlow: roundUp((avgsumFlow / filteredData.length), 0), - returnAmnt: roundUp((avgreturnAmnt / filteredData.length), 0), - efflAmnt: roundUp((avgefflAmnt / filteredData.length), 0), + totInflAmnt: avgtotInflAmnt && avgtotInflAmnt!=0 ? roundUp((avgtotInflAmnt / filteredData.length), 0) : 0, + inflAmnt: avginflAmnt && avginflAmnt!=0 ? roundUp((avginflAmnt / filteredData.length), 0) : 0, + sumFlow: avgsumFlow && avgsumFlow!=0 ? roundUp((avgsumFlow / filteredData.length), 0) : 0, + returnAmnt: avgreturnAmnt && avgreturnAmnt!=0 ? roundUp((avgreturnAmnt / filteredData.length), 0) : 0, + efflAmnt: avgefflAmnt && avgefflAmnt!=0 ? roundUp((avgefflAmnt / filteredData.length), 0) : 0, + noProcessInflAmnt : roundNumber(avgNoProcessInflAmnt / noProcessInflAmntCnt, 0), infoRnDay: avginfoRnDay > 0 ? roundUp((avginfoRnDay / filteredData.length), 1) : '0.0', rainEffectDay: 0, }, @@ -123,6 +137,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st sumFlow: roundUp(maxsumFlow, 0), returnAmnt: roundUp(maxreturnAmnt, 0), efflAmnt: roundUp(maxefflAmnt, 0), + noProcessInflAmnt : roundNumber(maxNoProcessInflAmnt, 0), infoRnDay: maxinfoRnDay > 0 ? roundUp(maxinfoRnDay, 1) : '0.0', rainEffectDay: 0, }, @@ -133,6 +148,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st sumFlow: roundUp(minsumFlow, 0), returnAmnt: roundUp(minreturnAmnt, 0), efflAmnt: roundUp(minefflAmnt, 0), + noProcessInflAmnt : roundNumber(minNoProcessInflAmnt, 0), infoRnDay: mininfoRnDay > 0 ? roundUp(mininfoRnDay, 1) : '0.0', rainEffectDay: 0, }, @@ -209,6 +225,10 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st boldArray={[0,1,2]} /> </div> + <div className="mt-14"> + <span className="text-2xl font-bold text-gray-500">☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​</span><br></br> + <span className="text-2xl font-bold text-gray-500">☞ 음수값 발생시 제외(null, 평균값 산정시 제외)</span><br></br> + </div> </TabsContent> <TabsContent value="tab_term_summer"> <FacilityTermModalHeader<FlowRateModalInterface> @@ -233,6 +253,10 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st boldArray={[0,1,2]} /> </div> + <div className="mt-14"> + <span className="text-2xl font-bold text-gray-500">☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​</span><br></br> + <span className="text-2xl font-bold text-gray-500">☞ 음수값 발생시 제외(null, 평균값 산정시 제외)</span><br></br> + </div> </TabsContent> <TabsContent value="tab_term_winter"> <FacilityTermModalHeader<FlowRateModalInterface> @@ -257,6 +281,10 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st boldArray={[0,1,2]} /> </div> + <div className="mt-14"> + <span className="text-2xl font-bold text-gray-500">☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​</span><br></br> + <span className="text-2xl font-bold text-gray-500">☞ 음수값 발생시 제외(null, 평균값 산정시 제외)</span><br></br> + </div> </TabsContent> <TabsContent value="tab_term_chuncheon"> <FacilityTermModalHeader<FlowRateModalInterface> @@ -282,6 +310,8 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st /> </div> <div className="mt-14"> + <span className="text-2xl font-bold text-gray-500">☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​</span><br></br> + <span className="text-2xl font-bold text-gray-500">☞ 음수값 발생시 제외(null, 평균값 산정시 제외)</span><br></br> <span className="text-2xl font-bold text-gray-500">☞ 청천시 : 강우량이 3mm미만의 날</span> </div> </TabsContent> @@ -299,6 +329,8 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st <UiTable headName="유량현황" tableData={copyYearList} headlist={upHeadListFlowRateModalYear} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} className="h-[370px]" boldArray={[0,1,2]}/> </div> <div className="mt-14"> + <span className="text-2xl font-bold text-gray-500">☞ 미처리하수량 =[(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​/강우시 일별유입BOD)​</span><br></br> + <span className="text-2xl font-bold text-gray-500">☞ 음수값 발생시 제외(null, 평균값 산정시 제외)</span><br></br> <span className="text-2xl font-bold text-gray-500">☞ 강우량 3mm 이상만 날과 강우영향일(강우일+2일)의 날</span> </div> </TabsContent> diff --git a/apps/fo/app/pages/(with-layout)/planSewage/page.tsx b/apps/fo/app/pages/(with-layout)/planSewage/page.tsx index b39a3e8df..00539da13 100644 --- a/apps/fo/app/pages/(with-layout)/planSewage/page.tsx +++ b/apps/fo/app/pages/(with-layout)/planSewage/page.tsx @@ -104,10 +104,9 @@ export default function PlanSewage() { initializeCommonData(); searchPlanSewageList(1, 10, selectSearchYear[0]?.val || "0", ref.current.partValue); } - }, [isInit, initializeCommonData, searchPlanSewageList]); + }, [isInit, initializeCommonData, searchPlanSewageList, selectSearchYear]); useEffect(() => { - console.log('excelList' , excelList); if (excelList && excelList.length > 0) { downloadExcel({ data: excelList as unknown as JSON[], diff --git a/apps/fo/app/pages/(with-layout)/processFacility/modal/page.tsx b/apps/fo/app/pages/(with-layout)/processFacility/modal/page.tsx index 3afed1166..b27984df7 100644 --- a/apps/fo/app/pages/(with-layout)/processFacility/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/processFacility/modal/page.tsx @@ -1,12 +1,13 @@ "use client" +import { roundNumber } from "@/app/components/common/DataForm"; import { useFoStore } from "@/app/store"; import type { TableUpperProps } from "@/app/store/dashboard"; -import { UITab, UiTable } from "@common/business_components/ui"; +import { downloadExcel, filePickedBlobArray, UITab, UiTable } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; import { TabsContent } from "@common/components"; -import { Table, TableCell, TableHead, TableRow } from "@common/components/ui"; +import { Button, Table, TableCell, TableHead, TableRow } from "@common/components/ui"; type ModalType = { fcltyName: string; @@ -82,8 +83,8 @@ const headMakeList = (upHeadList: TableUpperProps[], gridNum:number) => { export default function ProcessFacilityInfoModal(props: ModalType) { // 그리드 관련 - const {ProcessFacilityDetail} = useFoStore((state) => state); - + const {Common, ProcessFacilityDetail} = useFoStore((state) => state); + const { btnClass } = Common; const { upHeadListPlanInfo, gridListPlanInfo, @@ -115,6 +116,78 @@ export default function ProcessFacilityInfoModal(props: ModalType) { const upHeadListPlanInfoChange = headMakeList(upHeadListPlanInfo, 2); const upHeadListFcltyHistInfoChange = headMakeList(upHeadListFcltyHistInfo, 3); const upHeadListFcltyWaterQltyInfoChange = headMakeList(upHeadListFcltyWaterQltyInfo, 4); + + const excelDownloadPlan = () => { + const excelDownList: any[] = []; + + if(gridListFcltyHistInfo.length > 0){ + gridListFcltyHistInfo.forEach((item) => { + excelDownList.push({ + "차수": item.extnsSeqno, + "구분": item.extnsNm, + "사업시작일": item.bzStrtYrMnth, + "사업종료일": item.bzEdYrMnth, + "설치인가일": item.eqpPrmsDt, + "준공일": item.cmplDt, + "시운전완료일": item.trlrnCmplDt, + "가동개시일": item.rnDt, + "시설용량(m³/일)": roundNumber(item.fctCpc,0), + }); + }); + } + if (excelDownList && excelDownList.length > 0) { + downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.fcltyName + ' 시설이력관리', sheetNameArray: [props.fcltyName + ' 시설이력관리'], headerRange: 'A1:I1' }); + } else if (gridListFcltyHistInfo.length == 0) { + alert('다운받을 데이터가 없습니다.'); + } + } + + const excelDownloadQlty = () => { + fetch(`/dashBoadModalWaterQlty.xlsx`, {}).then(async (response) => { + if (!response.ok) { + throw Error(response.statusText); + } + + // 받은 파일 바인너리 처리 + const blobRet = await response.arrayBuffer(); + const excelData = gridListFcltyWaterQltyInfo.map((item) => { + return [ + item.extnsSeqno, + item.plInflWqltBod, + item.plInflWqltToc, + item.plInflWqltCod, + item.plInflWqltSs, + item.plInflWqltTn, + item.plInflWqltTp, + item.dsInflWqltBod, + item.dsInflWqltToc, + item.dsInflWqltCod, + item.dsInflWqltSs, + item.dsInflWqltTn, + item.dsInflWqltTp, + item.plEfflWqltBod, + item.plEfflWqltToc, + item.plEfflWqltCod, + item.plEfflWqltSs, + item.plEfflWqltTn, + item.plEfflWqltTp, + ]; + }); + + const sheetParameter = [ + { + data: excelData, + headerNum: 2, + headerRange: 'A1:S2', + sheetName: '시설 수질정보', + startCol: 'A' + }, + ]; + // 버퍼에 있는 엑셀데이터 전달 후 json으로 변환 + await filePickedBlobArray(blobRet, props.fcltyName +' 수질정보', sheetParameter); + }); + } + return ( <> <ListDiv className="!h-[80px]"> @@ -132,7 +205,7 @@ export default function ProcessFacilityInfoModal(props: ModalType) { </div> </ListDiv> <div className="overflow-y-auto"> - <div className="!h-[600px]"> + <div className="h-[550px]"> <ListDiv className=""> <UITab tabList={tabList} defaultValue="common_info"> <TabsContent value="common_info"> @@ -184,8 +257,11 @@ export default function ProcessFacilityInfoModal(props: ModalType) { <TabsContent value="history_info"> <ListDiv> - <div className="h-[270px] w-full overflow-y-auto overflow-x-hidden"> - <div className="h-[130%]"> + <div className="h-[250px] w-full overflow-y-auto overflow-x-hidden"> + <Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownloadPlan}> + {"엑셀다운로드"} + </Button> + <div className="h-[120%]"> <UiTable headName={"시설 이력관리"} tableData={gridListFcltyHistInfo} headlist={upHeadListFcltyHistInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}> {upHeadListFcltyHistInfoChange} </UiTable> @@ -193,8 +269,11 @@ export default function ProcessFacilityInfoModal(props: ModalType) { </div> </ListDiv> <ListDiv> - <div className="h-[270px] w-full overflow-y-auto overflow-x-hidden"> - <div className="h-[130%]"> + <div className="h-[250px] w-full overflow-y-auto overflow-x-hidden"> + <Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownloadQlty}> + {"엑셀다운로드"} + </Button> + <div className="h-[120%]"> <UiTable headName={"시설 수질정보"} tableData={gridListFcltyWaterQltyInfo} headlist={upHeadListFcltyWaterQltyInfo} pageSize={0} total={0} cellClick={undefined} onPageChange={()=>{}}> {upHeadListFcltyWaterQltyInfoChange} </UiTable> diff --git a/apps/fo/app/pages/(with-layout)/rdi/page.tsx b/apps/fo/app/pages/(with-layout)/rdi/page.tsx index b9a785233..9f0fef1b3 100644 --- a/apps/fo/app/pages/(with-layout)/rdi/page.tsx +++ b/apps/fo/app/pages/(with-layout)/rdi/page.tsx @@ -107,7 +107,7 @@ export default function Rdi() { initializeCommonData(); searchRdiList(1, 10, selectSearchYear[0]?.val || "0"); } - }, [isInit, initializeCommonData, searchRdiList]); + }, [isInit, initializeCommonData, searchRdiList, selectSearchYear]); useEffect(() => { if (excelList && excelList.length > 0) { @@ -197,7 +197,8 @@ export default function Rdi() { <div className={widthSize}> <UiTable cellClick={ undefined } headName={"RDII추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} /> </div> - <span className="text-2xl text-gray-500">※주) 처리장 유입부에서 측정된 유량 및 수질조사 자료를 기준으로 산정된 결과임</span> + <span className="text-2xl text-gray-500">※ 강우시 총 추정유입량 = 청천시 유입하수량 + RDII 추정값</span><br></br> + <span className="text-2xl text-gray-500">※ 주) 처리장 유입부에서 측정된 유량 및 수질조사 자료를 기준으로 산정된 결과임</span> </div> </ListDiv> </ContentsDiv> diff --git a/apps/fo/app/pages/(with-layout)/sewageOccur/modal/page.tsx b/apps/fo/app/pages/(with-layout)/sewageOccur/modal/page.tsx index 4081b4547..37cadc7c6 100644 --- a/apps/fo/app/pages/(with-layout)/sewageOccur/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/sewageOccur/modal/page.tsx @@ -1,15 +1,17 @@ "use client" +import { roundNumber } from "@/app/components/common/DataForm"; import { useFoStore } from "@/app/store"; import type { modalTableType } from "@/app/store/sewageOccur"; -import { DateMonthPicker, UiTable } from "@common/business_components/ui"; +import { DateMonthPicker, downloadExcel, UiTable } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; -import { Table, TableCell, TableHead, TableRow } from "@common/components/ui"; +import { Button, Table, TableCell, TableHead, TableRow } from "@common/components/ui"; import { useEffect, useState } from "react"; export default function SewageOccurModal(props: { fcltyName: string; facilityCd : string; searchYear : string}) { // 그리드 관련 - const {SewageOccurDetail, searchSewageOccurDetailList} = useFoStore((state) => state); - + const { Common, SewageOccurDetail, searchSewageOccurDetailList} = useFoStore((state) => state); + const { btnClass } = Common; + // searchYear 유효성 검사 및 기본값 설정 const validSearchYear = props.searchYear && /^\d{4}$/.test(props.searchYear) ? props.searchYear : new Date().getFullYear().toString(); @@ -61,6 +63,25 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd } }, [endYearMonth, startYearMonth]); + const excelDownload = () => { + const excelDownList: any[] = []; + if(detailList.length > 0){ + detailList.forEach((item) => { + excelDownList.push({ + "날짜": item.msrDt, + "물사용량(m³/일)": roundNumber(item.waterUsage, 0), + "오수전환율(%)": roundNumber(item.swageChangePercent, 0), + "오수발생량 추정(m³/일)": roundNumber(item.estimationSewage, 0), + }); + }); + } + if (excelDownList && excelDownList.length > 0) { + downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: props.searchYear+'년 '+props.fcltyName + ' 오수발생량 추정', sheetNameArray: [props.fcltyName + ' 오수발생량 추정'], headerRange: 'A1:D1' }); + } else if (detailList.length == 0) { + alert('다운받을 데이터가 없습니다.'); + } + } + return ( <> <ListDiv className="!h-[80px] !mt-10"> @@ -118,6 +139,9 @@ export default function SewageOccurModal(props: { fcltyName: string; facilityCd </ListDiv> <ListDiv className="!h-[570px] overflow-y-auto"> <div className="h-[120%]"> + <Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}> + {"엑셀다운로드"} + </Button> <UiTable headName={"오수발생량 추정"} tableData={detailList} headlist={upHeadListSewageOccurDetail} pageSize={0} total={0} cellClick={undefined} onPageChange={() => {}} boldArray={[0, 1, 2]}> </UiTable> </div> diff --git a/apps/fo/app/pages/(with-layout)/underWaterInput/modal/page.tsx b/apps/fo/app/pages/(with-layout)/underWaterInput/modal/page.tsx index 79c35b251..1d4ea2310 100644 --- a/apps/fo/app/pages/(with-layout)/underWaterInput/modal/page.tsx +++ b/apps/fo/app/pages/(with-layout)/underWaterInput/modal/page.tsx @@ -1,9 +1,11 @@ "use client" +import { roundNumber } from "@/app/components/common/DataForm"; import { useFoStore } from "@/app/store"; import type { UnderWaterInputModalProps } from "@/app/store/underWaterInput/types"; +import { downloadExcel } from "@common/business_components"; import { DateMonthPicker, UITab, UiTable } from "@common/business_components/ui"; import ListDiv from "@common/business_components/ui/list_div"; -import { Table, TableCell, TableHead, TableRow, TabsContent } from "@common/components/ui"; +import { Button, Table, TableCell, TableHead, TableRow, TabsContent } from "@common/components/ui"; import { useEffect, useState } from "react"; type ModalProps ={ @@ -20,8 +22,8 @@ const tabList1 = [ export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYear=new Date().getFullYear().toString()} : ModalProps) { // 그리드 관련 - const {UnderWaterDetail, unserWaterModal} = useFoStore((state) => state); - + const {Common, UnderWaterDetail, unserWaterModal} = useFoStore((state) => state); + const { btnClass } = Common; const [startYmDate, setStartYmDate] = useState<string>(searchYear+'01'); const [endYmDate, setEndYmDate] = useState<string>(searchYear+'12'); const [tabTerm, setTabTerm] = useState<string>('tab_term_year'); @@ -87,9 +89,31 @@ export default function UnderWaterInputModal({fcltyCd='', fcltyName='',searchYea unserWaterModal(fcltyCd, searchYear, prevStartYmDate, prevEndYmDate); } , [fcltyCd, searchYear, unserWaterModal, prevStartYmDate, prevEndYmDate]); + const excelDownload = () => { + const excelDownList: any[] = []; + if(copyYearList.length > 0){ + copyYearList.forEach((item) => { + excelDownList.push({ + "날짜": item.msrDt, + "청천시 실제 하수유입량(m³/일)": roundNumber(item.realSewageInput, 0), + "오수발생량(m³/일)": roundNumber(item.sewageOccur, 0), + "지하수 유입량(m³/일)": roundNumber(item.underWaterInput, 0), + }); + }); + } + if (excelDownList && excelDownList.length > 0) { + downloadExcel({ data: JSON.parse(JSON.stringify(excelDownList)), fileName: searchYear+'년 '+fcltyName + ' 지하수유입량', sheetNameArray: [fcltyName + ' 지하수유입량'], headerRange: 'A1:D1' }); + } else if (copyYearList.length == 0) { + alert('다운받을 데이터가 없습니다.'); + } + } + return ( <> <UITab tabList={tabList1} defaultValue="tab_term_year" onValueChange={(val) => {setTabTerm(val)}}> + <Button className={btnClass} style={{float: 'right'}} color="green" onClick={excelDownload}> + {"엑셀다운로드"} + </Button> <TabsContent value="tab_term_year"> <ListDiv className="!h-[100px]"> <div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r"> diff --git a/apps/fo/app/pages/(with-layout)/underWaterInput/page.tsx b/apps/fo/app/pages/(with-layout)/underWaterInput/page.tsx index e731fb7a3..2126a31a0 100644 --- a/apps/fo/app/pages/(with-layout)/underWaterInput/page.tsx +++ b/apps/fo/app/pages/(with-layout)/underWaterInput/page.tsx @@ -223,6 +223,7 @@ export default function UnderWaterInput() { <UiTable cellClick={(index: number | undefined) => index !== undefined && cellClick(index)} headName={"지하수유입량 추정"} tableData={mainList} headlist={upheadList} pageSize={10} total={total} resetPageNo={resetPage} onPageChange={handlePageChange} /> </div> </div> + <span className="text-2xl text-gray-500">※적정여부 = 연간 지하수유입량/연평균 유입하수량*100 </span><br></br> <span className="text-2xl text-gray-500">※지하수 유입량 = 하수처리장 청천시 실제유입량 - (물사용량 × 오수전환율)</span> </ListDiv> </ContentsDiv> diff --git a/apps/fo/app/store/common/index.tsx b/apps/fo/app/store/common/index.tsx index 5646ea126..1c9b06991 100644 --- a/apps/fo/app/store/common/index.tsx +++ b/apps/fo/app/store/common/index.tsx @@ -201,6 +201,9 @@ const selectMiddleRegionData: SelectDataType[] = [ { text: "전체", val: '0' } ]; +// 오수전환율 +export const OSU_PERCENT = 0.9; + /** * 반올림 함수 * @param value : 대상 숫자 @@ -211,6 +214,17 @@ export const roundUp = (value: number, precision: number = 1): number => { return Math.round(value * (10 ** precision)) / (10 ** precision); } +/** + * 수질 데이터 포맷 변경 함수 + * @param value : 수질 데이터 + * @param day : 일수 + * @param digit : 소수점 자리수 + */ +export const qltyDataSetting = (value: number, day : number, digit: number) => { + const toZero = digit === 1 ? '0.0' : digit === 2 ? '0.00' : '0.000'; + return value > 0 ? roundUp((value/day), digit).toFixed(digit) : toZero; +}; + /** * STORE - API */ @@ -406,7 +420,7 @@ export const commonState: CommonType = { selectFlowTerm: selectFlowTerm, selectFlowPanel: selectFlowPanel, selectEnvPartData: selectEnvPartData, - btnClass: "p-4 m-2 text-white rounded-sm text-lg font-medium", + btnClass: "p-4 m-2 !mr-10 text-white rounded-sm text-lg font-medium", }, auth: { diff --git a/apps/fo/app/store/dashboard/index.tsx b/apps/fo/app/store/dashboard/index.tsx index 8ad56e070..f5861a21e 100644 --- a/apps/fo/app/store/dashboard/index.tsx +++ b/apps/fo/app/store/dashboard/index.tsx @@ -3,10 +3,12 @@ */ import { getFetch } from "@/app/components/api"; +import CalcRainEffect from "@/app/components/common/CalcRainEffect"; import DataForm from "@/app/components/common/DataForm"; -import { fetchPlanInfo, roundUp } from "../common"; -import type { FacilityWaterQltyProps } from "../facilityWaterQlty"; -import { calRainEffectDay, type ApiResponse, type FlowDataItem } from "../underWaterInput"; +import { fetchPlanInfo, OSU_PERCENT, qltyDataSetting, roundUp } from "../common"; +import { type FacilityWaterQltyProps } from "../facilityWaterQlty"; +import { fetchFlowRateModalList } from "../flowRate"; +import { fetchFacilityWaterQltyInfo } from "../processFacility"; // selectBox export type SelectDataType = { @@ -99,7 +101,7 @@ export type lineBarChartDataProps = { export type lineChartDataProps = { label : string, - val : number + val : number, } export interface RainManageListProps { @@ -146,6 +148,7 @@ export interface RainManageListProps { dsInflWqltTp: number | '', extnsSeqno?: number | '', rainEffectDay?: number | '', + toBeInfoRnDay? : number | '', } export interface RainManageExcelType { @@ -660,6 +663,7 @@ const chart_inflTn : lineChartDataProps[] = []; const chart_efflTn : lineChartDataProps[] = []; const chart_inflBod : lineChartDataProps[] = []; const chart_efflBod : lineChartDataProps[] = []; +const waterQltyStandartd : any = []; const rainManageList : RainManageListProps[] = []; @@ -732,6 +736,250 @@ const fetchMainGraph = async (searchYear: string|undefined, fcltyCd: string|unde } } +// 수질 데이터 청천시, 강우시 재계산 +const calcWaterQltyData = async (data: any[], searchYear : string|undefined, fcltyCd : string|undefined) => { + + const nullToZero = (value: any) => { + return value === null || value === undefined || value === '' ? 0 : Number(value); + }; + + const orgData = data; + const res = await fetchMainGraph(searchYear, fcltyCd); + if(res.data.wqltObjs.length> 0) { + const clone = (arr: any[]) => arr?.map(v => ({ ...v })) ?? []; + const qltyData = res.data.wqltObjs; + const qltyChungchunData = CalcRainEffect(clone(qltyData), 'SUNNY'); + const qltyRainData = CalcRainEffect(clone(qltyData), 'RAIN'); + + // (0) 전체변수 + let summerDay = 0; + let totalInflBodAvgSummer = 0; + let totalInflTnAvgSummer = 0; + let totalInflTpAvgSummer = 0; + let totalEfflBodAvgSummer = 0; + let totalEfflTnAvgSummer = 0; + let totalEfflTpAvgSummer = 0; + + let winterDay = 0; + let totalInflBodAvgWinter = 0; + let totalInflTnAvgWinter = 0; + let totalInflTpAvgWinter = 0; + let totalEfflBodAvgWinter = 0; + let totalEfflTnAvgWinter = 0; + let totalEfflTpAvgWinter = 0; + + // 전체 대상 + qltyData.forEach((item: any) => { + const month = item.msrDt.substring(4, 6); // 월 추출 + if(month === '01' || month === '02'){ + const inflbod = nullToZero(item.inflAssctBfrWqltBod); + const infltn = nullToZero(item.inflAssctBfrWqltTn); + const infltp = nullToZero(item.inflAssctBfrWqltTp); + const effbod = nullToZero(item.efflWqltBod); + const efftn = nullToZero(item.efflWqltTn); + const efftp = nullToZero(item.efflWqltTp); + + totalInflBodAvgWinter += inflbod; + totalInflTnAvgWinter += infltn; + totalInflTpAvgWinter += infltp; + totalEfflBodAvgWinter += effbod; + totalEfflTnAvgWinter += efftn; + totalEfflTpAvgWinter += efftp; + winterDay += 1; + }else if(month === '06' || month === '07' || month === '08'){ + summerDay += 1; + const inflbod = nullToZero(item.inflAssctBfrWqltBod); + const infltn = nullToZero(item.inflAssctBfrWqltTn); + const infltp = nullToZero(item.inflAssctBfrWqltTp); + const effbod = nullToZero(item.efflWqltBod); + const efftn = nullToZero(item.efflWqltTn); + const efftp = nullToZero(item.efflWqltTp); + + totalInflBodAvgSummer += inflbod; + totalInflTnAvgSummer += infltn; + totalInflTpAvgSummer += infltp; + totalEfflBodAvgSummer += effbod; + totalEfflTnAvgSummer += efftn; + totalEfflTpAvgSummer += efftp; + } + }); + + orgData[5].winterAll = qltyDataSetting(totalInflBodAvgWinter, winterDay, 1); + orgData[6].winterAll = qltyDataSetting(totalEfflBodAvgWinter, winterDay, 1); + orgData[7].winterAll = qltyDataSetting(totalInflTnAvgWinter, winterDay, 3); + orgData[8].winterAll = qltyDataSetting(totalEfflTnAvgWinter, winterDay, 3); + orgData[9].winterAll = qltyDataSetting(totalInflTpAvgWinter, winterDay, 3); + orgData[10].winterAll = qltyDataSetting(totalEfflTpAvgWinter, winterDay, 3); + + orgData[5].summerAll = qltyDataSetting(totalInflBodAvgSummer, summerDay, 1); + orgData[6].summerAll = qltyDataSetting(totalEfflBodAvgSummer, summerDay, 1); + orgData[7].summerAll = qltyDataSetting(totalInflTnAvgSummer, summerDay, 3); + orgData[8].summerAll = qltyDataSetting(totalEfflTnAvgSummer, summerDay, 3); + orgData[9].summerAll = qltyDataSetting(totalInflTpAvgSummer, summerDay, 3); + orgData[10].summerAll = qltyDataSetting(totalEfflTpAvgSummer, summerDay, 3); + + // (1) 청천시 변수 + // (1-1) 날짜 count + let chungchunSummerDay = 0; + let chungchunWinterDay = 0; + + // (1-2) 하절기 + let chungchunInflBodAvgSummer = 0; + let chungchunInflTnAvgSummer = 0; + let chungchunInflTpAvgSummer = 0; + let chungchunEfflBodAvgSummer = 0; + let chungchunEfflTnAvgSummer = 0; + let chungchunEfflTpAvgSummer = 0; + + // (1-3) 동절기 (최대, 최소, 평균 다 필요) + let chungchunInflBodAvg = 0; + let chungchunInflTnAvg = 0; + let chungchunInflTpAvg = 0; + let chungchunInflBodMax = 0; + let chungchunInflTnMax= 0; + let chungchunInflTpMax = 0; + let chungchunInflBodMin = 99999999; + let chungchunInflTnMin = 99999999; + let chungchunInflTpMin = 99999999; + + let chungchunEfflBodAvg = 0; + let chungchunEfflTnAvg = 0; + let chungchunEfflTpAvg = 0; + let chungchunEfflBodMax = 0; + let chungchunEfflTnMax= 0; + let chungchunEfflTpMax = 0; + let chungchunEfflBodMin = 99999999; + let chungchunEfflTnMin = 99999999; + let chungchunEfflTpMin = 99999999; + + // 청천시 + qltyChungchunData.forEach((item: any) => { + const month = item.msrDt.substring(4, 6); // 월 추출 + if(month === '01' || month === '02'){ + chungchunWinterDay += 1; + + const inflbod = nullToZero(item.inflAssctBfrWqltBod); + const infltn = nullToZero(item.inflAssctBfrWqltTn); + const infltp = nullToZero(item.inflAssctBfrWqltTp); + const effbod = nullToZero(item.efflWqltBod); + const efftn = nullToZero(item.efflWqltTn); + const efftp = nullToZero(item.efflWqltTp); + + chungchunInflBodAvg += inflbod; + chungchunInflTnAvg += infltn; + chungchunInflTpAvg += infltp; + chungchunEfflBodAvg += effbod; + chungchunEfflTnAvg += efftn; + chungchunEfflTpAvg += efftp; + + if(chungchunInflBodMax < inflbod) chungchunInflBodMax = inflbod; + if(chungchunInflTnMax < infltn) chungchunInflTnMax = infltn; + if(chungchunInflTpMax < infltp) chungchunInflTpMax = infltp; + if(chungchunEfflBodMax < effbod) chungchunEfflBodMax = effbod; + if(chungchunEfflTnMax < efftn) chungchunEfflTnMax = efftn; + if(chungchunEfflTpMax < efftp) chungchunEfflTpMax = efftp; + + if(chungchunInflBodMin > inflbod) chungchunInflBodMin = inflbod; + if(chungchunInflTnMin > infltn) chungchunInflTnMin = infltn; + if(chungchunInflTpMin > infltp) chungchunInflTpMin = infltp; + if(chungchunEfflBodMin > effbod) chungchunEfflBodMin = effbod; + if(chungchunEfflTnMin > efftn) chungchunEfflTnMin = efftn; + if(chungchunEfflTpMin > efftp) chungchunEfflTpMin = efftp; + }else if(month === '06' || month === '07' || month === '08'){ + chungchunSummerDay += 1; + + const inflbod = nullToZero(item.inflAssctBfrWqltBod); + const infltn = nullToZero(item.inflAssctBfrWqltTn); + const infltp = nullToZero(item.inflAssctBfrWqltTp); + const effbod = nullToZero(item.efflWqltBod); + const efftn = nullToZero(item.efflWqltTn); + const efftp = nullToZero(item.efflWqltTp); + + chungchunInflBodAvgSummer += inflbod; + chungchunInflTnAvgSummer += infltn; + chungchunInflTpAvgSummer += infltp; + chungchunEfflBodAvgSummer += effbod; + chungchunEfflTnAvgSummer += efftn; + chungchunEfflTpAvgSummer += efftp; + } + }); + + // 청천시 수질 데이터 수정 + // 하절기 + orgData[5].summerRain = qltyDataSetting(chungchunInflBodAvgSummer, chungchunSummerDay, 1); + orgData[6].summerRain = qltyDataSetting(chungchunEfflBodAvgSummer, chungchunSummerDay, 1); + orgData[7].summerRain = qltyDataSetting(chungchunInflTnAvgSummer, chungchunSummerDay, 3); + orgData[8].summerRain = qltyDataSetting(chungchunEfflTnAvgSummer, chungchunSummerDay, 3); + orgData[9].summerRain = qltyDataSetting(chungchunInflTpAvgSummer, chungchunSummerDay, 3); + orgData[10].summerRain = qltyDataSetting(chungchunEfflTpAvgSummer, chungchunSummerDay, 3); + + // 동절기 + orgData[5].winterSunnyAvg = qltyDataSetting(chungchunInflBodAvg, chungchunWinterDay, 1); + orgData[6].winterSunnyAvg = qltyDataSetting(chungchunEfflBodAvg, chungchunWinterDay, 1); + orgData[7].winterSunnyAvg = qltyDataSetting(chungchunInflTnAvg, chungchunWinterDay, 3); + orgData[8].winterSunnyAvg = qltyDataSetting(chungchunEfflTnAvg, chungchunWinterDay, 3); + orgData[9].winterSunnyAvg = qltyDataSetting(chungchunInflTpAvg, chungchunWinterDay, 3); + orgData[10].winterSunnyAvg = qltyDataSetting(chungchunEfflTpAvg, chungchunWinterDay, 3); + + orgData[5].winterSunnyMax = roundUp(chungchunInflBodMax, 1).toFixed(1); + orgData[6].winterSunnyMax = roundUp(chungchunEfflBodMax, 1).toFixed(1); + orgData[7].winterSunnyMax = roundUp(chungchunInflTnMax, 3).toFixed(3); + orgData[8].winterSunnyMax = roundUp(chungchunEfflTnMax, 3).toFixed(3); + orgData[9].winterSunnyMax = roundUp(chungchunInflTpMax, 3).toFixed(3); + orgData[10].winterSunnyMax = roundUp(chungchunEfflTpMax, 3).toFixed(3); + + orgData[5].winterSunnyMin = chungchunInflBodMin === 99999999 ? '0.0' : roundUp(chungchunInflBodMin, 1).toFixed(1); + orgData[6].winterSunnyMin = chungchunEfflBodMin === 99999999 ? '0.0' : roundUp(chungchunEfflBodMin, 1).toFixed(1); + orgData[7].winterSunnyMin = chungchunInflTnMin === 99999999 ? '0.000' : roundUp(chungchunInflTnMin, 3).toFixed(3); + orgData[8].winterSunnyMin = chungchunEfflTnMin === 99999999 ? '0.000' : roundUp(chungchunEfflTnMin, 3).toFixed(3); + orgData[9].winterSunnyMin = chungchunInflTpMin === 99999999 ? '0.000' : roundUp(chungchunInflTpMin, 3).toFixed(3); + orgData[10].winterSunnyMin = chungchunEfflTpMin === 99999999 ? '0.000' : roundUp(chungchunEfflTpMin, 3).toFixed(3); + + // 강우시 변수 + let rainSummerDay = 0; + + let rainInflBodAvg = 0; + let rainInflTnAvg = 0; + let rainInflTpAvg = 0; + let rainEfflBodAvg = 0; + let rainEfflTnAvg = 0; + let rainEfflTpAvg = 0; + + // 강우시 + qltyRainData.forEach((item: any) => { + const month = item.msrDt.substring(4, 6); // 월 추출 + if(month === '06' || month === '07' || month === '08'){ + rainSummerDay += 1; + + const inflbod = nullToZero(item.inflAssctBfrWqltBod); + const infltn = nullToZero(item.inflAssctBfrWqltTn); + const infltp = nullToZero(item.inflAssctBfrWqltTp); + const effbod = nullToZero(item.efflWqltBod); + const efftn = nullToZero(item.efflWqltTn); + const efftp = nullToZero(item.efflWqltTp); + + rainInflBodAvg += inflbod; + rainInflTnAvg += infltn; + rainInflTpAvg += infltp; + rainEfflBodAvg += effbod; + rainEfflTnAvg += efftn; + rainEfflTpAvg += efftp; + } + }); + + // 강우시 수질 데이터 수정 + orgData[5].summerThree = qltyDataSetting(rainInflBodAvg, rainSummerDay, 1); + orgData[6].summerThree = qltyDataSetting(rainEfflBodAvg, rainSummerDay, 1); + orgData[7].summerThree = qltyDataSetting(rainInflTnAvg, rainSummerDay, 3); + orgData[8].summerThree = qltyDataSetting(rainEfflTnAvg, rainSummerDay, 3); + orgData[9].summerThree = qltyDataSetting(rainInflTpAvg, rainSummerDay, 3); + orgData[10].summerThree = qltyDataSetting(rainEfflTpAvg, rainSummerDay, 3); + return orgData; + } else { + return orgData; + } +}; + /**==================================== * Store - action ====================================*/ @@ -773,7 +1021,7 @@ export type DashBoardType = { OperationStatus : { isInit : boolean; upHeadListOperationStatus : TableUpperProps[]; - operationalStatusList : OperationalStatusListProps[]; + operationalStatusList : any; isLoadingOperationStatus : boolean; } @@ -788,6 +1036,7 @@ export type DashBoardType = { chart_efflTn : lineChartDataProps[]; chart_inflBod : lineChartDataProps[]; chart_efflBod : lineChartDataProps[]; + waterQltyStandartd : any; isLoadingMainGraph : boolean; }, @@ -850,6 +1099,7 @@ export const dashBoardInitState:DashBoardType = { chart_efflTn : chart_efflTn, chart_inflBod : chart_inflBod, chart_efflBod : chart_efflBod, + waterQltyStandartd : waterQltyStandartd, isLoadingMainGraph : false, }, @@ -999,55 +1249,6 @@ const searchWaterUsage = async (searchYear: string, fcltyCd: string) => { return waterUsage; } -// 강우영향일 계산 및 강우량 덮어씌우기 -export const calRainEffectDayRainManage = (data: RainManageListProps[]) => { - - // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) - for(let idx = 0; idx < data.length; idx++) { - const item = data[idx]; - if(item){ - if(item.infoRnDay && Number(item.infoRnDay) >= 3) { - item.rainEffectDay = 1; - } else { - item.rainEffectDay = 0; - } - } - } - - // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 - for(let idx = 0; idx < data.length; idx++) { - if(data[idx]) { - // 하루 전이 강우영향일(3 이상)인 경우 - if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) { - data[idx]!.rainEffectDay = 1; - } - // 이틀 전이 강우영향일(3 이상)인 경우 - if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) { - data[idx]!.rainEffectDay = 1; - } - } - } - - for(let idx = 0; idx < data.length; idx++) { - if(data[idx] && data[idx]?.rainEffectDay === 1) { - if(idx > 1){ - if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay) >= 3) { - data[idx]!.infoRnDay = data[idx-1]!.infoRnDay; - } - } - if(idx > 2){ - if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay) >= 3) { - data[idx]!.infoRnDay = data[idx-2]!.infoRnDay; - } - } - } - } - - let rtnData : RainManageListProps[] = []; - rtnData = data.filter((item: RainManageListProps) => item.rainEffectDay === 1); - return rtnData; -} - export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) => void)=>DashBoardActions=(set: (fn: (state: DashBoardType) => DashBoardType) => void) => { return { initializeDashBoardData: async () => { @@ -1131,14 +1332,13 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) el.provisionalApproval = rtnPlanData?rtnPlanData.ugwtUseSum:''; } - if(index == 0 || index === 2){ + if(index === 2){ dataFormSettingPlan(el, 1); }else if(index == 4){ }else{ dataFormSettingPlan(el, 0); } - set((state: DashBoardType) => ({ ...state, PlanFclty: { @@ -1173,14 +1373,47 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) let winterSunnyMin = 1; let winterSunnyAvg = 1; let winterSunnyMax = 1; + + // 최대, 최소 총 유입량 (1년 하루 합계의 최대, 최소) + + // 하절기 청천시, 강우시 재계산 리턴값 + let summerChungchunFlow = 1 + let summerChungchunReturnAmnt = 1; + let summerChungchunEfflAmnt = 1; + let summerRainInflAmnt = 1; + let summerRainReturnAmnt = 1; + let summerRainEfflAmnt = 1; + + // 동절기 청천시 최대, 최소, 평균 리턴값 + let winterChungchunFlowAvg = 1 ; + let winterChungchunFlowMax = 1 ; + let winterChungchunFlowMin = 1 ; + let winterChungchunReturnAvg = 1 ; + let winterChungchunReturnMax = 1 ; + let winterChungchunReturnMin = 1 ; + let winterChungchunEfflAvg = 1 ; + let winterChungchunEfflMax = 1 ; + let winterChungchunEfflMin = 1 ; if(data && operationalStatusList){ // 유량 - 유입 if (operationalStatusList?.[0]) { // 연간 - const yearAvg = data.yearData===null?'':(data.yearData.AVG_INFL_AMNT?data.yearData.AVG_INFL_AMNT:0)+(data.yearData.AVG_SUM_FLOW?data.yearData.AVG_SUM_FLOW:0)+(data.yearData.AVG_RETURN_AMNT?data.yearData.AVG_RETURN_AMNT:0); - const yearMax = data.yearData===null?'':(data.yearData.MAX_INFL_AMNT?data.yearData.MAX_INFL_AMNT:0)+(data.yearData.MAX_SUM_FLOW?data.yearData.MAX_SUM_FLOW:0)+(data.yearData.MAX_RETURN_AMNT?data.yearData.MAX_RETURN_AMNT:0); - const yearMin = data.yearData===null?'':(data.yearData.MIN_INFL_AMNT?data.yearData.MIN_INFL_AMNT:0)+(data.yearData.MIN_SUM_FLOW?data.yearData.MIN_SUM_FLOW:0)+(data.yearData.MIN_RETURN_AMNT?data.yearData.MIN_RETURN_AMNT:0); + const yearAvg = data.yearData===null ? '' : ( + (data.yearData.AVG_INFL_AMNT?data.yearData.AVG_INFL_AMNT:0) + + (data.yearData.AVG_SUM_FLOW?data.yearData.AVG_SUM_FLOW:0) + + (data.yearData.AVG_RETURN_AMNT?data.yearData.AVG_RETURN_AMNT:0) + ); + const yearMax = data.yearData===null ? '' : ( + (data.yearData.MAX_INFL_AMNT?data.yearData.MAX_INFL_AMNT:0) + + (data.yearData.MAX_SUM_FLOW?data.yearData.MAX_SUM_FLOW:0) + + (data.yearData.MAX_RETURN_AMNT?data.yearData.MAX_RETURN_AMNT:0) + ); + const yearMin = data.yearData===null ? '' : ( + (data.yearData.MIN_INFL_AMNT?data.yearData.MIN_INFL_AMNT:0) + + (data.yearData.MIN_SUM_FLOW?data.yearData.MIN_SUM_FLOW:0) + + (data.yearData.MIN_RETURN_AMNT?data.yearData.MIN_RETURN_AMNT:0) + ); operationalStatusList[0].yearAvg = yearAvg; operationalStatusList[0].yearMax = yearMax; @@ -1188,18 +1421,15 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) // 여름 operationalStatusList[0].summerAll = data.summer === null ? '' : ( (data.summer.AVG_INFL_AMNT ? data.summer.AVG_INFL_AMNT : 0) + - (data.summer.AVG_SUM_FLOW ? data.summer.AVG_SUM_FLOW : 0) + - (data.summer.AVG_TP_INFL_WQLT_TP ? data.summer.AVG_TP_INFL_WQLT_TP : 0) + (data.summer.AVG_SUM_FLOW ? data.summer.AVG_SUM_FLOW : 0) ); operationalStatusList[0].summerThree = data.summerRainy === null ? '' : ( (data.summerRainy.AVG_INFL_AMNT ? data.summerRainy.AVG_INFL_AMNT : 0) + - (data.summerRainy.AVG_SUM_FLOW ? data.summerRainy.AVG_SUM_FLOW : 0) + - (data.summerRainy.AVG_TP_INFL_WQLT_TP ? data.summerRainy.AVG_TP_INFL_WQLT_TP : 0) + (data.summerRainy.AVG_SUM_FLOW ? data.summerRainy.AVG_SUM_FLOW : 0) ); operationalStatusList[0].summerRain = data.summerSunny === null ? '' : ( (data.summerSunny.AVG_INFL_AMNT ? data.summerSunny.AVG_INFL_AMNT : 0) + - (data.summerSunny.AVG_SUM_FLOW ? data.summerSunny.AVG_SUM_FLOW : 0) + - (data.summerSunny.AVG_TP_INFL_WQLT_TP ? data.summerSunny.AVG_TP_INFL_WQLT_TP : 0) + (data.summerSunny.AVG_SUM_FLOW ? data.summerSunny.AVG_SUM_FLOW : 0) ); // 겨울 operationalStatusList[0].winterAll = data.winter === null ? '' : ( @@ -1230,29 +1460,47 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) let summerChungchunDay = 0; let winterChungchuDay = 0; + let totFlowMax = 0; + let totFlowMin = 9999999; + let yearSumFlow = 0; let maxYearSumFlow = 0; let minYearSumFlow = 9999999; let summerSumFlow = 0; let summerChungchunSumFlow = 0; let summerRainDaySumFlow = 0; + let summerRainDayFlow = 0; + let summerRainDayReturnFlow = 0; + let summerRainDayEfflFlow = 0; + let winterSumFlow = 0; let winterChungchunSumFlow = 0; let minWinterChungchunSumFlow = 9999999; let maxWinterChungchunSumFlow = 0; - + // 연계처리수,지하수유입량 const bscFctCd = fcltyCd; - const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse; + const res2 = await fetchFlowRateModalList(bscFctCd, searchYear); yearDay = res2.data?res2.data.length:1; - res2.data.forEach((item: FlowDataItem) => { + res2.data.forEach((item: any) => { yearSumFlow += item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0; if(maxYearSumFlow < (item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0)) { maxYearSumFlow = item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0; } - if(minYearSumFlow > (item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0) || minYearSumFlow === 0) { + if(minYearSumFlow > (item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0)) { minYearSumFlow = item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0; } + + // 1년 최대 총 하수유입량 + let totYearFlow = 0; + totYearFlow = (item.inflAmnt && item.inflAmnt !== 'x' ? Number(item.inflAmnt.toString().trim()) : 0) + (item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0) + (item.returnAmnt && item.returnAmnt !== 'x' ? Number(item.returnAmnt.toString().trim()) : 0); + if(totFlowMax < totYearFlow) { + totFlowMax = totYearFlow; + } + if(totFlowMin > totYearFlow || totFlowMin === 0) { + totFlowMin = totYearFlow; + } + if(item.msrDt.substring(4,6) === '06' || item.msrDt.substring(4,6) === '07' || item.msrDt.substring(4,6) === '08') { summerDay += 1; summerSumFlow += item.sumFlow && item.sumFlow !== 'x' ? Number(item.sumFlow.toString().trim()) : 0; @@ -1262,54 +1510,103 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) } }); - const calData = calRainEffectDay(res2.data, 'SUNNY'); - const calRainDate = calRainEffectDay(res2.data, 'RAIN'); + const clone = (arr: any[]) => arr?.map(v => ({ ...v })) ?? []; + const calData = CalcRainEffect(clone(res2.data), 'SUNNY'); + const calRainDate = CalcRainEffect(clone(res2.data), 'RAIN'); // 지하수유입량 - 청천시 기준 let chungcunSumFlow = 0; let sumSummerChungcunFlow = 0; let sumWinterChungcunFlow = 0; + + // 하절기 청천시 총인설비 반류수 + let summerChungchunDayReturnAmnt = 0; + // 하절기 청천시 방류수 + let summerChungchunDayEfflAmnt = 0; + + // 동절기 총 유입량 최대, 최소 + let winterChungchunTotalInflAmntMax = 0 ; + let winterChungchunTotalInflAmntMin = 9999999 ; + // 동절기 청천시 하수유입량 최대, 최소 + let winterChungchunDayFlowMax = 0 ; + let winterChungchunDayFlowMin = 9999999 ; + // 동절기 청천시 총인반류수 최대, 최소, 평균 + let winterChungchunDayReturnMax = 0 ; + let winterChungchunDayReturnMin = 9999999 ; + let winterChungchunDayReturnAvg = 0 ; + // 동절기 청천시 방류량 최대, 최소, 평균 + let winterChungchunDayEfflMax = 0 ; + let winterChungchunDayEfflMin = 9999999 ; + let winterChungchunDayEfflAvg = 0; // 하절기, 동절기 청천시 계산 - calData.forEach((flowItem: FlowDataItem) => { + 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'){ summerChungchunDay += 1; summerChungchunSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + summerChungchunDayReturnAmnt += flowItem.returnAmnt && flowItem.returnAmnt !== 'x' ? Number(flowItem.returnAmnt.toString().trim()) : 0; + summerChungchunDayEfflAmnt += flowItem.efflAmnt && flowItem.efflAmnt !== 'x' ? Number(flowItem.efflAmnt.toString().trim()) : 0; + }else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){ - if(minWinterChungchunSumFlow > (flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0) || minWinterChungchunSumFlow === 0) { + winterChungchuDay += 1; + winterChungchunSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; + sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + winterChungchunDayReturnAvg += flowItem.returnAmnt && flowItem.returnAmnt !== 'x' ? Number(flowItem.returnAmnt.toString().trim()) : 0; + winterChungchunDayEfflAvg += flowItem.efflAmnt && flowItem.efflAmnt !== 'x' ? Number(flowItem.efflAmnt.toString().trim()) : 0; + + let totWinterTotalInflAmnt = 0; + totWinterTotalInflAmnt = (flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0) + (flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0) + (flowItem.returnAmnt && flowItem.returnAmnt !== 'x' ? Number(flowItem.returnAmnt.toString().trim()) : 0); + if(winterChungchunTotalInflAmntMax < totWinterTotalInflAmnt) { + winterChungchunTotalInflAmntMax = totWinterTotalInflAmnt; + } + if(winterChungchunTotalInflAmntMin > totWinterTotalInflAmnt || winterChungchunTotalInflAmntMin === 0) { + winterChungchunTotalInflAmntMin = totWinterTotalInflAmnt; + } + + if(winterChungchunDayFlowMin > (flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0)) { + winterChungchunDayFlowMin = flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + } + if(winterChungchunDayFlowMax < (flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0)) { + winterChungchunDayFlowMax = flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + } + + if(minWinterChungchunSumFlow > (flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0) ) { minWinterChungchunSumFlow = flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; } if(maxWinterChungchunSumFlow < (flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0)) { maxWinterChungchunSumFlow = flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; } - winterChungchuDay += 1; - winterChungchunSumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; - sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + + if(winterChungchunDayReturnMin > (flowItem.returnAmnt && flowItem.returnAmnt !== 'x' ? Number(flowItem.returnAmnt.toString().trim()) : 0)) { + winterChungchunDayReturnMin = flowItem.returnAmnt && flowItem.returnAmnt !== 'x' ? Number(flowItem.returnAmnt.toString().trim()) : 0; + } + if(winterChungchunDayReturnMax < (flowItem.returnAmnt && flowItem.returnAmnt !== 'x' ? Number(flowItem.returnAmnt.toString().trim()) : 0)) { + winterChungchunDayReturnMax = flowItem.returnAmnt && flowItem.returnAmnt !== 'x' ? Number(flowItem.returnAmnt.toString().trim()) : 0; + } + + if(winterChungchunDayEfflMin > (flowItem.efflAmnt && flowItem.efflAmnt !== 'x' ? Number(flowItem.efflAmnt.toString().trim()) : 0)) { + winterChungchunDayEfflMin = flowItem.efflAmnt && flowItem.efflAmnt !== 'x' ? Number(flowItem.efflAmnt.toString().trim()) : 0; + } + if(winterChungchunDayEfflMax < (flowItem.efflAmnt && flowItem.efflAmnt !== 'x' ? Number(flowItem.efflAmnt.toString().trim()) : 0)) { + winterChungchunDayEfflMax = flowItem.efflAmnt && flowItem.efflAmnt !== 'x' ? Number(flowItem.efflAmnt.toString().trim()) : 0; + } } }); // 하절기 강우시 계산 - calRainDate.forEach((flowItem: FlowDataItem) => { + calRainDate.forEach((flowItem: any) => { if(flowItem.msrDt.substring(4,6) === '06' || flowItem.msrDt.substring(4,6) === '07' || flowItem.msrDt.substring(4,6) === '08') { summerRainDay += 1; summerRainDaySumFlow += flowItem.sumFlow && flowItem.sumFlow !== 'x' ? Number(flowItem.sumFlow.toString().trim()) : 0; + summerRainDayFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; + summerRainDayReturnFlow += flowItem.returnAmnt && flowItem.returnAmnt !== 'x' ? Number(flowItem.returnAmnt.toString().trim()) : 0; + summerRainDayEfflFlow += flowItem.efflAmnt && flowItem.efflAmnt !== 'x' ? Number(flowItem.efflAmnt.toString().trim()) : 0; } }); - operationalStatusList[0].yearAvg = roundUp(Number(operationalStatusList[0].yearAvg) + (yearSumFlow&&Number(yearSumFlow) != 0?Number(yearSumFlow / yearDay):0), 0); - operationalStatusList[0].yearMax = roundUp(Number(operationalStatusList[0].yearMax) + Number(maxYearSumFlow), 0); - operationalStatusList[0].yearMin = roundUp(Number(operationalStatusList[0].yearMin) + Number(minYearSumFlow), 0); - operationalStatusList[0].summerAll = roundUp(Number(operationalStatusList[0].summerAll) + (summerSumFlow&&Number(summerSumFlow)!=0?Number(summerSumFlow / summerDay):0), 0); - operationalStatusList[0].summerThree = roundUp(Number(operationalStatusList[0].summerThree) + (summerRainDaySumFlow&&Number(summerRainDaySumFlow)!=0?Number(summerRainDaySumFlow / summerRainDay):0), 0); - operationalStatusList[0].summerRain = roundUp(Number(operationalStatusList[0].summerRain) + (summerChungchunSumFlow&&Number(summerChungchunSumFlow)!=0?Number(summerChungchunSumFlow / summerChungchunDay):0), 0); - operationalStatusList[0].winterAll = roundUp(Number(operationalStatusList[0].winterAll) + (winterSumFlow&&Number(winterSumFlow)!=0?Number(winterSumFlow / winterDay):0), 0); - operationalStatusList[0].winterSunnyMin = roundUp(Number(operationalStatusList[0].winterSunnyMin) + Number(minWinterChungchunSumFlow), 0); - operationalStatusList[0].winterSunnyMax = roundUp(Number(operationalStatusList[0].winterSunnyMax) + (winterChungchunSumFlow&&Number(winterChungchunSumFlow)!=0?Number(winterChungchunSumFlow / winterChungchuDay):0), 0); - operationalStatusList[0].winterSunnyAvg = roundUp(Number(operationalStatusList[0].winterSunnyAvg) + Number(maxWinterChungchunSumFlow), 0); - // 연계처리수 yearAvgSumFlow = Number((yearSumFlow&&Number(yearSumFlow)!=0)?(yearSumFlow / yearDay):''); yearMaxSumFlow = maxYearSumFlow; @@ -1322,14 +1619,58 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) winterSunnyAvg = winterChungchunSumFlow&&Number(winterChungchunSumFlow)!=0?(winterChungchunSumFlow / winterChungchuDay):0; winterSunnyMax = maxWinterChungchunSumFlow; + // 하절기 강우시 계산 + // 하수유입량 (강우시) + summerRainInflAmnt = summerRainDayFlow&&Number(summerRainDayFlow)!=0?Number(summerRainDayFlow / summerRainDay):0; + // 총인설비방류수 (강우시) + summerRainReturnAmnt = summerRainDayReturnFlow&&Number(summerRainDayReturnFlow)!=0?Number(summerRainDayReturnFlow / summerRainDay):0; + // 방루량 (강우시) + summerRainEfflAmnt = summerRainDayEfflFlow&&summerRainDayEfflFlow!=0?summerRainDayEfflFlow / summerRainDay:0; + + // 동절기 청천시 계산 + // 하수유입량 (청천시) 평균 + winterChungchunFlowAvg = sumWinterChungcunFlow&&Number(sumWinterChungcunFlow)!=0?(sumWinterChungcunFlow / winterChungchuDay):0; + // 총인반류수 (청천시) 평균 + winterChungchunReturnAvg = winterChungchunDayReturnAvg&&Number(winterChungchunDayReturnAvg)!=0?(winterChungchunDayReturnAvg / winterChungchuDay):0; + // 방류량 (청천시) 평균 + winterChungchunEfflAvg = winterChungchunDayEfflAvg&&Number(winterChungchunDayEfflAvg)!=0?(winterChungchunDayEfflAvg / winterChungchuDay):0; + // 하수유입량 (청천시) 최대 + winterChungchunFlowMax = winterChungchunDayFlowMax; + // 총인반류수 (청천시) 최대 + winterChungchunReturnMax = winterChungchunDayReturnMax; + // 방류량 (청천시) 최대 + winterChungchunEfflMax = winterChungchunDayEfflMax; + // 하수유입량 (청천시) 최소 + winterChungchunFlowMin = winterChungchunDayFlowMin; + // 총인반류수 (청천시) 최소 + winterChungchunReturnMin = winterChungchunDayReturnMin; + // 방류량 (청천시) 최소 + winterChungchunEfflMin = winterChungchunDayEfflMin + + operationalStatusList[0].yearAvg = roundUp(Number(operationalStatusList[0].yearAvg), 0) + roundUp(yearAvgSumFlow, 0); + operationalStatusList[0].yearMax = roundUp(totFlowMax, 0); // + roundUp(yearMaxSumFlow, 0); + operationalStatusList[0].yearMin = roundUp(totFlowMin, 0); + operationalStatusList[0].summerAll = roundUp(Number(operationalStatusList[0].summerAll), 0) + roundUp(summerAll, 0); + operationalStatusList[0].summerThree = roundUp(Number(operationalStatusList[0].summerThree), 0) + roundUp(summerThree, 0); + operationalStatusList[0].summerRain = roundUp(Number(operationalStatusList[0].summerRain), 0) + roundUp(summerRain, 0); + operationalStatusList[0].winterAll = roundUp(Number(operationalStatusList[0].winterAll), 0) + roundUp(winterAll, 0); + operationalStatusList[0].winterSunnyMin = roundUp(winterChungchunTotalInflAmntMin, 0); + operationalStatusList[0].winterSunnyMax = roundUp(winterChungchunTotalInflAmntMax, 0); + operationalStatusList[0].winterSunnyAvg = roundUp(Number(operationalStatusList[0].winterSunnyAvg), 0) + roundUp(winterSunnyAvg, 0); + // 지하수유입량 const usage = chungcunSumFlow / calData.length; const summerUsage = sumSummerChungcunFlow / summerChungchunDay; const winterUsage = sumWinterChungcunFlow / winterChungchuDay; - operationalStatusList[0].groundWaterAvg = Math.round((usage-(usage*0.65*0.8)) * 100) / 100; - operationalStatusList[0].groundWaterSummer = Math.round((summerUsage-(summerUsage*0.65*0.8)) * 100) / 100; - operationalStatusList[0].groundWaterWinter = Math.round((winterUsage-(winterUsage*0.65*0.8)) * 100) / 100; + // 임시 계산변수값들 메인에 대입 + summerChungchunFlow = summerUsage; + summerChungchunReturnAmnt = summerChungchunDayReturnAmnt / summerChungchunDay; + summerChungchunEfflAmnt = summerChungchunDayEfflAmnt / summerChungchunDay; + + operationalStatusList[0].groundWaterAvg = Math.round((usage-(usage*0.65*OSU_PERCENT)) * 100) / 100; + operationalStatusList[0].groundWaterSummer = Math.round((summerUsage-(summerUsage*0.65*OSU_PERCENT)) * 100) / 100; + operationalStatusList[0].groundWaterWinter = Math.round((winterUsage-(winterUsage*0.65*OSU_PERCENT)) * 100) / 100; //operationalStatusList[0].groundWaterAvg = calData.length === 0 ? '' : Number(calData[0].inflAmnt) - (Number(calData[0].inflAmnt)*0.65*0.8); //operationalStatusList[0].groundWaterSummer = calData.length === 0 ? '' : Number(calData[0].inflAmnt) - (Number(calData[0].inflAmnt)*0.65*0.8); @@ -1343,7 +1684,6 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) const summerLowRain = data.summerBod&&data.summerBod.INFO_RN_DAY&&data.summerBod.INFO_RN_DAY!='null'?Number(data.summerBod.INFO_RN_DAY):0; operationalStatusList[0].rdi = winterAvgBod===0?0:roundUp(summerLowFlow * ((winterAvgBod - summerLowBod) / winterAvgBod), 2); operationalStatusList[0].rdiRain = summerLowRain; - dataFormSetting(operationalStatusList[0]); } if(operationalStatusList[0] && operationalStatusList[7]){ @@ -1373,6 +1713,17 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) } } + // 순수하수량 + if(operationalStatusList[1]){ + operationalStatusList[1].summerThree = summerRainInflAmnt; + operationalStatusList[1].summerRain = summerChungchunFlow; + operationalStatusList[1].winterSunnyAvg = winterChungchunFlowAvg; + operationalStatusList[1].winterSunnyMax = winterChungchunFlowMax; + operationalStatusList[1].winterSunnyMin = winterChungchunFlowMin; + dataFormSetting(operationalStatusList[1]); + } + + // 연계처리수 if(operationalStatusList[2]){ operationalStatusList[2].yearAvg = yearAvgSumFlow; operationalStatusList[2].yearMax = yearMaxSumFlow; @@ -1386,11 +1737,69 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) operationalStatusList[2].winterSunnyMax = winterSunnyMax; dataFormSetting(operationalStatusList[2]); } + + // 총인설비방류수 + if(operationalStatusList[3]){ + operationalStatusList[3].summerThree = summerRainReturnAmnt; + operationalStatusList[3].summerRain = summerChungchunReturnAmnt; + operationalStatusList[3].winterSunnyAvg = winterChungchunReturnAvg; + operationalStatusList[3].winterSunnyMax = winterChungchunReturnMax; + operationalStatusList[3].winterSunnyMin = winterChungchunReturnMin; + dataFormSetting(operationalStatusList[3]); + } + + // 방류수 + if(operationalStatusList[4]){ + operationalStatusList[4].summerThree = summerRainEfflAmnt; + operationalStatusList[4].summerRain = summerChungchunEfflAmnt; + operationalStatusList[4].winterSunnyAvg = winterChungchunEfflAvg; + operationalStatusList[4].winterSunnyMax = winterChungchunEfflMax; + operationalStatusList[4].winterSunnyMin = winterChungchunEfflMin; + dataFormSetting(operationalStatusList[4]); + } + + if (operationalStatusList[0]) { + // 안전하게 숫자 변환하는 함수 + const toNum = (val) => { + if (val === null || val === undefined || val === '' || val === '0') return 0; + return Number(val.toString().replaceAll(',', '')) || 0; + }; + + operationalStatusList[0].summerAll = + toNum(operationalStatusList[1]?.summerAll) + + toNum(operationalStatusList[2]?.summerAll) + + toNum(operationalStatusList[3]?.summerAll); + + operationalStatusList[0].summerThree = + toNum(operationalStatusList[1]?.summerThree) + + toNum(operationalStatusList[2]?.summerThree) + + toNum(operationalStatusList[3]?.summerThree); + + operationalStatusList[0].summerRain = + toNum(operationalStatusList[1]?.summerRain) + + toNum(operationalStatusList[2]?.summerRain) + + toNum(operationalStatusList[3]?.summerRain); + + operationalStatusList[0].winterAll = + toNum(operationalStatusList[1]?.winterAll) + + toNum(operationalStatusList[2]?.winterAll) + + toNum(operationalStatusList[3]?.winterAll); + + operationalStatusList[0].winterSunnyAvg = + toNum(operationalStatusList[1]?.winterSunnyAvg) + + toNum(operationalStatusList[2]?.winterSunnyAvg) + + toNum(operationalStatusList[3]?.winterSunnyAvg); + + dataFormSetting(operationalStatusList[0]); + } } - // - if(data.yearData.TP_INFL_WQLT_TP === null || data.yearData.TP_INFL_WQLT_TP === undefined || data.yearData.TP_INFL_WQLT_TP === 'null') { - operationalStatusList = operationalStatusList.slice(0, 10); + const rtnData = await calcWaterQltyData(operationalStatusList, searchYear, fcltyCd); + operationalStatusList = rtnData; + + // 총인설비가 없을 경우 제외 + if(!data.yearData.REAL_TP_EFFCTV || data.yearData.REAL_TP_EFFCTV === null) { + operationalStatusList = operationalStatusList.slice(0, 11); } set((state: DashBoardType) => ({ ...state, @@ -1412,6 +1821,24 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) }, })); const res = await fetchMainGraph(searchYear, fcltyCd); + const res2 = await fetchFacilityWaterQltyInfo(fcltyCd); + + // 법적방류수질 데이터 + const sortedWaterQltyInfo = [...res2].sort((a, b) => { + // 숫자로 변환하여 비교 + const numA = Number(a.extnsSeqno); + const numB = Number(b.extnsSeqno); + if (!isNaN(numA) && !isNaN(numB)) { + return numA - numB; + } + // 숫자 변환이 실패하면 문자열로 비교 + return String(a.extnsSeqno).localeCompare(String(b.extnsSeqno)); + }); + + const waterQltyStandartd : any = sortedWaterQltyInfo && sortedWaterQltyInfo.length > 0 + ? sortedWaterQltyInfo[sortedWaterQltyInfo.length - 1] + : []; + if(res == null || res.data == null || res.data.length === 0) { set((state: DashBoardType) => ({ ...state, @@ -1426,6 +1853,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) chart_efflTn: [], chart_inflBod: [], chart_efflBod: [], + waterQltyStandartd : [], isLoadingMainGraph : false, } })); @@ -1449,10 +1877,10 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) label: item.msrDt.substring(0, 4)+"-"+item.msrDt.substring(4, 6)+"-"+item.msrDt.substring(6, 8), val : item.inflAssctBfrWqltTp ?? 0 })); - + const chart_chongInTp = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({ label: item.msrDt.substring(0, 4)+"-"+item.msrDt.substring(4, 6)+"-"+item.msrDt.substring(6, 8), - val : item.tpInflWqltTp ?? 0 + val : Number(item.tpInflWqltTp) == 0 ? null : item.tpInflWqltTp })); const chart_efflTp = res.data.wqltObjs.map((item: FacilityWaterQltyProps) => ({ @@ -1493,6 +1921,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) chart_efflTn: chart_efflTn, chart_inflBod: chart_inflBod, chart_efflBod: chart_efflBod, + waterQltyStandartd : waterQltyStandartd, isLoadingMainGraph : false, }, })) @@ -1554,7 +1983,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) // 청천시 중 강우영향일인 날짜는 이전의 강우량을 대입해 리스트 수정 - const rainEffectList = calRainEffectDayRainManage(res.data.wqltObjs); + const rainEffectList = CalcRainEffect(res.data.wqltObjs, 'RAIN_DAY'); // Process the data and create rain management list const totItemCnt = rainEffectList?rainEffectList.length : 1; @@ -1581,7 +2010,9 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) totEfflWqltTn += item.efflWqltTn ? Number(item.efflWqltTn.toString().trim()) : 0; totEfflWqltTp += item.efflWqltTp ? Number(item.efflWqltTp.toString().trim()) : 0; - if(Number(item.infoRnDay) >= 3 && Number(item.infoRnDay) < 10){ + const toBeRain = item.toBeInfoRnDay ? Number(item.toBeInfoRnDay) : 0; + + if(toBeRain >= 3 && toBeRain < 10){ rainDate[1] = Number(rainDate[1] || 0) + 1; inflAmtCnt[1] = Number(inflAmtCnt[1] || 0) + 1; inflAmnt[1] = Number(inflAmnt[1] || 0) + Number(item.inflAmnt || 0); @@ -1606,7 +2037,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) efflWqltTn[1] = Number(efflWqltTn[1] || 0) + Number(item.efflWqltTn || 0); efflWqltTpCnt[1] = Number(efflWqltTpCnt[1] || 0) + 1; efflWqltTp[1] = Number(efflWqltTp[1] || 0) + Number(item.efflWqltTp || 0); - }else if(Number(item.infoRnDay) >= 10 && Number(item.infoRnDay) < 20){ + }else if(toBeRain >= 10 && toBeRain < 20){ rainDate[2] = Number(rainDate[2] || 0) + 1; inflAmtCnt[2] = Number(inflAmtCnt[2] || 0) + 1; inflAmnt[2] = Number(inflAmnt[2] || 0) + Number(item.inflAmnt || 0); @@ -1631,7 +2062,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) efflWqltTn[2] = Number(efflWqltTn[2] || 0) + Number(item.efflWqltTn || 0); efflWqltTpCnt[2] = Number(efflWqltTpCnt[2] || 0) + 1; efflWqltTp[2] = Number(efflWqltTp[2] || 0) + Number(item.efflWqltTp || 0); - }else if(Number(item.infoRnDay) >= 20 && Number(item.infoRnDay) < 30){ + }else if(toBeRain >= 20 && toBeRain < 30){ rainDate[3] = Number(rainDate[3] || 0) + 1; inflAmtCnt[3] = Number(inflAmtCnt[3] || 0) + 1; inflAmnt[3] = Number(inflAmnt[3] || 0) + Number(item.inflAmnt || 0); @@ -1656,7 +2087,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) efflWqltTn[3] = Number(efflWqltTn[3] || 0) + Number(item.efflWqltTn || 0); efflWqltTpCnt[3] = Number(efflWqltTpCnt[3] || 0) + 1; efflWqltTp[3] = Number(efflWqltTp[3] || 0) + Number(item.efflWqltTp || 0); - }else if(Number(item.infoRnDay) >= 30 && Number(item.infoRnDay) < 40){ + }else if(toBeRain >= 30 && toBeRain < 40){ rainDate[4] = Number(rainDate[4] || 0) + 1; inflAmtCnt[4] = Number(inflAmtCnt[4] || 0) + 1; inflAmnt[4] = Number(inflAmnt[4] || 0) + Number(item.inflAmnt || 0); @@ -1681,7 +2112,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) efflWqltTn[4] = Number(efflWqltTn[4] || 0) + Number(item.efflWqltTn || 0); efflWqltTpCnt[4] = Number(efflWqltTpCnt[4] || 0) + 1; efflWqltTp[4] = Number(efflWqltTp[4] || 0) + Number(item.efflWqltTp || 0); - }else if(Number(item.infoRnDay) >= 40 && Number(item.infoRnDay) < 50){ + }else if(toBeRain >= 40 && toBeRain < 50){ rainDate[5] = Number(rainDate[5] || 0) + 1; inflAmtCnt[5] = Number(inflAmtCnt[5] || 0) + 1; inflAmnt[5] = Number(inflAmnt[5] || 0) + Number(item.inflAmnt || 0); @@ -1706,7 +2137,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) efflWqltTn[5] = Number(efflWqltTn[5] || 0) + Number(item.efflWqltTn || 0); efflWqltTpCnt[5] = Number(efflWqltTpCnt[5] || 0) + 1; efflWqltTp[5] = Number(efflWqltTp[5] || 0) + Number(item.efflWqltTp || 0); - }else if(Number(item.infoRnDay) >= 50 && Number(item.infoRnDay) < 60){ + }else if(toBeRain >= 50 && toBeRain < 60){ rainDate[6] = Number(rainDate[6] || 0) + 1; inflAmtCnt[6] = Number(inflAmtCnt[6] || 0) + 1; inflAmnt[6] = Number(inflAmnt[6] || 0) + Number(item.inflAmnt || 0); @@ -1731,7 +2162,7 @@ export const dashBoardReducer:(set:(fn: (state: DashBoardType) => DashBoardType) efflWqltTn[6] = Number(efflWqltTn[6] || 0) + Number(item.efflWqltTn || 0); efflWqltTpCnt[6] = Number(efflWqltTpCnt[6] || 0) + 1; efflWqltTp[6] = Number(efflWqltTp[6] || 0) + Number(item.efflWqltTp || 0); - }else if(Number(item.infoRnDay) >= 60){ + }else if(toBeRain >= 60){ rainDate[7] = Number(rainDate[7] || 0) + 1; inflAmtCnt[7] = Number(inflAmtCnt[7] || 0) + 1; inflAmnt[7] = Number(inflAmnt[7] || 0) + Number(item.inflAmnt || 0); diff --git a/apps/fo/app/store/facilityPrecipitation/index.tsx b/apps/fo/app/store/facilityPrecipitation/index.tsx index 66727122d..77a053fc5 100644 --- a/apps/fo/app/store/facilityPrecipitation/index.tsx +++ b/apps/fo/app/store/facilityPrecipitation/index.tsx @@ -49,11 +49,11 @@ export interface ExcelType { 시군구: string, 시설이름: string, 주소: string, - 시설용량: number, + "시설옹량(m³/일)": number, 관측소정보 : string, - 강우일 : number, - 강우영향일 : number, - 연간총강수량 : number, + "강우일(일)": number, + "강우영향일(일)": number, + "연간총강수량(mm)": number, } /**==================================== @@ -135,7 +135,6 @@ const gridListPrecipitationDetail:PrecipitationPropsDetailProps[] = [ const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { const tailStr = '/'+pageNo + '/' + pageSize + '/' + searchYear + (part?'/' + part:'' ) + (nameCd?'/' + nameCd:'' ) + (fcltCpct?'/' + fcltCpct:'' ) + (operationValue?'/' + operationValue:'' ) + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') ; - console.log('tailStr', tailStr); const url = '/fclt/rain' + tailStr; const res = await getFetch('fo', url); const tmpData:PrecipitationPropsDetailProps[] = []; @@ -146,31 +145,13 @@ const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number, const rainDt = res.data[idx].rainyDayObjList[idx2].rainDt; const infoRnDay = res.data[idx].rainyDayObjList[idx2].infoRnDay; const rainDay = res.data[idx].rainyDayObjList[idx2].infoRnDay>=3?1:0; - let rainEffectDay = 0; - if(idx2 < res.data[idx].rainyDayObjList.length-2){ - if(rainDay==1){ - rainEffectDay = 1; - } else { - if(idx2 >= 2){ - if(res.data[idx].rainyDayObjList[idx2-1].infoRnDay>=3 || res.data[idx].rainyDayObjList[idx2-2].infoRnDay>=3){ - rainEffectDay = 1; - } - } - } - } else if(idx2 < res.data[idx].rainyDayObjList.length-1){ - if(rainDay==1 || res.data[idx].rainyDayObjList[idx2+1].infoRnDay>=3){ - rainEffectDay = 1; - } - } else { - rainEffectDay = rainDay; - } tmpData.push({ bscFctCd : bscFctCd, rainDt : rainDt, infoRnDay : infoRnDay, rainDay : rainDay, - rainEffectDay : rainEffectDay + rainEffectDay : rainDay }) } } @@ -183,8 +164,10 @@ const fetchFacilityPrecipitationList = async (pageNo: number, pageSize: number, item.rainEffectDay = filteredList.reduce((acc, curr) => acc + curr.rainEffectDay, 0); item.totalYearRain = filteredList.reduce((acc, curr) => acc + curr.infoRnDay, 0); item.infoRnDay = filteredList.reduce((acc, curr) => acc + curr.rainDay, 0); - }) + }); + } + return { data: res.data, count: res.count, detailData: tmpData }; } @@ -280,11 +263,11 @@ export const facilityPrecipitationReducer:(set:(fn: (state: FacilityPrecipitatio 시군구: item.gugun, 시설이름: item.bscFctNm, 주소: item.addr, - 시설용량: item.fctCpc, + "시설옹량(m³/일)": item.fctCpc, 관측소정보: item.stnKo, - 강우일: item.infoRnDay, - 강우영향일: item.rainEffectDay, - 연간총강수량: item.totalYearRain, + "강우일(일)": item.infoRnDay, + "강우영향일(일)": item.rainEffectDay, + "연간총강수량(mm)": item.totalYearRain, }) }) }else{ diff --git a/apps/fo/app/store/facilityWaterQlty/index.tsx b/apps/fo/app/store/facilityWaterQlty/index.tsx index 5b7bcf816..f8b874c85 100644 --- a/apps/fo/app/store/facilityWaterQlty/index.tsx +++ b/apps/fo/app/store/facilityWaterQlty/index.tsx @@ -1,6 +1,7 @@ import { getFetch } from "@/app/components/api"; -import DataForm from "@/app/components/common/DataForm"; +import DataForm, { roundNumber } from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; +import CalcRainEffect from "@/app/components/common/CalcRainEffect"; export type { TableUpperProps }; /**==================================== @@ -42,7 +43,7 @@ export interface FacilityWaterQltyProps { mdmbsn:string|'', inflAmnt: number | '', lclgvrnmntNm: string, - infoRnDay: number | '', + infoRnDay: number | string | '', rainEffectDay: number | '', tpInflWqltTmprtr: number | '', tpInflWqltPh: string | '', @@ -53,6 +54,7 @@ export interface FacilityWaterQltyProps { tpInflWqltTp: string | '', tpInflWqltEclgyTox: string | '', tpInflWqltClfgrpcnt: string | '', + noProcessInflAmnt : string | number | '', } export interface ExcelType { 시설코드: string, @@ -64,17 +66,17 @@ export interface ExcelType { 시군구: string, 시설이름: string, 주소: string, - 용량: number, - 유입BOD: string | '', - 유입TOC: string | '', - 유입SS: string | '', - 유입TN: string | '', - 유입TP: string | '', - 유출BOD: string | '', - 유출TOC: string | '', - 유출SS: string | '', - 유출TN: string | '', - 유출TP: string | '', + "시설용량(m³/일)": number, + "유입BOD(mg/L)": string | '', + "유입TOC(mg/L)": string | '', + "유입SS(mg/L)": string | '', + "유입TN(mg/L)": string | '', + "유입TP(mg/L)": string | '', + "유출BOD(mg/L)": string | '', + "유출TOC(mg/L)": string | '', + "유출SS(mg/L)": string | '', + "유출TN(mg/L)": string | '', + "유출TP(mg/L)": string | '', } /** @@ -208,7 +210,8 @@ const upHeadListModalYear: TableUpperProps[] = [ { id: "efflWqltSs", title: "SS\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" }, { id: "efflWqltTn", title: "T-N\n(mg/L)", upName: "upChangeRe2", upSequnce: 2, align: "right" }, { id: "efflWqltTp", title: "T-P\n(mg/L)", upName: "upChangeRe2", upSequnce: 3, align: "right" }, - /* { id: "infoRnDay", title: "강우량(mm/일)", align: "right" }, */ + { id: "noProcessInflAmnt", title: "미처리하수량\n(m³/일)", align:"right"}, + { id: "infoRnDay", title: "강우량\n(mm/일)", align: "right" } ]; // 처리시설 수질현황 헤더(모달-수질TMS) @@ -375,6 +378,7 @@ export type FacilityWaterQltyActions = { */ const dataFormSetting = (item: FacilityWaterQltyProps) => { DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record<string, unknown> }); + DataForm({ type: 'float1', column: 'infoRnDay', item: item as unknown as Record<string, unknown> }); } export type FacilityWaterQltyStore = FacilityWaterQltyType & FacilityWaterQltyActions; @@ -461,17 +465,17 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType 시군구: item.sggNm, 시설이름: item.bscFctNm, 주소: item.addr, - 용량: item.fctCpc, - 유입BOD: item.inflAssctBfrWqltBod, - 유입TOC: item.inflAssctBfrWqltToc, - 유입SS: item.inflAssctBfrWqltSs, - 유입TN: item.inflAssctBfrWqltTn, - 유입TP: item.inflAssctBfrWqltTp, - 유출BOD: item.efflWqltBod, - 유출TOC: item.efflWqltToc, - 유출SS: item.efflWqltSs, - 유출TN: item.efflWqltTn, - 유출TP: item.efflWqltTp, + "시설용량(m³/일)": item.fctCpc, + "유입BOD(mg/L)": item.inflAssctBfrWqltBod, + "유입TOC(mg/L)": item.inflAssctBfrWqltToc, + "유입SS(mg/L)": item.inflAssctBfrWqltSs, + "유입TN(mg/L)": item.inflAssctBfrWqltTn, + "유입TP(mg/L)": item.inflAssctBfrWqltTp, + "유출BOD(mg/L)": item.efflWqltBod, + "유출TOC(mg/L)": item.efflWqltToc, + "유출SS(mg/L)": item.efflWqltSs, + "유출TN(mg/L)": item.efflWqltTn, + "유출TP(mg/L)": item.efflWqltTp, }); }); }else{ @@ -573,48 +577,33 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType } // facilityPrecipitation의 rainEffectDay 계산 로직을 적용 - - const data = res.data.wqltObjs; - // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) - for(let idx = 0; idx < data.length; idx++) { - const item = data[idx]; - if(item){ - if(item.infoRnDay && Number(item.infoRnDay) > 3) { - item.rainEffectDay = 1; - } else { - item.rainEffectDay = 0; - } - } - } + const data = CalcRainEffect(res.data.wqltObjs); - // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 - for(let idx = 0; idx < data.length; idx++) { - if(data[idx]) { - // 하루 전이 강우영향일(3 이상)인 경우 - if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay) >= 3) { - data[idx]!.rainEffectDay = 1; - } - // 이틀 전이 강우영향일(3 이상)인 경우 - if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay) >= 3) { - data[idx]!.rainEffectDay = 1; - } - } - } + /** + * [(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​ + /강우시 일별유입BOD) + */ + //let rainInflAmnt = 0; + let sunnyInflAmnt = 0; + let sunnyBod = 0; + //let rainDay = 0; + let sunnyDay = 0; - for(let idx = 0; idx < data.length; idx++) { - if(data[idx] && data[idx]?.rainEffectDay === 1) { - if(idx > 1){ - if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay) >= 3) { - data[idx]!.infoRnDay = data[idx-1]!.infoRnDay; - } - } - if(idx > 2){ - if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay) >= 3) { - data[idx]!.infoRnDay = data[idx-2]!.infoRnDay; - } - } + data.forEach(item => { + if(item.rainEffectDay == 1){ + //rainDay += 1; + //rainInflAmnt += Number(item.inflAmnt); + } else { + sunnyDay += 1; + sunnyInflAmnt += Number(item.inflAmnt); + sunnyBod += Number(item.inflAssctBfrWqltBod); } - } + }); + + //const yearRainAmnt = rainInflAmnt===0?0:rainInflAmnt / rainDay; + const yearSunnyAmnt = sunnyInflAmnt===0?0:sunnyInflAmnt / sunnyDay; + const yearSunnyBod = sunnyBod===0?0:sunnyBod / sunnyDay; + // const rtnData = data.map((item: FacilityWaterQltyProps) => { dataFormSetting(item) @@ -665,6 +654,11 @@ export const facilityWaterQltyReducer = (set: (fn: (state: FacilityWaterQltyType }else{ item.tpInflWqltTp = ''; } + + const dayBod = Number(item.inflAssctBfrWqltBod); + const noProcessInflAmnt = roundNumber(((Number(item.inflAmnt) * dayBod) - (yearSunnyAmnt * yearSunnyBod)) / dayBod, 0) + item.noProcessInflAmnt = noProcessInflAmnt && Number(noProcessInflAmnt.replaceAll(',','')) > 0 ? noProcessInflAmnt : ''; + return item; }) set((state: FacilityWaterQltyType) => ({ diff --git a/apps/fo/app/store/flowRate/index.tsx b/apps/fo/app/store/flowRate/index.tsx index ec64465d0..571a7ffb2 100644 --- a/apps/fo/app/store/flowRate/index.tsx +++ b/apps/fo/app/store/flowRate/index.tsx @@ -1,6 +1,8 @@ import { getFetch } from "@/app/components/api"; import type { TableUpperProps } from "../dashboard"; -import DataForm from "@/app/components/common/DataForm"; +import DataForm, { roundNumber } from "@/app/components/common/DataForm"; +import CalcRainEffect from "@/app/components/common/CalcRainEffect"; +import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty"; /**==================================== * Store - 타입 @@ -36,17 +38,17 @@ export interface ExcelType { 권역:string|'', 단위유역:string|'', 중권역:string|'', + 환경청:string|'', 시도: string, 시군구: string, 시설이름: string, 주소: string, - 용량: number, - 총유입량: number | '', - 하수유입량: number | '', - 연계처리량: number | '', - 총인반류수량: number | '', - 방류량: number | '', - 환경청:string|'', + "시설용량(m³/일)": number, + "총유입량(m³/일)": number | '', + "하수유입량(m³/일)": number | '', + "연계처리량(m³/일)": number | '', + "총인반류수량(m³/일)": number | '', + "방류량(m³/일)": number | '', } export type modalExcelType = { @@ -70,6 +72,7 @@ export interface FlowRateModalInterface { efflAmnt : number | '', infoRnDay : number | string | '', rainEffectDay : number | string | '' , + noProcessInflAmnt : number | string | '' } export type FlowRateModalProps = { msrDt : string, @@ -80,6 +83,7 @@ export type FlowRateModalProps = { efflAmnt : number, infoRnDay : number | string | '', rainEffectDay : number | string | '', + noProcessInflAmnt : number | string | '' } /**==================================== @@ -154,6 +158,7 @@ const upHeadListFlowRateModal:TableUpperProps[] = [ { id: "sumFlow", title: "연계처리량(m³/일)", align:"right"}, { id: "returnAmnt", title: "총인 반류수량(m³/일)", align:"right"}, { id: "efflAmnt", title: "방류량(m³/일)", align:"right"}, + { id: "noProcessInflAmnt", title: "미처리하수량(m³/일)", align:"right"}, { id: "infoRnDay", title: "강우량(mm/일)", align:"right"} ] @@ -165,7 +170,8 @@ const modalFlowRateListYear:FlowRateModalProps[] = [ ====================================*/ const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { try { - const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr; + const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; + const url = '/fclt/flow/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr; const res = await getFetch('fo', url); return { data: res.data, count: res.count } } catch (error) { @@ -174,7 +180,7 @@ const fetchFlowRateList = async (pageNo: number, pageSize: number, searchYear: s } } -const fetchFlowRateModalList = async (bscFctCd: string, searchYear: string) => { +export const fetchFlowRateModalList = async (bscFctCd: string, searchYear: string) => { try { const url = '/fclt/flow/' + bscFctCd + '/' + searchYear; const res = await getFetch('fo', url); @@ -292,12 +298,12 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow 시군구: item.gugun, 시설이름: item.bscFctNm, 주소: item.daddr, - 용량: item.fctCpc, - 총유입량: item.totInflAmnt, - 하수유입량: item.inflAmnt, - 연계처리량: item.sumFlow, - 총인반류수량: item.returnAmnt, - 방류량: item.efflAmnt, + "시설용량(m³/일)": item.fctCpc, + "총유입량(m³/일)": item.totInflAmnt, + "하수유입량(m³/일)": item.inflAmnt, + "연계처리량(m³/일)": item.sumFlow, + "총인반류수량(m³/일)": item.returnAmnt, + "방류량(m³/일)": item.efflAmnt, }); }); } @@ -318,50 +324,43 @@ export const flowRateSearchReducer:(set:(fn: (state: FlowRateSearchType) => Flow }, searchFlowRateModalList: async (bscFctCd: string, searchYear: string) => { const res = await fetchFlowRateModalList(bscFctCd, searchYear); - const data = res.data; - // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) - for(let idx = 0; idx < data.length; idx++) { - const item = data[idx]; - if(item){ - if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) { - item.rainEffectDay = 1; - } else { - item.rainEffectDay = 0; - } - } - } + const inflData = CalcRainEffect(res.data); - // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 - for(let idx = 0; idx < data.length; idx++) { - if(data[idx]) { - // 하루 전이 강우영향일(3 이상)인 경우 - if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.rainEffectDay = 1; - } - // 이틀 전이 강우영향일(3 이상)인 경우 - if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.rainEffectDay = 1; - } - } - } + const res2 = await fetchFacilityWaterQltyListHist(searchYear, bscFctCd); + const wqltData = CalcRainEffect(res2?.data.wqltObjs); - for(let idx = 0; idx < data.length; idx++) { - if(data[idx] && data[idx]?.rainEffectDay === 1) { - if(idx > 1){ - if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.infoRnDay = data[idx-1]!.infoRnDay; - } - } - if(idx > 2){ - if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.infoRnDay = data[idx-2]!.infoRnDay; - } - } - } - } + /** + * [(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)]​ + /강우시 일별유입BOD) + */ + //let rainInflAmnt = 0; + let sunnyInflAmnt = 0; + let sunnyBod = 0; + //let rainDay = 0; + let sunnyDay = 0; - const rtnData = data.map((item: FlowRateModalProps) => { - item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0) + inflData.forEach(item => { + if(item.rainEffectDay == 1){ + //rainDay += 1; + //rainInflAmnt += Number(item.inflAmnt); + } else { + const msrDt = item.msrDt.replaceAll('-',''); + sunnyDay += 1; + sunnyInflAmnt += Number(item.inflAmnt); + sunnyBod += Number(wqltData.filter((wqitem)=>wqitem.msrDt === msrDt)[0].inflAssctBfrWqltBod); + } + }); + + //const yearRainAmnt = rainInflAmnt===0?0:rainInflAmnt / rainDay; + const yearSunnyAmnt = sunnyInflAmnt===0?0:sunnyInflAmnt / sunnyDay; + const yearSunnyBod = sunnyBod===0?0:sunnyBod / sunnyDay; + + const rtnData = inflData.map((item: FlowRateModalProps) => { + const dayBod = Number(wqltData.filter(wqitem=>wqitem.msrDt === item.msrDt.replaceAll('-',''))[0].inflAssctBfrWqltBod); + const noProcessInflAmnt = roundNumber(((Number(item.inflAmnt) * dayBod) - (yearSunnyAmnt * yearSunnyBod)) / dayBod, 0) + + item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0); + item.noProcessInflAmnt = noProcessInflAmnt && Number(noProcessInflAmnt.replaceAll(',','')) > 0 ? noProcessInflAmnt : ''; dataFormSetting(item); return item; }); diff --git a/apps/fo/app/store/planSewage/index.tsx b/apps/fo/app/store/planSewage/index.tsx index 885949e3b..21a711e8b 100644 --- a/apps/fo/app/store/planSewage/index.tsx +++ b/apps/fo/app/store/planSewage/index.tsx @@ -1,7 +1,9 @@ import DataForm from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; import { getFetch } from "@/app/components/api"; -import { calRainEffectDay, type ApiResponse, type FlowDataItem } from "../underWaterInput"; +import { type ApiResponse, type FlowDataItem } from "../underWaterInput"; +import CalcRainEffect from "@/app/components/common/CalcRainEffect"; +import { roundUp } from "../common"; export type { TableUpperProps }; /**==================================== * Store - 타입 @@ -51,7 +53,7 @@ const upHeadList1:TableUpperProps[] = [ { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' }, { id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' }, - { id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' }, + { id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' }, { id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' }, ]; @@ -64,7 +66,7 @@ const upHeadList2:TableUpperProps[] = [ { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' }, { id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' }, - { id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' }, + { id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' }, { id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' }, ]; @@ -81,7 +83,7 @@ const upHeadList3:TableUpperProps[] = [ { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량(m³/일)", row:0, rowSpan:2, align:'right' }, { id: "spareCapacity", title: "여유용량(m³/일)", row:0, rowSpan:2, align:'right' }, - { id: "variableLoadPercent", title: "변동부하율", row:0, rowSpan:2, align:'right' }, + { id: "variableLoadPercent", title: "변동부하율(%)", row:0, rowSpan:2, align:'right' }, { id: "classifiedSewerPercent", title: "분류식화율(%)", row:0, rowSpan:2, align:'right' }, ]; @@ -94,7 +96,6 @@ const planSewageList:PlanSewageProps[] = [ const fetchPlanSewageList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { const tailStr = partCd ? '/'+ partCd + '/' + (nameCd || '0') + '/' + (fcltCpct || '0') + '/' + (operationValue || '0') +'/0'+ (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; const url = '/prcsFclt/info/plan/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr; - console.log(url); const res = await getFetch('fo', url); return { data: res.data, count: res.count } } @@ -112,10 +113,10 @@ export type ExcelType = { 시군구: string; 시설이름: string; 주소: string; - 시설용량: number; - 여유용량: number; - 변동부하율 : number; - 분류식화율 : number; + "시설용량(m³/일)": number; + "여유용량(m³/일)": number; + "변동부하율(%)" : number; + "분류식화율(%)" : number; } const dataFormSetting=(item : PlanSewageProps)=> { @@ -182,22 +183,25 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy const data = res.data const processedData = await Promise.all(data.map(async (item:PlanSewageProps) => { const res2 = await getFetch('fo', '/fclt/flow/' + item.bscFctCd + '/' + searchYear) as ApiResponse; - const calData = calRainEffectDay(res2.data, 'SUNNY'); + const calData = CalcRainEffect(res2.data, 'SUNNY'); let sumInflAmntSunny = 0; let avgInflAmntSunny = 0; + let maxInflAmntSunny = 0; calData.forEach((flowItem:FlowDataItem) => { sumInflAmntSunny += Number(flowItem.inflAmnt); - }) + + if(Number(flowItem.inflAmnt) > maxInflAmntSunny){ + maxInflAmntSunny = Number(flowItem.inflAmnt); + } + }); + avgInflAmntSunny = sumInflAmntSunny / calData.length; - item.avgInflAmntSunny = avgInflAmntSunny; - if(item.bscFctCd === '11200PB001R'){ - console.log('avgInflAmntSunny : ',item.avgInflAmntSunny); - console.log('calData : ',calData); - } + item.avgInflAmntSunny = roundUp(avgInflAmntSunny, 0); + item.maxInflAmntSunny = roundUp(maxInflAmntSunny, 0); return item; })); - + /** * 결과데이터 계산 * (1) 여유용량 = 시설용량 - 건기시 평균유량 @@ -205,8 +209,6 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy * (3) 분류식화율 = 분류식지역 면적(㎢)/처리구역 면적합계(㎢) ×100 */ const resultData = processedData.map((item:PlanSewageProps) => { - console.log('item.fctCpc : ',item.fctCpc); - console.log('item.avgInflAmntSunny : ',item.avgInflAmntSunny); item.spareCapacity = Number(item.fctCpc) - Number(item.avgInflAmntSunny); item.variableLoadPercent = item.maxInflAmntSunny && item.maxInflAmntSunny!==0 ? Number(item.maxInflAmntSunny) / Number(item.avgInflAmntSunny) : 0; item.classifiedSewerPercent = item.sprtProcZoneAr && item.sprtProcZoneAr!==0 ? Number(item.sprtProcZoneAr) / Number(item.procZoneSm) * 100 : 0; @@ -229,10 +231,10 @@ export const planSewageReducer:(set:(fn: (state: PlanSewageType) => PlanSewageTy 시도: item.sido, 시군구: item.gugun, 주소: item.daddr, - 시설용량: item.fctCpc, - 여유용량: item.spareCapacity, - 변동부하율: item.variableLoadPercent, - 분류식화율: item.classifiedSewerPercent, + "시설용량(m³/일)": item.fctCpc, + "여유용량(m³/일)": item.spareCapacity, + "변동부하율(%)": item.variableLoadPercent, + "분류식화율(%)": item.classifiedSewerPercent, }) }) } diff --git a/apps/fo/app/store/processArea/index.tsx b/apps/fo/app/store/processArea/index.tsx index dc3826fef..ccad3436e 100644 --- a/apps/fo/app/store/processArea/index.tsx +++ b/apps/fo/app/store/processArea/index.tsx @@ -63,25 +63,25 @@ export interface ExcelType { 시설코드: string, 시설명: string, 주소: string, - 시설용량: number | '', - 증설계획기존: number | '', - 증설계획현재: number | '', - 증설계획1단계: number | '', - 증설계획2단계: number | '', - 증설계획3단계: number | '', - 증설계획4단계: number | '', - 처리인구기존: number | '', - 처리인구현재: number | '', - 처리인구1단계: number | '', - 처리인구2단계: number | '', - 처리인구3단계: number | '', - 처리인구4단계: number | '', - 처리구역기존: number | '', - 처리구역현재: number | '', - 처리구역1단계: number | '', - 처리구역2단계: number | '', - 처리구역3단계: number | '', - 처리구역4단계: number | '', + "시설옹량(m³/일)": number | '', + "증설계획기존(m³/일)": number | '', + "증설계획현재(m³/일)": number | '', + "증설계획1단계(m³/일)": number | '', + "증설계획2단계(m³/일)": number | '', + "증설계획3단계(m³/일)": number | '', + "증설계획4단계(m³/일)": number | '', + "처리인구기존(인)": number | '', + "처리인구현재(인)": number | '', + "처리인구1단계(인)": number | '', + "처리인구2단계(인)": number | '', + "처리인구3단계(인)": number | '', + "처리인구4단계(인)": number | '', + "처리구역기존(km²)": number | '', + "처리구역현재(km²)": number | '', + "처리구역1단계(km²)": number | '', + "처리구역2단계(km²)": number | '', + "처리구역3단계(km²)": number | '', + "처리구역4단계(km²)": number | '', 처리구역: string | '' } @@ -385,25 +385,25 @@ export const processAreaReducer:(set:SetStateFunction)=>ProcessAreaActions=(set: 시설코드: item.swtrmtFcltCd, 시설명: item.swtrmtFcltNm, 주소: item.location, - 시설용량: item.fctCpc, - 증설계획기존: item.planSwageQntSumDt4, - 증설계획현재: item.planSwageQntSum, - 증설계획1단계: item.planSwageQntSumDc1, - 증설계획2단계: item.planSwageQntSumDc2, - 증설계획3단계: item.planSwageQntSumDc3, - 증설계획4단계: item.planSwageQntSumDc4, - 처리인구기존: item.swtrmtPpltnCntDt4, - 처리인구현재: item.swtrmtPpltnCnt, - 처리인구1단계: item.swtrmtPpltnCntDc1, - 처리인구2단계: item.swtrmtPpltnCntDc2, - 처리인구3단계: item.swtrmtPpltnCntDc3, - 처리인구4단계: item.swtrmtPpltnCntDc4, - 처리구역기존: item.swtrmtZoneAreaDt4, - 처리구역현재: item.swtrmtZoneArea, - 처리구역1단계: item.swtrmtZoneAreaDc1, - 처리구역2단계: item.swtrmtZoneAreaDc2, - 처리구역3단계: item.swtrmtZoneAreaDc3, - 처리구역4단계: item.swtrmtZoneAreaDc4, + "시설옹량(m³/일)": item.fctCpc, + "증설계획기존(m³/일)": item.planSwageQntSumDt4, + "증설계획현재(m³/일)": item.planSwageQntSum, + "증설계획1단계(m³/일)": item.planSwageQntSumDc1, + "증설계획2단계(m³/일)": item.planSwageQntSumDc2, + "증설계획3단계(m³/일)": item.planSwageQntSumDc3, + "증설계획4단계(m³/일)": item.planSwageQntSumDc4, + "처리인구기존(인)": item.swtrmtPpltnCntDt4, + "처리인구현재(인)": item.swtrmtPpltnCnt, + "처리인구1단계(인)": item.swtrmtPpltnCntDc1, + "처리인구2단계(인)": item.swtrmtPpltnCntDc2, + "처리인구3단계(인)": item.swtrmtPpltnCntDc3, + "처리인구4단계(인)": item.swtrmtPpltnCntDc4, + "처리구역기존(km²)": item.swtrmtZoneAreaDt4, + "처리구역현재(km²)": item.swtrmtZoneArea, + "처리구역1단계(km²)": item.swtrmtZoneAreaDc1, + "처리구역2단계(km²)": item.swtrmtZoneAreaDc2, + "처리구역3단계(km²)": item.swtrmtZoneAreaDc3, + "처리구역4단계(km²)": item.swtrmtZoneAreaDc4, 처리구역: item.trtDstr }); }); diff --git a/apps/fo/app/store/processFacility/index.tsx b/apps/fo/app/store/processFacility/index.tsx index 9a2572916..ecb668063 100644 --- a/apps/fo/app/store/processFacility/index.tsx +++ b/apps/fo/app/store/processFacility/index.tsx @@ -44,9 +44,9 @@ export interface ExcelType { 시군구: string, 시설이름: string, 주소: string, - 시설용량: number | '', - 계획유입수질: number | '', - 설계유입수질: number | '', + "시설용량(m³/일)": number | '', + "계획유입수질(mg/L)": number | '', + "설계유입수질(mg/L)": number | '', 공법: string, 가동개시일: string, 준공일: string, @@ -118,7 +118,7 @@ export type fcltyHistInfoProps = { sitArea : number, trtDstrArea : number, swrTrtPopl : number, - fcltCpc : number | '' + fctCpc : number | '' } // 시설 수질정보 @@ -345,7 +345,7 @@ const gridListFcltyHistInfo:fcltyHistInfoProps[] = [ sitArea : 0, trtDstrArea : 0, swrTrtPopl : 0, - fcltCpc : 860000 + fctCpc : 860000 } ]; @@ -456,7 +456,7 @@ const fetchFacilityHistInfo = async (facilityCd:string ): Promise<fcltyHistInfoP }; // 시설정보 수질정보 데이터 호출 -const fetchFacilityWaterQltyInfo = async (facilityCd:string ): Promise<fcltyWaterQltyInfoProps[]> => { +export const fetchFacilityWaterQltyInfo = async (facilityCd:string ): Promise<fcltyWaterQltyInfoProps[]> => { try { const res = await getFetch('fo', '/prcsFclt/info/history/'+facilityCd); const data = res.data; @@ -623,13 +623,13 @@ export const processFacilityReducer:(set:SetStateFunction)=>ProcessFacilityActio 시군구: item.gugun, 시설이름: item.bscFctNm, 주소: item.daddr, - 시설용량: item.fctCpc ? Number(item.fctCpc) : '', - 계획유입수질: item.plInflWqltBod ? Number(item.plInflWqltBod) : '', - 설계유입수질: item.dsInflWqltBod ? Number(item.dsInflWqltBod) : '', + "시설용량(m³/일)": item.fctCpc ? Number(item.fctCpc.toString().replaceAll(',','')) : '', + "계획유입수질(mg/L)": item.plInflWqltBod ? Number(item.plInflWqltBod) : '', + "설계유입수질(mg/L)": item.dsInflWqltBod ? Number(item.dsInflWqltBod) : '', 공법: item.trtFrfNm, 가동개시일: item.rnDt, 준공일: item.cmplDt, - 관리대행업자: item.mnstr, + 관리대행업자: item.trstOprEtpNm, }) }) } diff --git a/apps/fo/app/store/rdi/index.tsx b/apps/fo/app/store/rdi/index.tsx index 6fe400ce9..2c4997010 100644 --- a/apps/fo/app/store/rdi/index.tsx +++ b/apps/fo/app/store/rdi/index.tsx @@ -1,8 +1,9 @@ import { getFetch } from "@/app/components/api"; +import CalcRainEffect from "@/app/components/common/CalcRainEffect"; import DataForm from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty"; -import { calRainEffectDay } from "../underWaterInput"; +import type { FlowResponse } from "../sewageOccur"; export type { TableUpperProps }; /**==================================== * Store - 타입 @@ -30,6 +31,9 @@ export type RdiProps = { lgbsn : string, mdmbsn : string, rainEffectDay : number, // 강우영향일 + chungchunFlow : string | number | '', + rainCalInflAmnt : string | number | '', + properYn : string, } export interface RdiInterface { @@ -49,6 +53,10 @@ export interface RdiInterface { rvbsn : string, lgbsn : string, mdmbsn : string, + rainEffectDay : number, // 강우영향일 + chungchunFlow : string | number | '', + rainCalInflAmnt : string | number | '', + properYn : string, } // 모달 @@ -79,12 +87,15 @@ export interface ExcelType { 시군구: string, 시설명: string, 주소: string, - 시설용량: number, - 하절기강우일최저유입BOD: number | '', - 하절기최저유입BOD유입유량: number | string | '', - 동절기청천시유입BOD: number | '', - RDII추정 : number | '', - RDII추정시일강수량 : number | '', + "시설용량(m³/일)": number, + "청천시유입하수량(m³/일)": string | number | '', + "하절기강우일최저유입BOD(mg/L)": number | '', + "하절기최저유입BOD유입유량(m³/일)": number | string | '', + "동절기청천시유입BOD(mg/L)": number | '', + "RDII추정" : number | '', + "RDII추정시일강수량(mm)": number | '', + "강우시총추정유입량(m³/일)" : string | number | '', + 적정여부 : string, } // 리스트 헤더 @@ -95,6 +106,7 @@ const upHeadList1:TableUpperProps[] = [ { id: "bscFctNm", title: "시설명", row:0, rowSpan:2 }, { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량\n(m³/일)", align:"right", row:0, rowSpan:2 }, + { id: "chungchunFlow", title: "청천시 유입하수량\n(m³/일)", align:"right", row:0, rowSpan:2 }, { id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 }, { id: "summerMinBodValue", title: "3mm 이상 강우일 중 최저 유입BOD\n(mg/L)", align:"right", row:1 }, { id: "inflAmnt", title: "하절기최저유입BOD유입유량\n(m³/일)", row:1, align:"right" }, @@ -102,6 +114,8 @@ const upHeadList1:TableUpperProps[] = [ { id: "winterAvgBodLowRainfall", title: "청천시 유입BOD\n(mg/L)", row:1, align:"right" }, { id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" }, { id: "infoRnDay", title: "RDII추정시일강수량\n(mm)", row:0, rowSpan:2, align:"right" }, + { id: "rainCalInflAmnt", title: "강우시 총 추정유입량\n(m³/일)", row:0, rowSpan:2, align:"right" }, + { id: "properYn", title: "적정여부", row:0, rowSpan:2 }, ]; const upHeadList2:TableUpperProps[] = [ @@ -112,6 +126,7 @@ const upHeadList2:TableUpperProps[] = [ { id: "bscFctNm", title: "시설명", row:0, rowSpan:2 }, { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 }, + { id: "chungchunFlow", title: "청천시 유입하수량\n(m³/일)", align:"right", row:0, rowSpan:2 }, { id: "B", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 }, { id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 }, { id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1, align:"right" }, @@ -119,6 +134,8 @@ const upHeadList2:TableUpperProps[] = [ { id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1, align:"right" }, { id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" }, { id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2, align:"right" }, + { id: "rainCalInflAmnt", title: "강우시 총 추정유입량\n(m³/일)", row:0, rowSpan:2, align:"right" }, + { id: "properYn", title: "적정여부", row:0, rowSpan:2 }, ]; const upHeadList3:TableUpperProps[] = [ @@ -133,6 +150,7 @@ const upHeadList3:TableUpperProps[] = [ { id: "bscFctNm", title: "시설명", row:0, rowSpan:2 }, { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 }, + { id: "chungchunFlow", title: "청천시 유입하수량\n(m³/일)", align:"right", row:0, rowSpan:2 }, { id: "C", title: "하절기 운영현황(6~8월)", row:0, colSpan:2 }, { id: "summerMinBodValue", title: "하절기강우일최저유입BOD", align:"right", row:1 }, { id: "inflAmnt", title: "하절기최저유입BOD유입유량", row:1, align:"right" }, @@ -140,6 +158,8 @@ const upHeadList3:TableUpperProps[] = [ { id: "winterAvgBodLowRainfall", title: "동절기청천시유입BOD", row:1, align:"right" }, { id: "rdiiValue", title: "RDII추정", row:0, rowSpan:2, align:"right" }, { id: "infoRnDay", title: "RDII추정시일강수량", row:0, rowSpan:2, align:"right" }, + { id: "rainCalInflAmnt", title: "강우시 총 추정유입량\n(m³/일)", row:0, rowSpan:2, align:"right" }, + { id: "properYn", title: "적정여부", row:0, rowSpan:2 }, ]; const rdiList:RdiProps[] = [ @@ -153,7 +173,6 @@ const fetchRdiList = async (pageNo: number, pageSize: number, searchYear: string try{ const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : ''; const url = '/rdii/list/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr; - console.log(url); const res = await getFetch('fo', url); return { data: res.data, count: res.count } }catch(error){ @@ -209,9 +228,11 @@ const dataFormSetting=(item : RdiProps)=> { DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> }); DataForm({ type: 'float1', column: 'summerMinBodValue', item: item as unknown as Record<string, unknown>}); DataForm({ type: 'float1', column: 'winterAvgBodLowRainfall', item: item as unknown as Record<string, unknown>}); - DataForm({ type: 'float1', column: 'rdiiValue', item: item as unknown as Record<string, unknown>}); + DataForm({ type: 'float0', column: 'rdiiValue', item: item as unknown as Record<string, unknown>}); DataForm({ type: 'float1', column: 'infoRnDay', item: item as unknown as Record<string, unknown>}); DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown>}); + DataForm({ type: 'float0', column: 'chungchunFlow', item: item as unknown as Record<string, unknown>}); + DataForm({ type: 'float0', column: 'rainCalInflAmnt', item: item as unknown as Record<string, unknown>}); } // Add type definitions for state setter function @@ -232,9 +253,32 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio const res = await fetchRdiList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); const data = res.data; - const excelDownList: ExcelType[] = []; + const reData = await Promise.all(data.map(async (item: RdiProps) => { + 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; - const rtnData = data.map((item: RdiProps) => { + 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); + item.properYn = Number(item.rainCalInflAmnt) > Number(item.fctCpc) ? '초과유입' : '적정'; + return item; + })); + + const excelDownList: ExcelType[] = []; + const rtnData = reData.map((item: RdiProps) => { return { ...item, sido: item.lclgvrnmntNm.split(' ')[0]?.toString() || '', @@ -256,9 +300,9 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio dataItem.rainEffectDay = 0; }); - calRainEffectDay(rtnWqltData, 'SUNNY'); + const calcData = CalcRainEffect(rtnWqltData, 'SUNNY'); - const rtnWqltWinterData = rtnWqltData.filter((dataItem: any) => + const rtnWqltWinterData = calcData.filter((dataItem: any) => (dataItem.msrDt.substring(4, 6) === '01' || dataItem.msrDt.substring(4, 6) === '02') && dataItem.rainEffectDay == 0 @@ -294,12 +338,15 @@ export const rdiReducer:(set:SetStateFunction)=>RdiActions=(set: SetStateFunctio 시도: item.sido, 시군구: item.sigungo, 주소: item.daddr, - 시설용량: item.fctCpc, - 하절기강우일최저유입BOD: item.summerMinBodValue, - 하절기최저유입BOD유입유량: item.inflAmnt, - 동절기청천시유입BOD: item.winterAvgBodLowRainfall, - RDII추정 : item.rdiiValue, - RDII추정시일강수량 : item.infoRnDay, + "시설용량(m³/일)": item.fctCpc, + "청천시유입하수량(m³/일)": item.chungchunFlow, + "하절기강우일최저유입BOD(mg/L)": item.summerMinBodValue, + "하절기최저유입BOD유입유량(m³/일)": item.inflAmnt, + "동절기청천시유입BOD(mg/L)": item.winterAvgBodLowRainfall, + "RDII추정": item.rdiiValue, + "RDII추정시일강수량(mm)": item.infoRnDay, + "강우시총추정유입량(m³/일)": item.rainCalInflAmnt, + 적정여부: item.properYn, }); }); } diff --git a/apps/fo/app/store/sewageOccur/index.tsx b/apps/fo/app/store/sewageOccur/index.tsx index 4a6d055f0..efc51a5af 100644 --- a/apps/fo/app/store/sewageOccur/index.tsx +++ b/apps/fo/app/store/sewageOccur/index.tsx @@ -1,6 +1,8 @@ import DataForm from "@/app/components/common/DataForm"; import type { TableUpperProps } from "../dashboard"; import { getFetch } from "@/app/components/api"; +import CalcRainEffect from "@/app/components/common/CalcRainEffect"; +import { OSU_PERCENT } from "../common"; export type { TableUpperProps }; /**==================================== * Store - 타입 @@ -50,12 +52,12 @@ export interface ExcelType { 시군구: string, 시설명: string, 주소: string, - 시설용량: number, - 물사용량: number | '', - 오수전환율: number | '', - 오수발생량추정: number | '', - 연간하수유입량: number | '', - 청천시하수유입량: number | '', + "시설용량(m³/일)": number, + "물사용량(m³/일)": number | '', + "오수전환율(%)": number | '', + "오수발생량추정(m³/일)": number | '', + "연간하수유입량(m³/일)": number | '', + "청천시하수유입량(m³/일)": number | '', } // 리스트 헤더 @@ -236,47 +238,9 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { let totWaterUsage = 0; // 강우영향일 계산 (강우량이 3 초과이면 무조건 강우영향일) - for(let idx = 0; idx < res2.data.length; idx++) { - const item = res2.data[idx]; - if(item){ - if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) { - item.rainEffectDay = 1; - } else { - item.rainEffectDay = 0; - } - } - } - - // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 - for(let idx = 0; idx < res2.data.length; idx++) { - if(res2.data[idx]) { - // 하루 전이 강우영향일(3 이상)인 경우 - if(idx > 0 && res2.data[idx-1]?.infoRnDay && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) { - res2.data[idx]!.rainEffectDay = 1; - } - // 이틀 전이 강우영향일(3 이상)인 경우 - if(idx > 1 && res2.data[idx-2]?.infoRnDay && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) { - res2.data[idx]!.rainEffectDay = 1; - } - } - } - - for(let idx = 0; idx < res2.data.length; idx++) { - if(res2.data[idx] && res2.data[idx]?.rainEffectDay === 1) { - if(idx > 1){ - if(res2.data[idx-1]?.infoRnDay && Number(res2.data[idx]?.infoRnDay) < 3 && Number(res2.data[idx-1]?.infoRnDay.toString().trim()) >= 3) { - res2.data[idx]!.infoRnDay = res2.data[idx-1]!.infoRnDay; - } - } - if(idx > 2){ - if(res2.data[idx-2]?.infoRnDay && Number(res2.data[idx]?.infoRnDay) < 3 && Number(res2.data[idx-2]?.infoRnDay.toString().trim()) >= 3) { - res2.data[idx]!.infoRnDay = res2.data[idx-2]!.infoRnDay; - } - } - } - } + const rainEffectData = CalcRainEffect(res2.data); - res2.data.forEach((item: FlowDataItem) => { + rainEffectData.forEach((item: FlowDataItem) => { if(Number(item.rainEffectDay) === 0){ chungcunSumFlow += Number(item.inflAmnt); @@ -314,12 +278,12 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { 시도: item.sidoNm, 시군구: item.sggNm, 주소: item.daddr, - 시설용량: item.fctCpc, - 물사용량: item.waterUsage, - 오수전환율: item.swageChangePercent, - 오수발생량추정: item.estimationSewage, - 연간하수유입량 : item.sewageInputYear, - 청천시하수유입량 : item.sewageInputChungchun, + "시설용량(m³/일)": item.fctCpc, + "물사용량(m³/일)": item.waterUsage, + "오수전환율(%)": item.swageChangePercent, + "오수발생량추정(m³/일)": item.estimationSewage, + "연간하수유입량(m³/일)": item.sewageInputYear, + "청천시하수유입량(m³/일)": item.sewageInputChungchun, }); }); } @@ -382,8 +346,8 @@ export const sewageOccurReducer:(set:any)=>SewageOccurActions=(set: any) => { 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*0.9) * 100) / 100) * 100, - estimationSewage: Math.round(item.usege*0.9 * 1) / 1 + swageChangePercent: (Math.round((item.usege/item.usege*OSU_PERCENT) * 100) / 100) * 100, + estimationSewage: Math.round(item.usege*OSU_PERCENT * 1) / 1 }) if (item.usege > maxWaterUsage) { maxWaterUsage = item.usege; diff --git a/apps/fo/app/store/underWaterInput/index.tsx b/apps/fo/app/store/underWaterInput/index.tsx index e9c664b99..816860469 100644 --- a/apps/fo/app/store/underWaterInput/index.tsx +++ b/apps/fo/app/store/underWaterInput/index.tsx @@ -2,6 +2,8 @@ import { getFetch } from "@/app/components/api"; import DataForm 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 { OSU_PERCENT } from "../common"; export type { TableUpperProps }; // SewageOccurDetailProps 타입을 여기에 정의 @@ -38,10 +40,12 @@ const upHeadList1:TableUpperProps[] = [ { id: "bscFctNm", title: "시설명", row:0, rowSpan:2 }, { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 }, + { id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2 }, { id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 }, { id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 }, { id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 }, { id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 }, + { id: "properYn", title: "적정여부", row:0, rowSpan:2 }, ]; const upHeadList2:TableUpperProps[] = [ @@ -52,10 +56,12 @@ const upHeadList2:TableUpperProps[] = [ { id: "bscFctNm", title: "시설명", row:0, rowSpan:2 }, { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 }, + { id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2 }, { id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 }, { id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 }, { id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 }, { id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 }, + { id: "properYn", title: "적정여부", row:0, rowSpan:2 }, ]; const upHeadList3:TableUpperProps[] = [ @@ -70,10 +76,12 @@ const upHeadList3:TableUpperProps[] = [ { id: "bscFctNm", title: "시설명", row:0, rowSpan:2 }, { id: "daddr", title: "주소", row:0, rowSpan:2 }, { id: "fctCpc", title: "시설용량(m³/일)", align:"right", row:0, rowSpan:2 }, + { id: "inflAmnt", title: "연평균유입하수량(m³/일)", align:"right", row:0, rowSpan:2 }, { id: "C", title: "지하수 유입량 추정", align:"right", row:0, colSpan:3 }, { id: "underWaterInputYear", title: "연간\n(m³/일)", align:"right", row:1 }, { id: "underWaterInputSummer", title: "하절기\n(m³/일)", align:"right", row:1 }, { id: "underWaterInputWinter", title: "동절기\n(m³/일)", align:"right", row:1 }, + { id: "properYn", title: "적정여부", row:0, rowSpan:2 }, ]; // 모달 @@ -251,6 +259,7 @@ export const underWaterInitState: UnderWaterType = { const dataFormSetting=(item : UnderWaterProps)=> { DataForm({ type: 'float0', column: 'fctCpc', item: item as unknown as Record<string, unknown> }); + DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record<string, unknown> }); DataForm({ type: 'float0', column: 'underWaterInputYear', item: item as unknown as Record<string, unknown>}); DataForm({ type: 'float0', column: 'underWaterInputSummer', item: item as unknown as Record<string, unknown>}); DataForm({ type: 'float0', column: 'underWaterInputWinter', item: item as unknown as Record<string, unknown>}); @@ -258,65 +267,6 @@ const dataFormSetting=(item : UnderWaterProps)=> { export type UnderWaterStore = UnderWaterType & UnderWaterActions; -/** - * - * @param data - * @param weather ('ALL' | 'SUNNY' | 'RAINY') - * @returns - */ -export const calRainEffectDay = (data: any, weather: string) => { - // 강우영향일 계산 (강우량이 3 이상이면 무조건 강우영향일) - for(let idx = 0; idx < data.length; idx++) { - const item = data[idx]; - if(item){ - if(item.infoRnDay && Number(item.infoRnDay.toString().trim()) >= 3) { - item.rainEffectDay = 1; - } else { - item.rainEffectDay = 0; - } - } - } - - // 이틀 전, 하루 전이 강우영향일(3 이상)인 경우 해당 날도 강우영향일로 설정 - for(let idx = 0; idx < data.length; idx++) { - if(data[idx]) { - // 하루 전이 강우영향일(3 이상)인 경우 - if(idx > 0 && data[idx-1]?.infoRnDay && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.rainEffectDay = 1; - } - // 이틀 전이 강우영향일(3 이상)인 경우 - if(idx > 1 && data[idx-2]?.infoRnDay && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.rainEffectDay = 1; - } - } - } - - for(let idx = 0; idx < data.length; idx++) { - if(data[idx] && data[idx]?.rainEffectDay === 1) { - if(idx > 1){ - if(data[idx-1]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-1]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.infoRnDay = data[idx-1]!.infoRnDay; - } - } - if(idx > 2){ - if(data[idx-2]?.infoRnDay && Number(data[idx]?.infoRnDay) < 3 && Number(data[idx-2]?.infoRnDay.toString().trim()) >= 3) { - data[idx]!.infoRnDay = data[idx-2]!.infoRnDay; - } - } - } - } - - let rtnData : FlowDataItem[] = []; - if (weather === 'ALL') { - rtnData = data; - } else if (weather === 'SUNNY') { - rtnData = data.filter((item: FlowDataItem) => item.rainEffectDay === 0); - } else { - rtnData = data.filter((item: FlowDataItem) => item.rainEffectDay === 1); - } - return rtnData; -} - export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterType) => void)=>UnderWaterActions=(set: (fn: (state: UnderWaterType) => UnderWaterType) => void) => { return { searchUnderWaterList: async (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { @@ -337,7 +287,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy const bscFctCd = item.bscFctCd; const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse; - const calData = calRainEffectDay(res2.data, 'SUNNY'); + const calData = CalcRainEffect(res2.data, 'SUNNY'); let chungcunSumFlow = 0; let sumSummerChungcunDay = 0; @@ -357,20 +307,19 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0; } }); - - const usage = chungcunSumFlow / calData.length; - const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay; - const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay; + const usage = chungcunSumFlow&&chungcunSumFlow>0?chungcunSumFlow / calData.length:0; + const summerUsage = sumSummerChungcunFlow?sumSummerChungcunFlow / sumSummerChungcunDay:0; + const winterUsage = sumWinterChungcunFlow?sumWinterChungcunFlow / sumWinterChungcunDay:0; - if(bscFctCd === '11200PB001R') { + //bscFctCd === '11200PB001R') 중랑 - 테스트할 때 코드넣고 해야 보기편해요~ + /* if(bscFctCd === '11200PB001R') { console.log('calData.length : ', calData.length); console.log('usage : ', usage, 'summerUsage : ', summerUsage, 'winterUsage : ', winterUsage); - } - - item.underWaterInputYear = Math.round((usage-(usage*0.65*0.9)) * 1) / 1; - item.underWaterInputSummer = Math.round((summerUsage-(summerUsage*0.65*0.9)) * 1) / 1; - item.underWaterInputWinter = Math.round((winterUsage-(winterUsage*0.65*0.9)) * 1) / 1; - + } */ + 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; })); @@ -391,11 +340,12 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy 시군구: item.sggNm, 시설명: item.bscFctNm, 주소: item.daddr, - 시설용량: item.fctCpc, - 연간지하수유입량: item.underWaterInputYear, - 하절기지하수유입량: item.underWaterInputSummer, - 동절기지하수유입량: item.underWaterInputWinter, - + "시설용량(m³/일)": item.fctCpc, + "평균유입하수량(m³/일)": item.inflAmnt, + "연간지하수유입량(m³/일)": item.underWaterInputYear, + "하절기지하수유입량(m³/일)": item.underWaterInputSummer, + "동절기지하수유입량(m³/일)": item.underWaterInputWinter, + 적정여부: item.properYn, }); }); }else{ @@ -425,7 +375,7 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear); const monthData: SewageOccurDetailProps[] = []; - const calData = calRainEffectDay(res.data, 'SUNNY'); + const calData = CalcRainEffect(res.data, 'SUNNY'); let tot = 0; let cnt = 0; @@ -456,8 +406,8 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy 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*0.9 * 1) / 1, - underWaterInput:Math.round((item.usege-(item.usege*0.65*0.9)) * 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, }) if (item.usege > maxWaterUsage) { maxWaterUsage = item.usege; @@ -468,28 +418,33 @@ export const underWaterReducer:(set:(fn: (state: UnderWaterType) => UnderWaterTy } }); - console.log('tot', tot, 'calData.length', calData.length); + + if(monthData.length == 0){ + maxWaterUsage = 0; + avgWaterUsage = 0; + minWaterUsage = 0; + } + avgWaterUsage = tot/cnt; - console.log(avgWaterUsage); const newData= [ { msrDt: '평균', realSewageInput:Math.round(avgWaterUsage*1) /1, - sewageOccur:Math.round(avgWaterUsage*0.65*0.9 * 1) / 1, - underWaterInput: Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.9)) * 1) / 1 + sewageOccur:Math.round(avgWaterUsage*0.65*OSU_PERCENT * 1) / 1, + underWaterInput: Math.round((avgWaterUsage-(avgWaterUsage*0.65*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*0.9 * 1) / 1, - underWaterInput: Math.round((maxWaterUsage-(maxWaterUsage*0.65*0.9)) * 1) / 1, + sewageOccur: Math.round(maxWaterUsage*0.65*OSU_PERCENT * 1) / 1, + underWaterInput: Math.round((maxWaterUsage-(maxWaterUsage*0.65*OSU_PERCENT)) * 1) / 1, }, { msrDt: '최소', realSewageInput: Math.round(minWaterUsage*1) /1, - sewageOccur: Math.round(minWaterUsage*0.65*0.9 * 1) / 1, - underWaterInput: Math.round((minWaterUsage-(minWaterUsage*0.65*0.9)) * 1) / 1, + sewageOccur: Math.round(minWaterUsage*0.65*OSU_PERCENT * 1) / 1, + underWaterInput: Math.round((minWaterUsage-(minWaterUsage*0.65*OSU_PERCENT)) * 1) / 1, }, ...tableData ] diff --git a/apps/fo/app/store/underWaterInput/types.tsx b/apps/fo/app/store/underWaterInput/types.tsx index c90c654ad..396bd631b 100644 --- a/apps/fo/app/store/underWaterInput/types.tsx +++ b/apps/fo/app/store/underWaterInput/types.tsx @@ -14,6 +14,8 @@ export type UnderWaterProps = { rvbsn : string, lgbsn : string, mdmbsn : string, + inflAmnt : number | '', + properYn : string | '', } export interface UnderWaterInterface { bscFctCd : string, @@ -30,6 +32,8 @@ export interface UnderWaterInterface { rvbsn : string, lgbsn : string, mdmbsn : string, + inflAmnt : number | '', + properYn : string | '', } // 모달 @@ -51,8 +55,10 @@ export interface ExcelType { 시군구: string, 시설명: string, 주소: string, - 시설용량: number, - 연간지하수유입량: number | '', - 하절기지하수유입량: number | '', - 동절기지하수유입량: number | '', + "시설용량(m³/일)": number, + "평균유입하수량(m³/일)": number | '', + "연간지하수유입량(m³/일)": number | '', + "하절기지하수유입량(m³/일)": number | '', + "동절기지하수유입량(m³/일)": number | '', + 적정여부: string | '', } \ No newline at end of file diff --git a/apps/fo/middleware.ts b/apps/fo/middleware.ts index 317c6a706..32257341d 100644 --- a/apps/fo/middleware.ts +++ b/apps/fo/middleware.ts @@ -6,7 +6,7 @@ const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization"; const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || ""; const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || ""; const SEWERAGE_API_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || ""; - +const serverApiUrl = SERVER_API_CS_URL; export function middleware(req: NextRequest) { console.log("Middleware 진입:", req.nextUrl.pathname); const pathname = req.nextUrl.pathname; @@ -14,7 +14,7 @@ export function middleware(req: NextRequest) { if (pathname.startsWith("/server")) { const queryParams = searchParams.toString(); - const newUrl = `${SERVER_API_CS_URL}${pathname.replace("/server", "")}${ + const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${ queryParams ? `?${queryParams}` : "" }`; console.log(`[Middleware] Rewriting from '/server' path to: ${newUrl}`); @@ -76,13 +76,47 @@ export function middleware(req: NextRequest) { const requestHeaders = new Headers(req.headers); const token = req.cookies.get(CLAIM_NAME)?.value; const userId = req.cookies.get(AUTH_USER_ID)?.value; - const newUrl = `${SERVER_API_CS_URL}${pathname}`; + const newUrl = `${serverApiUrl}${pathname}`; if (token) requestHeaders.set(CLAIM_NAME, token); if (userId) requestHeaders.set(AUTH_USER_ID, userId); console.log( - `[Middleware] Rewriting from '/attach-service' path to: ${newUrl}`, + `[Middleware] Rewriting from '/attach-service' path to: ${newUrl}` + ); + return NextResponse.rewrite(new URL(newUrl), { + headers: requestHeaders, + }); + } + + if (pathname.startsWith("/operation-service")) { + const requestHeaders = new Headers(req.headers); + const token = req.cookies.get(CLAIM_NAME)?.value; + const userId = req.cookies.get(AUTH_USER_ID)?.value; + const newUrl = `${serverApiUrl}${pathname}`; + + if (token) requestHeaders.set(CLAIM_NAME, token); + if (userId) requestHeaders.set(AUTH_USER_ID, userId); + + console.log( + `[Middleware] Rewriting from '/operation-service' path to: ${newUrl}` + ); + return NextResponse.rewrite(new URL(newUrl), { + headers: requestHeaders, + }); + } + + if (pathname.startsWith("/reuse-service")) { + const requestHeaders = new Headers(req.headers); + const token = req.cookies.get(CLAIM_NAME)?.value; + const userId = req.cookies.get(AUTH_USER_ID)?.value; + const newUrl = `${serverApiUrl}${pathname}`; + + if (token) requestHeaders.set(CLAIM_NAME, token); + if (userId) requestHeaders.set(AUTH_USER_ID, userId); + + console.log( + `[Middleware] Rewriting from '/reuse-service' path to: ${newUrl}` ); return NextResponse.rewrite(new URL(newUrl), { headers: requestHeaders, @@ -94,12 +128,13 @@ export function middleware(req: NextRequest) { const newUrl = `${SERVER_API_CS_URL}${pathname}`; console.log( - `[Middleware] Rewriting from '/user-service' path to: ${newUrl}`, + `[Middleware] Rewriting from '/user-service' path to: ${newUrl}` ); return NextResponse.rewrite(new URL(newUrl), { headers: requestHeaders, }); } + if (pathname === "/") { return NextResponse.redirect(new URL("/pages/dashboard", req.url)); } @@ -108,11 +143,13 @@ export function middleware(req: NextRequest) { export const config = { matcher: [ + "/", "/server/:path*", "/geoserver/:path*", "/attach-service/:path*", "/user-service/:path*", "/cms-service/:path*", - "/" + "/operation-service/:path*", + "/reuse-service/:path*", ], }; diff --git a/apps/fo/public/dashBoadModalWaterQlty.xlsx b/apps/fo/public/dashBoadModalWaterQlty.xlsx new file mode 100644 index 000000000..dc555a880 Binary files /dev/null and b/apps/fo/public/dashBoadModalWaterQlty.xlsx differ diff --git a/packages/common/business_components/src/ui/chart/LineBarChart.tsx b/packages/common/business_components/src/ui/chart/LineBarChart.tsx index a7319cb01..eee09fb65 100644 --- a/packages/common/business_components/src/ui/chart/LineBarChart.tsx +++ b/packages/common/business_components/src/ui/chart/LineBarChart.tsx @@ -109,6 +109,35 @@ export default function LineBarchart({ const lineMaxValue = getMaxValue(chartData, 'lineVal'); const barMaxValue = getMaxValue(chartData, 'barVal'); + /** + * 최대값과 구간 수에 따른 범례 만들기 + * maxValue : 최대값, segments : 구간 수 (구간수가 5면 눈금은 6) + */ + const makeNiceScale = (maxValue: number, segments = 5) => { + // 최대값이 이상할 경우 0, 0으로 반환 + if (!isFinite(maxValue) || maxValue <= 0) { + return { max: 0, ticks: [0] }; + } + + const exponent = Math.floor(Math.log10(maxValue)); + const base = Math.pow(10, exponent); + const fraction = maxValue / base; + + let niceFraction: number; + if (fraction <= 1) niceFraction = 1; + else if (fraction <= 2) niceFraction = 3; + else if (fraction <= 5) niceFraction = 5; + else niceFraction = 10; + + const niceMax = niceFraction * base; // round up to 1/2/5 * 10^k + const step = niceMax / segments; + const ticks = Array.from({ length: segments + 1 }, (_, i) => Number((i * step).toFixed(10))); + return { max: niceMax, ticks }; + }; + + const leftScale = makeNiceScale(lineMaxValue, 5); + const rightScale = makeNiceScale(barMaxValue, 5); + const getTicks = (data : any []) => { const monthSet = new Set<string>(); const rtnData : string[] = []; @@ -182,23 +211,26 @@ export default function LineBarchart({ {yFieldText && <YAxis yAxisId="left" className="text-[12px] font-bold" - tickCount={6} tickFormatter={(value) => typeof value === "number" ? value.toLocaleString() : value } + domain={[0, leftScale.max]} + ticks={leftScale.ticks} orientation="left" label={(props) => <CustomAxisText {...props} fieldText={yFieldText} position="left" />} + />} {/* 오른쪽 Y축: barVal */} {yFieldText2 && <YAxis yAxisId="right" className="text-[12px] font-bold" - tickCount={6} orientation="right" tickFormatter={(value) => typeof value === "number" ? value.toLocaleString() : value } - label={(props) => <CustomAxisText {...props} fieldText={yFieldText} position="right" />} + domain={[0, rightScale.max]} + ticks={rightScale.ticks} + label={(props) => <CustomAxisText {...props} fieldText={yFieldText2} position="right" />} reversed={true} />} <Tooltip content={<CustomTooltip active={undefined} payload={undefined} label={undefined} />} />