Files
frontend/apps/fo/app/store/underWaterInput/index.tsx
T
2025-09-02 16:43:38 +09:00

462 lines
19 KiB
TypeScript

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 타입을 여기에 정의
export type SewageOccurDetailProps = {
cnt : number,
sum : number,
yr:string,
usege:number
}
/**====================================
* Store - 타입
====================================*/
/**
* (1) 메인페이지
*/
// 시설별 강수현황
/**====================================
* Store - data
====================================*/
/**
* (1) 메인페이지
*/
// 검색단
const LabelArray:string[] = ['구분', '시도', '시군구','용량별', '시설명', '조회기간', '시설상태', '권역', '단위유역', '중권역', '환경청별'];
// 리스트 헤더
const upHeadList1:TableUpperProps[] = [
{ id: "A", title: "행정구역", row:0, colSpan:2 },
{ id: "sidoNm", title: "시도", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "sggNm", title: "시군구", upName:"upChangeRe",upSequnce:2, row:1 },
{ 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[] = [
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe", upSequnce:1, row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe", upSequnce:2, row:1 },
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe", upSequnce:3, row:1 },
{ 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[] = [
{ id: "A", title: "유역", row:0, colSpan:3 },
{ id: "rvbsn", title: "권역", upName:"upChangeRe1", upSequnce:1, row:1 },
{ id: "lgbsn", title: "단위유역", upName:"upChangeRe1", upSequnce:2, row:1 },
{ id: "mdmbsn", title: "중권역", upName:"upChangeRe1", upSequnce:3, row:1 },
{ id: "rgnNm", title: "환경청", row:0, rowSpan:2 },
{ id: "B", title: "행정구역", row:0, colSpan:2 },
{ id: "sidoNm", title: "시도", upName:"upChangeRe2", upSequnce:1, row:1 },
{ id: "sggNm", title: "시군구", upName:"upChangeRe2",upSequnce:2, row:1 },
{ 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 upHeadListUnderWaterDetail:TableUpperProps[] = [
{ id: "msrDt", title: "날짜" },
{ id: "realSewageInput", title: "청천시 실제 하수유입량\n(m³/일)", align:"right" },
{ id: "sewageOccur", title: "오수발생량\n(m³/일)", align:"right" },
{ id: "underWaterInput", title: "지하수 유입량\n(m³/일)", align:"right" },
];
const underWaterList:UnderWaterProps[] = [
]
const underWaterDetailList:UnderWaterInputModalProps[] = [
{
msrDt : "2024-01",
realSewageInput : 178007,
sewageOccur : 10.5,
underWaterInput : 80.6,
},
{
msrDt : "2024-02",
realSewageInput : 123007,
sewageOccur : 10.7,
underWaterInput : 80.6,
},
{
msrDt : "2024-03",
realSewageInput : 213007,
sewageOccur : 10.1,
underWaterInput : 80.6,
},
{
msrDt : "2024-04",
realSewageInput : 83007,
sewageOccur : 9.57,
underWaterInput : 80.6,
},
{
msrDt : "2024-05",
realSewageInput : 15007,
sewageOccur : 3.57,
underWaterInput : 80.6,
},
{
msrDt : "2024-06",
realSewageInput : 123007,
sewageOccur : '',
underWaterInput : 80.6,
},
{
msrDt : "2024-07",
realSewageInput : 101007,
sewageOccur : 1,
underWaterInput : 80.6,
},
{
msrDt : "2024-08",
realSewageInput : 103807,
sewageOccur : 10.57,
underWaterInput : '',
},
{
msrDt : "2024-09",
realSewageInput : 9007,
sewageOccur : 10.57,
underWaterInput : 80.6,
},
{
msrDt : "2024-10",
realSewageInput : 163007,
sewageOccur : 10.57,
underWaterInput : 80.6,
},
{
msrDt : "2024-11",
realSewageInput : 123007,
sewageOccur : 10.57,
underWaterInput : 80.6,
},
{
msrDt : "2024-12",
realSewageInput : 1007,
sewageOccur : 10.57,
underWaterInput : 80.6,
},
]
/**====================================
* Store - API
====================================*/
// API response types
export interface FlowDataItem {
inflAmnt: number | string;
infoRnDay: number;
msrDt: string;
rainEffectDay? : number;
sumFlow? : number | string | '';
}
export interface ApiResponse {
data: FlowDataItem[];
count: number;
}
const fetchUnderWaterList = async (pageNo: number, pageSize: number, searchYear: string, partCd?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => {
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 }
/*
const tailStr = partCd ? '/'+ partCd + '/' + nameCd + '/' + fcltCpct + '/' + operationValue + (fcltyNm && fcltyNm !== '' ? '/' + fcltyNm : '') : '';
const url = '/fclt/qlty/' + pageNo + '/' + pageSize + '/' + searchYear + tailStr;
const res = await getFetch('fo', url);
return { data: res.data, count: res.count } */
//return { data: underWaterList, count: 2 };
}
/**====================================
* Store - expaort
====================================*/
export type UnderWaterActions = {
searchUnderWaterList: (pageNo: number, pageSize: number, searchYear: string, part?: string, nameCd?: string, fcltCpct?: string, operationValue?: string, fcltyNm?: string) => void;
unserWaterModal:(bscFctCd:string, searchYear:string, startYm:string, endYm:string)=>void
}
export type UnderWaterType = {
UnderWaterSearch: {
isInit: boolean;
labelArray:string[];
},
UnderWater : {
isInit: boolean;
upHeadList1: TableUpperProps[];
upHeadList2: TableUpperProps[];
upHeadList3: TableUpperProps[];
underWaterList: UnderWaterProps[]; // Changed from facilityAreaProps to ProcessAreaProps
underWaterCount: number;
excelList: ExcelType[];
isLoading: boolean;
},
UnderWaterDetail : {
isInit: boolean;
upHeadListUnderWaterDetail: TableUpperProps[];
gridListUnderWaterDetail: UnderWaterInputModalProps[];
}
}
export const underWaterInitState: UnderWaterType = {
UnderWaterSearch: {
isInit: false,
labelArray: LabelArray,
},
UnderWater : {
isInit : false,
upHeadList1 : upHeadList1,
upHeadList2 : upHeadList2,
upHeadList3 : upHeadList3,
underWaterList : underWaterList,
underWaterCount : 4,
excelList : [],
isLoading : true,
},
UnderWaterDetail : {
isInit: false,
upHeadListUnderWaterDetail: upHeadListUnderWaterDetail,
gridListUnderWaterDetail: underWaterDetailList,
}
}
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>});
}
export type UnderWaterStore = UnderWaterType & UnderWaterActions;
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) => {
set((state: UnderWaterType) => ({
...state,
UnderWater: {
...state.UnderWater,
isLoading: true,
},
}));
const res = await fetchUnderWaterList(pageNo, pageSize, searchYear, part, nameCd, fcltCpct, operationValue, fcltyNm);
const data = res.data;
const calData = await Promise.all(data.map(async (item: UnderWaterProps) => {
item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || '';
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
const bscFctCd = item.bscFctCd;
const res2 = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear) as ApiResponse;
const calData = CalcRainEffect(res2.data, 'SUNNY');
let chungcunSumFlow = 0;
let sumSummerChungcunDay = 0;
let sumSummerChungcunFlow = 0;
let sumWinterChungcunDay = 0;
let sumWinterChungcunFlow = 0;
calData.forEach((flowItem: FlowDataItem) => {
chungcunSumFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
if(flowItem.msrDt.substring(4,6) ==='06' || flowItem.msrDt.substring(4,6) ==='07' || flowItem.msrDt.substring(4,6) ==='08'){
sumSummerChungcunDay += 1;
sumSummerChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
}else if(flowItem.msrDt.substring(4,6) ==='01' || flowItem.msrDt.substring(4,6) ==='02'){
sumWinterChungcunDay += 1;
sumWinterChungcunFlow += flowItem.inflAmnt && flowItem.inflAmnt !== 'x' ? Number(flowItem.inflAmnt.toString().trim()) : 0;
}
});
const usage = chungcunSumFlow / calData.length;
const summerUsage = sumSummerChungcunFlow / sumSummerChungcunDay;
const winterUsage = sumWinterChungcunFlow / sumWinterChungcunDay;
//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*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;
}));
const excelDownList: ExcelType[] = [];
if(pageSize>5000){
calData.forEach(item => {
dataFormSetting(item)
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
/* item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */
excelDownList.push({
시설코드: item.bscFctCd,
권역: item.rvbsn,
단위유역: item.lgbsn,
중권역: item.mdmbsn,
환경청: item.rgnNm,
시도: item.sidoNm,
시군구: item.sggNm,
시설명: item.bscFctNm,
주소: item.daddr,
"시설용량(m³/일)": item.fctCpc,
"평균유입하수량(m³/일)": item.inflAmnt,
"연간지하수유입량(m³/일)": item.underWaterInputYear,
"하절기지하수유입량(m³/일)": item.underWaterInputSummer,
"동절기지하수유입량(m³/일)": item.underWaterInputWinter,
적정여부: item.properYn,
});
});
}else{
data.forEach((item: UnderWaterProps) => {
dataFormSetting(item)
item.fctCpc = parseFloat(item.fctCpc.toString().replace(/,/g, ''));
/* item.sidoNm = item.lclgvrnmntNm.split(' ')[0]?.toString() || '';
item.sggNm = item.lclgvrnmntNm.split(' ')[1]?.toString() || ''; */
});
}
set((state: UnderWaterType) => ({
...state,
UnderWater: pageSize<5000?{
...state.UnderWater,
underWaterList: calData,
underWaterCount: res.count,
isLoading : false,
}:{
...state.UnderWater,
isLoading : false,
excelList: excelDownList
},
}))
},
unserWaterModal:async (bscFctCd, searchYear, startYm, endYm)=>{
const res = await getFetch('fo', '/fclt/flow/' + bscFctCd + '/' + searchYear);
const monthData: SewageOccurDetailProps[] = [];
const calData = CalcRainEffect(res.data, 'SUNNY');
let tot = 0;
let cnt = 0;
calData.forEach((item: FlowDataItem) => {
const month = item.msrDt?.substring(4, 6);
const monthIdx = month ? Number(month) - 1 : -1;
if (monthIdx >= 0 && (monthIdx>=Number(startYm.substring(4,6))-1 && monthIdx <= Number(endYm.substring(4, 6))-1)) {
if (typeof monthData[monthIdx] === 'object') {
monthData[monthIdx].sum += Number(item.inflAmnt);
monthData[monthIdx].cnt++;
} else {
monthData[monthIdx] = {cnt:1, sum:Number(item.inflAmnt), yr:item.msrDt.substring(0,4), usege:0};
}
}
if(month >= startYm.substring(4, 6) && month <= endYm.substring(4, 6)){
cnt++;
tot += item.inflAmnt && item.inflAmnt !== 'x' ? Number(item.inflAmnt.toString().trim()) : 0;
}
});
const tableData:UnderWaterInputModalProps[] = []
let maxWaterUsage = 0;
let minWaterUsage = 9999999999;
let avgWaterUsage = 0;
monthData.forEach((item, index) => {
item.usege = item.sum/item.cnt
tableData.push({
msrDt: item.yr+'-'+(index+1>=10?String(index+1):'0'+(index+1)),
realSewageInput:Math.round(item.usege*1) /1,
sewageOccur:Math.round(item.usege*0.65*OSU_PERCENT * 1) / 1,
underWaterInput:Math.round((item.usege-(item.usege*0.65*OSU_PERCENT)) * 1) / 1,
})
if (item.usege > maxWaterUsage) {
maxWaterUsage = item.usege;
}
if (item.usege < minWaterUsage) {
minWaterUsage = item.usege;
}
});
if(monthData.length == 0){
maxWaterUsage = 0;
avgWaterUsage = 0;
minWaterUsage = 0;
}
avgWaterUsage = tot/cnt;
const newData= [
{
msrDt: '평균',
realSewageInput:Math.round(avgWaterUsage*1) /1,
sewageOccur:Math.round(avgWaterUsage*0.65*OSU_PERCENT * 1) / 1,
underWaterInput: Math.round((avgWaterUsage-(avgWaterUsage*0.65*OSU_PERCENT)) * 1) / 1
//underWaterInput:Math.round((avgWaterUsage-(avgWaterUsage*0.65*0.8)) * 100) / 100,
},
{
msrDt: '최대',
realSewageInput: Math.round(maxWaterUsage*1) /1,
sewageOccur: Math.round(maxWaterUsage*0.65*OSU_PERCENT * 1) / 1,
underWaterInput: Math.round((maxWaterUsage-(maxWaterUsage*0.65*OSU_PERCENT)) * 1) / 1,
},
{
msrDt: '최소',
realSewageInput: Math.round(minWaterUsage*1) /1,
sewageOccur: Math.round(minWaterUsage*0.65*OSU_PERCENT * 1) / 1,
underWaterInput: Math.round((minWaterUsage-(minWaterUsage*0.65*OSU_PERCENT)) * 1) / 1,
},
...tableData
]
set((state: UnderWaterType) => ({
...state,
UnderWaterDetail: {
...state.UnderWaterDetail,
gridListUnderWaterDetail:newData
}
}))
}
}
}