From ca83ac22aa9e70a7329b98cc849be4dd3893eaa7 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Mon, 16 Feb 2026 15:03:38 +0900 Subject: [PATCH 01/14] =?UTF-8?q?feat:=2002.=ED=95=98=EC=88=98=EA=B4=80?= =?UTF-8?q?=EB=A1=9C=20tab3=EA=B4=80=EC=A2=85=EB=B3=84=20=ED=98=84?= =?UTF-8?q?=ED=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/review/SewagePipeRvw.tsx | 3 + .../util/column/review/SewagePipeRvwColumn.ts | 166 +++++++++++++----- .../api/statistics-management-service.ts | 27 ++- ...statistics-sewage-pipe-review-interface.ts | 47 +++++ 4 files changed, 199 insertions(+), 44 deletions(-) diff --git a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx index 34fe00910..f8129ad85 100644 --- a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx @@ -94,9 +94,12 @@ const SewagePipeRvw = () => { if (tabKey === 'b') { response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current); + }else if(tabKey === 'c'){ + response = await statisticsManagementApi.getSewagePipeTypeList(searchParamRef.current); } if (response?.status === 'success' && response.data) { + setRowDataMap(prev => { const next = new Map(prev); next.set(tabKey, toGridRows(response.data as object[])); diff --git a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts index 7bcb3a41f..a6e3d79b4 100644 --- a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts @@ -56,7 +56,7 @@ const rawList = [ ] }, { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, editable: false }, + { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true,editable: false }, { name: 'displayYear', fieldName: 'displayYear', @@ -235,7 +235,7 @@ const rawList = [ ] }, { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '하수처리장명' }, editable: false }, + { name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '하수처리장명' },mergeCells: true, editable: false }, { name: 'displayYear', fieldName: 'displayYear', @@ -351,47 +351,133 @@ const rawList = [ 'rmk' ] }, - { - tabKey: 'c', - tabLabel: '관종별 현황', - rowStartNum: 2, - fixedColumns: 3, - columns: [ - { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, - { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, - { name: 'SWRG_PIPE_NM', fieldName: '관종', header: { text: '관종' } }, - { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { + tabKey: 'c', + tabLabel: '관종별 현황', + rowStartNum: 2, + fixedColumns: 3, + columns: [ + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const uniqueValues = new Set(); + for (let i = 0; i < dataSource.getRowCount(); i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue) uniqueValues.add(String(divisionValue)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const uniqueValues = new Set(); + for (let i = 0; i < dataSource.getRowCount(); i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue) uniqueValues.add(String(divisionValue)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true, editable: false }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const uniqueValues = new Set(); + for (let i = 0; i < dataSource.getRowCount(); i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue) uniqueValues.add(String(divisionValue)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const uniqueValues = new Set(); + for (let i = 0; i < dataSource.getRowCount(); i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue) uniqueValues.add(String(divisionValue)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } + ] + }, - { name: 'TOTAL_EXTN_SUM', fieldName: '계(총계)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'LAYING_EXTN_SUM', fieldName: '매설연장(m)_총계', header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'REMVL_EXTN_SUM', fieldName: '철거연장(m)_총계', header: { text: '철거연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + /* 총계 필드 */ + { name: 'totalExtnSum', fieldName: 'totalExtnSum', header: { text: '계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'layingExtnSum', fieldName: 'layingExtnSum', header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'remvlExtnSum', fieldName: 'remvlExtnSum', header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - ...Array.from({ length: 30 }, (_, i) => { - const yNum = (30 - i).toString().padStart(2, '0'); - const yrOffset = 29 - i; - return [ - { name: `TOTAL_EXTN_${yNum}Y`, fieldName: `계(-${yrOffset}년)`, header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: `LAYING_EXTN_${yNum}Y`, fieldName: `매설연장(m)_(-${yrOffset}년)`, header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: `REMVL_EXTN_${yNum}Y`, fieldName: `철거연장(m)_(-${yrOffset}년)`, header: { text: '철거연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' } - ]; - }).flat(), + /* 30개년 동적 컬럼 생성 (SewerPipeTypeItem 필드 매핑) */ + ...Array.from({ length: 30 }, (_, i) => { + const yNum = (30 - i).toString().padStart(2, '0'); + const yrOffset = 29 - i; + return [ + { name: `totalExtn${yNum}y`, fieldName: `totalExtn${yNum}y`, header: { text: '계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: `layingExtn${yNum}y`, fieldName: `layingExtn${yNum}y`, header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: `remvlExtn${yNum}y`, fieldName: `remvlExtn${yNum}y`, header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' } + ]; + }).flat(), - { name: 'LAYING_EXTN', fieldName: `매설연장(m)_당해년도`, header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, - ], - columnLayout: [ - { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, - 'SWRG_PIPE_NM', 'YR_GBN', - { name: 'summaryGroup', header: { text: '총계' }, items: ['TOTAL_EXTN_SUM', 'LAYING_EXTN_SUM', 'REMVL_EXTN_SUM'] }, - ...Array.from({ length: 30 }, (_, i) => { - const yNum = (30 - i).toString().padStart(2, '0'); - const yrOffset = 29 - i; - return { name: `yr${yNum}Group`, header: { text: `-${yrOffset}년` }, items: [`TOTAL_EXTN_${yNum}Y`, `LAYING_EXTN_${yNum}Y`, `REMVL_EXTN_${yNum}Y`] }; - }), - { name: 'currentYrGroup', header: { text: `${baseYear}년` }, items: ['LAYING_EXTN'] }, - 'RMK' - ] - }, + { name: 'layingExtn', fieldName: 'layingExtn', header: { text: '매설연장(m)\n(당해년도)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'areaGroup', + header: { text: '행정구역' }, + items: [ + // sido부터 swrgPipeNm(관종)까지 푸터 병합 + { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'gugun', + 'swrgPipeNm', + ] + }, + 'displayYear', + { name: 'summaryGroup', header: { text: '총계' }, items: ['totalExtnSum', 'layingExtnSum', 'remvlExtnSum'] }, + + ...Array.from({ length: 30 }, (_, i) => { + const yNum = (30 - i).toString().padStart(2, '0'); + const yrOffset = 29 - i; + return { + name: `yr${yNum}Group`, + header: { text: `-${yrOffset}년` }, + items: [`totalExtn${yNum}y`, `layingExtn${yNum}y`, `remvlExtn${yNum}y`] + }; + }), + + { name: 'currentYrGroup', header: { text: `${baseYear}년` }, items: ['layingExtn'] }, + 'rmk' + ] +}, { tabKey: 'd', tabLabel: '관경별 현황', diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index 89718aaf0..5fc81ab34 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -5,17 +5,17 @@ import { ENDPOINT } from "@/shared/config"; import { type StatsInputStatusReviewApiResponse } from "../model/statistics-input-review-interface"; -import { - type SewagePipeReviewRegionalApiResponse -} from "../model/statistics-sewage-pipe-review-interface"; import { type SewerageSupplyRateReviewRequestParams, type SewerageSupplyRateReviewApiResponse, } from "../model/statistics-sewerage-penetration-review-interface"; import { - type SewagePipeFacilityApiResponse + type SewagePipeReviewRegionalApiResponse , + type SewagePipeFacilityApiResponse, + type SewerPipeTypeApiResponse, } from "../model/statistics-sewage-pipe-review-interface"; + export class StatisticsManagementApiService { /** * 00. 통계 입력 현황 목록 조회 @@ -93,6 +93,25 @@ export class StatisticsManagementApiService { ); return response.data; } + + /** + * 02. 하수관로 관종별 시설현황 조회 (Tab2) + * @param params (sido, gugun, yr, bsnmCd) + */ + public async getSewagePipeTypeList( + params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + } + ): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe/type-status`, + { params } + ); + return response.data; + } } // 통합 인스턴스 수출 diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts index 0d82096ad..ea7500cf5 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts @@ -149,4 +149,51 @@ export interface SewagePipeFacilityService { sido?: string; // 시도 gugun?: string; // 구군 }): Promise; +} + +/** + * 02. 하수관로 관종별 시설현황 (PipeType) + * + */ +export interface SewerPipeTypeItem { + // --- SewerPipeTab3Response 기본 필드 --- + sido: string; // 시도 + gugun: string; // 시군구 + adstCd: string; // 행정코드 + swrgPipeNm: string; // 관종명 + displayYear: string; // 구분 표시용 (예: 2024년확정) + yr: string; // 연도 + rmk: string; // 비고 + yrGbn?: string; // 구분 (매설/철거 등 행 구분용 - 그리드 설정 기준) + + // --- BasePipeExtnResponse 상속 필드 --- + layingExtn: number; // 매설연장(m) - 당해년도 + + // 총계(Sum) 필드 (그리드 설정에서 사용하는 합계용 필드) + totalExtnSum?: number; + layingExtnSum?: number; + remvlExtnSum?: number; + + // 01y ~ 30y 동적 필드 처리 (Index Signature) + // 예: totalExtn01y, layingExtn05y, remvlExtn30y 등 + [key: `totalExtn${string}y`]: number | undefined; + [key: `layingExtn${string}y`]: number | undefined; + [key: `remvlExtn${string}y`]: number | undefined; +} + + +export interface SewerPipeTypeResponseData { + pipeTypeStatusList: SewerPipeTypeItem[]; +} + +export type SewerPipeTypeApiResponse = ApiResponse; + +export interface SewagePipeTypeService { + + getSewagePipeTypeList(params: { + yr?: string; // 조회 연도 + bsnmCd?: string; // 사업장 코드 + sido?: string; // 시도 + gugun?: string; // 구군 + }): Promise; } \ No newline at end of file From 37e3b6ebdb832d03f7d8feb50c42316f2de168e1 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Mon, 16 Feb 2026 16:33:25 +0900 Subject: [PATCH 02/14] =?UTF-8?q?feat:=2002.=ED=95=98=EC=88=98=EA=B4=80?= =?UTF-8?q?=EB=A1=9C=20tab4=EA=B4=80=EA=B2=BD=EB=B3=84=20=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/review/SewagePipeRvw.tsx | 2 + .../util/column/review/SewagePipeRvwColumn.ts | 155 ++++++++++++++---- .../api/statistics-management-service.ts | 22 ++- ...statistics-sewage-pipe-review-interface.ts | 46 +++++- 4 files changed, 193 insertions(+), 32 deletions(-) diff --git a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx index f8129ad85..ac7033e53 100644 --- a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx @@ -96,6 +96,8 @@ const SewagePipeRvw = () => { response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current); }else if(tabKey === 'c'){ response = await statisticsManagementApi.getSewagePipeTypeList(searchParamRef.current); + }else if(tabKey === 'd'){ + response = await statisticsManagementApi.getSewagePipeDiamList(searchParamRef.current); } if (response?.status === 'success' && response.data) { diff --git a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts index a6e3d79b4..b57a54d44 100644 --- a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts @@ -436,7 +436,6 @@ const rawList = [ { name: 'layingExtnSum', fieldName: 'layingExtnSum', header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, { name: 'remvlExtnSum', fieldName: 'remvlExtnSum', header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - /* 30개년 동적 컬럼 생성 (SewerPipeTypeItem 필드 매핑) */ ...Array.from({ length: 30 }, (_, i) => { const yNum = (30 - i).toString().padStart(2, '0'); const yrOffset = 29 - i; @@ -455,7 +454,7 @@ const rawList = [ name: 'areaGroup', header: { text: '행정구역' }, items: [ - // sido부터 swrgPipeNm(관종)까지 푸터 병합 + { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, 'gugun', 'swrgPipeNm', @@ -478,33 +477,131 @@ const rawList = [ 'rmk' ] }, - { - tabKey: 'd', - tabLabel: '관경별 현황', - rowStartNum: 2, - fixedColumns: 3, - columns: [ - { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, - { name: 'GUGUN', fieldName: '시군구', header: { text: '구군' } }, - { name: 'SWRG_PIPE_NM', fieldName: '관종', header: { text: '관종' } }, - { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, - { name: 'TOTAL_EXTN_M', fieldName: '총계(m)', header: { text: '총계(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'UNDER_200', fieldName: '200mm 미만', header: { text: '200mm 미만' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'OVER_200_UNDEV_300', fieldName: '200mm이상~300mm미만', header: { text: '200mm이상~\n300mm미만' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'OVER_300_UNDEV_500', fieldName: '300mm이상~500mm미만', header: { text: '300mm이상~\n500mm미만' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'OVER_500_UNDEV_800', fieldName: '500mm이상~800mm미만', header: { text: '500mm이상~\n800mm미만' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'OVER_800', fieldName: '800mm 이상', header: { text: '800mm 이상' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'BOX', fieldName: '사각형(m)', header: { text: '사각형(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'ETC', fieldName: '기타(측구/개거 등)', header: { text: '기타\n(측구/개거 등)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, - ], - columnLayout: [ - { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, - 'SWRG_PIPE_NM', 'YR_GBN', 'TOTAL_EXTN_M', - { name: 'circleGroup', header: { text: '원형(m)' }, items: ['UNDER_200', 'OVER_200_UNDEV_300', 'OVER_300_UNDEV_500', 'OVER_500_UNDEV_800', 'OVER_800'] }, - 'BOX', 'ETC', 'RMK', - ] - } + { + tabKey: 'd', + tabLabel: '관경별 현황', + rowStartNum: 2, + fixedColumns: 3, + columns: [ + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true, editable: false }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } + ] + }, + + { name: 'totalExtnM', fieldName: 'totalExtnM', header: { text: '총계(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'under200', fieldName: 'under200', header: { text: '200mm 미만' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'over200Undev300', fieldName: 'over200Undev300', header: { text: '200mm이상~\n300mm미만' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'over300Undev500', fieldName: 'over300Undev500', header: { text: '300mm이상~\n500mm미만' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'over500Undev500', fieldName: 'over500Undev500', header: { text: '500mm이상~\n800mm미만' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'over800', fieldName: 'over800', header: { text: '800mm 이상' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'box', fieldName: 'box', header: { text: '사각형(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'etc', fieldName: 'etc', header: { text: '기타\n(측구/개거 등)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'addrGroup', + header: { text: '행정구역' }, + items: [ + { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'gugun', + 'swrgPipeNm', + ] + }, + 'displayYear', + 'totalExtnM', + { + name: 'circleGroup', + header: { text: '원형(m)' }, + items: ['under200', 'over200Undev300', 'over300Undev500', 'over500Undev500', 'over800'] + }, + 'box', + 'etc', + 'rmk' + ] +} ]; export const SewagePipeColumnInfoListRvw = rawList.map(tab => ({ diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index 5fc81ab34..4413a8e1a 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -13,6 +13,7 @@ import { type SewagePipeReviewRegionalApiResponse , type SewagePipeFacilityApiResponse, type SewerPipeTypeApiResponse, + type SewerPipeDiamApiResponse } from "../model/statistics-sewage-pipe-review-interface"; @@ -95,7 +96,7 @@ export class StatisticsManagementApiService { } /** - * 02. 하수관로 관종별 시설현황 조회 (Tab2) + * 02. 하수관로 관종별 시설현황 조회 (Tab3) * @param params (sido, gugun, yr, bsnmCd) */ public async getSewagePipeTypeList( @@ -112,6 +113,25 @@ export class StatisticsManagementApiService { ); return response.data; } + + /** + * 02. 하수관로 관경별 시설현황 조회 (Tab 4) + * @param params (sido, gugun, yr, bsnmCd) + */ + public async getSewagePipeDiamList( + params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + } + ): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe/diam-status`, + { params } + ); + return response.data; + } } // 통합 인스턴스 수출 diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts index ea7500cf5..6abb98a80 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts @@ -82,7 +82,10 @@ export interface SewagePipeReviewService { }): Promise; } - +/** + * 02. 하수관로 시설별 시설현황 (Tab 2) + * + */ export interface SewagePipeReviewFacilityItem { // 1. 행정구역 및 기본 정보 sido: string; // 시도 @@ -152,7 +155,7 @@ export interface SewagePipeFacilityService { } /** - * 02. 하수관로 관종별 시설현황 (PipeType) + * 02. 하수관로 관종별 시설현황 (Tab 3) * */ export interface SewerPipeTypeItem { @@ -196,4 +199,43 @@ export interface SewagePipeTypeService { sido?: string; // 시도 gugun?: string; // 구군 }): Promise; +} + +/** + * 02. 하수관로 관경별 시설현황 아이템 (Tab 4) + */ +export interface SewerPipeDiamItem { + sido: string; // 시도 + gugun: string; // 시군구 + adstCd: string; // 행정코드 + swrgPipeNm: string; // 관종명 (또는 관경 관련 명칭) + displayYear: string; // 구분 (예: 2023년 확정 / 2024년) + + // 관경별 수치 데이터 + under200: number; // 200미만 + over200Undev300: number; // 200~300 + over300Undev500: number; // 300~500 + over500Undev500: number; // 500~800 (DTO 명칭 기준) + over800: number; // 800이상 + box: number; // BOX + etc: number; // 기타 + rmk: string; // 비고 +} + + +export interface SewerPipeDiamResponseData { + pipeDiamStatusList: SewerPipeDiamItem[]; +} + + +export type SewerPipeDiamApiResponse = ApiResponse; + + +export interface SewagePipeDiamService { + getSewagePipeDiamList(params: { + yr?: string; // 조회 연도 + bsnmCd?: string; // 사업장 코드 + sido?: string; // 시도 + gugun?: string; // 구군 + }): Promise; } \ No newline at end of file From 4b883a30c534f4639eda495c2446ff5a64f5e427 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Mon, 16 Feb 2026 17:47:28 +0900 Subject: [PATCH 03/14] =?UTF-8?q?feat:=2003.=ED=95=98=EC=88=98=EA=B4=80?= =?UTF-8?q?=EB=A1=9C=20=EC=9C=A0=EC=A7=80=EA=B4=80=EB=A6=AC=20tab1=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/SewagePipeMaintainRvw.tsx | 158 ++++++++++++++--- .../review/SewagePipeMaintainRvwColumn.ts | 162 ++++++++++++++---- .../api/statistics-management-service.ts | 22 +++ ...istics-sewage-pipe-mtc-review-interface.ts | 46 +++++ 4 files changed, 328 insertions(+), 60 deletions(-) create mode 100644 apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts diff --git a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx index 03549083e..8d66c5e0f 100644 --- a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx @@ -1,51 +1,159 @@ -import { useState } from "react"; - -import { TabDataGrid } from "@rsone/components"; +import { useState, useMemo, useRef } from "react"; +import TabDataGrid from "@/components/module/TabDataGrid"; import SearchForm from "@/components/module/SearchForm"; import SaveButton from "@/components/button/SaveButton"; import ApproveButton from "@/components/button/ApproveButton"; import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; import ReturnButton from "@/components/button/ReturnButton"; +import { LoadingWithAnimation } from "@common/components"; +import { useAlertStore } from "@/shared/lib"; +import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service"; import { SewagePipeMaintainColumnInfoList } from "@/components/util/column/review/SewagePipeMaintainRvwColumn"; +import type { ColumnInfoList, ColumnConfig } from "@/components/type/DataGrid.type"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import { toGridRows } from "@/components/util/grid/gridFunction"; -// 하수도 통계 관리 03. 하수관로 유지 관리 +// 하수도 통계 검토 03. 하수관로 유지 관리 const SewagePipeMaintainRvw = () => { + const { setMessage: alert } = useAlertStore((state) => state); const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const [isLoading, setIsLoading] = useState(false); + const [activeTab, setActiveTab] = useState('a'); - const approveFunc = () => { - console.log('approveFunc'); - // 승인 로직 + const searchParamRef = useRef(null); + + const columnInfo = useMemo(() => { + return SewagePipeMaintainColumnInfoList.map((tab: ColumnInfoList) => ({ + ...tab, + columns: (tab.columns ?? []).map((col: ColumnConfig) => ({ + ...col, + editable: false as const, + styleName: col.styleName ?? ("rg-cell-readonly" as const), + })), + })); + }, []); + + const handleReset = () => { + setRowDataMap(new Map()); + setActiveTab('a'); + searchParamRef.current = null; }; - const saveFunc = () => { - console.log('submit'); - // 저장 로직 + const handleSearch = async (values: SearchFormValues) => { + if (!values.sido || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + setActiveTab('a'); + setRowDataMap(new Map()); + + try { + setIsLoading(true); + + const searchParam = { + sido: values.sido, + gugun: values.gugun === 'ALL' ? '' : values.gugun, + bsnmCd: values.bsnmCd, + yr: values.year, + }; + + searchParamRef.current = searchParam; + const response = await statisticsManagementApi.getSewerPipeMtcList(searchParam); + + if (response?.status === 'success' && response.data) { + const newRowDataMap = new Map[]>(); + + // API 응답이 배열을 직접 반환하는 경우와 객체로 감싸진 경우 모두 처리 + const listData = Array.isArray(response.data) + ? response.data + : (response.data.mtcStatusList || []); + + newRowDataMap.set('a', toGridRows(listData as object[])); + setRowDataMap(newRowDataMap); + } else { + alert(response?.message || "데이터가 없습니다."); + } + } catch (error) { + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } }; - const reviewOpinionFunc = () => { - console.log('reviewOpinionFunc'); - // 검토의견 작성 - }; + const handleActiveTabChange = async (tabKey: string) => { + setActiveTab(tabKey); - const returnFunc = () => { - console.log('returnFunc'); - // 반려 + const existingAData = rowDataMap.get('a'); + const activeTabData = rowDataMap.get(tabKey); + + const hasAData = Array.isArray(existingAData) && existingAData.length > 0; + const hasActiveTabData = Array.isArray(activeTabData) && activeTabData.length > 0; + + if (hasAData && !hasActiveTabData && searchParamRef.current) { + try { + setIsLoading(true); + + let response; + + if (tabKey === 'a') { + response = await statisticsManagementApi.getSewerPipeMtcList(searchParamRef.current); + } + + if (response?.status === 'success' && response.data) { + setRowDataMap(prev => { + const next = new Map(prev); + + // API 응답이 배열을 직접 반환하는 경우와 객체로 감싸진 경우 모두 처리 + const listData = Array.isArray(response.data) + ? response.data + : (response.data.mtcStatusList || []); + + next.set(tabKey, toGridRows(listData as object[])); + return next; + }); + } else { + alert(response?.message || "데이터가 없습니다."); + } + } catch { + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } + } }; return ( - <> - +
+ +
- - - - + { }} /> + { }} /> + { }} /> + { }} />
- - + + {isLoading && ( +
+
+ +
+
+ )} + + +
); }; diff --git a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts index 28aa25ce5..b1e7b9f89 100644 --- a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts @@ -1,64 +1,156 @@ import { ValueType } from "realgrid"; +import { footerIntArrayByDivision, footerDecimal3ArrayByDivision, footerAvgDecimalArrayByDivision } from "@/components/util/grid/footerSummary"; +import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataGrid.type"; // 하수도 통계 관리 03. 하수관로 유지 관리 const rawMaintainList = [ - { + { tabKey: 'a', tabLabel: '개보수', rowStartNum: 4, fixedColumns: 2, columns: [ - /* 1. 행정 및 기본 정보 */ - { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, - { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, - { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + /* 1. 행정구역 (시도) */ + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + + /* 2. 구분 (displayYear) */ + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; + } + } + ] + }, - /* 2. 전체보수 (단위: m) */ - { name: 'RPAIR_PIPE_SM', fieldName: '계(전체보수)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RPAIR_CMBN_PIPE', fieldName: '합류식(전체보수)', header: { text: '합류식' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RPAIR_RAINWTR_PIPE', fieldName: '우수(전체보수)', header: { text: '우수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RPAIR_PLTWTR_PIPE', fieldName: '오수(전체보수)', header: { text: '오수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + /* 3. 전체보수 (m) - 소수점 1자리 합계 */ + { name: 'rpairPipeSm', fieldName: 'rpairPipeSm', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rpairCmbnPipe', fieldName: 'rpairCmbnPipe', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rpairRainwtrPipe', fieldName: 'rpairRainwtrPipe', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rpairPltwtrPipe', fieldName: 'rpairPltwtrPipe', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - /* 3. 부분보수 (단위: 개소) */ - { name: 'RPAIR_PIPE_SM2', fieldName: '계(부분보수)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RPAIR_CMBN_PIPE2', fieldName: '합류식(부분보수)', header: { text: '합류식' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RPAIR_RAINWTR_PIPE2', fieldName: '우수(부분보수)', header: { text: '우수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RPAIR_PLTWTR_PIPE2', fieldName: '오수(부분보수)', header: { text: '오수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + /* 4. 부분보수 (개소) - 정수 합계 */ + { name: 'rpairPipeSm2', fieldName: 'rpairPipeSm2', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rpairCmbnPipe2', fieldName: 'rpairCmbnPipe2', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rpairRainwtrPipe2', fieldName: 'rpairRainwtrPipe2', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rpairPltwtrPipe2', fieldName: 'rpairPltwtrPipe2', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - /* 4. 부속시설 (개소) */ - { name: 'MNHLE_SITE', fieldName: '합류식 맨홀', header: { text: '합류식\n맨홀' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PLTWTR_MNHLE_SITE', fieldName: '오수맨홀', header: { text: '오수맨홀' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'RAINWTR_MNHLE_SITE', fieldName: '우수맨홀', header: { text: '우수맨홀' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PLTWTR_RCVR_SITE', fieldName: '오수받이(개소)', header: { text: '오수받이(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'RAINWTR_RCVR_SITE', fieldName: '빗물받이(개소)', header: { text: '빗물받이(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'SOILHOLE_SITE', fieldName: '토실(개소)', header: { text: '토실(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'SOILSPLL_SITE', fieldName: '토구(개소)', header: { text: '토구(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + /* 5. 부속시설 (개소) - 정수 합계 */ + { name: 'mnhleSite', fieldName: 'mnhleSite', header: { text: '합류식\n맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrMnhleSite', fieldName: 'pltwtrMnhleSite', header: { text: '오수맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrMnhleSite', fieldName: 'rainwtrMnhleSite', header: { text: '우수맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrRcvrSite', fieldName: 'pltwtrRcvrSite', header: { text: '오수받이' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrRcvrSite', fieldName: 'rainwtrRcvrSite', header: { text: '빗물받이' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'soilspllSite', fieldName: 'soilspllSite', header: { text: '토실' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'soilholeSite', fieldName: 'soilholeSite', header: { text: '토구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - /* 5. 조사량 및 비고 */ - { name: 'CCTV', fieldName: '수밀검사·CCTV조사량(m)', header: { text: '수밀검사·\nCCTV조사량\n(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + /* 6. 조사량 및 비고 */ + { name: 'cctv', fieldName: 'cctv', header: { text: '수밀검사·\nCCTV조사량\n(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, ], columnLayout: [ - { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, - 'YR_GBN', + { + name: 'addrGroup', + header: { text: '행정구역' }, + items: [ + { column: 'sido', footerUserSpans: [{ colspan: 3 }, { colspan: 3 }] }, + 'gugun' + ] + }, + 'displayYear', { name: 'mtcPipeGroup', header: { text: '개·보수관로' }, items: [ { name: 'totalRepairGroup', header: { text: '전체보수(m)' }, - items: ['RPAIR_PIPE_SM', 'RPAIR_CMBN_PIPE', { name: 'sepTotalGroup', header: { text: '분류식' }, items: ['RPAIR_RAINWTR_PIPE', 'RPAIR_PLTWTR_PIPE'] }] + items: ['rpairPipeSm', 'rpairCmbnPipe', { name: 'sepTotalGroup', header: { text: '분류식' }, items: ['rpairRainwtrPipe', 'rpairPltwtrPipe'] }] }, { name: 'partRepairGroup', header: { text: '부분보수(개소)' }, - items: ['RPAIR_PIPE_SM2', 'RPAIR_CMBN_PIPE2', { name: 'sepPartGroup', header: { text: '분류식' }, items: ['RPAIR_RAINWTR_PIPE2', 'RPAIR_PLTWTR_PIPE2'] }] + items: ['rpairPipeSm2', 'rpairCmbnPipe2', { name: 'sepPartGroup', header: { text: '분류식' }, items: ['rpairRainwtrPipe2', 'rpairPltwtrPipe2'] }] } ] }, - 'MNHLE_SITE', - { name: 'sepMnhleGroup', header: { text: '분류식' }, items: ['PLTWTR_MNHLE_SITE', 'RAINWTR_MNHLE_SITE'] }, - 'PLTWTR_RCVR_SITE', 'RAINWTR_RCVR_SITE', - { name: 'soilGroup', header: { text: '토실·토구(개소)' }, items: ['SOILHOLE_SITE', 'SOILSPLL_SITE'] }, - 'CCTV', 'RMK' + 'mnhleSite', + { name: 'sepMnhleGroup', header: { text: '분류식' }, items: ['pltwtrMnhleSite', 'rainwtrMnhleSite'] }, + 'pltwtrRcvrSite', 'rainwtrRcvrSite', + { name: 'soilGroup', header: { text: '토실·토구(개소)' }, items: ['soilspllSite', 'soilholeSite'] }, + 'cctv', 'rmk' ] }, { diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index 4413a8e1a..30ff9fb98 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -15,6 +15,9 @@ import { type SewerPipeTypeApiResponse, type SewerPipeDiamApiResponse } from "../model/statistics-sewage-pipe-review-interface"; +import { + type SewerPipeMtcApiResponse +} from "../model/statistics-sewage-pipe-mtc-review-interface"; export class StatisticsManagementApiService { @@ -132,6 +135,25 @@ export class StatisticsManagementApiService { ); return response.data; } + + /** + * 03. 하수관로 유지관리 개보수 현황 조회 + * @param params (yr, bsnmCd, sido, gugun) + */ +public async getSewerPipeMtcList( + params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + } +): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe-mtc/repair`, + { params } + ); + return response.data; +} } // 통합 인스턴스 수출 diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts new file mode 100644 index 000000000..5bab50b28 --- /dev/null +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts @@ -0,0 +1,46 @@ +import type { ApiResponse } from "./statistics-interface"; + +/** + * 03. 하수관로 유지관리 개보수 아이템 + */ +export interface SewerPipeMtcItem { + // 1. 행정구역 및 기본정보 + sido: string; // 시도 + gugun: string; // 시군구 + adstCd: string; // 행정코드 + adstDong?: string; // 행정동 + yr: string; // 실제 연도 + displayYear: string; // 화면 표시용 (예: 2023년확정) + rowType: 'OLD' | 'CURR'; // OLD / CURR 구분 + + // 2. 개보수 관로 - 전체보수(m) + rpairPipeSm: number; // 계 + rpairCmbnPipe: number; // 합류식 + rpairRainwtrPipe: number; // 분류식-우수 + rpairPltwtrPipe: number; // 분류식-오수 + + // 3. 개보수 관로 - 부분보수(개소) + rpairPipeSm2: number; // 계 + rpairCmbnPipe2: number; // 합류식 + rpairRainwtrPipe2: number; // 분류식-우수 + rpairPltwtrPipe2: number; // 분류식-오수 + + // 4. 부속 시설물 (개소/m) + mnhleSite: number; // 합류식 맨홀 + pltwtrMnhleSite: number; // 오수 맨홀 (분류식) + rainwtrMnhleSite: number; // 우수 맨홀 (분류식) + pltwtrRcvrSite: number; // 오수받이 + rainwtrRcvrSite: number; // 빗물받이 + soilspllSite: number; // 토실 + soilholeSite: number; // 토구 + cctv: number; // CCTV 조사량 (m) + + // 5. 기타 및 상태값 + rmk: string; // 비고 +} + +export interface SewerPipeMtcResponseData { + mtcStatusList: SewerPipeMtcItem[]; +} + +export type SewerPipeMtcApiResponse = ApiResponse; \ No newline at end of file From be21ea3e8a087c1cd700353cb1e87ed64a2b7637 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Mon, 16 Feb 2026 17:58:41 +0900 Subject: [PATCH 04/14] =?UTF-8?q?feat:=2003.=ED=95=98=EC=88=98=EA=B4=80?= =?UTF-8?q?=EB=A1=9C=20=EC=9C=A0=EC=A7=80=EA=B4=80=EB=A6=AC=20tab2?= =?UTF-8?q?=EA=B4=80=EB=A1=9C=EC=A4=80=EC=84=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/SewagePipeMaintainRvw.tsx | 2 + .../review/SewagePipeMaintainRvwColumn.ts | 187 ++++++++++++------ .../api/statistics-management-service.ts | 22 ++- ...istics-sewage-pipe-mtc-review-interface.ts | 55 +++++- 4 files changed, 204 insertions(+), 62 deletions(-) diff --git a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx index 8d66c5e0f..f2da6cce4 100644 --- a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx @@ -99,6 +99,8 @@ const SewagePipeMaintainRvw = () => { if (tabKey === 'a') { response = await statisticsManagementApi.getSewerPipeMtcList(searchParamRef.current); + }else if (tabKey === 'b') { + response = await statisticsManagementApi.getSewerPipeDrdgList(searchParamRef.current); } if (response?.status === 'success' && response.data) { diff --git a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts index b1e7b9f89..ab32f39a5 100644 --- a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts @@ -153,71 +153,138 @@ const rawMaintainList = [ 'cctv', 'rmk' ] }, - { - tabKey: 'b', - tabLabel: '관로준설', - rowStartNum: 4, - fixedColumns: 2, - columns: [ - /* 1. 행정 및 기본 정보 */ - { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, - { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, - { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, - - /* 2. 시설 기본 정보 */ - { name: 'PIPL_FCLTY_EXTN', fieldName: '하수관로 총시설연장(m)', header: { text: '하수관로\n총시설연장\n(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { + tabKey: 'b', + tabLabel: '관로준설', + rowStartNum: 4, + fixedColumns: 2, + columns: [ + /* 1. 행정 및 기본 정보 */ + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue) uniqueValues.add(String(divisionValue)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue) uniqueValues.add(String(divisionValue)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView) => { + const uniqueValues = new Set(); + for (let i = 0; i < grid.getDataSource().getRowCount(); i++) { + const val = grid.getDataSource().getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > 0 ? divisionValues[0] + ' 합계' : ''; + } + }, + { + valueCallback: (grid: GridView) => { + const uniqueValues = new Set(); + for (let i = 0; i < grid.getDataSource().getRowCount(); i++) { + const val = grid.getDataSource().getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > 1 ? divisionValues[1] + ' 합계' : ''; + } + } + ] + }, + + /* 2. 시설 기본 정보 */ + { name: 'piplFcltyExtn', fieldName: 'piplFcltyExtn', header: { text: '하수관로\n총시설연장\n(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - /* 3. 준설연장 및 개소수 */ - { name: 'DRDG_PIPE_SM', fieldName: '합계(준설)', header: { text: '합계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'DRDG_CMBN_PIPE', fieldName: '합류식(준설)', header: { text: '합류식' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'DRDG_RAINWTR_PIPE', fieldName: '우수(준설)', header: { text: '우수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'DRDG_PLTWTR_PIPE', fieldName: '오수(준설)', header: { text: '오수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'MNHLE_SITE_DRDG', fieldName: '맨홀(개소)', header: { text: '맨홀\n(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PLTWTR_RCVR_SITE_DRDG', fieldName: '오·우수받이(개소)', header: { text: '오·우수받이\n(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'SOILSPLL_SOILHOLE_SITE', fieldName: '토실·토구(개소)', header: { text: '토실·토구\n(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + /* 3. 준설연장 및 개소수 */ + { name: 'drdgPipeSm', fieldName: 'drdgPipeSm', header: { text: '합계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drdgCmbnPipe', fieldName: 'drdgCmbnPipe', header: { text: '합류식' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drdgRainwtrPipe', fieldName: 'drdgRainwtrPipe', header: { text: '우수' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drdgPltwtrPipe', fieldName: 'drdgPltwtrPipe', header: { text: '오수' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'mnhleSite', fieldName: 'mnhleSite', header: { text: '맨홀\n(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrRcvrSite', fieldName: 'pltwtrRcvrSite', header: { text: '오·우수받이\n(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'soilspllSoilholeSite', fieldName: 'soilspllSoilholeSite', header: { text: '토실·토구\n(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - /* 4. 준설 계획 및 율 */ - { name: 'DRDG_TRGET_EXTN', fieldName: '준설 계획 연장(m)', header: { text: '준설 계획\n연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'DRDG_TRGET_RT', fieldName: '계획대비 준설율(%)', header: { text: '계획대비\n준설율\n(%)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PIPL_FCLTY_RT', fieldName: '준설계획 연장대비 준설율(%)', header: { text: '준설계획\n연장대비\n준설율(%)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + /* 4. 준설 계획 및 율 */ + { name: 'drdgTrgetExtn', fieldName: 'drdgTrgetExtn', header: { text: '준설 계획\n연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drdgTrgetRt', fieldName: 'drdgTrgetRt', header: { text: '계획대비\n준설율\n(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'piplFcltyRt', fieldName: 'piplFcltyRt', header: { text: '준설계획\n연장대비\n준설율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - /* 5. 준설실적 */ - { name: 'DRDG_ACMSLT_AMOUNT', fieldName: '금액(백만원)', header: { text: '금액\n(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'DRDG_ACMSLT_QY', fieldName: '준설량(㎥)', header: { text: '준설량\n(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + /* 5. 준설실적 */ + { name: 'drdgAcmsltAmount', fieldName: 'drdgAcmsltAmount', header: { text: '금액\n(백만원)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'drdgAcmsltQy', fieldName: 'drdgAcmsltQy', header: { text: '준설량\n(㎥)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - /* 6. 준설토사처리 */ - { name: 'DRDG_ACMSLT_UNTPC', fieldName: '준설토 처리비(백만원)', header: { text: '준설토\n처리비\n(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'DRDG_ETND_SM', fieldName: '처리량 계(톤)', header: { text: '처리량 계\n(톤)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RCLM', fieldName: '매립', header: { text: '매립' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'OCEAN_DPSL', fieldName: '해양투기', header: { text: '해양투기' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RUSE', fieldName: '재활용', header: { text: '재활용' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'ETC', fieldName: '기타(준설)', header: { text: '기타\n(소각, 고형화,\n시멘트원료 등)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + /* 6. 준설토사처리 */ + { name: 'drdgAcmsltUntpc', fieldName: 'drdgAcmsltUntpc', header: { text: '준설토\n처리비\n(백만원)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'drdgEtndSm', fieldName: 'drdgEtndSm', header: { text: '처리량 계\n(톤)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rclm', fieldName: 'rclm', header: { text: '매립' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'oceanDpsl', fieldName: 'oceanDpsl', header: { text: '해양투기' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ruse', fieldName: 'ruse', header: { text: '재활용' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'etc', fieldName: 'etc', header: { text: '기타' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - /* 7. 기타 및 의견 */ - { name: 'RMK_DRDG', fieldName: '비고(준설)', header: { text: '비고' } }, - ], - columnLayout: [ - { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, - 'YR_GBN', 'PIPL_FCLTY_EXTN', - { - name: 'drdgGroup', header: { text: '준설연장 및 개소수' }, - items: [ - { - name: 'pipeLenGroup', header: { text: '관로(m)' }, - items: ['DRDG_PIPE_SM', 'DRDG_CMBN_PIPE', { name: 'sepRepairGroup', header: { text: '분류식' }, items: ['DRDG_RAINWTR_PIPE', 'DRDG_PLTWTR_PIPE'] }] - }, - 'MNHLE_SITE_DRDG', 'PLTWTR_RCVR_SITE_DRDG', 'SOILSPLL_SOILHOLE_SITE' - ] - }, - 'DRDG_TRGET_EXTN', 'DRDG_TRGET_RT', 'PIPL_FCLTY_RT', - { name: 'acmsltGroup', header: { text: '준설실적' }, items: ['DRDG_ACMSLT_AMOUNT', 'DRDG_ACMSLT_QY'] }, - { - name: 'processGroup', header: { text: '준설토사처리' }, - items: ['DRDG_ACMSLT_UNTPC', 'DRDG_ETND_SM', 'RCLM', 'OCEAN_DPSL', 'RUSE', 'ETC'] - }, - 'RMK_DRDG' - ] - } + /* 7. 기타 및 의견 */ + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: [{ column: 'sido', footerUserSpans: [{ colspan: 3 }, { colspan: 3 }] }, 'gugun'] }, + 'displayYear', 'piplFcltyExtn', + { + name: 'drdgGroup', header: { text: '준설연장 및 개소수' }, + items: [ + { + name: 'pipeLenGroup', header: { text: '관로(m)' }, + items: ['drdgPipeSm', 'drdgCmbnPipe', { name: 'sepRepairGroup', header: { text: '분류식' }, items: ['drdgRainwtrPipe', 'drdgPltwtrPipe'] }] + }, + 'mnhleSite', 'pltwtrRcvrSite', 'soilspllSoilholeSite' + ] + }, + 'drdgTrgetExtn', 'drdgTrgetRt', 'piplFcltyRt', + { name: 'acmsltGroup', header: { text: '준설실적' }, items: ['drdgAcmsltAmount', 'drdgAcmsltQy'] }, + { + name: 'processGroup', header: { text: '준설토사처리' }, + items: ['drdgAcmsltUntpc', 'drdgEtndSm', 'rclm', 'oceanDpsl', 'ruse', 'etc'] + }, + 'rmk' + ] +} ]; export const SewagePipeMaintainColumnInfoList = rawMaintainList.map(tab => ({ diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index 30ff9fb98..4702636a8 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -16,7 +16,8 @@ import { type SewerPipeDiamApiResponse } from "../model/statistics-sewage-pipe-review-interface"; import { - type SewerPipeMtcApiResponse + type SewerPipeMtcApiResponse, + type SewerPipeDrdgApiResponse } from "../model/statistics-sewage-pipe-mtc-review-interface"; @@ -154,6 +155,25 @@ public async getSewerPipeMtcList( ); return response.data; } + +/** + * 03. 하수관로 유지관리 관로준설 현황 조회 (Tab B) + * @param params (yr, bsnmCd, sido, gugun) + */ +public async getSewerPipeDrdgList( + params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + } +): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe-mtc/dredging`, + { params } + ); + return response.data; +} } // 통합 인스턴스 수출 diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts index 5bab50b28..eb47c2de7 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts @@ -43,4 +43,57 @@ export interface SewerPipeMtcResponseData { mtcStatusList: SewerPipeMtcItem[]; } -export type SewerPipeMtcApiResponse = ApiResponse; \ No newline at end of file +export type SewerPipeMtcApiResponse = ApiResponse; + +/** + * 03. 하수관로 유지관리 관로준설 아이템 (Tab 2) + */ +export interface SewerPipeDrdgItem { + // 1. 기본 정보 + sido: string; // 시도 + gugun: string; // 시군구 + yr: string; // 연도 + displayYear: string; // 화면 표시용 (예: 2024년, 2023년확정) + rowType: 'OLD' | 'CURR'; // OLD / CURR 구분 + bsnmCd: string; // 사업소코드 + + // 2. 시설 현황 + piplFcltyExtn: number; // 관로연장 (m) + + // 3. 준설 실적 - 관로 (m) + drdgPipeSm: number; // 준설계 + drdgCmbnPipe: number; // 합류식 + drdgPltwtrPipe: number; // 분류식-오수 + drdgRainwtrPipe: number; // 분류식-우수 + + // 4. 준설 실적 - 부속시설 (개소) + mnhleSite: number; // 맨홀 + pltwtrRcvrSite: number; // 오수받이 + soilspllSoilholeSite: number; // 토실/토구 + + // 5. 준설 효율 및 성과 + drdgTrgetExtn: number; // 준설대상 연장 (m) + drdgTrgetRt: number; // 준설대상 대비 준설률 (%) + piplFcltyRt: number; // 시설연장 대비 준설률 (%) + drdgAcmsltQy: number; // 준설실적 - 양 (m3) + drdgAcmsltAmount: number; // 준설실적 - 금액 (천원) + drdgAcmsltUntpc: number; // 준설실적 - 단가 (원/m3) + + // 6. 준설토 처리 (톤) + drdgEtndSm: number; // 처리량 계 + rclm: number; // 매립 + oceanDpsl: number; // 해양투기 + ruse: number; // 재활용 + etc: number; // 기타 + + // 7. 기타 및 상태값 + rmk: string; // 비고 +} + + +export interface SewerPipeDrdgResponseData { + drdgStatusList: SewerPipeDrdgItem[]; +} + + +export type SewerPipeDrdgApiResponse = ApiResponse; \ No newline at end of file From 842ec36c322736295a7efb89f709fa1a65a1cb09 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Thu, 19 Feb 2026 15:41:19 +0900 Subject: [PATCH 05/14] =?UTF-8?q?feat:=20=ED=95=98=EC=88=98=20=EC=A0=80?= =?UTF-8?q?=EB=A5=98=EC=8B=9C=EC=84=A4=20=EB=B0=8F=20=EB=B9=97=EB=AC=BC=20?= =?UTF-8?q?=ED=8E=8C=ED=94=84=EC=9E=A5=20=EC=A1=B0=ED=9A=8C=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/SewageReservoirPumpRvw.tsx | 153 +++++- .../review/SewageReservoirPumpRvwColumn.ts | 448 ++++++++++++------ .../api/statistics-management-service.ts | 43 ++ .../sewage-reservoir-pump-review-interface.ts | 171 +++++++ 4 files changed, 640 insertions(+), 175 deletions(-) create mode 100644 apps/st/src/entities/statistics/model/sewage-reservoir-pump-review-interface.ts diff --git a/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx b/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx index a2b5e8de7..3b7645a4e 100644 --- a/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx +++ b/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx @@ -1,52 +1,153 @@ -import { useState } from "react"; - -import { TabDataGrid } from "@rsone/components"; +import { useState, useMemo, useRef } from "react"; +import TabDataGrid from "@/components/module/TabDataGrid"; import SearchForm from "@/components/module/SearchForm"; import SaveButton from "@/components/button/SaveButton"; import ApproveButton from "@/components/button/ApproveButton"; import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; import ReturnButton from "@/components/button/ReturnButton"; +import { LoadingWithAnimation } from "@common/components"; +import { useAlertStore } from "@/shared/lib"; +import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service"; import { SewageReservoirPumpInfoListRvw } from "@/components/util/column/review/SewageReservoirPumpRvwColumn"; +import type { ColumnInfoList, ColumnConfig } from "@/components/type/DataGrid.type"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import { toGridRows } from "@/components/util/grid/gridFunction"; -// 하수도 통계 관리 04. 하수저류 시설 및 빗물 펌프장 +/** + * 하수도 통계 검토 04. 하수저류 시설 및 빗물 펌프장 + * Tab A: 하수저류시설 + * Tab B: 빗물펌프장 + */ const SewageReservoirPumpRvw = () => { + const { setMessage: alert } = useAlertStore((state) => state); const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const [isLoading, setIsLoading] = useState(false); + const [activeTab, setActiveTab] = useState('a'); - const approveFunc = () => { - console.log('approveFunc'); - // 승인 로직 + const searchParamRef = useRef(null); + + const columnInfo = useMemo(() => { + return SewageReservoirPumpInfoListRvw.map((tab: ColumnInfoList) => ({ + ...tab, + columns: (tab.columns ?? []).map((col: ColumnConfig) => ({ + ...col, + editable: false as const, + styleName: col.styleName ?? ("rg-cell-readonly" as const), + })), + })); + }, []); + + const handleReset = () => { + setRowDataMap(new Map()); + setActiveTab('a'); + searchParamRef.current = null; }; - const saveFunc = () => { - console.log('submit'); - // 저장 로직 + // 조회 버튼 클릭 시: Tab A(하수저류시설) 데이터 로드 + const handleSearch = async (values: SearchFormValues) => { + if (!values.sido || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + setActiveTab('a'); + setRowDataMap(new Map()); + + try { + setIsLoading(true); + + const searchParam = { + sido: values.sido, + gugun: values.gugun === 'ALL' ? '' : values.gugun, + bsnmCd: values.bsnmCd, + yr: values.year, + }; + + searchParamRef.current = searchParam; + + //하수저류시설 (Tab A) + const response = await statisticsManagementApi.getSewerReservoirList(searchParam); + + if (response?.status === 'success' && response.data) { + const newRowDataMap = new Map[]>(); + newRowDataMap.set('a', toGridRows(response.data as object[])); + setRowDataMap(newRowDataMap); + } else { + alert(response?.message || "데이터가 없습니다."); + } + } catch (error) { + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } }; - const reviewOpinionFunc = () => { - console.log('reviewOpinionFunc'); - // 검토의견 작성 - }; + // 탭 전환 시: 데이터가 없는 경우 지연 로딩 (Tab B: 빗물펌프장) + const handleActiveTabChange = async (tabKey: string) => { + setActiveTab(tabKey); - const returnFunc = () => { - console.log('returnFunc'); - // 반려 + const activeTabData = rowDataMap.get(tabKey); + const hasActiveTabData = Array.isArray(activeTabData) && activeTabData.length > 0; + + // 메인 데이터(Tab A)가 있고, 현재 탭 데이터가 없을 때만 API 호출 + if (searchParamRef.current && !hasActiveTabData) { + try { + setIsLoading(true); + let response; + + if (tabKey === 'b') { + response = await statisticsManagementApi.getPumpStationList(searchParamRef.current); + } + + if (response?.status === 'success' && response.data) { + setRowDataMap(prev => { + const next = new Map(prev); + next.set(tabKey, toGridRows(response.data as object[])); + return next; + }); + } else if (response) { + alert(response?.message || "데이터가 없습니다."); + } + } catch { + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } + } }; return ( - <> - +
+ +
- - - - + { /* 검토의견 로직 */ }} /> + { /* 승인 로직 */ }} /> + { /* 반려 로직 */ }} /> + { /* 저장 로직 */ }} />
- - + + {isLoading && ( +
+
+ +
+
+ )} + + +
); }; -export default SewageReservoirPumpRvw; +export default SewageReservoirPumpRvw; \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts index 43aa1c62d..b5caf5604 100644 --- a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts @@ -1,186 +1,336 @@ import { ValueType } from "realgrid"; +import { + footerIntArrayByDivision, + footerDecimal1ArrayByDivision, + footerDecimal3ArrayByDivision +} from "@/components/util/grid/footerSummary"; +import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataGrid.type"; + // 하수도 통계 관리 04. 하수저류 시설 및 빗물 펌프장 const rawReservoirList = [ { tabKey: 'a', - tabLabel: '하수저류시설', + tabLabel: '하수저류시설현황', rowStartNum: 3, fixedColumns: 2, columns: [ /* 1. 기본 정보 */ - { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, - { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, - { name: 'SWGE_STRGE_NM', fieldName: '시설명', header: { text: '시설명' } }, - { name: 'ADDR', fieldName: '위치', header: { text: '위치' } }, - { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, - - /* 2. 시설 제원 */ - { name: 'RN_DT', fieldName: '가동개시 년월일', header: { text: '가동개시\n년월일' } }, - { name: 'PL_DSGN_FRQNC', fieldName: '계획설계빈도', header: { text: '계획설계빈도' } }, - { name: 'INS_PER1', fieldName: '침수예방', header: { text: '침수예방' } }, - { name: 'INS_PER2', fieldName: '수질오염저감', header: { text: '수질오염저감' } }, - { name: 'INS_PER3', fieldName: '하수 재이용 용도', header: { text: '하수\n재이용\n용도' } }, - { name: 'FAC_RES', fieldName: '시설구조', header: { text: '시설구조(일반지하식,지하터널식,기타)' } }, - { name: 'DGR_AR', fieldName: '집수구역면적(㎢)', header: { text: '집수구역면적(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, - { name: 'SWGE_SGBS_CPCTY', fieldName: '시설용량(㎥)', header: { text: '시설용량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - - /* 3. 펌프시설 */ - { name: 'TOT_CPCTY', fieldName: '총양수량(㎥/min)', header: { text: '총양수량\n(㎥/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_CALBR', fieldName: '구경(mm)_1', header: { text: '구경(mm)' } }, - { name: 'WP_CPCTY', fieldName: '대당 양수량_1', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_CO', fieldName: '펌프대수_1', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_PREPAR_CO', fieldName: '예비펌프대수_1', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_CALBR2', fieldName: '구경(mm)_2', header: { text: '구경(mm)' } }, - { name: 'WP_CPCTY2', fieldName: '대당 양수량_2', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_CO2', fieldName: '펌프대수_2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_PREPAR_CO2', fieldName: '예비펌프대수_2', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_CALBR3', fieldName: '구경(mm)_3', header: { text: '구경(mm)' } }, - { name: 'WP_CPCTY3', fieldName: '대당 양수량_3', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_CO3', fieldName: '펌프대수_3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_PREPAR_CO3', fieldName: '예비펌프대수_3', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - - /* 4. 부대시설 및 방식 */ - { name: 'FRE_FNNC', fieldName: '전처리시설(유/무)', header: { text: '전처리시설(유/무)' } }, - { name: 'DORZEQP_FNNC', fieldName: '탈취설비(유/무)', header: { text: '탈취설비(유/무)' } }, - { name: 'SELF_ETRQ_FNNC', fieldName: '자가발전(유/무)', header: { text: '자가발전(유/무)' } }, - { name: 'DRA_MTH', fieldName: '배수방식(자연배수,강제배수)', header: { text: '배수방식(자연배수,강제배수)' } }, - { name: 'ELEC_MTH', fieldName: '저류방식(직렬,병렬)', header: { text: '저류방식(직렬,병렬)' } }, - { name: 'ELEC_PRO_MAT', fieldName: '저류수 처리방법', header: { text: '저류수\n처리방법' } }, - { name: 'DIS_WAT', fieldName: '방류수역(또는 연계처리장명)', header: { text: '방류수역(또는 연계처리장명)' } }, - - /* 5. 최종처분량 및 방법 */ - { name: 'SDMT_TRE_CPCTY', fieldName: '침사(량)', header: { text: '침사' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'IPRT_TRE_CPCTY', fieldName: '협잡물(량)', header: { text: '협잡물' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'SDMT_TRE_MTH', fieldName: '침사(방법)', header: { text: '침사' } }, - { name: 'IPRT_TRE_MTH', fieldName: '협잡물(방법)', header: { text: '협잡물' } }, - - /* 6. 운영실적 */ - { name: 'YRSTP_RN_DYN', fieldName: '가동일수', header: { text: '가동일수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'DSPLCMNT_AMNT', fieldName: '총배수량(㎥/년)', header: { text: '총배수량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, - ], - columnLayout: [ - { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, - 'SWGE_STRGE_NM', 'ADDR', 'YR_GBN', 'RN_DT', 'PL_DSGN_FRQNC', { - name: 'purposeGroup', - header: { text: '설치목적(O,X로 표기, 중복체크 가능)' }, - items: ['INS_PER1', 'INS_PER2', 'INS_PER3'] - }, - 'FAC_RES', 'DGR_AR', 'SWGE_SGBS_CPCTY', - { - name: 'pumpMainGroup', - header: { text: '펌프시설' }, - items: [ - 'TOT_CPCTY', - { name: 'p1Group', header: { text: '펌프시설1' }, items: ['PUMP_CALBR', 'WP_CPCTY', 'PUMP_CO', 'PUMP_PREPAR_CO'] }, - { name: 'p2Group', header: { text: '펌프시설2' }, items: ['PUMP_CALBR2', 'WP_CPCTY2', 'PUMP_CO2', 'PUMP_PREPAR_CO2'] }, - { name: 'p3Group', header: { text: '펌프시설3' }, items: ['PUMP_CALBR3', 'WP_CPCTY3', 'PUMP_CO3', 'PUMP_PREPAR_CO3'] } + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; + return '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; + return '합계'; + } + } ] }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'swgeStrgeNm', fieldName: 'swgeStrgeNm', header: { text: '시설명' }, mergeCells: true, editable: false }, + { name: 'addr', fieldName: 'addr', header: { text: '위치' }, mergeCells: true, editable: false }, { - name: 'subFacGroup', - header: { text: '부대시설' }, - items: ['FRE_FNNC', 'DORZEQP_FNNC', 'SELF_ETRQ_FNNC'] + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } + ] }, - 'DRA_MTH', 'ELEC_MTH', 'ELEC_PRO_MAT', 'DIS_WAT', + + /* 2. 시설 제원 */ + { name: 'rnDt', fieldName: 'rnDt', header: { text: '가동개시 년월일' } }, + { name: 'plDsgnFrqnc', fieldName: 'plDsgnFrqnc', header: { text: '계획설계빈도' } }, + { name: 'insPer1', fieldName: 'insPer1', header: { text: '침수예방' } }, + { name: 'insPer2', fieldName: 'insPer2', header: { text: '수질오염저감' } }, + { name: 'insPer3', fieldName: 'insPer3', header: { text: '하수 재이용 용도' } }, + { name: 'facRes', fieldName: 'facRes', header: { text: '시설구조' } }, + { name: 'dgrAr', fieldName: 'dgrAr', header: { text: '집수구역면적(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000', footer: footerDecimal3ArrayByDivision }, + { name: 'swgeSgbsCpcty', fieldName: 'swgeSgbsCpcty', header: { text: '시설용량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + + /* 3. 펌프시설 */ + { name: 'totCpcty', fieldName: 'totCpcty', header: { text: '총양수량(㎥/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpCalbr', fieldName: 'pumpCalbr', header: { text: '구경(mm)' } }, + { name: 'wpCpcty', fieldName: 'wpCpcty', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpCo', fieldName: 'pumpCo', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpPreparCo', fieldName: 'pumpPreparCo', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpCalbr2', fieldName: 'pumpCalbr2', header: { text: '구경(mm)' } }, + { name: 'wpCpcty2', fieldName: 'wpCpcty2', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpCo2', fieldName: 'pumpCo2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpPreparCo2', fieldName: 'pumpPreparCo2', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpCalbr3', fieldName: 'pumpCalbr3', header: { text: '구경(mm)' } }, + { name: 'wpCpcty3', fieldName: 'wpCpcty3', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpCo3', fieldName: 'pumpCo3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpPreparCo3', fieldName: 'pumpPreparCo3', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + + /* 4. 부대시설 및 방식 */ + { name: 'freFnnc', fieldName: 'freFnnc', header: { text: '전처리시설(유/무)' } }, + { name: 'dorzeqpFnnc', fieldName: 'dorzeqpFnnc', header: { text: '탈취설비(유/무)' } }, + { name: 'selfEtrqFnnc', fieldName: 'selfEtrqFnnc', header: { text: '자가발전(유/무)' } }, + { name: 'draMth', fieldName: 'draMth', header: { text: '배수방식' } }, + { name: 'elecMth', fieldName: 'elecMth', header: { text: '저류방식' } }, + { name: 'elecProMat', fieldName: 'elecProMat', header: { text: '저류수 처리방법' } }, + { name: 'disWat', fieldName: 'disWat', header: { text: '방류수역' } }, + + /* 5. 최종처분량 및 방법 */ + { name: 'sdmtTreCpcty', fieldName: 'sdmtTreCpcty', header: { text: '침사' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'iprtTreCpcty', fieldName: 'iprtTreCpcty', header: { text: '협잡물' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'sdmtTreMth', fieldName: 'sdmtTreMth', header: { text: '침사' } }, + { name: 'iprtTreMth', fieldName: 'iprtTreMth', header: { text: '협잡물' } }, + + /* 6. 운영실적 */ + { name: 'yrstpRnDyn', fieldName: 'yrstpRnDyn', header: { text: '가동일수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'dsplcmntAmnt', fieldName: 'dsplcmntAmnt', header: { text: '총배수량(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + ], + columnLayout: [ { - name: 'disposalAmtGroup', - header: { text: '최종처분량(ton/년)' }, - items: ['SDMT_TRE_CPCTY', 'IPRT_TRE_CPCTY'] + name: 'areaGroup', header: { text: '행정구역' }, items: [ + { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'gugun', 'swgeStrgeNm', 'addr' + ] }, + 'displayYear', 'rnDt', 'plDsgnFrqnc', + { name: 'purposeGroup', header: { text: '설치목적' }, items: ['insPer1', 'insPer2', 'insPer3'] }, + 'facRes', 'dgrAr', 'swgeSgbsCpcty', { - name: 'disposalMthGroup', - header: { text: '최종처분방법' }, - items: ['SDMT_TRE_MTH', 'IPRT_TRE_MTH'] + name: 'pumpMainGroup', header: { text: '펌프시설' }, + items: [ + 'totCpcty', + { name: 'p1Group', header: { text: '펌프시설1' }, items: ['pumpCalbr', 'wpCpcty', 'pumpCo', 'pumpPreparCo'] }, + { name: 'p2Group', header: { text: '펌프시설2' }, items: ['pumpCalbr2', 'wpCpcty2', 'pumpCo2', 'pumpPreparCo2'] }, + { name: 'p3Group', header: { text: '펌프시설3' }, items: ['pumpCalbr3', 'wpCpcty3', 'pumpCo3', 'pumpPreparCo3'] } + ] }, - { - name: 'opGroup', - header: { text: '운영실적' }, - items: ['YRSTP_RN_DYN', 'DSPLCMNT_AMNT'] - }, - 'RMK' + { name: 'subFacGroup', header: { text: '부대시설' }, items: ['freFnnc', 'dorzeqpFnnc', 'selfEtrqFnnc'] }, + 'draMth', 'elecMth', 'elecProMat', 'disWat', + { name: 'disposalAmtGroup', header: { text: '최종처분량(ton/년)' }, items: ['sdmtTreCpcty', 'iprtTreCpcty'] }, + { name: 'disposalMthGroup', header: { text: '최종처분방법' }, items: ['sdmtTreMth', 'iprtTreMth'] }, + { name: 'opGroup', header: { text: '운영실적' }, items: ['yrstpRnDyn', 'dsplcmntAmnt'] }, + 'rmk' ] }, - { +{ tabKey: 'b', tabLabel: '빗물펌프장', rowStartNum: 3, fixedColumns: 2, columns: [ /* 1. 기본 정보 */ - { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, - { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, - { name: 'SWGE_STRGE_NM', fieldName: '시설명', header: { text: '시설명' } }, - { name: 'ADDR', fieldName: '위치', header: { text: '위치' } }, - { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, - - /* 2. 시설 제원 */ - { name: 'FCT_KND', fieldName: '시설물종류', header: { text: '시설물종류' } }, - { name: 'RN_DT', fieldName: '가동개시 년월일', header: { text: '가동개시\n년월일' } }, - { name: 'PL_DSGN_FRQNC', fieldName: '계획설계빈도', header: { text: '계획설계빈도' } }, - { name: 'DGR_AR', fieldName: '집수구역면적(㎢)', header: { text: '집수구역면적(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, - - /* 3. 유수지 및 흡수정 */ - { name: 'REV_FNNC', fieldName: '유수지유무(유,무)', header: { text: '유수지유무\n(유,무)' } }, - { name: 'REV_CPCTY', fieldName: '저류량(유수지)', header: { text: '저류량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'ABS_CPCTY', fieldName: '저류량(흡수정)', header: { text: '저류량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'SWGE_SGBS_CPCTY', fieldName: '시설용량(㎥)', header: { text: '시설용량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - - /* 4. 펌프시설 */ - { name: 'TOT_CPCTY', fieldName: '총양수량(㎥/min)', header: { text: '총양수량\n(㎥/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_CALBR', fieldName: '구경(mm)_1', header: { text: '구경(mm)' } }, - { name: 'WP_CPCTY', fieldName: '대당 양수량_1', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_CO', fieldName: '펌프대수_1', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_PREPAR_CO', fieldName: '예비펌프대수_1', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_CALBR2', fieldName: '구경(mm)_2', header: { text: '구경(mm)' } }, - { name: 'WP_CPCTY2', fieldName: '대당 양수량_2', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_CO2', fieldName: '펌프대수_2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_PREPAR_CO2', fieldName: '예비펌프대수_2', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_CALBR3', fieldName: '구경(mm)_3', header: { text: '구경(mm)' } }, - { name: 'WP_CPCTY3', fieldName: '대당 양수량_3', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_CO3', fieldName: '펌프대수_3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_PREPAR_CO3', fieldName: '예비펌프대수_3', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - - /* 5. 부대시설 및 기타 */ - { name: 'FRE_FNNC', fieldName: '전처리시설', header: { text: '전처리시설' } }, - { name: 'DORZEQP_FNNC', fieldName: '탈취설비', header: { text: '탈취설비' } }, - { name: 'SELF_ETRQ_FNNC', fieldName: '자가발전', header: { text: '자가발전' } }, - { name: 'DIS_WAT', fieldName: '방류수역', header: { text: '방류수역' } }, - - /* 6. 최종처분량 및 방법 */ - { name: 'SDMT_TRE_CPCTY', fieldName: '침사(량)', header: { text: '침사(량)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'IPRT_TRE_CPCTY', fieldName: '협잡물(량)', header: { text: '협잡물(량)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'SDMT_TRE_MTH', fieldName: '침사(방법)', header: { text: '침사(방법)' } }, - { name: 'IPRT_TRE_MTH', fieldName: '협잡물(방법)', header: { text: '협잡물(방법)' } }, - - /* 7. 운영실적 */ - { name: 'YRSTP_RN_DYN', fieldName: '가동일수', header: { text: '가동일수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'DSPLCMNT_AMNT', fieldName: '총배수량(㎥/년)', header: { text: '총배수량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; + return '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; + return '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'swgeStrgeNm', fieldName: 'swgeStrgeNm', header: { text: '시설명' }, mergeCells: true, editable: false }, + { name: 'addr', fieldName: 'addr', header: { text: '위치' }, mergeCells: true, editable: false }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } + ] + }, + { name: 'fctKnd', fieldName: 'fctKnd', header: { text: '시설물종류' } }, + { name: 'rnDt', fieldName: 'rnDt', header: { text: '가동개시 년월일' } }, + { name: 'plDsgnFrqnc', fieldName: 'plDsgnFrqnc', header: { text: '계획설계빈도' } }, + { name: 'dgrAr', fieldName: 'dgrAr', header: { text: '집수구역면적(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000', footer: footerDecimal3ArrayByDivision }, + { name: 'revFnnc', fieldName: 'revFnnc', header: { text: '유수지유무\n(유,무)' } }, + { name: 'revCpcty', fieldName: 'revCpcty', header: { text: '저류량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'absCpcty', fieldName: 'absCpcty', header: { text: '저류량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'swgeSgbsCpcty', fieldName: 'swgeSgbsCpcty', header: { text: '시설용량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'totCpcty', fieldName: 'totCpcty', header: { text: '총양수량(㎥/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpCalbr', fieldName: 'pumpCalbr', header: { text: '구경(mm)' } }, + { name: 'wpCpcty', fieldName: 'wpCpcty', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpCo', fieldName: 'pumpCo', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpPreparCo', fieldName: 'pumpPreparCo', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpCalbr2', fieldName: 'pumpCalbr2', header: { text: '구경(mm)' } }, + { name: 'wpCpcty2', fieldName: 'wpCpcty2', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpCo2', fieldName: 'pumpCo2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpPreparCo2', fieldName: 'pumpPreparCo2', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpCalbr3', fieldName: 'pumpCalbr3', header: { text: '구경(mm)' } }, + { name: 'wpCpcty3', fieldName: 'wpCpcty3', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpCo3', fieldName: 'pumpCo3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpPreparCo3', fieldName: 'pumpPreparCo3', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'freFnnc', fieldName: 'freFnnc', header: { text: '전처리시설' } }, + { name: 'dorzeqpFnnc', fieldName: 'dorzeqpFnnc', header: { text: '탈취설비' } }, + { name: 'selfEtrqFnnc', fieldName: 'selfEtrqFnnc', header: { text: '자가발전' } }, + { name: 'disWat', fieldName: 'disWat', header: { text: '방류수역' } }, + { name: 'sdmtTreCpcty', fieldName: 'sdmtTreCpcty', header: { text: '침사(량)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'iprtTreCpcty', fieldName: 'iprtTreCpcty', header: { text: '협잡물(량)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'sdmtTreMth', fieldName: 'sdmtTreMth', header: { text: '침사(방법)' } }, + { name: 'iprtTreMth', fieldName: 'iprtTreMth', header: { text: '협잡물(방법)' } }, + { name: 'yrstpRnDyn', fieldName: 'yrstpRnDyn', header: { text: '가동일수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'dsplcmntAmnt', fieldName: 'dsplcmntAmnt', header: { text: '총배수량(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, ], columnLayout: [ - { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, - 'SWGE_STRGE_NM', 'ADDR', 'YR_GBN', 'FCT_KND', 'RN_DT', 'PL_DSGN_FRQNC', 'DGR_AR', - { name: 'revGroup', header: { text: '유수지' }, items: ['REV_FNNC', 'REV_CPCTY'] }, - { name: 'absGroup', header: { text: '흡수정' }, items: ['ABS_CPCTY'] }, - 'SWGE_SGBS_CPCTY', + { + name: 'areaGroup', header: { text: '행정구역' }, items: [ + { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'gugun', 'swgeStrgeNm', 'addr' + ] + }, + 'displayYear', 'fctKnd', 'rnDt', 'plDsgnFrqnc', 'dgrAr', + { name: 'revGroup', header: { text: '유수지' }, items: ['revFnnc', 'revCpcty'] }, + { name: 'absGroup', header: { text: '흡수정' }, items: ['absCpcty'] }, + 'swgeSgbsCpcty', { name: 'pumpMainGroup', header: { text: '펌프시설' }, items: [ - 'TOT_CPCTY', - { name: 'p1Group', header: { text: '펌프시설1' }, items: ['PUMP_CALBR', 'WP_CPCTY', 'PUMP_CO', 'PUMP_PREPAR_CO'] }, - { name: 'p2Group', header: { text: '펌프시설2' }, items: ['PUMP_CALBR2', 'WP_CPCTY2', 'PUMP_CO2', 'PUMP_PREPAR_CO2'] }, - { name: 'p3Group', header: { text: '펌프시설3' }, items: ['PUMP_CALBR3', 'WP_CPCTY3', 'PUMP_CO3', 'PUMP_PREPAR_CO3'] } + 'totCpcty', + { name: 'p1Group', header: { text: '펌프시설1' }, items: ['pumpCalbr', 'wpCpcty', 'pumpCo', 'pumpPreparCo'] }, + { name: 'p2Group', header: { text: '펌프시설2' }, items: ['pumpCalbr2', 'wpCpcty2', 'pumpCo2', 'pumpPreparCo2'] }, + { name: 'p3Group', header: { text: '펌프시설3' }, items: ['pumpCalbr3', 'wpCpcty3', 'pumpCo3', 'pumpPreparCo3'] } ] }, - { name: 'subFacGroup', header: { text: '부대시설' }, items: ['FRE_FNNC', 'DORZEQP_FNNC', 'SELF_ETRQ_FNNC'] }, - 'DIS_WAT', - { name: 'disposalAmtGroup', header: { text: '최종처분량(ton/년)' }, items: ['SDMT_TRE_CPCTY', 'IPRT_TRE_CPCTY'] }, - { name: 'disposalMthGroup', header: { text: '최종처분방법' }, items: ['SDMT_TRE_MTH', 'IPRT_TRE_MTH'] }, - { name: 'opGroup', header: { text: '운영실적' }, items: ['YRSTP_RN_DYN', 'DSPLCMNT_AMNT'] }, - 'RMK' + { name: 'subFacGroup', header: { text: '부대시설' }, items: ['freFnnc', 'dorzeqpFnnc', 'selfEtrqFnnc'] }, + 'disWat', + { name: 'disposalAmtGroup', header: { text: '최종처분량(ton/년)' }, items: ['sdmtTreCpcty', 'iprtTreCpcty'] }, + { name: 'disposalMthGroup', header: { text: '최종처분방법' }, items: ['sdmtTreMth', 'iprtTreMth'] }, + { name: 'opGroup', header: { text: '운영실적' }, items: ['yrstpRnDyn', 'dsplcmntAmnt'] }, + 'rmk' ] } ]; diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index 4702636a8..20e3b532f 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -19,6 +19,11 @@ import { type SewerPipeMtcApiResponse, type SewerPipeDrdgApiResponse } from "../model/statistics-sewage-pipe-mtc-review-interface"; +import { + type SewerReservoirRegionalApiResponse, + type PumpingStationRegionalApiResponse +} from "../model/sewage-reservoir-pump-review-interface"; + export class StatisticsManagementApiService { @@ -174,6 +179,44 @@ public async getSewerPipeDrdgList( ); return response.data; } + +/** + * 04. 하수저류시설 tab1. 시설현황 조회 + * @param params (yr, bsnmCd, sido, gugun) + */ +public async getSewerReservoirList( + params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + } +): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-reservoir/facilities`, + { params } + ); + return response.data; +} + +/** + * 04. 빗물펌프장 tab2. 조회 + * @param params (yr, bsnmCd, sido, gugun) + */ +public async getPumpStationList( + params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + } +): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-reservoir/pumping-stations`, + { params } + ); + return response.data; +} } // 통합 인스턴스 수출 diff --git a/apps/st/src/entities/statistics/model/sewage-reservoir-pump-review-interface.ts b/apps/st/src/entities/statistics/model/sewage-reservoir-pump-review-interface.ts new file mode 100644 index 000000000..4f7b6bf7f --- /dev/null +++ b/apps/st/src/entities/statistics/model/sewage-reservoir-pump-review-interface.ts @@ -0,0 +1,171 @@ + +import type { ApiResponse } from "./statistics-interface"; + +/** + * 04. 하수저류시설 tab1. 시설현황 아이템 인터페이스 (Tab1) + */ +export interface SewerReservoirRegionalItem { +// 1. 기본 정보 및 행 제어 + sido: string; // 시도 + gugun: string; // 시군구 + adstCd: string; // 행정코드 + swgeStrgeNm: string; // 시설명 + addr: string; // 위치(주소) + yr: string; // 연도 + rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 + displayYear: string; // 구분 표시용 (2024년, 2023년확정 등) + + // 2. 시설 제원 + rnDt: string; // 가동개시일 (yyyyMMdd) + plDsgnFrqnc: string; // 계획설계빈도 + insPer1: string; // 설치목적: 침수예방 + insPer2: string; // 설치목적: 수질오염저감 + insPer3: string; // 설치목적: 하수재이용 + facRes: string; // 시설구조 + dgrAr: number; // 집수구역면적 + swgeSgbsCpcty: number; // 시설용량 + totCpcty: number; // 총양수량 + + // 3. 펌프시설 상세 (1호기) + pumpCalbr: string; // 구경 + wpCpcty: number; // 대당 양수량 + pumpCo: number; // 펌프대수 + pumpPreparCo: number; // 예비펌프대수 + + // 4. 펌프시설 상세 (2호기) - 추가 + pumpCalbr2: string; // 구경2 + wpCpcty2: number; // 대당 양수량2 + pumpCo2: number; // 펌프대수2 + pumpPreparCo2: number; // 예비펌프대수2 + + // 5. 펌프시설 상세 (3호기) - 추가 + pumpCalbr3: string; // 구경3 + wpCpcty3: number; // 대당 양수량3 + pumpCo3: number; // 펌프대수3 + pumpPreparCo3: number; // 예비펌프대수3 + + // 6. 부대시설 및 방식 - 추가 + freFnnc: string; // 전처리시설유무 + dorzeqpFnnc: string; // 탈취설비유무 + selfEtrqFnnc: string; // 자가발전유무 + draMth: string; // 배수방식 + elecMth: string; // 저류방식 + elecProMat: string; // 저류수 처리방법 + disWat: string; // 방류수역 + + // 7. 최종처분량 및 방법 - 추가 + sdmtTreCpcty: number; // 침사량 + iprtTreCpcty: number; // 협잡물량 + sdmtTreMth: string; // 침사 처분방법 + iprtTreMth: string; // 협잡물 처분방법 + + // 8. 운영 실적 + yrstpRnDyn: number; // 가동일수 + dsplcmntAmnt: number; // 총배수량 + rmk: string; // 비고 + + // 9. 상태 체크용 (그리드 배경색 제어용) - 추가 + lcnt: number; // 신규 여부 (1/0) + ocnt: number; // 기존 여부 (1/0) +} + +/** + * 하수저류시설 응답 데이터 구조 + */ +export interface SewerReservoirResponseData { + reservoirList: SewerReservoirRegionalItem[]; +} + +/** + * 하수저류시설 서비스 인터페이스 + */ +export interface SewerReservoirService { + /** + * 하수저류시설 리스트 조회 (Tab1) + */ + getSewerReservoirList(params: { + yr?: string; // 조회 연도 + bsnmCd?: string; // 사업장 코드 + sido?: string; // 시도 + gugun?: string; // 구군 + }): Promise; +} + +/** + * 04. 빗물펌프장 tab2. 시설현황 아이템 인터페이스 (Tab2) + */ +export interface PumpingStationRegionalItem { + // --- 기본 정보 --- + sido: string; // 시도 + gugun: string; // 시군구 + adstCd: string; // 행정코드 + swgeStrgeNm: string; // 시설명 + addr: string; // 위치 + yr: string; // 연도 + rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 + displayYear: string; // 구분 표시용 + + // --- 시설 제원 --- + fctKnd: string; // 시설물종류 + rnDt: string; // 가동개시일 + plDsgnFrqnc: string; // 계획설계빈도 + dgrAr: number; // 집수구역면적 + revFnnc: string; // 유수지유무 + revCpcty: number; // 유수지저류량 + absCpcty: number; // 흡수정저류량 + swgeSgbsCpcty: number; // 시설용량 + totCpcty: number; // 총양수량 + + // --- 펌프시설 상세 (1, 2, 3호기) --- + pumpCalbr: string; wpCpcty: number; pumpCo: number; pumpPreparCo: number; + pumpCalbr2: string; wpCpcty2: number; pumpCo2: number; pumpPreparCo2: number; + pumpCalbr3: string; wpCpcty3: number; pumpCo3: number; pumpPreparCo3: number; + + // --- 부대시설 및 방식 --- + freFnnc: string; // 전처리시설유무 + dorzeqpFnnc: string; // 탈취설비유무 + selfEtrqFnnc: string; // 자가발전유무 + disWat: string; // 방류수역 + + // --- 최종처분량 및 방법 --- + sdmtTreCpcty: number; // 침사 처분량 + iprtTreCpcty: number; // 협잡물 처분량 + sdmtTreMth: string; // 침사 처분방법 + iprtTreMth: string; // 협잡물 처분방법 + + // --- 운영실적 --- + yrstpRnDyn: number; // 가동일수 + dsplcmntAmnt: number; // 총배수량 + rmk: string; // 비고 +} + +/** + * 응답 타입 정의 + */ +export type SewerReservoirRegionalApiResponse = ApiResponse; +export type PumpingStationRegionalApiResponse = ApiResponse; + +/** + * 하수저류시설 및 빗물펌프장 서비스 인터페이스 + */ +export interface SewerReservoirService { + /** + * 하수저류시설 리스트 조회 (Tab1) + */ + getSewerReservoirList(params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + }): Promise; + + /** + * 빗물펌프장 리스트 조회 (Tab2) + */ + getPumpStationList(params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + }): Promise; +} \ No newline at end of file From b6a75f6ee02899b5cd2846b5280c81d03df14f98 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Fri, 20 Feb 2026 14:02:27 +0900 Subject: [PATCH 06/14] =?UTF-8?q?feat:=2005.=ED=8E=8C=ED=94=84=EC=9E=A5=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/review/PumpingStationRvw.tsx | 98 +++++++-- .../column/review/PumpingStationRvwColumn.ts | 206 +++++++++++++----- .../api/statistics-management-service.ts | 24 +- ...istics-pumping-station-review-interface.ts | 86 ++++++++ 4 files changed, 343 insertions(+), 71 deletions(-) create mode 100644 apps/st/src/entities/statistics/model/statistics-pumping-station-review-interface.ts diff --git a/apps/st/src/components/statistics/review/PumpingStationRvw.tsx b/apps/st/src/components/statistics/review/PumpingStationRvw.tsx index 8a9df541a..b1a1d6f9d 100644 --- a/apps/st/src/components/statistics/review/PumpingStationRvw.tsx +++ b/apps/st/src/components/statistics/review/PumpingStationRvw.tsx @@ -1,26 +1,82 @@ -import { useState } from "react"; - -import { DataGrid } from "@rsone/components"; +import { useState, useMemo } from "react"; +import DataGrid from "@/components/module/DataGrid"; import SearchForm from "@/components/module/SearchForm"; import SaveButton from "@/components/button/SaveButton"; import ApproveButton from "@/components/button/ApproveButton"; import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; import ReturnButton from "@/components/button/ReturnButton"; +import { LoadingWithAnimation } from "@common/components"; +import { useAlertStore } from "@/shared/lib"; import { PumpingStationInfoList } from "@/components/util/column/review/PumpingStationRvwColumn"; +import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import { toGridRows } from "@/components/util/grid/gridFunction"; -// 하수도 통계 관리 05.펌프장 +// 하수도 통계 검토 05.중계펌프장 const PumpingStationRvw = () => { - const [rowData, setRowData] = useState[]>([]); + const { setMessage: alert } = useAlertStore((state) => state); + const [rowData, setRowData] = useState([]); + const [isLoading, setIsLoading] = useState(false); - const approveFunc = () => { console.log('approveFunc'); }; - const saveFunc = () => { console.log('submit'); }; - const reviewOpinionFunc = () => { console.log('reviewOpinionFunc'); }; - const returnFunc = () => { console.log('returnFunc'); }; + const columnInfo = useMemo(() => { + const { columns, columnLayout, fixedColumns, rowStartNum } = PumpingStationInfoList; + return { + columnLayout, + fixedColumns, + rowStartNum, + columns: columns.map((col) => ({ + ...col, + editable: false as const, // 검토 화면이므로 읽기 전용 + styleName: col.styleName ?? ("rg-cell-readonly" as const), + })), + }; + }, []); + + const handleReset = () => { + setRowData([]); + }; + + const handleSearch = async (values: SearchFormValues) => { + if (values.sido === '' || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + try { + setIsLoading(true); + + const response = await statisticsManagementApi.getMediationPumpStationList({ + sido: values.sido, + gugun: values.gugun === 'ALL' ? '' : values.gugun, + bsnmCd: values.bsnmCd, + yr: values.year, + bscFctNm: values.fctName, // 시설명 검색 + }); + + if (response.status === 'success' && response.data) { + setRowData(toGridRows(response.data)); + } else { + setRowData([]); + alert(response.message || "데이터가 없습니다."); + } + } catch (error) { + console.error("중계펌프장 조회 중 에러 발생:", error); + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } + }; + + const approveFunc = () => console.log('approveFunc'); + const saveFunc = () => console.log('submit'); + const reviewOpinionFunc = () => console.log('reviewOpinionFunc'); + const returnFunc = () => console.log('returnFunc'); return ( - <> - +
+ +
@@ -29,8 +85,24 @@ const PumpingStationRvw = () => {
- - + + {isLoading && ( +
+
+ +
+
+ )} + + +
); }; diff --git a/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts b/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts index 058eb39e3..7ab5e8e59 100644 --- a/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts +++ b/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts @@ -1,106 +1,198 @@ import { ValueType } from "realgrid"; +import { footerIntArrayByDivision, footerDecimal3ArrayByDivision, footerAvgDecimalArrayByDivision } from "@/components/util/grid/footerSummary"; +import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataGrid.type"; -// 하수도 통계 관리 05.펌프장 export const rawPumpingStationInfoList = { columns: [ /* 1. 행정구역 및 기본정보 */ - { name: 'sido', fieldName: '시도', header: { text: '시도' } }, - { name: 'sgg', fieldName: '구군', header: { text: '구군' } }, - { name: 'PUMP_NM', fieldName: '펌프장명', header: { text: '펌프장명' } }, - { name: 'GBN', fieldName: '구분', header: { text: '구분' } }, - { name: 'TRT_FCT_NM', fieldName: '처리장명', header: { text: '처리장명' } }, - { name: 'TYPE_GBN', fieldName: '구분(합류식분류식)', header: { text: '구분(합류식분류식)' } }, - { name: 'ADDR', fieldName: '위치', header: { text: '위치' } }, - { name: 'RN_DT', fieldName: '가동년월일 yyyy-mm-dd', header: { text: '가동년월일\nyyyy-mm-dd' } }, - { name: 'DSN_AR', fieldName: '계획배수면적(km2)', header: { text: '계획배수면적\n(km2)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + }, + { + valueCallback: (grid: GridView) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'pumpNm', fieldName: 'pumpNm', header: { text: '펌프장명' }, mergeCells: true, editable: false, sortdisable: true }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const uniqueValues = new Set(); + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + }, + { + valueCallback: (grid: GridView) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const uniqueValues = new Set(); + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } + ] + }, + { name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '처리장명' } }, + { name: 'pumpCls', fieldName: 'pumpCls', header: { text: '구분\n(합류/분류)' } }, + { name: 'addr', fieldName: 'addr', header: { text: '위치' }, styleName: 'rg-cell-left' }, + { name: 'rnDt', fieldName: 'rnDt', header: { text: '가동년월일\nyyyy-mm-dd' } }, + { + name: 'planDrhgAr', fieldName: 'planDrhgAr', header: { text: '계획배수면적\n(km2)' }, + footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' + }, /* 2. 계획배수량 (m3/hr) */ - { name: 'DSN_QTY_A', fieldName: '청천시(A)', header: { text: '청천시(A)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'DSN_QTY_B', fieldName: '우천시(B)', header: { text: '우천시(B)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'DSN_QTY_DIFF', fieldName: '우수량(B-A)', header: { text: '우수량(B-A)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'finewtDrngVl', fieldName: 'finewtDrngVl', header: { text: '청천시(A)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rainwtDrngVl', fieldName: 'rainwtDrngVl', header: { text: '우천시(B)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'vlWtr', fieldName: 'vlWtr', header: { text: '우수량(B-A)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, /* 3. 총 양수량 (m3/min) */ - { name: 'TOT_PUMP_QTY_O', fieldName: '오수펌프 총양수량', header: { text: '오수펌프\n총양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'TOT_PUMP_QTY_W', fieldName: '우수펌프 총양수량', header: { text: '우수펌프\n총양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'pltwtrTotCpcty', fieldName: 'pltwtrTotCpcty', header: { text: '오수펌프\n총양수량' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rainwtrTotCpcty', fieldName: 'rainwtrTotCpcty', header: { text: '우수펌프\n총양수량' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, /* 4. 오수펌프 상세 (1, 2, 3) */ - { name: 'PUMP_O1_D', fieldName: '구경(mm)_오수1', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_O1_Q', fieldName: '양수량(m3/min)_오수1', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_O1_C', fieldName: '펌프대수_오수1', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_O1_S', fieldName: '예비대수_오수1', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrPumpCalbr1', fieldName: 'pltwtrPumpCalbr1', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'pltwtrPumpCpcty1', fieldName: 'pltwtrPumpCpcty1', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'pltwtrPumpCnt1', fieldName: 'pltwtrPumpCnt1', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrPumpPreparCnt1', fieldName: 'pltwtrPumpPreparCnt1', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + { name: 'pltwtrPumpCalbr2', fieldName: 'pltwtrPumpCalbr2', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'pltwtrPumpCpcty2', fieldName: 'pltwtrPumpCpcty2', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'pltwtrPumpCnt2', fieldName: 'pltwtrPumpCnt2', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrPumpPreparCnt2', fieldName: 'pltwtrPumpPreparCnt2', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_O2_D', fieldName: '구경(mm)_오수2', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_O2_Q', fieldName: '양수량(m3/min)_오수2', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_O2_C', fieldName: '펌프대수_오수2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_O2_S', fieldName: '예비대수_오수2', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - - { name: 'PUMP_O3_D', fieldName: '구경(mm)_오수3', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_O3_Q', fieldName: '양수량(m3/min)_오수3', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_O3_C', fieldName: '펌프대수_오수3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_O3_S', fieldName: '예비대수_오수3', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrPumpCalbr3', fieldName: 'pltwtrPumpCalbr3', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'pltwtrPumpCpcty3', fieldName: 'pltwtrPumpCpcty3', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'pltwtrPumpCnt3', fieldName: 'pltwtrPumpCnt3', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrPumpPreparCnt3', fieldName: 'pltwtrPumpPreparCnt3', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, /* 5. 우수펌프 상세 (1, 2, 3) */ - { name: 'PUMP_W1_D', fieldName: '구경(mm)_우수1', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_W1_Q', fieldName: '양수량(m3/min)_우수1', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_W1_C', fieldName: '펌프대수_우수1', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_W1_S', fieldName: '예비대수_우수1', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrPumpCalbr1', fieldName: 'rainwtrPumpCalbr1', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rainwtrPumpCpcty1', fieldName: 'rainwtrPumpCpcty1', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rainwtrPumpCnt1', fieldName: 'rainwtrPumpCnt1', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrPumpPreparCnt1', fieldName: 'rainwtrPumpPreparCnt1', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_W2_D', fieldName: '구경(mm)_우수2', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_W2_Q', fieldName: '양수량(m3/min)_우수2', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_W2_C', fieldName: '펌프대수_우수2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_W2_S', fieldName: '예비대수_우수2', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrPumpCalbr2', fieldName: 'rainwtrPumpCalbr2', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rainwtrPumpCpcty2', fieldName: 'rainwtrPumpCpcty2', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rainwtrPumpCnt2', fieldName: 'rainwtrPumpCnt2', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrPumpPreparCnt2', fieldName: 'rainwtrPumpPreparCnt2', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_W3_D', fieldName: '구경(mm)_우수3', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_W3_Q', fieldName: '양수량(m3/min)_우수3', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'PUMP_W3_C', fieldName: '펌프대수_우수3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'PUMP_W3_S', fieldName: '예비대수_우수3', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrPumpCalbr3', fieldName: 'rainwtrPumpCalbr3', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rainwtrPumpCpcty3', fieldName: 'rainwtrPumpCpcty3', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rainwtrPumpCnt3', fieldName: 'rainwtrPumpCnt3', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrPumpPreparCnt3', fieldName: 'rainwtrPumpPreparCnt3', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - /* 6. 운영 정보 */ - { name: 'PWR_USAGE', fieldName: '연간전력사용량(kWh/년)', header: { text: '연간전력사용량\n(kWh/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + /* 6. 기타 및 운영 */ + { name: 'elcpwAmnt', fieldName: 'elcpwAmnt', header: { text: '연간전력사용량\n(kWh/년)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, ], columnLayout: [ - { name: 'groupA', header: { text: '행정구역' }, items: ['sido', 'sgg'] }, - 'PUMP_NM', 'GBN', 'TRT_FCT_NM', 'TYPE_GBN', 'ADDR', 'RN_DT', 'DSN_AR', + { + name: 'groupA', + header: { text: '행정구역' }, + items: [ + { column: 'sido', footerUserSpans: [{ colspan: 3 }, { colspan: 3 }] }, + 'gugun', + 'pumpNm', + ] + }, + 'displayYear', + 'bscFctNm', + 'pumpCls', + 'addr', + 'rnDt', + 'planDrhgAr', { name: 'groupB', header: { text: '계획시간대최대배수량(m3/hr)' }, - items: ['DSN_QTY_A', 'DSN_QTY_B', 'DSN_QTY_DIFF'], + items: ['finewtDrngVl', 'rainwtDrngVl', 'vlWtr'], }, { name: 'groupC', header: { text: '배수능력' }, items: [ - 'TOT_PUMP_QTY_O', + 'pltwtrTotCpcty', { name: 'pumpO_Detail', header: { text: '오수펌프 상세' }, items: [ - { name: 'O1', header: { text: '오수펌프(1)' }, items: ['PUMP_O1_D', 'PUMP_O1_Q', 'PUMP_O1_C', 'PUMP_O1_S'] }, - { name: 'O2', header: { text: '오수펌프(2)' }, items: ['PUMP_O2_D', 'PUMP_O2_Q', 'PUMP_O2_C', 'PUMP_O2_S'] }, - { name: 'O3', header: { text: '오수펌프(3)' }, items: ['PUMP_O3_D', 'PUMP_O3_Q', 'PUMP_O3_C', 'PUMP_O3_S'] } + { name: 'O1', header: { text: '오수펌프(1)' }, items: ['pltwtrPumpCalbr1', 'pltwtrPumpCpcty1', 'pltwtrPumpCnt1', 'pltwtrPumpPreparCnt1'] }, + { name: 'O2', header: { text: '오수펌프(2)' }, items: ['pltwtrPumpCalbr2', 'pltwtrPumpCpcty2', 'pltwtrPumpCnt2', 'pltwtrPumpPreparCnt2'] }, + { name: 'O3', header: { text: '오수펌프(3)' }, items: ['pltwtrPumpCalbr3', 'pltwtrPumpCpcty3', 'pltwtrPumpCnt3', 'pltwtrPumpPreparCnt3'] } ] }, - 'TOT_PUMP_QTY_W', + 'rainwtrTotCpcty', { name: 'pumpW_Detail', header: { text: '우수펌프 상세' }, items: [ - { name: 'W1', header: { text: '우수펌프(1)' }, items: ['PUMP_W1_D', 'PUMP_W1_Q', 'PUMP_W1_C', 'PUMP_W1_S'] }, - { name: 'W2', header: { text: '우수펌프(2)' }, items: ['PUMP_W2_D', 'PUMP_W2_Q', 'PUMP_W2_C', 'PUMP_W2_S'] }, - { name: 'W3', header: { text: '우수펌프(3)' }, items: ['PUMP_W3_D', 'PUMP_W3_Q', 'PUMP_W3_C', 'PUMP_W3_S'] } + { name: 'W1', header: { text: '우수펌프(1)' }, items: ['rainwtrPumpCalbr1', 'rainwtrPumpCpcty1', 'rainwtrPumpCnt1', 'rainwtrPumpPreparCnt1'] }, + { name: 'W2', header: { text: '우수펌프(2)' }, items: ['rainwtrPumpCalbr2', 'rainwtrPumpCpcty2', 'rainwtrPumpCnt2', 'rainwtrPumpPreparCnt2'] }, + { name: 'W3', header: { text: '우수펌프(3)' }, items: ['rainwtrPumpCalbr3', 'rainwtrPumpCpcty3', 'rainwtrPumpCnt3', 'rainwtrPumpPreparCnt3'] } ] } ], }, - 'PWR_USAGE', 'RMK', - ] + 'elcpwAmnt', + 'rmk', + ], + fixedColumns: 2, + rowStartNum: 3 }; export const PumpingStationInfoList = { ...rawPumpingStationInfoList, columns: rawPumpingStationInfoList.columns.map(col => ({ ...col, - editable: false + editable: false, + styleName: col.styleName ?? "rg-cell-readonly" })) }; \ No newline at end of file diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index 20e3b532f..9fae80f45 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -23,7 +23,9 @@ import { type SewerReservoirRegionalApiResponse, type PumpingStationRegionalApiResponse } from "../model/sewage-reservoir-pump-review-interface"; - +import { + type MediationPumpStationApiResponse, +} from "../model/statistics-pumping-station-review-interface"; export class StatisticsManagementApiService { @@ -217,6 +219,26 @@ public async getPumpStationList( ); return response.data; } + +/** + * 05. 중계펌프장 통계관리 조회 + * @param params (yr, bsnmCd, sido, gugun, bscFctNm) + */ +public async getMediationPumpStationList( + params: { + yr?: string; // 조회 연도 + bsnmCd?: string; // 사업소 코드 + sido?: string; // 시도 + gugun?: string; // 구군 + bscFctNm?: string; // 펌프장명 (시설명) + } +): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/mediation-pump-stations`, + { params } + ); + return response.data; +} } // 통합 인스턴스 수출 diff --git a/apps/st/src/entities/statistics/model/statistics-pumping-station-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-pumping-station-review-interface.ts new file mode 100644 index 000000000..fbfc04711 --- /dev/null +++ b/apps/st/src/entities/statistics/model/statistics-pumping-station-review-interface.ts @@ -0,0 +1,86 @@ +import type { ApiResponse } from "./statistics-interface"; + +/** + * 중계펌프장 통계관리 아이템 인터페이스 + */ +export interface MediationPumpStationItem { + // 기본 정보 및 행 제어 + sido: string; // 시도 + gugun: string; // 시군구 + adstCd: string; // 행정코드 + pumpNm: string; // 펌프장명 + yr: string; // 연도 + displayYear: string; // 구분 표시용 (2024년확정 등) + rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 + + // 주요 제원 + bscFctNm: string; // 처리장명 + pumpCls: string; // 구분 (합류식/분류식) + addr: string; // 위치 + rnDt: string; // 가동년월일 + planDrhgAr: number; // 계획배수면적(㎢) + finewtDrngVl: number; // 계획시간대최대배수량 - 청천시(A) + rainwtDrngVl: number; // 계획시간대최대배수량 - 우천시(B) + vlWtr: number; // 계획시간대최대배수량 - 우수량(B-A) + + // 오수펌프 상세 (PLTWTR) + pltwtrTotCpcty: number; // 오수 총양수량(㎥/min) + pltwtrPumpCalbr1: number; // 오수펌프1 구경(mm) + pltwtrPumpCpcty1: number; // 오수펌프1 양수량(㎥/min) + pltwtrPumpCnt1: number; // 오수펌프1 펌프대수 + pltwtrPumpPreparCnt1: number; // 오수펌프1 예비대수 + + pltwtrPumpCalbr2: number; // 오수펌프2 구경(mm) + pltwtrPumpCpcty2: number; // 오수펌프2 양수량(㎥/min) + pltwtrPumpCnt2: number; // 오수펌프2 펌프대수 + pltwtrPumpPreparCnt2: number; // 오수펌프2 예비대수 + + pltwtrPumpCalbr3: number; // 오수펌프3 구경(mm) + pltwtrPumpCpcty3: number; // 오수펌프3 양수량(㎥/min) + pltwtrPumpCnt3: number; // 오수펌프3 펌프대수 + pltwtrPumpPreparCnt3: number; // 오수펌프3 예비대수 + + // 우수펌프 상세 (RAINWTR) + rainwtrTotCpcty: number; // 우수 총양수량(㎥/min) + rainwtrPumpCalbr1: number; // 우수펌프1 구경(mm) + rainwtrPumpCpcty1: number; // 우수펌프1 양수량(㎥/min) + rainwtrPumpCnt1: number; // 우수펌프1 펌프대수 + rainwtrPumpPreparCnt1: number; // 우수펌프1 예비대수 + + rainwtrPumpCalbr2: number; // 우수펌프2 구경(mm) + rainwtrPumpCpcty2: number; // 우수펌프2 양수량(㎥/min) + rainwtrPumpCnt2: number; // 우수펌프2 펌프대수 + rainwtrPumpPreparCnt2: number; // 우수펌프2 예비대수 + + rainwtrPumpCalbr3: number; // 우수펌프3 구경(mm) + rainwtrPumpCpcty3: number; // 우수펌프3 양수량(㎥/min) + rainwtrPumpCnt3: number; // 우수펌프3 펌프대수 + rainwtrPumpPreparCnt3: number; // 우수펌프3 예비대수 + + // 기타 + elcpwAmnt: number; // 연간전력사용량(kWh/년) + rmk: string; // 비고 + lcnt: string; // 당해 존재 여부 ('1'|'0') + ocnt: string; // 전년 존재 여부 ('1'|'0') +} + + +export interface MediationPumpStationResponseData { + pumpStationList: MediationPumpStationItem[]; +} + + +export type MediationPumpStationApiResponse = ApiResponse & { + message: string; +}; + + +export interface MediationPumpStationService { + getMediationPumpStationList(params: { + yr?: string; // 조회 연도 + bsnmCd?: string; // 사업소 코드 + sido?: string; // 시도 + gugun?: string; // 구군 + bscFctNm?: string; // 펌프장명 + }): Promise; +} \ No newline at end of file From cb29ac6c4d9524f64a2c3b58560510a09c6bbf58 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Fri, 20 Feb 2026 15:22:09 +0900 Subject: [PATCH 07/14] =?UTF-8?q?refactor:=20=EC=BB=AC=EB=9F=BC.ts-=20edit?= =?UTF-8?q?able:=20false,=20styleName:=20"rg-cell-readonly"=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../column/review/PumpingStationRvwColumn.ts | 10 ++- .../review/SewagePipeMaintainRvwColumn.ts | 13 ++-- .../util/column/review/SewagePipeRvwColumn.ts | 27 +++----- .../review/SewageReservoirPumpRvwColumn.ts | 19 +++--- .../SeweragePenetrationRateRvwColumn.ts | 64 +++++++++---------- .../review/StatsInputStatusRvwColumn.ts | 3 +- 6 files changed, 58 insertions(+), 78 deletions(-) diff --git a/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts b/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts index 7ab5e8e59..f031fed5e 100644 --- a/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts +++ b/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts @@ -10,7 +10,6 @@ export const rawPumpingStationInfoList = { fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { @@ -43,13 +42,12 @@ export const rawPumpingStationInfoList = { } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'pumpNm', fieldName: 'pumpNm', header: { text: '펌프장명' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'pumpNm', fieldName: 'pumpNm', header: { text: '펌프장명' }, mergeCells: true, sortdisable: true }, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -82,7 +80,7 @@ export const rawPumpingStationInfoList = { }, { name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '처리장명' } }, { name: 'pumpCls', fieldName: 'pumpCls', header: { text: '구분\n(합류/분류)' } }, - { name: 'addr', fieldName: 'addr', header: { text: '위치' }, styleName: 'rg-cell-left' }, + { name: 'addr', fieldName: 'addr', header: { text: '위치' } }, { name: 'rnDt', fieldName: 'rnDt', header: { text: '가동년월일\nyyyy-mm-dd' } }, { name: 'planDrhgAr', fieldName: 'planDrhgAr', header: { text: '계획배수면적\n(km2)' }, @@ -193,6 +191,6 @@ export const PumpingStationInfoList = { columns: rawPumpingStationInfoList.columns.map(col => ({ ...col, editable: false, - styleName: col.styleName ?? "rg-cell-readonly" + styleName: "rg-cell-readonly" })) }; \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts index ab32f39a5..f0ca4e7bc 100644 --- a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts @@ -16,8 +16,7 @@ const rawMaintainList = [ fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, - sortdisable: true, + tdisable: true, footer: [ { valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { @@ -53,14 +52,13 @@ const rawMaintainList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, /* 2. 구분 (displayYear) */ { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -165,7 +163,6 @@ const rawMaintainList = [ fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { @@ -198,12 +195,11 @@ const rawMaintainList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -291,6 +287,7 @@ export const SewagePipeMaintainColumnInfoList = rawMaintainList.map(tab => ({ ...tab, columns: tab.columns.map(col => ({ ...col, - editable: false + editable: false, + styleName: "rg-cell-readonly" })) })); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts index b57a54d44..4cc605836 100644 --- a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts @@ -16,7 +16,6 @@ const rawList = [ fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { @@ -55,13 +54,12 @@ const rawList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true,editable: false }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true,sortdisable: true }, + { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true }, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -197,7 +195,6 @@ const rawList = [ fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { @@ -234,13 +231,12 @@ const rawList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '하수처리장명' },mergeCells: true, editable: false }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '하수처리장명' },mergeCells: true }, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -362,7 +358,6 @@ const rawList = [ fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { @@ -393,13 +388,12 @@ const rawList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true, editable: false }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true,sortdisable: true }, + { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true }, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -488,7 +482,6 @@ const rawList = [ fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { @@ -525,13 +518,12 @@ const rawList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true, editable: false }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true }, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -608,6 +600,7 @@ export const SewagePipeColumnInfoListRvw = rawList.map(tab => ({ ...tab, columns: tab.columns.map(col => ({ ...col, - editable: false + editable: false, + styleName: "rg-cell-readonly" })) })); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts index b5caf5604..ded536777 100644 --- a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts @@ -21,7 +21,6 @@ const rawReservoirList = [ fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { @@ -60,14 +59,13 @@ const rawReservoirList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'swgeStrgeNm', fieldName: 'swgeStrgeNm', header: { text: '시설명' }, mergeCells: true, editable: false }, - { name: 'addr', fieldName: 'addr', header: { text: '위치' }, mergeCells: true, editable: false }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'swgeStrgeNm', fieldName: 'swgeStrgeNm', header: { text: '시설명' }, mergeCells: true }, + { name: 'addr', fieldName: 'addr', header: { text: '위치' }, mergeCells: true}, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -189,7 +187,6 @@ const rawReservoirList = [ fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { @@ -228,14 +225,13 @@ const rawReservoirList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'swgeStrgeNm', fieldName: 'swgeStrgeNm', header: { text: '시설명' }, mergeCells: true, editable: false }, - { name: 'addr', fieldName: 'addr', header: { text: '위치' }, mergeCells: true, editable: false }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'swgeStrgeNm', fieldName: 'swgeStrgeNm', header: { text: '시설명' }, mergeCells: true }, + { name: 'addr', fieldName: 'addr', header: { text: '위치' }, mergeCells: true }, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { @@ -339,6 +335,7 @@ export const SewageReservoirPumpInfoListRvw = rawReservoirList.map(tab => ({ ...tab, columns: tab.columns.map(col => ({ ...col, - editable: false + editable: false, + styleName: "rg-cell-readonly" })) })); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts b/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts index bf1af2259..fed92fbde 100644 --- a/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts @@ -2,88 +2,75 @@ import { ValueType } from "realgrid"; import { footerIntArrayByDivision, footerDecimal3ArrayByDivision, footerAvgDecimalArrayByDivision } from "@/components/util/grid/footerSummary"; import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataGrid.type"; -export const SeweragePenetrationRateInfoList = { + +const rawSeweragePenetrationRateInfoList = { columns: [ { name: 'sido', fieldName: 'sido', header: { text: '시도' }, mergeCells: true, - editable: false, sortdisable: true, footer: [ { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + valueCallback: (grid: GridView) => { const divisionIndex = 0; const dataSource = grid.getDataSource(); const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); for (let i = 0; i < rowCount; i++) { const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + if (divisionValue) uniqueValues.add(String(divisionValue)); } const divisionValues = Array.from(uniqueValues); - if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; - return '합계'; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; } }, { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + valueCallback: (grid: GridView) => { const divisionIndex = 1; const dataSource = grid.getDataSource(); const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); for (let i = 0; i < rowCount; i++) { const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + if (divisionValue) uniqueValues.add(String(divisionValue)); } const divisionValues = Array.from(uniqueValues); - if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; - return '합계'; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; } } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, - { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true, sortdisable: true }, { name: 'displayYear', fieldName: 'displayYear', header: { text: '구분' }, - editable: false, sortdisable: true, footer: [ { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + valueCallback: (grid: GridView) => { const divisionIndex = 0; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } const divisionValues = Array.from(uniqueValues); return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; } }, { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + valueCallback: (grid: GridView) => { const divisionIndex = 1; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } const divisionValues = Array.from(uniqueValues); return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; @@ -97,17 +84,15 @@ export const SeweragePenetrationRateInfoList = { { name: 'lgbsn', fieldName: 'lgbsn', header: { text: '중권역' } }, { name: 'mdmbsn', fieldName: 'mdmbsn', header: { text: '소권역' } }, { name: 'speclCntrplnAr', fieldName: 'speclCntrplnAr', header: { text: '특별대책지역' } }, - { name: 'popltnSm', fieldName: 'popltnSm', header: { text: '총인구' }, footer: footerIntArrayByDivision, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'popltnSm', fieldName: 'popltnSm', header: { text: '총인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'arSm', fieldName: 'arSm', header: { text: '총면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'swgeProcZoneInnerSm', fieldName: 'swgeProcZoneInnerSm', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0', styleName: 'rg-cell-total' }, + { name: 'swgeProcZoneInnerSm', fieldName: 'swgeProcZoneInnerSm', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - // 공공하수처리인구 { name: 'pblswrgPopltnSm', fieldName: 'pblswrgPopltnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'pblswrgPrmTrt', fieldName: 'pblswrgPrmTrt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'pblswrgScdTrt', fieldName: 'pblswrgScdTrt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'pblswrgTertTrt', fieldName: 'pblswrgTertTrt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - // 폐수처리인구(명) { name: 'wstrPopltnSm', fieldName: 'wstrPopltnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'wstrPrmTrt', fieldName: 'wstrPrmTrt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'wstrScdTrt', fieldName: 'wstrScdTrt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, @@ -183,4 +168,13 @@ export const SeweragePenetrationRateInfoList = { ], fixedColumns: 2, rowStartNum: 3 +}; + +export const SeweragePenetrationRateInfoList = { + ...rawSeweragePenetrationRateInfoList, + columns: rawSeweragePenetrationRateInfoList.columns.map(col => ({ + ...col, + editable: false, + styleName: "rg-cell-readonly" + })) }; \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/StatsInputStatusRvwColumn.ts b/apps/st/src/components/util/column/review/StatsInputStatusRvwColumn.ts index a5408cc7f..9f280338c 100644 --- a/apps/st/src/components/util/column/review/StatsInputStatusRvwColumn.ts +++ b/apps/st/src/components/util/column/review/StatsInputStatusRvwColumn.ts @@ -115,6 +115,7 @@ export const StatsInputStatusInfoList = { ...StatsInputStatusInfoColumnRaw, columns: StatsInputStatusInfoColumnRaw.columns.map(col => ({ ...col, - editable: false + editable: false, + styleName: "rg-cell-readonly" })) }; \ No newline at end of file From 8fa00797c8dd4035999c4de4474eed697b7f5f97 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Fri, 20 Feb 2026 16:10:39 +0900 Subject: [PATCH 08/14] =?UTF-8?q?refactor:=20tab=20key=20=EC=A7=80?= =?UTF-8?q?=EC=A0=95=EB=90=9C=20=EC=BD=94=EB=93=9C=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/review/SewagePipeMaintainRvw.tsx | 16 +++++++--------- .../statistics/review/SewagePipeRvw.tsx | 16 ++++++++-------- .../statistics/review/SewageReservoirPumpRvw.tsx | 13 +++++-------- .../column/review/SewagePipeMaintainRvwColumn.ts | 4 ++-- .../util/column/review/SewagePipeRvwColumn.ts | 8 ++++---- .../review/SewageReservoirPumpRvwColumn.ts | 4 ++-- 6 files changed, 28 insertions(+), 33 deletions(-) diff --git a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx index f2da6cce4..272ae04f1 100644 --- a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx @@ -19,7 +19,7 @@ const SewagePipeMaintainRvw = () => { const { setMessage: alert } = useAlertStore((state) => state); const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); const [isLoading, setIsLoading] = useState(false); - const [activeTab, setActiveTab] = useState('a'); + const [activeTab, setActiveTab] = useState('ST00030001'); const searchParamRef = useRef(null); @@ -36,7 +36,7 @@ const SewagePipeMaintainRvw = () => { const handleReset = () => { setRowDataMap(new Map()); - setActiveTab('a'); + setActiveTab('ST00030001'); searchParamRef.current = null; }; @@ -46,7 +46,7 @@ const SewagePipeMaintainRvw = () => { return; } - setActiveTab('a'); + setActiveTab('ST00030001'); setRowDataMap(new Map()); try { @@ -65,12 +65,11 @@ const SewagePipeMaintainRvw = () => { if (response?.status === 'success' && response.data) { const newRowDataMap = new Map[]>(); - // API 응답이 배열을 직접 반환하는 경우와 객체로 감싸진 경우 모두 처리 const listData = Array.isArray(response.data) ? response.data : (response.data.mtcStatusList || []); - newRowDataMap.set('a', toGridRows(listData as object[])); + newRowDataMap.set('ST00030001', toGridRows(listData as object[])); setRowDataMap(newRowDataMap); } else { alert(response?.message || "데이터가 없습니다."); @@ -85,7 +84,7 @@ const SewagePipeMaintainRvw = () => { const handleActiveTabChange = async (tabKey: string) => { setActiveTab(tabKey); - const existingAData = rowDataMap.get('a'); + const existingAData = rowDataMap.get('ST00030001'); const activeTabData = rowDataMap.get(tabKey); const hasAData = Array.isArray(existingAData) && existingAData.length > 0; @@ -97,9 +96,9 @@ const SewagePipeMaintainRvw = () => { let response; - if (tabKey === 'a') { + if (tabKey === 'ST00030001') { response = await statisticsManagementApi.getSewerPipeMtcList(searchParamRef.current); - }else if (tabKey === 'b') { + }else if (tabKey === 'ST00030002') { response = await statisticsManagementApi.getSewerPipeDrdgList(searchParamRef.current); } @@ -107,7 +106,6 @@ const SewagePipeMaintainRvw = () => { setRowDataMap(prev => { const next = new Map(prev); - // API 응답이 배열을 직접 반환하는 경우와 객체로 감싸진 경우 모두 처리 const listData = Array.isArray(response.data) ? response.data : (response.data.mtcStatusList || []); diff --git a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx index ac7033e53..94b79dfb0 100644 --- a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx @@ -19,7 +19,7 @@ const SewagePipeRvw = () => { const { setMessage: alert } = useAlertStore((state) => state); const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); const [isLoading, setIsLoading] = useState(false); - const [activeTab, setActiveTab] = useState('a'); + const [activeTab, setActiveTab] = useState('ST00020001'); const searchParamRef = useRef(null); @@ -36,7 +36,7 @@ const SewagePipeRvw = () => { const handleReset = () => { setRowDataMap(new Map()); - setActiveTab('a'); + setActiveTab('ST00020001'); }; const handleSearch = async (values: SearchFormValues) => { @@ -45,7 +45,7 @@ const SewagePipeRvw = () => { return; } - setActiveTab('a'); + setActiveTab('ST00020001'); setRowDataMap(new Map()); @@ -64,7 +64,7 @@ const SewagePipeRvw = () => { if (response?.status === 'success' && response.data) { const newRowDataMap = new Map[]>(); - newRowDataMap.set('a', toGridRows(response.data as object[])); + newRowDataMap.set('ST00020001', toGridRows(response.data as object[])); setRowDataMap(newRowDataMap); } else { alert(response?.message || "데이터가 없습니다."); @@ -79,7 +79,7 @@ const SewagePipeRvw = () => { const handleActiveTabChange = async (tabKey: string) => { setActiveTab(tabKey); - const existingAData = rowDataMap.get('a'); + const existingAData = rowDataMap.get('ST00020001'); const activeTabData = rowDataMap.get(tabKey); const hasAData = Array.isArray(existingAData) && existingAData.length > 0; @@ -92,11 +92,11 @@ const SewagePipeRvw = () => { let response; - if (tabKey === 'b') { + if (tabKey === 'ST00020002') { response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current); - }else if(tabKey === 'c'){ + }else if(tabKey === 'ST00020003'){ response = await statisticsManagementApi.getSewagePipeTypeList(searchParamRef.current); - }else if(tabKey === 'd'){ + }else if(tabKey === 'ST00020004'){ response = await statisticsManagementApi.getSewagePipeDiamList(searchParamRef.current); } diff --git a/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx b/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx index 3b7645a4e..346edb0cd 100644 --- a/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx +++ b/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx @@ -23,7 +23,7 @@ const SewageReservoirPumpRvw = () => { const { setMessage: alert } = useAlertStore((state) => state); const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); const [isLoading, setIsLoading] = useState(false); - const [activeTab, setActiveTab] = useState('a'); + const [activeTab, setActiveTab] = useState('ST00040001'); const searchParamRef = useRef(null); @@ -40,18 +40,17 @@ const SewageReservoirPumpRvw = () => { const handleReset = () => { setRowDataMap(new Map()); - setActiveTab('a'); + setActiveTab('ST00040001'); searchParamRef.current = null; }; - // 조회 버튼 클릭 시: Tab A(하수저류시설) 데이터 로드 const handleSearch = async (values: SearchFormValues) => { if (!values.sido || values.sido === 'ALL') { alert('시도를 선택해주세요.'); return; } - setActiveTab('a'); + setActiveTab('ST00040001'); setRowDataMap(new Map()); try { @@ -71,7 +70,7 @@ const SewageReservoirPumpRvw = () => { if (response?.status === 'success' && response.data) { const newRowDataMap = new Map[]>(); - newRowDataMap.set('a', toGridRows(response.data as object[])); + newRowDataMap.set('ST00040001', toGridRows(response.data as object[])); setRowDataMap(newRowDataMap); } else { alert(response?.message || "데이터가 없습니다."); @@ -83,20 +82,18 @@ const SewageReservoirPumpRvw = () => { } }; - // 탭 전환 시: 데이터가 없는 경우 지연 로딩 (Tab B: 빗물펌프장) const handleActiveTabChange = async (tabKey: string) => { setActiveTab(tabKey); const activeTabData = rowDataMap.get(tabKey); const hasActiveTabData = Array.isArray(activeTabData) && activeTabData.length > 0; - // 메인 데이터(Tab A)가 있고, 현재 탭 데이터가 없을 때만 API 호출 if (searchParamRef.current && !hasActiveTabData) { try { setIsLoading(true); let response; - if (tabKey === 'b') { + if (tabKey === 'ST00040002') { response = await statisticsManagementApi.getPumpStationList(searchParamRef.current); } diff --git a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts index f0ca4e7bc..aaf2bed67 100644 --- a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts @@ -5,7 +5,7 @@ import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataG // 하수도 통계 관리 03. 하수관로 유지 관리 const rawMaintainList = [ { - tabKey: 'a', + tabKey: 'ST00030001', tabLabel: '개보수', rowStartNum: 4, fixedColumns: 2, @@ -152,7 +152,7 @@ const rawMaintainList = [ ] }, { - tabKey: 'b', + tabKey: 'ST00030002', tabLabel: '관로준설', rowStartNum: 4, fixedColumns: 2, diff --git a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts index 4cc605836..93f52068f 100644 --- a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts @@ -6,7 +6,7 @@ import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataG // 하수도 통계 관리 02. 하수관로 const rawList = [ { - tabKey: 'a', + tabKey: 'ST00020001', tabLabel: '지역별 시설현황', rowStartNum: 4, fixedColumns: 2, @@ -185,7 +185,7 @@ const rawList = [ ] }, { - tabKey: 'b', + tabKey: 'ST00020002', tabLabel: '시설별 설치현황', rowStartNum: 4, fixedColumns: 3, @@ -348,7 +348,7 @@ const rawList = [ ] }, { - tabKey: 'c', + tabKey: 'ST00020003', tabLabel: '관종별 현황', rowStartNum: 2, fixedColumns: 3, @@ -472,7 +472,7 @@ const rawList = [ ] }, { - tabKey: 'd', + tabKey: 'ST00020004', tabLabel: '관경별 현황', rowStartNum: 2, fixedColumns: 3, diff --git a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts index ded536777..415d2896f 100644 --- a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts @@ -10,7 +10,7 @@ import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataG // 하수도 통계 관리 04. 하수저류 시설 및 빗물 펌프장 const rawReservoirList = [ { - tabKey: 'a', + tabKey: 'ST00040001', tabLabel: '하수저류시설현황', rowStartNum: 3, fixedColumns: 2, @@ -176,7 +176,7 @@ const rawReservoirList = [ ] }, { - tabKey: 'b', + tabKey: 'ST00040002', tabLabel: '빗물펌프장', rowStartNum: 3, fixedColumns: 2, From c2de582b767c77850b7644415bd2352482aee980 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Mon, 23 Feb 2026 17:08:56 +0900 Subject: [PATCH 09/14] =?UTF-8?q?refactor:=2001.=ED=95=98=EC=88=98?= =?UTF-8?q?=EB=8F=84=EB=B3=B4=EA=B8=89=EB=A5=A0=20=ED=91=9C=EC=A4=80?= =?UTF-8?q?=ED=99=94=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=A7=A4=EC=B9=AD=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/SeweragePenetrationRateRvw.tsx | 14 ++- .../SeweragePenetrationRateRvwColumn.ts | 98 +++++++-------- ...statistics-sewage-pipe-review-interface.ts | 1 - ...s-sewerage-penetration-review-interface.ts | 112 ++++++++---------- 4 files changed, 107 insertions(+), 118 deletions(-) diff --git a/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx b/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx index 8ad001c4c..65f3cea58 100644 --- a/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx +++ b/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx @@ -39,6 +39,7 @@ const SeweragePenetrationRateRvw = () => { }; const handleSearch = async (values: SearchFormValues) => { + if (values.sido === '' || values.sido === 'ALL') { alert('시도를 선택해주세요.'); return; @@ -48,17 +49,18 @@ const SeweragePenetrationRateRvw = () => { setIsLoading(true); const response = await statisticsManagementApi.getSewerageSupplyRateReviewList({ - sido: values.sido, - gugun: values.gugun === 'ALL' ? '' : values.gugun, - bsnmCd: values.bsnmCd, - yr: values.year, + ctpvNm: values.sido, + sggNm: values.gugun === 'ALL' ? '' : values.gugun, + sewerBzmnCd: values.bsnmCd, + statsYr: values.year, }); if (response.status === 'success' && response.data) { const rawList = response.data.sewerageSupplyRateList; - const convertedData: SewerageSupplyRateReviewItem[] = rawList.map((item) => ({ + const convertedData: SewerageSupplyRateReviewItem[] = rawList.map((item) => ({ ...item, - speclCntrplnAr: !item.speclCntrplnAr ? '해당없음' : item.speclCntrplnAr, + + spcCtpnRgnCn: !item.spcCtpnRgnCn ? '해당없음' : item.spcCtpnRgnCn, })); setRowData(toGridRows(convertedData)); diff --git a/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts b/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts index fed92fbde..94f272057 100644 --- a/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts @@ -4,10 +4,10 @@ import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataG const rawSeweragePenetrationRateInfoList = { - columns: [ + columns: [ { - name: 'sido', - fieldName: 'sido', + name: 'ctpvNm', + fieldName: 'ctpvNm', header: { text: '시도' }, mergeCells: true, sortdisable: true, @@ -42,8 +42,8 @@ const rawSeweragePenetrationRateInfoList = { } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, - { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true, sortdisable: true }, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true, sortdisable: true }, { name: 'displayYear', fieldName: 'displayYear', @@ -78,37 +78,37 @@ const rawSeweragePenetrationRateInfoList = { } ] }, - { name: 'rvbsn', fieldName: 'rvbsn', header: { text: '수계' } }, - { name: 'bstrm', fieldName: 'bstrm', header: { text: '지류' } }, - { name: 'mdbsn', fieldName: 'mdbsn', header: { text: '세부단위유역' } }, + { name: 'wtsysNm', fieldName: 'wtsysNm', header: { text: '수계' } }, + { name: 'trbtrNm', fieldName: 'trbtrNm', header: { text: '지류' } }, + { name: 'mdbsn', fieldName: 'mdbsn', header: { text: '세부단위유역' } }, { name: 'lgbsn', fieldName: 'lgbsn', header: { text: '중권역' } }, { name: 'mdmbsn', fieldName: 'mdmbsn', header: { text: '소권역' } }, - { name: 'speclCntrplnAr', fieldName: 'speclCntrplnAr', header: { text: '특별대책지역' } }, - { name: 'popltnSm', fieldName: 'popltnSm', header: { text: '총인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'arSm', fieldName: 'arSm', header: { text: '총면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'swgeProcZoneInnerSm', fieldName: 'swgeProcZoneInnerSm', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'spcCtpnRgnCn', fieldName: 'spcCtpnRgnCn', header: { text: '특별대책지역' } }, + { name: 'wholPpltnCnt', fieldName: 'wholPpltnCnt', header: { text: '총인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'wholArea', fieldName: 'wholArea', header: { text: '총면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'wholSwtrmtPpltnCnt', fieldName: 'wholSwtrmtPpltnCnt', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'pblswrgPopltnSm', fieldName: 'pblswrgPopltnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'pblswrgPrmTrt', fieldName: 'pblswrgPrmTrt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'pblswrgScdTrt', fieldName: 'pblswrgScdTrt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'pblswrgTertTrt', fieldName: 'pblswrgTertTrt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'wholPblSwtrmtPpltnCnt', fieldName: 'wholPblSwtrmtPpltnCnt', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ts1SwtrmtPpltnCnt', fieldName: 'ts1SwtrmtPpltnCnt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ts2SwtrmtPpltnCnt', fieldName: 'ts2SwtrmtPpltnCnt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ts3SwtrmtPpltnCnt', fieldName: 'ts3SwtrmtPpltnCnt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'wstrPopltnSm', fieldName: 'wstrPopltnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'wstrPrmTrt', fieldName: 'wstrPrmTrt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'wstrScdTrt', fieldName: 'wstrScdTrt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'wstrTertTrt', fieldName: 'wstrTertTrt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'wholWwtPrcsPpltnCnt', fieldName: 'wholWwtPrcsPpltnCnt', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ts1WwtPrcsPpltnCnt', fieldName: 'ts1WwtPrcsPpltnCnt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ts2WwtPrcsPpltnCnt', fieldName: 'ts2WwtPrcsPpltnCnt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ts3WwtPrcsPpltnCnt', fieldName: 'ts3WwtPrcsPpltnCnt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'notConectPopltn', fieldName: 'notConectPopltn', header: { text: '미접속인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'swgeProcZoneInnerAr', fieldName: 'swgeProcZoneInnerAr', header: { text: '면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'swgeProcZoneOuterSm', fieldName: 'swgeProcZoneOuterSm', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'townUnprocPopltn', fieldName: 'townUnprocPopltn', header: { text: '미처리인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'townSwttPopltn', fieldName: 'townSwttPopltn', header: { text: '오수처리인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'townWrrtnPopltn', fieldName: 'townWrrtnPopltn', header: { text: '정화조인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'swgeProcZoneOuterAr', fieldName: 'swgeProcZoneOuterAr', header: { text: '면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'pblswrgPopltnSuprt', fieldName: 'pblswrgPopltnSuprt', header: { text: '공공하수처리구역인구보급율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'adtrtPopltnSuprt', fieldName: 'adtrtPopltnSuprt', header: { text: '고도처리인구보급율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'swrgInstlrt', fieldName: 'swrgInstlrt', header: { text: '하수도설치율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + { name: 'yetCntnPpltnCnt', fieldName: 'yetCntnPpltnCnt', header: { text: '미접속인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'staaArea', fieldName: 'staaArea', header: { text: '면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'wholStaaExcpPpltnCnt', fieldName: 'wholStaaExcpPpltnCnt', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'unprcsPpltnCnt', fieldName: 'unprcsPpltnCnt', header: { text: '미처리인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'drtwPrcsPpltnCnt', fieldName: 'drtwPrcsPpltnCnt', header: { text: '오수처리인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'spctnkPpltnCnt', fieldName: 'spctnkPpltnCnt', header: { text: '정화조인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'staaExcpArea', fieldName: 'staaExcpArea', header: { text: '면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'staaPsplyRt', fieldName: 'staaPsplyRt', header: { text: '공공하수처리구역인구보급율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'altdPrcsPsplyRt', fieldName: 'altdPrcsPsplyRt', header: { text: '고도처리인구보급율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'sewerInstlRt', fieldName: 'sewerInstlRt', header: { text: '하수도설치율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, ], columnLayout: [ { @@ -116,55 +116,55 @@ const rawSeweragePenetrationRateInfoList = { hideChildHeaders: false, header: { text: '행정구역' }, items: [ - { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, - 'gugun', - 'adstDong', + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'sggNm', + 'admdstNm', ] }, 'displayYear', - 'rvbsn', - 'bstrm', + 'wtsysNm', + 'trbtrNm', { name: 'groupB', hideChildHeaders: false, header: { text: '수계영향권별분류' }, items: ['mdbsn', 'lgbsn', 'mdmbsn'], }, - 'speclCntrplnAr', - 'popltnSm', - 'arSm', + 'spcCtpnRgnCn', + 'wholPpltnCnt', + 'wholArea', { name: 'groupD', hideChildHeaders: false, header: { text: '하수처리구역내' }, items: [ - 'swgeProcZoneInnerSm', + 'wholSwtrmtPpltnCnt', { name: 'pblswrgGroup', hideChildHeaders: false, header: { text: '공공하수처리인구(명)' }, - items: ['pblswrgPopltnSm', 'pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt'], + items: ['wholPblSwtrmtPpltnCnt', 'ts1SwtrmtPpltnCnt', 'ts2SwtrmtPpltnCnt', 'ts3SwtrmtPpltnCnt'], }, { name: 'wstrGroup', hideChildHeaders: false, header: { text: '폐수처리인구(명)' }, - items: ['wstrPopltnSm', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt'], + items: ['wholWwtPrcsPpltnCnt', 'ts1WwtPrcsPpltnCnt', 'ts2WwtPrcsPpltnCnt', 'ts3WwtPrcsPpltnCnt'], }, - 'notConectPopltn', - 'swgeProcZoneInnerAr' + 'yetCntnPpltnCnt', + 'staaArea' ], }, { name: 'groupE', hideChildHeaders: false, header: { text: '하수처리구역외' }, - items: ['swgeProcZoneOuterSm', 'townUnprocPopltn', 'townSwttPopltn', 'townWrrtnPopltn', 'swgeProcZoneOuterAr'], + items: ['wholStaaExcpPpltnCnt', 'unprcsPpltnCnt', 'drtwPrcsPpltnCnt', 'spctnkPpltnCnt', 'staaExcpArea'], }, - 'pblswrgPopltnSuprt', - 'adtrtPopltnSuprt', - 'swrgInstlrt', - 'rmk', + 'staaPsplyRt', + 'altdPrcsPsplyRt', + 'sewerInstlRt', + 'rmrk', ], fixedColumns: 2, rowStartNum: 3 diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts index 6abb98a80..9aefdbd5b 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts @@ -104,7 +104,6 @@ export interface SewagePipeReviewFacilityItem { procZoneSm: number; // 합계(면적) cmbnProcZoneAr: number; // 합류식(면적) sprtProcZoneAr: number; // 분류식(면적) - sepRate: number; // 분류식화 (%) // 4. 배수설비(개소) drngEqpSm: number; // 합계(배수) diff --git a/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts index 8fbf7ea1f..ce82890d6 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts @@ -2,69 +2,65 @@ import type { ApiResponse } from "./statistics-interface"; // 검토 01.하수도 보급률 데이터 항목 export interface SewerageSupplyRateReviewItem { +/* 지역 및 구분 정보 */ + ctpvNm: string; // 시도명 + sggNm: string; // 시군구명 + statsYr: string; // 통계연도 + admdstNm: string; // 행정구역명 + admdstCd: string; // 행정구역코드 + displayYear: string; // 화면 표시 연도 + rowType: 'OLD' | 'CURR'; // 데이터 구분(OLD: 확정, CURR: 당해년도) - sido: string; - gugun: string; - adstDong: string; - displayYear: string; - rowType: 'OLD' | 'CURR'; - adstCd: string; - bsnmCd: string; - yr: number; + /* 수계 및 지역 정보 */ + lgbsn: string; // 중권역 + mdbsn: string; // 세부단위유역 + mdmbsn: string; // 소수계 + wtsysNm: string | null; // 수계명 + trbtrNm: string | null; // 지류명 + spcCtpnRgnCn: string | null; // 특별대책지역내용 - /* ====================================================================== - * 수계 및 지역 정보 - * ====================================================================== */ - rvbsn: string; - lgbsn: string; - mdbsn: string; - mdmbsn: string; - wrssm: string | null; - bstrm: string; - speclCntrplnAr: string | null; + /* 인구 및 면적 데이터 */ + wholPpltnCnt: number; // 전체인구수(명) + wholArea: number; // 전체면적(㎢) - /* ====================================================================== - * 인구 및 면적 데이터 (공통 필드명) - * ====================================================================== */ - popltnSm: number; // 총인구 - arSm: number; // 총면적(㎢) - - /* 하수처리구역내 (groupD) */ - swgeProcZoneInnerSm: number; // 계 - pblswrgPopltnSm: number; // 공공하수처리인구-합계 - pblswrgPrmTrt: number; // 1차처리 - pblswrgScdTrt: number; // 2차처리 - pblswrgTertTrt: number; // 3차처리 + /* 하수처리구역내 */ + wholSwtrmtPpltnCnt: number; // 전체하수처리인구수(명) + wholPblSwtrmtPpltnCnt: number; // 전체공공하수처리인구수(명) + ts1SwtrmtPpltnCnt: number; // 1차하수처리인구수(명) + ts2SwtrmtPpltnCnt: number; // 2차하수처리인구수(명) + ts3SwtrmtPpltnCnt: number; // 3차하수처리인구수(명) - wstrPopltnSm: number; // 폐수처리인구-합계 - wstrPrmTrt: number; // 1차처리 - wstrScdTrt: number; // 2차처리 - wstrTertTrt: number; // 3차처리 + wholWwtPrcsPpltnCnt: number; // 전체폐수처리인구수(명) + ts1WwtPrcsPpltnCnt: number | null; // 1차폐수처리인구수(명) + ts2WwtPrcsPpltnCnt: number | null; // 2차폐수처리인구수(명) + ts3WwtPrcsPpltnCnt: number | null; // 3차폐수처리인구수(명) - notConectPopltn: number; // 미접속인구 - swgeProcZoneInnerAr: number; // 면적(㎢) + yetCntnPpltnCnt: number; // 미접속인구수(명) + staaArea: number; // 하수처리구역면적(㎢) - /* 하수처리구역외 (groupE) */ - swgeProcZoneOuterSm: number; // 계 - townUnprocPopltn: number; // 미처리인구 (Town + Uptown 합산값) - townSwttPopltn: number; // 오수처리인구 (Town + Uptown 합산값) - townWrrtnPopltn: number; // 정화조인구 (Town + Uptown 합산값) - swgeProcZoneOuterAr: number; // 면적(㎢) + /* 하수처리구역외 */ + wholStaaExcpPpltnCnt: number; // 전체하수처리구역외인구수(명) + unprcsPpltnCnt: number | null; // 미처리인구수(명) + drtwPrcsPpltnCnt: number | null; // 오수처리인구수(명) + spctnkPpltnCnt: number | null; // 정화조인구수(명) + staaExcpArea: number; // 하수처리구역외면적(㎢) - /* ====================================================================== - * 보급률 및 기타 - * ====================================================================== */ - pblswrgPopltnSuprt: number; // 공공하수보급률(%) - adtrtPopltnSuprt: number; // 고도처리보급률(%) - swrgInstlrt: number; // 하수도설치율(%) - rmk: string | null; // 비고 + /* 보급률 및 기타 */ + staaPsplyRt: number; // 하수처리구역보급비율(%) + altdPrcsPsplyRt: number; // 고도처리보급비율(%) + sewerInstlRt: number; // 하수도설치비율(%) + rmrk: string | null; // 비고 - /* ====================================================================== - * Flag (필요 시 유지) - * ====================================================================== */ - lcnt: number | null; - ocnt: number | null; + /* 기타 플래그 */ + lcnt?: number | null; + ocnt?: number | null; +} +export interface SewerageSupplyRateReviewRequestParams { + ctpvNm?: string; + sggNm?: string; + statsYr?: string; + sewerBzmnCd?: string; } export interface SewerageSupplyRateReviewResponseData { @@ -75,14 +71,6 @@ export type SewerageSupplyRateReviewApiResponse = ApiResponse; } \ No newline at end of file From 8e7baee9305a3d1e846f6dd4f09bc774fa57602b Mon Sep 17 00:00:00 2001 From: rsone001 Date: Tue, 24 Feb 2026 11:42:16 +0900 Subject: [PATCH 10/14] =?UTF-8?q?refactor:=2001.=20=ED=95=98=EC=88=98?= =?UTF-8?q?=EB=8F=84=20=EB=B3=B4=EA=B8=89=EB=A5=A0=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=EC=BB=AC=EB=9F=BC=20=EC=A0=9C=EA=B1=B0=20=20=EB=B0=8F?= =?UTF-8?q?=20=EC=BB=AC=EB=9F=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SeweragePenetrationRateRvwColumn.ts | 19 ++--- ...s-sewerage-penetration-review-interface.ts | 80 ++++++++----------- 2 files changed, 42 insertions(+), 57 deletions(-) diff --git a/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts b/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts index 94f272057..490e79099 100644 --- a/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts @@ -16,11 +16,10 @@ const rawSeweragePenetrationRateInfoList = { valueCallback: (grid: GridView) => { const divisionIndex = 0; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue) uniqueValues.add(String(divisionValue)); + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } const divisionValues = Array.from(uniqueValues); return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; @@ -30,11 +29,10 @@ const rawSeweragePenetrationRateInfoList = { valueCallback: (grid: GridView) => { const divisionIndex = 1; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue) uniqueValues.add(String(divisionValue)); + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } const divisionValues = Array.from(uniqueValues); return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; @@ -78,7 +76,7 @@ const rawSeweragePenetrationRateInfoList = { } ] }, - { name: 'wtsysNm', fieldName: 'wtsysNm', header: { text: '수계' } }, + { name: 'wtsysNm', fieldName: 'rvbsn', header: { text: '수계' } }, { name: 'trbtrNm', fieldName: 'trbtrNm', header: { text: '지류' } }, { name: 'mdbsn', fieldName: 'mdbsn', header: { text: '세부단위유역' } }, { name: 'lgbsn', fieldName: 'lgbsn', header: { text: '중권역' } }, @@ -87,17 +85,14 @@ const rawSeweragePenetrationRateInfoList = { { name: 'wholPpltnCnt', fieldName: 'wholPpltnCnt', header: { text: '총인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'wholArea', fieldName: 'wholArea', header: { text: '총면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, { name: 'wholSwtrmtPpltnCnt', fieldName: 'wholSwtrmtPpltnCnt', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'wholPblSwtrmtPpltnCnt', fieldName: 'wholPblSwtrmtPpltnCnt', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'ts1SwtrmtPpltnCnt', fieldName: 'ts1SwtrmtPpltnCnt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'ts2SwtrmtPpltnCnt', fieldName: 'ts2SwtrmtPpltnCnt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'ts3SwtrmtPpltnCnt', fieldName: 'ts3SwtrmtPpltnCnt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'wholWwtPrcsPpltnCnt', fieldName: 'wholWwtPrcsPpltnCnt', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'ts1WwtPrcsPpltnCnt', fieldName: 'ts1WwtPrcsPpltnCnt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'ts2WwtPrcsPpltnCnt', fieldName: 'ts2WwtPrcsPpltnCnt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'ts3WwtPrcsPpltnCnt', fieldName: 'ts3WwtPrcsPpltnCnt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'yetCntnPpltnCnt', fieldName: 'yetCntnPpltnCnt', header: { text: '미접속인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, { name: 'staaArea', fieldName: 'staaArea', header: { text: '면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, { name: 'wholStaaExcpPpltnCnt', fieldName: 'wholStaaExcpPpltnCnt', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, diff --git a/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts index ce82890d6..9c4d0ac1e 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts @@ -2,58 +2,48 @@ import type { ApiResponse } from "./statistics-interface"; // 검토 01.하수도 보급률 데이터 항목 export interface SewerageSupplyRateReviewItem { -/* 지역 및 구분 정보 */ - ctpvNm: string; // 시도명 - sggNm: string; // 시군구명 - statsYr: string; // 통계연도 - admdstNm: string; // 행정구역명 - admdstCd: string; // 행정구역코드 - displayYear: string; // 화면 표시 연도 - rowType: 'OLD' | 'CURR'; // 데이터 구분(OLD: 확정, CURR: 당해년도) +ctpvNm: string; + sggNm: string; + statsYr: string; + admdstNm: string; + admdstCd: string; + displayYear: string; + rowType: 'OLD' | 'CURR'; - /* 수계 및 지역 정보 */ - lgbsn: string; // 중권역 - mdbsn: string; // 세부단위유역 - mdmbsn: string; // 소수계 - wtsysNm: string | null; // 수계명 - trbtrNm: string | null; // 지류명 - spcCtpnRgnCn: string | null; // 특별대책지역내용 + lgbsn: string; + mdbsn: string; + mdmbsn: string; + rvbsn: string | null; + trbtrNm: string | null; + spcCtpnRgnCn: string | null; - /* 인구 및 면적 데이터 */ - wholPpltnCnt: number; // 전체인구수(명) - wholArea: number; // 전체면적(㎢) + wholPpltnCnt: number; + wholArea: number; - /* 하수처리구역내 */ - wholSwtrmtPpltnCnt: number; // 전체하수처리인구수(명) - wholPblSwtrmtPpltnCnt: number; // 전체공공하수처리인구수(명) - ts1SwtrmtPpltnCnt: number; // 1차하수처리인구수(명) - ts2SwtrmtPpltnCnt: number; // 2차하수처리인구수(명) - ts3SwtrmtPpltnCnt: number; // 3차하수처리인구수(명) + wholSwtrmtPpltnCnt: number; + wholPblSwtrmtPpltnCnt: number; + ts1SwtrmtPpltnCnt: number; + ts2SwtrmtPpltnCnt: number; + ts3SwtrmtPpltnCnt: number; - wholWwtPrcsPpltnCnt: number; // 전체폐수처리인구수(명) - ts1WwtPrcsPpltnCnt: number | null; // 1차폐수처리인구수(명) - ts2WwtPrcsPpltnCnt: number | null; // 2차폐수처리인구수(명) - ts3WwtPrcsPpltnCnt: number | null; // 3차폐수처리인구수(명) + wholWwtPrcsPpltnCnt: number; + ts1WwtPrcsPpltnCnt: number | null; + ts2WwtPrcsPpltnCnt: number | null; + ts3WwtPrcsPpltnCnt: number | null; - yetCntnPpltnCnt: number; // 미접속인구수(명) - staaArea: number; // 하수처리구역면적(㎢) + yetCntnPpltnCnt: number; + staaArea: number; - /* 하수처리구역외 */ - wholStaaExcpPpltnCnt: number; // 전체하수처리구역외인구수(명) - unprcsPpltnCnt: number | null; // 미처리인구수(명) - drtwPrcsPpltnCnt: number | null; // 오수처리인구수(명) - spctnkPpltnCnt: number | null; // 정화조인구수(명) - staaExcpArea: number; // 하수처리구역외면적(㎢) + wholStaaExcpPpltnCnt: number; + unprcsPpltnCnt: number | null; + drtwPrcsPpltnCnt: number | null; + spctnkPpltnCnt: number | null; + staaExcpArea: number; - /* 보급률 및 기타 */ - staaPsplyRt: number; // 하수처리구역보급비율(%) - altdPrcsPsplyRt: number; // 고도처리보급비율(%) - sewerInstlRt: number; // 하수도설치비율(%) - rmrk: string | null; // 비고 - - /* 기타 플래그 */ - lcnt?: number | null; - ocnt?: number | null; + staaPsplyRt: number; + altdPrcsPsplyRt: number; + sewerInstlRt: number; + rmrk: string | null; } export interface SewerageSupplyRateReviewRequestParams { From ec250bded1475c47cef54491e523656cae22293f Mon Sep 17 00:00:00 2001 From: rsone001 Date: Tue, 24 Feb 2026 16:23:47 +0900 Subject: [PATCH 11/14] =?UTF-8?q?refactor:=2002.=ED=95=98=EC=88=98?= =?UTF-8?q?=EA=B4=80=EB=A1=9C=20tab1.=EC=A7=80=EC=97=AD=EB=B3=84=20?= =?UTF-8?q?=EC=8B=9C=EC=84=A4=ED=98=84=ED=99=A9=20=ED=91=9C=EC=A4=80?= =?UTF-8?q?=ED=99=94=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=A7=A4=ED=95=91=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/review/SewagePipeRvw.tsx | 62 ++++---- .../util/column/review/SewagePipeRvwColumn.ts | 142 ++++++++---------- .../api/statistics-management-service.ts | 12 +- ...statistics-sewage-pipe-review-interface.ts | 119 ++++++++------- 4 files changed, 162 insertions(+), 173 deletions(-) diff --git a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx index 94b79dfb0..2c68978bd 100644 --- a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx @@ -13,6 +13,8 @@ import { SewagePipeColumnInfoListRvw } from "@/components/util/column/review/Sew import type { ColumnInfoList, ColumnConfig } from "@/components/type/DataGrid.type"; import type { SearchFormValues } from "@/components/type/SearchForm.type"; import { toGridRows } from "@/components/util/grid/gridFunction"; +import type { SewagePipeReviewRequestParams } from "@/entities/statistics/model/statistics-sewage-pipe-review-interface"; + // 하수도 통계 검토 02.하수관로 const SewagePipeRvw = () => { @@ -21,7 +23,7 @@ const SewagePipeRvw = () => { const [isLoading, setIsLoading] = useState(false); const [activeTab, setActiveTab] = useState('ST00020001'); - const searchParamRef = useRef(null); + const searchParamRef = useRef(null); const columnInfo = useMemo(() => { return SewagePipeColumnInfoListRvw.map((tab: ColumnInfoList) => ({ @@ -52,11 +54,11 @@ const SewagePipeRvw = () => { try { setIsLoading(true); - const searchParam = { - sido: values.sido, - gugun: values.gugun === 'ALL' ? '' : values.gugun, - bsnmCd: values.bsnmCd, - yr: values.year, + const searchParam: SewagePipeReviewRequestParams = { + statsYr: values.year, + sewerBzmnCd: values.bsnmCd, + ctpvNm: values.sido, + sggNm: values.gugun === 'ALL' ? '' : values.gugun }; searchParamRef.current = searchParam; @@ -87,34 +89,34 @@ const SewagePipeRvw = () => { if (hasAData && !hasActiveTabData && searchParamRef.current) { - try { - setIsLoading(true); + // try { + // setIsLoading(true); - let response; + // let response; - if (tabKey === 'ST00020002') { - response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current); - }else if(tabKey === 'ST00020003'){ - response = await statisticsManagementApi.getSewagePipeTypeList(searchParamRef.current); - }else if(tabKey === 'ST00020004'){ - response = await statisticsManagementApi.getSewagePipeDiamList(searchParamRef.current); - } + // if (tabKey === 'ST00020002') { + // response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current); + // }else if(tabKey === 'ST00020003'){ + // response = await statisticsManagementApi.getSewagePipeTypeList(searchParamRef.current); + // }else if(tabKey === 'ST00020004'){ + // response = await statisticsManagementApi.getSewagePipeDiamList(searchParamRef.current); + // } - if (response?.status === 'success' && response.data) { + // if (response?.status === 'success' && response.data) { - setRowDataMap(prev => { - const next = new Map(prev); - next.set(tabKey, toGridRows(response.data as object[])); - return next; - }); - } else { - alert(response?.message || "데이터가 없습니다."); - } - } catch { - alert('데이터 조회 중 오류가 발생했습니다.'); - } finally { - setIsLoading(false); - } + // setRowDataMap(prev => { + // const next = new Map(prev); + // next.set(tabKey, toGridRows(response.data as object[])); + // return next; + // }); + // } else { + // alert(response?.message || "데이터가 없습니다."); + // } + // } catch { + // alert('데이터 조회 중 오류가 발생했습니다.'); + // } finally { + // setIsLoading(false); + // } } }; diff --git a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts index 93f52068f..9ae786be8 100644 --- a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts @@ -5,57 +5,49 @@ import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataG // 하수도 통계 관리 02. 하수관로 const rawList = [ - { + { tabKey: 'ST00020001', tabLabel: '지역별 시설현황', rowStartNum: 4, fixedColumns: 2, columns: [ { - name: 'sido', - fieldName: 'sido', - header: { text: '시도' }, - mergeCells: true, - sortdisable: true, + name: 'ctpvNm', + fieldName: 'ctpvNm', + header: { text: '시도' }, + mergeCells: true, + sortdisable: true, footer: [ { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + valueCallback: (grid: GridView) => { const divisionIndex = 0; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } const divisionValues = Array.from(uniqueValues); - if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; - return '합계'; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; } }, { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + valueCallback: (grid: GridView) => { const divisionIndex = 1; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } const divisionValues = Array.from(uniqueValues); - if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; - return '합계'; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; } } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true,sortdisable: true }, - { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true }, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true }, { name: 'displayYear', fieldName: 'displayYear', @@ -63,32 +55,26 @@ const rawList = [ sortdisable: true, footer: [ { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + valueCallback: (grid: GridView) => { const divisionIndex = 0; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } const divisionValues = Array.from(uniqueValues); return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; } }, { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + valueCallback: (grid: GridView) => { const divisionIndex = 1; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } const divisionValues = Array.from(uniqueValues); return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; @@ -99,14 +85,14 @@ const rawList = [ /* 하수정비 기본계획 */ { name: 'targetYr', fieldName: 'targetYr', header: { text: '하수정보기본계획목표년도' } }, - { name: 'piplImprmnPlanExtn', fieldName: 'piplImprmnPlanExtn', header: { text: '총관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'piplPlanExtn', fieldName: 'piplPlanExtn', header: { text: '총계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'piplFcltyExtn', fieldName: 'piplFcltyExtn', header: { text: '총시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'piplSupprt', fieldName: 'piplSupprt', header: { text: '하수관로\n보급률(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'swrgPipeMntnPlanExtn', fieldName: 'swrgPipeMntnPlanExtn', header: { text: '총관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'swrgPipePlanExtn', fieldName: 'swrgPipePlanExtn', header: { text: '총계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'swrgPipeFcltyExtn', fieldName: 'swrgPipeFcltyExtn', header: { text: '총시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'swrgPipePsplyRt', fieldName: 'swrgPipePsplyRt', header: { text: '하수관로\n보급률(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, /* 합류식(m) */ - { name: 'cmbnPlanAr', fieldName: 'cmbnPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, - { name: 'cmbnImprmnPlanExtn', fieldName: 'cmbnImprmnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cmbnMntnPlanAr', fieldName: 'cmbnMntnPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'cmbnMntnPlanExtn', fieldName: 'cmbnMntnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'cmbnPlanExtn', fieldName: 'cmbnPlanExtn', header: { text: '계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'cmbnFcltyExtn', fieldName: 'cmbnFcltyExtn', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'cmbnRctglExtn', fieldName: 'cmbnRctglExtn', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, @@ -115,50 +101,50 @@ const rawList = [ { name: 'cmbnSdgttrExtn', fieldName: 'cmbnSdgttrExtn', header: { text: '측구(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, /* 분류식 - 오수관로 */ - { name: 'pltwtrPlanAr', fieldName: 'pltwtrPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, - { name: 'pltwtrImprmnPlanExtn', fieldName: 'pltwtrImprmnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrMntnPlanAr', fieldName: 'pltwtrMntnPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'pltwtrMntnPlanExtn', fieldName: 'pltwtrMntnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'pltwtrPlanExtn', fieldName: 'pltwtrPlanExtn', header: { text: '계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'pltwtrFlctyExtn', fieldName: 'pltwtrFlctyExtn', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'pltwtrSqreExtn', fieldName: 'pltwtrSqreExtn', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'pltwtrCiclExtn', fieldName: 'pltwtrCiclExtn', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrFcltyExtn', fieldName: 'pltwtrFcltyExtn', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrRctglExtn', fieldName: 'pltwtrRctglExtn', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrCicleExtn', fieldName: 'pltwtrCicleExtn', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, /* 분류식 - 우수관로 */ - { name: 'rainwtrPlanAr', fieldName: 'rainwtrPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, - { name: 'rainwtrImprmnPlanExtn', fieldName: 'rainwtrImprmnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrMntnPlanAr', fieldName: 'rainwtrMntnPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'rainwtrMntnPlanExtn', fieldName: 'rainwtrMntnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'rainwtrPlanExtn', fieldName: 'rainwtrPlanExtn', header: { text: '계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'rainwtrFlctyExtn', fieldName: 'rainwtrFlctyExtn', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'rainwtrSqreExtn', fieldName: 'rainwtrSqreExtn', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'rainwtrCiclExtn', fieldName: 'rainwtrCiclExtn', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrFcltyExtn', fieldName: 'rainwtrFcltyExtn', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrRctglExtn', fieldName: 'rainwtrRctglExtn', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrCicleExtn', fieldName: 'rainwtrCicleExtn', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'rainwtrOpswrExtn', fieldName: 'rainwtrOpswrExtn', header: { text: '개거(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'rainwtrSdgttrExtn', fieldName: 'rainwtrSdgttrExtn', header: { text: '측구(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, /* 부속시설 */ - { name: 'mnhleSite', fieldName: 'mnhleSite', header: { text: '합류식맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'pltwtrMnhleSite', fieldName: 'pltwtrMnhleSite', header: { text: '오수맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'rainwtrMnhleSite', fieldName: 'rainwtrMnhleSite', header: { text: '우수맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'pltwtrRcvrSite', fieldName: 'pltwtrRcvrSite', header: { text: '오수받이(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'rainwtrRcvrSite', fieldName: 'rainwtrRcvrSite', header: { text: '빗물받이(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'soilspllSite', fieldName: 'soilspllSite', header: { text: '우수토실(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'soilholeSite', fieldName: 'soilholeSite', header: { text: '우수토구(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'cmbnMnhleCnt', fieldName: 'cmbnMnhleCnt', header: { text: '합류식맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrMnhleCnt', fieldName: 'pltwtrMnhleCnt', header: { text: '오수맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrMnhleCnt', fieldName: 'rainwtrMnhleCnt', header: { text: '우수맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrRcvrCnt', fieldName: 'pltwtrRcvrCnt', header: { text: '오수받이(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrRcvrCnt', fieldName: 'rainwtrRcvrCnt', header: { text: '우수받이(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrChmbrCnt', fieldName: 'rainwtrChmbrCnt', header: { text: '우수토실(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrOutltCnt', fieldName: 'rainwtrOutltCnt', header: { text: '우수토구(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, /* 대장 및 기타 */ - { name: 'sewerRegstrCmptExtn', fieldName: 'sewerRegstrCmptExtn', header: { text: '하수도대장전산화연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'sewerRegstrCmptRt', fieldName: 'sewerRegstrCmptRt', header: { text: '하수도대장전산화율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + { name: 'swrgRegstrCmptExtn', fieldName: 'swrgRegstrCmptExtn', header: { text: '하수도대장전산화연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'swrgRegstrCmptRt', fieldName: 'swrgRegstrCmptRt', header: { text: '하수도대장전산화율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, ], columnLayout: [ { name: 'areaGroup', header: { text: '행정구역' }, items: [ - { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, - 'gugun', - 'adstDong', + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'sggNm', + 'admdstNm', ] }, 'displayYear', - 'targetYr', 'piplImprmnPlanExtn', 'piplPlanExtn', 'piplFcltyExtn', 'piplSupprt', + 'targetYr', 'swrgPipeMntnPlanExtn', 'swrgPipePlanExtn', 'swrgPipeFcltyExtn', 'swrgPipePsplyRt', { name: 'combinedGroup', header: { text: '합류식(m)' }, - items: ['cmbnPlanAr', 'cmbnImprmnPlanExtn', 'cmbnPlanExtn', 'cmbnFcltyExtn', + items: ['cmbnMntnPlanAr', 'cmbnMntnPlanExtn', 'cmbnPlanExtn', 'cmbnFcltyExtn', { name: 'cmbnAmGroup', header: { text: '암거' }, items: ['cmbnRctglExtn', 'cmbnCicleExtn'] }, 'cmbnOpswrExtn', 'cmbnSdgttrExtn' ], @@ -168,20 +154,20 @@ const rawList = [ items: [ { name: 'foulPipeGroup', header: { text: '오수관로' }, - items: ['pltwtrPlanAr', 'pltwtrImprmnPlanExtn', 'pltwtrPlanExtn', 'pltwtrFlctyExtn', - { name: 'foulAmGroup', header: { text: '암거' }, items: ['pltwtrSqreExtn', 'pltwtrCiclExtn'] }] + items: ['pltwtrMntnPlanAr', 'pltwtrMntnPlanExtn', 'pltwtrPlanExtn', 'pltwtrFcltyExtn', + { name: 'foulAmGroup', header: { text: '암거' }, items: ['pltwtrRctglExtn', 'pltwtrCicleExtn'] }] }, { name: 'rainPipeGroup', header: { text: '우수관로' }, - items: ['rainwtrPlanAr', 'rainwtrImprmnPlanExtn', 'rainwtrPlanExtn', 'rainwtrFlctyExtn', - { name: 'rainAmGroup', header: { text: '암거' }, items: ['rainwtrSqreExtn', 'rainwtrCiclExtn'] }, + items: ['rainwtrMntnPlanAr', 'rainwtrMntnPlanExtn', 'rainwtrPlanExtn', 'rainwtrFcltyExtn', + { name: 'rainAmGroup', header: { text: '암거' }, items: ['rainwtrRctglExtn', 'rainwtrCicleExtn'] }, 'rainwtrOpswrExtn', 'rainwtrSdgttrExtn'] } ], }, - 'mnhleSite', - { name: 'fcltyGroup', header: { text: '부속시설(개소)' }, items: ['pltwtrMnhleSite', 'rainwtrMnhleSite'] }, - 'pltwtrRcvrSite', 'rainwtrRcvrSite', 'soilspllSite', 'soilholeSite', 'sewerRegstrCmptExtn', 'sewerRegstrCmptRt', 'rmk' + 'cmbnMnhleCnt', + { name: 'fcltyGroup', header: { text: '부속시설(개소)' }, items: ['pltwtrMnhleCnt', 'rainwtrMnhleCnt'] }, + 'pltwtrRcvrCnt', 'rainwtrRcvrCnt', 'rainwtrChmbrCnt', 'rainwtrOutltCnt', 'swrgRegstrCmptExtn', 'swrgRegstrCmptRt', 'rmrk' ] }, { diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index 9fae80f45..bd49adc1c 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -10,10 +10,12 @@ import { type SewerageSupplyRateReviewApiResponse, } from "../model/statistics-sewerage-penetration-review-interface"; import { + type SewagePipeReviewRequestParams, type SewagePipeReviewRegionalApiResponse , type SewagePipeFacilityApiResponse, type SewerPipeTypeApiResponse, - type SewerPipeDiamApiResponse + type SewerPipeDiamApiResponse, + type SewagePipeReviewService } from "../model/statistics-sewage-pipe-review-interface"; import { type SewerPipeMtcApiResponse, @@ -74,12 +76,7 @@ export class StatisticsManagementApiService { * @param params (sido, gugun, yr, bsnmCd) */ public async getSewagePipeReviewRegionalList( - params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - } + params: SewagePipeReviewRequestParams ): Promise { const response = await axios.get( `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe/regional-status`, @@ -87,6 +84,7 @@ export class StatisticsManagementApiService { ); return response.data; } + /** * 02. 하수관로 시설별 설치현황 목록 조회 (Tab2) * @param params (sido, gugun, yr, bsnmCd) diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts index 9aefdbd5b..ce3828a22 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts @@ -4,84 +4,87 @@ import type { ApiResponse } from "./statistics-interface"; * 02. 하수관로 tab1.지역별 시설현황 아이템 인터페이스 (Tab1) */ export interface SewagePipeReviewrRegionalItem { - // 기본 정보 및 행 제어 - sido: string; // 시도 - gugun: string; // 시군구 - adstDong: string; // 행정구역명 - adstCd: string; // 행정코드 - yr: string; // 연도 - rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 - displayYear: string; // 구분 표시용 (2024년확정 등) - // 하수정비 기본계획 - targetYr: number; // 하수정보기본계획목표년도 - piplImprmnPlanExtn: number; // 총관로정비 계획연장(m) - piplPlanExtn: number; // 총계획연장(m) - piplFcltyExtn: number; // 총시설연장(m) - piplSupprt: number; // 하수관로 보급률(%) +/* --- 기본 정보 및 행 제어 --- */ + ctpvNm: string; // 시도명 + sggNm: string; // 시군구명 + admdstNm: string; // 행정구역명 + admdstCd: string; // 행정구역코드 + statsYr: string; // 통계 연도 + rowType: 'OLD' | 'CURR'; // 데이터 구분 (OLD: 확정분, CURR: 당해년도) + displayYear: string; // 화면 표시용 연도 - // 합류식 (CMBN) - cmbnPlanAr: number; // 관로정비 계획면적(㎢) - cmbnImprmnPlanExtn: number; // 관로정비 계획연장(m) - cmbnPlanExtn: number; // 계획연장(m) - cmbnFcltyExtn: number; // 시설연장(m) - cmbnRctglExtn: number; // 사각형(m) - cmbnCicleExtn: number; // 원형(m) - cmbnOpswrExtn: number; // 개거(m) - cmbnSdgttrExtn: number; // 측구(m) + /* --- 하수정비 기본계획 --- */ + targetYr: number; // 하수정보기본계획 목표년도 + swrgPipeMntnPlanExtn: number; // 총 관로정비 계획연장(m) + swrgPipePlanExtn: number; // 총 계획연장(m) + swrgPipeFcltyExtn: number; // 총 시설연장(m) + swrgPipePsplyRt: number; // 하수관로 보급률(%) - // 분류식 - 오수관로 (PLTWTR) - pltwtrPlanAr: number; // 관로정비 계획면적(㎢) - pltwtrImprmnPlanExtn: number; // 관로정비 계획연장(m) - pltwtrPlanExtn: number; // 계획연장(m) - pltwtrFlctyExtn: number; // 시설연장(m) - pltwtrSqreExtn: number; // 사각형(m) - pltwtrCiclExtn: number; // 원형(m) + /* --- 합류식 (Combined System) --- */ + cmbnMntnPlanAr: number; // 관로정비 계획면적(㎢) + cmbnMntnPlanExtn: number; // 관로정비 계획연장(m) + cmbnPlanExtn: number; // 계획연장(m) + cmbnFcltyExtn: number; // 시설연장(m) + cmbnRctglExtn: number; // 사각형 암거 연장(m) + cmbnCicleExtn: number; // 원형 암거 연장(m) + cmbnOpswrExtn: number; // 개거 연장(m) + cmbnSdgttrExtn: number; // 측구 연장(m) - // 분류식 - 우수관로 (RAINWTR) - rainwtrPlanAr: number; // 관로정비 계획면적(㎢) - rainwtrImprmnPlanExtn: number; // 관로정비 계획연장(m) - rainwtrPlanExtn: number; // 계획연장(m) - rainwtrFlctyExtn: number; // 시설연장(m) - rainwtrSqreExtn: number; // 사각형(m) - rainwtrCiclExtn: number; // 원형(m) - rainwtrOpswrExtn: number; // 개거(m) - rainwtrSdgttrExtn: number; // 측구(m) + /* --- 분류식 - 오수관로 (Foul Water Pipe) --- */ + pltwtrMntnPlanAr: number; // 관로정비 계획면적(㎢) + pltwtrMntnPlanExtn: number; // 관로정비 계획연장(m) + pltwtrPlanExtn: number; // 계획연장(m) + pltwtrFcltyExtn: number; // 시설연장(m) + pltwtrRctglExtn: number; // 사각형 암거 연장(m) + pltwtrCicleExtn: number; // 원형 암거 연장(m) - // 부속시설 (개소) - mnhleSite: number; // 합류식맨홀 - pltwtrMnhleSite: number; // 오수맨홀 - rainwtrMnhleSite: number; // 우수맨홀 - pltwtrRcvrSite: number; // 오수받이 - rainwtrRcvrSite: number; // 빗물받이 - soilspllSite: number; // 우수토실 - soilholeSite: number; // 우수토구 + /* --- 분류식 - 우수관로 (Rain Water Pipe) --- */ + rainwtrMntnPlanAr: number; // 관로정비 계획면적(㎢) + rainwtrMntnPlanExtn: number; // 관로정비 계획연장(m) + rainwtrPlanExtn: number; // 계획연장(m) + rainwtrFcltyExtn: number; // 시설연장(m) + rainwtrRctglExtn: number; // 사각형 암거 연장(m) + rainwtrCicleExtn: number; // 원형 암거 연장(m) + rainwtrOpswrExtn: number; // 개거 연장(m) + rainwtrSdgttrExtn: number; // 측구 연장(m) + + /* --- 부속시설 (개소) --- */ + cmbnMnhleCnt: number; // 합류식 맨홀 수 + pltwtrMnhleCnt: number; // 오수 맨홀 수 + rainwtrMnhleCnt: number; // 우수 맨홀 수 + pltwtrRcvrCnt: number; // 오수받이 수 + rainwtrRcvrCnt: number; // 우수받이(빗물받이) 수 + rainwtrChmbrCnt: number; // 우수토실 수 + rainwtrOutltCnt: number; // 우수토구 수 + + /* --- 대장 및 기타 --- */ + swrgRegstrCmptExtn: number; // 하수도대장 전산화 연장(m) + swrgRegstrCmptRt: number; // 하수도대장 전산화율(%) + rmrk: string; // 비고 - // 대장 및 기타 - sewerRegstrCmptExtn: number; // 하수도대장 전산화연장(m) - sewerRegstrCmptRt: number; // 하수도대장 전산화율(%) - rmk: string; // 비고 } export interface SewagePipeReviewResponseData { sewagePipeList: SewagePipeReviewrRegionalItem[]; } +export interface SewagePipeReviewRequestParams { + ctpvNm?: string; // 시도명 + sggNm?: string; // 시군구명 + statsYr?: string; // 통계 연도 + sewerBzmnCd?: string; // 하수도사업자 코드 +} export type SewagePipeReviewRegionalApiResponse = ApiResponse & { message: string; }; export interface SewagePipeReviewService { - - getSewagePipeReviewList(params: { - yr?: string; // 조회 연도 - bsnmCd?: string; // 사업장 코드 - sido?: string; // 시도 - gugun?: string; // 구군 - }): Promise; + getSewagePipeReviewRegionalList(params: SewagePipeReviewRequestParams): Promise; } + /** * 02. 하수관로 시설별 시설현황 (Tab 2) * From f402961de7a41d99d0f7d3a293026aced47e35b3 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Tue, 24 Feb 2026 17:19:16 +0900 Subject: [PATCH 12/14] =?UTF-8?q?refactor:=2002.=ED=95=98=EC=88=98?= =?UTF-8?q?=EA=B4=80=EB=A1=9C=20tab2.=EC=8B=9C=EC=84=A4=EB=B3=84=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98=ED=98=84=ED=99=A9=20=ED=91=9C=EC=A4=80?= =?UTF-8?q?=ED=99=94=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=A7=A4=ED=95=91=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/review/SewagePipeRvw.tsx | 49 +++++---- .../util/column/review/SewagePipeRvwColumn.ts | 104 +++++++----------- .../api/statistics-management-service.ts | 7 +- ...statistics-sewage-pipe-review-interface.ts | 75 ++++++------- 4 files changed, 99 insertions(+), 136 deletions(-) diff --git a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx index 2c68978bd..157fd87fd 100644 --- a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx @@ -89,34 +89,35 @@ const SewagePipeRvw = () => { if (hasAData && !hasActiveTabData && searchParamRef.current) { - // try { - // setIsLoading(true); + try { + setIsLoading(true); - // let response; + let response; - // if (tabKey === 'ST00020002') { - // response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current); - // }else if(tabKey === 'ST00020003'){ - // response = await statisticsManagementApi.getSewagePipeTypeList(searchParamRef.current); - // }else if(tabKey === 'ST00020004'){ - // response = await statisticsManagementApi.getSewagePipeDiamList(searchParamRef.current); - // } + if (tabKey === 'ST00020002') { + response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current); + } + // }else if(tabKey === 'ST00020003'){ + // response = await statisticsManagementApi.getSewagePipeTypeList(searchParamRef.current); + // }else if(tabKey === 'ST00020004'){ + // response = await statisticsManagementApi.getSewagePipeDiamList(searchParamRef.current); + // } - // if (response?.status === 'success' && response.data) { + if (response?.status === 'success' && response.data) { - // setRowDataMap(prev => { - // const next = new Map(prev); - // next.set(tabKey, toGridRows(response.data as object[])); - // return next; - // }); - // } else { - // alert(response?.message || "데이터가 없습니다."); - // } - // } catch { - // alert('데이터 조회 중 오류가 발생했습니다.'); - // } finally { - // setIsLoading(false); - // } + setRowDataMap(prev => { + const next = new Map(prev); + next.set(tabKey, toGridRows(response.data as object[])); + return next; + }); + } else { + alert(response?.message || "데이터가 없습니다."); + } + } catch { + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } } }; diff --git a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts index 9ae786be8..db5034cb3 100644 --- a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts @@ -170,15 +170,15 @@ const rawList = [ 'pltwtrRcvrCnt', 'rainwtrRcvrCnt', 'rainwtrChmbrCnt', 'rainwtrOutltCnt', 'swrgRegstrCmptExtn', 'swrgRegstrCmptRt', 'rmrk' ] }, - { + { tabKey: 'ST00020002', tabLabel: '시설별 설치현황', rowStartNum: 4, fixedColumns: 3, columns: [ { - name: 'sido', - fieldName: 'sido', + name: 'ctpvNm', + fieldName: 'ctpvNm', header: { text: '시도' }, mergeCells: true, sortdisable: true, @@ -196,7 +196,7 @@ const rawList = [ } } const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; } }, { @@ -212,13 +212,13 @@ const rawList = [ } } const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; } } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, - { name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '하수처리장명' },mergeCells: true }, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'swrmtFcltyNm', fieldName: 'swrmtFcltyNm', header: { text: '하수처리시설 명칭' }, mergeCells: true }, { name: 'displayYear', fieldName: 'displayYear', @@ -229,108 +229,84 @@ const rawList = [ valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { const divisionIndex = 0; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } - const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[divisionIndex] + ' 합계' : ''; } }, { valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { const divisionIndex = 1; const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + for (let i = 0; i < dataSource.getRowCount(); i++) { + const val = dataSource.getValue(i, 'displayYear'); + if (val) uniqueValues.add(String(val)); } - const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[divisionIndex] + ' 합계' : ''; } } ] }, - { name: 'fctCpc', fieldName: 'fctCpc', header: { text: '하수처리\n시설용량\n(㎥/일)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - - /* 처리구역면적(㎢) */ - { name: 'procZoneSm', fieldName: 'procZoneSm', header: { text: '합계' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'swrmtFcltyCpc', fieldName: 'swrmtFcltyCpc', header: { text: '하수처리\n시설용량\n(㎥/일)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'procZoneArSm', fieldName: 'procZoneArSm', header: { text: '합계' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, { name: 'cmbnProcZoneAr', fieldName: 'cmbnProcZoneAr', header: { text: '합류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, - { name: 'sprtProcZoneAr', fieldName: 'sprtProcZoneAr', header: { text: '분류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, - { name: 'sepRate', fieldName: 'sepRate', header: { text: '분류식화(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - - /* 배수설비(개소) */ + { name: 'sprsysProcZoneAr', fieldName: 'sprsysProcZoneAr', header: { text: '분류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, { name: 'drngEqpSm', fieldName: 'drngEqpSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, { name: 'cmbnDrngEqp', fieldName: 'cmbnDrngEqp', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'sprtDrngEqpSm', fieldName: 'sprtDrngEqpSm', header: { text: '합계(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'sprtDrngEqpCnnc', fieldName: 'sprtDrngEqpCnnc', header: { text: '연결' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'sprtDrngEqpDcnnc', fieldName: 'sprtDrngEqpDcnnc', header: { text: '미연결' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - - /* 하수관로 */ - { name: 'piplFcltyExtn', fieldName: 'piplFcltyExtn', header: { text: '총\n시설연장\n(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'icgMnnSm', fieldName: 'icgMnnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'sprsysDrngEqpSm', fieldName: 'sprsysDrngEqpSm', header: { text: '분류식 합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'swrgPipeFcltyExtn', fieldName: 'swrgPipeFcltyExtn', header: { text: '총\n시설연장\n(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'icgPltwtrMnnSm', fieldName: 'icgPltwtrMnnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'icgExtn', fieldName: 'icgExtn', header: { text: '차집' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'mnnExtn', fieldName: 'mnnExtn', header: { text: '오수간선' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - - /* 토실/토구(개소) */ - { name: 'cmbnSoilholeSite', fieldName: 'cmbnSoilholeSite', header: { text: '우수토실(합류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'sprtSoilholeSite', fieldName: 'sprtSoilholeSite', header: { text: '우수토실(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'sprtSoilspllSite', fieldName: 'sprtSoilspllSite', header: { text: '우수토구(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - - /* 지선(m) */ + { name: 'pltwtrMnnExtn', fieldName: 'pltwtrMnnExtn', header: { text: '오수간선' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cmbnRainwtrChmbrCnt', fieldName: 'cmbnRainwtrChmbrCnt', header: { text: '우수토실(합류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysRainwtrChmbrCnt', fieldName: 'sprsysRainwtrChmbrCnt', header: { text: '우수토실(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysRainwtrOutltCnt', fieldName: 'sprsysRainwtrOutltCnt', header: { text: '우수토구(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, { name: 'brnchlnSm', fieldName: 'brnchlnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, { name: 'cmbnBrnchlnExtn', fieldName: 'cmbnBrnchlnExtn', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'rainwtrBrnchlnExtn', fieldName: 'rainwtrBrnchlnExtn', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'pltwtrBrnchlnExtn', fieldName: 'pltwtrBrnchlnExtn', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - - { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + { name: 'sprsysExlnBrnchlnExtn', fieldName: 'sprsysExlnBrnchlnExtn', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'sprsysDrtwBrnchlnExtn', fieldName: 'sprsysDrtwBrnchlnExtn', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, ], columnLayout: [ { name: 'addrGroup', header: { text: '행정구역' }, items: [ - { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, - 'gugun', - 'bscFctNm', + { column: 'ctpvNm', footerUserSpans: [{ colspan: 3 }, { colspan: 3 }] }, + 'sggNm', + 'swrmtFcltyNm', ] }, - - 'fctCpc', + 'swrmtFcltyCpc', 'displayYear', - { name: 'areaGroup', header: { text: '처리구역면적(㎢)' }, items: ['procZoneSm', 'cmbnProcZoneAr', 'sprtProcZoneAr'] }, - 'sepRate', + { name: 'areaGroup', header: { text: '처리구역면적(㎢)' }, items: ['procZoneArSm', 'cmbnProcZoneAr', 'sprsysProcZoneAr'] }, { name: 'drainGroup', header: { text: '배수설비(개소)' }, - items: ['drngEqpSm', 'cmbnDrngEqp', { name: 'sepDrainGroup', header: { text: '분류식' }, items: ['sprtDrngEqpSm', 'sprtDrngEqpCnnc', 'sprtDrngEqpDcnnc'] }], + items: ['drngEqpSm', 'cmbnDrngEqp', 'sprsysDrngEqpSm'], }, { name: 'pipeGroup', header: { text: '하수관로' }, items: [ - 'piplFcltyExtn', - { name: 'trunkGroup', header: { text: '차집/오수간선(m)' }, items: ['icgMnnSm', 'icgExtn', 'mnnExtn'] }, + 'swrgPipeFcltyExtn', + { name: 'trunkGroup', header: { text: '차집/오수간선(m)' }, items: ['icgPltwtrMnnSm', 'icgExtn', 'pltwtrMnnExtn'] }, { name: 'siteGroup', header: { text: '토실/토구(개소)' }, items: [ - { name: 'cmbnSiteGroup', header: { text: '합류식' }, items: ['cmbnSoilholeSite'] }, - { name: 'sepSiteGroup', header: { text: '분류식' }, items: ['sprtSoilholeSite', 'sprtSoilspllSite'] } + { name: 'cmbnSiteGroup', header: { text: '합류식' }, items: ['cmbnRainwtrChmbrCnt'] }, + { name: 'sepSiteGroup', header: { text: '분류식' }, items: ['sprsysRainwtrChmbrCnt', 'sprsysRainwtrOutltCnt'] } ] }, { name: 'branchGroup', header: { text: '지선(m)' }, - items: ['brnchlnSm', 'cmbnBrnchlnExtn', { name: 'sepBranchGroup', header: { text: '우수/오수' }, items: ['rainwtrBrnchlnExtn', 'pltwtrBrnchlnExtn'] }] + items: ['brnchlnSm', 'cmbnBrnchlnExtn', { name: 'sepBranchGroup', header: { text: '우수/오수' }, items: ['sprsysExlnBrnchlnExtn', 'sprsysDrtwBrnchlnExtn'] }] } ], }, - 'rmk' + 'rmrk' ] }, { diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index bd49adc1c..d514fd576 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -90,12 +90,7 @@ export class StatisticsManagementApiService { * @param params (sido, gugun, yr, bsnmCd) */ public async getSewagePipeFacilityList( - params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - } + params: SewagePipeReviewRequestParams ): Promise { const response = await axios.get( `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe/facility-status`, diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts index ce3828a22..3d97ec558 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts @@ -84,56 +84,52 @@ export interface SewagePipeReviewService { getSewagePipeReviewRegionalList(params: SewagePipeReviewRequestParams): Promise; } - /** - * 02. 하수관로 시설별 시설현황 (Tab 2) - * + * 02. 하수관로 시설별 설치현황 데이터 항목 (Tab 2) */ export interface SewagePipeReviewFacilityItem { // 1. 행정구역 및 기본 정보 - sido: string; // 시도 - gugun: string; // 시군구 - adstCd: string; // 행정코드 - adstDong: string; // 행정구역명 - yr: string; // 연도 - rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 - displayYear: string; // 구분 표시용 (2024년확정 등) + ctpvNm: string; // 시도명 + sggNm: string; // 시군구명 + admdstCd: string; // 행정구역코드 + admdstNm: string; // 행정구역명 + statsYr: string; // 통계연도 + rowType: 'OLD' | 'CURR'; // 데이터 구분 (OLD: 확정, CURR: 당해년도) + displayYear: string; // 화면 표시용 연도 // 2. 시설 정보 - bscFctNm: string; // 하수처리장명 - fctCpc: number; // 하수처리시설용량(㎥/일) + swrmtFcltyNm: string; // 하수처리시설 명칭 + swrmtFcltyCpc: number; // 하수처리시설 용량(㎥/일) - // 3. 처리구역면적(㎢) - procZoneSm: number; // 합계(면적) - cmbnProcZoneAr: number; // 합류식(면적) - sprtProcZoneAr: number; // 분류식(면적) + // 3. 처리구역 면적(㎢) + procZoneArSm: number; // 처리구역 면적 합계 + cmbnProcZoneAr: number; // 합류식 처리구역 면적 + sprsysProcZoneAr: number; // 분류식 처리구역 면적 // 4. 배수설비(개소) - drngEqpSm: number; // 합계(배수) - cmbnDrngEqp: number; // 합류식(배수) - sprtDrngEqpSm: number; // 합계(분류배수) - sprtDrngEqpCnnc: number; // 연결 - sprtDrngEqpDcnnc: number; // 미연결 + drngEqpSm: number; // 배수설비 합계 + cmbnDrngEqp: number; // 합류식 배수설비 + sprsysDrngEqpSm: number; // 분류식 배수설비 합계 // 5. 하수관로 (m) - piplFcltyExtn: number; // 총 시설연장(m) - icgMnnSm: number; // 합계(차집/오수간선) - icgExtn: number; // 차집 - mnnExtn: number; // 오수간선 + swrgPipeFcltyExtn: number; // 총 시설연장 + icgPltwtrMnnSm: number; // 차집 및 오수간선 합계 + icgExtn: number; // 차집관로 연장 + pltwtrMnnExtn: number; // 오수간선 연장 - // 6. 토실/토구 (개소) - cmbnSoilholeSite: number; // 우수토실(합류) - sprtSoilholeSite: number; // 우수토실(분류) - sprtSoilspllSite: number; // 우수토구(분류) + // 6. 우수토실/토구 (개소) + cmbnRainwtrChmbrCnt: number; // 합류식 우수토실 + sprsysRainwtrChmbrCnt: number; // 분류식 우수토실 + sprsysRainwtrOutltCnt: number; // 분류식 우수토구 // 7. 지선 (m) - brnchlnSm: number; // 합계(지선) - cmbnBrnchlnExtn: number; // 합류식(지선) - rainwtrBrnchlnExtn: number; // 우수(지선) - pltwtrBrnchlnExtn: number; // 오수(지선) + brnchlnSm: number; // 지선 합계 + cmbnBrnchlnExtn: number; // 합류식 지선연장 + sprsysExlnBrnchlnExtn: number; // 분류식 우수지선연장 + sprsysDrtwBrnchlnExtn: number; // 분류식 오수지선연장 // 비고 - rmk: string; // 비고 + rmrk: string | null; // 비고 } @@ -141,19 +137,14 @@ export interface SewagePipeFacilityResponseData { facilityPipeList: SewagePipeReviewFacilityItem[]; } -export type SewagePipeFacilityApiResponse = ApiResponse & { + +export type SewagePipeFacilityApiResponse = ApiResponse & { message: string; }; export interface SewagePipeFacilityService { - - getSewagePipeFacilityList(params: { - yr?: string; // 조회 연도 - bsnmCd?: string; // 사업장 코드 - sido?: string; // 시도 - gugun?: string; // 구군 - }): Promise; + getSewagePipeFacilityList(params: SewagePipeReviewRequestParams): Promise; } /** From 1a5b000b02f01bb7aa97ff825f979e30a04496a7 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Wed, 25 Feb 2026 13:34:56 +0900 Subject: [PATCH 13/14] =?UTF-8?q?03.=ED=95=98=EC=88=98=EA=B4=80=EB=A1=9C?= =?UTF-8?q?=20=EC=9C=A0=EC=A7=80=EA=B4=80=EB=A6=AC=20tab1.=20=EA=B0=9C?= =?UTF-8?q?=EB=B3=B4=EC=88=98=20=ED=91=9C=EC=A4=80=ED=99=94=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/SewagePipeMaintainRvw.tsx | 18 +- .../review/SewagePipeMaintainRvwColumn.ts | 265 +++++++++--------- .../api/statistics-management-service.ts | 20 +- ...istics-sewage-pipe-mtc-review-interface.ts | 70 ++--- 4 files changed, 183 insertions(+), 190 deletions(-) diff --git a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx index 272ae04f1..59d001a2a 100644 --- a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx @@ -13,6 +13,8 @@ import { SewagePipeMaintainColumnInfoList } from "@/components/util/column/revie import type { ColumnInfoList, ColumnConfig } from "@/components/type/DataGrid.type"; import type { SearchFormValues } from "@/components/type/SearchForm.type"; import { toGridRows } from "@/components/util/grid/gridFunction"; +import type { SewerPipeMtcRequestParams } from "@/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface"; + // 하수도 통계 검토 03. 하수관로 유지 관리 const SewagePipeMaintainRvw = () => { @@ -21,7 +23,7 @@ const SewagePipeMaintainRvw = () => { const [isLoading, setIsLoading] = useState(false); const [activeTab, setActiveTab] = useState('ST00030001'); - const searchParamRef = useRef(null); + const searchParamRef = useRef(null); const columnInfo = useMemo(() => { return SewagePipeMaintainColumnInfoList.map((tab: ColumnInfoList) => ({ @@ -52,12 +54,12 @@ const SewagePipeMaintainRvw = () => { try { setIsLoading(true); - const searchParam = { - sido: values.sido, - gugun: values.gugun === 'ALL' ? '' : values.gugun, - bsnmCd: values.bsnmCd, - yr: values.year, - }; + const searchParam: SewerPipeMtcRequestParams = { + statsYr: values.year, + sewerBzmnCd: values.bsnmCd, + ctpvNm: values.sido, + sggNm: values.gugun === 'ALL' ? '' : values.gugun + }; searchParamRef.current = searchParam; const response = await statisticsManagementApi.getSewerPipeMtcList(searchParam); @@ -99,7 +101,7 @@ const SewagePipeMaintainRvw = () => { if (tabKey === 'ST00030001') { response = await statisticsManagementApi.getSewerPipeMtcList(searchParamRef.current); }else if (tabKey === 'ST00030002') { - response = await statisticsManagementApi.getSewerPipeDrdgList(searchParamRef.current); + // response = await statisticsManagementApi.getSewerPipeDrdgList(searchParamRef.current); } if (response?.status === 'success' && response.data) { diff --git a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts index aaf2bed67..a9433e643 100644 --- a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts @@ -5,152 +5,143 @@ import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataG // 하수도 통계 관리 03. 하수관로 유지 관리 const rawMaintainList = [ { - tabKey: 'ST00030001', - tabLabel: '개보수', - rowStartNum: 4, - fixedColumns: 2, - columns: [ - /* 1. 행정구역 (시도) */ - { - name: 'sido', - fieldName: 'sido', - header: { text: '시도' }, - mergeCells: true, - tdisable: true, - footer: [ - { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { - const divisionIndex = 0; - const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); - const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + tabKey: 'ST00030001', + tabLabel: '개보수', + rowStartNum: 4, + fixedColumns: 2, + columns: [ + { + name: 'ctpvNm', + fieldName: 'ctpvNm', + header: { text: '시도' }, + mergeCells: true, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); } - const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; - } - }, - { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { - const divisionIndex = 1; - const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); - const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } - } - const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; } - ] - }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, - - /* 2. 구분 (displayYear) */ - { - name: 'displayYear', - fieldName: 'displayYear', - header: { text: '구분' }, - sortdisable: true, - footer: [ - { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { - const divisionIndex = 0; - const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); - const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); } - const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; } - }, - { - valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { - const divisionIndex = 1; - const dataSource = grid.getDataSource(); - const rowCount = dataSource.getRowCount(); - const uniqueValues = new Set(); - for (let i = 0; i < rowCount; i++) { - const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; + } + } + ] + }, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); } - const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; } - ] - }, - - /* 3. 전체보수 (m) - 소수점 1자리 합계 */ - { name: 'rpairPipeSm', fieldName: 'rpairPipeSm', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'rpairCmbnPipe', fieldName: 'rpairCmbnPipe', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'rpairRainwtrPipe', fieldName: 'rpairRainwtrPipe', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'rpairPltwtrPipe', fieldName: 'rpairPltwtrPipe', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - - /* 4. 부분보수 (개소) - 정수 합계 */ - { name: 'rpairPipeSm2', fieldName: 'rpairPipeSm2', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'rpairCmbnPipe2', fieldName: 'rpairCmbnPipe2', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'rpairRainwtrPipe2', fieldName: 'rpairRainwtrPipe2', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'rpairPltwtrPipe2', fieldName: 'rpairPltwtrPipe2', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - - /* 5. 부속시설 (개소) - 정수 합계 */ - { name: 'mnhleSite', fieldName: 'mnhleSite', header: { text: '합류식\n맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'pltwtrMnhleSite', fieldName: 'pltwtrMnhleSite', header: { text: '오수맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'rainwtrMnhleSite', fieldName: 'rainwtrMnhleSite', header: { text: '우수맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'pltwtrRcvrSite', fieldName: 'pltwtrRcvrSite', header: { text: '오수받이' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'rainwtrRcvrSite', fieldName: 'rainwtrRcvrSite', header: { text: '빗물받이' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'soilspllSite', fieldName: 'soilspllSite', header: { text: '토실' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - { name: 'soilholeSite', fieldName: 'soilholeSite', header: { text: '토구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - - /* 6. 조사량 및 비고 */ - { name: 'cctv', fieldName: 'cctv', header: { text: '수밀검사·\nCCTV조사량\n(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, - ], - columnLayout: [ - { - name: 'addrGroup', - header: { text: '행정구역' }, - items: [ - { column: 'sido', footerUserSpans: [{ colspan: 3 }, { colspan: 3 }] }, - 'gugun' - ] - }, - 'displayYear', - { - name: 'mtcPipeGroup', header: { text: '개·보수관로' }, - items: [ - { - name: 'totalRepairGroup', header: { text: '전체보수(m)' }, - items: ['rpairPipeSm', 'rpairCmbnPipe', { name: 'sepTotalGroup', header: { text: '분류식' }, items: ['rpairRainwtrPipe', 'rpairPltwtrPipe'] }] - }, - { - name: 'partRepairGroup', header: { text: '부분보수(개소)' }, - items: ['rpairPipeSm2', 'rpairCmbnPipe2', { name: 'sepPartGroup', header: { text: '분류식' }, items: ['rpairRainwtrPipe2', 'rpairPltwtrPipe2'] }] + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; } - ] - }, - 'mnhleSite', - { name: 'sepMnhleGroup', header: { text: '분류식' }, items: ['pltwtrMnhleSite', 'rainwtrMnhleSite'] }, - 'pltwtrRcvrSite', 'rainwtrRcvrSite', - { name: 'soilGroup', header: { text: '토실·토구(개소)' }, items: ['soilspllSite', 'soilholeSite'] }, - 'cctv', 'rmk' - ] - }, + } + ] + }, + { name: 'mendngWhol', fieldName: 'mendngWhol', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'cbsysMendngPrlg', fieldName: 'cbsysMendngPrlg', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'sprsysExlnPrlg', fieldName: 'sprsysExlnPrlg', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'sprsysDrtwPrlg', fieldName: 'sprsysDrtwPrlg', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'partMendngWhol', fieldName: 'partMendngWhol', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'cbsysPartMendngPrlg', fieldName: 'cbsysPartMendngPrlg', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysExlnMendngPrlg', fieldName: 'sprsysExlnMendngPrlg', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysDrtwMendngPrlg', fieldName: 'sprsysDrtwMendngPrlg', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'cbsysMnhlCnt', fieldName: 'cbsysMnhlCnt', header: { text: '합류식\n맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysDrtwMnhlCnt', fieldName: 'sprsysDrtwMnhlCnt', header: { text: '오수맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysExlnMnhlCnt', fieldName: 'sprsysExlnMnhlCnt', header: { text: '우수맨홀' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'drtwRcvprpCnt', fieldName: 'drtwRcvprpCnt', header: { text: '오수받이' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'exlnRcvprpCnt', fieldName: 'exlnRcvprpCnt', header: { text: '빗물받이' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'stofcbrCnt', fieldName: 'stofcbrCnt', header: { text: '토실' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'otflCnt', fieldName: 'otflCnt', header: { text: '토구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'cctvExmnPrlg', fieldName: 'cctvExmnPrlg', header: { text: '수밀검사·\nCCTV조사량\n(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'addrGroup', + header: { text: '행정구역' }, + items: [ + { column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }, { colspan: 2 }] }, + 'sggNm', + 'admdstNm', + ] + }, + 'displayYear', + { + name: 'mtcPipeGroup', header: { text: '개·보수관로' }, + items: [ + { + name: 'totalRepairGroup', header: { text: '전체보수(m)' }, + items: ['mendngWhol', 'cbsysMendngPrlg', { name: 'sepTotalGroup', header: { text: '분류식' }, items: ['sprsysExlnPrlg', 'sprsysDrtwPrlg'] }] + }, + { + name: 'partRepairGroup', header: { text: '부분보수(개소)' }, + items: ['partMendngWhol', 'cbsysPartMendngPrlg', { name: 'sepPartGroup', header: { text: '분류식' }, items: ['sprsysExlnMendngPrlg', 'sprsysDrtwMendngPrlg'] }] + } + ] + }, + 'cbsysMnhlCnt', + { name: 'sepMnhleGroup', header: { text: '분류식' }, items: ['sprsysDrtwMnhlCnt', 'sprsysExlnMnhlCnt'] }, + 'drtwRcvprpCnt', 'exlnRcvprpCnt', + { name: 'soilGroup', header: { text: '토실·토구(개소)' }, items: ['stofcbrCnt', 'otflCnt'] }, + 'cctvExmnPrlg', 'rmrk' + ] + }, { tabKey: 'ST00030002', tabLabel: '관로준설', diff --git a/apps/st/src/entities/statistics/api/statistics-management-service.ts b/apps/st/src/entities/statistics/api/statistics-management-service.ts index d514fd576..0e67b89fe 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -19,7 +19,8 @@ import { } from "../model/statistics-sewage-pipe-review-interface"; import { type SewerPipeMtcApiResponse, - type SewerPipeDrdgApiResponse + type SewerPipeDrdgApiResponse, + type SewerPipeMtcRequestParams } from "../model/statistics-sewage-pipe-mtc-review-interface"; import { type SewerReservoirRegionalApiResponse, @@ -138,17 +139,12 @@ export class StatisticsManagementApiService { } /** - * 03. 하수관로 유지관리 개보수 현황 조회 - * @param params (yr, bsnmCd, sido, gugun) - */ -public async getSewerPipeMtcList( - params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - } -): Promise { + * 03. 하수관로 유지관리 개보수 현황 조회 + * @param params (yr, bsnmCd, sido, gugun) + */ + public async getSewerPipeMtcList( + params: SewerPipeMtcRequestParams + ): Promise { const response = await axios.get( `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe-mtc/repair`, { params } diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts index eb47c2de7..0281e43bc 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-mtc-review-interface.ts @@ -3,48 +3,52 @@ import type { ApiResponse } from "./statistics-interface"; /** * 03. 하수관로 유지관리 개보수 아이템 */ + export interface SewerPipeMtcItem { - // 1. 행정구역 및 기본정보 - sido: string; // 시도 - gugun: string; // 시군구 - adstCd: string; // 행정코드 - adstDong?: string; // 행정동 - yr: string; // 실제 연도 - displayYear: string; // 화면 표시용 (예: 2023년확정) - rowType: 'OLD' | 'CURR'; // OLD / CURR 구분 - - // 2. 개보수 관로 - 전체보수(m) - rpairPipeSm: number; // 계 - rpairCmbnPipe: number; // 합류식 - rpairRainwtrPipe: number; // 분류식-우수 - rpairPltwtrPipe: number; // 분류식-오수 - - // 3. 개보수 관로 - 부분보수(개소) - rpairPipeSm2: number; // 계 - rpairCmbnPipe2: number; // 합류식 - rpairRainwtrPipe2: number; // 분류식-우수 - rpairPltwtrPipe2: number; // 분류식-오수 - - // 4. 부속 시설물 (개소/m) - mnhleSite: number; // 합류식 맨홀 - pltwtrMnhleSite: number; // 오수 맨홀 (분류식) - rainwtrMnhleSite: number; // 우수 맨홀 (분류식) - pltwtrRcvrSite: number; // 오수받이 - rainwtrRcvrSite: number; // 빗물받이 - soilspllSite: number; // 토실 - soilholeSite: number; // 토구 - cctv: number; // CCTV 조사량 (m) - - // 5. 기타 및 상태값 - rmk: string; // 비고 + ctpvNm: string; + sggNm: string; + statsYr: string; + rowType: 'OLD' | 'CURR'; + displayYear: string; + sewerBzmnCd: string; + admdstNm:string; + mendngWhol: number; + cbsysMendngPrlg: number; + sprsysDrtwPrlg: number; + sprsysExlnPrlg: number; + partMendngWhol: number; + cbsysPartMendngPrlg: number; + sprsysDrtwMendngPrlg: number; + sprsysExlnMendngPrlg: number; + cbsysMnhlCnt: number; + sprsysDrtwMnhlCnt: number; + sprsysExlnMnhlCnt: number; + exlnRcvprpCnt: number; + drtwRcvprpCnt: number; + stofcbrCnt: number; + otflCnt: number; + cctvExmnPrlg: number; + rmrk: string | null; } export interface SewerPipeMtcResponseData { mtcStatusList: SewerPipeMtcItem[]; } +export interface SewerPipeMtcRequestParams { + ctpvNm?: string; + sggNm?: string; + statsYr?: string; + sewerBzmnCd?: string; +} + export type SewerPipeMtcApiResponse = ApiResponse; +export interface SewagePipeMtcService { + getSewerPipeMtcYearlyStatus(params: SewerPipeMtcRequestParams): Promise; +} + + /** * 03. 하수관로 유지관리 관로준설 아이템 (Tab 2) */ From 2a473c85dbaf70e959fc1021d08712eefa8cce44 Mon Sep 17 00:00:00 2001 From: rsone001 Date: Wed, 25 Feb 2026 13:39:03 +0900 Subject: [PATCH 14/14] =?UTF-8?q?refactor:=2003.=ED=95=98=EC=88=98?= =?UTF-8?q?=EA=B4=80=EB=A1=9C=20=EC=9C=A0=EC=A7=80=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EC=8B=9C=EC=84=A4=EB=AA=85=20=EA=B2=80=EC=83=89=EC=B0=BD=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/statistics/review/SewagePipeMaintainRvw.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx index 59d001a2a..a841bc273 100644 --- a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx @@ -128,7 +128,7 @@ const SewagePipeMaintainRvw = () => { return (
- +