From a11eaf031d9ba479ab0dba57772dc83e9a16948c Mon Sep 17 00:00:00 2001 From: yangsein Date: Mon, 15 Jun 2026 00:52:54 +0900 Subject: [PATCH] =?UTF-8?q?feat:[=EC=A7=91=EA=B3=84=ED=91=9C]08.=EA=B0=9C?= =?UTF-8?q?=EC=9D=B8=ED=95=98=EC=88=98=EC=B2=98=EB=A6=AC=EC=8B=9C=EC=84=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../total/PrivateSewageFacilityTot.tsx | 202 +++++++++++++++++- .../SewerPrivateSewageTab1Column.ts | 46 ++++ .../SewerPrivateSewageTab2Column.ts | 72 +++++++ .../SewerPrivateSewageTab3Column.ts | 48 +++++ ...atistics-private-sewage-total-interface.ts | 109 ++++++++++ 5 files changed, 474 insertions(+), 3 deletions(-) create mode 100644 apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab1Column.ts create mode 100644 apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab2Column.ts create mode 100644 apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab3Column.ts create mode 100644 apps/st/src/entities/statistics/model/statistics-total/statistics-private-sewage-total-interface.ts diff --git a/apps/st/src/components/statistics/total/PrivateSewageFacilityTot.tsx b/apps/st/src/components/statistics/total/PrivateSewageFacilityTot.tsx index 1171f7b2c..0948ab60e 100644 --- a/apps/st/src/components/statistics/total/PrivateSewageFacilityTot.tsx +++ b/apps/st/src/components/statistics/total/PrivateSewageFacilityTot.tsx @@ -1,10 +1,206 @@ +import { useRef, useState } from "react"; + +import { useAlertStore } from "@/shared/lib"; +import { LoadingWithAnimation, Tabs, TabsContent, TabsList, TabsTrigger } from "@common/components"; + import SearchForm from "@/components/module/SearchForm"; +import DataGrid from "@/components/module/DataGrid"; +import type { ColumnInfo } from "@/components/type/DataGrid.type"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import { toGridRows } from "@/components/util/grid/gridFunction"; + +// 분리된 개별 3개 컬럼 스펙 파일 로드 +import { PrivateSewageTab1ColumnConfig } from "@/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab1Column"; +import { PrivateSewageTab2ColumnConfig } from "@/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab2Column"; +import { PrivateSewageTab3ColumnConfig } from "@/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab3Column"; + +// 통계 API 서비스 및 통합 DTO 명세 임포트 +import { statisticsTotalStatusApi } from "@/entities/statistics/api/statistics-total-service"; +import type { + PrivateSewageFacilitySummaryRequest +} from "@/entities/statistics/model/statistics-total/statistics-private-sewage-total-interface"; +import CellColorInfo from "./CellColorInfo"; + +const PrivateSewageColumnListTot = [ + PrivateSewageTab1ColumnConfig, + PrivateSewageTab2ColumnConfig, + PrivateSewageTab3ColumnConfig +]; + +const firstTabKey = PrivateSewageColumnListTot[0]?.tabKey ?? "ST00040005_1"; const PrivateSewageFacilityTot = () => { + const { setMessage: alert } = useAlertStore((state) => state); + + // null 컴파일 예러를 사전에 원천 차단한 안전 상태 맵 선언 + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const [isLoading, setIsLoading] = useState(false); + const [activeTab, setActiveTab] = useState(firstTabKey); + const lastSearchedValuesRef = useRef(null); + + const columnInfo = PrivateSewageColumnListTot; + + const handleReset = () => { + setRowDataMap(new Map()); + setActiveTab(firstTabKey); + lastSearchedValuesRef.current = null; + }; + + /** 각 탭별 엔드포인트 비동기 디스패치 및 연동 */ + const loadGridData = async (tabKey: string, values: SearchFormValues): Promise => { + const param: PrivateSewageFacilitySummaryRequest = { + ctpvNm: values.sido === "ALL" ? "" : values.sido, + sggNm: values.gugun === "ALL" ? "" : values.gugun, + sewerBzmnCd: values.bsnmCd, + statsYr: values.year, + rowDataYn: values.isDetail, + summaryYn: values.isSummary !== 'ALL', + summaryYearCnt: values.isSummary !== 'ALL' ? Number(values.isSummary) : undefined + }; + + try { + // [Tab1] 처리용량별 오수처리시설 + if (tabKey === "ST00080001") { + const response = await statisticsTotalStatusApi.getPrivateSewageTab1List(param); + if (response && response.status === "success" && response.data) { + setRowDataMap((prev) => new Map(prev).set(tabKey, toGridRows(response.data as object[]))); + return true; + } + alert(response?.message || "데이터 조회 중 오류가 발생했습니다."); + } + + // [Tab2] 정화조현황 + if (tabKey === "ST00080002") { + const response = await statisticsTotalStatusApi.getPrivateSewageTab2List(param); + if (response && response.status === "success" && response.data) { + setRowDataMap((prev) => new Map(prev).set(tabKey, toGridRows(response.data as object[]))); + return true; + } + alert(response?.message || "데이터 조회 중 오류가 발생했습니다."); + } + + // [Tab3] 개인하수도 관리지역 지정공고 현황 + if (tabKey === "ST00080003") { + const response = await statisticsTotalStatusApi.getPrivatePrivateMgmtAreaList(param); + if (response && response.status === "success" && response.data) { + setRowDataMap((prev) => new Map(prev).set(tabKey, toGridRows(response.data as object[]))); + return true; + } + alert(response?.message || "데이터 조회 중 오류가 발생했습니다."); + } + return false; + } catch { + alert("서버 연결 중 오류가 발생했습니다."); + return false; + } + }; + + const handleSearch = async (values: SearchFormValues) => { + try { + setIsLoading(true); + const ok = await loadGridData(activeTab, values); + if (ok) { + lastSearchedValuesRef.current = values; + } else { + lastSearchedValuesRef.current = null; + } + } catch { + alert("데이터 조회 중 오류가 발생했습니다."); + lastSearchedValuesRef.current = null; + } finally { + setIsLoading(false); + } + }; + + const handleActiveTabChange = async (tabKey: string) => { + setActiveTab(tabKey); + const values = lastSearchedValuesRef.current; + if (!values) return; + + const existing = rowDataMap.get(tabKey); + if (existing && existing.length > 0) return; // 캐싱 검증 스킵 + + try { + setIsLoading(true); + await loadGridData(tabKey, values); + } catch { + alert("데이터 조회 중 오류가 발생했습니다."); + } finally { + setIsLoading(false); + } + }; + return ( - <> - - +
+ + + {/* 하수관로 규칙과 100% 싱크 맞춘 중앙 정렬 소형 팝업 로딩 바 고정 */} + {isLoading && ( +
+
+ +
+
+ )} + + + +
+ void handleActiveTabChange(v)} className="w-full" variant="default"> + + {columnInfo.map((info) => ( + + {info.tabLabel} + + ))} + + + {columnInfo.map((info) => { + const tabKey = info.tabKey; + + // 단언 연산자(as) 배제 형태 완벽 적용 + const rowData = rowDataMap.get(tabKey) ?? []; + + const gridColumnInfo: ColumnInfo = { + columns: info.columns, + columnLayout: info.columnLayout, + }; + + return ( + + { + setRowDataMap((prev) => { + const next = new Map(prev); + const cur = next.get(tabKey) ?? []; + const n = typeof updater === "function" ? updater(cur) : updater; + next.set(tabKey, n); + return next; + }); + }} + isExcelImport={false} + isExcelExport={true} + showHeaderCheckbox={false} + fixedColumns={info.fixedColumns} + enableSort={false} + cellStyleCallback={({ row }) => { + const rowType = String(row.rowType ?? ''); + if (rowType === 'DETAIL') return undefined; + if (rowType === 'BIZ_SUM') return 'rg-cell-rowtype-biz-sum'; + if (rowType === 'SUMMARY') return 'rg-cell-rowtype-summary'; + return 'rg-cell-rowtype-other'; + }} + /> + + ); + })} + +
+
); }; diff --git a/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab1Column.ts b/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab1Column.ts new file mode 100644 index 000000000..c4af5d5a6 --- /dev/null +++ b/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab1Column.ts @@ -0,0 +1,46 @@ +import { ValueType } from "realgrid"; + +export const PrivateSewageTab1ColumnConfig = { + tabKey: "ST00080001", + tabLabel: "처리용량별 오수처리시설", + rowStartNum: 3, + fixedColumns: 3, + columns: [ + { name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false }, + { name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false }, + { name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역명" }, editable: false }, + { name: "wholDrtwPrcsFcltCnt", fieldName: "wholDrtwPrcsFcltCnt", header: { text: "총계" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + + // 하수처리구역 내 + { name: "wholStaaCnt", fieldName: "wholStaaCnt", header: { text: "계" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step1StaaPrcsQnt", fieldName: "step1StaaPrcsQnt", header: { text: "2이하" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step2StaaPrcsQnt", fieldName: "step2StaaPrcsQnt", header: { text: "3~10" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step3StaaPrcsQnt", fieldName: "step3StaaPrcsQnt", header: { text: "11~20" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step4StaaPrcsQnt", fieldName: "step4StaaPrcsQnt", header: { text: "21~50" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step5StaaPrcsQnt", fieldName: "step5StaaPrcsQnt", header: { text: "51~100" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step6StaaPrcsQnt", fieldName: "step6StaaPrcsQnt", header: { text: "101~500" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step7StaaPrcsQnt", fieldName: "step7StaaPrcsQnt", header: { text: "501이상" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + + // 하수처리구역 외 + { name: "staaExcpWhol", fieldName: "staaExcpWhol", header: { text: "계" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step1StaaExcpPrcsQnt", fieldName: "step1StaaExcpPrcsQnt", header: { text: "2이하" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step2StaaExcpPrcsQnt", fieldName: "step2StaaExcpPrcsQnt", header: { text: "3~10" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step3StaaExcpPrcsQnt", fieldName: "step3StaaExcpPrcsQnt", header: { text: "11~20" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step4StaaExcpPrcsQnt", fieldName: "step4StaaExcpPrcsQnt", header: { text: "21~50" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step5StaaExcpPrcsQnt", fieldName: "step5StaaExcpPrcsQnt", header: { text: "51~100" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step6StaaExcpPrcsQnt", fieldName: "step6StaaExcpPrcsQnt", header: { text: "101~500" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step7StaaExcpPrcsQnt", fieldName: "step7StaaExcpPrcsQnt", header: { text: "501이상" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false } + ], + columnLayout: [ + { name: "areaGroup", header: { text: "행정구역" }, items: ["ctpvNm", "sggNm", "admdstNm"] }, + "wholDrtwPrcsFcltCnt", + { + name: "privateSewageFacilityGroup", + header: { text: "오수처리시설" }, + items: [ + { name: "insideGroup", header: { text: "하수처리구역 내(㎥/일)" }, items: ["wholStaaCnt", "step1StaaPrcsQnt", "step2StaaPrcsQnt", "step3StaaPrcsQnt", "step4StaaPrcsQnt", "step5StaaPrcsQnt", "step6StaaPrcsQnt", "step7StaaPrcsQnt"] }, + { name: "outsideGroup", header: { text: "하수처리구역 외(㎥/일)" }, items: ["staaExcpWhol", "step1StaaExcpPrcsQnt", "step2StaaExcpPrcsQnt", "step3StaaExcpPrcsQnt", "step4StaaExcpPrcsQnt", "step5StaaExcpPrcsQnt", "step6StaaExcpPrcsQnt", "step7StaaExcpPrcsQnt"] } + ] + } + ] +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab2Column.ts b/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab2Column.ts new file mode 100644 index 000000000..19fc4d1fb --- /dev/null +++ b/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab2Column.ts @@ -0,0 +1,72 @@ +import { ValueType } from "realgrid"; + +export const PrivateSewageTab2ColumnConfig = { + tabKey: "ST00080002", + tabLabel: "정화조현황", + rowStartNum: 4, + fixedColumns: 3, + columns: [ + { name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false }, + { name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false }, + { name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역명" }, editable: false }, + { name: "grssFcltCnt", fieldName: "grssFcltCnt", header: { text: "총 시설 수\n(A+D)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + + // 하수처리구역 내 소속 항목들 + { name: "staaInsdWhol", fieldName: "staaInsdWhol", header: { text: "총계\nA=(B+C)/2" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaInsdPrcsCpctByWhol", fieldName: "staaInsdPrcsCpctByWhol", header: { text: "계(C)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaInsdSttkNprsflCnt", fieldName: "staaInsdSttkNprsflCnt", header: { text: "자연유하" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step1StaaInsdSttkFrcCnt", fieldName: "step1StaaInsdSttkFrcCnt", header: { text: "강제펌핑식" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaInsdSprktpFltrtbCnt", fieldName: "staaInsdSprktpFltrtbCnt", header: { text: "살수여상" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaInsdAertMthdCnt", fieldName: "staaInsdAertMthdCnt", header: { text: "폭기방법" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaInsdCntcAertCnt", fieldName: "staaInsdCntcAertCnt", header: { text: "접촉폭기" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaInsdEtcCnt", fieldName: "staaInsdEtcCnt", header: { text: "기타" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step1StaaInsdNope", fieldName: "step1StaaInsdNope", header: { text: "10인조\n이하" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step2StaaInsdNope", fieldName: "step2StaaInsdNope", header: { text: "11~20" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step3StaaInsdNope", fieldName: "step3StaaInsdNope", header: { text: "21~30" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step4StaaInsdNope", fieldName: "step4StaaInsdNope", header: { text: "31~50" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step5StaaInsdNope", fieldName: "step5StaaInsdNope", header: { text: "51~199" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step6StaaInsdNope", fieldName: "step6StaaInsdNope", header: { text: "200~499" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step7StaaInsdNope", fieldName: "step7StaaInsdNope", header: { text: "500~999" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step8StaaInsdNope", fieldName: "step8StaaInsdNope", header: { text: "1,000이상" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + + // 하수처리구역 외 소속 항목들 + { name: "staaExcpWhol", fieldName: "staaExcpWhol", header: { text: "총계\nD=(E+F)/2" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaExcpPrcsCpctByWhol", fieldName: "staaExcpPrcsCpctByWhol", header: { text: "계(F)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaExcpSttkNprsflCnt", fieldName: "staaExcpSttkNprsflCnt", header: { text: "자연유하" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step1StaaExcpSttkFrcCnt", fieldName: "step1StaaExcpSttkFrcCnt", header: { text: "강제펌핑식" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaExcpSprktpFltrtbCnt", fieldName: "staaExcpSprktpFltrtbCnt", header: { text: "살수여상" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaExcpAertMthdCnt", fieldName: "staaExcpAertMthdCnt", header: { text: "폭기방법" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaExcpCntcAertCnt", fieldName: "staaExcpCntcAertCnt", header: { text: "접촉폭기" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "staaExcpEtcCnt", fieldName: "staaExcpEtcCnt", header: { text: "기타" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step1StaaExcpNope", fieldName: "step1StaaExcpNope", header: { text: "10인조\n이하" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step2StaaExcpNope", fieldName: "step2StaaExcpNope", header: { text: "11~20" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step3StaaExcpNope", fieldName: "step3StaaExcpNope", header: { text: "21~30" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step4StaaExcpNope", fieldName: "step4StaaExcpNope", header: { text: "31~50" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step5StaaExcpNope", fieldName: "step5StaaExcpNope", header: { text: "51~199" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step6StaaExcpNope", fieldName: "step6StaaExcpNope", header: { text: "200~499" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step7StaaExcpNope", fieldName: "step7StaaExcpNope", header: { text: "500~999" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "step8StaaExcpNope", fieldName: "step8StaaExcpNope", header: { text: "1,000이상" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false } + ], + columnLayout: [ + { name: "areaGroup", header: { text: "행정구역" }, items: ["ctpvNm", "sggNm", "admdstNm"] }, + "grssFcltCnt", + { + name: "insideSewerGroup", + header: { text: "하수처리구역 내" }, + items: [ + "staaInsdWhol", + { name: "insdBGroup", header: { text: "계(B)" }, items: ["staaInsdSttkNprsflCnt", "step1StaaInsdSttkFrcCnt", "staaInsdSprktpFltrtbCnt", "staaInsdAertMthdCnt", "staaInsdCntcAertCnt", "staaInsdEtcCnt"] }, + { name: "insdCGroup", header: { text: "처리용량별" }, items: ["staaInsdPrcsCpctByWhol", "step1StaaInsdNope", "step2StaaInsdNope", "step3StaaInsdNope", "step4StaaInsdNope", "step5StaaInsdNope", "step6StaaInsdNope", "step7StaaInsdNope", "step8StaaInsdNope"] } + ] + }, + { + name: "outsideSewerGroup", + header: { text: "하수처리구역 외" }, + items: [ + "staaExcpWhol", + { name: "excpEGroup", header: { text: "계(E)" }, items: ["staaExcpSttkNprsflCnt", "step1StaaExcpSttkFrcCnt", "staaExcpSprktpFltrtbCnt", "staaExcpAertMthdCnt", "staaExcpCntcAertCnt", "staaExcpEtcCnt"] }, + { name: "excpFGroup", header: { text: "처리용량별" }, items: ["staaExcpPrcsCpctByWhol", "step1StaaExcpNope", "step2StaaExcpNope", "step3StaaExcpNope", "step4StaaExcpNope", "step5StaaExcpNope", "step6StaaExcpNope", "step7StaaExcpNope", "step8StaaExcpNope"] } + ] + } + ] +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab3Column.ts b/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab3Column.ts new file mode 100644 index 000000000..98a629759 --- /dev/null +++ b/apps/st/src/components/util/column/total/sewerPrivateSewageColumn/SewerPrivateSewageTab3Column.ts @@ -0,0 +1,48 @@ +import { ValueType } from "realgrid"; + +export const PrivateSewageTab3ColumnConfig = { + tabKey: "ST00080003", // 08번 개인하수처리시설 TAB3 매핑 키 고정 + tabLabel: "개인하수도 관리지역 지정공고 현황", + rowStartNum: 3, // 3단 다단 레이아웃 스펙에 맞추어 3으로 설정합니다. + fixedColumns: 1, + columns: [ + // 행정구역 그룹 소속 (시도, 시군구, 행정구역명) + { name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false }, + { name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false }, + { name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역명" }, editable: false }, + + // 마스터 단일 컬럼 영역 (개소, 면적) + { name: "indvSwagePbancRgnCnt", fieldName: "indvSwagePbancRgnCnt", header: { text: "공고지역\n(개소)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "indvSwageDsgnScpLen", fieldName: "indvSwageDsgnScpLen", header: { text: "지정범위\n(㎢)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.00", editable: false }, + + // 정화조 그룹 소속 (개소수, 처리용량) + { name: "spctnkGrssFcltCnt", fieldName: "spctnkGrssFcltCnt", header: { text: "총시설수" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "spctnkQnt", fieldName: "spctnkQnt", header: { text: "처리용량\n(인/일)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false }, + + // 오수처리시설 그룹 소속 (개소수, 처리용량) + { name: "drtwPrcsFcltGrssFcltCnt", fieldName: "drtwPrcsFcltGrssFcltCnt", header: { text: "총시설수" }, valueType: ValueType.NUMBER, dataFormat: "#,##0", editable: false }, + { name: "drtwPrcsFcltQnt", fieldName: "drtwPrcsFcltQnt", header: { text: "처리용량\n(㎥/일)" }, valueType: ValueType.NUMBER, dataFormat: "#,##0.0", editable: false } + ], + columnLayout: [ + // 행정구역 묶음 + { name: "areaGroup", header: { text: "행정구역" }, items: ["ctpvNm", "sggNm", "admdstNm"] }, + + // 메인 마스터 지표 + "indvSwagePbancRgnCnt", + "indvSwageDsgnScpLen", + + // 정화조 다단 묶음 + { + name: "septicTankGroup", + header: { text: "정화조" }, + items: ["spctnkGrssFcltCnt", "spctnkQnt"] + }, + + // 오수처리시설 다단 묶음 + { + name: "sewageTreatmentGroup", + header: { text: "오수처리시설" }, + items: ["drtwPrcsFcltGrssFcltCnt", "drtwPrcsFcltQnt"] + } + ] +}; \ No newline at end of file diff --git a/apps/st/src/entities/statistics/model/statistics-total/statistics-private-sewage-total-interface.ts b/apps/st/src/entities/statistics/model/statistics-total/statistics-private-sewage-total-interface.ts new file mode 100644 index 000000000..43c4f4c9a --- /dev/null +++ b/apps/st/src/entities/statistics/model/statistics-total/statistics-private-sewage-total-interface.ts @@ -0,0 +1,109 @@ +/** 08. 개인하수처리시설 공통 요청 검색 파라미터 */ +export interface PrivateSewageFacilitySummaryRequest { + ctpvNm?: string; + sggNm?: string; + statsYr?: string; + swtrmtFcltNm?: string; // Controller 수신 규격 + sewerBzmnCd?: string; + rowDataYn?: boolean; + summaryYn?: boolean; + summaryYearCnt?: number; +} + +/** [Tab1] 오수처리시설 목록 항목 */ +export interface PrivateSewageTab1StatusItem { + ctpvNm: string; + sggNm: string | null; + statsYr: string; + admdstCd: string; + admdstNm: string; + sewerBzmnCd: string; + rowType: string; + wholDrtwPrcsFcltCnt: number; + // 하수처리구역 내 + wholStaaCnt: number; + step1StaaPrcsQnt: number; + step2StaaPrcsQnt: number; + step3StaaPrcsQnt: number; + step4StaaPrcsQnt: number; + step5StaaPrcsQnt: number; + step6StaaPrcsQnt: number; + step7StaaPrcsQnt: number; + // 하수처리구역 외 + staaExcpWhol: number; + step1StaaExcpPrcsQnt: number; + step2StaaExcpPrcsQnt: number; + step3StaaExcpPrcsQnt: number; + step4StaaExcpPrcsQnt: number; + step5StaaExcpPrcsQnt: number; + step6StaaExcpPrcsQnt: number; + step7StaaExcpPrcsQnt: number; +} + +/** [Tab2] 정화조 현황 목록 항목 */ +export interface PrivateSewageTab2StatusItem { + ctpvNm: string; + sggNm: string | null; + statsYr: string; + admdstCd: string; + admdstNm: string; + sewerBzmnCd: string; + rowType: string; + grssFcltCnt: number; + // 하수처리구역 내 + staaInsdWhol: number; + staaInsdSttkNprsflCnt: number; + step1StaaInsdSttkFrcCnt: number; + staaInsdSprktpFltrtbCnt: number; + staaInsdAertMthdCnt: number; + staaInsdCntcAertCnt: number; + staaInsdEtcCnt: number; + staaInsdPrcsCpctByWhol: number; + step1StaaInsdNope: number; + step2StaaInsdNope: number; + step3StaaInsdNope: number; + step4StaaInsdNope: number; + step5StaaInsdNope: number; + step6StaaInsdNope: number; + step7StaaInsdNope: number; + step8StaaInsdNope: number; + // 하수처리구역 외 + staaExcpWhol: number; + staaExcpSttkNprsflCnt: number; + step1StaaExcpSttkFrcCnt: number; + staaExcpSprktpFltrtbCnt: number; + staaExcpAertMthdCnt: number; + staaExcpCntcAertCnt: number; + staaExcpEtcCnt: number; + staaExcpPrcsCpctByWhol: number; + step1StaaExcpNope: number; + step2StaaExcpNope: number; + step3StaaExcpNope: number; + step4StaaExcpNope: number; + step5StaaExcpNope: number; + step6StaaExcpNope: number; + step7StaaExcpNope: number; + step8StaaExcpNope: number; +} + +/** [Tab3] 개인하수도 관리지역 지정공고 현황 목록 항목 */ +export interface PrivateSewageTab3StatusItem { + ctpvNm: string; + sggNm: string | null; + statsYr: string; + admdstCd: string; + admdstNm: string; + sewerBzmnCd: string; + rowType: string; + indvSwagePbancRgnCnt: number; + indvSwageDsgnScpLen: number; + spctnkGrssFcltCnt: number; + spctnkQnt: number; + drtwPrcsFcltGrssFcltCnt: number; + drtwPrcsFcltQnt: number; +} + +/** 3개 탭 개별 API 응답 규격 정의 */ +export interface PrivateSewageTab1Response { status: string; message?: string; data: PrivateSewageTab1StatusItem[]; } +export interface PrivateSewageTab2Response { status: string; message?: string; data: PrivateSewageTab2StatusItem[]; } +export interface PrivateSewageTab3Response { status: string; message?: string; data: PrivateSewageTab3StatusItem[]; } \ No newline at end of file