import { getFetch } from "@/app/components/api"; import type { TableUpperProps } from "../dashboard"; import DataForm from "@/app/components/common/DataForm"; import CalcRainEffect from "@/app/components/common/CalcRainEffect"; import { fetchFacilityWaterQltyListHist } from "../facilityWaterQlty"; import CommaToNumber from "@/app/components/common/CommaToNumber"; /**==================================== * Store - 타입 ====================================*/ /** * (1) 메인페이지 */ const FlowRateSearchLabelArray: string[] = ['구분', '시도', '시군구', '용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별']; export type flowRateListProps = { bscFctCd: string, sido: string, gugun: string, bscFctNm: string, daddr: string, fctCpc: number, lclgvrnmntNm: string, totInflAmnt: number | '', inflAmnt: number | '', sumFlow: number | '', returnAmnt: number | '', efflAmnt: number | '', rgnNm: string, rvbsn: string, lgbsn: string, mdmbsn: string, infoRnDay: number | '', } export interface ExcelType { 시설코드: string, 권역: string | '', 단위유역: string | '', 중권역: string | '', 환경청: string | '', 시도: string, 시군구: string, 시설이름: string, 주소: string, "시설용량(m³/일)": number, "총유입량(m³/일)": number | '', "하수유입량(m³/일)": number | '', "연계처리량(m³/일)": number | '', "총인반류수량(m³/일)": number | '', "방류량(m³/일)": number | '', } export type modalExcelType = { "날짜": string, "총유입량(m³/일)": number | '', "하수유입량(m³/일)": number | '', "연계처리량(m³/일)": number | '', "총인반류수량(m³/일)": number | '', "방류량(m³/일)": number | '', "미처리하수 추정량(m³/일)": number | '', "강우량(mm/일)": number | string | '', } /** * (2) 모달 */ export interface FlowRateModalInterface { msrDt: string, totInflAmnt: number | '', inflAmnt: number | '', sumFlow: number | '', returnAmnt: number | '', efflAmnt: number | '', infoRnDay: number | string | '', rainEffectDay: number | string | '', noProcessInflAmnt: number | string | '' } export type FlowRateModalProps = { msrDt: string, totInflAmnt: number, inflAmnt: number, sumFlow: number, returnAmnt: number, efflAmnt: number, infoRnDay: number | string | '', rainEffectDay: number | string | '', noProcessInflAmnt: number | string | '' } /**==================================== * Store - data ====================================*/ /** * (1) 메인페이지 */ // 리스트 (행정별) const upHeadList1: TableUpperProps[] = [ { id: "A", title: "행정명", row: 0, colSpan: 2, widthPercent: 16 }, { id: "sido", title: "시도", upName: "upChangeRe", row: 1, widthPercent: 8 }, { id: "gugun", title: "시군구", upName: "upChangeRe", row: 1, widthPercent: 8 }, { id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 }, { id: "daddr", title: "주소", row: 0, rowSpan: 2 }, { id: "fctCpc", title: "시설용량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "totInflAmnt", title: "총 유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "inflAmnt", title: "하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "sumFlow", title: '연계처리량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "efflAmnt", title: '방류량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 } ]; // 리스트 (권역별) const upHeadList2: TableUpperProps[] = [ { id: "A", title: "유역", row: 0, colSpan: 3, widthPercent: 24 }, { id: "rvbsn", title: "권역", upName: "upChangeRe", row: 1, widthPercent: 8 }, { id: "lgbsn", title: "단위유역", upName: "upChangeRe", row: 1, widthPercent: 8 }, { id: "mdmbsn", title: "중권역", upName: "upChangeRe", row: 1, widthPercent: 8 }, { id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 10 }, { id: "daddr", title: "주소", row: 0, rowSpan: 2 }, { id: "fctCpc", title: "시설용량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 10 }, { id: "totInflAmnt", title: "총 유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "inflAmnt", title: "하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "sumFlow", title: '연계처리량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "efflAmnt", title: '방류량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 } ]; // 리스트 (환경청별별) const upHeadList3: TableUpperProps[] = [ { id: "A", title: "유역", row: 0, colSpan: 3, widthPercent: 15 }, { id: "rvbsn", title: "권역", upName: "upChangeRe1", row: 1, widthPercent: 5 }, { id: "lgbsn", title: "단위유역", upName: "upChangeRe1", row: 1, widthPercent: 5 }, { id: "mdmbsn", title: "중권역", upName: "upChangeRe1", row: 1, widthPercent: 5 }, { id: "rgnNm", title: "환경청", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "B", title: "행정명", row: 0, colSpan: 2, widthPercent: 10 }, { id: "sido", title: "시도", upName: "upChangeRe2", row: 1, widthPercent: 5 }, { id: "gugun", title: "시군구", upName: "upChangeRe2", row: 1, widthPercent: 5 }, { id: "bscFctNm", title: "시설명", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "daddr", title: "주소", row: 0, rowSpan: 2 }, { id: "fctCpc", title: "시설용량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "totInflAmnt", title: "총 유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "inflAmnt", title: "하수유입량\n(m³/일)", align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "sumFlow", title: '연계처리량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "returnAmnt", title: '총인 반류수량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 }, { id: "efflAmnt", title: '방류량\n(m³/일)', align: "right", row: 0, rowSpan: 2, widthPercent: 7 } ]; const flowRateList: flowRateListProps[] = [ ] /** * (2) 모달 */ const upHeadListFlowRateModal: TableUpperProps[] = [ { id: "msrDt", title: "날짜" }, { id: "totInflAmnt", title: "총 유입량(m³/일)", align: "right" }, { id: "inflAmnt", title: "하수유입량(m³/일)", align: "right" }, { 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" } ] const modalFlowRateListYear: FlowRateModalProps[] = [ ] /**==================================== * Store - API ====================================*/ 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 res = await getFetch('fo', url); return { data: res.data, count: res.count, status: res.status} } catch (error) { console.error('시설정보 유량현황 데이터를 가져오는데 실패했습니다:', error); console.log(error); return { data: [], count: 0, status: 300 }; } } export const fetchFlowRateModalList = async (bscFctCd: string, searchYear: string) => { try { const url = '/fclt/flow/' + bscFctCd + '/' + searchYear; const res = await getFetch('fo', url); // msrDt 오름차순으로 정렬 const sortedData = res.data.sort((a: FlowRateModalInterface, b: FlowRateModalInterface) => { return new Date(a.msrDt).getTime() - new Date(b.msrDt).getTime(); }); return { data: sortedData } } catch (error) { console.error('시설정보 유량현황 모달 데이터를 가져오는데 실패했습니다:', error); return { data: [] } } } /**==================================== * Store - expaort ====================================*/ export type FlowRateSearchActions = { searchFlowRateList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void; searchFlowRateModalList: (bscFctCd: string, searchYear: string) => void; } export type FlowRateSearchType = { FlowRateSearch: { isInit: boolean; flowRateSearchLabelArray: string[]; }, FlowRateList: { isInit: boolean; upHeadList1: TableUpperProps[]; upHeadList2: TableUpperProps[]; upHeadList3: TableUpperProps[]; flowRateList: flowRateListProps[]; flowRateCount: number; excelList: ExcelType[]; isLoading: boolean; }, FlowRateModal: { isInit: boolean; modalFlowRateListYear: FlowRateModalProps[]; upHeadListFlowRateModalYear: TableUpperProps[]; } } export type FlowRateSearchStore = FlowRateSearchType & FlowRateSearchActions; export const dataFormSetting = (item: flowRateListProps | FlowRateModalProps | FlowRateModalInterface) => { DataForm({ type: 'date', column: 'msrDt', item: item as unknown as Record }); DataForm({ type: 'float0', column: 'totInflAmnt', item: item as unknown as Record }); DataForm({ type: 'float0', column: 'inflAmnt', item: item as unknown as Record }); DataForm({ type: 'float0', column: 'sumFlow', item: item as unknown as Record }); DataForm({ type: 'float0', column: 'efflWqltBod', item: item as unknown as Record }); DataForm({ type: 'float0', column: 'returnAmnt', item: item as unknown as Record }); DataForm({ type: 'float0', column: 'efflAmnt', item: item as unknown as Record }); } export const flowRateSearchInitState: FlowRateSearchType = { FlowRateSearch: { isInit: false, flowRateSearchLabelArray: FlowRateSearchLabelArray, }, FlowRateList: { isInit: false, upHeadList1: upHeadList1, upHeadList2: upHeadList2, upHeadList3: upHeadList3, flowRateList: flowRateList, flowRateCount: 0, excelList: [], isLoading: true, }, FlowRateModal: { isInit: false, upHeadListFlowRateModalYear: upHeadListFlowRateModal, modalFlowRateListYear: modalFlowRateListYear, } } export const flowRateSearchReducer: (set: (fn: (state: FlowRateSearchType) => FlowRateSearchType) => void) => FlowRateSearchActions = (set: (fn: (state: FlowRateSearchType) => FlowRateSearchType) => void) => { return { searchFlowRateList: async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => { set((state: FlowRateSearchType) => ({ ...state, FlowRateList: { ...state.FlowRateList, isLoading: true, }, })); // const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); //--------- const flowRateList: any[] = []; const results: any[] = []; if (pageSize < 5000) { const res = await fetchFlowRateList(pageNo, pageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); flowRateList.push(...res.data); results.push(res); } else { for (let idx = 0; idx < pageSize; idx += 100) { const tmpPageNo = Math.floor(idx / 100) + 1; const tmpPageSize = Math.min(100, pageSize - idx); const result = await fetchFlowRateList( tmpPageNo, tmpPageSize, searchYear, partCd, nameCd, fcltCpct, operationValue, fcltyNm); results.push(result); if (result?.count < tmpPageNo * tmpPageSize) { break; // 더 이상 데이터가 없으면 중지 } } // console.log(results); // 결과를 합치기 for (const res of results) { if (res?.status === 200 && Array.isArray(res?.data)) { flowRateList.push(...res.data); } } } //--------- const recordCount = results[0]?.count || 0; //------- // const data = res.data; const data = flowRateList; const excelDownList: ExcelType[] = []; const rtnData = data.map((item: flowRateListProps) => { item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, '')); item.totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0); // 하수유입량 + 연계처리량 + 반류수유량(m³/일) dataFormSetting(item); return item; }); if (pageSize > 5000) { rtnData.forEach((item: flowRateListProps) => { excelDownList.push({ 시설코드: item.bscFctCd, 권역: item.rvbsn, 단위유역: item.lgbsn, 중권역: item.mdmbsn, 환경청: item.rgnNm, 시도: item.sido, 시군구: item.gugun, 시설이름: item.bscFctNm, 주소: item.daddr, "시설용량(m³/일)": item.fctCpc, "총유입량(m³/일)": CommaToNumber(item.totInflAmnt), "하수유입량(m³/일)": CommaToNumber(item.inflAmnt), "연계처리량(m³/일)": CommaToNumber(item.sumFlow), "총인반류수량(m³/일)": CommaToNumber(item.returnAmnt), "방류량(m³/일)": CommaToNumber(item.efflAmnt), }); }); } set((state: FlowRateSearchType) => ({ ...state, FlowRateList: pageSize < 5000 ? { ...state.FlowRateList, flowRateList: rtnData, flowRateCount: recordCount, isLoading: false, } : { ...state.FlowRateList, excelList: excelDownList, isLoading: false, }, })) }, searchFlowRateModalList: async (bscFctCd: string, searchYear: string) => { const res = await fetchFlowRateModalList(bscFctCd, searchYear); const inflData = CalcRainEffect(res.data); const res2 = await fetchFacilityWaterQltyListHist(searchYear, bscFctCd); const wqltData = res2?.data.wqltObjs; //const wqltData = CalcRainEffect(res2?.data.wqltObjs); /** * [(강우시 일별유입유량*강우시 일별유입BOD)-(청천시 연평균유입유량*청천시 연평균유입BOD)] / 강우시 일별유입BOD */ let sunnyInflAmnt = 0; // 청천시 일별유입유량 let sunnyBod = 0; // 청천시 일별유입BOD let sunnyDay = 0; let rainEffectDay = 0; wqltData?.forEach(item => { if (item.infoRnDay == null) item.infoRnDay = 0; if (Number(item.infoRnDay) >= 3) { rainEffectDay = 2; } else { rainEffectDay--; } if (rainEffectDay < 0) { //청천시 sunnyDay += 1; sunnyInflAmnt += Number(item.inflAmnt); sunnyBod += Number(item.inflAssctBfrWqltBod); } }); const yearSunnyAmnt = sunnyDay > 0 ? sunnyInflAmnt / sunnyDay : 0; // 청천시 연평균유입유량 const yearSunnyBod = sunnyDay > 0 ? sunnyBod / sunnyDay : 0; // 청천시 연평균유입BOD //console.log(inflData); const rtnData = inflData.map((item: FlowRateModalProps) => { const targetWqItem = wqltData?.find(wqitem => wqitem.msrDt === item.msrDt.replaceAll('-', '')); const dayBod = targetWqItem ? Number(targetWqItem.inflAssctBfrWqltBod) : 0; const noProcessInflAmnt = Math.round(((Number(item.inflAmnt) * dayBod) - (yearSunnyAmnt * yearSunnyBod)) / dayBod) const totInflAmnt = Number(item.inflAmnt || 0) + Number(item.sumFlow || 0) + Number(item.returnAmnt || 0); return { ...item, totInflAmnt, noProcessInflAmnt: noProcessInflAmnt && noProcessInflAmnt > 0 ? noProcessInflAmnt : '', msrDt: (item.msrDt.length === 8 && !item.msrDt.includes('-')) ? `${item.msrDt.slice(0, 4)}-${item.msrDt.slice(4, 6)}-${item.msrDt.slice(6, 8)}` : item.msrDt, }; }); //console.log(rtnData); set((state: FlowRateSearchType) => ({ ...state, FlowRateModal: { ...state.FlowRateModal, modalFlowRateListYear: rtnData || [], } })) } } }