03.하수관로 유지관리 tab1. 개보수 표준화 데이터 조회

This commit is contained in:
2026-02-25 13:34:56 +09:00
parent f402961de7
commit 1a5b000b02
4 changed files with 183 additions and 190 deletions
@@ -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<boolean>(false);
const [activeTab, setActiveTab] = useState<string>('ST00030001');
const searchParamRef = useRef<SearchFormValues | null>(null);
const searchParamRef = useRef<SewerPipeMtcRequestParams | null>(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) {
@@ -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<string>();
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<string>();
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<string>();
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<string>();
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<string>();
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<string>();
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<string>();
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<string>();
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: '관로준설',
@@ -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<SewerPipeMtcApiResponse> {
* 03. 하수관로 유지관리 개보수 현황 조회
* @param params (yr, bsnmCd, sido, gugun)
*/
public async getSewerPipeMtcList(
params: SewerPipeMtcRequestParams
): Promise<SewerPipeMtcApiResponse> {
const response = await axios.get<SewerPipeMtcApiResponse>(
`${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe-mtc/repair`,
{ params }
@@ -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<SewerPipeMtcResponseData>;
export interface SewagePipeMtcService {
getSewerPipeMtcYearlyStatus(params: SewerPipeMtcRequestParams): Promise<SewerPipeMtcApiResponse>;
}
/**
* 03. 하수관로 유지관리 관로준설 아이템 (Tab 2)
*/