diff --git a/apps/wr/app/stats/rainStat/page.tsx b/apps/wr/app/stats/rainStat/page.tsx index 1dd4fab9d..17e2d4bae 100644 --- a/apps/wr/app/stats/rainStat/page.tsx +++ b/apps/wr/app/stats/rainStat/page.tsx @@ -34,7 +34,7 @@ export default function RainStat() { searchRainStatList(searchYear ,code.cityCd); }, [code.cityCd, searchRainStatList]) - const excelDetailDownLoad = () => { + const excelDetailDownLoad=() =>{ const sidoList = new Set(); const sidoDataMap = new Map(); // 시도별 데이터를 저장할 Map const sidoDetailMap = new Map(); // 시도별 상세 데이터를 저장할 Map @@ -82,14 +82,14 @@ export default function RainStat() { if (sidoText && sidoDataMap.has(sidoText)) { const sidoData = sidoDataMap.get(sidoText)!; for (let i = 1; i < item.length && i < sidoData.length; i++) { - if (i == 2) { + if(i == 2){ sidoData[i] = '합계'; } else if (i == 3) { const sidoDataCount = transformedRainDetailList.filter((data: unknown[]) => Array.isArray(data) && data.length > 0 && String(data[0]) === sidoText ).length; sidoData[i] = sidoDataCount; - } else if (i == 4) { + } else if( i == 4){ sidoData[i] = ''; } else if (i == 6) { const bumCnt = transformedRainDetailList.filter((data: unknown[]) => @@ -108,12 +108,12 @@ export default function RainStat() { // 시도별로 합계와 상세 데이터를 순서대로 배치 const summaryExcelData: (string | number)[][] = []; - + // 시도별로 순회하면서 합계와 상세 데이터를 추가 Array.from(sidoList).forEach((sidoText) => { const sidoSummary = sidoDataMap.get(sidoText); const sidoDetails = sidoDetailMap.get(sidoText) || []; - + if (sidoSummary) { // 시도 합계 데이터 추가 summaryExcelData.push(sidoSummary); @@ -128,14 +128,14 @@ export default function RainStat() { const sidoTotalSummary = [['전국', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '']]; sidoSummaryList.forEach((item: (string | number)[]) => { item.forEach((value: string | number, index: number) => { - if (typeof value === 'number') { + if(typeof value === 'number') { if (sidoTotalSummary[0] && index < sidoTotalSummary[0].length) { sidoTotalSummary[0][index] = Number(sidoTotalSummary[0][index]) + Number(value); } } }); }); - + // sidoSummaryList와 rainDetailList를 합쳐서 엑셀 데이터 생성 const excelData = [...sidoTotalSummary, ...sidoSummaryList, ...summaryExcelData]; @@ -276,7 +276,7 @@ export default function RainStat() { total={0} headName={""} cellClick={undefined} - onPageChange={() => { }} + onPageChange={() => {}} > diff --git a/apps/wr/app/stats/rswtStat/page.tsx b/apps/wr/app/stats/rswtStat/page.tsx index 6968552cb..99a8bc4f3 100644 --- a/apps/wr/app/stats/rswtStat/page.tsx +++ b/apps/wr/app/stats/rswtStat/page.tsx @@ -14,78 +14,81 @@ import { import ListDiv from "@common/business_components/ui/list_div"; import { Button } from "@common/components/ui"; import { useEffect, useState } from "react"; +import toast, { Toaster } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; export default function RswtStat() { const { code, rswtStat, searchRswtStatList } = useWrStore((state) => state); - const { rswtStatList, excelList, rswtDetailList } = rswtStat; + const { rswtStatList, rswtDetailList } = rswtStat; const [rswtTable, setRswtTable] = useState(); const [searchYear, setSearchYear] = useState( String(new Date().getFullYear()) ); - const [excelData, setExceData] = useState[]>(); + const { t } = useTranslation('base'); useEffect(() => { - searchRswtStatList(searchYear) - }, [searchRswtStatList]) + searchRswtStatList(searchYear, code.cityCd) + }, [searchRswtStatList, code.cityCd]) const excelClick = () => { - downloadExcel({ - data: (excelData as unknown as JSON[]) ?? [], - fileName: "중수도재이용통계", - sheetNameArray: ["Sheet1"], - headerRange: "A1:N1" - }) + + if (rswtTable) { + const data = rswtTable.map((item: RswtStatProps) => { + return { + "시도": item.cityText, + "개소": item.ctpvCnt, + // "건축연면적(m³)": item.archArea, + "처리용량(m³)": item.filtrTrtmfctCpct, + "물사용량(m³/년)": item.wtrUsqty, + "중수도+대체수이용량(m³/년)": item.rswtAltSum, + "중수도이용량(m³/년)": item.rswtrUsqty, + "대체수이용량(m³/년)": item.altUswtrUtztnQnt, + "조경용수": item.lndwtr, + "청소화장실용수": item.cleanToilUswtr, + "농업용수": item.farmUswtr, + "공업용수": item.indstUswtr, + "친수용수": item.hydUswtr, + "기타": item.ithlEtcUswtr, + "연간운영비(백만원/년)": item.anlOperCst, + }; + }) + + downloadExcel({ + data: (data as unknown as JSON[]) ?? [], + fileName: "중수도재이용통계", + sheetNameArray: ["Sheet1"], + headerRange: "A1:N1" + }) + } else { + toast.error(t("excelDownErrMsg")) + } } useEffect(() => { const transData = Array.isArray(rswtStatList) ? rswtStatList : [rswtStatList]; - const data = tableData(transData, { code }); - const tbData = Array.isArray(data) - ? data.map((item: RswtStatProps) => { + const cityData = tableData(transData, { code }); + const tbData = Array.isArray(cityData) + ? cityData.map((item: RswtStatProps) => { return { ...item, - ctpvCd: item.cityText + ctpvCd: item.cityText === '전체' ? '전국' : item.cityText, + cityText: item.cityText === '전체' ? '전국' : item.cityText }; - }).filter((item: RswtStatProps) => item.cityText !== '없음') - : []; - setRswtTable(tbData); - }, [code, rswtStatList]) + }) : []; - useEffect(() => { - const transExcel = Array.isArray(excelList) ? excelList : [excelList]; - const exData = tableData(transExcel, { code }); - const tbData = Array.isArray(exData) ? - exData - .filter((item: RswtStatProps) => item.cityText !== '없음') - .map((item: RswtStatProps) => { - return { - "시도": item.cityText, - "개소": item.ctpvCnt, - // "건축연면적(m³)": item.archArea, - "처리용량(m³)": item.filtrTrtmfctCpct, - "물사용량(m³/년)": item.wtrUsqty, - "중수도+대체수이용량(m³/년)": item.rswtAltSum, - "중수도이용량(m³/년)": item.rswtrUsqty, - "대체수이용량(m³/년)": item.altUswtrUtztnQnt, - "조경용수": item.lndwtr, - "청소화장실용수": item.cleanToilUswtr, - "농업용수": item.farmUswtr, - "공업용수": item.indstUswtr, - "친수용수": item.hydUswtr, - "기타": item.ithlEtcUswtr, - "연간운영비(백만원/년)": item.anlOperCst, - }; - }) : []; - setExceData(tbData); - }, [code, excelList]) + setRswtTable(tbData); + }, [code, rswtStatList]); const excelDetailDownLoad = () => { + const sidoList = new Set(); const sidoDataMap = new Map(); // 시도별 데이터를 저장할 Map const sidoDetailMap = new Map(); // 시도별 상세 데이터를 저장할 Map // 먼저 시도별 상세 데이터를 그룹화 - rswtDetailList.forEach((item: RswtStatProps[]) => { + const transformedRswtDetailList = rswtDetailList.map((originItem: RswtStatProps[]) => { + // rswtDetailList.forEach((item: RswtStatProps[]) => { + const item = [...originItem]; // 원본 복사 const sidoVal = item.at(0)?.toString().trim(); const sigunVal = item.at(1)?.toString().trim(); let sidoText = ''; @@ -127,10 +130,11 @@ export default function RswtStat() { } sidoDataMap.set(sidoText, initialData); } + return item; }); // 시도별 합계 계산 - rswtDetailList.forEach((item: RswtStatProps[]) => { + transformedRswtDetailList.forEach((item: RswtStatProps[]) => { const sidoText = item[0]?.toString(); if (sidoText && sidoDataMap.has(sidoText)) { const sidoData = sidoDataMap.get(sidoText)!; @@ -199,7 +203,7 @@ export default function RswtStat() { }); const sidoSummaryList = Array.from(sidoDataMap.values()); - const sidoTotalSummary = [['전체', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '', 0]]; + const sidoTotalSummary = [['전국', '', '합계', 0, '', '', 0, '', '', 0, 0, 0, 0, 0, 0, '']]; sidoSummaryList.forEach((item: (string | number)[]) => { item.forEach((value: string | number, index: number) => { if (typeof value === 'number') { @@ -217,7 +221,7 @@ export default function RswtStat() { excelData as unknown as [][], "중수도시설 통계", "sample_rswtStats.xlsx", - "A1:Q3", + "A1:P3", 4 ); } @@ -244,7 +248,7 @@ export default function RswtStat() { className="" size="sm" onClick={() => { - searchRswtStatList(searchYear) + searchRswtStatList(searchYear, code.cityCd) }} > 조회 @@ -285,6 +289,7 @@ export default function RswtStat() { + ); diff --git a/apps/wr/app/store/stats/rswtStat/excel.tsx b/apps/wr/app/store/stats/rswtStat/excel.tsx index 7c6e2b4cc..00935b8fb 100644 --- a/apps/wr/app/store/stats/rswtStat/excel.tsx +++ b/apps/wr/app/store/stats/rswtStat/excel.tsx @@ -1,4 +1,5 @@ import type { RswtStatProps } from "."; +import { bdstUsgCd } from "../../common/code/basicCode"; export const excelRswtStat = (excelList:RswtStatProps[]) : (string | number)[][] => { const excelData: (string | number)[][] = []; @@ -14,7 +15,7 @@ export const excelRswtStat = (excelList:RswtStatProps[]) : (string | number)[][] String(item.bdstNm) ?? "", //건축물용도코드(빈칸) //String(item.bdstUsgCd) ?? "", - "", + bdstUsgCd.find((cd)=> cd.val === item.bdstUsgCd.toString())?.text ?? "", //건축물용도 //주소 String(item.daddr) ?? "", //법적의무대상여부 diff --git a/apps/wr/app/store/stats/rswtStat/index.tsx b/apps/wr/app/store/stats/rswtStat/index.tsx index af106c3b3..89c4089c0 100644 --- a/apps/wr/app/store/stats/rswtStat/index.tsx +++ b/apps/wr/app/store/stats/rswtStat/index.tsx @@ -6,7 +6,7 @@ import { excelRswtStat } from "./excel"; export type RswtStatProps = { cityText: string //시도명 ctpvCd: string //시도 - sggCd : string //시군구 + sggCd: string //시군구 areaNm: string //행정구역명 bdstNm: string //시설명 daddr: string //주소 @@ -26,9 +26,10 @@ export type RswtStatProps = { ithlEtcUswtr: number //기타 anlOperCst: number //연간운영비 guideStats: GuideStatProps[] - utztnUsgCd : string //이용코드 - lawTrgtYn : string //법적의무대상여부 - instlCmptnDt : string //설치완료일자 + utztnUsgCd: string //이용코드 + lawTrgtYn: string //법적의무대상여부 + instlCmptnDt: string //설치완료일자 + bdstUsgCd: number } export type GuideStatProps = { @@ -37,7 +38,7 @@ export type GuideStatProps = { } type rswtStatActions = { - searchRswtStatList: (year: string) => void; + searchRswtStatList: (year: string, city: { val: string; text: string }[]) => void; } export type ExcelType = { @@ -71,36 +72,44 @@ export const rswtStatActionsExport: (set: any) => rswtStatActions = ( set: any ) => { return { - searchRswtStatList: async (year: string) => { + searchRswtStatList: async (year: string, city: { val: string; text: string }[]) => { const res = await getFetch(fetchType.WR, `/reuseChk/reuseWater/stat/${year}`) - + const data = res.filter(item => { + const code = item.ctpvCd.trim(); + return city.some(el => el.val === code); + }); const cityArr: any[] = []; - res.forEach((item: RswtStatProps) => { + data.forEach((item: RswtStatProps) => { let obj = cityArr.find((e) => { return e.ctpvCd == item.ctpvCd }) if (obj) { - obj.ctpvCnt += 1 - obj.archArea += item.archArea - obj.filtrTrtmfctCpct += item.filtrTrtmfctCpct - obj.wtrUsqty += item.wtrUsqty - obj.rswtAltSum += (item.rswtrUsqty + item.altUswtrUtztnQnt) - obj.rswtrUsqty += item.rswtrUsqty - obj.altUswtrUtztnQnt += item.altUswtrUtztnQnt - obj.anlOperCst += item.anlOperCst + obj.ctpvCnt += 1 //개소 + // obj.archArea += item.archArea 건축면적 삭제 + obj.filtrTrtmfctCpct += item.filtrTrtmfctCpct //처리용량 + obj.wtrUsqty += item.wtrUsqty //물사용량 + obj.rswtAltSum += (item.rswtrUsqty + item.altUswtrUtztnQnt) //중수도+대체수 + obj.rswtrUsqty += item.rswtrUsqty //중수도사용량 + obj.altUswtrUtztnQnt += item.altUswtrUtztnQnt //대체수이용량 + obj.anlOperCst += item.anlOperCst //연간운영비용 } else { - obj = {}; - obj.ctpvCd = item.ctpvCd - obj.ctpvCnt = 1 - obj.archArea = item.archArea - obj.filtrTrtmfctCpct = item.filtrTrtmfctCpct - obj.wtrUsqty = item.wtrUsqty - obj.rswtAltSum = item.rswtrUsqty + item.altUswtrUtztnQnt - obj.rswtrUsqty = item.rswtrUsqty - obj.altUswtrUtztnQnt = item.altUswtrUtztnQnt - obj.anlOperCst = item.anlOperCst - + obj = { + ctpvCd: item.ctpvCd, + ctpvCnt: 1, + filtrTrtmfctCpct: item.filtrTrtmfctCpct, + wtrUsqty: item.wtrUsqty, + rswtAltSum: item.rswtrUsqty + item.altUswtrUtztnQnt, + rswtrUsqty: item.rswtrUsqty, + altUswtrUtztnQnt: item.altUswtrUtztnQnt, + anlOperCst: item.anlOperCst, + lndwtr: 0, + cleanToilUswtr: 0, + farmUswtr: 0, + indstUswtr: 0, + hydUswtr: 0, + ithlEtcUswtr: 0, + } cityArr.push(obj) } @@ -120,11 +129,47 @@ export const rswtStatActionsExport: (set: any) => rswtStatActions = ( } }); + const total: any = { + ctpvCd: "0", + ctpvCnt: 0, + filtrTrtmfctCpct: 0, + wtrUsqty: 0, + rswtAltSum: 0, + rswtrUsqty: 0, + altUswtrUtztnQnt: 0, + anlOperCst: 0, + lndwtr: 0, + cleanToilUswtr: 0, + farmUswtr: 0, + indstUswtr: 0, + hydUswtr: 0, + ithlEtcUswtr: 0, + }; + + cityArr.forEach(item => { + total.ctpvCnt += item.ctpvCnt; + total.archArea += item.archArea; + total.filtrTrtmfctCpct += item.filtrTrtmfctCpct; + total.wtrUsqty += item.wtrUsqty; + total.rswtAltSum += item.rswtAltSum; + total.rswtrUsqty += item.rswtrUsqty; + total.altUswtrUtztnQnt += item.altUswtrUtztnQnt; + total.anlOperCst += item.anlOperCst; + total.lndwtr += item.lndwtr; + total.cleanToilUswtr += item.cleanToilUswtr; + total.farmUswtr += item.farmUswtr; + total.indstUswtr += item.indstUswtr; + total.hydUswtr += item.hydUswtr; + total.ithlEtcUswtr += item.ithlEtcUswtr; + }); + + cityArr.unshift(total); + cityArr.forEach(item => { excelDownList.push({ ctpvCd: item.ctpvCd, ctpvCnt: item.ctpvCnt, - archArea: item.archArea, + // archArea: item.archArea, filtrTrtmfctCpct: item.filtrTrtmfctCpct, wtrUsqty: item.wtrUsqty, rswtAltSum: item.rswtAltSum, @@ -141,19 +186,18 @@ export const rswtStatActionsExport: (set: any) => rswtStatActions = ( }) //상세 - const rswtDetailList : RswtStatProps[] = []; - res.forEach((item:RswtStatProps) => { + const rswtDetailList: RswtStatProps[] = []; + res.forEach((item: RswtStatProps) => { const utztnUsgArray = new Array(); item.guideStats.forEach((guideStat) => { utztnUsgArray.push(guideStat.utztnUsgCd); }) rswtDetailList.push({ ...item, - rswtAltSum : item.rswtrUsqty + item.altUswtrUtztnQnt, - utztnUsgCd : utztnUsgArray.join(', '), + rswtAltSum: item.rswtrUsqty + item.altUswtrUtztnQnt, + utztnUsgCd: utztnUsgArray.join(', '), }) }); - const excelDetailData = excelRswtStat(rswtDetailList); set((state: rswtStatState) => ({ rswtStat: { diff --git a/apps/wr/public/sample_rswtStats.xlsx b/apps/wr/public/sample_rswtStats.xlsx index 702c4cec0..bee059e26 100644 Binary files a/apps/wr/public/sample_rswtStats.xlsx and b/apps/wr/public/sample_rswtStats.xlsx differ