diff --git a/apps/st/app/(with-base-layout)/layout.tsx b/apps/st/app/(with-base-layout)/layout.tsx index 3fe61855e..98c126bf6 100644 --- a/apps/st/app/(with-base-layout)/layout.tsx +++ b/apps/st/app/(with-base-layout)/layout.tsx @@ -76,7 +76,7 @@ export default function WithBaseLayout({ // menuList에서 활성 탭의 메뉴 찾기 const findMenuByEngNm = (items: MenuItem[]): MenuItem | null => { for (const item of items) { - if (item.menuEngNm === activeTabId) { + if (item.urlPath === activeTabId) { return item; } if (item.children) { diff --git a/apps/st/src/components/module/TabDataGrid.tsx b/apps/st/src/components/module/TabDataGrid.tsx index aa36287ee..cbbe53a0c 100644 --- a/apps/st/src/components/module/TabDataGrid.tsx +++ b/apps/st/src/components/module/TabDataGrid.tsx @@ -92,20 +92,20 @@ function toNum(v: unknown): number { // } // } // } - + // if (!gridEl) return; - + // columns.forEach((col) => { // if (!col.fieldName && !col.name) return; - + // const fieldName = col.fieldName || col.name; // const direction = sortDir[fieldName] || sortDir[col.name] || "none"; // if (direction === "none") return; - + // // 헤더 셀 찾기 (fieldName 또는 name으로) // const headerCells = gridEl.querySelectorAll('.rg-header-cell, [class*="header"], .rg-header'); // let targetCell: HTMLElement | null = null; - + // headerCells.forEach((cell) => { // const el = cell as HTMLElement; // const text = el.textContent?.trim(); @@ -121,17 +121,17 @@ function toNum(v: unknown): number { // targetCell = el; // } // }); - + // if (!targetCell) return; - + // const headerCell = targetCell as HTMLElement; - + // // 기존 화살표 제거 // const existingIndicator = headerCell.querySelector(".rg-sort-indicator") as HTMLElement | null; // if (existingIndicator) { // existingIndicator.remove(); // } - + // // 화살표 추가 // const indicator = document.createElement("span"); // indicator.className = "rg-sort-indicator"; @@ -164,7 +164,7 @@ function createOnSortingHandler( const groupField = mergeCellCol?.fieldName || null; const orderByField = 'displayYear'; // 고정값 또는 설정 가능하게 할 수 있음 const hasMergeCells = mergeCellCols.length > 0; - + return function onSorting(g: unknown, fields: unknown[], _directions: unknown[]) { const grid = g as { getColumn?: (i: number) => { fieldName?: string; name?: string } | undefined; getDataSource?: () => { getRowCount(): number; getValue(r: number, f: string): unknown } }; const idx = fields?.[0]; @@ -178,10 +178,10 @@ function createOnSortingHandler( if (!sortField) return true; const col = columns.find((c) => (c.fieldName === sortField || c.name === sortField)); if (!col || col.sortdisable) return true; - + // mergeCells: true인 컬럼이 없으면 RealGrid 기본 정렬 사용 if (!hasMergeCells || !groupField) return true; - + const ds = grid.getDataSource?.(); if (!ds) return true; const cnt = ds.getRowCount(); @@ -229,7 +229,7 @@ function sortRowsGroupPreserving( if (!groups.has(k)) groups.set(k, []); groups.get(k)!.push(r); } - + // valueType에 따라 비교 함수 선택 const compareValue = (val: unknown): number | string => { if (valueType === ValueType.NUMBER) { @@ -238,7 +238,7 @@ function sortRowsGroupPreserving( // 텍스트나 기타 타입은 문자열로 비교 return String(val ?? ""); }; - + const rep = (arr: Record[]): number | string => { const values = arr.map((r) => compareValue(r[sortField])); if (valueType === ValueType.NUMBER) { @@ -253,7 +253,7 @@ function sortRowsGroupPreserving( return sortAsc ? (strs[0] as string) : (strs[strs.length - 1] as string); } }; - + const entries = [...groups.entries()].sort((a, b) => { const valA = rep(a[1]); const valB = rep(b[1]); @@ -265,7 +265,7 @@ function sortRowsGroupPreserving( const strB = String(valB); return (sortAsc ? 1 : -1) * strA.localeCompare(strB); }); - + return entries.flatMap(([, arr]) => arr); } @@ -306,9 +306,10 @@ function createNumberComparer(dp: RealGridDataProviderComparer): (field: string }; } -const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, rows = [], showHeaderCheckbox = false, rowDataMap, setRowDataMap, activeTab: activeTabProp, onActiveTabChange }: TabDataGridProps) => { +const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, rows = [], showHeaderCheckbox = false, rowDataMap, setRowDataMap, activeTab: activeTabProp, onActiveTabChange, getGridDataRef }: TabDataGridProps) => { // 각 탭별로 그리드 ref와 데이터를 관리 const gridRefs = useRef>(new Map()); + const activeTabRef = useRef(""); const fileInputRefs = useRef>(new Map()); // 각 탭별로 정렬 상태 관리 const sortDirRefs = useRef>>>(new Map()); @@ -323,7 +324,8 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r }); const isControlled = activeTabProp !== undefined; const activeTab = isControlled ? activeTabProp : internalActiveTab; - const setActiveTab = isControlled ? (onActiveTabChange ?? (() => {})) : setInternalActiveTab; + const setActiveTab = isControlled ? (onActiveTabChange ?? (() => { })) : setInternalActiveTab; + activeTabRef.current = activeTab; const exportExcel = (tabKey: string) => { const currentRowData = rowDataMap.get(tabKey) || []; @@ -345,7 +347,7 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r const columnInfoItem = columnInfo.find(info => info.tabKey === tabKey); if (!columnInfoItem) return; - + const tabLabel = columnInfoItem.tabLabel || tabKey; const columns = columnInfoItem.columns || []; const columnLayout = columnInfoItem.columnLayout || []; @@ -520,7 +522,7 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r const columns = columnInfoItem.columns || []; headers.forEach((headerText, colIndex) => { let fieldName: string | null = null; - + // 헤더에 fieldName이 포함된 경우 (예: "합계 (swgeProcZoneInnerSm)") const fieldNameMatch = headerText.match(/\(([a-zA-Z_][a-zA-Z0-9_]*)\)$/); if (fieldNameMatch && fieldNameMatch[1]) { @@ -529,13 +531,13 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r fieldName = extractedFieldName; } } - + // 매칭 실패 시 원본 헤더 텍스트 사용 if (!fieldName) { console.warn(`엑셀 컬럼 ${colIndex + 1} (헤더: "${headerText}") 매칭 실패 → 헤더 텍스트를 fieldName으로 사용`); fieldName = headerText; } - + headerToFieldNameMap.set(headerText, fieldName); }); @@ -656,6 +658,41 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r }); }, [rowDataMap, columnInfo]); + // getGridDataRef: 현재 활성 탭 그리드 데이터 반환 함수 할당 + useEffect(() => { + if (!getGridDataRef) return; + getGridDataRef.current = () => { + const tabKey = activeTabRef.current; + const gridRef = gridRefs.current.get(tabKey); + const gv = gridRef?.gridView as + | { + getDataSource?: () => { + getRowCount(): number; + getValue(r: number, f: string): unknown; + }; + } + | undefined; + if (!gv?.getDataSource) return []; + const ds = gv.getDataSource(); + if (!ds) return []; + const currentInfo = columnInfo.find((info) => info.tabKey === tabKey); + const columns = currentInfo?.columns ?? []; + const fieldNames = columns + .map((c) => c.fieldName) + .filter((x): x is string => Boolean(x)); + const cnt = ds.getRowCount(); + const rows: Record[] = []; + for (let i = 0; i < cnt; i++) { + const r: Record = {}; + for (const f of fieldNames) r[f] = ds.getValue(i, f) as string | number; + rows.push(r); + } + return rows; + }; + return () => { + if (getGridDataRef) getGridDataRef.current = null; + }; + }, [columnInfo, getGridDataRef]); // 탭 전환 시 그리드 레이아웃·푸터·포맷 재적용 (여러 시점 + ResizeObserver) const appliedTabRef = useRef(null); @@ -728,7 +765,7 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r if (item.valueCallback && footerArr[i]) (footerArr[i] as FooterItemWithCallback).valueCallback = item.valueCallback; }); - } catch (_) {} + } catch (_) { } }); } columns.forEach(col => { @@ -738,7 +775,7 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r const fo = col.footer as { valueCallback?: (g: unknown, col: unknown, fi: number, cf: unknown, v: unknown) => unknown }; if (column?.footer && fo.valueCallback) (column.footer as { valueCallback?: typeof fo.valueCallback }).valueCallback = fo.valueCallback; - } catch (_) {} + } catch (_) { } }); if (dp?.setRows && tabRowData.length) dp.setRows(tabRowData); @@ -788,7 +825,7 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r {columnInfo.map((info) => { const tabKey = info.tabKey; - + // isSplitGrid가 true이고 left, right가 있으면 SplitDataGrid 사용 if (info.isSplitGrid && info.left && info.right) { const leftRowData = rowDataMap.get(info.left.tabKey || `${tabKey}_left`) || []; @@ -886,277 +923,277 @@ const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, r
{activeTab === tabKey ? ( - { - if (el) { - gridRefs.current.set(tabKey, el); - // 그리드가 생성된 직후 fitStyle 설정 - if (el.gridView) { - setTimeout(() => { - const gridView = el.gridView; - if (!gridView) return; - - const currentInfo = columnInfo.find(info => info.tabKey === tabKey); - if (!currentInfo || !currentInfo.columns) return; - - const columns = currentInfo.columns; - - const dp = el.dataProvider as { setFields?: (fields: unknown[]) => void; setRows?: (rows: Record[]) => void } | undefined; - if (dp?.setFields) { - dp.setFields(buildFieldsFromColumns(columns)); - } - // setFields 호출 직후 행 데이터 적용 (realgrid-react의 setRows 타이밍 이슈 방지) - const tabRowData = rowDataMap.get(tabKey) || []; - if (dp?.setRows && tabRowData.length) { - dp.setRows(tabRowData); - } - - gridView.setDisplayOptions({ - fitStyle: GridFitStyle.EVEN - }); - gridView.header.height = 60; - - // 헤더 체크박스 표시 여부 설정 - gridView.setOptions({ - checkBar: { visible: showHeaderCheckbox }, - rowIndicator: { visible: false }, - }); - - // footer가 있는 컬럼이 있으면 footer 높이 설정 - const hasFooter = columns.some(col => col.footer); - if (hasFooter) { - // footer가 배열이거나 multiRow가 true인 footer가 있으면 멀티푸터 설정 (여러 행) - const hasArrayFooter = columns.some(col => col.footer && Array.isArray(col.footer)); - const hasMultiRowFooter = columns.some(col => { - const footer = col.footer; - return footer && !Array.isArray(footer) && 'multiRow' in footer && footer.multiRow === true; - }); - if (hasArrayFooter || hasMultiRowFooter) { - // footer 배열의 길이를 확인하여 행 수 결정 - const arrayFooterLengths = columns - .filter(col => col.footer && Array.isArray(col.footer)) - .map(col => (col.footer as unknown[]).length); - const maxFooterLength = arrayFooterLengths.length > 0 - ? Math.max(...arrayFooterLengths) - : 2; // 기본값 2 - const footerHeights = Array.from({ length: maxFooterLength }, () => ({ height: 40 })); - gridView.setFooters?.(footerHeights); - } else { - gridView.footer.height = 40; - } - } - - gridView.setOptions({ - summaryMode: "aggregate" - }); - - // footerUserSpans가 있는 경우 setColumnLayout으로 설정 - const checkFooterUserSpans = (layout: unknown[]): boolean => { - return layout.some(item => { - if (typeof item === 'string') return false; - if (item && typeof item === 'object' && 'footerUserSpans' in item) return true; - if (item && typeof item === 'object' && 'items' in item && Array.isArray(item.items)) { - return checkFooterUserSpans(item.items); - } - return false; - }); - }; - - if (checkFooterUserSpans(columnLayout)) { - // setColumnLayout은 그리드가 완전히 렌더링된 후 호출해야 함 - setTimeout(() => { - if (gridView && columnLayout) { - gridView.setColumnLayout?.(columnLayout); - } - }, 100); - } - - // footer 설정 (배열 또는 단일 객체 모두 처리) - // setFooters 호출 후 footer 배열 설정 + { + if (el) { + gridRefs.current.set(tabKey, el); + // 그리드가 생성된 직후 fitStyle 설정 + if (el.gridView) { setTimeout(() => { - const currentGridView = gridView; - if (!currentGridView || !currentGridView.columnByName) { - console.warn('GridView not available for footer setup'); - return; + const gridView = el.gridView; + if (!gridView) return; + + const currentInfo = columnInfo.find(info => info.tabKey === tabKey); + if (!currentInfo || !currentInfo.columns) return; + + const columns = currentInfo.columns; + + const dp = el.dataProvider as { setFields?: (fields: unknown[]) => void; setRows?: (rows: Record[]) => void } | undefined; + if (dp?.setFields) { + dp.setFields(buildFieldsFromColumns(columns)); } - - // footer가 배열인 컬럼이 있으면 setColumns를 다시 호출하여 footer 설정 - const hasArrayFooter = columns.some(col => col.footer && Array.isArray(col.footer)); - if (hasArrayFooter) { - // 모든 컬럼 정보를 다시 가져와서 footer 배열을 포함하여 setColumns 호출 - const columnsWithFooter: RealGridColumnInfo[] = columns.map(col => { - const colInfo: RealGridColumnInfo = { - name: col.name, - fieldName: col.fieldName, - header: col.header, - editable: col.editable, - valueType: col.valueType, - dataFormat: col.dataFormat, - ...(col.styleName != null && { styleName: col.styleName }), - ...(col.mergeCells && { mergeRule: { criteria: col.mergeGroupField ? `values['${col.mergeGroupField}'] + value` : 'value' as const } }), - }; - - if (col.footer) { - if (Array.isArray(col.footer)) { - colInfo.footer = col.footer; - } else { - colInfo.footer = { - text: col.footer.text, - expression: col.footer.expression, - numberFormat: col.footer.numberFormat, - }; - } - } - - return colInfo; + // setFields 호출 직후 행 데이터 적용 (realgrid-react의 setRows 타이밍 이슈 방지) + const tabRowData = rowDataMap.get(tabKey) || []; + if (dp?.setRows && tabRowData.length) { + dp.setRows(tabRowData); + } + + gridView.setDisplayOptions({ + fitStyle: GridFitStyle.EVEN + }); + gridView.header.height = 60; + + // 헤더 체크박스 표시 여부 설정 + gridView.setOptions({ + checkBar: { visible: showHeaderCheckbox }, + rowIndicator: { visible: false }, + }); + + // footer가 있는 컬럼이 있으면 footer 높이 설정 + const hasFooter = columns.some(col => col.footer); + if (hasFooter) { + // footer가 배열이거나 multiRow가 true인 footer가 있으면 멀티푸터 설정 (여러 행) + const hasArrayFooter = columns.some(col => col.footer && Array.isArray(col.footer)); + const hasMultiRowFooter = columns.some(col => { + const footer = col.footer; + return footer && !Array.isArray(footer) && 'multiRow' in footer && footer.multiRow === true; }); - - try { - (currentGridView as GridViewWithSetColumns).setColumns?.(columnsWithFooter); - - // setColumns 호출 후 footer 배열의 valueCallback을 다시 설정 - setTimeout(() => { - columns.forEach(col => { - if (!col.footer || !Array.isArray(col.footer)) return; - - try { - const column = currentGridView.columnByName(col.name); - if (!column) return; - - // footer 배열의 각 요소에 valueCallback 설정 - col.footer.forEach((footerItem, index) => { - if (footerItem.valueCallback && column.footer) { - // footer가 배열인 경우 - if (Array.isArray(column.footer) && column.footer[index]) { - (column.footer[index] as FooterItemWithCallback).valueCallback = footerItem.valueCallback; - } - } - }); - } catch (e) { - console.warn(`Error setting footer array valueCallback for column ${col.name}:`, e); + if (hasArrayFooter || hasMultiRowFooter) { + // footer 배열의 길이를 확인하여 행 수 결정 + const arrayFooterLengths = columns + .filter(col => col.footer && Array.isArray(col.footer)) + .map(col => (col.footer as unknown[]).length); + const maxFooterLength = arrayFooterLengths.length > 0 + ? Math.max(...arrayFooterLengths) + : 2; // 기본값 2 + const footerHeights = Array.from({ length: maxFooterLength }, () => ({ height: 40 })); + gridView.setFooters?.(footerHeights); + } else { + gridView.footer.height = 40; + } + } + + gridView.setOptions({ + summaryMode: "aggregate" + }); + + // footerUserSpans가 있는 경우 setColumnLayout으로 설정 + const checkFooterUserSpans = (layout: unknown[]): boolean => { + return layout.some(item => { + if (typeof item === 'string') return false; + if (item && typeof item === 'object' && 'footerUserSpans' in item) return true; + if (item && typeof item === 'object' && 'items' in item && Array.isArray(item.items)) { + return checkFooterUserSpans(item.items); + } + return false; + }); + }; + + if (checkFooterUserSpans(columnLayout)) { + // setColumnLayout은 그리드가 완전히 렌더링된 후 호출해야 함 + setTimeout(() => { + if (gridView && columnLayout) { + gridView.setColumnLayout?.(columnLayout); + } + }, 100); + } + + // footer 설정 (배열 또는 단일 객체 모두 처리) + // setFooters 호출 후 footer 배열 설정 + setTimeout(() => { + const currentGridView = gridView; + if (!currentGridView || !currentGridView.columnByName) { + console.warn('GridView not available for footer setup'); + return; + } + + // footer가 배열인 컬럼이 있으면 setColumns를 다시 호출하여 footer 설정 + const hasArrayFooter = columns.some(col => col.footer && Array.isArray(col.footer)); + if (hasArrayFooter) { + // 모든 컬럼 정보를 다시 가져와서 footer 배열을 포함하여 setColumns 호출 + const columnsWithFooter: RealGridColumnInfo[] = columns.map(col => { + const colInfo: RealGridColumnInfo = { + name: col.name, + fieldName: col.fieldName, + header: col.header, + editable: col.editable, + valueType: col.valueType, + dataFormat: col.dataFormat, + ...(col.styleName != null && { styleName: col.styleName }), + ...(col.mergeCells && { mergeRule: { criteria: col.mergeGroupField ? `values['${col.mergeGroupField}'] + value` : 'value' as const } }), + }; + + if (col.footer) { + if (Array.isArray(col.footer)) { + colInfo.footer = col.footer; + } else { + colInfo.footer = { + text: col.footer.text, + expression: col.footer.expression, + numberFormat: col.footer.numberFormat, + }; } - }); - }, 50); - } catch (e) { - console.warn('Failed to set columns with footer array:', e); - } - } - - // footer가 단일 객체이고 valueCallback이 있는 경우 - columns.forEach(col => { - if (!col.footer || Array.isArray(col.footer)) return; - - try { - const column = currentGridView.columnByName(col.name); - if (!column || !column.footer) return; - - const footerObj = col.footer as { valueCallback?: (grid: unknown, column: unknown, footerIndex: number, columnFooter: unknown, value: unknown) => unknown }; - if (footerObj.valueCallback) { - (column.footer as { valueCallback?: typeof footerObj.valueCallback }).valueCallback = footerObj.valueCallback; - } - } catch (e) { - console.warn(`Error setting footer valueCallback for column ${col.name}:`, e); - } - }); - }, 200); - - // 고정 컬럼 설정 - if (currentInfo.fixedColumns !== undefined && currentInfo.fixedColumns > 0) { - gridView.setFixedOptions({ - colCount: currentInfo.fixedColumns, - }); - } - - // 각 탭별 ref 초기화 - if (!sortDirRefs.current.has(tabKey)) { - sortDirRefs.current.set(tabKey, { current: {} }); - } - if (!originalRowsRefs.current.has(tabKey)) { - originalRowsRefs.current.set(tabKey, { current: {} }); - } - - const sortDirRef = sortDirRefs.current.get(tabKey)!; - const originalRowsRef = originalRowsRefs.current.get(tabKey)!; - - // mergeCells: true인 컬럼이 있으면 onSorting에서 클라이언트 정렬로 처리 - const hasMergeCells = columns.some((col) => col.mergeCells === true); - - // setDataComparer로 숫자 정렬 (mergeCells가 있으면 onSorting에서 클라이언트 정렬로 처리) - if (el.dataProvider) { - const dp = el.dataProvider as RealGridDataProviderComparer; - if (typeof dp.setDataComparer === "function" && typeof dp.getValue === "function") { - const numberComparer = createNumberComparer(dp); - const seen = new Set(); - columns.forEach((col) => { - if (hasMergeCells) return; // mergeCells가 있으면 모든 컬럼을 클라이언트 정렬로 처리 - if (col.valueType === ValueType.NUMBER && col.fieldName && !seen.has(col.fieldName)) { - seen.add(col.fieldName); - try { - dp.setDataComparer!(col.fieldName, numberComparer); - } catch (e) { - console.warn("setDataComparer:", e); } + + return colInfo; + }); + + try { + (currentGridView as GridViewWithSetColumns).setColumns?.(columnsWithFooter); + + // setColumns 호출 후 footer 배열의 valueCallback을 다시 설정 + setTimeout(() => { + columns.forEach(col => { + if (!col.footer || !Array.isArray(col.footer)) return; + + try { + const column = currentGridView.columnByName(col.name); + if (!column) return; + + // footer 배열의 각 요소에 valueCallback 설정 + col.footer.forEach((footerItem, index) => { + if (footerItem.valueCallback && column.footer) { + // footer가 배열인 경우 + if (Array.isArray(column.footer) && column.footer[index]) { + (column.footer[index] as FooterItemWithCallback).valueCallback = footerItem.valueCallback; + } + } + }); + } catch (e) { + console.warn(`Error setting footer array valueCallback for column ${col.name}:`, e); + } + }); + }, 50); + } catch (e) { + console.warn('Failed to set columns with footer array:', e); + } + } + + // footer가 단일 객체이고 valueCallback이 있는 경우 + columns.forEach(col => { + if (!col.footer || Array.isArray(col.footer)) return; + + try { + const column = currentGridView.columnByName(col.name); + if (!column || !column.footer) return; + + const footerObj = col.footer as { valueCallback?: (grid: unknown, column: unknown, footerIndex: number, columnFooter: unknown, value: unknown) => unknown }; + if (footerObj.valueCallback) { + (column.footer as { valueCallback?: typeof footerObj.valueCallback }).valueCallback = footerObj.valueCallback; + } + } catch (e) { + console.warn(`Error setting footer valueCallback for column ${col.name}:`, e); } }); + }, 200); + + // 고정 컬럼 설정 + if (currentInfo.fixedColumns !== undefined && currentInfo.fixedColumns > 0) { + gridView.setFixedOptions({ + colCount: currentInfo.fixedColumns, + }); } - } - - // mergeCells: true인 컬럼이 있으면 onSorting에서 그룹 내 순서 유지 정렬 적용 - const setRowData = (updater: React.SetStateAction[]>) => { - setRowDataMap(prev => { - const newMap = new Map(prev); - const currentData = newMap.get(tabKey) || []; - const newData = typeof updater === 'function' ? updater(currentData) : updater; - newMap.set(tabKey, newData); - return newMap; - }); - }; - - // 그리드 DOM 요소 찾기 (나중에 화살표 업데이트에 사용) - // 탭별로 그리드 요소를 찾기 위해 data-tab-key 사용 - const findGridElement = () => { - const tabContent = document.querySelector(`[data-tab-key="${tabKey}"]`); - return tabContent?.querySelector('.rg-grid, [data-grid-id]') as HTMLElement | null; - }; - - const onSortingHandler = createOnSortingHandler(columns, setRowData, sortDirRef, originalRowsRef, findGridElement); - (gridView as { onSorting?: (g: unknown, f: unknown[], d: unknown[]) => boolean }).onSorting = onSortingHandler; - }, 150); + + // 각 탭별 ref 초기화 + if (!sortDirRefs.current.has(tabKey)) { + sortDirRefs.current.set(tabKey, { current: {} }); + } + if (!originalRowsRefs.current.has(tabKey)) { + originalRowsRefs.current.set(tabKey, { current: {} }); + } + + const sortDirRef = sortDirRefs.current.get(tabKey)!; + const originalRowsRef = originalRowsRefs.current.get(tabKey)!; + + // mergeCells: true인 컬럼이 있으면 onSorting에서 클라이언트 정렬로 처리 + const hasMergeCells = columns.some((col) => col.mergeCells === true); + + // setDataComparer로 숫자 정렬 (mergeCells가 있으면 onSorting에서 클라이언트 정렬로 처리) + if (el.dataProvider) { + const dp = el.dataProvider as RealGridDataProviderComparer; + if (typeof dp.setDataComparer === "function" && typeof dp.getValue === "function") { + const numberComparer = createNumberComparer(dp); + const seen = new Set(); + columns.forEach((col) => { + if (hasMergeCells) return; // mergeCells가 있으면 모든 컬럼을 클라이언트 정렬로 처리 + if (col.valueType === ValueType.NUMBER && col.fieldName && !seen.has(col.fieldName)) { + seen.add(col.fieldName); + try { + dp.setDataComparer!(col.fieldName, numberComparer); + } catch (e) { + console.warn("setDataComparer:", e); + } + } + }); + } + } + + // mergeCells: true인 컬럼이 있으면 onSorting에서 그룹 내 순서 유지 정렬 적용 + const setRowData = (updater: React.SetStateAction[]>) => { + setRowDataMap(prev => { + const newMap = new Map(prev); + const currentData = newMap.get(tabKey) || []; + const newData = typeof updater === 'function' ? updater(currentData) : updater; + newMap.set(tabKey, newData); + return newMap; + }); + }; + + // 그리드 DOM 요소 찾기 (나중에 화살표 업데이트에 사용) + // 탭별로 그리드 요소를 찾기 위해 data-tab-key 사용 + const findGridElement = () => { + const tabContent = document.querySelector(`[data-tab-key="${tabKey}"]`); + return tabContent?.querySelector('.rg-grid, [data-grid-id]') as HTMLElement | null; + }; + + const onSortingHandler = createOnSortingHandler(columns, setRowData, sortDirRef, originalRowsRef, findGridElement); + (gridView as { onSorting?: (g: unknown, f: unknown[], d: unknown[]) => boolean }).onSorting = onSortingHandler; + }, 150); + } + } else { + gridRefs.current.delete(tabKey); } - } else { - gridRefs.current.delete(tabKey); - } - }} - autoGenerateField={true} - layout={columnLayout} - rows={currentRowData} - > - {columns.map((column) => ( - - ))} - + }} + autoGenerateField={true} + layout={columnLayout} + rows={currentRowData} + > + {columns.map((column) => ( + + ))} + ) : null}
diff --git a/apps/st/src/components/statistics/input/SewagePipeInp.tsx b/apps/st/src/components/statistics/input/SewagePipeInp.tsx index 4eac16126..20bed7f23 100644 --- a/apps/st/src/components/statistics/input/SewagePipeInp.tsx +++ b/apps/st/src/components/statistics/input/SewagePipeInp.tsx @@ -1,31 +1,87 @@ -import { useState } from "react"; +import { useState, useMemo } from "react"; import SearchForm from "@/components/module/SearchForm"; -import { TabDataGrid } from '@rsone/components'; +import TabDataGrid from "@/components/module/TabDataGrid"; import SubmitButton from "@/components/button/SumitButton"; import SaveButton from "@/components/button/SaveButton"; import LastYearDataButton from "@/components/button/LastYearDataButton"; import SubmitExceptionButton from "@/components/button/SubmitExceptionButton"; -import { RegionalFactStatusInpColumn } from "@/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn"; -import { FactInstallStatusInpColumn } from "@/components/util/column/input/sewagePipe/FactInstallStatusInpColumn"; -import { PipeTypeStatusInpColumn } from "@/components/util/column/input/sewagePipe/PipeTypeStatusInpColumn"; -import { PipeDiameterStatusInpColumn } from "@/components/util/column/input/sewagePipe/PipeDiameterStatusInpColumn"; -import { ManholeStatusInpColumn } from "@/components/util/column/input/sewagePipe/ManholeStatusInpColumn"; -import { ConnectionStatusInpColumn } from "@/components/util/column/input/sewagePipe/ConnectionStatusInpColumn"; +import { SewagePipeInpColumnInfoList } from "@/components/util/column/input/sewagePipe/SewagePipeInpColumn"; +import type { ColumnInfoList, ColumnConfig } from "@/components/type/DataGrid.type"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import { useAlertStore } from "@/shared/lib"; +import { useAdminStore } from "@/store/admin-store"; -// 하수도 통계 관리 > 02. 하수관로 +// 하수도 통계 관리 > 02. 하수관로 const SewagePipeInp = () => { - - // tab List - const SewagePipeInpTapList = [ - RegionalFactStatusInpColumn, - FactInstallStatusInpColumn, - PipeTypeStatusInpColumn, - PipeDiameterStatusInpColumn, - ManholeStatusInpColumn, - ConnectionStatusInpColumn, - ]; + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const { setMessage: alert } = useAlertStore((state) => state); + const [isLoading, setIsLoading] = useState(false); + const [activeTab, setActiveTab] = useState(SewagePipeInpColumnInfoList[0]?.tabKey ?? "ST00020001"); + const [isEnterable, setIsEnterable] = useState(true); + const { isAdminInfo } = useAdminStore(); + + const columnInfo = useMemo(() => { + const canEdit = isEnterable || isAdminInfo; + return SewagePipeInpColumnInfoList.map((tab: ColumnInfoList) => { + const applyEditable = (cols: ColumnConfig[] | undefined) => + (cols ?? []).map((col: ColumnConfig) => + canEdit + ? col + : { ...col, editable: false as const, styleName: col.styleName ?? "rg-cell-readonly" } + ); + + if (tab.left && tab.right) { + return { + ...tab, + left: { ...tab.left, columns: applyEditable(tab.left.columns) }, + right: { ...tab.right, columns: applyEditable(tab.right.columns) }, + }; + } + return { + ...tab, + columns: applyEditable(tab.columns), + }; + }); + }, [isEnterable, isAdminInfo]); + + const handleSearch = async (values: SearchFormValues) => { + if (!values.sido || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + setActiveTab('ST00020001'); + + setRowDataMap(new Map()); + + try { + setIsLoading(true); + + // const searchParam: SewagePipeReviewRequestParams = { + // statsYr: values.year, + // sewerBzmnCd: values.bsnmCd, + // ctpvNm: values.sido, + // sggNm: values.gugun === 'ALL' ? '' : values.gugun + // }; + + // searchParamRef.current = searchParam; + // const response = await statisticsManagementApi.getSewagePipeReviewRegionalList(searchParam); + + // if (response?.status === 'success' && response.data) { + // const newRowDataMap = new Map[]>(); + // newRowDataMap.set('ST00020001', toGridRows(response.data as object[])); + // setRowDataMap(newRowDataMap); + // } else { + // alert(response?.message || "데이터가 없습니다."); + // } + } catch { + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } + }; const SubmitExceptionFunc = () => { console.log('submit exception'); @@ -47,7 +103,6 @@ const SewagePipeInp = () => { // 저장 로직 }; - const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); return ( <> @@ -60,10 +115,12 @@ const SewagePipeInp = () => { - ); diff --git a/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx b/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx index cf6b184b4..6c660e77b 100644 --- a/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx +++ b/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx @@ -14,7 +14,13 @@ import SubmitDailog from "./SubmitDailog"; import { useAlertStore } from "@/shared/lib"; import { useAdminStore } from "@/store/admin-store"; -import { StatisticsInputSewSupplyRateApi } from "@/entities/statistics/api/statistics-input-sew-supply-rate-service"; +import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/statistics-input-sew-supply-rate-service"; +import { statisticsAPi } from "@/entities/statistics/api/statistics-service"; +import { toGridRows } from "@/components/util/grid/gridFunction"; +import { getFooterSummary } from "@/components/util/grid/footerSummary"; +import { getUserInfo } from "../../../../../../packages/common/components/src/api"; +import { useConfirm } from "@frontend-opensource/use-react-hooks"; + import type { SearchFormValues } from "@/components/type/SearchForm.type"; import type { SewerageSupplyRateItem, @@ -24,14 +30,12 @@ import type { SewerageSupplyRateSaveRequest, SewerageSupplyRateStatusInfo, } from "@/entities/statistics/model/statistics-sewage-supply-rate-input-interface"; +import type { cancelSubmitRequest } from "@/entities/statistics/model/statistics-interface"; import type { StatisticsInputSubmitInfoFormData } from "@/entities/statistics/model/statistics-input-submit-info-schema"; import { SeweragePenetrationRateInpColumn } from "@/components/util/column/input/SeweragePenetrationRateInpColumn"; -import { toGridRows } from "@/components/util/grid/gridFunction"; -import { getFooterSummary } from "@/components/util/grid/footerSummary"; -import { getUserInfo } from "../../../../../../packages/common/components/src/api"; -import { useConfirm } from "@frontend-opensource/use-react-hooks"; import { doList } from "@/components/util/column/input/DoList"; + type GridRowWithVerification = Record & { verificationResult?: SewerageSupplyRateVerificationResult; }; @@ -60,11 +64,12 @@ const SeweragePenetrationRateInp = () => { const [lastSearchedValues, setLastSearchedValues] = useState(null); const [statusInfo, setStatusInfo] = useState(null); const [showDailog, setShowDailog] = useState(false); + const [statsCd, setStatsCd] = useState(''); + const [footerFromApi, setFooterFromApi] = useState<{ sewerBzmnWholPpltnCnt?: number; sewerBzmnDomplWholPpltnCnt?: number; sewerBzmnFrgnrWholPpltnCnt?: number; sewerBzmnArea?: number } | null>(null); const { confirm } = useConfirm(); const { isAdminInfo } = useAdminStore(); - const [footerFromApi, setFooterFromApi] = useState<{ sewerBzmnWholPpltnCnt?: number; sewerBzmnDomplWholPpltnCnt?: number; sewerBzmnFrgnrWholPpltnCnt?: number; sewerBzmnArea?: number } | null>(null); const getGridDataRef = useRef<(() => Record[]) | null>(null); const _footerFieldNames = ['sewerBzmnWholPpltnCnt', 'sewerBzmnDomplWholPpltnCnt', 'sewerBzmnFrgnrWholPpltnCnt', 'sewerBzmnArea'] as const; @@ -103,7 +108,7 @@ const SeweragePenetrationRateInp = () => { const fetchSewerageSupplyRate = async (params: SewerageSupplyRateRequestParams, isEnterable: boolean) => { try { setIsLoading(true); - const response = await StatisticsInputSewSupplyRateApi.getSewerageSupplyRateList(params); + const response = await statisticsInputSewSupplyRateApi.getSewerageSupplyRateList(params); if (response.status === 'success' && response.data) { const commonInfo = response.data.commonInfo; const statusInfo = response.data.statusInfo; @@ -121,7 +126,7 @@ const SeweragePenetrationRateInp = () => { }) ); - setStatusInfo(response.data.statusInfo); + setStatusInfo(statusInfo); setFooterFromApi( commonInfo ? { @@ -132,7 +137,7 @@ const SeweragePenetrationRateInp = () => { } : null ); - + setStatsCd(commonInfo.statsCd); if (statusInfo && statusInfo.laeSbmsnSttsCd) { if (['2', '3'].includes(statusInfo.laeSbmsnSttsCd)) { setIsEnterable(false); @@ -163,7 +168,7 @@ const SeweragePenetrationRateInp = () => { } try { - const response = await StatisticsInputSewSupplyRateApi.checkInputPeriod(values.year || ''); + const response = await statisticsInputSewSupplyRateApi.checkInputPeriod(values.year || ''); if (response.status === 'success') { const checkEnterable = response.data; @@ -266,6 +271,7 @@ const SeweragePenetrationRateInp = () => { const requestData: SewerageSupplyRateSaveRequest = { sewerBzmnCd: searchValues?.bsnmCd ?? '', ctpvNm: searchValues?.sido ?? '', + sggNm: searchValues?.gugun ?? '', statsYr: searchValues?.year ?? '', userId: userInfo.userUnqId, submitList: convertedData, @@ -280,7 +286,7 @@ const SeweragePenetrationRateInp = () => { laeIdfrTelNo: submitInfo.laeIdfrTelNo, }; - const response = await StatisticsInputSewSupplyRateApi.submitSewerageSupplyRate(requestData); + const response = await statisticsInputSewSupplyRateApi.submitSewerageSupplyRate(requestData); if (response.status === 'success') { await fetchSewerageSupplyRate(getSewerageSupplyRateParams(searchValues ?? {}), false); alert('제출되었습니다.'); @@ -368,6 +374,7 @@ const SeweragePenetrationRateInp = () => { const requestData: SewerageSupplyRateSaveRequest = { sewerBzmnCd: searchValues?.bsnmCd ?? '', // 하수도 사업자 코드 ctpvNm: searchValues?.sido ?? '', // 시도 + sggNm: searchValues?.gugun ?? '', statsYr: searchValues?.year ?? '', // 통계 연도 userId: userInfo.userUnqId, // 사용자 saveList: convertedData, // 저장 데이터 @@ -378,7 +385,7 @@ const SeweragePenetrationRateInp = () => { requestData.superAdmin = 'superAdmin'; } - const response = await StatisticsInputSewSupplyRateApi.saveSewerageSupplyRate(requestData); + const response = await statisticsInputSewSupplyRateApi.saveSewerageSupplyRate(requestData); if (response.status === 'success') { fetchSewerageSupplyRate(getSewerageSupplyRateParams(searchValues ?? {}), true); @@ -395,7 +402,36 @@ const SeweragePenetrationRateInp = () => { setIsLoading(false); } }; - console.log(footerFromApi); + + const cnacelSubmitFunc = async () => { + try { + if (await confirm('제출된 내용을 취소하시겠습니까?')) { + + const userInfo = await getUserInfo(); + + const requestData: cancelSubmitRequest = { + sewerBzmnCd: searchValues?.bsnmCd ?? '', + ctpvNm: searchValues?.sido ?? '', + sggNm: searchValues?.gugun ?? '', + statsYr: searchValues?.year ?? '', + userId: userInfo.userUnqId, + statsCd: statsCd, + }; + + const response = await statisticsAPi.cancelSubmit(requestData); + + if (response.status === 'success') { + fetchSewerageSupplyRate(getSewerageSupplyRateParams(searchValues ?? {}), true); + alert('제출 취소되었습니다.'); + } else { + alert(response.message ?? '제출 취소 중 오류가 발생했습니다.'); + } + } + } catch { + alert('제출 취소 중 오류가 발생했습니다.'); + } + }; + return ( <>
@@ -411,7 +447,7 @@ const SeweragePenetrationRateInp = () => { )} - {statusInfo?.laeSbmsnSttsCd === '2' && console.log('test')} />} + {statusInfo?.laeSbmsnSttsCd === '2' && } {(isEnterable && (doList.includes(lastSearchedValues?.bsnmCd || '') ? Boolean(lastSearchedValues?.gugun && lastSearchedValues.gugun !== 'ALL') : true) || isAdminInfo) && }
diff --git a/apps/st/src/components/statistics/input/StatsInputStatusInp.tsx b/apps/st/src/components/statistics/input/StatsInputStatusInp.tsx index e6e87c207..4390777b9 100644 --- a/apps/st/src/components/statistics/input/StatsInputStatusInp.tsx +++ b/apps/st/src/components/statistics/input/StatsInputStatusInp.tsx @@ -1,7 +1,8 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; +import useSWR, { useSWRConfig } from "swr"; import SearchForm from "@/components/module/SearchForm"; -// import { DataGrid } from "@rsone/components"; +import { useTabStore } from "@/store/tab-store"; import DataGrid from "@/components/module/DataGrid"; import ApproveButton from "@/components/button/ApproveButton"; import RejectButton from "@/components/button/RejectButton"; @@ -13,45 +14,63 @@ import type { StatsInputStatusListRequestParams } from "@/entities/statistics/mo import type { SearchFormValues } from "@/components/type/SearchForm.type"; import { useAlertStore } from "@/shared/lib"; import { toGridRows } from "@/components/util/grid/gridFunction"; +import type { StatsInputStatusListApiResponse } from "@/entities/statistics/model/statistics-input-status-interface"; + +const getStatsInputStatusFetcher = async (key: [string, StatsInputStatusListRequestParams]): Promise => { + return StatisticsInputStatusApi.getStatisticsInputStatusList(key[1]); +}; // 하수도 통계 관리 > 00. 통계 입력 현황 const StatsInputStatusInp = () => { const { setMessage: alert } = useAlertStore((state) => state); + const activeTabId = useTabStore((state) => state.activeTabId); const [rowData, setRowData] = useState[]>([]); - const [isLoading, setIsLoading] = useState(false); + const [searchParams, setSearchParams] = useState(null); - const handleSearch = async (values: SearchFormValues) => { - if (values.sido === '' || values.sido === 'ALL') { - alert('시도를 선택해주세요.'); + const swrKey = searchParams ? (["stats-input-status", searchParams] as const) : null; + const { mutate } = useSWRConfig(); + const { isLoading } = useSWR( + swrKey, + getStatsInputStatusFetcher, + { + revalidateOnFocus: true, + onSuccess: (data) => { + if (data.status === "success" && data.data) { + setRowData(toGridRows(data.data)); + } else { + alert(data.message ?? "조회에 실패했습니다."); + } + }, + onError: () => { + alert("데이터 조회 중 오류가 발생했습니다."); + setRowData([]); + }, + }, + ); + + useEffect(() => { + if (activeTabId === 'StatsInputStatusInp' && swrKey) { + mutate(swrKey); + } + }, [activeTabId]); + + const handleSearch = (values: SearchFormValues) => { + if (values.sido === "" || values.sido === "ALL") { + alert("시도를 선택해주세요."); return; } - - const searchParam: StatsInputStatusListRequestParams = { + const params: StatsInputStatusListRequestParams = { ctpvNm: values.sido, sewerBzmnCd: values.bsnmCd, - sggNm: values.gugun === 'ALL' ? '' : values.gugun, + sggNm: values.gugun === "ALL" ? "" : values.gugun, statsYr: values.year, }; - - try { - setIsLoading(true); - - const response = await StatisticsInputStatusApi.getStatisticsInputStatusList(searchParam); - console.log(response) - if (response.status === 'success' && response.data) { - setRowData(toGridRows(response.data)); - } else { - alert(response.message); - } - } catch { - alert('데이터 조회 중 오류가 발생했습니다.'); - setRowData([]); - } finally { - setIsLoading(false); - } + setSearchParams(params); + mutate(["stats-input-status", params]); }; const handleReset = () => { + setSearchParams(null); setRowData([]); }; diff --git a/apps/st/src/components/statistics/input/SubmitDailog.tsx b/apps/st/src/components/statistics/input/SubmitDailog.tsx index b286117b7..7b67d4cb7 100644 --- a/apps/st/src/components/statistics/input/SubmitDailog.tsx +++ b/apps/st/src/components/statistics/input/SubmitDailog.tsx @@ -155,7 +155,7 @@ const SubmitDailog = ({ open, onOpenChange, statusInfo, onConfirm }: SubmitDialo 취소 diff --git a/apps/st/src/components/statistics/review/PumpingStationRvw.tsx b/apps/st/src/components/statistics/review/PumpingStationRvw.tsx index 3fc34a034..346a9ef33 100644 --- a/apps/st/src/components/statistics/review/PumpingStationRvw.tsx +++ b/apps/st/src/components/statistics/review/PumpingStationRvw.tsx @@ -12,12 +12,15 @@ import { PumpingStationInfoList } from "@/components/util/column/review/PumpingS import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service"; import type { SearchFormValues } from "@/components/type/SearchForm.type"; import { toGridRows } from "@/components/util/grid/gridFunction"; +import type { MediationPumpStationItem } from "@/entities/statistics/model/statistics-pumping-station-review-interface"; -// 하수도 통계 검토 05.중계펌프장 +/** + * 하수도 통계 검토 05.중계펌프장 + */ const PumpingStationRvw = () => { const { setMessage: alert } = useAlertStore((state) => state); const [rowData, setRowData] = useState[]>([]); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(false); const columnInfo = useMemo(() => { const { columns, columnLayout, fixedColumns, rowStartNum } = PumpingStationInfoList; @@ -27,7 +30,7 @@ const PumpingStationRvw = () => { rowStartNum, columns: columns.map((col) => ({ ...col, - editable: false as const, // 검토 화면이므로 읽기 전용 + editable: false as const, styleName: col.styleName ?? ("rg-cell-readonly" as const), })), }; @@ -38,7 +41,7 @@ const PumpingStationRvw = () => { }; const handleSearch = async (values: SearchFormValues) => { - if (values.sido === '' || values.sido === 'ALL') { + if (!values.sido || values.sido === 'ALL') { alert('시도를 선택해주세요.'); return; } @@ -47,15 +50,22 @@ const PumpingStationRvw = () => { 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, // 시설명 검색 + ctpvNm: values.sido, + sggNm: values.gugun === 'ALL' ? '' : values.gugun, + sewerBzmnCd: values.bsnmCd, + statsYr: values.year, + pumpstNm: values.fctName, }); if (response.status === 'success' && response.data) { - setRowData(toGridRows(response.data)); + const rawList = response.data as MediationPumpStationItem[]; + + const convertedData = rawList.map(item => ({ + ...item, + rmrk: item.rmrk || '' + })); + + setRowData(toGridRows(convertedData)); } else { setRowData([]); alert(response.message || "데이터가 없습니다."); @@ -64,7 +74,7 @@ const PumpingStationRvw = () => { console.error("중계펌프장 조회 중 에러 발생:", error); alert('데이터 조회 중 오류가 발생했습니다.'); } finally { - setIsLoading(false); + setIsLoading(false); } }; @@ -74,9 +84,9 @@ const PumpingStationRvw = () => { const returnFunc = () => console.log('returnFunc'); return ( -
- - +
+ +
diff --git a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx index d8cdc7d0e..26629d3a5 100644 --- a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx @@ -101,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/statistics/review/SewagePipeRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx index fab4d2cbc..77d3a5d88 100644 --- a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx @@ -96,12 +96,11 @@ const SewagePipeRvw = () => { 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); } - // }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) { diff --git a/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx b/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx index 13303f6c1..4a250d2aa 100644 --- a/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx +++ b/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx @@ -13,11 +13,12 @@ import { SewageReservoirPumpInfoListRvw } from "@/components/util/column/review/ 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 { SewerReservoirRequestParams } from "@/entities/statistics/model/sewage-reservoir-pump-review-interface"; /** * 하수도 통계 검토 04. 하수저류 시설 및 빗물 펌프장 - * Tab A: 하수저류시설 - * Tab B: 빗물펌프장 + * Tab A: 하수저류시설 (ST00040001) + * Tab B: 빗물펌프장 (ST00040002) */ const SewageReservoirPumpRvw = () => { const { setMessage: alert } = useAlertStore((state) => state); @@ -25,7 +26,7 @@ const SewageReservoirPumpRvw = () => { const [isLoading, setIsLoading] = useState(false); const [activeTab, setActiveTab] = useState('ST00040001'); - const searchParamRef = useRef(null); + const searchParamRef = useRef(null); const columnInfo = useMemo(() => { return SewageReservoirPumpInfoListRvw.map((tab: ColumnInfoList) => ({ @@ -56,16 +57,15 @@ const SewageReservoirPumpRvw = () => { try { setIsLoading(true); - const searchParam = { - sido: values.sido, - gugun: values.gugun === 'ALL' ? '' : values.gugun, - bsnmCd: values.bsnmCd, - yr: values.year, + const searchParam: SewerReservoirRequestParams = { + statsYr: values.year, + sewerBzmnCd: values.bsnmCd, + ctpvNm: values.sido, + sggNm: values.gugun === 'ALL' ? '' : values.gugun, }; searchParamRef.current = searchParam; - - //하수저류시설 (Tab A) + const response = await statisticsManagementApi.getSewerReservoirList(searchParam); if (response?.status === 'success' && response.data) { @@ -85,15 +85,21 @@ const SewageReservoirPumpRvw = () => { const handleActiveTabChange = async (tabKey: string) => { setActiveTab(tabKey); + const existingAData = rowDataMap.get('ST00040001'); const activeTabData = rowDataMap.get(tabKey); + + const hasAData = Array.isArray(existingAData) && existingAData.length > 0; const hasActiveTabData = Array.isArray(activeTabData) && activeTabData.length > 0; - if (searchParamRef.current && !hasActiveTabData) { + if (hasAData && !hasActiveTabData && searchParamRef.current) { try { setIsLoading(true); + let response; - if (tabKey === 'ST00040002') { + if (tabKey === 'ST00040001') { + response = await statisticsManagementApi.getSewerReservoirList(searchParamRef.current); + } else if (tabKey === 'ST00040002') { response = await statisticsManagementApi.getPumpStationList(searchParamRef.current); } @@ -116,19 +122,19 @@ const SewageReservoirPumpRvw = () => { return (
- +
- { /* 검토의견 로직 */ }} /> - { /* 승인 로직 */ }} /> - { /* 반려 로직 */ }} /> - { /* 저장 로직 */ }} /> + { }} /> + { }} /> + { }} /> + { }} />
{isLoading && ( -
+
diff --git a/apps/st/src/components/statistics/verification/GeneralVerificationManagement.tsx b/apps/st/src/components/statistics/verification/GeneralVerificationManagement.tsx index 0bd348123..16947f896 100644 --- a/apps/st/src/components/statistics/verification/GeneralVerificationManagement.tsx +++ b/apps/st/src/components/statistics/verification/GeneralVerificationManagement.tsx @@ -1,79 +1,141 @@ "use client"; -import { useState } from 'react'; +import { useMemo, useState } from 'react'; import { CodeSelect } from '@/entities/code'; import { Button, Label, - Table, - TableBody, - TableCell, - TableHead, - TableRow, + // Table, + // TableBody, + // TableCell, + // TableHead, + // TableRow, + DataTable, } from "@common/components"; +import { getCoreRowModel, useReactTable } from "@tanstack/react-table"; +// import { useDataTable } from "@/shared/lib"; +import { GeneralVerificationColumn } from '@/components/util/column/management/GeneralVerificationColumn'; +import type { GeneralverificationList } from '@/entities/statistics/model/general-verification-interface'; + const GeneralVerificationManagement = () => { const [statsCd, setStatsCd] = useState(''); + // const [rowSelection, setRowSelection] = useState({}); + // const [pagination, setPagination] = useState({ + // pageIndex: 0, + // pageSize: 100, + // }); + + // const { tableComponent } = useDataTable({ + // tableOptions: { + // GeneralVerificationColumn, + // state: { + // pagination, + // rowSelection, + // }, + // manualPagination: true, + // enableMultiRowSelection: true, + // getCoreRowModel: getCoreRowModel(), + // onPaginationChange: setPagination, + // onRowSelectionChange: setRowSelection, + // }, + // // dataTableOptions: { + // // onRowClick: handleRowClick, + // // viewPagination: true, + // // }, + // }); + + const mockData = useMemo( + () => [ + { + vrfSn: 1, + tabNm: '하수도보급률', + vrfNm: '인구수 검증', + vrfClsCd: '시', + statsCd: 'ST000001', + useYn: 'Y', + rgtrId: '관리자', + regDt: '20260102', + }, + { + vrfSn: 2, + tabNm: '하수도보급률', + vrfNm: '인구수 검증', + vrfClsCd: '시', + statsCd: 'ST000001', + useYn: 'Y', + rgtrId: '관리자', + regDt: '20260102', + }, + { + vrfSn: 3, + tabNm: '하수도보급률', + vrfNm: '인구수 검증', + vrfClsCd: '시', + statsCd: 'ST000001', + useYn: 'Y', + rgtrId: '관리자', + regDt: '20260102', + }, + { + vrfSn: 4, + tabNm: '하수도보급률', + vrfNm: '인구수 검증', + vrfClsCd: '시', + statsCd: 'ST000001', + useYn: 'Y', + rgtrId: '관리자', + regDt: '20260102', + }, + ], + [] + ); + + const table = useReactTable({ + data: mockData, + columns: GeneralVerificationColumn, + getCoreRowModel: getCoreRowModel(), + }); + + const handleSearch = () => { + console.log(statsCd); + }; return ( -
+
-
-
-
- - -
-
- - -
+
+
+ +
- +
+ + +
+
-
+
- - - No - 검증항목 - 등록자 - 등록일 - 사용여부 - - - - - 1 - - - 인구수검증 - - - 관리자 - - - 2026-02-09 - - - Y - - - -
+
+

일반 검증 목록

+
+
+ +
diff --git a/apps/st/src/components/type/DataGrid.type.ts b/apps/st/src/components/type/DataGrid.type.ts index d9bf1997c..1423c7940 100644 --- a/apps/st/src/components/type/DataGrid.type.ts +++ b/apps/st/src/components/type/DataGrid.type.ts @@ -262,6 +262,10 @@ export type TabDataGridProps = { activeTab?: string; /** 활성 탭 변경 시 호출 (제어 모드). activeTab과 함께 넘기면 부모가 탭 상태를 가짐 */ onActiveTabChange?: (tabKey: string) => void; + /** 저장 등 시점에 현재 활성 탭 그리드 데이터를 가져올 수 있도록 할당 (편집 반영된 값) */ + getGridDataRef?: { + current: (() => Record[]) | null; + }; }; export type SplitDataGridProps = { diff --git a/apps/st/src/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn.ts index a02919150..50c16fe40 100644 --- a/apps/st/src/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn.ts +++ b/apps/st/src/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn.ts @@ -6,92 +6,97 @@ import { ValueType } from "realgrid"; export const RegionalFactStatusInpColumn = { columns: [ // 행정구역 - { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, - { name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' }, editable: false }, + { name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false, styleName: 'rg-cell-readonly' }, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, editable: false, styleName: 'rg-cell-readonly' }, + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, editable: false, styleName: 'rg-cell-readonly' }, // 기본 정보 - { name: 'targetYr', fieldName: '하수정비기본계획목표년도', header: { text: '하수정비기본계획목표년도' }}, - { name: 'piplImprnPlanExtn', fieldName: '총관로정비계획연장(m)', header: { text: '총관로정비계획연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'piplPlanExtn', fieldName: '총계획연장(m)', header: { text: '총계획연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'piplFcltyExtn', fieldName: '총시설연장(m)', header: { text: '총시설연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'piplSupprt', fieldName: '하수관로보급률(%)', header: { text: '하수관로보급률(%)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'goalYr', fieldName: 'goalYr', header: { text: '하수정비기본계획목표년도' }}, + { name: 'wholPplMtncPlanPrlg', fieldName: 'wholPplMtncPlanPrlg', header: { text: '총관로정비계획연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'wholPlanPrlg', fieldName: 'wholPlanPrlg', header: { text: '총계획연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'wholFcltPrlg', fieldName: 'wholFcltPrlg', header: { text: '총시설연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'swagePplPsplyRt', fieldName: 'swagePplPsplyRt', header: { text: '하수관로보급률(%)' }, footer: footerDecimal1, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, // 합류식(m) - { name: 'cmbnPlanAr', fieldName: '관로정비계획면적(㎢)', header: { text: '관로정비계획면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'cmbnImprnPlanExtn', fieldName: '관로정비계획연장(m)', header: { text: '관로정비계획연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'cmbnPlanExtn', fieldName: '계획연장(m)', header: { text: '계획연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'cmbnFcltyExtn', fieldName: '시설연장(m)', header: { text: '시설연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'cmbnRctglExtn', fieldName: '사각형(m)', header: { text: '사각형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'cmbnCicleExtn', fieldName: '원형(m)', header: { text: '원형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'cmbnOpswrExtn', fieldName: '개거(m)', header: { text: '개거(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'cmbnSdgttrExtn', fieldName: '측구(m)', header: { text: '측구(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'cbsysPplMtncPlanArea', fieldName: 'cbsysPplMtncPlanArea', header: { text: '관로정비계획면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'cbsysPplMtncPlanPrlg', fieldName: 'cbsysPplMtncPlanPrlg', header: { text: '관로정비계획연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'cbsysPlanPrlg', fieldName: 'cbsysPlanPrlg', header: { text: '계획연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'cbsysFcltPrlg', fieldName: 'cbsysFcltPrlg', header: { text: '시설연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'cbsysSqrePrlg', fieldName: 'cbsysSqrePrlg', header: { text: '사각형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'cbsysCiclPrlg', fieldName: 'cbsysCiclPrlg', header: { text: '원형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'cbsysOpnPrlg', fieldName: 'cbsysOpnPrlg', header: { text: '개거(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'cbsysGttrPrlg', fieldName: 'cbsysGttrPrlg', header: { text: '측구(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, // 분류식(m) > 오수관로 - { name: 'pltwtrPlanAr', fieldName: '관로정비계획면적(㎢)', header: { text: '관로정비계획면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'pltwtrImprnPlanExtn', fieldName: '관로정비계획연장(m)', header: { text: '관로정비계획연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'pltwtrPlanExtn', fieldName: '계획연장(m)', header: { text: '계획연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'pltwtrFlctyExtn', fieldName: '시설연장(m)', header: { text: '시설연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'pltwtrSqreExtn', fieldName: '사각형(m)', header: { text: '사각형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'pltwtrCiclExtn', fieldName: '원형(m)', header: { text: '원형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'drtwPplMtncPlanArea', fieldName: 'drtwPplMtncPlanArea', header: { text: '관로정비계획면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'drtwPplMtncPlanPrlg', fieldName: 'drtwPplMtncPlanPrlg', header: { text: '관로정비계획연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'drtwPplPlanPrlg', fieldName: 'drtwPplPlanPrlg', header: { text: '계획연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'drtwPplFcltPrlg', fieldName: 'drtwPplFcltPrlg', header: { text: '시설연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'drtwPplSqrePrlg', fieldName: 'drtwPplSqrePrlg', header: { text: '사각형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'drtwPplCiclPrlg', fieldName: 'drtwPplCiclPrlg', header: { text: '원형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, // 분류식(m) > 우수관로 - { name: 'rainwtrPlanAr', fieldName: '관로정비계획면적(㎢)', header: { text: '관로정비계획면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, - { name: 'rainwtrImprnPlanExtn', fieldName: '관로정비계획연장(m)', header: { text: '관로정비계획연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'rainwtrPlanExtn', fieldName: '계획연장(m)', header: { text: '계획연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'rainwtrFlctyExtn', fieldName: '시설연장(m)', header: { text: '시설연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'rainwtrSqreExtn', fieldName: '사각형(m)', header: { text: '사각형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'rainwtrCiclExtn', fieldName: '원형(m)', header: { text: '원형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'rainwtrOpswrExtn', fieldName: '개거(m)', header: { text: '개거(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, - { name: 'rainwtrSdgttrExtn', fieldName: '측구(m)', header: { text: '측구(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'exlnPplMtncPlanArea', fieldName: 'exlnPplMtncPlanArea', header: { text: '관로정비계획면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'exlnPplMtncPlanPrlg', fieldName: 'exlnPplMtncPlanPrlg', header: { text: '관로정비계획연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'exlnPplPlanPrlg', fieldName: 'exlnPplPlanPrlg', header: { text: '계획연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'exlnPplFcltPrlg', fieldName: 'exlnPplFcltPrlg', header: { text: '시설연장(m)' }, footer: footerDecimal2, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'exlnPplSqrePrlg', fieldName: 'exlnPplSqrePrlg', header: { text: '사각형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'exlnPplCiclPrlg', fieldName: 'exlnPplCiclPrlg', header: { text: '원형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'exlnPplOpnPrlg', fieldName: 'exlnPplOpnPrlg', header: { text: '개거(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'exlnPplGttrPrlg', fieldName: 'exlnPplGttrPrlg', header: { text: '측구(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, // 합류식맨홀(개소) - { name: 'mnhleSite', fieldName: '합류식맨홀(개소)', header: { text: '합류식맨홀(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'cbsysMnhlCnt', fieldName: 'cbsysMnhlCnt', header: { text: '합류식맨홀(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, // 분류식 > 오수맨홀, 우수맨홀 - { name: 'pltwtrMnhleSite', fieldName: '오수맨홀(개소)', header: { text: '오수맨홀(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'rainwtrMnhleSite', fieldName: '우수맨홀(개소)', header: { text: '우수맨홀(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sprsysDrtwMnhlCnt', fieldName: 'sprsysDrtwMnhlCnt', header: { text: '오수맨홀(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sprsysExlnMnhlCnt', fieldName: 'sprsysExlnMnhlCnt', header: { text: '우수맨홀(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'pltwtrRcvrSite', fieldName: '오수받이(개소)', header: { text: '오수받이(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'rainwtrRcvrSite', fieldName: '빗물받이(개소)', header: { text: '빗물받이(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'soilspllSite', fieldName: '우수토실(개소)', header: { text: '우수토실(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'soilholeSite', fieldName: '우수토구(개소)', header: { text: '우수토구(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'drtwRcvprpCnt', fieldName: 'drtwRcvprpCnt', header: { text: '오수받이(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'exlnRcvprpCnt', fieldName: 'exlnRcvprpCnt', header: { text: '빗물받이(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'stofcbrCnt', fieldName: 'stofcbrCnt', header: { text: '우수토실(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'exlnOtflCnt', fieldName: 'exlnOtflCnt', header: { text: '우수토구(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, // 하수도대장 전산화 - { name: 'sewerRegstrCmptExtn', fieldName: '하수도대장전산화연장(m)', header: { text: '하수도대장전산화연장(m)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, - { name: 'sewerRegstrCmptRt', fieldName: '하수도대장전산화율(%)', header: { text: '하수도대장전산화율(%)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'sewerLdgrEdpPrlg', fieldName: 'sewerLdgrEdpPrlg', header: { text: '하수도대장전산화연장(m)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sewerLdgrEdpRt', fieldName: 'sewerLdgrEdpRt', header: { text: '하수도대장전산화율(%)' }, footer: footerDecimal1, editable: false, styleName: 'rg-cell-readonly', valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, // 비고 - { name: 'rmk', fieldName: '비고', header: { text: '비고' } }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, ], columnLayout: [ { name: 'adminArea', hideChildHeaders: false, header: { text: '행정구역' }, - items: ['sido', 'sgg'], + items: [ + { column: 'ctpvNm', footerUserSpans: [{ colspan: 3 }] }, + 'sggNm', + 'admdstNm', + ], }, - 'targetYr', - 'piplImprnPlanExtn', - 'piplPlanExtn', - 'piplFcltyExtn', - 'piplSupprt', + 'goalYr', + 'wholPplMtncPlanPrlg', + 'wholPlanPrlg', + 'wholFcltPrlg', + 'swagePplPsplyRt', { name: 'combined', hideChildHeaders: false, header: { text: '합류식(m)' }, items: [ - 'cmbnPlanAr', - 'cmbnImprnPlanExtn', - 'cmbnPlanExtn', - 'cmbnFcltyExtn', + 'cbsysPplMtncPlanArea', + 'cbsysPplMtncPlanPrlg', + 'cbsysPlanPrlg', + 'cbsysFcltPrlg', { name: 'cmbnCulvert', hideChildHeaders: false, header: { text: '암거' }, - items: ['cmbnRctglExtn', 'cmbnCicleExtn'], + items: ['cbsysSqrePrlg', 'cbsysCiclPrlg'], }, - 'cmbnOpswrExtn', - 'cmbnSdgttrExtn', + 'cbsysOpnPrlg', + 'cbsysGttrPrlg', ], }, { @@ -104,15 +109,15 @@ export const RegionalFactStatusInpColumn = { hideChildHeaders: false, header: { text: '오수관로' }, items: [ - 'pltwtrPlanAr', - 'pltwtrImprnPlanExtn', - 'pltwtrPlanExtn', - 'pltwtrFlctyExtn', + 'drtwPplMtncPlanArea', + 'drtwPplMtncPlanPrlg', + 'drtwPplPlanPrlg', + 'drtwPplFcltPrlg', { name: 'pltwtrCulvert', hideChildHeaders: false, header: { text: '암거' }, - items: ['pltwtrSqreExtn', 'pltwtrCiclExtn'], + items: ['drtwPplSqrePrlg', 'drtwPplCiclPrlg'], }, ], }, @@ -121,39 +126,39 @@ export const RegionalFactStatusInpColumn = { hideChildHeaders: false, header: { text: '우수관로' }, items: [ - 'rainwtrPlanAr', - 'rainwtrImprnPlanExtn', - 'rainwtrPlanExtn', - 'rainwtrFlctyExtn', + 'exlnPplMtncPlanArea', + 'exlnPplMtncPlanPrlg', + 'exlnPplPlanPrlg', + 'exlnPplFcltPrlg', { name: 'rainwtrCulvert', hideChildHeaders: false, header: { text: '암거' }, - items: ['rainwtrSqreExtn', 'rainwtrCiclExtn'], + items: ['exlnPplSqrePrlg', 'exlnPplCiclPrlg'], }, - 'rainwtrOpswrExtn', - 'rainwtrSdgttrExtn', + 'exlnPplOpnPrlg', + 'exlnPplGttrPrlg', ], }, ], }, - 'mnhleSite', + 'cbsysMnhlCnt', { name: 'separatedManhole', hideChildHeaders: false, header: { text: '분류식' }, - items: ['pltwtrMnhleSite', 'rainwtrMnhleSite'], + items: ['sprsysDrtwMnhlCnt', 'sprsysExlnMnhlCnt'], }, - 'pltwtrRcvrSite', - 'rainwtrRcvrSite', - 'soilspllSite', - 'soilholeSite', - 'sewerRegstrCmptExtn', - 'sewerRegstrCmptRt', - 'rmk', + 'drtwRcvprpCnt', + 'exlnRcvprpCnt', + 'stofcbrCnt', + 'exlnOtflCnt', + 'sewerLdgrEdpPrlg', + 'sewerLdgrEdpRt', + 'rmrk', ], rowStartNum: 4, fixedColumns: 1, - tabKey: 'regionalFactStatusInp', + tabKey: 'ST00020001', tabLabel: '지역별 시설현황' }; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipe/SewagePipeInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipe/SewagePipeInpColumn.ts new file mode 100644 index 000000000..9030d4700 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipe/SewagePipeInpColumn.ts @@ -0,0 +1,17 @@ +import type { ColumnInfoList } from "@/components/type/DataGrid.type"; +import { RegionalFactStatusInpColumn } from "./RegionalFactStatusInpColumn"; +import { FactInstallStatusInpColumn } from "./FactInstallStatusInpColumn"; +import { PipeTypeStatusInpColumn } from "./PipeTypeStatusInpColumn"; +import { PipeDiameterStatusInpColumn } from "./PipeDiameterStatusInpColumn"; +import { ManholeStatusInpColumn } from "./ManholeStatusInpColumn"; +import { ConnectionStatusInpColumn } from "./ConnectionStatusInpColumn"; + +/** 하수관로 입력 탭 컬럼 리스트 (TabDataGrid columnInfo용) */ +export const SewagePipeInpColumnInfoList: ColumnInfoList[] = [ + RegionalFactStatusInpColumn, + FactInstallStatusInpColumn, + PipeTypeStatusInpColumn, + PipeDiameterStatusInpColumn, + ManholeStatusInpColumn, + ConnectionStatusInpColumn, +]; diff --git a/apps/st/src/components/util/column/management/GeneralVerificationColumn.tsx b/apps/st/src/components/util/column/management/GeneralVerificationColumn.tsx new file mode 100644 index 000000000..b61ad9ea3 --- /dev/null +++ b/apps/st/src/components/util/column/management/GeneralVerificationColumn.tsx @@ -0,0 +1,62 @@ +import dayjs from "dayjs"; +import { useState } from "react"; +import type { ColumnDef } from "@tanstack/react-table"; +import { Button } from "@common/components"; +import type { GeneralverificationList } from "@/entities/statistics/model/general-verification-interface"; + +export const GeneralVerificationColumn: ColumnDef[] = [ + { + id: "no", + header: "NO", + cell: ({ row, table }) => { + const totalRows = table.getRowCount(); + const { pageIndex, pageSize } = table.getState().pagination; + return totalRows - (pageIndex * pageSize + row.index); + }, + }, + { + accessorKey: "vrfSn", + header: "일련번호", + enableHiding: true, + }, + { + accessorKey: "tabNm", + header: "통계항목", + }, + { + accessorKey: "vrfNm", + header: "검증명", + }, + { + accessorKey: "vrfClsCd", + header: "검증분류", + }, + { + accessorKey: "useYn", + header: "사용여부", + }, + { + accessorKey: "regDt", + header: "등록일", + cell: ({ row }) => { + const date = dayjs(row.original.regDt); + return date.format("YYYY-MM-DD"); + }, + }, + { + id: "actions", + header: "관리", + cell: ({ row }) => ( +
e.stopPropagation()}> + +
+ ), + }, +]; + +const GeneralVerificationManageButton = ({ vrfSn }: { vrfSn: number }) => { + const [dialogOpen, setDialogOpen] = useState(false); + return ( + + ); +}; diff --git a/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts b/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts index b42f1637a..3c22c517c 100644 --- a/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts +++ b/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts @@ -4,185 +4,195 @@ import type { GridView } from "@/components/type/DataGrid.type"; export const rawPumpingStationInfoList = { columns: [ - /* 1. 행정구역 및 기본정보 */ + { + name: 'ctpvNm', + fieldName: 'ctpvNm', + header: { text: '시도' }, + mergeCells: true, + 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 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) => { + 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) => { + 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) => { + 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: 'pumpstNm', fieldName: 'pumpstNm', header: { text: '펌프장명' }, mergeCells: true }, + { name: 'swtrmtFcltNm', fieldName: 'swtrmtFcltNm', header: { text: '처리장명' } }, // bscFctNm -> swtrmtFcltNm + { name: 'pumpSeNm', fieldName: 'pumpSeNm', header: { text: '구분\n(합류/분류)' } }, // pumpCls -> pumpSeNm + { name: 'impdFcltPstnCn', fieldName: 'impdFcltPstnCn', header: { text: '위치' } }, // addr -> impdFcltPstnCn + { name: 'oprtngStrtYmd', fieldName: 'oprtngStrtYmd', header: { text: '가동년월일' } }, // rnDt -> oprtngStrtYmd { - name: 'sido', - fieldName: 'sido', - header: { text: '시도' }, - mergeCells: true, - 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, sortdisable: true }, - { name: 'pumpNm', fieldName: 'pumpNm', header: { text: '펌프장명' }, mergeCells: true, sortdisable: true }, - { - name: 'displayYear', - fieldName: 'displayYear', - header: { text: '구분' }, - 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: '위치' } }, - { name: 'rnDt', fieldName: 'rnDt', header: { text: '가동년월일\nyyyy-mm-dd' } }, - { - name: 'planDrhgAr', fieldName: 'planDrhgAr', header: { text: '계획배수면적\n(km2)' }, + name: 'planMltvArea', fieldName: 'planMltvArea', header: { text: '계획배수면적\n(km2)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, /* 2. 계획배수량 (m3/hr) */ - { 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' }, + { name: 'sndyArea', fieldName: 'sndyArea', header: { text: '청천시(A)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // finewtDrngVl -> sndyArea + { name: 'rainArea', fieldName: 'rainArea', header: { text: '우천시(B)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // rainwtDrngVl -> rainArea + { name: 'exlnQnt', fieldName: 'exlnQnt', header: { text: '우수량(B-A)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // vlWtr -> exlnQnt /* 3. 총 양수량 (m3/min) */ - { 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' }, + { name: 'drtwPumpGrssPpqty', fieldName: 'drtwPumpGrssPpqty', header: { text: '오수펌프\n총양수량' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // pltwtrTotCpcty -> drtwPumpGrssPpqty + { name: 'exlnPumpGrssPpqty', fieldName: 'exlnPumpGrssPpqty', header: { text: '우수펌프\n총양수량' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // rainwtrTotCpcty -> exlnPumpGrssPpqty /* 4. 오수펌프 상세 (1, 2, 3) */ - { 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: 'drtwPumpN1DmtrArea', fieldName: 'drtwPumpN1DmtrArea', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // pltwtrPumpCalbr1 -> drtwPumpN1DmtrArea + { name: 'drtwPumpN1Ppqty', fieldName: 'drtwPumpN1Ppqty', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // pltwtrPumpCpcty1 -> drtwPumpN1Ppqty + { name: 'drtwPumpN1Cnt', fieldName: 'drtwPumpN1Cnt', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, // pltwtrPumpCnt1 -> drtwPumpN1Cnt + { name: 'drtwPumpN1RsrvCnt', fieldName: 'drtwPumpN1RsrvCnt', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, // pltwtrPumpPreparCnt1 -> drtwPumpN1RsrvCnt - { 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: 'drtwPumpN2DmtrArea', fieldName: 'drtwPumpN2DmtrArea', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drtwPumpN2Ppqty', fieldName: 'drtwPumpN2Ppqty', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drtwPumpN2Cnt', fieldName: 'drtwPumpN2Cnt', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'drtwPumpN2RsrvCnt', fieldName: 'drtwPumpN2RsrvCnt', header: { text: '예비대수' }, footer: footerIntArrayByDivision, 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' }, + { name: 'drtwPumpN3DmtrArea', fieldName: 'drtwPumpN3DmtrArea', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drtwPumpN3Ppqty', fieldName: 'drtwPumpN3Ppqty', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drtwPumpN3Cnt', fieldName: 'drtwPumpN3Cnt', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'drtwPumpN3RsrvCnt', fieldName: 'drtwPumpN3RsrvCnt', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, - /* 5. 우수펌프 상세 (1, 2, 3) */ - { 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' }, + /* 5. 우수펌프 상세 (1, 2, 3) - N1, N2, N3*/ + { name: 'exlnPumpN1DmtrArea', fieldName: 'exlnPumpN1DmtrArea', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // rainwtrPumpCalbr1 -> exlnPumpN1DmtrArea + { name: 'exlnPumpN1Ppqty', fieldName: 'exlnPumpN1Ppqty', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // rainwtrPumpCpcty1 -> exlnPumpN1Ppqty + { name: 'exlnPumpN1Cnt', fieldName: 'exlnPumpN1Cnt', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, // rainwtrPumpCnt1 -> exlnPumpN1Cnt + { name: 'exlnPumpN4RsrvCnt', fieldName: 'exlnPumpN4RsrvCnt', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, // rainwtrPumpPreparCnt1 -> exlnPumpN4RsrvCnt + + { name: 'exlnPumpN2DmtrArea', fieldName: 'exlnPumpN2DmtrArea', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'exlnPumpN2Ppqty', fieldName: 'exlnPumpN2Ppqty', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'exlnPumpN2Cnt', fieldName: 'exlnPumpN2Cnt', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'exlnPumpN2RsrvCnt', fieldName: 'exlnPumpN2RsrvCnt', header: { text: '예비대수' }, footer: footerIntArrayByDivision, 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: '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' }, + { name: 'exlnPumpN3DmtrArea', fieldName: 'exlnPumpN3DmtrArea', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'exlnPumpN3Ppqty', fieldName: 'exlnPumpN3Ppqty', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'exlnPumpN3Cnt', fieldName: 'exlnPumpN3Cnt', header: { text: '펌프대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'exlnPumpN3RsrvCnt', fieldName: 'exlnPumpN3RsrvCnt', header: { text: '예비대수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, /* 6. 기타 및 운영 */ - { name: 'elcpwAmnt', fieldName: 'elcpwAmnt', header: { text: '연간전력사용량\n(kWh/년)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + { name: 'anlElpwrUseQnt', fieldName: 'anlElpwrUseQnt', header: { text: '연간전력사용량\n(kWh/년)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, // elcpwAmnt -> anlElpwrUseQnt + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, ], columnLayout: [ { name: 'groupA', header: { text: '행정구역' }, items: [ - { column: 'sido', footerUserSpans: [{ colspan: 3 }, { colspan: 3 }] }, - 'gugun', - 'pumpNm', + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'sggNm', ] }, + 'pumpstNm', 'displayYear', - 'bscFctNm', - 'pumpCls', - 'addr', - 'rnDt', - 'planDrhgAr', + 'swtrmtFcltNm', + 'pumpSeNm', + 'impdFcltPstnCn', + 'oprtngStrtYmd', + 'planMltvArea', { name: 'groupB', header: { text: '계획시간대최대배수량(m3/hr)' }, - items: ['finewtDrngVl', 'rainwtDrngVl', 'vlWtr'], + items: ['sndyArea', 'rainArea', 'exlnQnt'], }, { name: 'groupC', header: { text: '배수능력' }, items: [ - 'pltwtrTotCpcty', + 'drtwPumpGrssPpqty', { name: 'pumpO_Detail', header: { text: '오수펌프 상세' }, items: [ - { 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'] } + { name: 'O1', header: { text: '오수펌프(1)' }, items: ['drtwPumpN1DmtrArea', 'drtwPumpN1Ppqty', 'drtwPumpN1Cnt', 'drtwPumpN1RsrvCnt'] }, + { name: 'O2', header: { text: '오수펌프(2)' }, items: ['drtwPumpN2DmtrArea', 'drtwPumpN2Ppqty', 'drtwPumpN2Cnt', 'drtwPumpN2RsrvCnt'] }, + { name: 'O3', header: { text: '오수펌프(3)' }, items: ['drtwPumpN3DmtrArea', 'drtwPumpN3Ppqty', 'drtwPumpN3Cnt', 'drtwPumpN3RsrvCnt'] } ] }, - 'rainwtrTotCpcty', + 'exlnPumpGrssPpqty', { name: 'pumpW_Detail', header: { text: '우수펌프 상세' }, items: [ - { 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'] } + { name: 'W1', header: { text: '우수펌프(1)' }, items: ['exlnPumpN1DmtrArea', 'exlnPumpN1Ppqty', 'exlnPumpN1Cnt', 'exlnPumpN4RsrvCnt'] }, + { name: 'W2', header: { text: '우수펌프(2)' }, items: ['exlnPumpN2DmtrArea', 'exlnPumpN2Ppqty', 'exlnPumpN2Cnt', 'exlnPumpN2RsrvCnt'] }, + { name: 'W3', header: { text: '우수펌프(3)' }, items: ['exlnPumpN3DmtrArea', 'exlnPumpN3Ppqty', 'exlnPumpN3Cnt', 'exlnPumpN3RsrvCnt'] } ] } ], }, - 'elcpwAmnt', - 'rmk', + 'anlElpwrUseQnt', + 'rmrk', ], - fixedColumns: 2, + fixedColumns: 3, rowStartNum: 3 }; diff --git a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts index cbc536253..de413a34b 100644 --- a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts @@ -93,14 +93,19 @@ const rawMaintainList = [ } ] }, + /* 전체보수 (m) */ { 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' }, @@ -108,6 +113,8 @@ const rawMaintainList = [ { 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: '비고' } }, ], @@ -116,7 +123,7 @@ const rawMaintainList = [ name: 'addrGroup', header: { text: '행정구역' }, items: [ - { column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }, { colspan: 2 }] }, + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, 'sggNm', 'admdstNm', ] @@ -148,10 +155,9 @@ const rawMaintainList = [ rowStartNum: 4, fixedColumns: 2, columns: [ - /* 1. 행정 및 기본 정보 */ - { - name: 'sido', - fieldName: 'sido', + { + name: 'ctpvNm', + fieldName: 'ctpvNm', header: { text: '시도' }, mergeCells: true, sortdisable: true, @@ -164,7 +170,9 @@ const rawMaintainList = [ const uniqueValues = new Set(); for (let i = 0; i < rowCount; i++) { const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue) uniqueValues.add(String(divisionValue)); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } } const divisionValues = Array.from(uniqueValues); return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; @@ -178,7 +186,9 @@ const rawMaintainList = [ const uniqueValues = new Set(); for (let i = 0; i < rowCount; i++) { const divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue) uniqueValues.add(String(divisionValue)); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } } const divisionValues = Array.from(uniqueValues); return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; @@ -186,7 +196,8 @@ const rawMaintainList = [ } ] }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true }, { name: 'displayYear', fieldName: 'displayYear', @@ -195,83 +206,101 @@ const rawMaintainList = [ footer: [ { valueCallback: (grid: GridView) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); 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)); + 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 > 0 ? divisionValues[0] + ' 합계' : ''; + 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 < grid.getDataSource().getRowCount(); i++) { - const val = grid.getDataSource().getValue(i, 'displayYear'); - if (val) uniqueValues.add(String(val)); + 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 > 1 ? divisionValues[1] + ' 합계' : ''; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; } } ] }, + /* 2. 시설 기본 정보 */ + { name: 'wholFcltPrlg', fieldName: 'wholFcltPrlg', header: { text: '하수관로\n총시설연장\n(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, - /* 2. 시설 기본 정보 */ - { name: 'piplFcltyExtn', fieldName: 'piplFcltyExtn', header: { text: '하수관로\n총시설연장\n(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + /* 3. 준설연장 및 개소수 */ + { name: 'wholSwagePpl', fieldName: 'wholSwagePpl', header: { text: '합계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'cbsysPplPrlg', fieldName: 'cbsysPplPrlg', header: { text: '합류식' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'sprsysExlnPrlg', fieldName: 'sprsysExlnPrlg', header: { text: '우수' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'sprsysDrtwPrlg', fieldName: 'sprsysDrtwPrlg', header: { text: '오수' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'mnhlCnt', fieldName: 'mnhlCnt', header: { text: '맨홀\n(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'exlnDrtwRcvprpCnt', fieldName: 'exlnDrtwRcvprpCnt', header: { text: '오·우수받이\n(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'stofcbrOtflCnt', fieldName: 'stofcbrOtflCnt', header: { text: '토실·토구\n(개소)' }, footer: footerIntArrayByDivision, 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: 'drdgnPlanPrlg', fieldName: 'drdgnPlanPrlg', header: { text: '준설 계획\n연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'drdgnTrgtCtrsDrdgnRt', fieldName: 'drdgnTrgtCtrsDrdgnRt', header: { text: '계획대비\n준설율\n(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'wholPrlgCtrsDrdgnRt', fieldName: 'wholPrlgCtrsDrdgnRt', header: { text: '전체연장대비\n준설율(%)' }, footer: footerAvgDecimalArrayByDivision, 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: 'drdgnAmt', fieldName: 'drdgnAmt', header: { text: '금액\n(백만원)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'drdgnQnt', fieldName: 'drdgnQnt', header: { text: '준설량\n(㎥)' }, footer: footerIntArrayByDivision, 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: 'drdgnUntprcAmt', fieldName: 'drdgnUntprcAmt', header: { text: '준설단가\n(원/m3)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'wholDrdgnPrcsQnt', fieldName: 'wholDrdgnPrcsQnt', header: { text: '처리량 계\n(톤)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rclmQnt', fieldName: 'rclmQnt', header: { text: '매립' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'oceanEmsnQnt', fieldName: 'oceanEmsnQnt', header: { text: '해양방출' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rcycQnt', fieldName: 'rcycQnt', header: { text: '재활용' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'etcQnt', fieldName: 'etcQnt', header: { text: '기타' }, footer: footerAvgDecimalArrayByDivision, 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', 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' - ] - } + /* 7. 기타 및 의견 */ + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'addrGroup', + header: { text: '행정구역' }, + items: [ + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, // sido -> ctpvNm + 'sggNm', + 'admdstNm' + ] + }, + 'displayYear', + 'wholFcltPrlg', + { + name: 'drdgGroup', header: { text: '준설연장 및 개소수' }, + items: [ + { + name: 'pipeLenGroup', header: { text: '관로(m)' }, + items: ['wholSwagePpl', 'cbsysPplPrlg', { name: 'sepRepairGroup', header: { text: '분류식' }, items: ['sprsysExlnPrlg', 'sprsysDrtwPrlg'] }] + }, + 'mnhlCnt', 'exlnDrtwRcvprpCnt', 'stofcbrOtflCnt' + ] + }, + 'drdgnPlanPrlg', 'drdgnTrgtCtrsDrdgnRt', 'wholPrlgCtrsDrdgnRt', + { name: 'acmsltGroup', header: { text: '준설실적' }, items: ['drdgnAmt', 'drdgnQnt'] }, + { + name: 'processGroup', header: { text: '준설토사처리' }, + items: ['drdgnUntprcAmt', 'wholDrdgnPrcsQnt', 'rclmQnt', 'oceanEmsnQnt', 'rcycQnt', 'etcQnt'] + }, + 'rmrk' + ] +} ]; export const SewagePipeMaintainColumnInfoList = rawMaintainList.map(tab => ({ diff --git a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts index 1020ce3bc..ae445b22d 100644 --- a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts @@ -10,553 +10,525 @@ const rawList = [ tabLabel: '지역별 시설현황', rowStartNum: 4, fixedColumns: 2, - columns: [ + columns: [ + { + name: 'ctpvNm', + fieldName: 'ctpvNm', + header: { text: '시도' }, + mergeCells: true, + sortdisable: true, + footer: [ { - name: 'ctpvNm', - fieldName: 'ctpvNm', - header: { text: '시도' }, - mergeCells: true, - 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] + '합계' : '합계'; - } + 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] + '합계' : '합계'; + } }, - { 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) => { - 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] + '합계' : ''; - } + 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)); } - ] - }, - - /* 하수정비 기본계획 */ - { name: 'targetYr', fieldName: 'targetYr', header: { text: '하수정보기본계획목표년도' } }, - { 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: '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' }, - { name: 'cmbnCicleExtn', fieldName: 'cmbnCicleExtn', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'cmbnOpswrExtn', fieldName: 'cmbnOpswrExtn', header: { text: '개거(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, - { name: 'cmbnSdgttrExtn', fieldName: 'cmbnSdgttrExtn', header: { text: '측구(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: '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: '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: '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: '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: '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: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, - 'sggNm', - 'admdstNm', - ] - }, - 'displayYear', - 'targetYr', 'swrgPipeMntnPlanExtn', 'swrgPipePlanExtn', 'swrgPipeFcltyExtn', 'swrgPipePsplyRt', - { - name: 'combinedGroup', header: { text: '합류식(m)' }, - items: ['cmbnMntnPlanAr', 'cmbnMntnPlanExtn', 'cmbnPlanExtn', 'cmbnFcltyExtn', - { name: 'cmbnAmGroup', header: { text: '암거' }, items: ['cmbnRctglExtn', 'cmbnCicleExtn'] }, - 'cmbnOpswrExtn', 'cmbnSdgttrExtn' - ], - }, - { - name: 'sepGroup', header: { text: '분류식(m)' }, - items: [ - { - name: 'foulPipeGroup', header: { text: '오수관로' }, - items: ['pltwtrMntnPlanAr', 'pltwtrMntnPlanExtn', 'pltwtrPlanExtn', 'pltwtrFcltyExtn', - { name: 'foulAmGroup', header: { text: '암거' }, items: ['pltwtrRctglExtn', 'pltwtrCicleExtn'] }] - }, - { - name: 'rainPipeGroup', header: { text: '우수관로' }, - items: ['rainwtrMntnPlanAr', 'rainwtrMntnPlanExtn', 'rainwtrPlanExtn', 'rainwtrFcltyExtn', - { name: 'rainAmGroup', header: { text: '암거' }, items: ['rainwtrRctglExtn', 'rainwtrCicleExtn'] }, - 'rainwtrOpswrExtn', 'rainwtrSdgttrExtn'] - } - ], - }, - 'cmbnMnhleCnt', - { name: 'fcltyGroup', header: { text: '부속시설(개소)' }, items: ['pltwtrMnhleCnt', 'rainwtrMnhleCnt'] }, - 'pltwtrRcvrCnt', 'rainwtrRcvrCnt', 'rainwtrChmbrCnt', 'rainwtrOutltCnt', 'swrgRegstrCmptExtn', 'swrgRegstrCmptRt', 'rmrk' + 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 }, { - tabKey: 'ST00020002', - tabLabel: '시설별 설치현황', - rowStartNum: 4, - fixedColumns: 3, - columns: [ + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + sortdisable: true, + footer: [ { - name: 'ctpvNm', - fieldName: 'ctpvNm', - header: { text: '시도' }, - mergeCells: true, - 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 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) => { - 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) => { + 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] + '합계' : ''; + } }, - { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, - { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true, sortdisable: true }, - { name: 'swrmtFcltyNm', fieldName: 'swrmtFcltyNm', header: { text: '하수처리시설 명' }, mergeCells: true, mergeGroupField: 'admdstNm' }, { - name: 'displayYear', - fieldName: 'displayYear', - header: { text: '구분' }, - 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)); - } - return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[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)); - } - return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[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)); } - ] - }, - { 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: '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: '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: '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: '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: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, - 'sggNm', - 'admdstNm', - 'swrmtFcltyNm', - ] - }, - 'swrmtFcltyCpc', - 'displayYear', - { name: 'areaGroup', header: { text: '처리구역면적(㎢)' }, items: ['procZoneArSm', 'cmbnProcZoneAr', 'sprsysProcZoneAr'] }, - { - name: 'drainGroup', header: { text: '배수설비(개소)' }, - items: ['drngEqpSm', 'cmbnDrngEqp', 'sprsysDrngEqpSm'], - }, - { - name: 'pipeGroup', header: { text: '하수관로' }, - items: [ - 'swrgPipeFcltyExtn', - { name: 'trunkGroup', header: { text: '차집/오수간선(m)' }, items: ['icgPltwtrMnnSm', 'icgExtn', 'pltwtrMnnExtn'] }, - { - name: 'siteGroup', header: { text: '토실/토구(개소)' }, - items: [ - { 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: ['sprsysExlnBrnchlnExtn', 'sprsysDrtwBrnchlnExtn'] }] - } - ], - }, - 'rmrk' + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } ] }, + + /* 하수정비 기본계획 및 총계 */ + { name: 'goalYr', fieldName: 'goalYr', header: { text: '하수정보기본계획목표년도' } }, + { name: 'wholPplMtncPlanPrlg', fieldName: 'wholPplMtncPlanPrlg', header: { text: '총관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'wholPlanPrlg', fieldName: 'wholPlanPrlg', header: { text: '총계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'wholFcltPrlg', fieldName: 'wholFcltPrlg', header: { text: '총시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'swagePplPsplyRt', fieldName: 'swagePplPsplyRt', header: { text: '하수관로\n보급률(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + /* 합류식 */ + { name: 'cbsysPplMtncPlanArea', fieldName: 'cbsysPplMtncPlanArea', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'cbsysPplMtncPlanPrlg', fieldName: 'cbsysPplMtncPlanPrlg', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cbsysPlanPrlg', fieldName: 'cbsysPlanPrlg', header: { text: '계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cbsysFcltPrlg', fieldName: 'cbsysFcltPrlg', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cbsysSqrePrlg', fieldName: 'cbsysSqrePrlg', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cbsysCiclPrlg', fieldName: 'cbsysCiclPrlg', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cbsysOpnPrlg', fieldName: 'cbsysOpnPrlg', header: { text: '개거(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cbsysGttrPrlg', fieldName: 'cbsysGttrPrlg', header: { text: '측구(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + /* 분류식 - 오수관로 */ + { name: 'drtwPplMtncPlanArea', fieldName: 'drtwPplMtncPlanArea', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'drtwPplMtncPlanPrlg', fieldName: 'drtwPplMtncPlanPrlg', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'drtwPplPlanPrlg', fieldName: 'drtwPplPlanPrlg', header: { text: '계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'drtwPplFcltPrlg', fieldName: 'drtwPplFcltPrlg', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'drtwPplSqrePrlg', fieldName: 'drtwPplSqrePrlg', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'drtwPplCiclPrlg', fieldName: 'drtwPplCiclPrlg', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + /* 분류식 - 우수관로 */ + { name: 'exlnPplMtncPlanArea', fieldName: 'exlnPplMtncPlanArea', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'exlnPplMtncPlanPrlg', fieldName: 'exlnPplMtncPlanPrlg', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'exlnPplPlanPrlg', fieldName: 'exlnPplPlanPrlg', header: { text: '계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'exlnPplFcltPrlg', fieldName: 'exlnPplFcltPrlg', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'exlnPplSqrePrlg', fieldName: 'exlnPplSqrePrlg', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'exlnPplCiclPrlg', fieldName: 'exlnPplCiclPrlg', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'exlnPplOpnPrlg', fieldName: 'exlnPplOpnPrlg', header: { text: '개거(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'exlnPplGttrPrlg', fieldName: 'exlnPplGttrPrlg', header: { text: '측구(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + /* 부속시설 */ + { name: 'cbsysMnhlCnt', fieldName: 'cbsysMnhlCnt', header: { text: '합류식맨홀(개소)' }, 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: 'exlnOtflCnt', fieldName: 'exlnOtflCnt', header: { text: '우수토구(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 대장 및 기타*/ + { name: 'sewerLdgrEdpPrlg', fieldName: 'sewerLdgrEdpPrlg', header: { text: '하수도대장전산화연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sewerLdgrEdpRt', fieldName: 'sewerLdgrEdpRt', header: { text: '하수도대장전산화율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, +], + columnLayout: [ + { + name: 'areaGroup', header: { text: '행정구역' }, items: [ + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'sggNm', + 'admdstNm', + ] + }, + 'displayYear', + 'goalYr', 'wholPplMtncPlanPrlg', 'wholPlanPrlg', 'wholFcltPrlg', 'swagePplPsplyRt', + { + name: 'combinedGroup', header: { text: '합류식(m)' }, + items: ['cbsysPplMtncPlanArea', 'cbsysPplMtncPlanPrlg', 'cbsysPlanPrlg', 'cbsysFcltPrlg', + { name: 'cmbnAmGroup', header: { text: '암거' }, items: ['cbsysSqrePrlg', 'cbsysCiclPrlg'] }, + 'cbsysOpnPrlg', 'cbsysGttrPrlg' + ], + }, + { + name: 'sepGroup', header: { text: '분류식(m)' }, + items: [ + { + name: 'foulPipeGroup', header: { text: '오수관로' }, + items: ['drtwPplMtncPlanArea', 'drtwPplMtncPlanPrlg', 'drtwPplPlanPrlg', 'drtwPplFcltPrlg', + { name: 'foulAmGroup', header: { text: '암거' }, items: ['drtwPplSqrePrlg', 'drtwPplCiclPrlg'] }] + }, + { + name: 'rainPipeGroup', header: { text: '우수관로' }, + items: ['exlnPplMtncPlanArea', 'exlnPplMtncPlanPrlg', 'exlnPplPlanPrlg', 'exlnPplFcltPrlg', + { name: 'rainAmGroup', header: { text: '암거' }, items: ['exlnPplSqrePrlg', 'exlnPplCiclPrlg'] }, + 'exlnPplOpnPrlg', 'exlnPplGttrPrlg'] + } + ], + }, + 'cbsysMnhlCnt', + { name: 'fcltyGroup', header: { text: '분류식' }, items: ['sprsysDrtwMnhlCnt', 'sprsysExlnMnhlCnt'] }, + 'drtwRcvprpCnt', 'exlnRcvprpCnt', 'stofcbrCnt', 'exlnOtflCnt', 'sewerLdgrEdpPrlg', 'sewerLdgrEdpRt', 'rmrk' + ] + }, + { + tabKey: 'ST00020002', + tabLabel: '시설별 설치현황', + rowStartNum: 4, + fixedColumns: 4, + columns: [ + { + name: 'ctpvNm', + fieldName: 'ctpvNm', + header: { text: '시도' }, + mergeCells: true, + 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 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) => { + 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: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true, sortdisable: true }, + { name: 'swtrmtFcltNm', fieldName: 'swtrmtFcltNm', header: { text: '하수처리시설 명' }, mergeCells: true, mergeGroupField: 'admdstNm' }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + 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)); + } + return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[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)); + } + return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[divisionIndex] + ' 합계' : ''; + } + } + ] + }, + { name: 'prcsFcltCpct', fieldName: 'prcsFcltCpct', header: { text: '하수처리\n시설용량\n(㎥/일)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'prcsZoneArea', fieldName: 'prcsZoneArea', header: { text: '합계' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'cbsysPrcsZoneArea', fieldName: 'cbsysPrcsZoneArea', header: { text: '합류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'sprsysPrcsZoneArea', fieldName: 'sprsysPrcsZoneArea', header: { text: '분류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'sprsysVartnRt', fieldName: 'sprsysVartnRt', header: { text: '분류식화' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'mltvEqpmCnt', fieldName: 'mltvEqpmCnt', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'cbsysMltvEqpmCnt', fieldName: 'cbsysMltvEqpmCnt', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysMltvEqpmCnt', fieldName: 'sprsysMltvEqpmCnt', header: { text: '분류식 합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'wholFcltPrlg', fieldName: 'wholFcltPrlg', header: { text: '총\n시설연장\n(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'wholIcptgAtlfcPrlg', fieldName: 'wholIcptgAtlfcPrlg', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'icptgPrlg', fieldName: 'icptgPrlg', header: { text: '차집' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'atlfcsPrlg', fieldName: 'atlfcsPrlg', header: { text: '오수간선' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cbsysStofcbrCnt', fieldName: 'cbsysStofcbrCnt', header: { text: '우수토실(합류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysStofcbrCnt', fieldName: 'sprsysStofcbrCnt', header: { text: '우수토실(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprsysExlnOtflCnt', fieldName: 'sprsysExlnOtflCnt', header: { text: '우수토구(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'wholBrchlnPrlg', fieldName: 'wholBrchlnPrlg', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cbsysBrchlnPrlg', fieldName: 'cbsysBrchlnPrlg', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'exlnBrchlnPrlg', fieldName: 'exlnBrchlnPrlg', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'drtwBrchlnPrlg', fieldName: 'drtwBrchlnPrlg', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, +], + columnLayout: [ + { + name: 'addrGroup', header: { text: '행정구역' }, + items: [ + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'sggNm', 'admdstNm' + ] + }, + 'swtrmtFcltNm','prcsFcltCpct', 'displayYear', + { name: 'areaGroup', header: { text: '처리구역면적(㎢)' }, items: ['prcsZoneArea', 'cbsysPrcsZoneArea', 'sprsysPrcsZoneArea'] }, // name 변경됨 + 'sprsysVartnRt', + { name: 'drainGroup', header: { text: '배수설비(개소)' }, items: ['mltvEqpmCnt', 'cbsysMltvEqpmCnt', 'sprsysMltvEqpmCnt'] }, // name 변경됨 + { + name: 'pipeGroup', header: { text: '하수관로' }, + items: [ + 'wholFcltPrlg', + { name: 'trunkGroup', header: { text: '차집/오수간선(m)' }, items: ['wholIcptgAtlfcPrlg', 'icptgPrlg', 'atlfcsPrlg'] }, // name 변경됨 + { + name: 'siteGroup', header: { text: '토실/토구(개소)' }, + items: [ + { name: 'cmbnSiteGroup', header: { text: '합류식' }, items: ['cbsysStofcbrCnt'] }, + { name: 'sepSiteGroup', header: { text: '분류식' }, items: ['sprsysStofcbrCnt', 'sprsysExlnOtflCnt'] } + ] + }, + { + name: 'branchGroup', header: { text: '지선(m)' }, + items: ['wholBrchlnPrlg', 'cbsysBrchlnPrlg', { name: 'sepBranchGroup', header: { text: '분류식' }, items: ['exlnBrchlnPrlg', 'drtwBrchlnPrlg'] }] + } + ], + }, + 'rmrk' +] + }, { tabKey: 'ST00020003', tabLabel: '관종별 현황', rowStartNum: 2, - fixedColumns: 3, - columns: [ + fixedColumns: 2, + columns: [ + { + name: 'ctpvNm', + fieldName: 'ctpvNm', + header: { text: '시도' }, + mergeCells: true, + sortdisable: true, + footer: [ { - name: 'sido', - fieldName: 'sido', - header: { text: '시도' }, - mergeCells: true, - 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 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) => { - 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] + '합계' : '합계'; - } + 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] + '합계' : '합계'; + } }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, - { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true }, { - name: 'displayYear', - fieldName: 'displayYear', - header: { text: '구분' }, - 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 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) => { - 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] + '합계' : ''; - } + 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)); } - ] - }, - - /* 총계 필드 */ - { 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: `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: '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: [ - - { 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' + 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, sortdisable: true }, + { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + 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)); + } + return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[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)); + } + return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[divisionIndex] + '합계' : ''; + } + } + ] + }, + + { name: 'pipeByPrstWholSum', fieldName: 'pipeByPrstWhol', header: { text: '계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'lyngPrlgSum', fieldName: 'lyngPrlg', header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'dmltnPrlgSum', fieldName: 'dmltnPrlg', header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 동적 연도 컬럼 (1996년이전[yy30] ~ 2025년[yy1]) */ + ...Array.from({ length: 30 }, (_, i) => { + const dtoNum = 30 - i; // 30, 29, ..., 1 + + const wholField = `yy${dtoNum}PrlgWhol`; + const lyngField = `yy${dtoNum}LyngPrlg`; + const dmltnField = `yy${dtoNum}DmltnPrlg`; + + return [ + { name: `${wholField}_col`, fieldName: wholField, header: { text: '계' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: `${lyngField}_col`, fieldName: lyngField, header: { text: '매설연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: `${dmltnField}_col`, fieldName: dmltnField, header: { text: '철거연장(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' } + ]; + }).flat(), + + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, + ],columnLayout: [ + { name: 'areaGroup', header: { text: '행정구역' }, items: ['ctpvNm', 'sggNm', 'swrgPipeNm'] }, + 'displayYear', + { name: 'summaryGroup', header: { text: '총계' }, items: ['pipeByPrstWholSum','lyngPrlgSum', 'dmltnPrlgSum'] }, + + ...Array.from({ length: 30 }, (_, i) => { + const dtoNum = 30 - i; + const yearLabel = i === 0 ? '1996년이전' : `${1995 + i}년`; + const wholField = `yy${dtoNum}PrlgWhol`; + + return { + name: `group_${yearLabel}`, + header: { text: yearLabel }, + items: [`${wholField}_col`, `yy${dtoNum}LyngPrlg_col`, `yy${dtoNum}DmltnPrlg_col`] + }; + }), + 'rmrk' + ] + }, { tabKey: 'ST00020004', tabLabel: '관경별 현황', rowStartNum: 2, fixedColumns: 3, - columns: [ + columns: [ + { + name: 'ctpvNm', + fieldName: 'ctpvNm', + header: { text: '시도' }, + mergeCells: true, + sortdisable: true, + footer: [ { - name: 'sido', - fieldName: 'sido', - header: { text: '시도' }, - mergeCells: true, - 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 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) => { - 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) => { + 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] + '합계' : '합계'; + } }, - { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, - { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true }, { - name: 'displayYear', - fieldName: 'displayYear', - header: { text: '구분' }, - 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 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) => { - 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) => { + 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)); } - ] - }, - - { 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' + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + } ] + }, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, // gugun -> sggNm + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true, sortdisable: true }, + { name: 'swrgPipeNm', fieldName: 'swrgPipeNm', header: { text: '관종' }, mergeCells: true }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + 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)); + } + return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[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)); + } + return Array.from(uniqueValues)[divisionIndex] ? Array.from(uniqueValues)[divisionIndex] + '합계' : ''; + } + } + ] + }, + + /* 관경별 수치 필드 */ + { name: 'pdmtByTsmWhol', fieldName: 'pdmtByTsmWhol', header: { text: '총계(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'step1PdmtPrlg', fieldName: 'step1PdmtPrlg', header: { text: '200mm 미만' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'step2PdmtPrlg', fieldName: 'step2PdmtPrlg', header: { text: '200mm이상~\n300mm미만' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'step3PdmtPrlg', fieldName: 'step3PdmtPrlg', header: { text: '300mm이상~\n500mm미만' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'step4PdmtPrlg', fieldName: 'step4PdmtPrlg', header: { text: '500mm이상~\n800mm미만' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'step5PdmtPrlg', fieldName: 'step5PdmtPrlg', header: { text: '800mm 이상' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'sqrePdmtPrlg', fieldName: 'sqrePdmtPrlg', header: { text: '사각형(m)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'etcPdmtPrlg', fieldName: 'etcPdmtPrlg', header: { text: '기타\n(측구/개거 등)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, // rmk -> rmrk +], + columnLayout: [ + { + name: 'addrGroup', + header: { text: '행정구역' }, + items: [ + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'sggNm', + 'admdstNm', + ] + }, + 'swrgPipeNm', + 'displayYear', + 'pdmtByTsmWhol', + { + name: 'circleGroup', + header: { text: '원형(m)' }, + items: ['step1PdmtPrlg', 'step2PdmtPrlg', 'step3PdmtPrlg', 'step4PdmtPrlg', 'step5PdmtPrlg'] // 이름 일괄 변경 + }, + 'sqrePdmtPrlg', + 'etcPdmtPrlg', + 'rmrk' +] } ]; diff --git a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts index 83d0ab65a..d6bc43849 100644 --- a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts +++ b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts @@ -1,5 +1,4 @@ import { ValueType } from "realgrid"; - import { footerIntArrayByDivision, footerDecimal1ArrayByDivision, @@ -13,12 +12,12 @@ const rawReservoirList = [ tabKey: 'ST00040001', tabLabel: '하수저류시설현황', rowStartNum: 3, - fixedColumns: 2, + fixedColumns: 4, columns: [ /* 1. 기본 정보 */ { - name: 'sido', - fieldName: 'sido', + name: 'ctpvNm', + fieldName: 'ctpvNm', header: { text: '시도' }, mergeCells: true, sortdisable: true, @@ -36,8 +35,7 @@ const rawReservoirList = [ } } const divisionValues = Array.from(uniqueValues); - if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; - return '합계'; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : '합계'; } }, { @@ -53,15 +51,15 @@ const rawReservoirList = [ } } 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: 'swgeStrgeNm', fieldName: 'swgeStrgeNm', header: { text: '시설명' }, mergeCells: true }, - { name: 'addr', fieldName: 'addr', header: { text: '위치' }, mergeCells: true}, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true }, + { name: 'impdFcltNm', fieldName: 'impdFcltNm', header: { text: '저류시설명' }, mergeCells: true, sortdisable: true }, + { name: 'impdFcltPstnCn', fieldName: 'impdFcltPstnCn', header: { text: '저류시설위치' }, mergeCells: true, sortdisable: true }, { name: 'displayYear', fieldName: 'displayYear', @@ -81,7 +79,7 @@ const rawReservoirList = [ } } const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; } }, { @@ -97,82 +95,84 @@ const rawReservoirList = [ } } const divisionValues = Array.from(uniqueValues); - return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + ' 합계' : ''; } } ] }, - /* 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 }, + /* 2. 시설 제원 */ + { name: 'oprtngStrtYmd', fieldName: 'oprtngStrtYmd', header: { text: '가동개시 년월일' } }, + { name: 'planDesignFreqCnt', fieldName: 'planDesignFreqCnt', header: { text: '계획설계빈도' } }, + { name: 'fldngPrvtnYn', fieldName: 'fldngPrvtnYn', header: { text: '침수예방' } }, + { name: 'wqPlltnMtgtYn', fieldName: 'wqPlltnMtgtYn', header: { text: '수질오염저감' } }, + { name: 'rtlztnUsgYn', fieldName: 'rtlztnUsgYn', header: { text: '하수 재이용 용도' } }, + { name: 'fcltStrctCn', fieldName: 'fcltStrctCn', header: { text: '시설구조' } }, + { name: 'wtrStrgZoneArea', fieldName: 'wtrStrgZoneArea', header: { text: '집수구역면적(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000', footer: footerDecimal3ArrayByDivision }, + { name: 'impdFcltCpct', fieldName: 'impdFcltCpct', 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 }, + { name: 'grssPpqty', fieldName: 'grssPpqty', header: { text: '총양수량(㎥/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpFcltN1DmtrExpln', fieldName: 'pumpFcltN1DmtrExpln', header: { text: '구경(mm)' } }, + { name: 'pumpFcltN1PerPpqty', fieldName: 'pumpFcltN1PerPpqty', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpFcltN1PumpCnt', fieldName: 'pumpFcltN1PumpCnt', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpFcltN1RsrvPumpCnt', fieldName: 'pumpFcltN1RsrvPumpCnt', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + + { name: 'pumpFcltN2DmtrExpln', fieldName: 'pumpFcltN2DmtrExpln', header: { text: '구경(mm)' } }, + { name: 'pumpFcltN2PerPpqty', fieldName: 'pumpFcltN2PerPpqty', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpFcltN2PumpCnt', fieldName: 'pumpFcltN2PumpCnt', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpFcltN2RsrvPumpCnt', fieldName: 'pumpFcltN2RsrvPumpCnt', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + + { name: 'pumpFcltN3DmtrExpln', fieldName: 'pumpFcltN3DmtrExpln', header: { text: '구경(mm)' } }, + { name: 'pumpFcltN3PerPpqty', fieldName: 'pumpFcltN3PerPpqty', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpFcltN3PumpCnt', fieldName: 'pumpFcltN3PumpCnt', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpFcltN3RsrvPumpCnt', fieldName: 'pumpFcltN3RsrvPumpCnt', 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: '방류수역' } }, + { name: 'prcsgFcltYn', fieldName: 'prcsgFcltYn', header: { text: '전처리시설(유/무)' } }, + { name: 'ddrztnEqpmYn', fieldName: 'ddrztnEqpmYn', header: { text: '탈취설비(유/무)' } }, + { name: 'oslfEtgtYn', fieldName: 'oslfEtgtYn', header: { text: '자가발전(유/무)' } }, + { name: 'mltvMthCn', fieldName: 'mltvMthCn', header: { text: '배수방식' } }, + { name: 'impdMthCn', fieldName: 'impdMthCn', header: { text: '저류방식' } }, + { name: 'impdPrcsMthdCn', fieldName: 'impdPrcsMthdCn', header: { text: '저류수 처리방법' } }, + { name: 'dschgWtrsExpln', fieldName: 'dschgWtrsExpln', 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: '협잡물' } }, + { name: 'prcptnLastDspsQnt', fieldName: 'prcptnLastDspsQnt', header: { text: '침사' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'ctmnLastDspsQnt', fieldName: 'ctmnLastDspsQnt', header: { text: '협잡물' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'prcptnLastDspsMthdExpln', fieldName: 'prcptnLastDspsMthdExpln', header: { text: '침사' } }, + { name: 'ctmnLastDspsMthdExpln', fieldName: 'ctmnLastDspsMthdExpln', 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: '비고' } }, + { name: 'oprtngDayCnt', fieldName: 'oprtngDayCnt', header: { text: '가동일수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'grssMltvQnt', fieldName: 'grssMltvQnt', header: { text: '총배수량(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, ], columnLayout: [ { name: 'areaGroup', header: { text: '행정구역' }, items: [ - { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, - 'gugun', 'swgeStrgeNm', 'addr' + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'sggNm','admdstNm' ] }, - 'displayYear', 'rnDt', 'plDsgnFrqnc', - { name: 'purposeGroup', header: { text: '설치목적' }, items: ['insPer1', 'insPer2', 'insPer3'] }, - 'facRes', 'dgrAr', 'swgeSgbsCpcty', + 'impdFcltNm', 'impdFcltPstnCn','displayYear', 'oprtngStrtYmd', 'planDesignFreqCnt', + { name: 'purposeGroup', header: { text: '설치목적' }, items: ['fldngPrvtnYn', 'wqPlltnMtgtYn', 'rtlztnUsgYn'] }, + 'fcltStrctCn', 'wtrStrgZoneArea', 'impdFcltCpct', { 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'] } + 'grssPpqty', + { name: 'p1Group', header: { text: '펌프시설1' }, items: ['pumpFcltN1DmtrExpln', 'pumpFcltN1PerPpqty', 'pumpFcltN1PumpCnt', 'pumpFcltN1RsrvPumpCnt'] }, + { name: 'p2Group', header: { text: '펌프시설2' }, items: ['pumpFcltN2DmtrExpln', 'pumpFcltN2PerPpqty', 'pumpFcltN2PumpCnt', 'pumpFcltN2RsrvPumpCnt'] }, + { name: 'p3Group', header: { text: '펌프시설3' }, items: ['pumpFcltN3DmtrExpln', 'pumpFcltN3PerPpqty', 'pumpFcltN3PumpCnt', 'pumpFcltN3RsrvPumpCnt'] } ] }, - { 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' + { name: 'subFacGroup', header: { text: '부대시설' }, items: ['prcsgFcltYn', 'ddrztnEqpmYn', 'oslfEtgtYn'] }, + 'mltvMthCn', 'impdMthCn', 'impdPrcsMthdCn', 'dschgWtrsExpln', + { name: 'disposalAmtGroup', header: { text: '최종처분량(ton/년)' }, items: ['prcptnLastDspsQnt', 'ctmnLastDspsQnt'] }, + { name: 'disposalMthGroup', header: { text: '최종처분방법' }, items: ['prcptnLastDspsMthdExpln', 'ctmnLastDspsMthdExpln'] }, + { name: 'opGroup', header: { text: '운영실적' }, items: ['oprtngDayCnt', 'grssMltvQnt'] }, + 'rmrk' ] }, { @@ -180,155 +180,162 @@ const rawReservoirList = [ tabLabel: '빗물펌프장', rowStartNum: 3, fixedColumns: 2, - columns: [ - /* 1. 기본 정보 */ - { - name: 'sido', - fieldName: 'sido', - header: { text: '시도' }, - mergeCells: true, - 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 divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + columns: [ + { + name: 'ctpvNm', + fieldName: 'ctpvNm', + header: { text: '시도' }, + mergeCells: true, + 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 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) => { - 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 '합계'; } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + ' 합계'; + return '합계'; } - ] - }, - { 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: '구분' }, - 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 divisionValue = dataSource.getValue(i, 'displayYear'); - if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { - uniqueValues.add(String(divisionValue)); - } + }, + { + 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)); } - 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 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); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + ' 합계'; + return '합계'; } - ] - }, - { 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: '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: [ - '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: ['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' - ] - } + } + ] + }, + { name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, mergeCells: true, sortdisable: true }, + { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, mergeCells: true }, + { name: 'impdFcltNm', fieldName: 'impdFcltNm', header: { text: '시설명' }, mergeCells: true, sortdisable: true }, + { name: 'impdFcltPstnCn',fieldName: 'impdFcltPstnCn',header: { text: '위치' }, mergeCells: true, sortdisable: true }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + 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 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) => { + 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. 시설 제원 */ + { name: 'fcltyKndCn', fieldName: 'fcltyKndCn', header: { text: '시설물종류' } }, + { name: 'oprtngStrtYmd', fieldName: 'oprtngStrtYmd', header: { text: '가동개시 년월일' } }, + { name: 'planDesignFreqCnt', fieldName: 'planDesignFreqCnt', header: { text: '계획설계빈도' } }, + { name: 'wtrStrgZoneArea', fieldName: 'wtrStrgZoneArea', header: { text: '집수구역면적(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000', footer: footerDecimal3ArrayByDivision }, + { name: 'rsvrYn', fieldName: 'rsvrYn', header: { text: '유수지유무\n(유,무)' } }, + { name: 'rsvrImpndQnt', fieldName: 'rsvrImpndQnt', header: { text: '저류량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'abstnRgnImdQnt', fieldName: 'abstnRgnImdQnt', header: { text: '저류량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'fcltCpct', fieldName: 'fcltCpct', header: { text: '시설용량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + + /* 3. 펌프시설 */ + { name: 'pumpFcltN1DmtrExpln', fieldName: 'pumpFcltN1DmtrExpln', header: { text: '구경(mm)' } }, + { name: 'pumpFcltN1PerPpqty', fieldName: 'pumpFcltN1PerPpqty', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpFcltN1PumpCnt', fieldName: 'pumpFcltN1PumpCnt', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpFcltN1RsrvPumpCnt', fieldName: 'pumpFcltN1RsrvPumpCnt', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + + { name: 'pumpFcltN2DmtrExpln', fieldName: 'pumpFcltN2DmtrExpln', header: { text: '구경(mm)' } }, + { name: 'pumpFcltN2PerPpqty', fieldName: 'pumpFcltN2PerPpqty', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpFcltN2PumpCnt', fieldName: 'pumpFcltN2PumpCnt', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpFcltN2RsrvPumpCnt', fieldName: 'pumpFcltN2RsrvPumpCnt', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + + { name: 'pumpFcltN3DmtrExpln', fieldName: 'pumpFcltN3DmtrExpln', header: { text: '구경(mm)' } }, + { name: 'pumpFcltN3PerPpqty', fieldName: 'pumpFcltN3PerPpqty', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0', footer: footerDecimal1ArrayByDivision }, + { name: 'pumpFcltN3PumpCnt', fieldName: 'pumpFcltN3PumpCnt', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'pumpFcltN3RsrvPumpCnt', fieldName: 'pumpFcltN3RsrvPumpCnt', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + + /* 4. 부대시설 */ + { name: 'prcsgFcltYn', fieldName: 'prcsgFcltYn', header: { text: '전처리시설' } }, + { name: 'ddrztnEqpmYn', fieldName: 'ddrztnEqpmYn', header: { text: '탈취설비' } }, + { name: 'oslfEtgtYn', fieldName: 'oslfEtgtYn', header: { text: '자가발전' } }, + { name: 'dschgWtrsExpln',fieldName: 'dschgWtrsExpln',header: { text: '방류수역' } }, + + /* 5. 최종처분량 */ + { name: 'prcptnLastDspsQnt', fieldName: 'prcptnLastDspsQnt', header: { text: '침사(량)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'ctmnLastDspsQnt', fieldName: 'ctmnLastDspsQnt', header: { text: '협잡물(량)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + + /* 6. 운영실적 */ + { name: 'oprtngDayCnt', fieldName: 'oprtngDayCnt', header: { text: '가동일수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'grssMltvQnt', fieldName: 'grssMltvQnt', header: { text: '총배수량(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0', footer: footerIntArrayByDivision }, + { name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'areaGroup', header: { text: '행정구역' }, items: [ + { column: 'ctpvNm', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'sggNm', 'admdstNm', + ] + }, + 'displayYear', 'fcltyKndCn', 'oprtngStrtYmd', 'planDesignFreqCnt', 'wtrStrgZoneArea', + { name: 'revGroup', header: { text: '유수지' }, items: ['rsvrYn', 'rsvrImpndQnt'] }, + { name: 'absGroup', header: { text: '흡수정' }, items: ['abstnRgnImdQnt'] }, + 'fcltCpct', + { + name: 'pumpMainGroup', header: { text: '펌프시설' }, + items: [ + { name: 'p1Group', header: { text: '펌프시설1' }, items: ['pumpFcltN1DmtrExpln', 'pumpFcltN1PerPpqty', 'pumpFcltN1PumpCnt', 'pumpFcltN1RsrvPumpCnt'] }, + { name: 'p2Group', header: { text: '펌프시설2' }, items: ['pumpFcltN2DmtrExpln', 'pumpFcltN2PerPpqty', 'pumpFcltN2PumpCnt', 'pumpFcltN2RsrvPumpCnt'] }, + { name: 'p3Group', header: { text: '펌프시설3' }, items: ['pumpFcltN3DmtrExpln', 'pumpFcltN3PerPpqty', 'pumpFcltN3PumpCnt', 'pumpFcltN3RsrvPumpCnt'] } + ] + }, + { name: 'subFacGroup', header: { text: '부대시설' }, items: ['prcsgFcltYn', 'ddrztnEqpmYn', 'oslfEtgtYn'] }, + 'dschgWtrsExpln', + { name: 'disposalAmtGroup', header: { text: '최종처분량(ton/년)' }, items: ['prcptnLastDspsQnt', 'ctmnLastDspsQnt'] }, + { name: 'opGroup', header: { text: '운영실적' }, items: ['oprtngDayCnt', 'grssMltvQnt'] }, + 'rmrk' + ] +} ]; export const SewageReservoirPumpInfoListRvw = rawReservoirList.map(tab => ({ diff --git a/apps/st/src/entities/statistics/api/statistics-input-sew-supply-rate-service.ts b/apps/st/src/entities/statistics/api/statistics-input-sew-supply-rate-service.ts index ba6d10874..7e4e23370 100644 --- a/apps/st/src/entities/statistics/api/statistics-input-sew-supply-rate-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-input-sew-supply-rate-service.ts @@ -21,7 +21,7 @@ export class StatisticsInputSewSupplyRateApiService implements StatisticsInputSe public async checkInputPeriod(params: string): Promise { const response = await stClient.get( - `${ENDPOINT.ST_SERVICE.INPUTCOMMON}/check-input-period?year=${params}`, + `${ENDPOINT.ST_SERVICE.INPUTCOMMON}/check-input-period?statsYr=${params}`, ); return response.data; } @@ -43,4 +43,4 @@ export class StatisticsInputSewSupplyRateApiService implements StatisticsInputSe } } -export const StatisticsInputSewSupplyRateApi = new StatisticsInputSewSupplyRateApiService(); \ No newline at end of file +export const statisticsInputSewSupplyRateApi = new StatisticsInputSewSupplyRateApiService(); \ 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 1e2a6336d..99f7ea552 100644 --- a/apps/st/src/entities/statistics/api/statistics-management-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -92,12 +92,7 @@ export class StatisticsManagementApiService { * @param params (sido, gugun, yr, bsnmCd) */ public async getSewagePipeTypeList( - params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - } + params: SewagePipeReviewRequestParams ): Promise { const response = await stClient.get( `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe/type-status`, @@ -111,12 +106,7 @@ export class StatisticsManagementApiService { * @param params (sido, gugun, yr, bsnmCd) */ public async getSewagePipeDiamList( - params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - } + params: SewagePipeReviewRequestParams ): Promise { const response = await stClient.get( `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe/diam-status`, @@ -144,12 +134,7 @@ export class StatisticsManagementApiService { * @param params (yr, bsnmCd, sido, gugun) */ public async getSewerPipeDrdgList( - params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - } + params: SewerPipeMtcRequestParams ): Promise { const response = await stClient.get( `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe-mtc/dredging`, @@ -163,12 +148,7 @@ export class StatisticsManagementApiService { * @param params (yr, bsnmCd, sido, gugun) */ public async getSewerReservoirList( - params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - } + params: SewerPipeMtcRequestParams ): Promise { const response = await stClient.get( `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-reservoir/facilities`, @@ -182,12 +162,7 @@ export class StatisticsManagementApiService { * @param params (yr, bsnmCd, sido, gugun) */ public async getPumpStationList( - params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - } + params: SewerPipeMtcRequestParams ): Promise { const response = await stClient.get( `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-reservoir/pumping-stations`, @@ -202,11 +177,11 @@ export class StatisticsManagementApiService { */ public async getMediationPumpStationList( params: { - yr?: string; // 조회 연도 - bsnmCd?: string; // 사업소 코드 - sido?: string; // 시도 - gugun?: string; // 구군 - bscFctNm?: string; // 펌프장명 (시설명) + ctpvNm?: string; + sggNm?: string; + statsYr?: string; + sewerBzmnCd?: string; + pumpstNm?: string; } ): Promise { const response = await stClient.get( diff --git a/apps/st/src/entities/statistics/api/statistics-service.ts b/apps/st/src/entities/statistics/api/statistics-service.ts index f75163e5c..82ed85b83 100644 --- a/apps/st/src/entities/statistics/api/statistics-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-service.ts @@ -6,6 +6,8 @@ import { type SearchCondition, type ApiResponse, type Sgg, + type cancelSubmitRequest, + type cancelSubmitResponse, } from "../model/statistics-interface"; export class StatisticsAPiService implements StatisticsService { @@ -23,6 +25,15 @@ export class StatisticsAPiService implements StatisticsService { ); return response.data; } + + // 입력 - 제출 취소 + public async cancelSubmit(param: cancelSubmitRequest): Promise { + const response = await stClient.put( + `${ENDPOINT.ST_SERVICE.INPUTCOMMON}/cancel-submit`, + param + ); + return response.data; + } } export const statisticsAPi = new StatisticsAPiService(); \ No newline at end of file diff --git a/apps/st/src/entities/statistics/model/general-verification-interface.ts b/apps/st/src/entities/statistics/model/general-verification-interface.ts new file mode 100644 index 000000000..c22504827 --- /dev/null +++ b/apps/st/src/entities/statistics/model/general-verification-interface.ts @@ -0,0 +1,12 @@ +export interface GeneralverificationList { + vrfSn: number; + tabNm: string; + vrfNm: string; + vrfClsCd: string; + statsCd: string; + useYn: string; + rgtrId?: string; + regDt?: string; + mdfrId?: string; + mdfcnDt?: string; +} \ No newline at end of file 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 index 4f7b6bf7f..d27d770f5 100644 --- 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 @@ -5,143 +5,134 @@ 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년확정 등) +// 1. 기본 정보 + statsYr: string; // 통계연도 + ctpvNm: string; // 시도명 + sggNm: string; // 시군구명 + admdstNm: string; // 행정구역명 + admdstCd: string; // 행정구역코드 + sewerBzmnCd: string; // 하수도사업자코드 + displayYear: string; // 화면 표시 연도 + impdFcltNm: string; // 저류시설명 + impdFcltPstnCn: string; // 저류시설위치내용 + rowType: 'OLD' | 'CURR'; // 데이터 구분 // 2. 시설 제원 - rnDt: string; // 가동개시일 (yyyyMMdd) - plDsgnFrqnc: string; // 계획설계빈도 - insPer1: string; // 설치목적: 침수예방 - insPer2: string; // 설치목적: 수질오염저감 - insPer3: string; // 설치목적: 하수재이용 - facRes: string; // 시설구조 - dgrAr: number; // 집수구역면적 - swgeSgbsCpcty: number; // 시설용량 - totCpcty: number; // 총양수량 + oprtngStrtYmd: string; // 가동개시일자 + planDesignFreqCnt: number; // 계획설계빈도 + fldngPrvtnYn: string; // 침수예방 + wqPlltnMtgtYn: string; // 수질오염저감 + rtlztnUsgYn: string; // 하수재이용용도 + fcltStrctCn: string; // 시설구조 + wtrStrgZoneArea: number; // 집수구역면적 + impdFcltCpct: number; // 시설용량 + grssPpqty: number; // 총양수량 - // 3. 펌프시설 상세 (1호기) - pumpCalbr: string; // 구경 - wpCpcty: number; // 대당 양수량 - pumpCo: number; // 펌프대수 - pumpPreparCo: number; // 예비펌프대수 + // 3. 펌프시설 상세 (1~3호기) + pumpFcltN1DmtrExpln: string; // 1구경 + pumpFcltN1PerPpqty: number; // 1대당양수량 + pumpFcltN1PumpCnt: number; // 1펌프대수 + pumpFcltN1RsrvPumpCnt: number; // 1예비펌프대수 - // 4. 펌프시설 상세 (2호기) - 추가 - pumpCalbr2: string; // 구경2 - wpCpcty2: number; // 대당 양수량2 - pumpCo2: number; // 펌프대수2 - pumpPreparCo2: number; // 예비펌프대수2 + pumpFcltN2DmtrExpln: string; // 2구경 + pumpFcltN2PerPpqty: number; // 2대당양수량 + pumpFcltN2PumpCnt: number; // 2펌프대수 + pumpFcltN2RsrvPumpCnt: number; // 2예비펌프대수 - // 5. 펌프시설 상세 (3호기) - 추가 - pumpCalbr3: string; // 구경3 - wpCpcty3: number; // 대당 양수량3 - pumpCo3: number; // 펌프대수3 - pumpPreparCo3: number; // 예비펌프대수3 + pumpFcltN3DmtrExpln: string; // 3구경 + pumpFcltN3PerPpqty: number; // 3대당양수량 + pumpFcltN3PumpCnt: number; // 3펌프대수 + pumpFcltN3RsrvPumpCnt: number; // 3예비펌프대수 - // 6. 부대시설 및 방식 - 추가 - freFnnc: string; // 전처리시설유무 - dorzeqpFnnc: string; // 탈취설비유무 - selfEtrqFnnc: string; // 자가발전유무 - draMth: string; // 배수방식 - elecMth: string; // 저류방식 - elecProMat: string; // 저류수 처리방법 - disWat: string; // 방류수역 + // 4. 부대시설 및 방식 + prcsgFcltYn: string; // 전처리시설 유무 + ddrztnEqpmYn: string; // 탈취설비 유무 + oslfEtgtYn: string; // 자가발전 유무 + mltvMthCn: string; // 배수방식 + impdMthCn: string; // 저류방식 + impdPrcsMthdCn: string; // 저류수 처리방법 + dschgWtrsExpln: string; // 방류수역 - // 7. 최종처분량 및 방법 - 추가 - sdmtTreCpcty: number; // 침사량 - iprtTreCpcty: number; // 협잡물량 - sdmtTreMth: string; // 침사 처분방법 - iprtTreMth: string; // 협잡물 처분방법 + // 5. 최종처분량 및 방법 + prcptnLastDspsQnt: number; // 침사 최종처분량 + ctmnLastDspsQnt: number; // 협잡물 최종처분량 + prcptnLastDspsMthdExpln: string; // 침사 최종처분방법 + ctmnLastDspsMthdExpln: 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; + // 6. 운영 실적 + oprtngDayCnt: number; // 가동일수 + grssMltvQnt: number; // 총배수량 + rmrk: string; // 비고 } /** * 04. 빗물펌프장 tab2. 시설현황 아이템 인터페이스 (Tab2) */ + export interface PumpingStationRegionalItem { // --- 기본 정보 --- - sido: string; // 시도 - gugun: string; // 시군구 - adstCd: string; // 행정코드 - swgeStrgeNm: string; // 시설명 - addr: string; // 위치 - yr: string; // 연도 - rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 - displayYear: string; // 구분 표시용 + ctpvNm: string; // 시도명 + sggNm: string; // 시군구명 + admdstNm: string; // 행정구역명 + admdstCd: string; // 행정구역코드 + sewerBzmnCd: string; // 하수도사업자코드 + displayYear: string; // 화면 표시 연도 + impdFcltNm: string; // 저류시설명 + impdFcltPstnCn: string; // 저류시설위치내용 + rowType: 'OLD' | 'CURR'; // 데이터 구분 // --- 시설 제원 --- - fctKnd: string; // 시설물종류 - rnDt: string; // 가동개시일 - plDsgnFrqnc: string; // 계획설계빈도 - dgrAr: number; // 집수구역면적 - revFnnc: string; // 유수지유무 - revCpcty: number; // 유수지저류량 - absCpcty: number; // 흡수정저류량 - swgeSgbsCpcty: number; // 시설용량 - totCpcty: number; // 총양수량 + fcltyKndCn: string; // 시설물종류 + oprtngStrtYmd: string; // 가동개시일자 + planDesignFreqCnt: number; // 계획설계빈도 + wtrStrgZoneArea: 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; + // 유수지 + rsvrYn: string; // 유수지유무 + rsvrImpndQnt: number; // 저류량 + abstnRgnImdQnt: number; // 흡수지 저류량 - // --- 부대시설 및 방식 --- - freFnnc: string; // 전처리시설유무 - dorzeqpFnnc: string; // 탈취설비유무 - selfEtrqFnnc: string; // 자가발전유무 - disWat: string; // 방류수역 + fcltCpct: number; // 시설용량 - // --- 최종처분량 및 방법 --- - sdmtTreCpcty: number; // 침사 처분량 - iprtTreCpcty: number; // 협잡물 처분량 - sdmtTreMth: string; // 침사 처분방법 - iprtTreMth: string; // 협잡물 처분방법 + // --- 펌프시설 상세 (1~3호기) --- + pumpFcltN1DmtrExpln: string; // 펌프시설1 구경 + pumpFcltN1PerPpqty: number; // 펌프시설1 대당양수량 + pumpFcltN1PumpCnt: number; // 펌프시설1 펌프대수 + pumpFcltN1RsrvPumpCnt: number; // 펌프시설1 예비펌프대수 + + pumpFcltN2DmtrExpln: string; // 펌프시설2 구경 + pumpFcltN2PerPpqty: number; // 펌프시설2 대당양수량 + pumpFcltN2PumpCnt: number; // 펌프시설2 펌프대수 + pumpFcltN2RsrvPumpCnt: number; // 펌프시설2 예비펌프대수 + + pumpFcltN3DmtrExpln: string; // 펌프시설3 구경 + pumpFcltN3PerPpqty: number; // 펌프시설3 대당양수량 + pumpFcltN3PumpCnt: number; // 펌프시설3 펌프대수 + pumpFcltN3RsrvPumpCnt: number; // 펌프시설3 예비펌프대수 + + // --- 부대시설 --- + prcsgFcltYn: string; // 전처리시설 유무 + ddrztnEqpmYn: string; // 탈취설비 유무 + oslfEtgtYn: string; // 자가발전 유무 + dschgWtrsExpln: string; // 방류수역 + + // --- 최종처분량 --- + prcptnLastDspsQnt: number; // 침사 최종처분량 + ctmnLastDspsQnt: number; // 협잡물 최종처분량 // --- 운영실적 --- - yrstpRnDyn: number; // 가동일수 - dsplcmntAmnt: number; // 총배수량 - rmk: string; // 비고 + oprtngDayCnt: number; // 가동일수 + grssMltvQnt: number; // 총배수량 + rmrk: string; // 비고 +} + +export interface SewerReservoirRequestParams { + ctpvNm?: string; // 시도명 + sggNm?: string; // 시군구명 + statsYr?: string; // 통계 연도 + sewerBzmnCd?: string; // 하수도사업자 코드 } -/** - * 응답 타입 정의 - */ export type SewerReservoirRegionalApiResponse = ApiResponse; export type PumpingStationRegionalApiResponse = ApiResponse; @@ -152,20 +143,14 @@ export interface SewerReservoirService { /** * 하수저류시설 리스트 조회 (Tab1) */ - getSewerReservoirList(params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - }): Promise; + getSewerReservoirList( + params: SewerReservoirRequestParams + ): Promise; /** * 빗물펌프장 리스트 조회 (Tab2) */ - getPumpStationList(params: { - yr?: string; - bsnmCd?: string; - sido?: string; - gugun?: string; - }): Promise; + getPumpStationList( + params: SewerReservoirRequestParams + ): Promise; } \ No newline at end of file diff --git a/apps/st/src/entities/statistics/model/statistics-interface.ts b/apps/st/src/entities/statistics/model/statistics-interface.ts index b909eba92..edf5d264c 100644 --- a/apps/st/src/entities/statistics/model/statistics-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-interface.ts @@ -15,6 +15,20 @@ export interface Sgg { bsnmCd: string; } +export interface cancelSubmitRequest { + statsYr: string; + ctpvNm: string; + sggNm: string; + sewerBzmnCd: string; + statsCd: string; + userId: string; +} + +export interface cancelSubmitResponse { + status: string; + message?: string; +} + export interface ApiResponse { status: string; data: T; @@ -24,4 +38,5 @@ export interface ApiResponse { export interface StatisticsService { getSidoList(): Promise>; getSggList(sidoName: string): Promise>; + cancelSubmit(param: cancelSubmitRequest): Promise; } \ No newline at end of file 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 index fbfc04711..0f34edf86 100644 --- 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 @@ -1,67 +1,65 @@ import type { ApiResponse } from "./statistics-interface"; /** - * 중계펌프장 통계관리 아이템 인터페이스 + * 05.중계펌프장 검토 아이템 인터페이스 */ export interface MediationPumpStationItem { - // 기본 정보 및 행 제어 - sido: string; // 시도 - gugun: string; // 시군구 - adstCd: string; // 행정코드 - pumpNm: string; // 펌프장명 - yr: string; // 연도 - displayYear: string; // 구분 표시용 (2024년확정 등) - rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 + // 기본 정보 + ctpvNm: string; + sggNm: string; + admdstCd: string; + statsYr: string; + displayYear: string; + rowType: 'OLD' | 'CURR'; + pumpstNm: string; + impdFcltPstnCn: string; + oprtngStrtYmd: string; + pumpSeNm: string; + swtrmtFcltNm: string; + + // 제원 및 계획량 + planMltvArea: number; + sndyArea: number; + rainArea: number; + exlnQnt: number; + + // 오수펌프 (DRTW) + drtwPumpGrssPpqty: number; + drtwPumpN1DmtrArea: number; + drtwPumpN1Ppqty: number; + drtwPumpN1Cnt: number; + drtwPumpN1RsrvCnt: number; - // 주요 제원 - 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 예비대수 + drtwPumpN2DmtrArea: number; + drtwPumpN2Ppqty: number; + drtwPumpN2Cnt: number; + drtwPumpN2RsrvCnt: number; - // 우수펌프 상세 (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 예비대수 + drtwPumpN3DmtrArea: number; + drtwPumpN3Ppqty: number; + drtwPumpN3Cnt: number; + drtwPumpN3RsrvCnt: number; + + // 우수펌프 (EXLN) + exlnPumpGrssPpqty: number; + exlnPumpN1DmtrArea: number; + exlnPumpN1Ppqty: number; + exlnPumpN1Cnt: number; + exlnPumpN4RsrvCnt: number; + + exlnPumpN2DmtrArea: number; + exlnPumpN2Ppqty: number; + exlnPumpN2Cnt: number; + exlnPumpN2RsrvCnt: number; + + exlnPumpN3DmtrArea: number; + exlnPumpN3Ppqty: number; + exlnPumpN3Cnt: number; + exlnPumpN3RsrvCnt: number; // 기타 - elcpwAmnt: number; // 연간전력사용량(kWh/년) - rmk: string; // 비고 - lcnt: string; // 당해 존재 여부 ('1'|'0') - ocnt: string; // 전년 존재 여부 ('1'|'0') + anlElpwrUseQnt: number; + rmrk: string; } @@ -77,10 +75,10 @@ export type MediationPumpStationApiResponse = ApiResponse; } \ No newline at end of file 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 0281e43bc..330403c73 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 @@ -100,4 +100,8 @@ export interface SewerPipeDrdgResponseData { } -export type SewerPipeDrdgApiResponse = ApiResponse; \ No newline at end of file +export type SewerPipeDrdgApiResponse = ApiResponse; + +export interface SewagePipeMtcService { + getSewerPipeMtcDrdgItem(params: SewerPipeMtcRequestParams): Promise; +} \ No newline at end of file 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 3d97ec558..6ffa91466 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,65 +4,62 @@ import type { ApiResponse } from "./statistics-interface"; * 02. 하수관로 tab1.지역별 시설현황 아이템 인터페이스 (Tab1) */ export interface SewagePipeReviewrRegionalItem { + ctpvNm: string; // 시도명 + sggNm: string; // 시군구명 + admdstNm: string; // 행정구역명 + admdstCd: string; // 행정구역코드 + statsYr: string; // 통계 연도 + displayYear: string; // 화면 표시용 연도 + rowType: 'OLD' | 'CURR'; // 데이터 구분 -/* --- 기본 정보 및 행 제어 --- */ - ctpvNm: string; // 시도명 - sggNm: string; // 시군구명 - admdstNm: string; // 행정구역명 - admdstCd: string; // 행정구역코드 - statsYr: string; // 통계 연도 - rowType: 'OLD' | 'CURR'; // 데이터 구분 (OLD: 확정분, CURR: 당해년도) - displayYear: string; // 화면 표시용 연도 + /* --- 하수정비 기본계획 및 총계 --- */ + goalYr: string; // 하수정비 기본계획 목표연도 + wholPplMtncPlanPrlg: number; // 총관로정비계획연장 + wholPlanPrlg: number; // 전체계획연장 + wholFcltPrlg: number; // 전체시설연장 + swagePplPsplyRt: number; // 하수관로보급비율 - /* --- 하수정비 기본계획 --- */ - targetYr: number; // 하수정보기본계획 목표년도 - swrgPipeMntnPlanExtn: number; // 총 관로정비 계획연장(m) - swrgPipePlanExtn: number; // 총 계획연장(m) - swrgPipeFcltyExtn: number; // 총 시설연장(m) - swrgPipePsplyRt: number; // 하수관로 보급률(%) + /* --- 합류식 (Combined) --- */ + cbsysPplMtncPlanArea: number; // 합류식관로정비계획면적 + cbsysPplMtncPlanPrlg: number; // 합류식관로정비계획연장 + cbsysPlanPrlg: number; // 합류식계획연장 + cbsysFcltPrlg: number; // 합류식시설연장 + cbsysSqrePrlg: number; // 합류식사각연장 + cbsysCiclPrlg: number; // 합류식원형연장 + cbsysOpnPrlg: number; // 합류식개방연장 + cbsysGttrPrlg: number; // 합류식측구연장 - /* --- 합류식 (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) + /* --- 분류식 - 오수관로 (Foul Water) --- */ + drtwPplMtncPlanArea: number; // 오수관로정비계획면적 + drtwPplMtncPlanPrlg: number; // 오수관로정비계획연장 + drtwPplPlanPrlg: number; // 오수관로계획연장 + drtwPplFcltPrlg: number; // 오수관로시설연장 + drtwPplSqrePrlg: number; // 오수관로사각연장 + drtwPplCiclPrlg: number; // 오수관로원형연장 - /* --- 분류식 - 오수관로 (Foul Water Pipe) --- */ - pltwtrMntnPlanAr: number; // 관로정비 계획면적(㎢) - pltwtrMntnPlanExtn: number; // 관로정비 계획연장(m) - pltwtrPlanExtn: number; // 계획연장(m) - pltwtrFcltyExtn: number; // 시설연장(m) - pltwtrRctglExtn: number; // 사각형 암거 연장(m) - pltwtrCicleExtn: number; // 원형 암거 연장(m) + /* --- 분류식 - 우수관로 (Rain Water) --- */ + exlnPplMtncPlanArea: number; // 우수관로정비계획면적 + exlnPplMtncPlanPrlg: number; // 우수관로정비계획연장 + exlnPplPlanPrlg: number; // 우수관로계획연장 + exlnPplFcltPrlg: number; // 우수관로시설연장 + exlnPplSqrePrlg: number; // 우수관로사각연장 + exlnPplCiclPrlg: number; // 우수관로원형연장 + exlnPplOpnPrlg: number; // 우수관로개방연장 + exlnPplGttrPrlg: 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; // 우수토구 수 + /* --- 부속시설 --- */ + cbsysMnhlCnt: number; // 합류식맨홀수 + sprsysDrtwMnhlCnt: number; // 분류식오수맨홀수 + sprsysExlnMnhlCnt: number; // 분류식우수맨홀수 + drtwRcvprpCnt: number; // 오수받이수 + exlnRcvprpCnt: number; // 우수받이수 + stofcbrCnt: number; // 우수토실수 + exlnOtflCnt: number; // 우수토구수 /* --- 대장 및 기타 --- */ - swrgRegstrCmptExtn: number; // 하수도대장 전산화 연장(m) - swrgRegstrCmptRt: number; // 하수도대장 전산화율(%) - rmrk: string; // 비고 - + sewerLdgrEdpPrlg: number; // 하수도대장전산화연장 + sewerLdgrEdpRt: number; // 하수도대장전산화비율 + rmrk: string | null; // 비고 } export interface SewagePipeReviewResponseData { @@ -70,10 +67,10 @@ export interface SewagePipeReviewResponseData { } export interface SewagePipeReviewRequestParams { - ctpvNm?: string; // 시도명 - sggNm?: string; // 시군구명 - statsYr?: string; // 통계 연도 - sewerBzmnCd?: string; // 하수도사업자 코드 + ctpvNm?: string; + sggNm?: string; + statsYr?: string; + sewerBzmnCd?: string; } export type SewagePipeReviewRegionalApiResponse = ApiResponse & { @@ -89,47 +86,48 @@ export interface SewagePipeReviewService { */ export interface SewagePipeReviewFacilityItem { // 1. 행정구역 및 기본 정보 - ctpvNm: string; // 시도명 - sggNm: string; // 시군구명 - admdstCd: string; // 행정구역코드 - admdstNm: string; // 행정구역명 - statsYr: string; // 통계연도 - rowType: 'OLD' | 'CURR'; // 데이터 구분 (OLD: 확정, CURR: 당해년도) - displayYear: string; // 화면 표시용 연도 + ctpvNm: string; + sggNm: string; + admdstCd: string; + admdstNm: string; + statsYr: string; + rowType: 'OLD' | 'CURR'; + displayYear: string; // 2. 시설 정보 - swrmtFcltyNm: string; // 하수처리시설 명칭 - swrmtFcltyCpc: number; // 하수처리시설 용량(㎥/일) + swtrmtFcltNm: string; + prcsFcltCpct: number; // 3. 처리구역 면적(㎢) - procZoneArSm: number; // 처리구역 면적 합계 - cmbnProcZoneAr: number; // 합류식 처리구역 면적 - sprsysProcZoneAr: number; // 분류식 처리구역 면적 + prcsZoneArea: number; + cbsysPrcsZoneArea: number; + sprsysPrcsZoneArea: number; + + sprsysVartnRt:number;//분류식 // 4. 배수설비(개소) - drngEqpSm: number; // 배수설비 합계 - cmbnDrngEqp: number; // 합류식 배수설비 - sprsysDrngEqpSm: number; // 분류식 배수설비 합계 + mltvEqpmCnt: number; + cbsysMltvEqpmCnt: number; + sprsysMltvEqpmCnt: number; // 5. 하수관로 (m) - swrgPipeFcltyExtn: number; // 총 시설연장 - icgPltwtrMnnSm: number; // 차집 및 오수간선 합계 - icgExtn: number; // 차집관로 연장 - pltwtrMnnExtn: number; // 오수간선 연장 + wholFcltPrlg: number; + wholIcptgAtlfcPrlg: number; + icptgPrlg: number; + atlfcsPrlg: number; // 6. 우수토실/토구 (개소) - cmbnRainwtrChmbrCnt: number; // 합류식 우수토실 - sprsysRainwtrChmbrCnt: number; // 분류식 우수토실 - sprsysRainwtrOutltCnt: number; // 분류식 우수토구 + cbsysStofcbrCnt: number; + sprsysStofcbrCnt: number; + sprsysExlnOtflCnt: number; // 7. 지선 (m) - brnchlnSm: number; // 지선 합계 - cmbnBrnchlnExtn: number; // 합류식 지선연장 - sprsysExlnBrnchlnExtn: number; // 분류식 우수지선연장 - sprsysDrtwBrnchlnExtn: number; // 분류식 오수지선연장 + wholBrchlnPrlg: number; + cbsysBrchlnPrlg: number; + exlnBrchlnPrlg: number; + drtwBrchlnPrlg: number; - // 비고 - rmrk: string | null; // 비고 + rmrk: string | null; } @@ -152,29 +150,22 @@ export interface SewagePipeFacilityService { * */ export interface SewerPipeTypeItem { - // --- SewerPipeTab3Response 기본 필드 --- - sido: string; // 시도 - gugun: string; // 시군구 - adstCd: string; // 행정코드 - swrgPipeNm: string; // 관종명 - displayYear: string; // 구분 표시용 (예: 2024년확정) - yr: string; // 연도 - rmk: string; // 비고 - yrGbn?: string; // 구분 (매설/철거 등 행 구분용 - 그리드 설정 기준) + ctpvNm: string; + sggNm: string; + admdstCd: string; + admdstNm: string; + swrgPipeNm: string; + statsYr: string; + displayYear: string; + rowType: 'OLD' | 'CURR'; + rmrk: string | null; - // --- BasePipeExtnResponse 상속 필드 --- - layingExtn: number; // 매설연장(m) - 당해년도 + // 총합 필드 + pipeByPrstWhol:number; + lyngPrlg: number; + dmltnPrlg: number; - // 총계(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; + [key: string]: string | number | null | undefined; } @@ -182,37 +173,60 @@ export interface SewerPipeTypeResponseData { pipeTypeStatusList: SewerPipeTypeItem[]; } -export type SewerPipeTypeApiResponse = ApiResponse; +export type SewerPipeTypeApiResponse = ApiResponse; export interface SewagePipeTypeService { - getSewagePipeTypeList(params: { - yr?: string; // 조회 연도 - bsnmCd?: string; // 사업장 코드 - sido?: string; // 시도 - gugun?: string; // 구군 - }): Promise; + getSewagePipeTypeList(params: SewagePipeReviewRequestParams): 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; // 비고 + // 1. 기본 정보 + ctpvNm: string; // 시도명 + sggNm: string; // 시군구명 + admdstNm: string; // 행정구역명 + admdstCd: string; // 행정구역코드 + statsYr: string; // 통계연도 (statsYr로 통일) + rowType: 'OLD' | 'CURR'; // 데이터 구분 + displayYear: string; // 화면 표시용 연도 + sewerBzmnCd: string; // 하수도사업자코드 + + // 2. 시설 현황 + wholFcltPrlg: number; // 전체시설연장 (m) + + // 3. 준설연장 및 개소수 - 관로 (m) + wholSwagePpl: number; // 전체하수관로 준설연장 (m) + cbsysPplPrlg: number; // 합류식관로연장 (m) + sprsysDrtwPrlg: number; // 분류식오수연장 (m) + sprsysExlnPrlg: number; // 분류식우수연장 (m) + + // 4. 준설연장 및 개소수 - 부속시설 (개소) + mnhlCnt: number; // 맨홀수 + exlnDrtwRcvprpCnt: number; // 우수오수받이수 + stofcbrOtflCnt: number; // 우수토실토구수 + + // 5. 준설 효율 및 성과 + drdgnPlanPrlg: number; // 준설계획연장 (m) + drdgnTrgtCtrsDrdgnRt: number; // 준설대상대비준설비율 (%) + wholPrlgCtrsDrdgnRt: number; // 전체연장대비준설비율 (%) + + // 6. 준설실적 + drdgnAmt: number; // 준설금액 (백만원) + drdgnQnt: number; // 준설량 (m3) + + // 7. 준설토사처리 (톤) + drdgnUntprcAmt: number; // 준설단가금액 (원/m3) + wholDrdgnPrcsQnt: number; // 전체준설처리량 (톤) + rclmQnt: number; // 매립량 + oceanEmsnQnt: number; // 해양방출량 + rcycQnt: number; // 재활용량 + etcQnt: number; // 기타량 + + // 8. 기타 + rmrk: string; // 비고 } @@ -225,10 +239,5 @@ export type SewerPipeDiamApiResponse = ApiResponse; export interface SewagePipeDiamService { - getSewagePipeDiamList(params: { - yr?: string; // 조회 연도 - bsnmCd?: string; // 사업장 코드 - sido?: string; // 시도 - gugun?: string; // 구군 - }): Promise; + getSewagePipeDiamList(params: SewagePipeReviewRequestParams): Promise; } \ No newline at end of file diff --git a/apps/st/src/entities/statistics/model/statistics-sewage-supply-rate-input-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewage-supply-rate-input-interface.ts index 5c1a1f6ef..b3f97fbb1 100644 --- a/apps/st/src/entities/statistics/model/statistics-sewage-supply-rate-input-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-sewage-supply-rate-input-interface.ts @@ -29,6 +29,7 @@ export interface SewerageSupplyRateCommonInfo { swagePplPsplyRt: number; ctpvNm: string; statsYr: string; + statsCd: string; } /** 검증 결과 한 건 (필드별 메시지) */ @@ -132,6 +133,7 @@ export interface SewerageSupplyRateSaveItem { export interface SewerageSupplyRateSaveRequest { statsYr: string; ctpvNm: string; + sggNm: string; sewerBzmnCd: string; userId: string; sewerBzmnFrgnrWholPpltnCnt?: number; diff --git a/apps/st/src/shared/ui/statistics-page-layout.tsx b/apps/st/src/shared/ui/statistics-page-layout.tsx index b34ebb5eb..d7d5b98b4 100644 --- a/apps/st/src/shared/ui/statistics-page-layout.tsx +++ b/apps/st/src/shared/ui/statistics-page-layout.tsx @@ -5,7 +5,7 @@ import { TabBar } from "./tab-bar"; function StatisticsPageLayout({ children }: { children: React.ReactNode }) { const { activeTabId, tabs } = useTabStore(); - const pageTitle = tabs.find((t) => t.menuItem.menuEngNm === activeTabId); + const pageTitle = tabs.find((t) => t.menuItem.urlPath === activeTabId); const menuPaths = pageTitle?.path?.split(">").map((path) => path.trim()); diff --git a/apps/st/src/store/tab-store.ts b/apps/st/src/store/tab-store.ts index 6c48a5074..ace855808 100644 --- a/apps/st/src/store/tab-store.ts +++ b/apps/st/src/store/tab-store.ts @@ -28,7 +28,7 @@ const useTabStoreHook = create((set, get) => ({ menuList: null, addTab: (menuItem: MenuItem) => { const { tabs, menuList } = get(); - const tabId = menuItem.menuEngNm || ''; + const tabId = menuItem.urlPath || ''; // 이미 존재하는 탭인지 확인 const existingTab = tabs.find((tab) => tab.id === tabId);