diff --git a/.gitignore b/.gitignore index ab07be55d..3327a728e 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,4 @@ apps/fo/.next/**/* pnpm-lock.yaml settings.json .npmrc -.cursor \ No newline at end of file +.cursor diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 000000000..82c73e102 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,3 @@ +#!/bin/sh +BRANCH=$(git rev-parse --abbrev-ref HEAD) +pnpm turbo run build --filter="...[origin/$BRANCH]" diff --git a/apps/cs/src/entities/link/model/link-interface.ts b/apps/cs/src/entities/link/model/link-interface.ts index 244bb4c63..67cd75807 100644 --- a/apps/cs/src/entities/link/model/link-interface.ts +++ b/apps/cs/src/entities/link/model/link-interface.ts @@ -118,7 +118,7 @@ export const linkFormSchema = z.object({ last_link_rslt_cd: z.string().max(4).nullable().optional(), last_link_excn_dt: z.string().max(40).nullable().optional(), next_link_excn_dt: z.string().max(40).nullable().optional(), - last_link_err_cd: z.string().max(10).nullable().optional(), + last_link_err_cd: z.string().max(50, { message: '마지막 연계 오류 코드는 50자 이하입니다.' }).nullable().optional(), mdfcn_dt: z.string().nullable().optional(), mdfr_id: z.string().nullable().optional(), link_cycle_mi: z.coerce.number().nullable().optional().refine((val) => { diff --git a/apps/st/.gitignore b/apps/st/.gitignore index b63718b61..f06d9d40b 100644 --- a/apps/st/.gitignore +++ b/apps/st/.gitignore @@ -38,4 +38,5 @@ yarn-error.log* next-env.d.ts .env* -!.env.example \ No newline at end of file +!.env.example +*.md \ No newline at end of file diff --git a/apps/st/.prettierrc b/apps/st/.prettierrc index b4bfed357..a7963dac2 100644 --- a/apps/st/.prettierrc +++ b/apps/st/.prettierrc @@ -1,3 +1,4 @@ { - "plugins": ["prettier-plugin-tailwindcss"] + "plugins": ["prettier-plugin-tailwindcss"], + "tabWidth": 4 } diff --git a/apps/st/app/(with-base-layout)/layout.tsx b/apps/st/app/(with-base-layout)/layout.tsx index b6f1e1cf8..3fe61855e 100644 --- a/apps/st/app/(with-base-layout)/layout.tsx +++ b/apps/st/app/(with-base-layout)/layout.tsx @@ -1,12 +1,13 @@ "use client"; -import { useEffect, useCallback } from "react"; +import { useEffect, useCallback, useMemo } from "react"; import { usePathname } from "next/navigation"; import { useQueryClient, useQuery } from "@tanstack/react-query"; import type { MenuItem } from "@/entities/menu"; import { useMenuStore, useAlertStore } from "@/shared/lib"; import { useTabStore, getTabStoreState } from "@/store/tab-store"; +import { useTabStore as gridTabStore } from "@rsone/components"; import { getConfig } from "@common/config"; import { getCookie } from "@/shared/lib"; import { getMenuList } from "../../../../packages/common/components/src/api"; @@ -29,10 +30,17 @@ export default function WithBaseLayout({ const queryClient = useQueryClient(); const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); + const currentMenuInfo = useMenuStore((state) => state.currentMenuInfo); const addTab = useTabStore((state) => state.addTab); const setActiveTab = useTabStore((state) => state.setActiveTab); const setMenuList = useTabStore((state) => state.setMenuList); + const activeTabId = useTabStore((state) => state.activeTabId); + const menuList = useTabStore((state) => state.menuList); + const tabs = useTabStore((state) => state.tabs); + const addTabForGrid = gridTabStore((state) => state.addTab); + const setActiveTabForGrid = gridTabStore((state) => state.setActiveTab); + const setMenuListForGrid = gridTabStore((state) => state.setMenuList); const alert = useAlertStore((state) => state.setMessage); const { data: menuListData } = useQuery({ @@ -44,8 +52,9 @@ export default function WithBaseLayout({ useEffect(() => { if (menuListData) { setMenuList(menuListData); + setMenuListForGrid(menuListData); } - }, [menuListData, setMenuList]); + }, [menuListData, setMenuList, setMenuListForGrid]); useEffect(() => { if (!pathname) return; @@ -55,23 +64,73 @@ export default function WithBaseLayout({ const tab = currentTabs.find((t) => t.path === pathname); if (tab) { setActiveTab(tab.id); + setActiveTabForGrid(tab.id); } - }, [pathname, setActiveTab]); + }, [pathname, setActiveTab, setActiveTabForGrid]); + + // 활성 탭의 메뉴를 찾아서 urlPath를 가져옴. 탭이 전부 닫히면 ''를 넘겨 LNB에서 메뉴 강조 제거 + const currentPath = useMemo(() => { + if (tabs.length === 0) return ""; + + if (activeTabId && menuList) { + // menuList에서 활성 탭의 메뉴 찾기 + const findMenuByEngNm = (items: MenuItem[]): MenuItem | null => { + for (const item of items) { + if (item.menuEngNm === activeTabId) { + return item; + } + if (item.children) { + const found = findMenuByEngNm(item.children); + if (found) return found; + } + } + return null; + }; + + const activeMenu = findMenuByEngNm(menuList); + + if (activeMenu?.urlPath) { + return activeMenu.urlPath; + } + } + + // 탭에서 직접 찾기 + if (activeTabId) { + const currentTabs = getTabStoreState().tabs; + const activeTab = currentTabs.find((t) => t.id === activeTabId); + if (activeTab?.menuItem?.urlPath) { + return activeTab.menuItem.urlPath; + } + } + + // currentMenuInfo에서 가져오기 + if (currentMenuInfo?.urlPath) { + return currentMenuInfo.urlPath; + } + + // 기본값으로 pathname 사용 + return pathname ?? ""; + }, [tabs.length, activeTabId, menuList, currentMenuInfo, pathname]); const handleMenuClick = useCallback((item: MenuItem) => { setCurrentMenuInfo(item); const addTabResult: boolean = addTab(item); + + // packages/rsone의 스토어에도 동기화 + if (addTabResult) { + addTabForGrid(item); + } if (!addTabResult) { alert(`최대 추가 할 수 있는 화면 수를 초과 하였습니다. 기존 화면을 닫은 후 이용해주세요.`); } - }, [setCurrentMenuInfo, addTab]); + }, [setCurrentMenuInfo, addTab, addTabForGrid, alert]); return ( {children} diff --git a/apps/st/app/(with-base-layout)/statistics/page.tsx b/apps/st/app/(with-base-layout)/statistics/page.tsx index 3c51a4307..f32417f76 100644 --- a/apps/st/app/(with-base-layout)/statistics/page.tsx +++ b/apps/st/app/(with-base-layout)/statistics/page.tsx @@ -1,3 +1,3 @@ -import { statisticsPage } from "@/pages/statistics"; +import { StatisticsPage } from "@/pages/statistics"; -export default statisticsPage; \ No newline at end of file +export default StatisticsPage; diff --git a/apps/st/eslint.config.mjs b/apps/st/eslint.config.mjs index 9109635e9..18107f0ca 100644 --- a/apps/st/eslint.config.mjs +++ b/apps/st/eslint.config.mjs @@ -6,16 +6,26 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const compat = new FlatCompat({ - baseDirectory: __dirname, + baseDirectory: __dirname, }); const eslintConfig = [ - ...compat.extends("next/core-web-vitals", "next/typescript"), - { - rules: { - "react-hooks/exhaustive-deps": "off", + ...compat.extends("next/core-web-vitals", "next/typescript"), + { + rules: { + "react-hooks/exhaustive-deps": "off", + "@typescript-eslint/no-unused-vars": [ + "warn", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + caughtErrorsIgnorePattern: "^_", + }, + ], + "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-wrapper-object-types": "warn", + }, }, - }, ]; export default eslintConfig; diff --git a/apps/st/middleware.ts b/apps/st/middleware.ts index 4ed1ed018..8b1ecb501 100644 --- a/apps/st/middleware.ts +++ b/apps/st/middleware.ts @@ -32,7 +32,7 @@ export function middleware(req: NextRequest) { `[Request]\n Original Pathname: ${pathname}`, ]; - if (pathname.startsWith("/st-service")) { + if (pathname.startsWith("/st-management-service") || pathname.startsWith("/st-input-service")) { const requestHeaders = new Headers(req.headers); const token = req.cookies.get(CLAIM_NAME)?.value; const userId = req.cookies.get(AUTH_USER_ID)?.value; @@ -138,5 +138,5 @@ export function middleware(req: NextRequest) { } export const config = { - matcher: ["/server/:path*", "/attach-service/:path*", "/api/link/:path*", "/st-service/:path*", "/"], + matcher: ["/server/:path*", "/attach-service/:path*", "/api/link/:path*", "/st-management-service/:path*", "/st-input-service/:path*", "/"], }; diff --git a/apps/st/package.json b/apps/st/package.json index b6de459f8..cd951af0d 100644 --- a/apps/st/package.json +++ b/apps/st/package.json @@ -12,6 +12,7 @@ "@common/assets": "workspace:*", "@common/components": "workspace:*", "@common/config": "workspace:*", + "@faker-js/faker": "^9.9.0", "@fontsource-variable/noto-sans-kr": "^5.2.5", "@frontend-opensource/use-react-hooks": "^1.1.4", "@fullcalendar/core": "^6.1.17", @@ -25,6 +26,7 @@ "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-tooltip": "^1.1.8", + "@rsone/components": "workspace:*", "@tanstack/react-query": "^5.67.1", "@tanstack/react-query-devtools": "^5.75.5", "@tanstack/react-table": "^8.21.2", diff --git a/apps/st/src/app/providers/app-provider.tsx b/apps/st/src/app/providers/app-provider.tsx index efd1f308e..70e69eee8 100644 --- a/apps/st/src/app/providers/app-provider.tsx +++ b/apps/st/src/app/providers/app-provider.tsx @@ -13,6 +13,7 @@ import { PromptDialog } from "@/shared/ui/prompt-dialog"; import { ConfirmDialog } from "@/shared/ui/confirm-dialog"; import { SelectPromptDialog } from "@/shared/ui/select-prompt-dialog"; import { PromptProvider, StoreProvider } from "@/shared/providers"; +import { AlertDialog as RsoneAlertDialog } from "@rsone/components"; const AppProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => { const queryClient = new QueryClient(); @@ -31,6 +32,7 @@ const AppProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => { + diff --git a/apps/st/src/components/button/AddArticleButton.tsx b/apps/st/src/components/button/AddArticleButton.tsx new file mode 100644 index 000000000..b1bb3252f --- /dev/null +++ b/apps/st/src/components/button/AddArticleButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface AddArticleButtonProps { + addArticleFunc: () => void; +} + +const AddArticleButton = ({ addArticleFunc }: AddArticleButtonProps) => { + return ( + + ); +}; + +export default AddArticleButton; \ No newline at end of file diff --git a/apps/st/src/components/button/ApproveButton.tsx b/apps/st/src/components/button/ApproveButton.tsx index 1cbfb0b28..36455f7ff 100644 --- a/apps/st/src/components/button/ApproveButton.tsx +++ b/apps/st/src/components/button/ApproveButton.tsx @@ -6,9 +6,9 @@ interface ApproveButtonProps { const ApproveButton = ({ approveFunc }: ApproveButtonProps) => { return ( - ); }; diff --git a/apps/st/src/components/button/DeleteArticleButton.tsx b/apps/st/src/components/button/DeleteArticleButton.tsx new file mode 100644 index 000000000..1a6432a64 --- /dev/null +++ b/apps/st/src/components/button/DeleteArticleButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface DeleteArticleButtonProps { + deleteArticleFunc: () => void; +} + +const DeleteArticleButton = ({ deleteArticleFunc }: DeleteArticleButtonProps) => { + return ( + + ); +}; + +export default DeleteArticleButton; \ No newline at end of file diff --git a/apps/st/src/components/button/InstallationStatusButton.tsx b/apps/st/src/components/button/InstallationStatusButton.tsx new file mode 100644 index 000000000..fffe4bb9c --- /dev/null +++ b/apps/st/src/components/button/InstallationStatusButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface InstallationStatusButtonProps { + installationStatusFunc: () => void; +} + +const InstallationStatusButton = ({ installationStatusFunc }: InstallationStatusButtonProps) => { + return ( + + ); +}; + +export default InstallationStatusButton; \ No newline at end of file diff --git a/apps/st/src/components/button/LastYearDataButton.tsx b/apps/st/src/components/button/LastYearDataButton.tsx new file mode 100644 index 000000000..d9020c4ae --- /dev/null +++ b/apps/st/src/components/button/LastYearDataButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface LastYearDataButtonProps { + getLastYearDataFunc: () => void; +} + +const LastYearDataButton = ({ getLastYearDataFunc }: LastYearDataButtonProps) => { + return ( + + ); +}; + +export default LastYearDataButton; \ No newline at end of file diff --git a/apps/st/src/components/button/NotApplicableCheckButton.tsx b/apps/st/src/components/button/NotApplicableCheckButton.tsx new file mode 100644 index 000000000..507334e2e --- /dev/null +++ b/apps/st/src/components/button/NotApplicableCheckButton.tsx @@ -0,0 +1,28 @@ +import { Checkbox, buttonVariants, cn } from "@common/components"; +import type React from "react"; + +interface NotApplicableCheckButtonProp { + isCheck: boolean; + setIsCheck: React.Dispatch>; +} + +const NotApplicableCheckButton = ({ isCheck, setIsCheck }: NotApplicableCheckButtonProp) => { + + const handleCheckChange = (value: boolean) => { + setIsCheck(value); + }; + + return ( +
+ + +
+ ); +}; + +export default NotApplicableCheckButton; \ No newline at end of file diff --git a/apps/st/src/components/button/OperateDataButton.tsx b/apps/st/src/components/button/OperateDataButton.tsx new file mode 100644 index 000000000..f2972180d --- /dev/null +++ b/apps/st/src/components/button/OperateDataButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface OperateDataButtonProps { + getOperateDataFunc: () => void; +} + +const OperateDataButton = ({ getOperateDataFunc }: OperateDataButtonProps) => { + return ( + + ); +}; + +export default OperateDataButton; \ No newline at end of file diff --git a/apps/st/src/components/button/RejectButton.tsx b/apps/st/src/components/button/RejectButton.tsx index 66dd34735..8210059ab 100644 --- a/apps/st/src/components/button/RejectButton.tsx +++ b/apps/st/src/components/button/RejectButton.tsx @@ -6,9 +6,9 @@ interface RejectButtonProps { const RejectButton = ({ rejectFunc }: RejectButtonProps) => { return ( - ); }; diff --git a/apps/st/src/components/button/ReturnButton.tsx b/apps/st/src/components/button/ReturnButton.tsx new file mode 100644 index 000000000..b433d66a7 --- /dev/null +++ b/apps/st/src/components/button/ReturnButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface ReturnButtonProps { + returnFunc: () => void; +} + +const ReturnButton = ({ returnFunc }: ReturnButtonProps) => { + return ( + + ); +}; + +export default ReturnButton; \ No newline at end of file diff --git a/apps/st/src/components/button/ReviewOpinionButton.tsx b/apps/st/src/components/button/ReviewOpinionButton.tsx new file mode 100644 index 000000000..50df8fcb4 --- /dev/null +++ b/apps/st/src/components/button/ReviewOpinionButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface ReviewOpinionButtonProps { + reviewOpinionFunc: () => void; +} + +const ReviewOpinionButton = ({ reviewOpinionFunc }: ReviewOpinionButtonProps) => { + return ( + + ); +}; + +export default ReviewOpinionButton; \ No newline at end of file diff --git a/apps/st/src/components/button/SaveButton.tsx b/apps/st/src/components/button/SaveButton.tsx new file mode 100644 index 000000000..08fbb8d94 --- /dev/null +++ b/apps/st/src/components/button/SaveButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface SaveButtonProps { + saveFunc: () => void; +} + +const SaveButton = ({ saveFunc }: SaveButtonProps) => { + return ( + + ); +}; + +export default SaveButton; \ No newline at end of file diff --git a/apps/st/src/components/button/SubmitExceptionButton.tsx b/apps/st/src/components/button/SubmitExceptionButton.tsx new file mode 100644 index 000000000..0bf100e68 --- /dev/null +++ b/apps/st/src/components/button/SubmitExceptionButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface SubmitExceptionButtonProps { + SubmitExceptionFunc: () => void; +} + +const SubmitExceptionButton = ({ SubmitExceptionFunc }: SubmitExceptionButtonProps) => { + return ( + + ); +}; + +export default SubmitExceptionButton; \ No newline at end of file diff --git a/apps/st/src/components/button/SumitButton.tsx b/apps/st/src/components/button/SumitButton.tsx new file mode 100644 index 000000000..0443889b7 --- /dev/null +++ b/apps/st/src/components/button/SumitButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface SubmitButtonProps { + submitFunc: () => void; +} + +const SubmitButton = ({ submitFunc }: SubmitButtonProps) => { + return ( + + ); +}; + +export default SubmitButton; \ No newline at end of file diff --git a/apps/st/src/components/button/UpdateOperateDataButton.tsx b/apps/st/src/components/button/UpdateOperateDataButton.tsx new file mode 100644 index 000000000..8229e7da3 --- /dev/null +++ b/apps/st/src/components/button/UpdateOperateDataButton.tsx @@ -0,0 +1,16 @@ +import { Button } from "@common/components"; + +interface UpdateOperateDataButtonProps { + updateOperateDataButtonFunc: () => void; +} + +const UpdateOperateDataButton = ({ updateOperateDataButtonFunc }: UpdateOperateDataButtonProps) => { + return ( + + ); +}; + +export default UpdateOperateDataButton; \ No newline at end of file diff --git a/apps/st/src/components/css/DataGrid.css b/apps/st/src/components/css/DataGrid.css index b7d8352da..f602400c7 100644 --- a/apps/st/src/components/css/DataGrid.css +++ b/apps/st/src/components/css/DataGrid.css @@ -1,105 +1,53 @@ -/* RealGrid2 폰트 설정 - 루트 폰트와 일치 */ -.rg-root, -.rg-grid, -.rg-body, -.rg-cell, -.rg-header, -.rg-head, -.rg-rowbarcontainer { - font-family: "Noto Sans KR", sans-serif !important; - font-size: 12px !important; - font-weight: 500; - color: #333 !important; +@tailwind components; + +@layer components { + .rg-grid .rg-header .rg-table .rg-header-group-cell { + @apply !bg-[#466995] !text-[#fff]; + } + .rg-grid .rg-header .rg-table .rg-header-cell { + @apply !bg-[#5987bf] !text-[#fff]; + } + .rg-grid .rg-body .rg-table .rg-data-row .rg-data-cell { + @apply !bg-white; + } + /* 셀 클래스가 있으면 위 기본색보다 우선 (같은 specificity + 나중 규칙) */ + .rg-grid .rg-body .rg-table .rg-data-row .rg-data-cell.rg-cell-readonly { + @apply !bg-[#f0f0f0] !text-[#666]; + } + .rg-grid .rg-body .rg-table .rg-data-row .rg-data-cell.rg-cell-verify-error { + @apply !bg-[#ffe6e6] !text-[#c00]; + } + .rg-grid .rg-body .rg-table .rg-data-row .rg-data-cell.rg-cell-total { + @apply !bg-[#e3eaf2]; + } + + [data-theme="black"] { + .rg-grid .rg-header .rg-table .rg-header-group-cell { + @apply !bg-[#3C4043] !text-[#fff]; + } + .rg-grid .rg-header .rg-table .rg-header-cell { + @apply !bg-[#62686d] !text-[#fff]; + } + .rg-grid .rg-body .rg-table .rg-data-row .rg-data-cell { + @apply !bg-[#545556] !text-[#fff]; + } + } + + [data-theme="red"] { + .rg-grid .rg-header .rg-table .rg-header-group-cell { + @apply !bg-[#646469] !text-[#fff]; + } + .rg-grid .rg-header .rg-table .rg-header-cell { + @apply !bg-[#8d8d94] !text-[#fff]; + } + } + + [data-theme="green"] { + .rg-grid .rg-header .rg-table .rg-header-group-cell { + @apply !bg-[#518585] !text-[#fff]; + } + .rg-grid .rg-header .rg-table .rg-header-cell { + @apply !bg-[#6bafae] !text-[#fff]; + } + } } - -/* RealGrid2 컨테이너 스타일 */ -.rg-root { - border-radius: 0.5rem !important; - overflow: hidden !important; - border: 1px solid #dbe2e6 !important; -} - -.rg-grid { - border-radius: 0.5rem !important; - /* box-shadow: 0 0 10px -1px rgba(0, 0, 0, 0.06); */ -} - -/* 헤더 스타일 */ -.rg-header, -.rg-head, -.rg-foot, -.rg-footer, -.rg-fixed-footer { - background-color: #f5f7fa !important; - color: #333 !important; -} - -/* 헤더 셀 스타일 */ -.rg-header .rg-cell, -.rg-head .rg-cell { - background-color: #f5f7fa !important; -} - -/* 헤더 필터링 영역 위치 조정 - 오른쪽 여백 추가 */ -.rg-header-filtering { - left: auto !important; - right: 8px !important; -} - -/* 그룹 헤더 스타일 */ -.rg-header-group, -.rg-header-group-cell { - background-color: #f5f7fa !important; -} - -/* 첫 번째 헤더 셀 - 왼쪽 상단 모서리 */ -.rg-header .rg-cell:first-child, -.rg-head .rg-cell:first-child { - border-top-left-radius: 8px !important; -} - -/* 마지막 헤더 셀 - 오른쪽 상단 모서리 */ -.rg-header .rg-cell:last-child, -.rg-head .rg-cell:last-child { - border-top-right-radius: 8px !important; -} - -/* border color 통일 */ -.rg-header .rg-table tr td, -.rg-head .rg-table tr td:not(:first-child), -.rg-body .rg-table tr td, -.rg-rowbarcontainer .rg-table tr td:not(:first-child) { - border-left: 1px solid #dbe2e6 !important; - border-bottom: 1px solid #dbe2e6 !important; - border-right: none !important; -} -.rg-rowindicator-head, -.rg-rowbarcontainer .rg-table tr td:first-child { - border-right: none !important; - border-bottom: 1px solid #dbe2e6 !important; - border-left: none !important; -} -.rg-footer .rg-table tr td, -.rg-fixed-footer .rg-table tr td, -.rg-foot .rg-table tr td { - border-right: 1px solid #dbe2e6 !important; - border-top: 1px solid #dbe2e6 !important; -} - -.rg-rowbarcontainer .rg-table tr td { - background-color: #f5f7fa !important; -} - -/* 푸터 마지막 요소 - 오른쪽 border 제거 */ -.rg-footer .rg-table tr td:last-child { - border-right: none !important; -} - -/* 고정 컬럼 바 */ -.rg-fixed-column-bar { - background-color: #ccc !important; - border-right: 1px solid #ccc !important; -} - - - diff --git a/apps/st/src/components/module/CompactDataGrid.tsx b/apps/st/src/components/module/CompactDataGrid.tsx new file mode 100644 index 000000000..4377eb762 --- /dev/null +++ b/apps/st/src/components/module/CompactDataGrid.tsx @@ -0,0 +1,295 @@ +import { useRef, useEffect } from "react" +import { ValueType } from "realgrid" + +import RealGrid, { GridFitStyle } from "realgrid" +import { RealGridReact, RGDataColumn } from "realgrid-react" +import type { DataGridProps, RealGridColumnInfo, GridViewWithSetColumns, FooterItemWithCallback } from "../type/DataGrid.type" +import { getComputedValueCallback } from "@/components/util/grid/computedFieldCallbacks" + +// RealGrid 타입 확장 +declare module "realgrid" { + interface GridView { + setOptions(options: { + footer?: { visible?: boolean }; + summaryMode?: 'aggregate' | 'statistical' | 'none'; + checkBar?: { visible?: boolean }; + }): void; + } +} + +RealGrid.setLicenseKey(process.env.NEXT_PUBLIC_ST_REALGRID_KEY || ''); + +/** setDataComparer(field, comparer) - setFields 없이 숫자 정렬용. comparer(field, row1, row2) => -1|0|1 */ +interface RealGridDataProviderComparer { + setDataComparer?(field: string | number, comparer: (field: string | number, row1: number, row2: number) => number): void; + getValue?(row: number, field: string | number): unknown; +} + +/** columnInfo → RealGrid DataField 배열 (computed → valueCallback 포함, setFields용) */ +function buildFieldsFromColumns(columns: { fieldName: string; valueType?: ValueType; computed?: import("../type/DataGrid.type").ComputedFieldConfig }[]) { + return columns.map((col) => { + const field: { fieldName: string; dataType: string; valueCallback?: (prod: unknown, dataRow: number, fieldName: string, fieldNames: string[], values: unknown[]) => number } = { + fieldName: col.fieldName, + dataType: col.valueType === ValueType.NUMBER ? "number" : "text", + }; + if (col.computed) { + const hasFields = "fields" in col.computed && col.computed.fields.length > 0; + const hasNumeratorDenominator = "numeratorFields" in col.computed && col.computed.numeratorFields.length > 0 && col.computed.denominatorFields.length > 0; + if (hasFields || hasNumeratorDenominator) { + field.valueCallback = getComputedValueCallback(col.computed) as (prod: unknown, dataRow: number, fieldName: string, fieldNames: string[], values: unknown[]) => number; + } + } + return field; + }); +} + +/** setDataComparer용 숫자 비교기. setFields 없이 숫자 정렬. */ +function createNumberComparer(dp: RealGridDataProviderComparer): (field: string | number, row1: number, row2: number) => number { + return (field, row1, row2) => { + const get = dp.getValue?.bind(dp); + if (!get) return 0; + const val1 = get(row1, field); + const val2 = get(row2, field); + if (val1 == null && val2 == null) return 0; + if (val1 == null) return 1; + if (val2 == null) return -1; + const num1 = typeof val1 === "number" ? val1 : parseFloat(String(val1)); + const num2 = typeof val2 === "number" ? val2 : parseFloat(String(val2)); + if (isNaN(num1) && isNaN(num2)) return 0; + if (isNaN(num1)) return 1; + if (isNaN(num2)) return -1; + return num1 > num2 ? 1 : num1 < num2 ? -1 : 0; + }; +} + +const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false, rowData, setRowData }: DataGridProps) => { + const { columns, columnLayout } = columnInfo; + const gridRef = useRef(null); + + useEffect(() => { + if (!gridRef.current?.gridView || !gridRef.current?.dataProvider) return; + + const gridView = gridRef.current.gridView; + const dataProvider = gridRef.current.dataProvider; + + // setDataComparer로 숫자 정렬 (setFields 미사용 → 데이터 유실·필드 중복 오류 없음) + const dp = dataProvider as RealGridDataProviderComparer; + if (typeof dp.setDataComparer === "function" && typeof dp.getValue === "function") { + const numberComparer = createNumberComparer(dp); + const seen = new Set(); + columns.forEach((col) => { + 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); + } + } + }); + } + + 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; + } + } + + // 고정 컬럼 설정 + if (fixedColumns !== undefined && fixedColumns > 0) { + gridView.setFixedOptions({ + colCount: fixedColumns, + }); + } + + 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 (gridRef.current?.gridView && columnLayout) { + gridRef.current.gridView.setColumnLayout?.(columnLayout); + } + }, 100); + } + + // footer 설정 (배열 또는 단일 객체 모두 처리) + // setFooters 호출 후 footer 배열 설정 + setTimeout(() => { + const currentGridView = gridRef.current?.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: '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; + }); + + 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; + + if (col.footer.valueCallback) { + (column.footer as { valueCallback?: typeof col.footer.valueCallback }).valueCallback = col.footer.valueCallback; + } + } catch (e) { + console.warn(`Error setting footer valueCallback for column ${col.name}:`, e); + } + }); + }, 200); + + }, [columns, columnLayout, fixedColumns, rowData, showHeaderCheckbox]); + + return ( +
+
+ { + const dp = gridRef.current?.dataProvider as { setFields?: (fields: unknown[]) => void } | undefined; + if (dp?.setFields) { + dp.setFields(buildFieldsFromColumns(columns)); + } + }} + > + {columns.map((column) => ( + + ))} + +
+
+ ); +}; + +export default CompactDataGrid; \ No newline at end of file diff --git a/apps/st/src/components/module/DataGrid.tsx b/apps/st/src/components/module/DataGrid.tsx index be6adc932..7d7f925ee 100644 --- a/apps/st/src/components/module/DataGrid.tsx +++ b/apps/st/src/components/module/DataGrid.tsx @@ -1,14 +1,35 @@ -import { useRef, useEffect, useState } from "react" +import { useRef, useEffect, useLayoutEffect } from "react"; +import { ValueType } from "realgrid"; + +import RealGrid, { GridFitStyle, type DisplayOptions } from "realgrid"; +import { RealGridReact, RGDataColumn } from "realgrid-react"; +import type { + DataGridProps, + RealGridColumnInfo, + GridViewWithSetColumns, + FooterItemWithCallback, + ColumnLayoutItem, + CellStyleCallback, +} from "../type/DataGrid.type"; +import { getComputedValueCallback } from "@/components/util/grid/computedFieldCallbacks"; +import JSZip from "jszip"; +import * as XLSX from "xlsx"; -import RealGrid, { GridFitStyle, type DisplayOptions } from "realgrid" -import { RealGridReact, RGDataColumn } from "realgrid-react" -import type { DataGridProps } from "../type/DataGrid.type" -import JSZip from "jszip" -import * as XLSX from "xlsx" import { useAlertStore } from "@/shared/lib"; import { Button } from "@common/components"; -import { useTabStore } from "@/store/tab-store" +import { useTabStore } from "@/store/tab-store"; + +// RealGrid 타입 확장 +declare module "realgrid" { + interface GridView { + setOptions(options: { + footer?: { visible?: boolean }; + summaryMode?: "aggregate" | "statistical" | "none"; + checkBar?: { visible?: boolean }; + }): void; + } +} // Window 인터페이스 확장 declare global { @@ -22,21 +43,402 @@ if (typeof window !== "undefined") { window.JSZip = JSZip; } -RealGrid.setLicenseKey(process.env.NEXT_PUBLIC_ST_REALGRID_KEY || ''); +RealGrid.setLicenseKey(process.env.NEXT_PUBLIC_ST_REALGRID_KEY || ""); -const DataGrid = ({ columnInfo, rows = [], rowStartNum, isExcelImport = true, fixedColumns }: DataGridProps) => { +/** setDataComparer(field, comparer) - setFields 없이 숫자 정렬용. comparer(field, row1, row2) => -1|0|1 */ +interface RealGridDataProviderComparer { + setDataComparer?( + field: string | number, + comparer: ( + field: string | number, + row1: number, + row2: number, + ) => number, + ): void; + getValue?(row: number, field: string | number): unknown; +} + +/** setDataComparer용 숫자 비교기. setFields 없이 숫자 정렬. */ +function createNumberComparer( + dp: RealGridDataProviderComparer, +): (field: string | number, row1: number, row2: number) => number { + return (field, row1, row2) => { + const get = dp.getValue?.bind(dp); + if (!get) return 0; + const val1 = get(row1, field); + const val2 = get(row2, field); + if (val1 == null && val2 == null) return 0; + if (val1 == null) return 1; + if (val2 == null) return -1; + const num1 = typeof val1 === "number" ? val1 : parseFloat(String(val1)); + const num2 = typeof val2 === "number" ? val2 : parseFloat(String(val2)); + if (isNaN(num1) && isNaN(num2)) return 0; + if (isNaN(num1)) return 1; + if (isNaN(num2)) return -1; + return num1 > num2 ? 1 : num1 < num2 ? -1 : 0; + }; +} + +/** 정렬 필드 값을 숫자로 파싱 (쉼표 제거) */ +function toNum(v: unknown): number { + if (v == null) return NaN; + if (typeof v === "number") return isNaN(v) ? NaN : v; + return parseFloat(String(v).replace(/,/g, "")) || NaN; +} + +/** 헤더에 정렬 화살표 표시 (CSS 방식) */ +function updateHeaderSortIndicator( + gridView: { + columnByIndex?: ( + i: number, + ) => { fieldName?: string; name?: string } | undefined; + columnByName?: ( + name: string, + ) => { fieldName?: string; name?: string } | undefined; + getColumn?: ( + i: number, + ) => { fieldName?: string; name?: string } | undefined; + }, + columns: { fieldName?: string; name: string }[], + sortDir: Record, +) { + try { + columns.forEach((col) => { + if (!col.fieldName && !col.name) return; + + // 컬럼 찾기 + let gridCol: { fieldName?: string; name?: string } | undefined; + for (let i = 0; i < 100; i++) { + const c = + gridView.columnByIndex?.(i) ?? gridView.getColumn?.(i); + if (!c) break; + if ( + c.fieldName === (col.fieldName || col.name) || + c.name === (col.fieldName || col.name) + ) { + gridCol = c; + break; + } + } + if (!gridCol) { + gridCol = gridView.columnByName?.(col.name); + } + + if (!gridCol) return; + + const fieldName = + gridCol.fieldName || gridCol.name || col.fieldName || col.name; + const direction = sortDir[fieldName] || sortDir[col.name] || "none"; + + // DOM에서 헤더 요소 찾기 + const gridEl1 = document.querySelector( + "[data-grid-id]", + ) as HTMLElement | null; + const gridEl2 = document.querySelector( + ".rg-grid", + ) as HTMLElement | null; + const gridEl = gridEl1 || gridEl2; + if (!gridEl) return; + + // 헤더 셀 찾기 (fieldName 또는 name으로) + const headerCells = gridEl.querySelectorAll( + '.rg-header-cell, [class*="header"]', + ); + let targetCell: HTMLElement | null = null; + + headerCells.forEach((cell) => { + const el = cell as HTMLElement; + const text = el.textContent?.trim(); + const colName = col.name; + const colFieldName = col.fieldName; + if ( + text && + (text.includes(colName) || + (colFieldName && text.includes(colFieldName))) + ) { + targetCell = el; + } + }); + + if (!targetCell) return; + + const headerCell = targetCell as HTMLElement; + + // 기존 화살표 제거 + const existingIndicator = headerCell.querySelector( + ".rg-sort-indicator", + ) as HTMLElement | null; + if (existingIndicator) { + existingIndicator.remove(); + } + + // 화살표 추가 + if (direction === "asc" || direction === "desc") { + const indicator = document.createElement("span"); + indicator.className = "rg-sort-indicator"; + indicator.textContent = direction === "asc" ? "▲" : "▼"; + indicator.style.marginLeft = "4px"; + indicator.style.fontSize = "10px"; + indicator.style.color = "#666"; + indicator.style.display = "inline-block"; + indicator.style.verticalAlign = "middle"; + headerCell.appendChild(indicator); + } + }); + } catch (e) { + console.warn("updateHeaderSortIndicator error:", e); + } +} + +/** onSorting: mergeCells: true인 컬럼이 있으면 그룹 내 순서 유지 정렬, 없으면 RealGrid 기본 정렬 */ +function createOnSortingHandler( + columns: { + fieldName?: string; + name: string; + mergeCells?: boolean; + sortdisable?: boolean; + valueType?: ValueType; + }[], + setRowData: React.Dispatch< + React.SetStateAction[]> + >, + sortDirRef: { current: Record }, + originalRowsRef: { + current: Record[]>; + }, +) { + const fieldNames = [ + ...new Set( + columns + .map((c) => c.fieldName) + .filter((x): x is string => typeof x === "string"), + ), + ]; + // mergeCells: true인 컬럼 찾기 (시군구 등) - 그룹 필드로 사용 + // 시군구를 우선으로 찾고, 없으면 첫 번째 mergeCells 컬럼 사용 + const mergeCellCols = columns.filter( + (c) => c.mergeCells === true && c.fieldName, + ); + const mergeCellCol = + mergeCellCols.find((c) => c.fieldName === "gugun") || mergeCellCols[0]; + 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]; + if (idx === undefined) return true; + let sortField: string | null = null; + if (typeof idx === "string") sortField = idx; + else { + const colObj = grid?.getColumn?.(typeof idx === "number" ? idx : 0); + sortField = colObj?.fieldName ?? colObj?.name ?? null; + } + 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(); + 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); + } + const prev = sortDirRef.current[sortField] ?? "none"; + const setRows = ( + ds as { setRows?: (r: unknown[]) => void } + ).setRows?.bind(ds); + + if (prev === "desc") { + const orig = originalRowsRef.current[sortField]; + if (orig && setRows) { + setRows(orig); + setRowData(orig); + } + sortDirRef.current[sortField] = "none"; + return false; + } + if (prev === "none") { + originalRowsRef.current[sortField] = rows.map((r) => ({ ...r })); + } + const sortAsc = prev !== "asc"; + sortDirRef.current[sortField] = sortAsc ? "asc" : "desc"; + const sorted = sortRowsGroupPreserving( + rows, + sortField, + sortAsc, + { groupField, orderByField }, + col.valueType, + ); + setRows?.(sorted); + setRowData(sorted); + return false; + }; +} + +/** sortPreserveGroupOrder: 그룹 간에는 sortField로 정렬, 그룹 내에서는 원본 순서 유지. */ +function sortRowsGroupPreserving( + rows: Record[], + sortField: string, + sortAsc: boolean, + opt: { groupField: string; orderByField?: string }, + valueType?: ValueType, +): Record[] { + const groups = new Map[]>(); + for (const r of rows) { + const k = String(r[opt.groupField] ?? ""); + if (!groups.has(k)) groups.set(k, []); + groups.get(k)!.push(r); + } + + // valueType에 따라 비교 함수 선택 + const compareValue = (val: unknown): number | string => { + if (valueType === ValueType.NUMBER) { + return toNum(val); + } + // 텍스트나 기타 타입은 문자열로 비교 + return String(val ?? ""); + }; + + const rep = (arr: Record[]): number | string => { + const values = arr.map((r) => compareValue(r[sortField])); + if (valueType === ValueType.NUMBER) { + const nums = values.filter( + (v): v is number => typeof v === "number" && !isNaN(v), + ); + if (nums.length === 0) return sortAsc ? Infinity : -Infinity; + return sortAsc ? Math.min(...nums) : Math.max(...nums); + } else { + // 문자열 정렬 + const strs = values.filter( + (v): v is string => typeof v === "string", + ); + if (strs.length === 0) return sortAsc ? "\uffff" : ""; + strs.sort(); + 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]); + if (typeof valA === "number" && typeof valB === "number") { + return (sortAsc ? 1 : -1) * (valA - valB); + } + // 문자열 비교 + const strA = String(valA); + const strB = String(valB); + return (sortAsc ? 1 : -1) * strA.localeCompare(strB); + }); + + return entries.flatMap(([, arr]) => arr); +} + +/** columnInfo → RealGrid DataField 배열 (computed → valueCallback 포함, setFields용) */ +function buildFieldsFromColumns( + columns: { + fieldName: string; + valueType?: ValueType; + computed?: import("../type/DataGrid.type").ComputedFieldConfig; + }[], +) { + return columns.map((col) => { + const field: { + fieldName: string; + dataType: string; + valueCallback?: ( + prod: unknown, + dataRow: number, + fieldName: string, + fieldNames: string[], + values: unknown[], + ) => number; + } = { + fieldName: col.fieldName, + dataType: col.valueType === ValueType.NUMBER ? "number" : "text", + }; + if (col.computed) { + const hasFields = + "fields" in col.computed && col.computed.fields.length > 0; + const hasNumeratorDenominator = + "numeratorFields" in col.computed && + col.computed.numeratorFields.length > 0 && + col.computed.denominatorFields.length > 0; + if (hasFields || hasNumeratorDenominator) { + field.valueCallback = getComputedValueCallback( + col.computed, + ) as ( + prod: unknown, + dataRow: number, + fieldName: string, + fieldNames: string[], + values: unknown[], + ) => number; + } + } + return field; + }); +} + +const DataGrid = ({ + columnInfo, + rowStartNum, + isExcelImport = true, + isExcelExport = true, + fixedColumns, + showHeaderCheckbox = false, + rowData, + setRowData, + getGridDataRef, + cellStyleCallback, + onRowClick, +}: DataGridProps) => { const { columns, columnLayout } = columnInfo; const gridRef = useRef(null); const fileInputRef = useRef(null); + const sortDirRef = useRef>({}); + const originalRowsRef = useRef[]>>({}); + const rowDataRef = useRef[]>(rowData); + const cellStyleCallbackRef = useRef(cellStyleCallback); + rowDataRef.current = rowData; + cellStyleCallbackRef.current = cellStyleCallback; + + useLayoutEffect(() => { + if (!cellStyleCallback || !gridRef.current?.gridView) return; + gridRef.current.gridView.refresh(); + }, [cellStyleCallback, rowData]); + const { setMessage: alert } = useAlertStore((state) => state); const activeTabId = useTabStore((state) => state.activeTabId); const menuList = useTabStore((state) => state.menuList); - const [rowData, setRowData] = useState[]>([]); - const exportExcel = () => { if (rowData.length === 0) { - alert('데이터가 없습니다.'); + alert("데이터가 없습니다."); return; } @@ -44,19 +446,129 @@ const DataGrid = ({ columnInfo, rows = [], rowStartNum, isExcelImport = true, fi const gridView = gridRef.current.gridView; - const menuName = menuList - ?.flatMap((m) => m.children || []) - .flatMap((subM) => subM || []) - .find((s) => s.menuEngNm === activeTabId) - ?.menuKornNm || 'export'; + const menuName = + menuList + ?.flatMap((m) => m.children || []) + .flatMap((subM) => subM || []) + .find((s) => s.menuEngNm === activeTabId)?.menuKornNm || + "export"; + + // 엑셀 import 시 매칭을 위해 헤더에 fieldName 포함 (예: "합계 (swgeProcZoneInnerSm)") + const originalHeaders: Map = new Map(); + columns.forEach((col) => { + if (col.fieldName && gridView.columnByName) { + const gridCol = gridView.columnByName(col.name); + if (gridCol && gridCol.header) { + const originalText = gridCol.header.text || ""; + originalHeaders.set(col.name, originalText); + const headerWithFieldName = `${originalText} (${col.fieldName})`; + gridCol.header.text = headerWithFieldName; + } + } + }); + + // exportGrid 호출 전에 columnLayout 정규화 (col 속성 추가) + const normalizeLayoutForExport = ( + layout: ColumnLayoutItem[], + ): ColumnLayoutItem[] => { + return layout.map((item) => { + if (typeof item === "string") { + return item; + } + if (item && typeof item === "object") { + // { column: string, footerUserSpans?: ... } 형태인 경우 + if ("column" in item && typeof item.column === "string") { + const colItem = item as { + column: string; + footerUserSpans?: unknown[]; + }; + // col 속성 추가 (RealGrid가 exportGrid에서 필요로 함) + return { + ...colItem, + col: + gridView.columnByName?.(colItem.column) || null, + } as ColumnLayoutItem; + } + // { name: string, items: ... } 형태인 경우 + if ("items" in item && Array.isArray(item.items)) { + return { + ...item, + items: normalizeLayoutForExport( + item.items as ColumnLayoutItem[], + ), + }; + } + } + return item; + }); + }; + + const originalLayout = columnLayout; + let normalizedLayout: ColumnLayoutItem[] | undefined; + let layoutRestored = false; + + // footerUserSpans가 있는 경우에만 정규화 + const checkFooterUserSpans = (layout: ColumnLayoutItem[]): 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 as ColumnLayoutItem[], + ); + } + return false; + }); + }; + + if (checkFooterUserSpans(columnLayout)) { + normalizedLayout = normalizeLayoutForExport(columnLayout); + // 정규화된 layout을 임시로 설정 + gridView.setColumnLayout?.(normalizedLayout); + } gridView.exportGrid({ - type: 'excel', - target: 'local', + type: "excel", + target: "local", fileName: `${menuName}.xlsx`, - footer: 'hidden', + footer: "hidden", done: () => { - alert('내보내기가 완료되었습니다.'); + // 헤더 원복 + columns.forEach((col) => { + if (col.fieldName && gridView.columnByName) { + const gridCol = gridView.columnByName(col.name); + if ( + gridCol && + gridCol.header && + originalHeaders.has(col.name) + ) { + gridCol.header.text = + originalHeaders.get(col.name) || ""; + } + } + }); + // columnLayout 원복 (footerUserSpans 유지) + if (normalizedLayout && !layoutRestored) { + layoutRestored = true; + setTimeout(() => { + if (gridRef.current?.gridView && originalLayout) { + gridRef.current.gridView.setColumnLayout?.( + originalLayout, + ); + } + }, 100); + } + alert("내보내기가 완료되었습니다."); }, }); }; @@ -75,21 +587,24 @@ const DataGrid = ({ columnInfo, rows = [], rowStartNum, isExcelImport = true, fi try { const data = event.target?.result; if (!data) { - alert('파일을 읽을 수 없습니다.'); + alert("파일을 읽을 수 없습니다."); return; } // SheetJS로 엑셀 파일을 JSON으로 변환 - const workbook = XLSX.read(data, { type: 'array', cellDates: true }); + const workbook = XLSX.read(data, { + type: "array", + cellDates: true, + }); const firstSheetName = workbook.SheetNames[0]; - const worksheet = workbook.Sheets[firstSheetName || '']; + const worksheet = workbook.Sheets[firstSheetName || ""]; - if (!worksheet || !worksheet['!ref']) { - alert('워크시트를 읽을 수 없습니다.'); + if (!worksheet || !worksheet["!ref"]) { + alert("워크시트를 읽을 수 없습니다."); return; } - const range = XLSX.utils.decode_range(worksheet['!ref']); + const range = XLSX.utils.decode_range(worksheet["!ref"]); const headerRowCount = rowStartNum || 1; // 기본값 1 const headerStartRow = Math.max(0, headerRowCount - 1); // 0-based index @@ -98,13 +613,28 @@ const DataGrid = ({ columnInfo, rows = [], rowStartNum, isExcelImport = true, fi const headerRowIndexes: number[] = []; for (let col = range.s.c; col <= range.e.c; col++) { - let headerValue = ''; + let headerValue = ""; let headerRowIndex = headerStartRow; // rowStartNum 행부터 시작해서 위로 올라가면서 헤더 찾기 - for (let rowIndex = headerStartRow; rowIndex >= 0; rowIndex--) { - const cell = worksheet[XLSX.utils.encode_cell({ r: rowIndex, c: col })]; - if (cell && cell.v !== undefined && cell.v !== null && cell.v !== '') { + for ( + let rowIndex = headerStartRow; + rowIndex >= 0; + rowIndex-- + ) { + const cell = + worksheet[ + XLSX.utils.encode_cell({ + r: rowIndex, + c: col, + }) + ]; + if ( + cell && + cell.v !== undefined && + cell.v !== null && + cell.v !== "" + ) { headerValue = String(cell.v); headerRowIndex = rowIndex; break; @@ -122,28 +652,105 @@ const DataGrid = ({ columnInfo, rows = [], rowStartNum, isExcelImport = true, fi } // 실제 데이터가 시작하는 행 찾기 (헤더가 있는 최대 행 번호 + 1) - const maxHeaderRowIndex = headerRowIndexes.length > 0 ? Math.max(...headerRowIndexes) : headerStartRow; + const maxHeaderRowIndex = + headerRowIndexes.length > 0 + ? Math.max(...headerRowIndexes) + : headerStartRow; const dataStartRow = maxHeaderRowIndex + 1; + // 엑셀 컬럼 인덱스 → 그리드 fieldName 매핑 + const headerToFieldNameMap = new Map(); + 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]) { + const extractedFieldName = fieldNameMatch[1]; + if ( + columns.find( + (c) => c.fieldName === extractedFieldName, + ) + ) { + fieldName = extractedFieldName; + } + } + + // 매칭 실패 시 원본 헤더 텍스트 사용 + if (!fieldName) { + console.warn( + `엑셀 컬럼 ${colIndex + 1} (헤더: "${headerText}") 매칭 실패 → 헤더 텍스트를 fieldName으로 사용`, + ); + fieldName = headerText; + } + + headerToFieldNameMap.set(headerText, fieldName); + }); + // 데이터 행 읽기 - const dataRows: Record[] = []; + const dataRows: Record[] = []; for (let row = dataStartRow; row <= range.e.r; row++) { - const rowData: Record = {}; + const rowData: Record = {}; let hasData = false; - for (let colIndex = 0; colIndex < headers.length; colIndex++) { + for ( + let colIndex = 0; + colIndex < headers.length; + colIndex++ + ) { const col = range.s.c + colIndex; - const cell = worksheet[XLSX.utils.encode_cell({ r: row, c: col })]; - const headerName = headers[colIndex] || `Column${colIndex + 1}`; - const cellValue = cell && cell.v !== undefined && cell.v !== null - ? String(cell.v) - : ''; + const cell = + worksheet[ + XLSX.utils.encode_cell({ r: row, c: col }) + ]; + const headerName = + headers[colIndex] || `Column${colIndex + 1}`; + // 헤더 텍스트를 fieldName으로 변환 + const fieldName = + headerToFieldNameMap.get(headerName) || + headerName; - if (cellValue !== '') { + let cellValue: string | number = ""; + if ( + cell && + cell.v !== undefined && + cell.v !== null + ) { + // 엑셀 셀 타입이 숫자이거나 값이 숫자인 경우 숫자로 변환 + if ( + cell.t === "n" || + (typeof cell.v === "number" && + !isNaN(cell.v)) + ) { + cellValue = cell.v as number; + } else { + const stringValue = String(cell.v); + // 문자열이지만 숫자로 변환 가능한 경우 숫자로 변환 + const numericValue = Number( + stringValue.replace(/,/g, ""), + ); + if ( + !isNaN(numericValue) && + stringValue.trim() !== "" + ) { + cellValue = numericValue; + } else { + cellValue = stringValue; + } + } + } + + if ( + cellValue !== "" && + cellValue !== null && + cellValue !== undefined + ) { hasData = true; } - rowData[headerName] = cellValue; + rowData[fieldName] = cellValue; } // 데이터가 하나라도 있는 행만 추가 @@ -151,44 +758,125 @@ const DataGrid = ({ columnInfo, rows = [], rowStartNum, isExcelImport = true, fi dataRows.push(rowData); } } - setRowData(dataRows); } catch (error) { - console.error('엑셀 파일 파싱 오류:', error); - alert('엑셀 파일 파싱 중 오류가 발생했습니다.'); + console.error("엑셀 파일 파싱 오류:", error); + alert("엑셀 파일 파싱 중 오류가 발생했습니다."); } finally { if (fileInputRef.current) { - fileInputRef.current.value = ''; + fileInputRef.current.value = ""; } } }; reader.onerror = () => { - alert('파일 읽기 중 오류가 발생했습니다.'); + alert("파일 읽기 중 오류가 발생했습니다."); if (fileInputRef.current) { - fileInputRef.current.value = ''; + fileInputRef.current.value = ""; } }; reader.readAsArrayBuffer(file); } catch (error) { - console.error('엑셀 파일 가져오기 오류:', error); - alert('엑셀 파일 가져오기 중 오류가 발생했습니다.'); + console.error("엑셀 파일 가져오기 오류:", error); + alert("엑셀 파일 가져오기 중 오류가 발생했습니다."); if (fileInputRef.current) { - fileInputRef.current.value = ''; + fileInputRef.current.value = ""; } } }; useEffect(() => { - if (!gridRef.current?.gridView) return; + if (!gridRef.current?.gridView || !gridRef.current?.dataProvider) + return; const gridView = gridRef.current.gridView; + const dataProvider = gridRef.current.dataProvider; - (gridView.displayOptions as DisplayOptions).fitStyle = GridFitStyle.EVEN; + // mergeCells: true인 컬럼이 있으면 onSorting에서 클라이언트 정렬로 처리 + const hasMergeCells = columns.some((col) => col.mergeCells === true); + + // setDataComparer로 숫자 정렬 (mergeCells가 있으면 onSorting에서 클라이언트 정렬로 처리) + const dp = 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에서 그룹 내 순서 유지 정렬 적용 + ( + gridView as { + onSorting?: (g: unknown, f: unknown[], d: unknown[]) => boolean; + } + ).onSorting = createOnSortingHandler( + columns, + setRowData, + sortDirRef, + originalRowsRef, + ); + + (gridView.displayOptions as DisplayOptions).fitStyle = + GridFitStyle.EVEN; + gridView.displayOptions.rowHeight = 30; gridView.header.height = 60; - if (rows.length > 0) { - setRowData(rows); + + // 헤더 체크박스 표시 여부 설정 + 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; + } } // 고정 컬럼 설정 @@ -197,49 +885,339 @@ const DataGrid = ({ columnInfo, rows = [], rowStartNum, isExcelImport = true, fi colCount: fixedColumns, }); } - }, [rows, columns, columnLayout, fixedColumns]); + + 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 (gridRef.current?.gridView && columnLayout) { + gridRef.current.gridView.setColumnLayout?.(columnLayout); + } + }, 100); + } + + // footer 설정 (배열 또는 단일 객체 모두 처리) + // setFooters 호출 후 footer 배열 설정 + setTimeout(() => { + const currentGridView = gridRef.current?.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: "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; + }, + ); + + 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; + + if (col.footer.valueCallback) { + ( + column.footer as { + valueCallback?: typeof col.footer.valueCallback; + } + ).valueCallback = col.footer.valueCallback; + } + } catch (e) { + console.warn( + `Error setting footer valueCallback for column ${col.name}:`, + e, + ); + } + }); + }, 200); + + if (getGridDataRef) { + const fieldNames = columns + .map((c) => c.fieldName) + .filter(Boolean) as string[]; + getGridDataRef.current = () => { + const gv = gridRef.current?.gridView as + | { + getDataSource?: () => { + getRowCount(): number; + getValue(r: number, f: string): unknown; + }; + } + | undefined; + if (!gv?.getDataSource) return []; + const ds = gv.getDataSource(); + if (!ds) return []; + 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; + }; + }, [ + columns, + columnLayout, + fixedColumns, + rowData, + showHeaderCheckbox, + getGridDataRef, + ]); + + // 행 클릭 이벤트 설정 + useEffect(() => { + if (!gridRef.current?.gridView || !onRowClick) return; + + const gridView = gridRef.current.gridView; + + // onCellClicked 이벤트 핸들러 설정 + gridView.onCellClicked = (grid, clickData) => { + // 데이터 셀만 처리 (헤더, 푸터 등 제외) + if ( + clickData.cellType === "data" && + clickData.itemIndex !== undefined + ) { + try { + // 행 전체 데이터 가져오기 + const row = rowData[clickData.itemIndex]; + + // 부모 컴포넌트로 데이터 전달 + onRowClick(row ?? {}); + } catch (error) { + console.error("행 데이터 가져오기 오류:", error); + } + } + }; + + // cleanup: 컴포넌트 언마운트 시 이벤트 핸들러 제거 + return () => { + if (gridView.onCellClicked) { + gridView.onCellClicked = undefined; + } + }; + }, [onRowClick]); return ( -
+
-
- {isExcelImport && - - } - + )} + {isExcelExport && ( + + )}
- - {columns.map((column) => ( - - ))} + { + if (!grid) return; + (grid as { onSorting?: (g: unknown, f: unknown[], d: unknown[]) => boolean }).onSorting = createOnSortingHandler(columns, setRowData, sortDirRef, originalRowsRef); + const dataProvider = gridRef.current?.dataProvider as unknown as + | { setFields?(f: unknown[]): void; setRows?(r: Record[]): void; getJsonRow?(r: number): Record } + | undefined; + if (dataProvider?.setFields) { + dataProvider.setFields(buildFieldsFromColumns(columns)); + } + if (dataProvider?.setRows && rowData?.length) { + dataProvider.setRows(rowData); + } + const gridView = gridRef.current?.gridView ?? grid; + if (!gridView?.columnByName) return; + setTimeout(() => { + const gv = gridRef.current?.gridView; + if (!gv?.columnByName) return; + columns.forEach((column) => { + const baseStyleName = column.styleName; + const gridCol = gv.columnByName(column.name) as { styleCallback?: (g: unknown, dataCell: { itemIndex?: number; index?: { itemIndex?: number }; dataField?: string; fieldName?: string }) => string } | null; + if (gridCol) { + gridCol.styleCallback = (_g, dataCell) => { + const itemIndex = dataCell?.index?.itemIndex ?? dataCell?.itemIndex ?? -1; + const fieldName = dataCell?.dataField ?? dataCell?.fieldName ?? column.fieldName; + const data = rowDataRef.current; + if (itemIndex < 0 || itemIndex >= data.length) return baseStyleName ?? ''; + const row = data[itemIndex] as Record; + const extra = cellStyleCallbackRef.current?.({ rowIndex: itemIndex, fieldName, row }); + if (!extra) return baseStyleName ?? ''; + return baseStyleName ? `${extra} ${baseStyleName}` : extra; + }; + } + }); + gv.refresh(); + }, 0); + }} + > + {columns.map((column) => { + const baseStyleName = column.styleName; + + return ( + + ); + })}
); }; -export default DataGrid; \ No newline at end of file +export default DataGrid; diff --git a/apps/st/src/components/module/SearchForm.tsx b/apps/st/src/components/module/SearchForm.tsx index b1fda5a07..91d823ed6 100644 --- a/apps/st/src/components/module/SearchForm.tsx +++ b/apps/st/src/components/module/SearchForm.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import useSWR from 'swr'; import { @@ -18,9 +18,9 @@ from "@common/components"; import { useAlertStore } from "@/shared/lib"; import { type SearchFormProps, type SearchFormValues, defaultSearchFormProps } from "../type/SearchForm.type"; import { statisticsAPi } from "@/entities/statistics/api/statistics-service"; -import type { ApiResponse, Sido, Sgg } from "@/entities/statistics/model/statistics-interface"; +import type { ApiResponse, SearchCondition, Sgg } from "@/entities/statistics/model/statistics-interface"; -const getSidoListFetcher = async (): Promise> => { +const getSidoListFetcher = async (): Promise> => { return statisticsAPi.getSidoList(); }; @@ -31,15 +31,11 @@ const getSggListFetcher = async (key: [string, string]): Promise { const { setMessage: alert } = useAlertStore((state) => state); const mergedProps = { ...defaultSearchFormProps, ...props }; - const [values, setValues] = useState({ - sido: props.defaultValues?.sido || "", - sgg: props.defaultValues?.sgg || "", - year: props.defaultValues?.year || "", - order: props.defaultValues?.order || "", - fctName: props.defaultValues?.fctName || "", - }); - const { data: sidoList } = useSWR>( + const currentYear = new Date().getFullYear(); + const defaultYear = currentYear - 1; + + const { data: sidoList } = useSWR>( "sido-list", getSidoListFetcher, { @@ -61,6 +57,15 @@ const SearchForm = (props: SearchFormProps = {}) => { } ); + const [values, setValues] = useState({ + sido: props.defaultValues?.sido || '', + gugun: props.defaultValues?.gugun || '', + year: props.defaultValues?.year || defaultYear.toString(), + order: props.defaultValues?.order || '', + fctName: props.defaultValues?.fctName || '', + bsnmCd: props.defaultValues?.bsnmCd || '', + }); + const { data: sggList } = useSWR>( values.sido && values.sido !== "ALL" ? ["sgg-list", values.sido] : null, getSggListFetcher, @@ -83,6 +88,7 @@ const SearchForm = (props: SearchFormProps = {}) => { } ); + const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); props.onSubmit?.(values); @@ -90,17 +96,44 @@ const SearchForm = (props: SearchFormProps = {}) => { const handleReset = () => { const resetValues: SearchFormValues = { - sido: "", - sgg: "", - year: "", - order: "", - fctName: "", + sido: '', + gugun: '', + year: String(defaultYear), + order: '', + fctName: '', + bsnmCd: '', }; setValues(resetValues); props.onReset?.(); - props.onSubmit?.(resetValues); }; + const handleSidoChange = (value: string) => { + const selectedBsnm = sidoList?.data.sidoList.find((v) => v.sido === value)?.bsnmCd || ''; + + setValues((prev) => ({ + ...prev, + sido: value, + gugun: '', + bsnmCd: selectedBsnm, + })); + }; + + const handleSggChange = (value: string) => { + const selectedBsnm = value === 'ALL' + ? (sidoList?.data.sidoList.find((v) => v.sido === values.sido)?.bsnmCd || '') + : (sggList?.data?.find((v) => v.gugun === value)?.bsnmCd || ''); + + setValues((prev) => ({ + ...prev, + gugun: value, + bsnmCd: selectedBsnm, + })); + }; + + useEffect(() => { + props.onValuesChange?.(values); + }, [values]); + return (
@@ -110,13 +143,13 @@ const SearchForm = (props: SearchFormProps = {}) => { - - + - 전체 - {sidoList?.data?.map((sido) => ( + 선택 + {sidoList?.data?.sidoList?.map((sido) => ( {sido.sido} @@ -125,12 +158,12 @@ const SearchForm = (props: SearchFormProps = {}) => {
} - {mergedProps.sgg && + {mergedProps.gugun &&
- @@ -152,10 +185,14 @@ const SearchForm = (props: SearchFormProps = {}) => {
@@ -176,10 +213,10 @@ const SearchForm = (props: SearchFormProps = {}) => {
}
- -
@@ -202,7 +239,7 @@ const SearchForm = (props: SearchFormProps = {}) => { } {mergedProps.userMenual &&
- diff --git a/apps/st/src/components/module/SplitDataGrid.tsx b/apps/st/src/components/module/SplitDataGrid.tsx new file mode 100644 index 000000000..7d24c96c0 --- /dev/null +++ b/apps/st/src/components/module/SplitDataGrid.tsx @@ -0,0 +1,35 @@ +import CompactDataGrid from "./CompactDataGrid"; +import type { SplitDataGridProps } from "../type/DataGrid.type"; + +const SplitDataGrid = ({ + leftColumnInfo, + rightColumnInfo, + leftFixedColumns, + rightFixedColumns, + showHeaderCheckbox = false, + leftRowData, + rightRowData, + setLeftRowData, + setRightRowData, +}: SplitDataGridProps) => { + return ( +
+ + +
+ ); +}; + +export default SplitDataGrid; diff --git a/apps/st/src/components/module/TabDataGrid.tsx b/apps/st/src/components/module/TabDataGrid.tsx new file mode 100644 index 000000000..71d94fad3 --- /dev/null +++ b/apps/st/src/components/module/TabDataGrid.tsx @@ -0,0 +1,1170 @@ +import { useRef, useEffect, useState } from "react" +import { ValueType } from "realgrid" + +import RealGrid, { GridFitStyle } from "realgrid" +import { RealGridReact, RGDataColumn } from "realgrid-react" +import type { TabDataGridProps, ColumnInfo, RealGridColumnInfo, GridViewWithSetColumns, FooterItemWithCallback, ColumnLayoutItem } from "../type/DataGrid.type" +import { getComputedValueCallback } from "@/components/util/grid/computedFieldCallbacks" +import JSZip from "jszip" +import * as XLSX from "xlsx" +import { useAlertStore } from "@/shared/lib"; +import { useTabStore } from "@/store/tab-store" + +import { Tabs, TabsList, TabsTrigger, TabsContent } from "@common/components"; +import { Button } from "@common/components"; +import SplitDataGrid from "./SplitDataGrid"; + +// RealGrid 타입 확장 +declare module "realgrid" { + interface GridView { + setOptions(options: { + footer?: { visible?: boolean }; + summaryMode?: 'aggregate' | 'statistical' | 'none'; + checkBar?: { visible?: boolean }; + }): void; + } +} + +interface RealGridDataProviderFill { + fillJsonData?(data: Record[], options?: { fillMode?: string }): void; +} + +/** setDataComparer(field, comparer) - setFields 없이 숫자 정렬용. comparer(field, row1, row2) => -1|0|1 */ +interface RealGridDataProviderComparer { + setDataComparer?(field: string | number, comparer: (field: string | number, row1: number, row2: number) => number): void; + getValue?(row: number, field: string | number): unknown; +} + +// Window 인터페이스 확장 +declare global { + interface Window { + JSZip: typeof JSZip; + } +} + +// RealGrid가 jszip을 사용할 수 있도록 전역에 등록 +if (typeof window !== "undefined") { + window.JSZip = JSZip; +} + +RealGrid.setLicenseKey(process.env.NEXT_PUBLIC_ST_REALGRID_KEY || ''); + +/** 정렬 필드 값을 숫자로 파싱 (쉼표 제거) */ +function toNum(v: unknown): number { + if (v == null) return NaN; + if (typeof v === "number") return isNaN(v) ? NaN : v; + return parseFloat(String(v).replace(/,/g, "")) || NaN; +} + +/** 헤더에 정렬 화살표 표시 (CSS 방식) */ +function updateHeaderSortIndicator( + gridView: { + columnByIndex?: (i: number) => { fieldName?: string; name?: string } | undefined; + columnByName?: (name: string) => { fieldName?: string; name?: string } | undefined; + getColumn?: (i: number) => { fieldName?: string; name?: string } | undefined; + getElement?: () => HTMLElement | null; + container?: HTMLElement; + }, + columns: { fieldName?: string; name: string }[], + sortDir: Record, + gridElement?: HTMLElement | null +) { + try { + // 그리드 DOM 요소 찾기 + let gridEl: HTMLElement | null = null; + if (gridElement) { + gridEl = gridElement; + } else if (gridView.getElement) { + gridEl = gridView.getElement(); + } else if (gridView.container) { + gridEl = gridView.container; + } else { + // 폴백: 모든 그리드 중에서 찾기 + const allGrids = document.querySelectorAll('.rg-grid, [data-grid-id]'); + if (allGrids.length > 0) { + // 활성 탭의 그리드를 찾기 위해 TabsContent 내부의 그리드 찾기 + const activeTabContent = document.querySelector('[data-state="active"]')?.closest('[role="tabpanel"]'); + if (activeTabContent) { + gridEl = activeTabContent.querySelector('.rg-grid, [data-grid-id]') as HTMLElement; + } + if (!gridEl && allGrids.length === 1) { + gridEl = allGrids[0] as HTMLElement; + } + } + } + + 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(); + const colName = col.name; + const colFieldName = col.fieldName; + // 헤더 텍스트와 컬럼 이름이 일치하는지 확인 + if (text && ( + text === colName || + text === colFieldName || + text.includes(colName) || + (colFieldName && text.includes(colFieldName)) + )) { + 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"; + indicator.textContent = direction === "asc" ? "▲" : "▼"; + indicator.style.marginLeft = "4px"; + indicator.style.fontSize = "10px"; + indicator.style.color = "#666"; + indicator.style.display = "inline-block"; + indicator.style.verticalAlign = "middle"; + headerCell.appendChild(indicator); + }); + } catch (e) { + console.warn("updateHeaderSortIndicator error:", e); + } +} + +/** onSorting: mergeCells: true인 컬럼이 있으면 그룹 내 순서 유지 정렬, 없으면 RealGrid 기본 정렬 */ +function createOnSortingHandler( + columns: { fieldName?: string; name: string; mergeCells?: boolean; sortdisable?: boolean; valueType?: ValueType }[], + setRowData: React.Dispatch[]>>, + sortDirRef: { current: Record }, + originalRowsRef: { current: Record[]> }, + findGridElement?: () => HTMLElement | null +) { + const fieldNames = [...new Set(columns.map((c) => c.fieldName).filter((x): x is string => typeof x === "string"))]; + // mergeCells: true인 컬럼 찾기 (시군구 등) - 그룹 필드로 사용 + // 시군구를 우선으로 찾고, 없으면 첫 번째 mergeCells 컬럼 사용 + const mergeCellCols = columns.filter((c) => c.mergeCells === true && c.fieldName); + const mergeCellCol = mergeCellCols.find((c) => c.fieldName === 'gugun') || mergeCellCols[0]; + 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]; + if (idx === undefined) return true; + let sortField: string | null = null; + if (typeof idx === "string") sortField = idx; + else { + const colObj = grid?.getColumn?.(typeof idx === "number" ? idx : 0); + sortField = (colObj?.fieldName ?? colObj?.name) ?? null; + } + 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(); + 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); + } + const prev = sortDirRef.current[sortField] ?? "none"; + const setRows = (ds as { setRows?: (r: unknown[]) => void }).setRows?.bind(ds); + + if (prev === "desc") { + const orig = originalRowsRef.current[sortField]; + if (orig && setRows) { + setRows(orig); + setRowData(orig); + } + sortDirRef.current[sortField] = "none"; + return false; + } + if (prev === "none") { + originalRowsRef.current[sortField] = rows.map((r) => ({ ...r })); + } + const sortAsc = prev !== "asc"; + sortDirRef.current[sortField] = sortAsc ? "asc" : "desc"; + const sorted = sortRowsGroupPreserving(rows, sortField, sortAsc, { groupField, orderByField }, col.valueType); + setRows?.(sorted); + setRowData(sorted); + return false; + }; +} + +/** sortPreserveGroupOrder: 그룹 간에는 sortField로 정렬, 그룹 내에서는 원본 순서 유지. */ +function sortRowsGroupPreserving( + rows: Record[], + sortField: string, + sortAsc: boolean, + opt: { groupField: string; orderByField?: string }, + valueType?: ValueType +): Record[] { + const groups = new Map[]>(); + for (const r of rows) { + const k = String(r[opt.groupField] ?? ""); + if (!groups.has(k)) groups.set(k, []); + groups.get(k)!.push(r); + } + + // valueType에 따라 비교 함수 선택 + const compareValue = (val: unknown): number | string => { + if (valueType === ValueType.NUMBER) { + return toNum(val); + } + // 텍스트나 기타 타입은 문자열로 비교 + return String(val ?? ""); + }; + + const rep = (arr: Record[]): number | string => { + const values = arr.map((r) => compareValue(r[sortField])); + if (valueType === ValueType.NUMBER) { + const nums = values.filter((v): v is number => typeof v === "number" && !isNaN(v)); + if (nums.length === 0) return sortAsc ? Infinity : -Infinity; + return sortAsc ? Math.min(...nums) : Math.max(...nums); + } else { + // 문자열 정렬 + const strs = values.filter((v): v is string => typeof v === "string"); + if (strs.length === 0) return sortAsc ? "\uffff" : ""; + strs.sort(); + 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]); + if (typeof valA === "number" && typeof valB === "number") { + return (sortAsc ? 1 : -1) * (valA - valB); + } + // 문자열 비교 + const strA = String(valA); + const strB = String(valB); + return (sortAsc ? 1 : -1) * strA.localeCompare(strB); + }); + + return entries.flatMap(([, arr]) => arr); +} + +/** columnInfo → RealGrid DataField 배열 (computed → valueCallback 포함, setFields용) */ +function buildFieldsFromColumns(columns: { fieldName: string; valueType?: ValueType; computed?: import("../type/DataGrid.type").ComputedFieldConfig }[]) { + return columns.map((col) => { + const field: { fieldName: string; dataType: string; valueCallback?: (prod: unknown, dataRow: number, fieldName: string, fieldNames: string[], values: unknown[]) => number } = { + fieldName: col.fieldName, + dataType: col.valueType === ValueType.NUMBER ? "number" : "text", + }; + if (col.computed) { + const hasFields = "fields" in col.computed && col.computed.fields.length > 0; + const hasNumeratorDenominator = "numeratorFields" in col.computed && col.computed.numeratorFields.length > 0 && col.computed.denominatorFields.length > 0; + if (hasFields || hasNumeratorDenominator) { + field.valueCallback = getComputedValueCallback(col.computed) as (prod: unknown, dataRow: number, fieldName: string, fieldNames: string[], values: unknown[]) => number; + } + } + return field; + }); +} + +/** setDataComparer용 숫자 비교기. setFields 없이 숫자 정렬. */ +function createNumberComparer(dp: RealGridDataProviderComparer): (field: string | number, row1: number, row2: number) => number { + return (field, row1, row2) => { + const get = dp.getValue?.bind(dp); + if (!get) return 0; + const val1 = get(row1, field); + const val2 = get(row2, field); + if (val1 == null && val2 == null) return 0; + if (val1 == null) return 1; + if (val2 == null) return -1; + const num1 = typeof val1 === "number" ? val1 : parseFloat(String(val1)); + const num2 = typeof val2 === "number" ? val2 : parseFloat(String(val2)); + if (isNaN(num1) && isNaN(num2)) return 0; + if (isNaN(num1)) return 1; + if (isNaN(num2)) return -1; + return num1 > num2 ? 1 : num1 < num2 ? -1 : 0; + }; +} + +const TabDataGrid = ({ columnInfo, isExcelImport = true, isExcelExport = true, rows = [], showHeaderCheckbox = false, rowDataMap, setRowDataMap, activeTab: activeTabProp, onActiveTabChange }: TabDataGridProps) => { + // 각 탭별로 그리드 ref와 데이터를 관리 + const gridRefs = useRef>(new Map()); + const fileInputRefs = useRef>(new Map()); + // 각 탭별로 정렬 상태 관리 + const sortDirRefs = useRef>>>(new Map()); + const originalRowsRefs = useRef[]>>>>(new Map()); + const { setMessage: alert } = useAlertStore((state) => state); + const activeTabId = useTabStore((state) => state.activeTabId); + const menuList = useTabStore((state) => state.menuList); + + const [internalActiveTab, setInternalActiveTab] = useState(() => { + const firstTab = columnInfo[0]; + return firstTab?.tabKey || ''; + }); + const isControlled = activeTabProp !== undefined; + const activeTab = isControlled ? activeTabProp : internalActiveTab; + const setActiveTab = isControlled ? (onActiveTabChange ?? (() => {})) : setInternalActiveTab; + + const exportExcel = (tabKey: string) => { + const currentRowData = rowDataMap.get(tabKey) || []; + if (currentRowData.length === 0) { + alert('데이터가 없습니다.'); + return; + } + + const gridRef = gridRefs.current.get(tabKey); + if (!gridRef?.gridView) return; + + const gridView = gridRef.gridView; + + const menuName = menuList + ?.flatMap((m) => m.children || []) + .flatMap((subM) => subM || []) + .find((s) => s.menuEngNm === activeTabId) + ?.menuKornNm || 'export'; + + const columnInfoItem = columnInfo.find(info => info.tabKey === tabKey); + if (!columnInfoItem) return; + + const tabLabel = columnInfoItem.tabLabel || tabKey; + const columns = columnInfoItem.columns || []; + const columnLayout = columnInfoItem.columnLayout || []; + + // 엑셀 import 시 매칭을 위해 헤더에 fieldName 포함 (예: "합계 (swgeProcZoneInnerSm)") + const originalHeaders: Map = new Map(); + columns.forEach((col) => { + if (col.fieldName && gridView.columnByName) { + const gridCol = gridView.columnByName(col.name); + if (gridCol && gridCol.header) { + const originalText = gridCol.header.text || ''; + originalHeaders.set(col.name, originalText); + const headerWithFieldName = `${originalText} (${col.fieldName})`; + gridCol.header.text = headerWithFieldName; + } + } + }); + + // exportGrid 호출 전에 columnLayout 정규화 (col 속성 추가) + const normalizeLayoutForExport = (layout: ColumnLayoutItem[]): ColumnLayoutItem[] => { + return layout.map(item => { + if (typeof item === 'string') { + return item; + } + if (item && typeof item === 'object') { + // { column: string, footerUserSpans?: ... } 형태인 경우 + if ('column' in item && typeof item.column === 'string') { + const colItem = item as { column: string; footerUserSpans?: unknown[] }; + // col 속성 추가 (RealGrid가 exportGrid에서 필요로 함) + return { + ...colItem, + col: gridView.columnByName?.(colItem.column) || null, + } as ColumnLayoutItem; + } + // { name: string, items: ... } 형태인 경우 + if ('items' in item && Array.isArray(item.items)) { + return { + ...item, + items: normalizeLayoutForExport(item.items as ColumnLayoutItem[]), + }; + } + } + return item; + }); + }; + + const originalLayout = columnLayout; + let normalizedLayout: ColumnLayoutItem[] | undefined; + let layoutRestored = false; + + // footerUserSpans가 있는 경우에만 정규화 + const checkFooterUserSpans = (layout: ColumnLayoutItem[]): 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 as ColumnLayoutItem[]); + } + return false; + }); + }; + + if (checkFooterUserSpans(columnLayout)) { + normalizedLayout = normalizeLayoutForExport(columnLayout); + // 정규화된 layout을 임시로 설정 + gridView.setColumnLayout?.(normalizedLayout); + } + + gridView.exportGrid({ + type: 'excel', + target: 'local', + fileName: `${menuName}_${tabLabel}.xlsx`, + footer: 'hidden', + done: () => { + // 헤더 원복 + columns.forEach((col) => { + if (col.fieldName && gridView.columnByName) { + const gridCol = gridView.columnByName(col.name); + if (gridCol && gridCol.header && originalHeaders.has(col.name)) { + gridCol.header.text = originalHeaders.get(col.name) || ''; + } + } + }); + // columnLayout 원복 (footerUserSpans 유지) + if (normalizedLayout && !layoutRestored) { + layoutRestored = true; + setTimeout(() => { + const currentGridRef = gridRefs.current.get(tabKey); + if (currentGridRef?.gridView && originalLayout) { + currentGridRef.gridView.setColumnLayout?.(originalLayout); + } + }, 100); + } + alert('내보내기가 완료되었습니다.'); + }, + }); + }; + + const importExcel = (tabKey: string) => { + const fileInput = fileInputRefs.current.get(tabKey); + fileInput?.click(); + }; + + const handleFileChange = async (e: React.ChangeEvent, tabKey: string) => { + const file = e.target.files?.[0]; + if (!file) return; + + const columnInfoItem = columnInfo.find(info => info.tabKey === tabKey); + if (!columnInfoItem) return; + + const rowStartNum = columnInfoItem.rowStartNum || 1; + + try { + const reader = new FileReader(); + reader.onload = (event) => { + try { + const data = event.target?.result; + if (!data) { + alert('파일을 읽을 수 없습니다.'); + return; + } + + // SheetJS로 엑셀 파일을 JSON으로 변환 + const workbook = XLSX.read(data, { type: 'array', cellDates: true }); + const firstSheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[firstSheetName || '']; + + if (!worksheet || !worksheet['!ref']) { + alert('워크시트를 읽을 수 없습니다.'); + return; + } + + const range = XLSX.utils.decode_range(worksheet['!ref']); + const headerRowCount = rowStartNum || 1; // 기본값 1 + const headerStartRow = Math.max(0, headerRowCount - 1); // 0-based index + + // 각 컬럼별로 헤더 찾기 (rowStartNum 행부터 위로 올라가면서) + const headers: string[] = []; + const headerRowIndexes: number[] = []; + + for (let col = range.s.c; col <= range.e.c; col++) { + let headerValue = ''; + let headerRowIndex = headerStartRow; + + // rowStartNum 행부터 시작해서 위로 올라가면서 헤더 찾기 + for (let rowIndex = headerStartRow; rowIndex >= 0; rowIndex--) { + const cell = worksheet[XLSX.utils.encode_cell({ r: rowIndex, c: col })]; + if (cell && cell.v !== undefined && cell.v !== null && cell.v !== '') { + headerValue = String(cell.v); + headerRowIndex = rowIndex; + break; + } + } + + // 헤더를 찾지 못한 경우 기본값 사용 + if (!headerValue) { + headerValue = `Column${col + 1}`; + headerRowIndex = headerStartRow; + } + + headers.push(headerValue); + headerRowIndexes.push(headerRowIndex); + } + + // 실제 데이터가 시작하는 행 찾기 (헤더가 있는 최대 행 번호 + 1) + const maxHeaderRowIndex = headerRowIndexes.length > 0 ? Math.max(...headerRowIndexes) : headerStartRow; + const dataStartRow = maxHeaderRowIndex + 1; + + // 엑셀 컬럼 인덱스 → 그리드 fieldName 매핑 + const headerToFieldNameMap = new Map(); + 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]) { + const extractedFieldName = fieldNameMatch[1]; + if (columns.find(c => c.fieldName === extractedFieldName)) { + fieldName = extractedFieldName; + } + } + + // 매칭 실패 시 원본 헤더 텍스트 사용 + if (!fieldName) { + console.warn(`엑셀 컬럼 ${colIndex + 1} (헤더: "${headerText}") 매칭 실패 → 헤더 텍스트를 fieldName으로 사용`); + fieldName = headerText; + } + + headerToFieldNameMap.set(headerText, fieldName); + }); + + // 데이터 행 읽기 + const dataRows: Record[] = []; + for (let row = dataStartRow; row <= range.e.r; row++) { + const rowData: Record = {}; + let hasData = false; + + for (let colIndex = 0; colIndex < headers.length; colIndex++) { + const col = range.s.c + colIndex; + const cell = worksheet[XLSX.utils.encode_cell({ r: row, c: col })]; + const headerName = headers[colIndex] || `Column${colIndex + 1}`; + // 헤더 텍스트를 fieldName으로 변환 + const fieldName = headerToFieldNameMap.get(headerName) || headerName; + + let cellValue: string | number = ''; + if (cell && cell.v !== undefined && cell.v !== null) { + // 엑셀 셀 타입이 숫자이거나 값이 숫자인 경우 숫자로 변환 + if (cell.t === 'n' || (typeof cell.v === 'number' && !isNaN(cell.v))) { + cellValue = cell.v as number; + } else { + const stringValue = String(cell.v); + // 문자열이지만 숫자로 변환 가능한 경우 숫자로 변환 + const numericValue = Number(stringValue.replace(/,/g, '')); + if (!isNaN(numericValue) && stringValue.trim() !== '') { + cellValue = numericValue; + } else { + cellValue = stringValue; + } + } + } + + if (cellValue !== '' && cellValue !== null && cellValue !== undefined) { + hasData = true; + } + + rowData[fieldName] = cellValue; + } + + // 데이터가 하나라도 있는 행만 추가 + if (hasData) { + dataRows.push(rowData); + } + } + + setRowDataMap(prev => { + const newMap = new Map(prev); + newMap.set(tabKey, dataRows); + return newMap; + }); + } catch (error) { + console.error('엑셀 파일 파싱 오류:', error); + alert('엑셀 파일 파싱 중 오류가 발생했습니다.'); + } finally { + const fileInput = fileInputRefs.current.get(tabKey); + if (fileInput) { + fileInput.value = ''; + } + } + }; + + reader.onerror = () => { + alert('파일 읽기 중 오류가 발생했습니다.'); + const fileInput = fileInputRefs.current.get(tabKey); + if (fileInput) { + fileInput.value = ''; + } + }; + + reader.readAsArrayBuffer(file); + } catch (error) { + console.error('엑셀 파일 가져오기 오류:', error); + alert('엑셀 파일 가져오기 중 오류가 발생했습니다.'); + const fileInput = fileInputRefs.current.get(tabKey); + if (fileInput) { + fileInput.value = ''; + } + } + }; + + // 초기 데이터 설정 + useEffect(() => { + if (rows.length > 0) { + columnInfo.forEach((info) => { + const tabKey = info.tabKey; + if (!rowDataMap.has(tabKey)) { + setRowDataMap(prev => { + const newMap = new Map(prev); + newMap.set(tabKey, rows); + return newMap; + }); + } + }); + } + }, [rows, columnInfo]); + + // rowDataMap이 변경될 때 그리드에 데이터 반영 (Excel import 등) + useEffect(() => { + columnInfo.forEach((info) => { + const tabKey = info.tabKey; + const gridRef = gridRefs.current.get(tabKey); + const currentData = rowDataMap.get(tabKey); + + if (gridRef?.gridView && gridRef?.dataProvider && currentData && currentData.length > 0) { + setTimeout(() => { + try { + const dp = gridRef.dataProvider as RealGridDataProviderFill | null; + if (dp?.fillJsonData) { + dp.fillJsonData(currentData, { fillMode: "set" }); + } + gridRef.gridView.refresh(); + } catch (error) { + console.error("그리드 데이터 설정 오류:", error); + } + }, 100); + } + }); + }, [rowDataMap, columnInfo]); + + + // 탭 전환 시 그리드 레이아웃·푸터·포맷 재적용 (여러 시점 + ResizeObserver) + const appliedTabRef = useRef(null); + + useEffect(() => { + appliedTabRef.current = null; + const currentInfo = columnInfo.find(info => info.tabKey === activeTab); + const columns = currentInfo?.columns; + const columnLayout = currentInfo?.columnLayout; + if (!columns?.length || !columnLayout) return; + + const tryApply = () => { + if (appliedTabRef.current === activeTab) return; + const gridRef = gridRefs.current.get(activeTab); + if (!gridRef?.gridView || !gridRef?.dataProvider) return; + + const gridView = gridRef.gridView; + const dp = gridRef.dataProvider as { setFields?: (fields: unknown[]) => void; setRows?: (rows: Record[]) => void } | undefined; + const tabRowData = rowDataMap.get(activeTab) || []; + + try { + if (dp?.setFields) dp.setFields(buildFieldsFromColumns(columns)); + + gridView.setDisplayOptions({ fitStyle: GridFitStyle.EVEN }); + gridView.setColumnLayout?.(columnLayout as ColumnLayoutItem[]); + + const hasFooter = columns.some(col => col.footer); + if (hasFooter) { + const hasArrayFooter = columns.some(col => col.footer && Array.isArray(col.footer)); + const hasMultiRowFooter = columns.some(col => { + const f = col.footer; + return f && !Array.isArray(f) && 'multiRow' in f && (f as { multiRow?: boolean }).multiRow === true; + }); + if (hasArrayFooter || hasMultiRowFooter) { + const lengths = columns.filter(col => col.footer && Array.isArray(col.footer)).map(col => (col.footer as unknown[]).length); + const maxLen = lengths.length ? Math.max(...lengths) : 2; + gridView.setFooters?.(Array.from({ length: maxLen }, () => ({ height: 40 }))); + } else { + gridView.footer.height = 40; + } + } + gridView.setOptions?.({ summaryMode: "aggregate" }); + + if (columns.some(col => col.footer && Array.isArray(col.footer))) { + const columnsWithFooter: RealGridColumnInfo[] = columns.map(col => { + const c: 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: 'value' as const } }), + }; + if (col.footer) { + if (Array.isArray(col.footer)) c.footer = col.footer; + else c.footer = { text: col.footer.text, expression: col.footer.expression, numberFormat: col.footer.numberFormat }; + } + return c; + }); + (gridView as GridViewWithSetColumns).setColumns?.(columnsWithFooter); + columns.forEach(col => { + if (!col.footer || !Array.isArray(col.footer)) return; + try { + const column = gridView.columnByName(col.name); + const footerArr = column?.footer as unknown[] | undefined; + if (footerArr && Array.isArray(footerArr)) + col.footer.forEach((item, i) => { + if (item.valueCallback && footerArr[i]) + (footerArr[i] as FooterItemWithCallback).valueCallback = item.valueCallback; + }); + } catch (_) {} + }); + } + columns.forEach(col => { + if (!col.footer || Array.isArray(col.footer)) return; + try { + const column = gridView.columnByName(col.name); + 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 (_) {} + }); + + if (dp?.setRows && tabRowData.length) dp.setRows(tabRowData); + gridView.refresh(); + appliedTabRef.current = activeTab; + } catch (e) { + console.warn('TabDataGrid activeTab layout re-apply:', e); + } + }; + + const delays = [200, 500, 1000, 1500]; + const timers = delays.map(d => setTimeout(tryApply, d)); + + const container = document.querySelector(`[data-tab-key="${activeTab}"]`); + let observer: ResizeObserver | null = null; + if (container && typeof ResizeObserver !== 'undefined') { + observer = new ResizeObserver(() => { + if ((container as HTMLElement).offsetWidth > 0) tryApply(); + }); + observer.observe(container); + } + + return () => { + timers.forEach(t => clearTimeout(t)); + observer?.disconnect(); + }; + }, [activeTab, columnInfo, rowDataMap]); + + if (columnInfo.length === 0) { + return
컬럼 정보가 없습니다.
; + } + + return ( +
+ + + {columnInfo.map((info) => { + const tabKey = info.tabKey; + const tabLabel = info.tabLabel || tabKey; + return ( + + {tabLabel} + + ); + })} + + + {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`) || []; + const rightRowData = rowDataMap.get(info.right.tabKey || `${tabKey}_right`) || []; + + // ColumnInfoList를 ColumnInfo로 변환 + const leftColumnInfo: ColumnInfo = { + columns: info.left.columns || [], + columnLayout: info.left.columnLayout || [] + }; + const rightColumnInfo: ColumnInfo = { + columns: info.right.columns || [], + columnLayout: info.right.columnLayout || [] + }; + + return ( + + { + setRowDataMap(prev => { + const newMap = new Map(prev); + const leftTabKey = info.left?.tabKey || `${tabKey}_left`; + const currentData = newMap.get(leftTabKey) || []; + const newData = typeof updater === 'function' ? updater(currentData) : updater; + newMap.set(leftTabKey, newData); + return newMap; + }); + }} + setRightRowData={(updater) => { + setRowDataMap(prev => { + const newMap = new Map(prev); + const rightTabKey = info.right?.tabKey || `${tabKey}_right`; + const currentData = newMap.get(rightTabKey) || []; + const newData = typeof updater === 'function' ? updater(currentData) : updater; + newMap.set(rightTabKey, newData); + return newMap; + }); + }} + /> + + ); + } + + // 일반 그리드 사용 + if (!info.columns || !info.columnLayout) { + return null; + } + const { columns, columnLayout } = info; + const currentRowData = rowDataMap.get(tabKey) || []; + + return ( + +
+ { + if (el) { + fileInputRefs.current.set(tabKey, el); + } else { + fileInputRefs.current.delete(tabKey); + } + }} + type="file" + accept=".xlsx,.xls,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" + style={{ display: 'none' }} + onChange={(e) => handleFileChange(e, tabKey)} + /> +
+ {isExcelImport && + + } + {isExcelExport && + + } +
+
+ {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 배열 설정 + 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: '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; + }); + + 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, + }); + } + + // 각 탭별 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); + } + }} + autoGenerateField={true} + layout={columnLayout} + rows={currentRowData} + > + {columns.map((column) => ( + + ))} + + ) : null} +
+
+
+ ); + })} +
+
+ ); +}; + +export default TabDataGrid; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/ExcretaTreatmentFacilityInp.tsx b/apps/st/src/components/statistics/input/ExcretaTreatmentFacilityInp.tsx new file mode 100644 index 000000000..94fbb6a3e --- /dev/null +++ b/apps/st/src/components/statistics/input/ExcretaTreatmentFacilityInp.tsx @@ -0,0 +1,80 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { DataGrid } from "@rsone/components"; +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 AddArticleButton from "@/components/button/AddArticleButton"; +import DeleteArticleButton from "@/components/button/DeleteArticleButton"; +import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton"; + +import { ExcretaTreatFactInpColumn } from "@/components/util/column/input/ExcretaTreatFactInpColumn" + +// 하수도 통계 관리 > 07. 분뇨처리시설 +const ExcretaTreatmentFacilityInp = () => { + + const submitExceptionFunc = () => { + console.log('submit exception'); + // 예외제출 로직 + }; + + const getLastYearDataFunc = () => { + console.log('get last year data'); + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + console.log('submit'); + // 제출 로직 + }; + + const saveFunc = () => { + console.log('save'); + // 저장 로직 + }; + + const addArticleFunc = () => { + console.log('save'); + // 항목 추가 로직 + }; + + const deleteArticleFunc = () => { + console.log('save'); + // 항목 제외 로직 + }; + + const [rowData, setRowData] = useState[]>([]); + const [isNotApplicable, setIsNotApplicable] = useState(false); + + return ( + <> + +
+
+ + + + +
+
+
+
+ + + +
+
+ + + ); +}; + +export default ExcretaTreatmentFacilityInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/PrivateSewageFacilityInp.tsx b/apps/st/src/components/statistics/input/PrivateSewageFacilityInp.tsx new file mode 100644 index 000000000..0dabb52c8 --- /dev/null +++ b/apps/st/src/components/statistics/input/PrivateSewageFacilityInp.tsx @@ -0,0 +1,62 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from "@rsone/components"; +import SubmitButton from "@/components/button/SumitButton"; +import SaveButton from "@/components/button/SaveButton"; +import SubmitExceptionButton from "@/components/button/SubmitExceptionButton"; +import LastYearDataButton from "@/components/button/LastYearDataButton"; + +import { SewageTreatFactStatusInpColumn } from "@/components/util/column/input/privateSewageFacility/SewageTreatFactStatusInpColumn" +import { SepticTankStatusInpColumn } from "@/components/util/column/input/privateSewageFacility/SepticTankStatusInpColumn" +import { PrivateSewageDesigStatusInpColumn } from "@/components/util/column/input/privateSewageFacility/PrivateSewageDesigStatusInpColumn" + +// 하수도 통계 관리 > 08. 개인하수처리시설 +const PrivateSewageFacilityInp = () => { + + // tab list + const PrivateSewageFacilityInpTabList = [ + SewageTreatFactStatusInpColumn, + SepticTankStatusInpColumn, + PrivateSewageDesigStatusInpColumn + ]; + + const submitExceptionFunc = () => { + // 예외 제출 로직 + }; + + const lastYearDataFunc = () => { + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + // 제출 로직 + }; + + const saveFunc = () => { + // 저장 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default PrivateSewageFacilityInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/PublicSewageFacilityInp.tsx b/apps/st/src/components/statistics/input/PublicSewageFacilityInp.tsx new file mode 100644 index 000000000..0a8e1d277 --- /dev/null +++ b/apps/st/src/components/statistics/input/PublicSewageFacilityInp.tsx @@ -0,0 +1,73 @@ +import { useState } from 'react'; + +import SearchForm from '@/components/module/SearchForm'; +import { DataGrid } from '@rsone/components'; +import SubmitButton from '@/components/button/SumitButton'; +import SaveButton from '@/components/button/SaveButton'; +import SubmitExceptionButton from '@/components/button/SubmitExceptionButton'; +import OperateDataButton from '@/components/button/OperateDataButton'; +import UpdateOperateDataButton from "@/components/button/UpdateOperateDataButton" +import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton"; + +import { PublicSewageFactInpColumn } from '@/components/util/column/input/PublicSewageFactInpColumn'; + +// 하수도 통계 관리 > 06. 공공하수처리시설 +const PublicSewageFacilityInp = () => { + + const SubmitExceptionFunc = () => { + console.log('submitException'); + // 예외제출 로직 + }; + + const submitFunc = () => { + console.log('submit'); + // 제출 로직 + }; + + const saveFunc = () => { + console.log('save'); + // 저장 로직 + }; + + const getOperateDataFunc = () => { + console.log('get operate data'); + // 운영 데이터 가져오기 + }; + + const updateOperateDataButtonFunc = () => { + console.log('updatedOperateData'); + // 운영 데이터 업데이트 로직 + }; + + const [rowData, setRowData] = useState[]>([]); + const [isNotApplicable, setIsNotApplicable] = useState(false); + + return ( + <> + +
+
+ + + +
+
+
+
+ + + +
+
+ + + ); +}; + +export default PublicSewageFacilityInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/PumpingStationInp.tsx b/apps/st/src/components/statistics/input/PumpingStationInp.tsx new file mode 100644 index 000000000..2261a8eac --- /dev/null +++ b/apps/st/src/components/statistics/input/PumpingStationInp.tsx @@ -0,0 +1,80 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { DataGrid } from '@rsone/components'; +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 AddArticleButton from "@/components/button/AddArticleButton"; +import DeleteArticleButton from "@/components/button/DeleteArticleButton"; +import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton"; + +import { PumpingStationInpColumn } from "@/components/util/column/input/PumpingStationInpColumn" + +// 하수도 통계 관리 > 05. 펌프장 +const PumpingStationInp = () => { + + const SubmitExceptionFunc = () => { + console.log('submit exception'); + // 예외 제출 로직 + }; + + const getLastYearDataFunc = () => { + console.log('get last year data'); + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + console.log('submit'); + // 제출 로직 + }; + + const saveFunc = () => { + console.log('save'); + // 저장 로직 + }; + + const addArticleFunc = () => { + console.log('save'); + // 항목 추가 로직 + }; + + const deleteArticleFunc = () => { + console.log('save'); + // 항목 제외 로직 + }; + + const [rowData, setRowData] = useState[]>([]); + const [isNotApplicable, setIsNotApplicable] = useState(false); + + return ( + <> + +
+
+ + + + +
+
+
+
+ + + +
+
+ + + ); +}; + +export default PumpingStationInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/SewageExcretaRelatedInp.tsx b/apps/st/src/components/statistics/input/SewageExcretaRelatedInp.tsx new file mode 100644 index 000000000..726d5718a --- /dev/null +++ b/apps/st/src/components/statistics/input/SewageExcretaRelatedInp.tsx @@ -0,0 +1,81 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from "@rsone/components"; +import SubmitButton from "@/components/button/SumitButton"; +import SaveButton from "@/components/button/SaveButton"; +import SubmitExceptionButton from "@/components/button/SubmitExceptionButton"; +import LastYearDataButton from "@/components/button/LastYearDataButton"; +import AddArticleButton from "@/components/button/AddArticleButton"; +import DeleteArticleButton from "@/components/button/DeleteArticleButton"; + +import { PublicInstitutionSewerIndustryInpColumn } from "@/components/util/column/input/sewageExcretaRelated/PublicInstitutionSewerIndustryInpColumn" +import { PublicInstitutionExcretaIndustryInpColumn } from "@/components/util/column/input/sewageExcretaRelated/PublicInstitutionExcretaIndustryInpColumn" +import { ExcretaRelatedIndustryInpColumn } from "@/components/util/column/input/sewageExcretaRelated/ExcretaRelatedIndustryInpColumn"; +import { PrivateSewageTreatRelatedIndustryInpColumn } from "@/components/util/column/input/sewageExcretaRelated/PrivateSewageTreatRelatedIndustryInpColumn"; + +// 하수도 통계 관리 > 12. 하수 및 분뇨관련산업 +const SewageExcretaRelatedInp = () => { + + // tab list + const SewageExcretaRelatedInpTabList = [ + PublicInstitutionSewerIndustryInpColumn, + PublicInstitutionExcretaIndustryInpColumn, + ExcretaRelatedIndustryInpColumn, + PrivateSewageTreatRelatedIndustryInpColumn + ]; + + const submitExceptionFunc = () => { + // 예외 제출 로직 + }; + + const lastYearDataFunc = () => { + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + // 제출 로직 + }; + + const saveFunc = () => { + // 저장 로직 + }; + + const addArticleFunc = () => { + // 항목 추가 로직 + }; + + const deleteArticleFunc = () => { + console.log('save'); + // 항목 제외 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + return ( + <> + +
+
+ + + + +
+
+
+
+ + +
+
+ + + ); +}; + +export default SewageExcretaRelatedInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/SewageExcretaSlurgeInp.tsx b/apps/st/src/components/statistics/input/SewageExcretaSlurgeInp.tsx new file mode 100644 index 000000000..a4ab5c947 --- /dev/null +++ b/apps/st/src/components/statistics/input/SewageExcretaSlurgeInp.tsx @@ -0,0 +1,84 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from "@rsone/components"; +import SubmitButton from "@/components/button/SumitButton"; +import SaveButton from "@/components/button/SaveButton"; +import SubmitExceptionButton from "@/components/button/SubmitExceptionButton"; +import LastYearDataButton from "@/components/button/LastYearDataButton"; +import AddArticleButton from "@/components/button/AddArticleButton"; +import DeleteArticleButton from "@/components/button/DeleteArticleButton"; +import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton"; + +import { SlurgeProcessingFacStatusInpColumn } from "@/components/util/column/input/sewageExcretaSlurge/SlurgeProcessingFacStatusInpColumn"; +import { DigestorOperatingStatusInpColumn } from "@/components/util/column/input/sewageExcretaSlurge/DigestorOperatingStatusInpColumn"; +import { SewageSlurgeProcessingFacStatusInpColumn } from "@/components/util/column/input/sewageExcretaSlurge/SewageSlurgeProcessingFacStatusInpColumn"; +import { ExcretaSlurgeProcessingStatusInpColumn } from "@/components/util/column/input/sewageExcretaSlurge/ExcretaSlurgeProcessingStatusInpColumn"; + + +// 하수도 통계 관리 > 11. 하수 및 분뇨찌꺼기(슬러지)처리 +const SewageExcretaSlurgeInp = () => { + + // tab list + const SewageExcretaSlurgeInpTabList = [ + SlurgeProcessingFacStatusInpColumn, + DigestorOperatingStatusInpColumn, + SewageSlurgeProcessingFacStatusInpColumn, + ExcretaSlurgeProcessingStatusInpColumn + ]; + + const submitExceptionFunc = () => { + // 예외 제출 로직 + }; + + const lastYearDataFunc = () => { + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + // 제출 로직 + }; + + const saveFunc = () => { + // 저장 로직 + }; + + const addArticleFunc = () => { + // 항목 추가 로직 + }; + + const deleteArticleFunc = () => { + // 항목 제외 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const [isNotApplicable, setIsNotApplicable] = useState(false); + + return ( + <> + +
+
+ + + + +
+
+
+
+ + + +
+
+ + + ); +}; + +export default SewageExcretaSlurgeInp; diff --git a/apps/st/src/components/statistics/input/SewagePipeInp.tsx b/apps/st/src/components/statistics/input/SewagePipeInp.tsx new file mode 100644 index 000000000..4eac16126 --- /dev/null +++ b/apps/st/src/components/statistics/input/SewagePipeInp.tsx @@ -0,0 +1,72 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from '@rsone/components'; +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"; + +// 하수도 통계 관리 > 02. 하수관로 +const SewagePipeInp = () => { + + // tab List + const SewagePipeInpTapList = [ + RegionalFactStatusInpColumn, + FactInstallStatusInpColumn, + PipeTypeStatusInpColumn, + PipeDiameterStatusInpColumn, + ManholeStatusInpColumn, + ConnectionStatusInpColumn, + ]; + + const SubmitExceptionFunc = () => { + console.log('submit exception'); + // 예외 제출 로직 + }; + + const getLastYearDataFunc = () => { + console.log('get last year data'); + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + console.log('submit'); + // 제출 로직 + }; + + const saveFunc = () => { + console.log('save'); + // 저장 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default SewagePipeInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/SewagePipeMaintainInp.tsx b/apps/st/src/components/statistics/input/SewagePipeMaintainInp.tsx new file mode 100644 index 000000000..c34d35498 --- /dev/null +++ b/apps/st/src/components/statistics/input/SewagePipeMaintainInp.tsx @@ -0,0 +1,64 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from '@rsone/components'; +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 { RepairStatusInpColumn } from "@/components/util/column/input/sewagePipeMaintain/RepairStatusInpColumn"; +import { PipeDredgingStatusInpColumn } from "@/components/util/column/input/sewagePipeMaintain/PipeDredgingStatusInpColumn"; + +// 하수도 통계 관리 > 03. 하수관로 유지관리 +const SewagePipeMaintainInp = () => { + + // tab List + const SewagePipeMaintainInpTabList = [ + RepairStatusInpColumn, + PipeDredgingStatusInpColumn + ]; + + const SubmitExceptionFunc = () => { + console.log('submit exception'); + // 예외 제출 로직 + }; + + const getLastYearDataFunc = () => { + console.log('get last year data'); + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + console.log('submit'); + // 제출 로직 + }; + + const saveFunc = () => { + console.log('save'); + // 저장 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default SewagePipeMaintainInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/SewageReservoirPumpInp.tsx b/apps/st/src/components/statistics/input/SewageReservoirPumpInp.tsx new file mode 100644 index 000000000..1ea0892c5 --- /dev/null +++ b/apps/st/src/components/statistics/input/SewageReservoirPumpInp.tsx @@ -0,0 +1,85 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from '@rsone/components'; +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 AddArticleButton from "@/components/button/AddArticleButton"; +import DeleteArticleButton from "@/components/button/DeleteArticleButton"; +import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton"; + +import { SewageReservoirInpColumn } from "@/components/util/column/input/sewageReservoirPump/SewageReservoirInpColumn"; +import { RainfallPumpStationInpColumn } from "@/components/util/column/input/sewageReservoirPump/RainfallPumpStationInpColumn"; + +// 하수도 통계 관리 > 04. 하수저류 시설 및 빗물 펌프장 +const SewageReservoirPumpInp = () => { + + // tab List + const SewageReservoirPumpInpTabList = [ + SewageReservoirInpColumn, + RainfallPumpStationInpColumn + ]; + + const submitExceptionFunc = () => { + console.log('submit exception'); + // 예외 제출 로직 + }; + + const getLastYearDataFunc = () => { + console.log('get last year data'); + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + console.log('submit'); + // 제출 로직 + }; + + const saveFunc = () => { + console.log('save'); + // 저장 로직 + }; + + const addArticleFunc = () => { + console.log('save'); + // 항목 추가 로직 + }; + + const deleteArticleFunc = () => { + console.log('save'); + // 항목 제외 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const [isNotApplicable, setIsNotApplicable] = useState(false); + + return ( + <> + +
+
+ + + + +
+
+
+
+ + + +
+
+ + + ); +}; + +export default SewageReservoirPumpInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/SewerageFinanceInp.tsx b/apps/st/src/components/statistics/input/SewerageFinanceInp.tsx new file mode 100644 index 000000000..c1c2177de --- /dev/null +++ b/apps/st/src/components/statistics/input/SewerageFinanceInp.tsx @@ -0,0 +1,64 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from '@rsone/components'; +import SubmitButton from "@/components/button/SumitButton"; +import SaveButton from "@/components/button/SaveButton"; +import SubmitExceptionButton from "@/components/button/SubmitExceptionButton"; +import LastYearDataButton from "@/components/button/LastYearDataButton"; + +import { SewerageFinanceSettleInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageFinanceSettleInpColumn" +import { SewerageChargeInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageChargeInpColumn" +import { SewerageUsageFeeInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageUsageFeeInpColumn" +import { CauserBurdenInpColumn } from "@/components/util/column/input/sewerageFinance/CauserBurdenInpColumn" + +// 하수도 통계 관리 > 09. 하수도재정 +const SewerageFinanceInp = () => { + + // tab list + const SewerageFinanceInpTabList = [ + SewerageFinanceSettleInpColumn, + SewerageChargeInpColumn, + SewerageUsageFeeInpColumn, + CauserBurdenInpColumn + ]; + + const submitExceptionFunc = () => { + // 예외 제출 로직 + }; + + const lastYearDataFunc = () => { + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + // 제출 로직 + }; + + const saveFunc = () => { + // 저장 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default SewerageFinanceInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx b/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx new file mode 100644 index 000000000..2c1b15f5e --- /dev/null +++ b/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx @@ -0,0 +1,302 @@ +import { useState, useMemo, useRef } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +// import { DataGrid } from "@rsone/components"; +import DataGrid from "@/components/module/DataGrid"; +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 { LoadingWithAnimation } from "@common/components"; +import { ConfirmDialog } from "@/shared/ui/confirm-dialog"; + +import { useAlertStore } from "@/shared/lib"; +import { statisticsInputAPi } from "@/entities/statistics/api/statistics-input-service"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import type { + SewerageSupplyRateItem, + SewerageSupplyRateRequestParams, + SewerageSupplyRateSaveItem, + SewerageSupplyRateVerificationResult, + SewerageSupplyRateSaveRequest +} from "@/entities/statistics/model/statistics-input-interface"; +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"; + +function getSewerageSupplyRateParams( + values: SearchFormValues, + overrides?: { yr?: string; demoYr?: string; mode?: string } +): SewerageSupplyRateRequestParams { + return { + sido: values.sido, + gugun: values.gugun === 'ALL' ? '' : values.gugun, + bsnmCd: values.bsnmCd, + yr: overrides?.yr ?? values.year, + ...(overrides?.mode && { mode: overrides.mode }), + }; +} + +// 하수도 통계 관리 > 01. 하수도 보급률 +const SeweragePenetrationRateInp = () => { + const { setMessage: alert } = useAlertStore((state) => state); + const [rowData, setRowData] = useState[]>([]); + const [isLoading, setIsLoading] = useState(false); + const [searchValues, setSearchValues] = useState(null); + const [isEnterable, setIsEnterable] = useState(true); + const [lastSearchedYear, setLastSearchedYear] = useState(null); + const { confirm } = useConfirm(); + + const [footerFromApi, setFooterFromApi] = useState<{ totalPopl?: number; poplSm?: number; frgnrPoplSm?: number } | null>(null); + const getGridDataRef = useRef<(() => Record[]) | null>(null); + + const footerFieldNames = ['totalPopl', 'poplSm', 'frgnrPoplSm'] as const; + const footerWithApiDefault = (fieldName: (typeof footerFieldNames)[number], numberFormat: string) => ({ + expression: 'sum' as const, + numberFormat, + valueCallback: (grid: Parameters[0], column: Parameters[1]) => + (footerFromApi && footerFromApi[fieldName] != null ? footerFromApi[fieldName] : null) ?? getFooterSummary(grid, column), + }); + + // 최상위 관리자일땐 모든 상황에서 edit 가능하게 수정 필요. + const columnInfo = useMemo(() => { + const { columns, columnLayout } = SeweragePenetrationRateInpColumn; + const base = isEnterable ? columns : columns.map((col) => ({ ...col, editable: false as const })); + return { + columnLayout, + columns: base.map((col) => { + if (col.fieldName === 'totalPopl') return { ...col, footer: footerWithApiDefault('totalPopl', '#,##0') }; + if (col.fieldName === 'poplSm') return { ...col, footer: footerWithApiDefault('poplSm', '#,##0') }; + if (col.fieldName === 'frgnrPoplSm') return { ...col, footer: footerWithApiDefault('frgnrPoplSm', '#,##0') }; + return col; + }), + }; + }, [isEnterable, footerFromApi]); + + const handleReset = () => { + setRowData([]); + setLastSearchedYear(null); + setFooterFromApi(null); + }; + + const fetchSewerageSupplyRate = async (params: SewerageSupplyRateRequestParams) => { + try { + setIsLoading(true); + const response = await statisticsInputAPi.getSewerageSupplyRateList(params); + if (response.status === 'success' && response.data) { + const commonInfo = response.data.commonInfo; + const convertedData: SewerageSupplyRateItem[] = response.data.sewerageSupplyRateList.map((d) => ({ + ...d, + sido: commonInfo.sido, + speclCntrplnAr: d.speclCntrplnAr === '' || d.speclCntrplnAr === null ? '해당없음' : d.speclCntrplnAr, + piplSupprt: commonInfo.piplSupprt, + })); + setRowData( + convertedData.map((d) => { + const row = toGridRows([d])[0] as Record & { verificationResult?: SewerageSupplyRateVerificationResult }; + if (d.verificationResult) row.verificationResult = d.verificationResult; + return row; + }) + ); + + setFooterFromApi( + commonInfo + ? { + totalPopl: commonInfo.bsnmTotalPopl, + poplSm: commonInfo.bsnmPoplSm, + frgnrPoplSm: commonInfo.bsnmFrgnrPoplSm, + } + : null + ); + } else { + alert(response.message); + } + } catch { + alert('데이터 조회 중 오류가 발생했습니다.'); + setRowData([]); + setFooterFromApi(null); + } finally { + setIsLoading(false); + } + }; + + const handleSearch = async (values: SearchFormValues) => { + if (values.sido === '' || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + try { + const response = await statisticsInputAPi.checkInputPeriod(values.year || ''); + + if (response.status === 'success') { + setIsEnterable(response.data); + setLastSearchedYear(values.year || null); + + await fetchSewerageSupplyRate(getSewerageSupplyRateParams(values)); + } else { + alert(response.message); + } + } catch { + alert('데이터 조회 중 오류가 발생했습니다.'); + } + }; + + const SubmitExceptionFunc = () => { + // 예외 제출 로직 + }; + + const getLastYearDataFunc = async (values: SearchFormValues) => { + if (values.sido === '' || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + // 실제 조회된 연도가 없으면 실행 불가 + if (!lastSearchedYear) { + alert('먼저 데이터를 조회해주세요.'); + return; + } + + await fetchSewerageSupplyRate(getSewerageSupplyRateParams(values, { mode: 'PRE' })); + }; + + const submitFunc = () => { + // 제출 로직 + }; + + const saveFunc = async () => { + try { + if (await confirm('저장 하시겠습니까?')) { + setIsLoading(true); + + const userInfo = await getUserInfo(); + const currentData = getGridDataRef.current?.(); + + if (!currentData || currentData.length === 0) { + alert('저장할 데이터가 없습니다.'); + return; + } + + // 컬럼 정의에서 dataFormat 추출 (소수점 자리수 맞추기 위해) + const columnFormatMap = new Map(); + SeweragePenetrationRateInpColumn.columns.forEach((col) => { + if (col.fieldName && col.dataFormat) { + columnFormatMap.set(col.fieldName, col.dataFormat); + } + }); + + // 숫자 포맷팅 함수 (dataFormat에 따라 소수점 자리수 맞춤) + const formatNumber = (value: string | number | null | undefined, fieldName: string): number => { + if (value === null || value === undefined || value === '') return 0; + const num = typeof value === 'string' ? parseFloat(value.replace(/,/g, '')) : value; + if (isNaN(num)) return 0; + + const format = columnFormatMap.get(fieldName); + if (!format) return num; + + // #,##0.000 → 소수점 3자리, #,##0.0 → 소수점 1자리, #,##0 → 정수 + const decimalPlaces = format.match(/\.(\d+)/)?.[1]?.length ?? 0; + return decimalPlaces > 0 ? parseFloat(num.toFixed(decimalPlaces)) : Math.round(num); + }; + + const convertedData: SewerageSupplyRateSaveItem[] = currentData.map((d) => ({ + gugun: (d.gugun as string) || null, + adstCd: d.adstCd as string, + adstDong: d.adstDong as string, + bstrm: d.bstrm as string, + speclCntrplnAr: d.speclCntrplnAr === '해당없음' ? null : (d.speclCntrplnAr as string | null), + pblswrgPrmTrt: formatNumber(d.pblswrgPrmTrt, 'pblswrgPrmTrt'), + pblswrgScdTrt: formatNumber(d.pblswrgScdTrt, 'pblswrgScdTrt'), + pblswrgTertTrt: formatNumber(d.pblswrgTertTrt, 'pblswrgTertTrt'), + wstrPrmTrt: formatNumber(d.wstrPrmTrt, 'wstrPrmTrt'), + wstrScdTrt: formatNumber(d.wstrScdTrt, 'wstrScdTrt'), + wstrTertTrt: formatNumber(d.wstrTertTrt, 'wstrTertTrt'), + notConectPopltn: formatNumber(d.notConectPopltn, 'notConectPopltn'), + swgeProcZoneInnerAr: formatNumber(d.swgeProcZoneInnerAr, 'swgeProcZoneInnerAr'), + townUnprocPopltn: formatNumber(d.townUnprocPopltn, 'townUnprocPopltn'), + townSwttPopltn: formatNumber(d.townSwttPopltn, 'townSwttPopltn'), + townWrrtnPopltn: formatNumber(d.townWrrtnPopltn, 'townWrrtnPopltn'), + swgeProcZoneOuterAr: formatNumber(d.swgeProcZoneOuterAr, 'swgeProcZoneOuterAr'), + rmk: (d.rmk as string) ?? '', + popltnSm: formatNumber(d.popltnSm, 'popltnSm'), + arSm: formatNumber(d.arSm, 'arSm'), + swgeProcZoneInnerSm: formatNumber(d.swgeProcZoneInnerSm, 'swgeProcZoneInnerSm'), + pblswrgPopltnSm: formatNumber(d.pblswrgPopltnSm, 'pblswrgPopltnSm'), + wstrPopltnSm: formatNumber(d.wstrPopltnSm, 'wstrPopltnSm'), + swgeProcZoneOuterSm: formatNumber(d.swgeProcZoneOuterSm, 'swgeProcZoneOuterSm'), + pblswrgPopltnSuprt: formatNumber(d.pblswrgPopltnSuprt, 'pblswrgPopltnSuprt'), + adtrtPopltnSuprt: formatNumber(d.adtrtPopltnSuprt, 'adtrtPopltnSuprt'), + swrgInstlrt: formatNumber(d.swrgInstlrt, 'swrgInstlrt'), + })); + + const requestData: SewerageSupplyRateSaveRequest = { + bsnmCd: searchValues?.bsnmCd ?? '', + sido: searchValues?.sido ?? '', + yr: searchValues?.year ?? '', + userId: userInfo.userName, + saveList: convertedData, + } + + const response = await statisticsInputAPi.saveSewerageSupplyRate(requestData); + console.log(convertedData) + console.log(response); + } else { + // 저장 취소 + } + } catch { + alert('데이터 저장 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } + }; + + return ( + <> +
+ + {rowData.length > 0 && +
+
+ {isEnterable && } + {isEnterable && getLastYearDataFunc(searchValues ?? {})} />} + {isEnterable && } + { + // 최고 관리자일땐 저장 가능하게 + + } +
+
+ } + {isLoading &&
+
+ +
+
} + 0) && isEnterable} + rowStartNum={3} + fixedColumns={1} + rowData={rowData} + setRowData={setRowData} + getGridDataRef={getGridDataRef} + cellStyleCallback={({ row, fieldName }) => { + const verification = (row as any).verificationResult as SewerageSupplyRateVerificationResult | undefined; + if (!verification) return; + const errors = verification[fieldName]; + if (Array.isArray(errors) && errors.length > 0) { + return 'rg-cell-verify-error'; + } + }} + /> +
+ + + ); +}; + +export default SeweragePenetrationRateInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/SewerageServiceLevelInp.tsx b/apps/st/src/components/statistics/input/SewerageServiceLevelInp.tsx new file mode 100644 index 000000000..7ce370bbb --- /dev/null +++ b/apps/st/src/components/statistics/input/SewerageServiceLevelInp.tsx @@ -0,0 +1,67 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from '@rsone/components'; +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 NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton"; + +import { ComplaintInpColumn } from "@/components/util/column/input/sewerageServiceLevel/ComplaintInpColumn"; +import { ResidentFriendlyFactInpColumn } from "@/components/util/column/input/sewerageServiceLevel/ResidentFriendlyFactInpColumn"; + +// 하수도 통계 관리 > 13. 하수도 서비스 수준 +const SewerageServiceLevelInp = () => { + + // tab List + const SewerageServiceLevelInpTabList = [ + ComplaintInpColumn, + ResidentFriendlyFactInpColumn + ]; + + const submitExceptionFunc = () => { + // 예외 제출 로직 + }; + + const getLastYearDataFunc = () => { + // 지난연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + // 제출 로직 + }; + + const saveFunc = () => { + // 저장 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const [isNotApplicable, setIsNotApplicable] = useState(false); + + return ( + <> + +
+
+ + + + +
+
+
+
+ +
+
+ + + ); +}; + +export default SewerageServiceLevelInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/StatsInputStatusInp.tsx b/apps/st/src/components/statistics/input/StatsInputStatusInp.tsx new file mode 100644 index 000000000..46f8620c2 --- /dev/null +++ b/apps/st/src/components/statistics/input/StatsInputStatusInp.tsx @@ -0,0 +1,44 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { DataGrid } from "@rsone/components"; +import ApproveButton from "@/components/button/ApproveButton"; +import RejectButton from "@/components/button/RejectButton"; + +import { StatsInputStatusInpColumn } from "@/components/util/column/input/StatsInputStatusInpColumn"; + +// 하수도 통계 관리 > 00. 통계 입력 현황 +const StatsInputStatusInp = () => { + + const rejectFunc = () => { + // 보완 요청 로직 + }; + + const approveFunc = () => { + // 승인 요청 로직 + }; + + const [rowData, setRowData] = useState[]>([]); + + return ( + <> + +
+
+ + +
+
+ + + ); +}; + +export default StatsInputStatusInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/input/WaterReuseInp.tsx b/apps/st/src/components/statistics/input/WaterReuseInp.tsx new file mode 100644 index 000000000..2479ef030 --- /dev/null +++ b/apps/st/src/components/statistics/input/WaterReuseInp.tsx @@ -0,0 +1,92 @@ +import { useState } from "react"; + +import SearchForm from "@/components/module/SearchForm"; +import { TabDataGrid } from '@rsone/components'; +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 UpdateOperateDataButton from "@/components/button/UpdateOperateDataButton" +import AddArticleButton from "@/components/button/AddArticleButton"; +import DeleteArticleButton from "@/components/button/DeleteArticleButton"; +import NotApplicableCheckButton from "@/components/button/NotApplicableCheckButton"; + +import { PublicSewageTreatWaterReuseInpColumn } from "@/components/util/column/input/waterReuse/PublicSewageTreatWaterReuseInpColumn"; +import { RecycledWaterStatusInpColumn } from "@/components/util/column/input/waterReuse/RecycledWaterStatusInpColumn"; +import { RainFallUtilFactStatusInpColumn } from "@/components/util/column/input/waterReuse/RainFallUtilFactStatusInpColumn"; +import { TreatWaterReuseDesignConstStatusInpColumn } from "@/components/util/column/input/waterReuse/TreatWaterReuseDesignConstStatusInpColumn"; +import { TreatWaterReuseBusinessApprStatusInpColumn } from "@/components/util/column/input/waterReuse/TreatWaterReuseBusinessApprStatusInpColumn"; + +// 하수도 통계 관리 > 10. 물 재이용 +const WaterReuseInp = () => { + + // tab list + const WaterReuseInpTabList = [ + PublicSewageTreatWaterReuseInpColumn, + RecycledWaterStatusInpColumn, + RainFallUtilFactStatusInpColumn, + TreatWaterReuseDesignConstStatusInpColumn, + TreatWaterReuseBusinessApprStatusInpColumn + ]; + const SubmitExceptionFunc = () => { + // 예외 제출 로직 + }; + + const getLastYearDataFunc = () => { + // 전연도 데이터 가져오기 로직 + }; + + const submitFunc = () => { + // 제출 로직 + }; + + const saveFunc = () => { + // 저장 로직 + }; + + const updateOperateDataButtonFunc = () => { + // 운영 데이터 업데이트 로직 - tab1. 공공하수처리수 재이용 + }; + + const addArticleFunc = () => { + console.log('save'); + // 항목 추가 로직 + }; + + const deleteArticleFunc = () => { + console.log('save'); + // 항목 제외 로직 + }; + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const [isNotApplicable, setIsNotApplicable] = useState(false); + + return ( + <> + +
+
+ + + + +
+
+
+
+ + + + +
+
+ + + ); +}; + +export default WaterReuseInp; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/ExcretaTreatmentFacilityMng.tsx b/apps/st/src/components/statistics/management/ExcretaTreatmentFacilityMng.tsx deleted file mode 100644 index 4b4988240..000000000 --- a/apps/st/src/components/statistics/management/ExcretaTreatmentFacilityMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const ExcretaTreatmentFacilityMng = () => { - return ( - <> - - - ); -}; - -export default ExcretaTreatmentFacilityMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/NotEnteredStatus.tsx b/apps/st/src/components/statistics/management/NotEnteredStatus.tsx new file mode 100644 index 000000000..723c29b18 --- /dev/null +++ b/apps/st/src/components/statistics/management/NotEnteredStatus.tsx @@ -0,0 +1,41 @@ +import { useState } from "react"; + +import { DataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import type { ColumnConfig } from "@/components/type/DataGrid.type"; + +const NotEnteredStatus = () => { + const [rowData, setRowData] = useState[]>([]); + + const columns: ColumnConfig[] = [ + { name: 'sido', fieldName: '시도', header: { text: '시도' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: '1', fieldName: '1', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: '2-1', fieldName: '2-1', header: { text: '2-1' }, mergeCells: true, editable: false, sortdisable: true }, + { name: '2-2', fieldName: '2-2', header: { text: '2-2' }, mergeCells: true, editable: false, sortdisable: true }, + { name: '2-3', fieldName: '2-3', header: { text: '2-3' }, mergeCells: true, editable: false, sortdisable: true }, + { name: '2-4', fieldName: '2-4', header: { text: '2-4' }, mergeCells: true, editable: false, sortdisable: true }, + { name: '3-1', fieldName: '3-1', header: { text: '3-1' }, mergeCells: true, editable: false, sortdisable: true }, + { name: '3-2', fieldName: '3-2', header: { text: '3-2' }, mergeCells: true, editable: false, sortdisable: true }, + ]; + + const columnLayout = [ + 'sido', + 'sgg', + { + name: 'groupA', + hideChildHeaders: false, + header: { text: '미입력 하수도 통계 세부항목(번호)' }, + items: ['1', '2-1', '2-2', '2-3', '2-4', '3-1', '3-2'], + }, + ]; + + return ( + <> + + + + ); +}; + +export default NotEnteredStatus; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/PrivateSewageFacilityMng.tsx b/apps/st/src/components/statistics/management/PrivateSewageFacilityMng.tsx deleted file mode 100644 index a57011038..000000000 --- a/apps/st/src/components/statistics/management/PrivateSewageFacilityMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const PrivateSewageFacilityMng = () => { - return ( - <> - - - ); -}; - -export default PrivateSewageFacilityMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/PublicSewageFacilityMng.tsx b/apps/st/src/components/statistics/management/PublicSewageFacilityMng.tsx deleted file mode 100644 index 3097a90c0..000000000 --- a/apps/st/src/components/statistics/management/PublicSewageFacilityMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const PublicSewageFacilityMng = () => { - return ( - <> - - - ); -}; - -export default PublicSewageFacilityMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/PumpingStationMng.tsx b/apps/st/src/components/statistics/management/PumpingStationMng.tsx deleted file mode 100644 index 1d8dadd65..000000000 --- a/apps/st/src/components/statistics/management/PumpingStationMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const PumpingStationMng = () => { - return ( - <> - - - ); -}; - -export default PumpingStationMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/SewageExcretaRelatedMng.tsx b/apps/st/src/components/statistics/management/SewageExcretaRelatedMng.tsx deleted file mode 100644 index 4305c6344..000000000 --- a/apps/st/src/components/statistics/management/SewageExcretaRelatedMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const SewageExcretaRelatedMng = () => { - return ( - <> - - - ); -}; - -export default SewageExcretaRelatedMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/SewageExcretaSlurgeMng.tsx b/apps/st/src/components/statistics/management/SewageExcretaSlurgeMng.tsx deleted file mode 100644 index ea3bd241a..000000000 --- a/apps/st/src/components/statistics/management/SewageExcretaSlurgeMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const SewageExcretaSlurgeMng = () => { - return ( - <> - - - ); -}; - -export default SewageExcretaSlurgeMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/SewagePipeMaintainMng.tsx b/apps/st/src/components/statistics/management/SewagePipeMaintainMng.tsx deleted file mode 100644 index 34cf8752a..000000000 --- a/apps/st/src/components/statistics/management/SewagePipeMaintainMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const SewagePipeMaintainMng = () => { - return ( - <> - - - ); -}; - -export default SewagePipeMaintainMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/SewageReservoirPumpMng.tsx b/apps/st/src/components/statistics/management/SewageReservoirPumpMng.tsx deleted file mode 100644 index 16b177121..000000000 --- a/apps/st/src/components/statistics/management/SewageReservoirPumpMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const SewageReservoirPumpMng = () => { - return ( - <> - - - ); -}; - -export default SewageReservoirPumpMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/SewerageFinanceMng.tsx b/apps/st/src/components/statistics/management/SewerageFinanceMng.tsx deleted file mode 100644 index 85e35d715..000000000 --- a/apps/st/src/components/statistics/management/SewerageFinanceMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const SewerageFinanceMng = () => { - return ( - <> - - - ); -}; - -export default SewerageFinanceMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/SewerageServiceLevelMng.tsx b/apps/st/src/components/statistics/management/SewerageServiceLevelMng.tsx deleted file mode 100644 index a9c2adf00..000000000 --- a/apps/st/src/components/statistics/management/SewerageServiceLevelMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "../../module/SearchForm"; - -const SewerageServiceLevelMng = () => { - return ( - <> - - - ); -}; - -export default SewerageServiceLevelMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/StatisticsInputManagement.tsx b/apps/st/src/components/statistics/management/StatisticsInputManagement.tsx new file mode 100644 index 000000000..150620d9b --- /dev/null +++ b/apps/st/src/components/statistics/management/StatisticsInputManagement.tsx @@ -0,0 +1,85 @@ +import { useState } from "react"; + +import { DataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import type { ColumnConfig } from "@/components/type/DataGrid.type"; + +const StatisticsInputManagement = () => { + const [rowData, setRowData] = useState[]>( + [], + ); + + const columns: ColumnConfig[] = [ + { + name: "sido", + fieldName: "시도", + header: { text: "시도" }, + mergeCells: true, + editable: false, + sortdisable: true, + }, + { + name: "sgg", + fieldName: "시군구", + header: { text: "시군구" }, + mergeCells: true, + editable: false, + sortdisable: true, + }, + { + name: "구분", + fieldName: "구분", + header: { text: "구분" }, + editable: false, + sortdisable: true, + }, + { + name: "광역자치단체", + fieldName: "광역자치단체", + header: { text: "광역자치단체" }, + editable: false, + sortdisable: true, + }, + { + name: "공단", + fieldName: "공단", + header: { text: "공단" }, + editable: false, + sortdisable: true, + }, + { + name: "처리내역", + fieldName: "처리내역", + header: { text: "처리내역" }, + editable: false, + sortdisable: true, + }, + ]; + + const columnLayout = [ + "sido", + "sgg", + "구분", + { + name: "groupA", + hideChildHeaders: false, + header: { text: "검토내역" }, + items: ["광역자치단체", "공단", "처리내역"], + }, + ]; + + return ( + <> + + + + ); +}; + +export default StatisticsInputManagement; diff --git a/apps/st/src/components/statistics/management/StatisticsPopulationManagement.tsx b/apps/st/src/components/statistics/management/StatisticsPopulationManagement.tsx new file mode 100644 index 000000000..c0c5e0de1 --- /dev/null +++ b/apps/st/src/components/statistics/management/StatisticsPopulationManagement.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const StatisticsPopulationManagement = () => { + return ( + <> + + + ); +}; + +export default StatisticsPopulationManagement; diff --git a/apps/st/src/components/statistics/management/StatisticsReviewHistory.tsx b/apps/st/src/components/statistics/management/StatisticsReviewHistory.tsx new file mode 100644 index 000000000..96bde4c32 --- /dev/null +++ b/apps/st/src/components/statistics/management/StatisticsReviewHistory.tsx @@ -0,0 +1,39 @@ +import { useState } from "react"; + +import { DataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import type { ColumnConfig } from "@/components/type/DataGrid.type"; + +const StatisticsReviewHistory = () => { + const [rowData, setRowData] = useState[]>([]); + + const columns: ColumnConfig[] = [ + { name: 'sido', fieldName: '시도', header: { text: '시도' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: '구분', fieldName: '구분', header: { text: '구분' }, editable: false, sortdisable: true }, + { name: '광역자치단체', fieldName: '광역자치단체', header: { text: '광역자치단체' }, editable: false, sortdisable: true }, + { name: '공단', fieldName: '공단', header: { text: '공단' }, editable: false, sortdisable: true }, + { name: '처리내역', fieldName: '처리내역', header: { text: '처리내역' }, editable: false, sortdisable: true }, + ]; + + const columnLayout = [ + 'sido', + 'sgg', + '구분', + { + name: 'groupA', + hideChildHeaders: false, + header: { text: '검토내역' }, + items: ['광역자치단체', '공단', '처리내역'], + }, + ]; + + return ( + <> + + + + ); +}; + +export default StatisticsReviewHistory; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/StatsInputSatusMng.tsx b/apps/st/src/components/statistics/management/StatsInputSatusMng.tsx deleted file mode 100644 index 32e134538..000000000 --- a/apps/st/src/components/statistics/management/StatsInputSatusMng.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; -import DataGrid from "@/components/module/DataGrid"; -import ApproveButton from "@/components/button/ApproveButton"; -import RejectButton from "@/components/button/RejectButton"; - -const StatsInputSatusMng = () => { - const columns = [ - { name: 'sido', fieldName: '시도', header: { text: '시도' } }, - { name: 'sgg', fieldName: '구군', header: { text: '구군' } }, - { name: 'menu_nm', fieldName: '구분', header: { text: '구분' } }, - { name: 'locg_status_nm', fieldName: '진행상황', header: { text: '진행상황' } }, - { name: 'locg_status', fieldName: '작성률', header: { text: '작성률' } }, - { name: 'locg_charger', fieldName: '작성자', header: { text: '작성자' } }, - { name: 'locg_cttpc', fieldName: '작성자 연락처', header: { text: '작성자 연락처' } }, - { name: 'locg_dept', fieldName: '작성자 부서', header: { text: '작성자 부서' } }, - { name: 'locg_job', fieldName: '작성자 직제', header: { text: '작성자 직제' } }, - { name: 'locg_cnfirm_nm', fieldName: '승인자', header: { text: '승인자' } }, - { name: 'locg_cnfirm_dept', fieldName: '승인자 부서', header: { text: '승인자 부서' } }, - { name: 'locg_cnfirm_job', fieldName: '승인자 직제', header: { text: '승인자 직제' } }, - { name: 'return_opinion_sm', fieldName: '반려 사유', header: { text: '반려 사유' } }, - ]; - - const columnLayout = [ - 'sido', - 'sgg', - 'menu_nm', - { - name: 'groupA', - hideChildHeaders: false, - header: { text: '하수도사업자' }, - items: columns.filter((c) => ['sido', 'sgg', 'menu_nm'].includes(c.name) === false).map((m) => m.name), - }, - ]; - - const approveFunc = () => { - console.log('appoved'); - }; - - const rejectFunc = () => { - console.log('reject'); - }; - - return ( - <> - -
- - -
- - - ); -}; - -export default StatsInputSatusMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/WaterReuseMng.tsx b/apps/st/src/components/statistics/management/WaterReuseMng.tsx deleted file mode 100644 index b4afc8254..000000000 --- a/apps/st/src/components/statistics/management/WaterReuseMng.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "../../module/SearchForm"; - -const WaterReuseMng = () => { - return ( - <> - - - ); -}; - -export default WaterReuseMng; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/ExcretaTreatmentFacilityRvw.tsx b/apps/st/src/components/statistics/review/ExcretaTreatmentFacilityRvw.tsx new file mode 100644 index 000000000..961f0a79e --- /dev/null +++ b/apps/st/src/components/statistics/review/ExcretaTreatmentFacilityRvw.tsx @@ -0,0 +1,38 @@ +import { useState } from "react"; + +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { ExcretaTreatmentFacilityInfoList } from "@/components/util/column/review/ExcretaTreatmentFacilityRvwColumn"; + +// 하수도 통계 관리 07.분뇨처리 시설 +const ExcretaTreatmentFacilityRvw = () => { + + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => console.log('approveFunc'); + const saveFunc = () => console.log('submit'); + const reviewOpinionFunc = () => console.log('reviewOpinionFunc'); + const returnFunc = () => console.log('returnFunc'); + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default ExcretaTreatmentFacilityRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/PrivateSewageFacilityRvw.tsx b/apps/st/src/components/statistics/review/PrivateSewageFacilityRvw.tsx new file mode 100644 index 000000000..619085736 --- /dev/null +++ b/apps/st/src/components/statistics/review/PrivateSewageFacilityRvw.tsx @@ -0,0 +1,52 @@ +import { useState } from "react"; + +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { PrivateSewageFacilityInfoListRvw } from "@/components/util/column/review/PrivateSewageFacilityColumn"; + +// 하수도 통계 관리 08.개인하수처리시설 +const PrivateSewageFacilityRvw = () => { + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => { + console.log('approveFunc'); + // 승인 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + // 검토의견 작성 + }; + + const returnFunc = () => { + console.log('returnFunc'); + // 반려 + }; + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default PrivateSewageFacilityRvw; diff --git a/apps/st/src/components/statistics/review/PublicSewageFacilityRvw.tsx b/apps/st/src/components/statistics/review/PublicSewageFacilityRvw.tsx new file mode 100644 index 000000000..b929e1e3f --- /dev/null +++ b/apps/st/src/components/statistics/review/PublicSewageFacilityRvw.tsx @@ -0,0 +1,48 @@ +import { useState } from "react"; + +import { DataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { PublicSewageFacilityInfoList } from "@/components/util/column/review/PublicSewageFacilityRvwColumn"; + +// 하수도 통계 관리 06.공공하수처리시설 +const PublicSewageFacilityRvw = () => { + const [rowData, setRowData] = useState[]>([]); + + const approveFunc = () => { + console.log('approveFunc'); + }; + + const saveFunc = () => { + console.log('submit'); + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + }; + + const returnFunc = () => { + console.log('returnFunc'); + }; + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default PublicSewageFacilityRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/PumpingStationRvw.tsx b/apps/st/src/components/statistics/review/PumpingStationRvw.tsx index cb6407e25..8a9df541a 100644 --- a/apps/st/src/components/statistics/review/PumpingStationRvw.tsx +++ b/apps/st/src/components/statistics/review/PumpingStationRvw.tsx @@ -1,12 +1,37 @@ -import SearchForm from "@/components/module/SearchForm"; +import { useState } from "react"; +import { DataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { PumpingStationInfoList } from "@/components/util/column/review/PumpingStationRvwColumn"; + +// 하수도 통계 관리 05.펌프장 const PumpingStationRvw = () => { - + const [rowData, setRowData] = useState[]>([]); + + const approveFunc = () => { console.log('approveFunc'); }; + const saveFunc = () => { console.log('submit'); }; + const reviewOpinionFunc = () => { console.log('reviewOpinionFunc'); }; + const returnFunc = () => { console.log('returnFunc'); }; + return ( <> - + +
+
+ + + + +
+
+ ); -} +}; export default PumpingStationRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/SewageExcretaRelatedRvw.tsx b/apps/st/src/components/statistics/review/SewageExcretaRelatedRvw.tsx new file mode 100644 index 000000000..bd594d334 --- /dev/null +++ b/apps/st/src/components/statistics/review/SewageExcretaRelatedRvw.tsx @@ -0,0 +1,53 @@ +import { useState } from "react"; + +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { SewageExcretaRelatedInfoListRvw } from "@/components/util/column/review/SewageExcretaRelatedRvwColumn"; + +// 하수도 통계 관리 12. 하수 및 분뇨 관련 산업 +const SewageExcretaRelatedRvw = () => { + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => { + console.log('approveFunc'); + // 승인 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + // 검토의견 작성 + }; + + const returnFunc = () => { + console.log('returnFunc'); + // 반려 + }; + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + + +export default SewageExcretaRelatedRvw; diff --git a/apps/st/src/components/statistics/review/SewageExcretaSlurgeRvw.tsx b/apps/st/src/components/statistics/review/SewageExcretaSlurgeRvw.tsx new file mode 100644 index 000000000..d0dbcb383 --- /dev/null +++ b/apps/st/src/components/statistics/review/SewageExcretaSlurgeRvw.tsx @@ -0,0 +1,52 @@ +import { useState } from "react"; + +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { SewageExcretaSludgeInfoListRvw } from "@/components/util/column/review/SewageExcretaSlurgeRvwColumn"; + +// 하수도 통계 관리 11. 하수 및 분뇨 찌꺼기(슬러지) 처리 +const SewageExcretaSlurgeRvw = () => { + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => { + console.log('approveFunc'); + // 승인 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + // 검토의견 작성 + }; + + const returnFunc = () => { + console.log('returnFunc'); + // 반려 + }; + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default SewageExcretaSlurgeRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx index 68e4e9e7d..03549083e 100644 --- a/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeMaintainRvw.tsx @@ -1,11 +1,52 @@ -import SearchForm from "@/components/module/SearchForm"; +import { useState } from "react"; +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { SewagePipeMaintainColumnInfoList } from "@/components/util/column/review/SewagePipeMaintainRvwColumn"; + +// 하수도 통계 관리 03. 하수관로 유지 관리 const SewagePipeMaintainRvw = () => { + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => { + console.log('approveFunc'); + // 승인 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + // 검토의견 작성 + }; + + const returnFunc = () => { + console.log('returnFunc'); + // 반려 + }; + return ( <> - + +
+
+ + + + +
+
+ ); -} +}; export default SewagePipeMaintainRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx index c6fbd817e..34fe00910 100644 --- a/apps/st/src/components/statistics/review/SewagePipeRvw.tsx +++ b/apps/st/src/components/statistics/review/SewagePipeRvw.tsx @@ -1,11 +1,148 @@ +import { useState, useMemo, useRef } from "react"; +import TabDataGrid from "@/components/module/TabDataGrid"; import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; +import { LoadingWithAnimation } from "@common/components"; +import { useAlertStore } from "@/shared/lib"; +import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service"; +import { SewagePipeColumnInfoListRvw } from "@/components/util/column/review/SewagePipeRvwColumn"; +import type { ColumnInfoList, ColumnConfig } from "@/components/type/DataGrid.type"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import { toGridRows } from "@/components/util/grid/gridFunction"; + +// 하수도 통계 검토 02.하수관로 const SewagePipeRvw = () => { + const { setMessage: alert } = useAlertStore((state) => state); + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + const [isLoading, setIsLoading] = useState(false); + const [activeTab, setActiveTab] = useState('a'); + + const searchParamRef = useRef(null); + + const columnInfo = useMemo(() => { + return SewagePipeColumnInfoListRvw.map((tab: ColumnInfoList) => ({ + ...tab, + columns: (tab.columns ?? []).map((col: ColumnConfig) => ({ + ...col, + editable: false as const, + styleName: col.styleName ?? ("rg-cell-readonly" as const), + })), + })); + }, []); + + const handleReset = () => { + setRowDataMap(new Map()); + setActiveTab('a'); + }; + + const handleSearch = async (values: SearchFormValues) => { + if (!values.sido || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + setActiveTab('a'); + + setRowDataMap(new Map()); + + try { + setIsLoading(true); + + const searchParam = { + sido: values.sido, + gugun: values.gugun === 'ALL' ? '' : values.gugun, + bsnmCd: values.bsnmCd, + yr: values.year, + }; + + searchParamRef.current = searchParam; + const response = await statisticsManagementApi.getSewagePipeReviewRegionalList(searchParam); + + if (response?.status === 'success' && response.data) { + const newRowDataMap = new Map[]>(); + newRowDataMap.set('a', toGridRows(response.data as object[])); + setRowDataMap(newRowDataMap); + } else { + alert(response?.message || "데이터가 없습니다."); + } + } catch (error) { + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } + }; + + const handleActiveTabChange = async (tabKey: string) => { + setActiveTab(tabKey); + + const existingAData = rowDataMap.get('a'); + const activeTabData = rowDataMap.get(tabKey); + + const hasAData = Array.isArray(existingAData) && existingAData.length > 0; + const hasActiveTabData = Array.isArray(activeTabData) && activeTabData.length > 0; + + if (hasAData && !hasActiveTabData && searchParamRef.current) { + + try { + setIsLoading(true); + + let response; + + if (tabKey === 'b') { + response = await statisticsManagementApi.getSewagePipeFacilityList(searchParamRef.current); + } + + if (response?.status === 'success' && response.data) { + setRowDataMap(prev => { + const next = new Map(prev); + next.set(tabKey, toGridRows(response.data as object[])); + return next; + }); + } else { + alert(response?.message || "데이터가 없습니다."); + } + } catch { + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } + } + }; + return ( - <> - - +
+ + +
+
+ { }} /> + { }} /> + { }} /> + { }} /> +
+
+ {isLoading && ( +
+
+ +
+
+ )} + + +
); -} +}; export default SewagePipeRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx b/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx index f5ce87d59..a2b5e8de7 100644 --- a/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx +++ b/apps/st/src/components/statistics/review/SewageReservoirPumpRvw.tsx @@ -1,11 +1,52 @@ -import SearchForm from "@/components/module/SearchForm"; +import { useState } from "react"; +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { SewageReservoirPumpInfoListRvw } from "@/components/util/column/review/SewageReservoirPumpRvwColumn"; + +// 하수도 통계 관리 04. 하수저류 시설 및 빗물 펌프장 const SewageReservoirPumpRvw = () => { + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => { + console.log('approveFunc'); + // 승인 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + // 검토의견 작성 + }; + + const returnFunc = () => { + console.log('returnFunc'); + // 반려 + }; + return ( <> - + +
+
+ + + + +
+
+ ); -} +}; -export default SewageReservoirPumpRvw; \ No newline at end of file +export default SewageReservoirPumpRvw; diff --git a/apps/st/src/components/statistics/review/SewerageFinanceRvw.tsx b/apps/st/src/components/statistics/review/SewerageFinanceRvw.tsx new file mode 100644 index 000000000..68a5b6cc0 --- /dev/null +++ b/apps/st/src/components/statistics/review/SewerageFinanceRvw.tsx @@ -0,0 +1,54 @@ +import { useState } from "react"; + +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { SewerageFinanceInfoListRvw } from "@/components/util/column/review/SewerageFinanceRvwColumn"; + + +// 하수도 통계 관리 09. 하수도 재정 +const SewerageFinanceRvw = () => { + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => { + console.log('approveFunc'); + // 승인 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + // 검토의견 작성 + }; + + const returnFunc = () => { + console.log('returnFunc'); + // 반려 + }; + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + + +export default SewerageFinanceRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx b/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx index 17df757f0..8ad001c4c 100644 --- a/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx +++ b/apps/st/src/components/statistics/review/SeweragePenetrationRateRvw.tsx @@ -1,11 +1,115 @@ +import { useState, useMemo } from "react"; +import DataGrid from "@/components/module/DataGrid"; import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; +import { LoadingWithAnimation } from "@common/components"; +import { useAlertStore } from "@/shared/lib"; +import { SeweragePenetrationRateInfoList } from "@/components/util/column/review/SeweragePenetrationRateRvwColumn"; +import type { SewerageSupplyRateReviewItem } from "@/entities/statistics/model/statistics-sewerage-penetration-review-interface"; +import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service"; +import type { SearchFormValues } from "@/components/type/SearchForm.type"; +import { toGridRows } from "@/components/util/grid/gridFunction"; + +// 하수도 통계 검토 01.하수도 보급률 const SeweragePenetrationRateRvw = () => { + const { setMessage: alert } = useAlertStore((state) => state); + const [rowData, setRowData] = useState([]); + const [isLoading, setIsLoading] = useState(false); + + const columnInfo = useMemo(() => { + const { columns, columnLayout, fixedColumns, rowStartNum } = SeweragePenetrationRateInfoList; + return { + columnLayout, + fixedColumns, + rowStartNum, + columns: columns.map((col) => ({ + ...col, + editable: false as const, + styleName: col.styleName ?? ("rg-cell-readonly" as const), + })), + }; + }, []); + + const handleReset = () => { + setRowData([]); + }; + + const handleSearch = async (values: SearchFormValues) => { + if (values.sido === '' || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + try { + setIsLoading(true); + + const response = await statisticsManagementApi.getSewerageSupplyRateReviewList({ + sido: values.sido, + gugun: values.gugun === 'ALL' ? '' : values.gugun, + bsnmCd: values.bsnmCd, + yr: values.year, + }); + + if (response.status === 'success' && response.data) { + const rawList = response.data.sewerageSupplyRateList; + const convertedData: SewerageSupplyRateReviewItem[] = rawList.map((item) => ({ + ...item, + speclCntrplnAr: !item.speclCntrplnAr ? '해당없음' : item.speclCntrplnAr, + })); + + setRowData(toGridRows(convertedData)); + } else { + setRowData([]); + alert(response.message || "데이터가 없습니다."); + } + } catch (error) { + console.error("조회 중 에러 발생:", error); + alert('데이터 조회 중 오류가 발생했습니다.'); + } finally { + setIsLoading(false); + } + }; + + const approveFunc = () => console.log('approveFunc'); + const saveFunc = () => console.log('submit'); + const reviewOpinionFunc = () => console.log('reviewOpinionFunc'); + const returnFunc = () => console.log('returnFunc'); + return ( - <> - - +
+ + +
+
+ + + + +
+
+ + {isLoading && ( +
+
+ +
+
+ )} + + +
); -} +}; export default SeweragePenetrationRateRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/SewerageServiceLevelRvw.tsx b/apps/st/src/components/statistics/review/SewerageServiceLevelRvw.tsx new file mode 100644 index 000000000..e8aa771df --- /dev/null +++ b/apps/st/src/components/statistics/review/SewerageServiceLevelRvw.tsx @@ -0,0 +1,53 @@ +import { useState } from "react"; + +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { SewerageServiceLevelInfoListRvw } from "@/components/util/column/review/SewerageServiceLevelRvwColumn"; + +// 하수도 통계 관리 13. 하수도 서비스 수준 +const SewerageServiceLevelRvw = () => { + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => { + console.log('approveFunc'); + // 승인 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + // 검토의견 작성 + }; + + const returnFunc = () => { + console.log('returnFunc'); + // 반려 + }; + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + + +export default SewerageServiceLevelRvw; diff --git a/apps/st/src/components/statistics/review/StatsInputSatusRvw.tsx b/apps/st/src/components/statistics/review/StatsInputSatusRvw.tsx deleted file mode 100644 index d89ff9290..000000000 --- a/apps/st/src/components/statistics/review/StatsInputSatusRvw.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SearchForm from "@/components/module/SearchForm"; - -const StatsInputSatusRvw = () => { - return ( - <> - - - ); -} - -export default StatsInputSatusRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/StatsInputStatusRvw.tsx b/apps/st/src/components/statistics/review/StatsInputStatusRvw.tsx new file mode 100644 index 000000000..2c11f7abc --- /dev/null +++ b/apps/st/src/components/statistics/review/StatsInputStatusRvw.tsx @@ -0,0 +1,113 @@ +import { useState, useMemo } from "react"; +import { DataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; +import { LoadingWithAnimation } from "@common/components"; + +import { useAlertStore } from "@/shared/lib"; +import { StatsInputStatusInfoList } from "@/components/util/column/review/StatsInputStatusRvwColumn"; +import { statisticsManagementApi } from "@/entities/statistics/api/statistics-management-service"; +import type { StatsInputStatusReviewItem } from "@/entities/statistics/model/statistics-input-review-interface"; +import { toGridRows } from "@/components/util/grid/gridFunction"; + +// 하수도 통계 검토 00. 통계 입력 현황 +const StatsInputStatusRvw = () => { + const { setMessage: alert } = useAlertStore((state) => state); + const [rowData, setRowData] = useState([]); + const [isLoading, setIsLoading] = useState(false); + + const columnInfo = useMemo(() => { + const { columns, columnLayout } = StatsInputStatusInfoList; + return { + columnLayout, + columns: columns.map((col) => ({ + ...col, + editable: false as const, + })), + }; + }, []); + + const handleReset = () => { + setRowData([]); + }; + + const handleSearch = async (values: any) => { + if (!values.sido || values.sido === 'ALL') { + alert('시도를 선택해주세요.'); + return; + } + + try { + setIsLoading(true); + + const response = await statisticsManagementApi.getStatsInputStatusList({ + sido: values.sido, + gugun: values.gugun === 'ALL' ? '' : values.gugun, + yr: values.year || values.yr, + bsnmCd: values.bsnmCd + }); + + if (response.status === 'success' && response.data) { + const rawList = response.data.sewerageSupplyRateList || response.data; + + const convertedData: StatsInputStatusReviewItem[] = rawList.map((item: any) => ({ + ...item, + status: item.status || '미확인', + })); + + setRowData(toGridRows(convertedData)); + } else { + setRowData([]); + alert(response.message || "조회된 데이터가 없습니다."); + } + } catch (error) { + console.error("입력현황 조회 중 에러 발생:", error); + alert('데이터 조회 중 오류가 발생했습니다.'); + setRowData([]); + } finally { + setIsLoading(false); + } + }; + + const approveFunc = () => console.log('approveFunc'); + const saveFunc = () => console.log('submit'); + const reviewOpinionFunc = () => console.log('reviewOpinionFunc'); + const returnFunc = () => console.log('returnFunc'); + + return ( +
+ + +
+
+ + + + +
+
+ + {isLoading && ( +
+
+ +
+
+ )} + + +
+ ); +}; + +export default StatsInputStatusRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/review/WaterReuseRvw.tsx b/apps/st/src/components/statistics/review/WaterReuseRvw.tsx new file mode 100644 index 000000000..e642a4448 --- /dev/null +++ b/apps/st/src/components/statistics/review/WaterReuseRvw.tsx @@ -0,0 +1,51 @@ +import { useState } from "react"; + +import { TabDataGrid } from "@rsone/components"; +import SearchForm from "@/components/module/SearchForm"; +import SaveButton from "@/components/button/SaveButton"; +import ApproveButton from "@/components/button/ApproveButton"; +import ReviewOpinionButton from "@/components/button/ReviewOpinionButton"; +import ReturnButton from "@/components/button/ReturnButton"; + +import { WaterReuseInfoList } from "@/components/util/column/review/WaterReuseRvwColumn"; + +const WaterReuseRvw = () => { + const [rowDataMap, setRowDataMap] = useState[]>>(new Map()); + + const approveFunc = () => { + console.log('approveFunc'); + // 승인 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const reviewOpinionFunc = () => { + console.log('reviewOpinionFunc'); + // 검토의견 작성 + }; + + const returnFunc = () => { + console.log('returnFunc'); + // 반려 + }; + + return ( + <> + +
+
+ + + + +
+
+ + + ); +}; + +export default WaterReuseRvw; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/ExcretaTreatmentFacilityTot.tsx b/apps/st/src/components/statistics/total/ExcretaTreatmentFacilityTot.tsx new file mode 100644 index 000000000..e470b07fa --- /dev/null +++ b/apps/st/src/components/statistics/total/ExcretaTreatmentFacilityTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const ExcretaTreatmentFacilityTot = () => { + return ( + <> + + + ); +}; + +export default ExcretaTreatmentFacilityTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/PrivateSewageFacilityTot.tsx b/apps/st/src/components/statistics/total/PrivateSewageFacilityTot.tsx new file mode 100644 index 000000000..1171f7b2c --- /dev/null +++ b/apps/st/src/components/statistics/total/PrivateSewageFacilityTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const PrivateSewageFacilityTot = () => { + return ( + <> + + + ); +}; + +export default PrivateSewageFacilityTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/PublicSewageFacilityTot.tsx b/apps/st/src/components/statistics/total/PublicSewageFacilityTot.tsx new file mode 100644 index 000000000..6eb3f2991 --- /dev/null +++ b/apps/st/src/components/statistics/total/PublicSewageFacilityTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const PublicSewageFacilityTot = () => { + return ( + <> + + + ); +}; + +export default PublicSewageFacilityTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/SewagePipeMng.tsx b/apps/st/src/components/statistics/total/PumpingStationTot.tsx similarity index 50% rename from apps/st/src/components/statistics/management/SewagePipeMng.tsx rename to apps/st/src/components/statistics/total/PumpingStationTot.tsx index d49184044..fd4cc679d 100644 --- a/apps/st/src/components/statistics/management/SewagePipeMng.tsx +++ b/apps/st/src/components/statistics/total/PumpingStationTot.tsx @@ -1,11 +1,11 @@ import SearchForm from "@/components/module/SearchForm"; -const SewagePipeMng = () => { +const PumpingStationTot = () => { return ( <> - + ); }; -export default SewagePipeMng; \ No newline at end of file +export default PumpingStationTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/SewageExcretaRelatedTot.tsx b/apps/st/src/components/statistics/total/SewageExcretaRelatedTot.tsx new file mode 100644 index 000000000..adcc810ad --- /dev/null +++ b/apps/st/src/components/statistics/total/SewageExcretaRelatedTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const SewageExcretaRelatedTot = () => { + return ( + <> + + + ); +}; + +export default SewageExcretaRelatedTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/SewageExcretaSlurgeTot.tsx b/apps/st/src/components/statistics/total/SewageExcretaSlurgeTot.tsx new file mode 100644 index 000000000..c384f1461 --- /dev/null +++ b/apps/st/src/components/statistics/total/SewageExcretaSlurgeTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const SewageExcretaSlurgeTot = () => { + return ( + <> + + + ); +}; + +export default SewageExcretaSlurgeTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/SewagePipeMaintainTot.tsx b/apps/st/src/components/statistics/total/SewagePipeMaintainTot.tsx new file mode 100644 index 000000000..12e71151d --- /dev/null +++ b/apps/st/src/components/statistics/total/SewagePipeMaintainTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const SewagePipeMaintainTot = () => { + return ( + <> + + + ); +}; + +export default SewagePipeMaintainTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/SewagePipeTot.tsx b/apps/st/src/components/statistics/total/SewagePipeTot.tsx new file mode 100644 index 000000000..232ef7883 --- /dev/null +++ b/apps/st/src/components/statistics/total/SewagePipeTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const SewagePipeTot = () => { + return ( + <> + + + ); +}; + +export default SewagePipeTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/SewageReservoirPumpTot.tsx b/apps/st/src/components/statistics/total/SewageReservoirPumpTot.tsx new file mode 100644 index 000000000..6016a7930 --- /dev/null +++ b/apps/st/src/components/statistics/total/SewageReservoirPumpTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const SewageReservoirPumpTot = () => { + return ( + <> + + + ); +}; + +export default SewageReservoirPumpTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/SewerageFinanceTot.tsx b/apps/st/src/components/statistics/total/SewerageFinanceTot.tsx new file mode 100644 index 000000000..a73eaba2f --- /dev/null +++ b/apps/st/src/components/statistics/total/SewerageFinanceTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "@/components/module/SearchForm"; + +const SewerageFinanceTot = () => { + return ( + <> + + + ); +}; + +export default SewerageFinanceTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/management/SeweragePenetrationRateMng.tsx b/apps/st/src/components/statistics/total/SeweragePenetrationRateTot.tsx similarity index 78% rename from apps/st/src/components/statistics/management/SeweragePenetrationRateMng.tsx rename to apps/st/src/components/statistics/total/SeweragePenetrationRateTot.tsx index ffd10f966..fe266e743 100644 --- a/apps/st/src/components/statistics/management/SeweragePenetrationRateMng.tsx +++ b/apps/st/src/components/statistics/total/SeweragePenetrationRateTot.tsx @@ -1,10 +1,15 @@ import SearchForm from "@/components/module/SearchForm"; import DataGrid from "@/components/module/DataGrid"; +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 { useState } from "react"; -const SeweragePenetrationRate = () => { +const SeweragePenetrationRateTot = () => { const columns = [ { name: 'sido', fieldName: '시도', header: { text: '시도' } }, - { name: 'sgg', fieldName: '구군', header: { text: '구군' } }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' } }, { name: 'rvbsn', fieldName: '수계', header: { text: '수계' } }, { name: 'bstrm', fieldName: '지류', header: { text: '지류' } }, { name: 'mdbsn', fieldName: '세부단위유역', header: { text: '세부단위유역' } }, @@ -98,12 +103,40 @@ const SeweragePenetrationRate = () => { 'rmk', ]; + const submitFunc = () => { + console.log('submit'); + // 제출 로직 + }; + + const saveFunc = () => { + console.log('submit'); + // 저장 로직 + }; + + const getLastYearDataFunc = () => { + console.log('get last year data'); + // 지난연도 데이터 가져오기 로직 + }; + + const SubmitExceptionFunc = () => { + console.log('submit exception'); + // 예외 제출 로직 + }; + + const [rowData, setRowData] = useState[]>([]); + return ( <> - - + +
+ + + + +
+ ); }; -export default SeweragePenetrationRate; \ No newline at end of file +export default SeweragePenetrationRateTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/SewerageServiceLevelTot.tsx b/apps/st/src/components/statistics/total/SewerageServiceLevelTot.tsx new file mode 100644 index 000000000..2f6b5131e --- /dev/null +++ b/apps/st/src/components/statistics/total/SewerageServiceLevelTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "../../module/SearchForm"; + +const SewerageServiceLevelTot = () => { + return ( + <> + + + ); +}; + +export default SewerageServiceLevelTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/total/WaterReuseTot.tsx b/apps/st/src/components/statistics/total/WaterReuseTot.tsx new file mode 100644 index 000000000..567797983 --- /dev/null +++ b/apps/st/src/components/statistics/total/WaterReuseTot.tsx @@ -0,0 +1,11 @@ +import SearchForm from "../../module/SearchForm"; + +const WaterReuseTot = () => { + return ( + <> + + + ); +}; + +export default WaterReuseTot; \ No newline at end of file diff --git a/apps/st/src/components/statistics/verification/HbStatisticsVerification.tsx b/apps/st/src/components/statistics/verification/HbStatisticsVerification.tsx new file mode 100644 index 000000000..81fa83b2a --- /dev/null +++ b/apps/st/src/components/statistics/verification/HbStatisticsVerification.tsx @@ -0,0 +1,483 @@ +"use client"; + +import { useState } from "react"; +// import { DataGrid } from "@rsone/components"; +import DataGrid from "@/components/module/DataGrid"; +import SearchForm from "@/components/module/SearchForm"; +import { + Button, + Input, + Label, + Select, + SelectTrigger, + SelectContent, + SelectItem, + SelectValue, + Checkbox, +} from "@common/components"; +import { verificationHistoryColumnInfo } from "@/entities/statistics/model/verification-history-column"; +import { verificationHistoryMockData } from "@/entities/statistics/model/verification-history-mock"; + +interface VerificationFormValues { + mu: string; + percentile: string; + a: string; + c: string; + verificationYear: string; + checkboxOptions: { + sidoDistribution: boolean; + countyDistribution: boolean; + countyDistributionUserManagement: boolean; + lowerDistribution: boolean; + sidoServiceAvailability: boolean; + individualService: boolean; + legalServiceUsage: boolean; + excessUse: boolean; + lowerOrgStatistics: boolean; + studentStatistics: boolean; + developmentStatistics: boolean; + lowerManagementEnterprise: boolean; + }; +} + +const HbStatisticsVerification = () => { + const [verificationHistoryRowData, setVerificationHistoryRowData] = + useState[]>( + verificationHistoryMockData, + ); + + const [formValues, setFormValues] = useState({ + mu: "0", + percentile: "0", + a: "0", + c: "0", + verificationYear: "2025", + checkboxOptions: { + sidoDistribution: false, + countyDistribution: false, + countyDistributionUserManagement: false, + lowerDistribution: false, + sidoServiceAvailability: false, + individualService: false, + legalServiceUsage: false, + excessUse: false, + lowerOrgStatistics: false, + studentStatistics: false, + developmentStatistics: false, + lowerManagementEnterprise: false, + }, + }); + + const handleCheckboxChange = ( + key: keyof VerificationFormValues["checkboxOptions"], + ) => { + setFormValues((prev) => ({ + ...prev, + checkboxOptions: { + ...prev.checkboxOptions, + [key]: !prev.checkboxOptions[key], + }, + })); + }; + + const handleInputChange = ( + key: keyof Omit, + value: string, + ) => { + setFormValues((prev) => ({ + ...prev, + [key]: value, + })); + }; + + const handleSubmit = () => { + console.log("검증 실행:", formValues); + }; + + const handleReset = () => { + console.log("초기화"); + }; + + return ( +
+
+ {/* 통계 검증 섹션 */} +
+

+ 통계 검증 +

+ +
+ {/* 왼쪽: 검증 변수 */} +
+

+ 검증 변수 +

+ +
+
+ + + handleInputChange( + "mu", + e.target.value, + ) + } + className="flex-1" + /> +
+ +
+ + + handleInputChange( + "percentile", + e.target.value, + ) + } + className="flex-1" + /> +
+ +
+ + + handleInputChange( + "a", + e.target.value, + ) + } + className="flex-1" + /> +
+ +
+ + + handleInputChange( + "c", + e.target.value, + ) + } + className="flex-1" + /> +
+ +
+ + +
+
+
+ + {/* 오른쪽: 검증 대상 */} +
+

+ 검증 대상 +

+ +
+
+
+ + handleCheckboxChange( + "sidoDistribution", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "countyDistribution", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "countyDistributionUserManagement", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "lowerDistribution", + ) + } + /> + +
+
+ +
+
+ + handleCheckboxChange( + "sidoServiceAvailability", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "individualService", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "sidoServiceAvailability", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "individualService", + ) + } + /> + +
+
+ +
+
+ + handleCheckboxChange( + "lowerOrgStatistics", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "studentStatistics", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "lowerOrgStatistics", + ) + } + /> + +
+ +
+ + handleCheckboxChange( + "studentStatistics", + ) + } + /> + +
+
+ +
+
+ + handleCheckboxChange( + "lowerManagementEnterprise", + ) + } + /> + +
+
+
+
+
+
+ + {/* 버튼 */} +
+ + +
+ + {/* 검증 이력 섹션 */} +
+

+ 검증 이력 +

+ +
+
+
+ ); +}; + +export default HbStatisticsVerification; diff --git a/apps/st/src/components/statistics/verification/VerificationArticleManagement.tsx b/apps/st/src/components/statistics/verification/VerificationArticleManagement.tsx new file mode 100644 index 000000000..caef0180b --- /dev/null +++ b/apps/st/src/components/statistics/verification/VerificationArticleManagement.tsx @@ -0,0 +1,262 @@ +"use client"; + +import DataGrid from "@/components/module/DataGrid"; +import { + hbArticleColumnInfo, + imrArticleColumnInfo, + validationArticleColumnInfo, +} from "@/entities/statistics/model/verification-article-column"; +import { + Button, + Input, + Label, + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@common/components"; +import { CodeSelect } from "@/entities/code/ui/code-select"; +import { verificationTargetManagementApi } from "@/entities/statistics/api/verification-target-management-service"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { useState } from "react"; +import { ENDPOINT } from "@/shared/config"; +import type { + VerificationTargetManagementSearchParams, + VerificationTargetManagementResponse, +} from "@/entities/statistics/model/verification-target-management-interface"; +import { VerificationTargetDialog } from "./VerificationTargetDialog"; +import { useConfirm } from "@frontend-opensource/use-react-hooks"; + +const TAB_CONFIG = { + HB: { value: "HB", label: "H-B", columnInfo: hbArticleColumnInfo }, + IMR: { value: "IMR", label: "I-MR", columnInfo: imrArticleColumnInfo }, + VV: { + value: "VV", + label: "Validation", + columnInfo: validationArticleColumnInfo, + }, +} as const; + +export type TabValue = keyof typeof TAB_CONFIG; + +function VerificationArticleManagement() { + const queryClient = useQueryClient(); + const { confirm } = useConfirm(); + const [activeTab, setActiveTab] = useState("HB"); + const [statsCd, setStatsCd] = useState(""); + const [vrfcTrgtNm, setVrfcTrgtNm] = useState(""); + const [searchParams, setSearchParams] = + useState({ + vrfcMthdCd: activeTab, + statsCd, + vrfcTrgtNm, + }); + const [dialogOpen, setDialogOpen] = useState(false); + const [selectedData, setSelectedData] = + useState(null); + + const { data: verificationData } = useQuery({ + queryKey: [ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG, searchParams], + queryFn: async () => { + const response = + await verificationTargetManagementApi.getVerificationTargetManagementList( + { + vrfcMthdCd: searchParams.vrfcMthdCd, + statsCd: searchParams.statsCd || undefined, + vrfcTrgtNm: searchParams.vrfcTrgtNm || undefined, + }, + ); + return response; + }, + }); + + const rowData = (verificationData?.content || []) as unknown as Record< + string, + string | number + >[]; + const columnInfo = TAB_CONFIG[activeTab].columnInfo; + + function handleSearch() { + setSearchParams({ + vrfcMthdCd: activeTab, + statsCd, + vrfcTrgtNm, + }); + } + + function handleInitialize() { + setStatsCd(""); + setVrfcTrgtNm(""); + setSearchParams({ + vrfcMthdCd: activeTab, + statsCd: "", + vrfcTrgtNm: "", + }); + } + + function handleTabChange(value: string) { + const newTab = value as TabValue; + setActiveTab(newTab); + setSearchParams({ + vrfcMthdCd: newTab, + statsCd, + vrfcTrgtNm, + }); + } + + const updateMutation = useMutation({ + mutationFn: (data: VerificationTargetManagementResponse) => + verificationTargetManagementApi.updateVerificationTargetManagement( + data.vrfcTrgtSn, + { + vrfcMthdCd: data.vrfcMthdCd, + statsCd: data.statsCd, + schmNm: data.schmNm, + tblNm: data.tblNm, + colNm: data.colNm, + pkColNm: data.pkColNm, + ipcrCntVl: data.ipcrCntVl, + pctlCrtrVl: data.pctlCrtrVl, + scopCntCntVl: data.scopCntCntVl, + thrsCntVl: data.thrsCntVl, + useYn: data.useYn, + vrfcTrgtNm: data.vrfcTrgtNm, + }, + ), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG], + }); + setDialogOpen(false); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: (vrfcTrgtSn: number) => + verificationTargetManagementApi.deleteVerificationTargetManagement( + vrfcTrgtSn, + ), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG], + }); + setDialogOpen(false); + }, + }); + + function handleRowClick(rowData: Record) { + setSelectedData( + rowData as unknown as VerificationTargetManagementResponse, + ); + setDialogOpen(true); + } + + function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + handleSearch(); + } + + async function handleSave(data: VerificationTargetManagementResponse) { + if (await confirm("저장하시겠습니까?")) { + updateMutation.mutate(data); + } + } + + async function handleDelete(vrfcTrgtSn: number) { + if (await confirm("정말 삭제하시겠습니까?")) { + deleteMutation.mutate(vrfcTrgtSn); + } + } + + return ( + + + {Object.entries(TAB_CONFIG).map(([key, config]) => ( + + {config.label} + + ))} + + +
+ +
+
+ + +
+ +
+ + setVrfcTrgtNm(e.target.value)} + placeholder="검증명" + className="w-[20rem]" + /> +
+ +
+ + +
+
+ +
+ + {Object.entries(TAB_CONFIG).map(([key, config]) => ( + + {}} + onRowClick={handleRowClick} + isExcelImport={false} + /> + + ))} + + +
+ ); +} + +export default VerificationArticleManagement; diff --git a/apps/st/src/components/statistics/verification/VerificationTargetDialog.tsx b/apps/st/src/components/statistics/verification/VerificationTargetDialog.tsx new file mode 100644 index 000000000..40fa92826 --- /dev/null +++ b/apps/st/src/components/statistics/verification/VerificationTargetDialog.tsx @@ -0,0 +1,376 @@ +"use client"; + +import { + Button, + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + Input, + Table, + TableBody, + TableCell, + TableHead, + TableRow, +} from "@common/components"; +import { CodeSelect } from "@/entities/code/ui/code-select"; +import type { VerificationTargetManagementResponse } from "@/entities/statistics/model/verification-target-management-interface"; +import { + verificationTargetManagementSchema, + type VerificationTargetManagementFormData, +} from "@/entities/statistics/model/verification-target-management-schema"; +import { useEffect } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import type { TabValue } from "./VerificationArticleManagement"; + +interface VerificationTargetDialogProps { + tabValue: TabValue; + open: boolean; + onOpenChange: (open: boolean) => void; + data: VerificationTargetManagementResponse | null; + onSave: (data: VerificationTargetManagementResponse) => void; + onDelete: (vrfcTrgtSn: number) => void; +} + +export function VerificationTargetDialog({ + tabValue, + open, + onOpenChange, + data, + onSave, + onDelete, +}: VerificationTargetDialogProps) { + const { + control, + handleSubmit, + reset, + formState: { errors }, + } = useForm({ + resolver: zodResolver(verificationTargetManagementSchema), + defaultValues: data || undefined, + }); + + useEffect(() => { + if (data && open) reset(data); + }, [data, open, reset]); + + function onSubmit(formData: VerificationTargetManagementFormData) { + if (!data) return; + onSave({ + ...data, + ...formData, + } as VerificationTargetManagementResponse); + } + + function handleDelete() { + if (data?.vrfcTrgtSn) { + onDelete(data.vrfcTrgtSn); + } + } + + if (!data) return null; + + return ( + + + + 검증 항목 상세 + + +
+ + + + + 통계항목 + + + ( +
+ +
+ )} + /> +
+ + 검증명 + + + ( + + )} + /> + +
+ + + + 스키마명 + + + ( +
+ +
+ )} + /> +
+ + 테이블명 + + + ( +
+ +
+ )} + /> +
+
+ + + + 컬럼명 + + + ( +
+ +
+ )} + /> +
+ + PK 키 + + + ( +
+ +
+ )} + /> +
+
+ + {tabValue !== "IMR" && ( + + + 중요도 계수(μ) + + + ( +
+ + field.onChange( + e.target.value + ? Number( + e.target + .value, + ) + : null, + ) + } + placeholder="(0 ~ 1, 0.1 단위)" + /> +
+ )} + /> +
+ + 백분위수 기준값(pct) + + + ( +
+ + field.onChange( + e.target.value + ? Number( + e.target + .value, + ) + : null, + ) + } + placeholder="(0 ~ 0.5, 0.1 단위)" + /> +
+ )} + /> +
+
+ )} + + {tabValue !== "IMR" && ( + + + 스케일 조정 계수(A) + + + ( +
+ + field.onChange( + e.target.value + ? Number( + e.target + .value, + ) + : null, + ) + } + placeholder="(0 ~ 1, 0.01 단위)" + /> +
+ )} + /> +
+ + 임계 계수(c) + + + ( +
+ + field.onChange( + e.target.value + ? Number( + e.target + .value, + ) + : null, + ) + } + placeholder="(0 ~ 100, 1 단위)" + /> +
+ )} + /> +
+
+ )} +
+
+ + + + + + +
+
+
+ ); +} diff --git a/apps/st/src/components/type/DataGrid.type.ts b/apps/st/src/components/type/DataGrid.type.ts index 01284cef9..59948afb8 100644 --- a/apps/st/src/components/type/DataGrid.type.ts +++ b/apps/st/src/components/type/DataGrid.type.ts @@ -1,26 +1,267 @@ +import React from "react"; +import { ValueType } from "realgrid"; + +// RealGrid 타입 정의 +/** setColumns에 전달하는 컬럼 정보 (footer 배열/단일 객체 포함) */ +export type RealGridColumnInfo = { + name: string; + fieldName: string; + header: { text: string }; + editable?: boolean; + valueType?: import("realgrid").ValueType; + dataFormat?: string; + styleName?: string; + mergeRule?: { criteria: "value" }; + footer?: + | { + text?: string; + expression?: "sum" | "avg" | "count" | "max" | "min"; + numberFormat?: string; + valueCallback?: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: ColumnFooter, + value: number | string | undefined, + ) => number | string; + } + | Array<{ + text?: string; + expression?: "sum" | "avg" | "count" | "max" | "min"; + numberFormat?: string; + valueCallback?: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: ColumnFooter, + value: number | string | undefined, + ) => number | string; + }>; +}; + +/** setColumns 메서드가 있는 GridView */ +export type GridViewWithSetColumns = GridView & { + setColumns?: (columns: RealGridColumnInfo[]) => void; +}; + +/** footer 배열 요소에 valueCallback 할당용 */ +export type FooterItemWithCallback = { + valueCallback?: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: ColumnFooter, + value: number | string | undefined, + ) => number | string; +}; + +export type GridView = { + getSummary( + field: string, + summary: "sum" | "avg" | "count" | "max" | "min", + ): number | undefined; + getDataSource(): { + getRowCount(): number; + getValue(rowIndex: number, field: string): number | string; + getDataRowId(dataRow: number): number | string; + }; + getDataRow(itemIndex: number): number; +}; + +export type MergeCallback = ( + grid: GridView, + column: DataColumn, + itemIndex: number, + value: number | string | null | undefined, +) => number | null; + +export type DataColumn = { + name: string; + fieldName: string; +}; + +export type ColumnFooter = { + text?: string; + expression?: string; + numberFormat?: string; +}; + +/** 정렬 시 같은 그룹 내에서는 orderByField 순서 유지, 그룹 간에는 정렬 필드로 비교. */ +export type SortPreserveGroupOrder = { + groupField: string; + orderByField?: string; +}; + +/** RealGrid valueCallback 시그니처 (계산 필드용) */ +export type DataFieldValueCallback = ( + prod: unknown, + dataRow: number, + fieldName: string, + fieldNames: string[], + values: unknown[], +) => number | string | undefined; + +/** 계산 필드 설정 (computedFieldCallbacks.ts 참고) */ +export type ComputedFieldConfig = + | { fields: string[]; type: "sum" | "avg" } + | { + numeratorFields: string[]; + denominatorFields: string[]; + type: "pblswrgPopltnSuprtRate"; + } + | { + numeratorFields: string[]; + denominatorFields: string[]; + type: "adtrtPopltnSuprtRate"; + } + | { + numeratorFields: string[]; + denominatorFields: string[]; + thirdFields: string[]; + type: "swrgInstlrtRate"; + }; + export type ColumnConfig = { name: string; fieldName: string; header: { text: string }; + /** 계산 필드: fields 합계/평균 등. valueCallback으로 dataProvider.setFields 시 전달 */ + computed?: ComputedFieldConfig; + editable?: boolean; // 셀 편집 가능 여부 + /** 그리드에서 컬럼 숨김 (수식용 필드 등) */ + visible?: boolean; + /** 셀에 적용할 CSS 클래스명 (예: 'rg-cell-readonly', 'rg-cell-total') */ + styleName?: string; + mergeCells?: boolean; + sortdisable?: boolean; + sortPreserveGroupOrder?: SortPreserveGroupOrder; + valueType?: ValueType; + dataFormat?: string; + footer?: + | { + text?: string; + expression?: "sum" | "avg" | "count" | "max" | "min"; + numberFormat?: string; + valueCallback?: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: ColumnFooter, + value: number | string | undefined, + ) => number | string; + multiRow?: boolean; // 여러 행 footer 사용 여부 + } + | Array<{ + text?: string; + expression?: "sum" | "avg" | "count" | "max" | "min"; + numberFormat?: string; + valueCallback?: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: ColumnFooter, + value: number | string | undefined, + ) => number | string; + }>; // RealGrid에서 footer를 배열로 설정할 수 있음 }; -export type ColumnLayoutItem = string | { - name: string; - hideChildHeaders?: boolean; - header: { text: string }; - items: (string | ColumnLayoutItem)[]; +export type FooterUserSpan = { + rowspan?: number; // 병합할 행 수 + colspan?: number; // 병합할 컬럼 수 + text?: string; // 표시할 텍스트 }; +export type ColumnLayoutItem = + | string + | { + name: string; + hideChildHeaders?: boolean; + header: { text: string }; + items: (string | ColumnLayoutItem)[]; + footerUserSpans?: FooterUserSpan[]; // footer 병합 설정 + } + | { + column: string; // 컬럼 이름 (footerUserSpans 사용 시) + footerUserSpans?: FooterUserSpan[]; // footer 병합 설정 + }; + export type ColumnInfo = { columns: ColumnConfig[]; columnLayout: ColumnLayoutItem[]; }; +export type ColumnInfoList = { + tabKey: string; // 탭을 식별하는 고유 키 (필수), server(api)에 전송할 변수 값 + columns?: ColumnConfig[]; // 일반 그리드용 (isSplitGrid가 false일 때) + columnLayout?: ColumnLayoutItem[]; // 일반 그리드용 (isSplitGrid가 false일 때) + rowStartNum?: number; + fixedColumns?: number; + tabLabel?: string; // 탭에 표시될 레이블 + isSplitGrid?: boolean; // 5:5 분리형 그리드 유무 + left?: ColumnInfoList; // SplitDataGrid용 왼쪽 그리드 정보 + right?: ColumnInfoList; // SplitDataGrid용 오른쪽 그리드 정보 +}; + +// 개별 셀 스타일을 동적으로 결정하기 위한 콜백 (예: 검증 오류 셀 강조) +export type CellStyleCallbackParams = { + rowIndex: number; + fieldName: string; + row: Record; +}; + +export type CellStyleCallback = (params: CellStyleCallbackParams) => string | undefined; + export type DataGridProps = { columnInfo: ColumnInfo; - rows?: Record[]; rowStartNum?: number; // 헤더 행 개수 (1부터 시작, 예: 2면 1행과 2행까지 헤더로 간주) - isExcelImport?: boolean; // 엑셀 가져오기 유무무 - onRowsChange?: (rows: Record[]) => void; + isExcelImport?: boolean; // 엑셀 가져오기 유무 + isExcelExport?: boolean; + onRowsChange?: (rows: Record[]) => void; fixedColumns?: number; // 고정할 컬럼 개수 (좌측부터) -}; \ No newline at end of file + showHeaderCheckbox?: boolean; // 헤더 체크박스 표시 여부 (기본값: true) + rowData: Record[]; + setRowData: React.Dispatch< + React.SetStateAction[]> + >; + /** 셀 단위로 styleName을 동적으로 결정 (예: 검증 오류 셀) */ + cellStyleCallback?: CellStyleCallback; + /** 저장 등 시점에 그리드 현재 데이터를 가져올 수 있도록 할당 (편집 반영된 값) */ + getGridDataRef?: { + current: (() => Record[]) | null; + }; + onRowClick?: (rowData: Record) => void; // 행 클릭 이벤트 +}; + +export type TabDataGridProps = { + columnInfo: ColumnInfoList[]; + rows?: Record[]; + isExcelImport?: boolean; // 엑셀 가져오기 유무 + isExcelExport?: boolean; + onRowsChange?: (rows: Record[]) => void; + showHeaderCheckbox?: boolean; // 헤더 체크박스 표시 여부 (기본값: true) + rowDataMap: Map[]>; + setRowDataMap: React.Dispatch< + React.SetStateAction[]>> + >; + isSplitGrid?: boolean; // 5:5 분리형 그리드 유무 + /** 활성 탭 키 (제어 모드). 부모에서 넘기면 해당 탭이 선택됨 */ + activeTab?: string; + /** 활성 탭 변경 시 호출 (제어 모드). activeTab과 함께 넘기면 부모가 탭 상태를 가짐 */ + onActiveTabChange?: (tabKey: string) => void; +}; + +export type SplitDataGridProps = { + leftColumnInfo: ColumnInfo; + rightColumnInfo: ColumnInfo; + leftFixedColumns?: number; + rightFixedColumns?: number; + showHeaderCheckbox?: boolean; + leftRowData: Record[]; + rightRowData: Record[]; + setLeftRowData: React.Dispatch< + React.SetStateAction[]> + >; + setRightRowData: React.Dispatch< + React.SetStateAction[]> + >; +}; diff --git a/apps/st/src/components/type/SearchForm.type.ts b/apps/st/src/components/type/SearchForm.type.ts index 50bd72a5d..b6fd4211d 100644 --- a/apps/st/src/components/type/SearchForm.type.ts +++ b/apps/st/src/components/type/SearchForm.type.ts @@ -1,26 +1,28 @@ export type SearchFormValues = { sido?: string; - sgg?: string; + gugun?: string; year?: string; order?: string; fctName?: string; + bsnmCd?: string; }; export type SearchFormProps = { sido?: boolean; - sgg?: boolean; + gugun?: boolean; year?: boolean; order?: boolean; fctName?: boolean; userMenual?: boolean; onSubmit?: (values: SearchFormValues) => void; onReset?: () => void; + onValuesChange?: (values: SearchFormValues) => void; defaultValues?: SearchFormValues; }; -export const defaultSearchFormProps: Required> = { +export const defaultSearchFormProps: Required> = { sido: true, - sgg: true, + gugun: true, year: true, order: false, fctName: false, diff --git a/apps/st/src/components/util/column/input/ExcretaTreatFactInpColumn.ts b/apps/st/src/components/util/column/input/ExcretaTreatFactInpColumn.ts new file mode 100644 index 000000000..4896a2194 --- /dev/null +++ b/apps/st/src/components/util/column/input/ExcretaTreatFactInpColumn.ts @@ -0,0 +1,107 @@ +import { footerInt, footerDecimal1, footerDecimal3 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +/** + * 하수도 통계 관리 > 07. 분뇨처리시설 + * 단일 Tab + */ +export const ExcretaTreatFactInpColumn = { + columns: [ + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'gugun', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } }, + + // 기본 정보 + { name: 'ecscs_nm', fieldName: '시설명', header: { text: '시설명' } }, + { name: 'locplcs', fieldName: '소재지', header: { text: '소재지' } }, + { name: 'telno', fieldName: '전화번호', header: { text: '전화번호' } }, + + // 날짜 정보 + { name: 'comp_dt', fieldName: '준공일 yyyy-mm-dd', header: { text: '준공일 yyyy-mm-dd' } }, + { name: 'rn_dt', fieldName: '가동개시일 yyyy-mm-dd', header: { text: '가동개시일 yyyy-mm-dd' } }, + + // 사업비/용량 정보 + { name: 'wct', fieldName: '사업비(백만원)', header: { text: '사업비(백만원)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ecscs_cpcty', fieldName: '시설용량(m³/일)', header: { text: '시설용량(m³/일)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'process_cpcty', fieldName: '처리량(m³/일)', header: { text: '처리량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'opr_daycnt', fieldName: '가동일수(일/년)', header: { text: '가동일수(일/년)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 처리 공법 및 연계 + { name: 'trt_msrc', fieldName: '처리공법', header: { text: '처리공법' } }, + { name: 'cntc_prcplt', fieldName: '연계처리장명', header: { text: '연계처리장명' } }, + { name: 'assct_trt_cpc', fieldName: '연계처리량(m³/일)', header: { text: '연계처리량(m³/일)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 유입수질 + { name: 'infl_wqlt_bod', fieldName: 'BOD', header: { text: 'BOD' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'infl_wqlt_toc', fieldName: 'TOC', header: { text: 'TOC' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'infl_wqlt_ss', fieldName: 'SS', header: { text: 'SS' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'infl_wqlt_tn', fieldName: 'T-N', header: { text: 'T-N' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'infl_wqlt_tp', fieldName: 'T-P', header: { text: 'T-P' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'infl_wqlt_clfgrpcnt', fieldName: '대장균군수', header: { text: '대장균군수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 방류수질 + { name: 'effl_wqlt_bod', fieldName: 'BOD', header: { text: 'BOD' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'effl_wqlt_toc', fieldName: 'TOC', header: { text: 'TOC' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'effl_wqlt_ss', fieldName: 'SS', header: { text: 'SS' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'effl_wqlt_tn', fieldName: 'T-N', header: { text: 'T-N' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'effl_wqlt_tp', fieldName: 'T-P', header: { text: 'T-P' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'effl_wqlt_clfgrpcnt', fieldName: '대장균군수', header: { text: '대장균군수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 방류수역 + { name: 'rvbsn', fieldName: '수계', header: { text: '수계' } }, + { name: 'bstrm', fieldName: '지류', header: { text: '지류' } }, + { name: 'lgbsn', fieldName: '중권역', header: { text: '중권역' } }, + { name: 'mdmbsn', fieldName: '소권역', header: { text: '소권역' } }, + + // 운영 정보 + { name: 'oper_mth', fieldName: '운영주체(자체/공기업/민간위탁)', header: { text: '운영주체(자체/공기업/민간위탁)' } }, + { name: 'cntc_prcplt_cpc', fieldName: '직원총수(명)', header: { text: '직원총수(명)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'safe_acdnt_co', fieldName: '안전사고건수(건/인/년)', header: { text: '안전사고건수(건/인/년)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'rmk', fieldName: '비고', header: { text: '비고' } }, + ], + + columnLayout: [ + { + name: 'adminGroup', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'gugun'], + }, + 'ecscs_nm', + 'locplcs', + 'telno', + 'comp_dt', + 'rn_dt', + 'wct', + 'ecscs_cpcty', + 'process_cpcty', + 'opr_daycnt', + 'trt_msrc', + 'cntc_prcplt', + 'assct_trt_cpc', + { + name: 'influenceGroup', + hideChildHeaders: false, + header: { text: '유입수질(mg/L, 개/mL)' }, + items: ['infl_wqlt_bod', 'infl_wqlt_toc', 'infl_wqlt_ss', 'infl_wqlt_tn', 'infl_wqlt_tp', 'infl_wqlt_clfgrpcnt'], + }, + { + name: 'effluentGroup', + hideChildHeaders: false, + header: { text: '방류수질(mg/L, 개/mL)' }, + items: ['effl_wqlt_bod', 'effl_wqlt_toc', 'effl_wqlt_ss', 'effl_wqlt_tn', 'effl_wqlt_tp', 'effl_wqlt_clfgrpcnt'], + }, + { + name: 'dischargeGroup', + hideChildHeaders: false, + header: { text: '방류수역' }, + items: ['rvbsn', 'bstrm', 'lgbsn', 'mdmbsn'], + }, + 'oper_mth', + 'cntc_prcplt_cpc', + 'safe_acdnt_co', + 'rmk', + ] +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/PublicSewageFactInpColumn.ts b/apps/st/src/components/util/column/input/PublicSewageFactInpColumn.ts new file mode 100644 index 000000000..d070c9b9d --- /dev/null +++ b/apps/st/src/components/util/column/input/PublicSewageFactInpColumn.ts @@ -0,0 +1,211 @@ +import { footerInt, footerDecimal1, footerDecimal3 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +/** + * 하수도 통계 관리 > 06. 공공하수처리시설 + * 단일 Tab + */ +export const PublicSewageFactInpColumn = { + columns: [ + // 행정구역 + { name: 'sidoCd', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'gugun', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 시설명 + { name: 'bscFctNm', fieldName: '시설명(500m³/일 이상/미만)', header: { text: '시설명(500m³/일 이상/미만)' }, editable: false }, + + // 소재지 + { name: 'addr', fieldName: '소재지', header: { text: '소재지' }, editable: false }, + + // 시설용량 + { name: 'fctCpc', fieldName: '시설용량(500m³/일 이상/미만)', header: { text: '시설용량(500m³/일 이상/미만)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // (m³/일) + { name: 'fctCpc1', fieldName: '물리적', header: { text: '물리적' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'fctCpc2', fieldName: '생물학적', header: { text: '생물학적' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'fctCpc3', fieldName: '고도', header: { text: '고도' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 유입하수량 + { name: 'totInflAmntAve', fieldName: '유입하수량(500m³/일 이상/미만)', header: { text: '유입하수량(500m³/일 이상/미만)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // (m³/일) + { name: 'pInflAmntAve', fieldName: '물리적', header: { text: '물리적' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'oInflAmntAve', fieldName: '생물학적', header: { text: '생물학적' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'aInflAmntAve', fieldName: '고도', header: { text: '고도' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 방류량 + { name: 'totTputAve', fieldName: '방류량(500m³/일 이상/미만)', header: { text: '방류량(500m³/일 이상/미만)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 방류량 - (m³/일) + { name: 'pTputAve', fieldName: '물리적', header: { text: '물리적' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'oTputAve', fieldName: '생물학적', header: { text: '생물학적' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'aTputAve', fieldName: '고도', header: { text: '고도' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 수질 + { name: 'inflAssctBfrWqltBod', fieldName: '유입BOD', header: { text: '유입BOD' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'efflWqltBod', fieldName: '방류BOD', header: { text: '방류BOD' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'inflAssctBfrWqltToc', fieldName: '유입TOC', header: { text: '유입TOC' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'efflWqltToc', fieldName: '방류TOC', header: { text: '방류TOC' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'inflAssctBfrWqltSs', fieldName: '유입SS', header: { text: '유입SS' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'efflWqltSs', fieldName: '방류SS', header: { text: '방류SS' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'inflAssctBfrWqltTn', fieldName: '유입T-N', header: { text: '유입T-N' }, editable: false, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'efflWqltTn', fieldName: '방류T-N', header: { text: '방류T-N' }, editable: false, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'inflAssctBfrWqltTp', fieldName: '유입T-P', header: { text: '유입T-P' }, editable: false, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'efflWqltTp', fieldName: '방류T-P', header: { text: '방류T-P' }, editable: false, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'inflAssctBfrWqltClfgrpcnt', fieldName: '유입총대장균군수', header: { text: '유입총대장균군수' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'efflWqltClfgrpcnt', fieldName: '방류총대장균군수', header: { text: '방류총대장균군수' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 처리특성 + { name: 'tmEfficiency', fieldName: '처리효율(%)', header: { text: '처리효율(%)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'pcLoad', fieldName: '처리부하량(kgBOD/D)', header: { text: '처리부하량(kgBOD/D)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'trtFrfHanNm', fieldName: '처리방법', header: { text: '처리방법' }, editable: false }, + + // 연계처리량 + { name: 'excretionsTot', fieldName: '분뇨', header: { text: '분뇨' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'stkrsngWstwtrTot', fieldName: '축산', header: { text: '축산' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'lchtTot', fieldName: '침출수', header: { text: '침출수' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'etcTot', fieldName: '기타', header: { text: '기타' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 시설정보 + { name: 'tel', fieldName: '전화번호', header: { text: '전화번호' }, editable: false }, + { name: 'rnDt', fieldName: '준공일', header: { text: '준공일' }, editable: false }, + { name: 'compDt', fieldName: '가동개시일', header: { text: '가동개시일' }, editable: false }, + { name: 'tot', fieldName: '사업비', header: { text: '사업비' }, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 방류수 소독방법 + { name: 'dsfctNm', fieldName: '방류수 소독방법', header: { text: '방류수 소독방법' }, editable: false }, + + // 방류수역 + { name: 'wbsnNm', fieldName: '수계', header: { text: '수계' }, editable: false }, + { name: 'rvNm', fieldName: '지류', header: { text: '지류' }, editable: false }, + { name: 'mdmbsn', fieldName: '세부단위구역', header: { text: '세부단위구역' }, editable: false }, + { name: 'efflWqltStndrdNm', fieldName: '지역구분', header: { text: '지역구분' }, editable: false }, + + // 방류수역 > 중권역 + { name: 'lgbsn', fieldName: '명칭', header: { text: '명칭' }, editable: false }, + { name: 'lgbsnBod', fieldName: '목표수질(BOD)', header: { text: '목표수질(BOD)' }, editable: false }, + + // 에너지 자립률 + { name: 'toeRt', fieldName: '에너지자립률(%)', header: { text: '에너지자립률(%)' }, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 에너지 자체 생산량 + { name: 'useQnty', fieldName: '에너지자체생산량(TOE)', header: { text: '에너지자체생산량(TOE)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 연간 총 에너지 사용량 + { name: 'toeSum', fieldName: '계(TOE)', header: { text: '계(TOE)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'elcpwAmnt', fieldName: '총 전력사용량(kWh)', header: { text: '총 전력사용량(kWh)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'toeQnty', fieldName: '자체 에너지사용량(TOE)', header: { text: '자체 에너지사용량(TOE)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 하수처리량당 CO2배출량 + { name: 'co2Emissions', fieldName: '하수처리량당 CO2배출량(kgCO2/m³)', header: { text: '하수처리량당 CO2배출량(kgCO2/m³)' }, editable: false, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + + // 운영주체 + { name: 'oprClsNm', fieldName: '운영주체(자체/공기업/민간대행)', header: { text: '운영주체(자체/공기업/민간대행)' }, editable: false }, + + // 위탁현황 + { name: 'trstOprEtpNm', fieldName: '위탁업체명', header: { text: '위탁업체명' } }, + { name: 'yrstpTrstCst', fieldName: '위탁비용(백만원/년)', header: { text: '위탁비용(백만원/년)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'trstOprDt', fieldName: '위탁계약기간(yyyy-mm-dd~yyyy-mm-dd)', header: { text: '위탁계약기간(yyyy-mm-dd~yyyy-mm-dd)' } }, + + // 기타 + { name: 'cntrTrtFctNm', fieldName: '중심처리시설', header: { text: '중심처리시설' } }, + { name: 'totWtrQrm', fieldName: '직원총수(명)', header: { text: '직원총수(명)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'safeAcdntCo', fieldName: '안전사고건수', header: { text: '안전사고건수' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'rmk', fieldName: '비고', header: { text: '비고' } }, + ], + + columnLayout: [ + { + name: 'administrative', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sidoCd', 'gugun'], + }, + 'bscFctNm', + 'addr', + 'fctCpc', + { + name: 'facilityCapacityDetail', + hideChildHeaders: false, + header: { text: '(m³/일)' }, + items: ['fctCpc1', 'fctCpc2', 'fctCpc3'], + }, + 'totInflAmntAve', + { + name: 'influentWaterDetail', + hideChildHeaders: false, + header: { text: '(m³/일)' }, + items: ['pInflAmntAve', 'oInflAmntAve', 'aInflAmntAve'], + }, + 'totTputAve', + { + name: 'effluentWaterDetail', + hideChildHeaders: false, + header: { text: '(m³/일)' }, + items: ['pTputAve', 'oTputAve', 'aTputAve'], + }, + 'inflAssctBfrWqltBod', + 'efflWqltBod', + 'inflAssctBfrWqltToc', + 'efflWqltToc', + 'inflAssctBfrWqltSs', + 'efflWqltSs', + 'inflAssctBfrWqltTn', + 'efflWqltTn', + 'inflAssctBfrWqltTp', + 'efflWqltTp', + 'inflAssctBfrWqltClfgrpcnt', + 'efflWqltClfgrpcnt', + 'tmEfficiency', + 'pcLoad', + 'trtFrfHanNm', + { + name: 'linkedTreatment', + hideChildHeaders: false, + header: { text: '연계처리량(m³/일) (500m³/일 이상/미만)' }, + items: ['excretionsTot', 'stkrsngWstwtrTot', 'lchtTot', 'etcTot'], + }, + 'tel', + 'rnDt', + 'compDt', + 'tot', + 'dsfctNm', + { + name: 'dischargeArea', + hideChildHeaders: false, + header: { text: '방류수역' }, + items: [ + 'wbsnNm', + 'rvNm', + 'mdmbsn', + 'efflWqltStndrdNm', + { + name: 'mediumWatershed', + hideChildHeaders: false, + header: { text: '중권역' }, + items: ['lgbsn', 'lgbsnBod'], + }, + ], + }, + 'toeRt', + 'useQnty', + { + name: 'energy', + hideChildHeaders: false, + header: { text: '연간 총 에너지 사용량(TOE)' }, + items: ['toeSum', 'elcpwAmnt', 'toeQnty'], + }, + 'co2Emissions', + 'oprClsNm', + { + name: 'consignmentStatus', + hideChildHeaders: false, + header: { text: '위탁현황' }, + items: ['trstOprEtpNm', 'yrstpTrstCst', 'trstOprDt'], + }, + 'cntrTrtFctNm', + 'totWtrQrm', + 'safeAcdntCo', + 'rmk', + ] +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/PumpingStationInpColumn.ts b/apps/st/src/components/util/column/input/PumpingStationInpColumn.ts new file mode 100644 index 000000000..6a174daca --- /dev/null +++ b/apps/st/src/components/util/column/input/PumpingStationInpColumn.ts @@ -0,0 +1,143 @@ +import { footerInt, footerDecimal1, footerDecimal3 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +/** + * 하수도 통계 관리 > 05. 펌프장 + * 단일 Tab + */ +export const PumpingStationInpColumn = { + columns: [ + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } }, + + // 기본 정보 + { name: 'treatmentFacilityName', fieldName: '처리장명', header: { text: '처리장명' } }, + { name: 'facilityName', fieldName: '시설명', header: { text: '시설명' } }, + { name: 'classification', fieldName: '구분(합류식 분류식)', header: { text: '구분(합류식 분류식)' } }, + { name: 'location', fieldName: '위치', header: { text: '위치' } }, + { name: 'operationDate', fieldName: '가동 년월일 yyyy-mm-dd', header: { text: '가동 년월일 yyyy-mm-dd' } }, + { name: 'planDrainageArea', fieldName: '계획배수면적(㎢)', header: { text: '계획배수면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + + // 계획시간 대 최대배수량 + { name: 'fairWeatherFlow', fieldName: '청천시(A)', header: { text: '청천시(A)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'rainyWeatherFlow', fieldName: '우천시(B)', header: { text: '우천시(B)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'rainwaterFlow', fieldName: '우수량(B-A)', header: { text: '우수량(B-A)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 배수능력 > 총 양수량 (오수) + { name: 'sewageTotalPumpCapacity', fieldName: '총양수량(m³/min)', header: { text: '총양수량(m³/min)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 배수능력 > 오수펌프(1) + { name: 'sewagePump1Diameter', fieldName: '오수펌프(1) 구경(mm)', header: { text: '구경(mm)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sewagePump1Capacity', fieldName: '오수펌프(1) 대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'sewagePump1Count', fieldName: '오수펌프(1) 펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sewagePump1Reserve', fieldName: '오수펌프(1) 예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 배수능력 > 오수펌프(2) + { name: 'sewagePump2Diameter', fieldName: '오수펌프(2) 구경(mm)', header: { text: '구경(mm)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sewagePump2Capacity', fieldName: '오수펌프(2) 대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'sewagePump2Count', fieldName: '오수펌프(2) 펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sewagePump2Reserve', fieldName: '오수펌프(2) 예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 배수능력 > 오수펌프(3) + { name: 'sewagePump3Diameter', fieldName: '오수펌프(3) 구경(mm)', header: { text: '구경(mm)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sewagePump3Capacity', fieldName: '오수펌프(3) 대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'sewagePump3Count', fieldName: '오수펌프(3) 펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sewagePump3Reserve', fieldName: '오수펌프(3) 예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 배수능력 > 총 양수량 (우수) + { name: 'rainwaterTotalPumpCapacity', fieldName: '총양수량(m³/min)', header: { text: '총양수량(m³/min)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 배수능력 > 우수펌프(1) + { name: 'rainwaterPump1Diameter', fieldName: '우수펌프(1) 구경(mm)', header: { text: '구경(mm)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'rainwaterPump1Capacity', fieldName: '우수펌프(1) 대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'rainwaterPump1Count', fieldName: '우수펌프(1) 펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'rainwaterPump1Reserve', fieldName: '우수펌프(1) 예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 배수능력 > 우수펌프(2) + { name: 'rainwaterPump2Diameter', fieldName: '우수펌프(2) 구경(mm)', header: { text: '구경(mm)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'rainwaterPump2Capacity', fieldName: '우수펌프(2) 대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'rainwaterPump2Count', fieldName: '우수펌프(2) 펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'rainwaterPump2Reserve', fieldName: '우수펌프(2) 예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 배수능력 > 우수펌프(3) + { name: 'rainwaterPump3Diameter', fieldName: '우수펌프(3) 구경(mm)', header: { text: '구경(mm)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'rainwaterPump3Capacity', fieldName: '우수펌프(3) 대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'rainwaterPump3Count', fieldName: '우수펌프(3) 펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'rainwaterPump3Reserve', fieldName: '우수펌프(3) 예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 연간전력 사용량 + { name: 'annualPowerUsage', fieldName: '연간전력사용량(kWh/년)', header: { text: '연간전력사용량(kWh/년)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'remarks', fieldName: '비고', header: { text: '비고' } }, + ], + + columnLayout: [ + { + name: 'administrativeArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'sgg'], + }, + 'treatmentFacilityName', + 'facilityName', + 'classification', + 'location', + 'operationDate', + 'planDrainageArea', + { + name: 'planFlowGroup', + hideChildHeaders: false, + header: { text: '계획시간대최대배수량(m³/hr)' }, + items: ['fairWeatherFlow', 'rainyWeatherFlow', 'rainwaterFlow'], + }, + { + name: 'drainageCapability', + hideChildHeaders: false, + header: { text: '배수능력' }, + items: [ + 'sewageTotalPumpCapacity', + { + name: 'sewagePump1Group', + hideChildHeaders: false, + header: { text: '오수펌프(1)' }, + items: ['sewagePump1Diameter', 'sewagePump1Capacity', 'sewagePump1Count', 'sewagePump1Reserve'], + }, + { + name: 'sewagePump2Group', + hideChildHeaders: false, + header: { text: '오수펌프(2)' }, + items: ['sewagePump2Diameter', 'sewagePump2Capacity', 'sewagePump2Count', 'sewagePump2Reserve'], + }, + { + name: 'sewagePump3Group', + hideChildHeaders: false, + header: { text: '오수펌프(3)' }, + items: ['sewagePump3Diameter', 'sewagePump3Capacity', 'sewagePump3Count', 'sewagePump3Reserve'], + }, + 'rainwaterTotalPumpCapacity', + { + name: 'rainwaterPump1Group', + hideChildHeaders: false, + header: { text: '우수펌프(1)' }, + items: ['rainwaterPump1Diameter', 'rainwaterPump1Capacity', 'rainwaterPump1Count', 'rainwaterPump1Reserve'], + }, + { + name: 'rainwaterPump2Group', + hideChildHeaders: false, + header: { text: '우수펌프(2)' }, + items: ['rainwaterPump2Diameter', 'rainwaterPump2Capacity', 'rainwaterPump2Count', 'rainwaterPump2Reserve'], + }, + { + name: 'rainwaterPump3Group', + hideChildHeaders: false, + header: { text: '우수펌프(3)' }, + items: ['rainwaterPump3Diameter', 'rainwaterPump3Capacity', 'rainwaterPump3Count', 'rainwaterPump3Reserve'], + }, + ], + }, + 'annualPowerUsage', + 'remarks', + ] +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/SeweragePenetrationRateInpColumn.ts b/apps/st/src/components/util/column/input/SeweragePenetrationRateInpColumn.ts new file mode 100644 index 000000000..41a9c5700 --- /dev/null +++ b/apps/st/src/components/util/column/input/SeweragePenetrationRateInpColumn.ts @@ -0,0 +1,256 @@ +import { footerInt, footerDecimal3, footerAvgDecimal } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; +/** + * 하수도 통계 관리 > 01. 하수도 보급률 + * 단일 Tab + */ +export const SeweragePenetrationRateInpColumn = { + columns: [ + // 행정구역 + { name: 'sido', fieldName: 'sido', header: { text: '시도' }, footer: { text: '합계' }, editable: false, styleName: 'rg-cell-readonly' }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, editable: false, styleName: 'rg-cell-readonly' }, + { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, editable: false, styleName: 'rg-cell-readonly' }, + + // 수계 및 권역 + { name: 'rvbsn', fieldName: 'rvbsn', header: { text: '수계' }, editable: false, styleName: 'rg-cell-readonly' }, + { name: 'bstrm', fieldName: 'bstrm', header: { text: '지류' } }, + + // 수계영향권별분류 + { name: 'mdbsn', fieldName: 'mdbsn', header: { text: '세부단위유역' }, editable: false, styleName: 'rg-cell-readonly' }, + { name: 'lgbsn', fieldName: 'lgbsn', header: { text: '중권역' }, editable: false, styleName: 'rg-cell-readonly' }, + { name: 'mdmbsn', fieldName: 'mdmbsn', header: { text: '소권역' }, editable: false, styleName: 'rg-cell-readonly' }, + + // 특별대책지역 + { name: 'speclCntrplnAr', fieldName: 'speclCntrplnAr', header: { text: '특별대책지역' } }, + + // 행정참고자료인구 + { name: 'totalPopl', fieldName: 'totalPopl', header: { text: '총인구' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0', styleName: 'rg-cell-readonly' }, + { name: 'poplSm', fieldName: 'poplSm', header: { text: '내국인' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0', styleName: 'rg-cell-readonly' }, + { name: 'frgnrPoplSm', fieldName: 'frgnrPoplSm', header: { text: '외국인' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0', styleName: 'rg-cell-readonly' }, + + // 행정참고자료면적 + { name: 'area', fieldName: 'area', header: { text: '행정참고자료면적(㎢)' }, footer: footerDecimal3, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.000', styleName: 'rg-cell-readonly' }, + + // 총인구 + { + name: 'popltnSm', + fieldName: 'popltnSm', + header: { text: '총인구(명)' }, + footer: footerInt, + editable: false, + valueType: ValueType.NUMBER, + dataFormat: '#,##0', + computed: { fields: ['pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt', 'notConectPopltn', 'townUnprocPopltn', 'townSwttPopltn', 'townWrrtnPopltn'], type: 'sum' as const }, + styleName: 'rg-cell-total', + }, + + // 총면적 + { + name: 'arSm', + fieldName: 'arSm', + header: { text: '총면적(㎢)' }, + footer: footerDecimal3, + valueType: ValueType.NUMBER, + dataFormat: '#,##0.000', + computed: { fields: ['swgeProcZoneInnerAr', 'swgeProcZoneOuterAr'], type: 'sum' as const }, + styleName: 'rg-cell-total', + }, + + // 하수처리구역 내 > 합계 + { + name: 'swgeProcZoneInnerSm', + fieldName: 'swgeProcZoneInnerSm', + header: { text: '합계' }, + footer: footerInt, + editable: false, + valueType: ValueType.NUMBER, + dataFormat: '#,##0', + computed: { fields: ['pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt', 'notConectPopltn'], type: 'sum' as const }, + styleName: 'rg-cell-total', + }, + + // 하수처리구역 내 > 공공하수처리인구 + { + name: 'pblswrgPopltnSm', + fieldName: 'pblswrgPopltnSm', + header: { text: '소계' }, + footer: footerInt, + editable: false, + valueType: ValueType.NUMBER, + dataFormat: '#,##0', + computed: { fields: ['pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt'], type: 'sum' as const }, + styleName: 'rg-cell-total', + }, + { name: 'pblswrgPrmTrt', fieldName: 'pblswrgPrmTrt', header: { text: '물리적처리' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pblswrgScdTrt', fieldName: 'pblswrgScdTrt', header: { text: '생물학적처리' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pblswrgTertTrt', fieldName: 'pblswrgTertTrt', header: { text: '고도처리' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 내 > 폐수처리인구 + { + name: 'wstrPopltnSm', + fieldName: 'wstrPopltnSm', + header: { text: '소계' }, + footer: footerInt, + editable: false, + valueType: ValueType.NUMBER, + dataFormat: '#,##0', + computed: { fields: ['wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt'], type: 'sum' as const }, + styleName: 'rg-cell-total', + }, + { name: 'wstrPrmTrt', fieldName: 'wstrPrmTrt', header: { text: '물리적처리' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'wstrScdTrt', fieldName: 'wstrScdTrt', header: { text: '생물학적처리' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'wstrTertTrt', fieldName: 'wstrTertTrt', header: { text: '고도처리' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 내 > 미접속인구 + { name: 'notConectPopltn', fieldName: 'notConectPopltn', header: { text: '미접속인구' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 내 > 면적 + { name: 'swgeProcZoneInnerAr', fieldName: 'swgeProcZoneInnerAr', header: { text: '면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + + // 하수처리구역 외 + { + name: 'swgeProcZoneOuterSm', + fieldName: 'swgeProcZoneOuterSm', + header: { text: '합계' }, + footer: footerInt, + editable: false, + valueType: ValueType.NUMBER, + dataFormat: '#,##0', + computed: { fields: ['townUnprocPopltn', 'townSwttPopltn', 'townWrrtnPopltn'], type: 'sum' as const }, + styleName: 'rg-cell-total', + }, + { name: 'townUnprocPopltn', fieldName: 'townUnprocPopltn', header: { text: '미처리인구' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'townSwttPopltn', fieldName: 'townSwttPopltn', header: { text: '오수처리인구' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'townWrrtnPopltn', fieldName: 'townWrrtnPopltn', header: { text: '정화조인구' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'swgeProcZoneOuterAr', fieldName: 'swgeProcZoneOuterAr', header: { text: '면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + + // 공공하수처리구역 인구보급률 (하수처리구역 내 인구 / 전체 인구 * 100) + { + name: 'pblswrgPopltnSuprt', + fieldName: 'pblswrgPopltnSuprt', + header: { text: '공공하수처리구역인구보급률(%)' }, + footer: footerAvgDecimal, + editable: false, + valueType: ValueType.NUMBER, + dataFormat: '#,##0.0', + computed: { + numeratorFields: ['pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt', 'notConectPopltn'], + denominatorFields: ['pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt', 'notConectPopltn', 'townUnprocPopltn', 'townSwttPopltn', 'townWrrtnPopltn'], + type: 'pblswrgPopltnSuprtRate' as const + }, + styleName: 'rg-cell-total', + }, + + // 고도처리 인구보급률 (고도처리 인구 / 전체 인구 * 100) + { + name: 'adtrtPopltnSuprt', + fieldName: 'adtrtPopltnSuprt', + header: { text: '고도처리인구보급률(%)' }, + footer: footerAvgDecimal, + editable: false, + valueType: ValueType.NUMBER, + dataFormat: '#,##0.0', + computed: { + numeratorFields: ['pblswrgTertTrt', 'wstrTertTrt'], + denominatorFields: ['pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt', 'notConectPopltn', 'townUnprocPopltn', 'townSwttPopltn', 'townWrrtnPopltn'], + type: 'adtrtPopltnSuprtRate' as const + }, + styleName: 'rg-cell-total', + }, + + // 하수도 설치율 + { + name: 'swrgInstlrt', + fieldName: 'swrgInstlrt', + header: { text: '하수도설치율(%)' }, + footer: footerAvgDecimal, + editable: false, + valueType: ValueType.NUMBER, + dataFormat: '#,##0.0', + computed: { + numeratorFields: ['pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt', 'notConectPopltn', 'swgeProcZoneOuterSm'], + denominatorFields: ['pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt', 'notConectPopltn'], + thirdFields: ['piplSupprt'], + type: 'swrgInstlrtRate' as const + }, + styleName: 'rg-cell-total', + }, + + // 비고 + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + + { name: 'piplSupprt', fieldName: 'piplSupprt', header: { text: '하수관로보급률(%)' }, visible: false }, + { name: 'adstCd', fieldName: 'adstCd', header: { text: '행정코드' }, visible: false }, + ], + + columnLayout: [ + { + name: 'groupA', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: [ + { column: 'sido', footerUserSpans: [{ colspan: 3 }] }, + 'gugun', + 'adstDong', + ], + }, + 'rvbsn', + 'bstrm', + { + name: 'groupB', + hideChildHeaders: false, + header: { text: '수계영향권별분류' }, + items: ['mdbsn', 'lgbsn', 'mdmbsn'], + }, + 'speclCntrplnAr', + { + name: 'groupC', + hideChildHeaders: false, + header: { text: '행정참고자료인구' }, + items: ['totalPopl', 'poplSm', 'frgnrPoplSm'], + }, + 'area', + 'popltnSm', + 'arSm', + { + name: 'groupD', + hideChildHeaders: false, + header: { text: '하수처리구역내' }, + items: [ + 'swgeProcZoneInnerSm', + { + name: 'pblswrgGroup', + hideChildHeaders: false, + header: { text: '공공하수처리인구(명)' }, + items: ['pblswrgPopltnSm', 'pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt'], + }, + { + name: 'wstrGroup', + hideChildHeaders: false, + header: { text: '폐수처리인구(명)' }, + items: ['wstrPopltnSm', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt'], + }, + 'notConectPopltn', + 'swgeProcZoneInnerAr' + ], + }, + { + name: 'groupE', + hideChildHeaders: false, + header: { text: '하수처리구역외' }, + items: [ + 'swgeProcZoneOuterSm', + 'townUnprocPopltn', + 'townSwttPopltn', + 'townWrrtnPopltn', + 'swgeProcZoneOuterAr' + ], + }, + 'pblswrgPopltnSuprt', + 'adtrtPopltnSuprt', + 'swrgInstlrt', + 'rmk', + 'piplSupprt', + 'adstCd', + ] +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/StatsInputStatusInpColumn.ts b/apps/st/src/components/util/column/input/StatsInputStatusInpColumn.ts new file mode 100644 index 000000000..09d10d3d1 --- /dev/null +++ b/apps/st/src/components/util/column/input/StatsInputStatusInpColumn.ts @@ -0,0 +1,46 @@ +import { ValueType } from "realgrid"; + +/** + * 하수도 통계 관리 > 00. 통계 입력 현황 + * 단일 Tab + */ +export const StatsInputStatusInpColumn = { + columns: [ + { name: 'sido', fieldName: '시도', header: { text: '시도' } }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'menu_nm', fieldName: '구분', header: { text: '구분' } }, + { name: 'locg_status_nm', fieldName: '진행상황', header: { text: '진행상황' } }, + { name: 'locg_status', fieldName: '작성률', header: { text: '작성률' }, valueType: ValueType.NUMBER }, + { name: 'locg_charger', fieldName: '작성자', header: { text: '작성자' } }, + { name: 'locg_cttpc', fieldName: '작성자연락처', header: { text: '작성자연락처' } }, + { name: 'locg_dept', fieldName: '부서', header: { text: '부서' } }, + { name: 'locg_job', fieldName: '직제', header: { text: '직제' } }, + { name: 'locg_cnfirm_nm', fieldName: '승인자', header: { text: '승인자' } }, + { name: 'locg_cnfirm_dept', fieldName: '부서', header: { text: '부서' } }, + { name: 'locg_cnfirm_job', fieldName: '직제', header: { text: '직제' } }, + { name: 'return_opinion_sm', fieldName: '반려사유', header: { text: '반려사유' } }, + ], + + columnLayout: [ + 'sido', + 'sgg', + 'menu_nm', + { + name: 'groupA', + hideChildHeaders: false, + header: { text: '하수도사업자' }, + items: [ + 'locg_status_nm', + 'locg_status', + 'locg_charger', + 'locg_cttpc', + 'locg_dept', + 'locg_job', + 'locg_cnfirm_nm', + 'locg_cnfirm_dept', + 'locg_cnfirm_job', + 'return_opinion_sm' + ], + }, + ] +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/privateSewageFacility/PrivateSewageDesigStatusInpColumn.ts b/apps/st/src/components/util/column/input/privateSewageFacility/PrivateSewageDesigStatusInpColumn.ts new file mode 100644 index 000000000..b7eaf2cca --- /dev/null +++ b/apps/st/src/components/util/column/input/privateSewageFacility/PrivateSewageDesigStatusInpColumn.ts @@ -0,0 +1,73 @@ +import { footerInt, footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 08.개인하수처리시설 > tab 3. 개인하수도 관리지역 지정공고현황 +export const PrivateSewageDesigStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 개인하수도관리지역공고현황 + { name: 'MGMT_AR', fieldName: '공고지역(개소)', header: { text: '공고지역(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'APPN_SCOPE', fieldName: '지정범위(㎢)', header: { text: '지정범위(㎢)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 개인하수도관리지역공고현황 > 정화조 + { name: 'STTY_CNT', fieldName: '개소수', header: { text: '개소수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_CPC', fieldName: '처리용량(인/일)', header: { text: '처리용량(인/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 개인하수도관리지역공고현황 > 오수시설 + { name: 'WRRTN_CNT', fieldName: '개소수', header: { text: '개소수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'WRRTN_CPC', fieldName: '처리용량(m³/일)', header: { text: '처리용량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // 검증 필드 (hidden) + { name: 'CHK_MGMT_AR', fieldName: 'CHK_MGMT_AR', header: { text: '' } }, + { name: 'CHK_APPN_SCOPE', fieldName: 'CHK_APPN_SCOPE', header: { text: '' } }, + { name: 'CHK_STTY_CNT', fieldName: 'CHK_STTY_CNT', header: { text: '' } }, + { name: 'CHK_STTY_CPC', fieldName: 'CHK_STTY_CPC', header: { text: '' } }, + { name: 'CHK_WRRTN_CNT', fieldName: 'CHK_WRRTN_CNT', header: { text: '' } }, + { name: 'CHK_WRRTN_CPC', fieldName: 'CHK_WRRTN_CPC', header: { text: '' } }, + + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' } }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' } }, + ], + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + { + name: 'group_notice', + header: { text: '개인하수도관리지역공고현황 (하수도법제34조의2)' }, + items: [ + 'MGMT_AR', + 'APPN_SCOPE', + { + name: 'group_septic', + header: { text: '정화조' }, + items: [ + 'STTY_CNT', + 'STTY_CPC' + ] + }, + { + name: 'group_sewage', + header: { text: '오수시설' }, + items: [ + 'WRRTN_CNT', + 'WRRTN_CPC' + ] + } + ] + }, + 'RMK' + ], + rowStartNum: 3, + fixedColumns: 1, + tabKey: 'privateSewageDesigStatusInp', + tabLabel: '개인하수도 관리지역 지정공고 현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/privateSewageFacility/SepticTankStatusInpColumn.ts b/apps/st/src/components/util/column/input/privateSewageFacility/SepticTankStatusInpColumn.ts new file mode 100644 index 000000000..4d2b45b8f --- /dev/null +++ b/apps/st/src/components/util/column/input/privateSewageFacility/SepticTankStatusInpColumn.ts @@ -0,0 +1,235 @@ +import { footerInt } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 08.개인하수처리시설 > tab 2. 정화조 현황 +export const SepticTankStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 총 시설 수 + { name: 'TOT_FCLTY_CNT', fieldName: '총 시설 수 (A+D)', header: { text: '총 시설 수 (A+D)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 내 > 총계 + { name: 'SPZI_SM', fieldName: '총계 A=(B+C)/2', header: { text: '총계 A=(B+C)/2' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 내 > 처리방식별 + { name: 'SPZI_MTHD_SM', fieldName: '계(B)', header: { text: '계(B)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 내 > 처리방식별 > 부패탱크 + { name: 'SPZI_ROT_NPFL_CNT', fieldName: '자연유하', header: { text: '자연유하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_ROT_ENFCT_PUMP_1', fieldName: '강제펌핑식', header: { text: '강제펌핑식' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 내 > 처리방식별 + { name: 'SPZI_WTROT_NPFL_CNT', fieldName: '살수여상', header: { text: '살수여상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_TFM', fieldName: '폭기방법', header: { text: '폭기방법' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_ARTM', fieldName: '접촉폭기', header: { text: '접촉폭기' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_CTARM', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 내 > 처리용량별 + { name: 'SPZI_PROC_CPC_SM', fieldName: '계(C)', header: { text: '계(C)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_1', fieldName: '10인조이하', header: { text: '10인조이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_2', fieldName: '11~20', header: { text: '11~20' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_3', fieldName: '21~30', header: { text: '21~30' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_4', fieldName: '31~50', header: { text: '31~50' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_5', fieldName: '51~199', header: { text: '51~199' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_6', fieldName: '200~499', header: { text: '200~499' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_7', fieldName: '500~999', header: { text: '500~999' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_8', fieldName: '1,000 이상', header: { text: '1,000 이상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 외 > 총계 + { name: 'SPZO_SM', fieldName: '총계 D=(E+F)/2', header: { text: '총계 D=(E+F)/2' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 외 > 처리방식별 + { name: 'SPZO_MTHD_SM', fieldName: '계(E)', header: { text: '계(E)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 외 > 처리방식별 > 부패탱크 + { name: 'SPZO_ROT_NPFL_CNT', fieldName: '자연유하', header: { text: '자연유하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_ROT_ENFCT_PUMP_1', fieldName: '강제펌핑식', header: { text: '강제펌핑식' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 외 > 처리방식별 + { name: 'SPZO_WTROT_NPFL_CNT', fieldName: '살수여상', header: { text: '살수여상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_TFM', fieldName: '폭기방법', header: { text: '폭기방법' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_ARTM', fieldName: '접촉폭기', header: { text: '접촉폭기' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_CTARM', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수처리구역 외 > 처리용량별 + { name: 'SPZO_PROC_CPC_SM', fieldName: '계(F)', header: { text: '계(F)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_PROC_CPC_1', fieldName: '10인조이하', header: { text: '10인조이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_PROC_CPC_2', fieldName: '11~20', header: { text: '11~20' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_PROC_CPC_3', fieldName: '21~30', header: { text: '21~30' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_PROC_CPC_4', fieldName: '31~50', header: { text: '31~50' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_PROC_CPC_5', fieldName: '51~199', header: { text: '51~199' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_PROC_CPC_6', fieldName: '200~499', header: { text: '200~499' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_PROC_CPC_7', fieldName: '500~999', header: { text: '500~999' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SPZO_PROC_CPC_8', fieldName: '1,000 이상', header: { text: '1,000 이상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // hidden + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' } }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' } }, + + // 검증 필드 (검증 여부 표시용 - 빨간색 표시) + { name: 'CHK_TOT_FCLTY_CNT', fieldName: 'CHK_TOT_FCLTY_CNT', header: { text: '' } }, + { name: 'CHK_SPZI_SM', fieldName: 'CHK_SPZI_SM', header: { text: '' } }, + { name: 'CHK_SPZI_MTHD_SM', fieldName: 'CHK_SPZI_MTHD_SM', header: { text: '' } }, + { name: 'CHK_SPZI_ROT_NPFL_CNT', fieldName: 'CHK_SPZI_ROT_NPFL_CNT', header: { text: '' } }, + { name: 'CHK_SPZI_ROT_ENFCT_PUMP_1', fieldName: 'CHK_SPZI_ROT_ENFCT_PUMP_1', header: { text: '' } }, + { name: 'CHK_SPZI_ROT_ENFCT_PUMP_2', fieldName: 'CHK_SPZI_ROT_ENFCT_PUMP_2', header: { text: '' } }, + { name: 'CHK_SPZI_ROT_ENFCT_PUMP_3', fieldName: 'CHK_SPZI_ROT_ENFCT_PUMP_3', header: { text: '' } }, + { name: 'CHK_SPZI_ROT_TANK_SM', fieldName: 'CHK_SPZI_ROT_TANK_SM', header: { text: '' } }, + { name: 'CHK_SPZI_IMHF_NPFL_CNT', fieldName: 'CHK_SPZI_IMHF_NPFL_CNT', header: { text: '' } }, + { name: 'CHK_SPZI_IMHF_ENFCT_PUMP_1', fieldName: 'CHK_SPZI_IMHF_ENFCT_PUMP_1', header: { text: '' } }, + { name: 'CHK_SPZI_IMHF_ENFCT_PUMP_2', fieldName: 'CHK_SPZI_IMHF_ENFCT_PUMP_2', header: { text: '' } }, + { name: 'CHK_SPZI_IMHF_ENFCT_PUMP_3', fieldName: 'CHK_SPZI_IMHF_ENFCT_PUMP_3', header: { text: '' } }, + { name: 'CHK_SPZI_IMHF_TANK_SM', fieldName: 'CHK_SPZI_IMHF_TANK_SM', header: { text: '' } }, + { name: 'CHK_SPZI_WTROT_NPFL_CNT', fieldName: 'CHK_SPZI_WTROT_NPFL_CNT', header: { text: '' } }, + { name: 'CHK_SPZI_WTROT_ENFCT_PUMP_1', fieldName: 'CHK_SPZI_WTROT_ENFCT_PUMP_1', header: { text: '' } }, + { name: 'CHK_SPZI_WTROT_ENFCT_PUMP_2', fieldName: 'CHK_SPZI_WTROT_ENFCT_PUMP_2', header: { text: '' } }, + { name: 'CHK_SPZI_WTROT_ENFCT_PUMP_3', fieldName: 'CHK_SPZI_WTROT_ENFCT_PUMP_3', header: { text: '' } }, + { name: 'CHK_SPZI_WTROT_TANK_SM', fieldName: 'CHK_SPZI_WTROT_TANK_SM', header: { text: '' } }, + { name: 'CHK_SPZI_TFM', fieldName: 'CHK_SPZI_TFM', header: { text: '' } }, + { name: 'CHK_SPZI_ARTM', fieldName: 'CHK_SPZI_ARTM', header: { text: '' } }, + { name: 'CHK_SPZI_CTARM', fieldName: 'CHK_SPZI_CTARM', header: { text: '' } }, + { name: 'CHK_SPZI_NPFL', fieldName: 'CHK_SPZI_NPFL', header: { text: '' } }, + { name: 'CHK_SPZI_ENFCT_PUMP', fieldName: 'CHK_SPZI_ENFCT_PUMP', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_SM', fieldName: 'CHK_SPZI_PROC_CPC_SM', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_1', fieldName: 'CHK_SPZI_PROC_CPC_1', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_2', fieldName: 'CHK_SPZI_PROC_CPC_2', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_3', fieldName: 'CHK_SPZI_PROC_CPC_3', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_4', fieldName: 'CHK_SPZI_PROC_CPC_4', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_5', fieldName: 'CHK_SPZI_PROC_CPC_5', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_6', fieldName: 'CHK_SPZI_PROC_CPC_6', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_7', fieldName: 'CHK_SPZI_PROC_CPC_7', header: { text: '' } }, + { name: 'CHK_SPZI_PROC_CPC_8', fieldName: 'CHK_SPZI_PROC_CPC_8', header: { text: '' } }, + { name: 'CHK_SPZO_SM', fieldName: 'CHK_SPZO_SM', header: { text: '' } }, + { name: 'CHK_SPZO_MTHD_SM', fieldName: 'CHK_SPZO_MTHD_SM', header: { text: '' } }, + { name: 'CHK_SPZO_ROT_NPFL_CNT', fieldName: 'CHK_SPZO_ROT_NPFL_CNT', header: { text: '' } }, + { name: 'CHK_SPZO_ROT_ENFCT_PUMP_1', fieldName: 'CHK_SPZO_ROT_ENFCT_PUMP_1', header: { text: '' } }, + { name: 'CHK_SPZO_ROT_ENFCT_PUMP_2', fieldName: 'CHK_SPZO_ROT_ENFCT_PUMP_2', header: { text: '' } }, + { name: 'CHK_SPZO_ROT_ENFCT_PUMP_3', fieldName: 'CHK_SPZO_ROT_ENFCT_PUMP_3', header: { text: '' } }, + { name: 'CHK_SPZO_ROT_TANK_SM', fieldName: 'CHK_SPZO_ROT_TANK_SM', header: { text: '' } }, + { name: 'CHK_SPZO_IMHF_NPFL_CNT', fieldName: 'CHK_SPZO_IMHF_NPFL_CNT', header: { text: '' } }, + { name: 'CHK_SPZO_IMHF_ENFCT_PUMP_1', fieldName: 'CHK_SPZO_IMHF_ENFCT_PUMP_1', header: { text: '' } }, + { name: 'CHK_SPZO_IMHF_ENFCT_PUMP_2', fieldName: 'CHK_SPZO_IMHF_ENFCT_PUMP_2', header: { text: '' } }, + { name: 'CHK_SPZO_IMHF_ENFCT_PUMP_3', fieldName: 'CHK_SPZO_IMHF_ENFCT_PUMP_3', header: { text: '' } }, + { name: 'CHK_SPZO_IMHF_TANK_SM', fieldName: 'CHK_SPZO_IMHF_TANK_SM', header: { text: '' } }, + { name: 'CHK_SPZO_WTROT_NPFL_CNT', fieldName: 'CHK_SPZO_WTROT_NPFL_CNT', header: { text: '' } }, + { name: 'CHK_SPZO_WTROT_ENFCT_PUMP_1', fieldName: 'CHK_SPZO_WTROT_ENFCT_PUMP_1', header: { text: '' } }, + { name: 'CHK_SPZO_WTROT_ENFCT_PUMP_2', fieldName: 'CHK_SPZO_WTROT_ENFCT_PUMP_2', header: { text: '' } }, + { name: 'CHK_SPZO_WTROT_ENFCT_PUMP_3', fieldName: 'CHK_SPZO_WTROT_ENFCT_PUMP_3', header: { text: '' } }, + { name: 'CHK_SPZO_WTROT_TANK_SM', fieldName: 'CHK_SPZO_WTROT_TANK_SM', header: { text: '' } }, + { name: 'CHK_SPZO_TFM', fieldName: 'CHK_SPZO_TFM', header: { text: '' } }, + { name: 'CHK_SPZO_ARTM', fieldName: 'CHK_SPZO_ARTM', header: { text: '' } }, + { name: 'CHK_SPZO_CTARM', fieldName: 'CHK_SPZO_CTARM', header: { text: '' } }, + { name: 'CHK_SPZO_NPFL', fieldName: 'CHK_SPZO_NPFL', header: { text: '' } }, + { name: 'CHK_SPZO_ENFCT_PUMP', fieldName: 'CHK_SPZO_ENFCT_PUMP', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_SM', fieldName: 'CHK_SPZO_PROC_CPC_SM', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_1', fieldName: 'CHK_SPZO_PROC_CPC_1', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_2', fieldName: 'CHK_SPZO_PROC_CPC_2', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_3', fieldName: 'CHK_SPZO_PROC_CPC_3', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_4', fieldName: 'CHK_SPZO_PROC_CPC_4', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_5', fieldName: 'CHK_SPZO_PROC_CPC_5', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_6', fieldName: 'CHK_SPZO_PROC_CPC_6', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_7', fieldName: 'CHK_SPZO_PROC_CPC_7', header: { text: '' } }, + { name: 'CHK_SPZO_PROC_CPC_8', fieldName: 'CHK_SPZO_PROC_CPC_8', header: { text: '' } }, + ], + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'TOT_FCLTY_CNT', + { + name: 'group_spzi', + header: { text: '하수처리구역 내' }, + items: [ + 'SPZI_SM', + { + name: 'group_spzi_mthd', + header: { text: '처리방식별' }, + items: [ + 'SPZI_MTHD_SM', + { + name: 'group_spzi_rot', + header: { text: '부패탱크' }, + items: [ + 'SPZI_ROT_NPFL_CNT', + 'SPZI_ROT_ENFCT_PUMP_1' + ] + }, + 'SPZI_WTROT_NPFL_CNT', + 'SPZI_TFM', + 'SPZI_ARTM', + 'SPZI_CTARM' + ] + }, + { + name: 'group_spzi_proc', + header: { text: '처리용량별' }, + items: [ + 'SPZI_PROC_CPC_SM', + 'SPZI_PROC_CPC_1', + 'SPZI_PROC_CPC_2', + 'SPZI_PROC_CPC_3', + 'SPZI_PROC_CPC_4', + 'SPZI_PROC_CPC_5', + 'SPZI_PROC_CPC_6', + 'SPZI_PROC_CPC_7', + 'SPZI_PROC_CPC_8' + ] + } + ] + }, + { + name: 'group_spzo', + header: { text: '하수처리구역 외' }, + items: [ + 'SPZO_SM', + { + name: 'group_spzo_mthd', + header: { text: '처리방식별' }, + items: [ + 'SPZO_MTHD_SM', + { + name: 'group_spzo_rot', + header: { text: '부패탱크' }, + items: [ + 'SPZO_ROT_NPFL_CNT', + 'SPZO_ROT_ENFCT_PUMP_1' + ] + }, + 'SPZO_WTROT_NPFL_CNT', + 'SPZO_TFM', + 'SPZO_ARTM', + 'SPZO_CTARM' + ] + }, + { + name: 'group_spzo_proc', + header: { text: '처리용량별' }, + items: [ + 'SPZO_PROC_CPC_SM', + 'SPZO_PROC_CPC_1', + 'SPZO_PROC_CPC_2', + 'SPZO_PROC_CPC_3', + 'SPZO_PROC_CPC_4', + 'SPZO_PROC_CPC_5', + 'SPZO_PROC_CPC_6', + 'SPZO_PROC_CPC_7', + 'SPZO_PROC_CPC_8' + ] + } + ] + }, + 'RMK' + ], + rowStartNum: 4, + fixedColumns: 1, + tabKey: 'septicTankStatusInp', + tabLabel: '정화조 현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/privateSewageFacility/SewageTreatFactStatusInpColumn.ts b/apps/st/src/components/util/column/input/privateSewageFacility/SewageTreatFactStatusInpColumn.ts new file mode 100644 index 000000000..40e77978a --- /dev/null +++ b/apps/st/src/components/util/column/input/privateSewageFacility/SewageTreatFactStatusInpColumn.ts @@ -0,0 +1,107 @@ +import { footerInt } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 08.개인하수처리시설 > tab 1. 처리용량별 오수처리시설현황 +export const SewageTreatFactStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 총계 + { name: 'STTY_SM', fieldName: '총계', header: { text: '총계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 오수처리시설 > 하수처리구역 내(m³/일) + { name: 'STTY_ZONE_INNER_SM', fieldName: '계', header: { text: '계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_2', fieldName: '2이하', header: { text: '2이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_3', fieldName: '3~10', header: { text: '3~10' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_11', fieldName: '11~20', header: { text: '11~20' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_21', fieldName: '21~50', header: { text: '21~50' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_51', fieldName: '51~100', header: { text: '51~100' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_101', fieldName: '101~500', header: { text: '101~500' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_501', fieldName: '501이상', header: { text: '501이상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 오수처리시설 > 하수처리구역 외(m³/일) + { name: 'STTY_ZONE_OUTER_SM', fieldName: '계', header: { text: '계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_2', fieldName: '2이하', header: { text: '2이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_3', fieldName: '3~10', header: { text: '3~10' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_11', fieldName: '11~20', header: { text: '11~20' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_21', fieldName: '21~50', header: { text: '21~50' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_51', fieldName: '51~100', header: { text: '51~100' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_101', fieldName: '101~500', header: { text: '101~500' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_501', fieldName: '501이상', header: { text: '501이상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // hidden + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' } }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' } }, + + // 검증 필드 (검증 여부 표시용, 빨간색 표시) + { name: 'CHK_STTY_SM', fieldName: 'CHK_STTY_SM', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_INNER_SM', fieldName: 'CHK_STTY_ZONE_INNER_SM', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_INNER_2', fieldName: 'CHK_STTY_ZONE_INNER_2', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_INNER_3', fieldName: 'CHK_STTY_ZONE_INNER_3', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_INNER_11', fieldName: 'CHK_STTY_ZONE_INNER_11', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_INNER_21', fieldName: 'CHK_STTY_ZONE_INNER_21', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_INNER_51', fieldName: 'CHK_STTY_ZONE_INNER_51', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_INNER_101', fieldName: 'CHK_STTY_ZONE_INNER_101', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_INNER_501', fieldName: 'CHK_STTY_ZONE_INNER_501', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_OUTER_SM', fieldName: 'CHK_STTY_ZONE_OUTER_SM', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_OUTER_2', fieldName: 'CHK_STTY_ZONE_OUTER_2', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_OUTER_3', fieldName: 'CHK_STTY_ZONE_OUTER_3', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_OUTER_11', fieldName: 'CHK_STTY_ZONE_OUTER_11', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_OUTER_21', fieldName: 'CHK_STTY_ZONE_OUTER_21', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_OUTER_51', fieldName: 'CHK_STTY_ZONE_OUTER_51', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_OUTER_101', fieldName: 'CHK_STTY_ZONE_OUTER_101', header: { text: '' } }, + { name: 'CHK_STTY_ZONE_OUTER_501', fieldName: 'CHK_STTY_ZONE_OUTER_501', header: { text: '' } }, + ], + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'STTY_SM', + { + name: 'group_stty', + header: { text: '오수처리시설' }, + items: [ + { + name: 'group_inner', + header: { text: '하수처리구역 내(m³/일)' }, + items: [ + 'STTY_ZONE_INNER_SM', + 'STTY_ZONE_INNER_2', + 'STTY_ZONE_INNER_3', + 'STTY_ZONE_INNER_11', + 'STTY_ZONE_INNER_21', + 'STTY_ZONE_INNER_51', + 'STTY_ZONE_INNER_101', + 'STTY_ZONE_INNER_501' + ] + }, + { + name: 'group_outer', + header: { text: '하수처리구역 외(m³/일)' }, + items: [ + 'STTY_ZONE_OUTER_SM', + 'STTY_ZONE_OUTER_2', + 'STTY_ZONE_OUTER_3', + 'STTY_ZONE_OUTER_11', + 'STTY_ZONE_OUTER_21', + 'STTY_ZONE_OUTER_51', + 'STTY_ZONE_OUTER_101', + 'STTY_ZONE_OUTER_501' + ] + } + ] + }, + 'RMK' + ], + rowStartNum: 3, + fixedColumns: 1, + tabKey: 'sewageTreatFactStatusInp', + tabLabel: '처리용량별 오수처리시설 현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageExcretaRelated/ExcretaRelatedIndustryInpColumn.ts b/apps/st/src/components/util/column/input/sewageExcretaRelated/ExcretaRelatedIndustryInpColumn.ts new file mode 100644 index 000000000..a2b645123 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageExcretaRelated/ExcretaRelatedIndustryInpColumn.ts @@ -0,0 +1,78 @@ +import { footerInt } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 12. 하수 및 분뇨관련산업 > tab 3. 분뇨수집·운반업 +export const ExcretaRelatedIndustryInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 행정코드 (hidden) + { name: 'ADST_DSTR_CD', fieldName: '행정구역코드', header: { text: '행정구역코드' }, visible: false }, + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' }, visible: false }, + { name: 'ADST_DONG', fieldName: '행정동', header: { text: '행정동' }, visible: false }, + { name: 'RGN_NM', fieldName: '지역명', header: { text: '지역명' }, visible: false }, + + // 업체수(개소) + { name: 'ECSCS_SM', fieldName: '업체수(개소)', header: { text: '업체수(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 종사인원(명) + { name: 'ECSCS_BSMN', fieldName: '종사인원(명)', header: { text: '종사인원(명)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 시설(차량) 확보현황(대수) + { name: 'VHCLE_SM', fieldName: '계', header: { text: '계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'THREE_BELOW', fieldName: '3톤이하', header: { text: '3톤이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'FOUR_BELOW', fieldName: '4.5톤이하', header: { text: '4.5톤이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'EIGHT_BELOW', fieldName: '8톤이하', header: { text: '8톤이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ETC', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 수집·운반 실적(m³/년) + { name: 'COLCT_TRSP_ACMSLT', fieldName: '수집·운반 실적(m³/년)', header: { text: '수집·운반 실적(m³/년)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 필드 + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_ECSCS_SM', fieldName: 'CHK_ECSCS_SM', header: { text: 'CHK_ECSCS_SM' }, visible: false }, + { name: 'CHK_ECSCS_BSMN', fieldName: 'CHK_ECSCS_BSMN', header: { text: 'CHK_ECSCS_BSMN' }, visible: false }, + { name: 'CHK_VHCLE_SM', fieldName: 'CHK_VHCLE_SM', header: { text: 'CHK_VHCLE_SM' }, visible: false }, + { name: 'CHK_THREE_BELOW', fieldName: 'CHK_THREE_BELOW', header: { text: 'CHK_THREE_BELOW' }, visible: false }, + { name: 'CHK_FOUR_BELOW', fieldName: 'CHK_FOUR_BELOW', header: { text: 'CHK_FOUR_BELOW' }, visible: false }, + { name: 'CHK_EIGHT_BELOW', fieldName: 'CHK_EIGHT_BELOW', header: { text: 'CHK_EIGHT_BELOW' }, visible: false }, + { name: 'CHK_ETC', fieldName: 'CHK_ETC', header: { text: 'CHK_ETC' }, visible: false }, + { name: 'CHK_COLCT_TRSP_ACMSLT', fieldName: 'CHK_COLCT_TRSP_ACMSLT', header: { text: 'CHK_COLCT_TRSP_ACMSLT' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'ECSCS_SM', + 'ECSCS_BSMN', + { + name: 'group_vehicle_status', + header: { text: '시설(차량) 확보현황(대수)' }, + items: [ + 'VHCLE_SM', + 'THREE_BELOW', + 'FOUR_BELOW', + 'EIGHT_BELOW', + 'ETC' + ] + }, + 'COLCT_TRSP_ACMSLT', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 1, + tabKey: 'excretaRelatedIndustryInp', + tabLabel: '분뇨수집·운반업' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageExcretaRelated/PrivateSewageTreatRelatedIndustryInpColumn.ts b/apps/st/src/components/util/column/input/sewageExcretaRelated/PrivateSewageTreatRelatedIndustryInpColumn.ts new file mode 100644 index 000000000..5e61f6afe --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageExcretaRelated/PrivateSewageTreatRelatedIndustryInpColumn.ts @@ -0,0 +1,86 @@ +import { footerInt } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 12. 하수 및 분뇨관련산업 > tab 4. 개인하수처리관련업 +export const PrivateSewageTreatRelatedIndustryInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 행정코드 (hidden) + { name: 'ADST_DONG', fieldName: '행정동', header: { text: '행정동' }, visible: false }, + { name: 'RGN_NM', fieldName: '지역명', header: { text: '지역명' }, visible: false }, + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' }, visible: false }, + + // 개인하수처리시설 설계·시공업 + { name: 'CNSTRCT_ENTRPS', fieldName: '업소수', header: { text: '업소수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CNSTRCT_BSMN', fieldName: '종사인원(명)', header: { text: '종사인원(명)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 개인하수처리시설 제조업 + { name: 'MNFCTUR_ENTRPS', fieldName: '업소수', header: { text: '업소수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'MNFCTUR_BSMN', fieldName: '종사인원(명)', header: { text: '종사인원(명)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 개인하수처리시설 관리업 + { name: 'MGMT_ENTRPS', fieldName: '업소수', header: { text: '업소수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'MGMT_BSMN', fieldName: '종사인원(명)', header: { text: '종사인원(명)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 필드 + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: 추가 필드 (화면에 미노출이, DB 저장) + { name: 'CNSTRCT_FCT_CNT', fieldName: '설계시공시설개수', header: { text: '설계시공시설개수' }, visible: false }, + { name: 'CNSTRCT_FCT_CPCTY', fieldName: '설계시공시설용량', header: { text: '설계시공시설용량' }, visible: false }, + { name: 'MNFCTUR_STTY_CNT', fieldName: '제조정원', header: { text: '제조정원' }, visible: false }, + { name: 'MNFCTUR_WRRTN_CNT', fieldName: '제조권원', header: { text: '제조권원' }, visible: false }, + { name: 'MGMT_STTY_CNT', fieldName: '관리정원', header: { text: '관리정원' }, visible: false }, + { name: 'MGMT_WRRTN_CNT', fieldName: '관리권원', header: { text: '관리권원' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_CNSTRCT_ENTRPS', fieldName: 'CHK_CNSTRCT_ENTRPS', header: { text: 'CHK_CNSTRCT_ENTRPS' }, visible: false }, + { name: 'CHK_CNSTRCT_BSMN', fieldName: 'CHK_CNSTRCT_BSMN', header: { text: 'CHK_CNSTRCT_BSMN' }, visible: false }, + { name: 'CHK_CNSTRCT_FCT_CNT', fieldName: 'CHK_CNSTRCT_FCT_CNT', header: { text: 'CHK_CNSTRCT_FCT_CNT' }, visible: false }, + { name: 'CHK_CNSTRCT_FCT_CPCTY', fieldName: 'CHK_CNSTRCT_FCT_CPCTY', header: { text: 'CHK_CNSTRCT_FCT_CPCTY' }, visible: false }, + { name: 'CHK_MNFCTUR_ENTRPS', fieldName: 'CHK_MNFCTUR_ENTRPS', header: { text: 'CHK_MNFCTUR_ENTRPS' }, visible: false }, + { name: 'CHK_MNFCTUR_BSMN', fieldName: 'CHK_MNFCTUR_BSMN', header: { text: 'CHK_MNFCTUR_BSMN' }, visible: false }, + { name: 'CHK_MNFCTUR_STTY_CNT', fieldName: 'CHK_MNFCTUR_STTY_CNT', header: { text: 'CHK_MNFCTUR_STTY_CNT' }, visible: false }, + { name: 'CHK_MNFCTUR_WRRTN_CNT', fieldName: 'CHK_MNFCTUR_WRRTN_CNT', header: { text: 'CHK_MNFCTUR_WRRTN_CNT' }, visible: false }, + { name: 'CHK_MGMT_ENTRPS', fieldName: 'CHK_MGMT_ENTRPS', header: { text: 'CHK_MGMT_ENTRPS' }, visible: false }, + { name: 'CHK_MGMT_BSMN', fieldName: 'CHK_MGMT_BSMN', header: { text: 'CHK_MGMT_BSMN' }, visible: false }, + { name: 'CHK_MGMT_STTY_CNT', fieldName: 'CHK_MGMT_STTY_CNT', header: { text: 'CHK_MGMT_STTY_CNT' }, visible: false }, + { name: 'CHK_MGMT_WRRTN_CNT', fieldName: 'CHK_MGMT_WRRTN_CNT', header: { text: 'CHK_MGMT_WRRTN_CNT' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + { + name: 'group_design_construct', + header: { text: '개인하수처리시설 설계·시공업' }, + items: ['CNSTRCT_ENTRPS', 'CNSTRCT_BSMN'] + }, + { + name: 'group_manufacture', + header: { text: '개인하수처리시설 제조업' }, + items: ['MNFCTUR_ENTRPS', 'MNFCTUR_BSMN'] + }, + { + name: 'group_management', + header: { text: '개인하수처리시설 관리업' }, + items: ['MGMT_ENTRPS', 'MGMT_BSMN'] + }, + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 1, + tabKey: 'privateSewageTreatRelatedIndustryInp', + tabLabel: '개인하수처리관련업' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageExcretaRelated/PublicInstitutionExcretaIndustryInpColumn.ts b/apps/st/src/components/util/column/input/sewageExcretaRelated/PublicInstitutionExcretaIndustryInpColumn.ts new file mode 100644 index 000000000..8df679707 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageExcretaRelated/PublicInstitutionExcretaIndustryInpColumn.ts @@ -0,0 +1,90 @@ +import { footerInt } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 12. 하수 및 분뇨관련산업 > tab 2. 공공기관 분뇨분야 +export const PublicInstitutionExcretaIndustryInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 행정코드 (hidden) + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' }, visible: false }, + + // 직제 + { name: 'OCGNZ', fieldName: '직 제', header: { text: '직 제' } }, + + // 직원총수 + { name: 'TOT_WTR_QRM', fieldName: '직원총수', header: { text: '직원총수' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 행정직 + { name: 'ADMINIST_JSSFC', fieldName: '행정직', header: { text: '행정직' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 기술직 + { name: 'TCHNLGY_JSSFC_SM', fieldName: '계', header: { text: '계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ENGRK_JSSFC', fieldName: '토목', header: { text: '토목' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'MCHN_JSSFC', fieldName: '기계', header: { text: '기계' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ELCTY_JSSFC', fieldName: '전기', header: { text: '전기' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CHMSTRY_JSSFC', fieldName: '화공', header: { text: '화공' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ENVRN_JSSFC', fieldName: '환경', header: { text: '환경' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'TCHNLGY_ETC', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 기능직 (hidden) + { name: 'TCNSRV', fieldName: '기능직', header: { text: '기능직' }, visible: false }, + + // 기타 + { name: 'ETC', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 필드 + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_OCGNZ', fieldName: 'CHK_OCGNZ', header: { text: 'CHK_OCGNZ' }, visible: false }, + { name: 'CHK_TOT_WTR_QRM', fieldName: 'CHK_TOT_WTR_QRM', header: { text: 'CHK_TOT_WTR_QRM' }, visible: false }, + { name: 'CHK_ADMINIST_JSSFC', fieldName: 'CHK_ADMINIST_JSSFC', header: { text: 'CHK_ADMINIST_JSSFC' }, visible: false }, + { name: 'CHK_TCHNLGY_JSSFC_SM', fieldName: 'CHK_TCHNLGY_JSSFC_SM', header: { text: 'CHK_TCHNLGY_JSSFC_SM' }, visible: false }, + { name: 'CHK_ENGRK_JSSFC', fieldName: 'CHK_ENGRK_JSSFC', header: { text: 'CHK_ENGRK_JSSFC' }, visible: false }, + { name: 'CHK_MCHN_JSSFC', fieldName: 'CHK_MCHN_JSSFC', header: { text: 'CHK_MCHN_JSSFC' }, visible: false }, + { name: 'CHK_ELCTY_JSSFC', fieldName: 'CHK_ELCTY_JSSFC', header: { text: 'CHK_ELCTY_JSSFC' }, visible: false }, + { name: 'CHK_CHMSTRY_JSSFC', fieldName: 'CHK_CHMSTRY_JSSFC', header: { text: 'CHK_CHMSTRY_JSSFC' }, visible: false }, + { name: 'CHK_ENVRN_JSSFC', fieldName: 'CHK_ENVRN_JSSFC', header: { text: 'CHK_ENVRN_JSSFC' }, visible: false }, + { name: 'CHK_TCHNLGY_ETC', fieldName: 'CHK_TCHNLGY_ETC', header: { text: 'CHK_TCHNLGY_ETC' }, visible: false }, + { name: 'CHK_TCNSRV', fieldName: 'CHK_TCNSRV', header: { text: 'CHK_TCNSRV' }, visible: false }, + { name: 'CHK_ETC', fieldName: 'CHK_ETC', header: { text: 'CHK_ETC' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'OCGNZ', + 'TOT_WTR_QRM', + 'ADMINIST_JSSFC', + { + name: 'group_technology', + header: { text: '기술직' }, + items: [ + 'TCHNLGY_JSSFC_SM', + 'ENGRK_JSSFC', + 'MCHN_JSSFC', + 'ELCTY_JSSFC', + 'CHMSTRY_JSSFC', + 'ENVRN_JSSFC', + 'TCHNLGY_ETC' + ] + }, + 'ETC', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 0, + tabKey: 'publicInstitutionExcretaIndustryInp', + tabLabel: '공공기관 분뇨분야' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageExcretaRelated/PublicInstitutionSewerIndustryInpColumn.ts b/apps/st/src/components/util/column/input/sewageExcretaRelated/PublicInstitutionSewerIndustryInpColumn.ts new file mode 100644 index 000000000..9df115260 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageExcretaRelated/PublicInstitutionSewerIndustryInpColumn.ts @@ -0,0 +1,90 @@ +import { footerInt } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 12. 하수 및 분뇨관련산업 > tab 1. 공공기관 하수분야 +export const PublicInstitutionSewerIndustryInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 행정코드 (hidden) + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' }, visible: false }, + + // 직제 + { name: 'OCGNZ', fieldName: '직 제', header: { text: '직 제' } }, + + // 직원총수 + { name: 'TOT_WTR_QRM', fieldName: '직원총수', header: { text: '직원총수' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 행정직 + { name: 'ADMINIST_JSSFC', fieldName: '행정직', header: { text: '행정직' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 기술직 + { name: 'TCHNLGY_JSSFC_SM', fieldName: '계', header: { text: '계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ENGRK_JSSFC', fieldName: '토목', header: { text: '토목' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'MCHN_JSSFC', fieldName: '기계', header: { text: '기계' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ELCTY_JSSFC', fieldName: '전기', header: { text: '전기' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CHMSTRY_JSSFC', fieldName: '화공', header: { text: '화공' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ENVRN_JSSFC', fieldName: '환경', header: { text: '환경' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'TCHNLGY_ETC', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 기능직 (hidden) + { name: 'TCNSRV', fieldName: '기능직', header: { text: '기능직' }, visible: false }, + + // 기타 + { name: 'ETC', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 필드 + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_OCGNZ', fieldName: 'CHK_OCGNZ', header: { text: 'CHK_OCGNZ' }, visible: false }, + { name: 'CHK_TOT_WTR_QRM', fieldName: 'CHK_TOT_WTR_QRM', header: { text: 'CHK_TOT_WTR_QRM' }, visible: false }, + { name: 'CHK_ADMINIST_JSSFC', fieldName: 'CHK_ADMINIST_JSSFC', header: { text: 'CHK_ADMINIST_JSSFC' }, visible: false }, + { name: 'CHK_TCHNLGY_JSSFC_SM', fieldName: 'CHK_TCHNLGY_JSSFC_SM', header: { text: 'CHK_TCHNLGY_JSSFC_SM' }, visible: false }, + { name: 'CHK_ENGRK_JSSFC', fieldName: 'CHK_ENGRK_JSSFC', header: { text: 'CHK_ENGRK_JSSFC' }, visible: false }, + { name: 'CHK_MCHN_JSSFC', fieldName: 'CHK_MCHN_JSSFC', header: { text: 'CHK_MCHN_JSSFC' }, visible: false }, + { name: 'CHK_ELCTY_JSSFC', fieldName: 'CHK_ELCTY_JSSFC', header: { text: 'CHK_ELCTY_JSSFC' }, visible: false }, + { name: 'CHK_CHMSTRY_JSSFC', fieldName: 'CHK_CHMSTRY_JSSFC', header: { text: 'CHK_CHMSTRY_JSSFC' }, visible: false }, + { name: 'CHK_ENVRN_JSSFC', fieldName: 'CHK_ENVRN_JSSFC', header: { text: 'CHK_ENVRN_JSSFC' }, visible: false }, + { name: 'CHK_TCHNLGY_ETC', fieldName: 'CHK_TCHNLGY_ETC', header: { text: 'CHK_TCHNLGY_ETC' }, visible: false }, + { name: 'CHK_TCNSRV', fieldName: 'CHK_TCNSRV', header: { text: 'CHK_TCNSRV' }, visible: false }, + { name: 'CHK_ETC', fieldName: 'CHK_ETC', header: { text: 'CHK_ETC' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'OCGNZ', + 'TOT_WTR_QRM', + 'ADMINIST_JSSFC', + { + name: 'group_technology', + header: { text: '기술직' }, + items: [ + 'TCHNLGY_JSSFC_SM', + 'ENGRK_JSSFC', + 'MCHN_JSSFC', + 'ELCTY_JSSFC', + 'CHMSTRY_JSSFC', + 'ENVRN_JSSFC', + 'TCHNLGY_ETC' + ] + }, + 'ETC', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 1, + tabKey: 'publicInstitutionSewerIndustryInp', + tabLabel: '공공기관 하수분야' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageExcretaSlurge/DigestorOperatingStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewageExcretaSlurge/DigestorOperatingStatusInpColumn.ts new file mode 100644 index 000000000..c6b70ea6c --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageExcretaSlurge/DigestorOperatingStatusInpColumn.ts @@ -0,0 +1,91 @@ +import { footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 11. 하수 및 분뇨찌꺼기(슬러지)처리 > tab 2. 소화조 운영현황 +export const DigestorOperatingStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO_CD', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'ADST_CD', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 하수처리장명 + { name: 'BSC_FCT_NM', fieldName: '하수처리장명', header: { text: '하수처리장명' }, editable: false }, + + // 소화조 운영현황 + { name: 'DGSTR_FNNC', fieldName: '소화조 유/무(Y/N)선택', header: { text: '소화조 유/무(Y/N)선택' } }, + { name: 'DGSTR_CPC', fieldName: '설계용량(m³)', header: { text: '설계용량(m³)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_OPR_CPC', fieldName: '실제운전용량(m³)', header: { text: '실제운전용량(m³)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_IN', fieldName: '투입량(m³/일)', header: { text: '투입량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_TS', fieldName: '투입 TS 농도(%)', header: { text: '투입 TS 농도(%)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_YRSTP_RN_DYN', fieldName: '가동일수(연간)', header: { text: '가동일수(연간)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_OCCUR_GAS', fieldName: '발생가스량(m³/일)', header: { text: '발생가스량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 소화조 운영현황 > 소화가스 이용현황(m³/일) + { name: 'DGSTR_SM', fieldName: '계', header: { text: '계' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_SLE', fieldName: '판매', header: { text: '판매' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_ELTGNR', fieldName: '발전', header: { text: '발전' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_ONSLF', fieldName: '자체활용', header: { text: '자체활용' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DGSTR_ETC', fieldName: '기타(CNG등)', header: { text: '기타(CNG등)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 소화조 운영현황 > 잉여가스량 + { name: 'DGSTR_GAS', fieldName: '잉여가스량(m³/일)', header: { text: '잉여가스량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'DGSTR_RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: Check fields for change detection + { name: 'CHK_DGSTR_FNNC', fieldName: 'CHK_DGSTR_FNNC', header: { text: 'CHK_DGSTR_FNNC' }, visible: false }, + { name: 'CHK_DGSTR_IN', fieldName: 'CHK_DGSTR_IN', header: { text: 'CHK_DGSTR_IN' }, visible: false }, + { name: 'CHK_DGSTR_TS', fieldName: 'CHK_DGSTR_TS', header: { text: 'CHK_DGSTR_TS' }, visible: false }, + { name: 'CHK_DGSTR_YRSTP_RN_DYN', fieldName: 'CHK_DGSTR_YRSTP_RN_DYN', header: { text: 'CHK_DGSTR_YRSTP_RN_DYN' }, visible: false }, + { name: 'CHK_DGSTR_OCCUR_GAS', fieldName: 'CHK_DGSTR_OCCUR_GAS', header: { text: 'CHK_DGSTR_OCCUR_GAS' }, visible: false }, + { name: 'CHK_DGSTR_CPC', fieldName: 'CHK_DGSTR_CPC', header: { text: 'CHK_DGSTR_CPC' }, visible: false }, + { name: 'CHK_DGSTR_OPR_CPC', fieldName: 'CHK_DGSTR_OPR_CPC', header: { text: 'CHK_DGSTR_OPR_CPC' }, visible: false }, + { name: 'CHK_DGSTR_SM', fieldName: 'CHK_DGSTR_SM', header: { text: 'CHK_DGSTR_SM' }, visible: false }, + { name: 'CHK_DGSTR_SLE', fieldName: 'CHK_DGSTR_SLE', header: { text: 'CHK_DGSTR_SLE' }, visible: false }, + { name: 'CHK_DGSTR_ELTGNR', fieldName: 'CHK_DGSTR_ELTGNR', header: { text: 'CHK_DGSTR_ELTGNR' }, visible: false }, + { name: 'CHK_DGSTR_ONSLF', fieldName: 'CHK_DGSTR_ONSLF', header: { text: 'CHK_DGSTR_ONSLF' }, visible: false }, + { name: 'CHK_DGSTR_ETC', fieldName: 'CHK_DGSTR_ETC', header: { text: 'CHK_DGSTR_ETC' }, visible: false }, + { name: 'CHK_DGSTR_GAS', fieldName: 'CHK_DGSTR_GAS', header: { text: 'CHK_DGSTR_GAS' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO_CD', 'ADST_CD'] + }, + 'BSC_FCT_NM', + { + name: 'group_digestor_operating', + header: { text: '소화조 운영현황' }, + items: [ + 'DGSTR_FNNC', + 'DGSTR_CPC', + 'DGSTR_OPR_CPC', + 'DGSTR_IN', + 'DGSTR_TS', + 'DGSTR_YRSTP_RN_DYN', + 'DGSTR_OCCUR_GAS', + { + name: 'group_gas_usage', + header: { text: '소화가스 이용현황(m³/일)' }, + items: [ + 'DGSTR_SM', + 'DGSTR_SLE', + 'DGSTR_ELTGNR', + 'DGSTR_ONSLF', + 'DGSTR_ETC' + ] + }, + 'DGSTR_GAS' + ] + }, + 'DGSTR_RMK' + ], + + rowStartNum: 3, + fixedColumns: 0, + tabKey: 'digestorOperatingStatusInp', + tabLabel: '소화조 운영현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageExcretaSlurge/ExcretaSlurgeProcessingStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewageExcretaSlurge/ExcretaSlurgeProcessingStatusInpColumn.ts new file mode 100644 index 000000000..7edfb7a40 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageExcretaSlurge/ExcretaSlurgeProcessingStatusInpColumn.ts @@ -0,0 +1,83 @@ +import { footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 11.하수 및 분뇨찌꺼기(슬러지) 처리 > tab 4. 분뇨찌꺼기(슬러지)처리 현황 +export const ExcretaSlurgeProcessingStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO_CD', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'ADST_CD', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 분뇨처리장명 + { name: 'ECSCS_NM', fieldName: '분 뇨 처리장명', header: { text: '분 뇨 처리장명' }, editable: false }, + + // 발생량 + { name: 'OCTY', fieldName: '발생량 (A)=(B)+(C)', header: { text: '발생량 (A)=(B)+(C)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 처 분 량(톤/년) + { name: 'PROCESS_CPCTY_SM', fieldName: '계(B)', header: { text: '계(B)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RUSE', fieldName: '재활용', header: { text: '재활용' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'LAND_RCLM', fieldName: '육상매립', header: { text: '육상매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'INCNR', fieldName: '소각', header: { text: '소각' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'OCEAN_DPSL', fieldName: '해양투기', header: { text: '해양투기' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'FUEL', fieldName: '연료화', header: { text: '연료화' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'ETC', fieldName: '기타', header: { text: '기타' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 미처분량(이월량)(C) + { name: 'CYFD_CPCTY', fieldName: '미처분량(이월량)(C)', header: { text: '미처분량(이월량)(C)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 타시설연계여부 + { name: 'OUT_BSC_FCT_NM', fieldName: '타시설연계여부', header: { text: '타시설연계여부' } }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: Check fields for change detection + { name: 'CHK_ECSCS_NM', fieldName: 'CHK_ECSCS_NM', header: { text: 'CHK_ECSCS_NM' }, visible: false }, + { name: 'CHK_OCTY', fieldName: 'CHK_OCTY', header: { text: 'CHK_OCTY' }, visible: false }, + { name: 'CHK_PROCESS_CPCTY_SM', fieldName: 'CHK_PROCESS_CPCTY_SM', header: { text: 'CHK_PROCESS_CPCTY_SM' }, visible: false }, + { name: 'CHK_RUSE', fieldName: 'CHK_RUSE', header: { text: 'CHK_RUSE' }, visible: false }, + { name: 'CHK_LAND_RCLM', fieldName: 'CHK_LAND_RCLM', header: { text: 'CHK_LAND_RCLM' }, visible: false }, + { name: 'CHK_INCNR', fieldName: 'CHK_INCNR', header: { text: 'CHK_INCNR' }, visible: false }, + { name: 'CHK_OCEAN_DPSL', fieldName: 'CHK_OCEAN_DPSL', header: { text: 'CHK_OCEAN_DPSL' }, visible: false }, + { name: 'CHK_FUEL', fieldName: 'CHK_FUEL', header: { text: 'CHK_FUEL' }, visible: false }, + { name: 'CHK_ETC', fieldName: 'CHK_ETC', header: { text: 'CHK_ETC' }, visible: false }, + { name: 'CHK_CYFD_CPCTY', fieldName: 'CHK_CYFD_CPCTY', header: { text: 'CHK_CYFD_CPCTY' }, visible: false }, + { name: 'CHK_OUT_BSC_FCT_NM', fieldName: 'CHK_OUT_BSC_FCT_NM', header: { text: 'CHK_OUT_BSC_FCT_NM' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO_CD', 'ADST_CD'] + }, + 'ECSCS_NM', + 'OCTY', + { + name: 'group_process_amount', + header: { text: '처 분 량(톤/년)' }, + items: [ + 'PROCESS_CPCTY_SM', + 'RUSE', + 'LAND_RCLM', + 'INCNR', + 'OCEAN_DPSL', + 'FUEL', + 'ETC' + ] + }, + 'CYFD_CPCTY', + 'OUT_BSC_FCT_NM', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 2, + tabKey: 'excretaSlurgeProcessingStatusInp', + tabLabel: '분뇨찌꺼기(슬러지)처리현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageExcretaSlurge/SewageSlurgeProcessingFacStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewageExcretaSlurge/SewageSlurgeProcessingFacStatusInpColumn.ts new file mode 100644 index 000000000..dedf4af98 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageExcretaSlurge/SewageSlurgeProcessingFacStatusInpColumn.ts @@ -0,0 +1,69 @@ +import { footerInt, footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 11.하수 및 분뇨찌꺼기(슬러지) 처리 > tab 3. 하수찌꺼기 처리시설 운영현황 +export const SewageSlurgeProcessingFacStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO_CD', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'ADST_CD', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } }, + + // 찌꺼기처리시설명 + { name: 'SLG_FCT_NM', fieldName: '찌꺼기처리시설명', header: { text: '찌꺼기처리시설명' } }, + + // 처리시설 운영현황 + { name: 'TRT_METHOD', fieldName: '처리방식', header: { text: '처리방식' } }, + { name: 'SLG_FCT_CPC', fieldName: '시설용량(톤/일)', header: { text: '시설용량(톤/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'OPR_CPC', fieldName: '연간처리량(톤/년)', header: { text: '연간처리량(톤/년)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'ODY_RN_TIME', fieldName: '일평균가동시간(1~24)', header: { text: '일평균가동시간(1~24)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'YRSTP_RN_DYN', fieldName: '연중 가동일(1~330)', header: { text: '연중 가동일(1~330)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'OPR_RT', fieldName: '가동율(%)', header: { text: '가동율(%)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'SLG_FCT_RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 기본 정보 + { name: 'STPN_SEQ', fieldName: 'STPN_SEQ', header: { text: 'STPN_SEQ' }, visible: false }, + { name: 'BSC_FCT_NM', fieldName: 'BSC_FCT_NM', header: { text: 'BSC_FCT_NM' }, visible: false }, + { name: 'YR', fieldName: 'YR', header: { text: 'YR' }, visible: false }, + { name: 'ODR', fieldName: 'ODR', header: { text: 'ODR' }, visible: false }, + { name: 'BSNM_CD', fieldName: 'BSNM_CD', header: { text: 'BSNM_CD' }, visible: false }, + { name: 'BSC_FCT_CD', fieldName: 'BSC_FCT_CD', header: { text: 'BSC_FCT_CD' }, visible: false }, + + // Hidden: Check fields for change detection + { name: 'CHK_SLG_FCT_NM', fieldName: 'CHK_SLG_FCT_NM', header: { text: 'CHK_SLG_FCT_NM' }, visible: false }, + { name: 'CHK_TRT_METHOD', fieldName: 'CHK_TRT_METHOD', header: { text: 'CHK_TRT_METHOD' }, visible: false }, + { name: 'CHK_SLG_FCT_CPC', fieldName: 'CHK_SLG_FCT_CPC', header: { text: 'CHK_SLG_FCT_CPC' }, visible: false }, + { name: 'CHK_OPR_CPC', fieldName: 'CHK_OPR_CPC', header: { text: 'CHK_OPR_CPC' }, visible: false }, + { name: 'CHK_ODY_RN_TIME', fieldName: 'CHK_ODY_RN_TIME', header: { text: 'CHK_ODY_RN_TIME' }, visible: false }, + { name: 'CHK_YRSTP_RN_DYN', fieldName: 'CHK_YRSTP_RN_DYN', header: { text: 'CHK_YRSTP_RN_DYN' }, visible: false }, + { name: 'CHK_OPR_RT', fieldName: 'CHK_OPR_RT', header: { text: 'CHK_OPR_RT' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO_CD', 'ADST_CD'] + }, + 'SLG_FCT_NM', + { + name: 'group_processing_fac_operating', + header: { text: '처리시설 운영현황' }, + items: [ + 'TRT_METHOD', + 'SLG_FCT_CPC', + 'OPR_CPC', + 'ODY_RN_TIME', + 'YRSTP_RN_DYN', + 'OPR_RT' + ] + }, + 'SLG_FCT_RMK' + ], + + rowStartNum: 2, + fixedColumns: 1, + tabKey: 'sewageSlurgeProcessingFacStatusInp', + tabLabel: '하수찌꺼기 처리시설 운영현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageExcretaSlurge/SlurgeProcessingFacStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewageExcretaSlurge/SlurgeProcessingFacStatusInpColumn.ts new file mode 100644 index 000000000..364c4e378 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageExcretaSlurge/SlurgeProcessingFacStatusInpColumn.ts @@ -0,0 +1,216 @@ +import { footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 11. 하수 및 분뇨찌꺼기(슬러지)처리 > tab 1: 찌꺼기(슬러지)처리시설현황 +export const SlurgeProcessingFacStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO_CD', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'ADST_CD', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } }, + + // 하수처리장명 + { name: 'BSC_FCT_NM', fieldName: '하수처리장명', header: { text: '하수처리장명' }, }, + + // 찌꺼기발생량(톤/년, 탈수기준) + { name: 'TOT_AMNT', fieldName: '합계', header: { text: '합계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'P_AMNT', fieldName: '자체', header: { text: '자체' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'OUT_AMNT', fieldName: '외부유입량', header: { text: '외부유입량' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 이송처리장 + { name: 'OUT_FCT_NM', fieldName: '이송처리장', header: { text: '이송처리장' } }, + + // 이송처리량 - 쿼리에서 못찾음 (임의) + { name: 'a', fieldName: '이송처리량(m³/년)', header: { text: '이송처리량(m³/년)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 함수율 + { name: 'DSP_MOIRAT', fieldName: '함수율(%, 탈수기준)', header: { text: '함수율(%, 탈수기준)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 찌꺼기처리량합계 + { name: 'DSP_SM', fieldName: '찌꺼기처리량합계(톤/년)', header: { text: '찌꺼기처리량합계(톤/년)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 자체 찌꺼기 처리량 > 자체찌꺼기처리량소계 + { name: 'DSP_SELF_SM', fieldName: '자체찌꺼기처리량소계', header: { text: '자체찌꺼기처리량소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 자체 찌꺼기 처리량 > 매립 + { name: 'O_DSP_RCLM', fieldName: '매립', header: { text: '매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 자체 찌꺼기 처리량 > 소각(1차) + { name: 'O_DSP_INCNR', fieldName: '소각(1차)', header: { text: '소각(1차)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 자체 찌꺼기 처리량 > 소각 후 처리(2차) - 쿼리에 없음 (임의 생성) + { name: 'b1', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'b2', fieldName: '매립', header: { text: '매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'b3', fieldName: '제품원료', header: { text: '제품원료' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'b4', fieldName: '복토재', header: { text: '복토재' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'b5', fieldName: '시설(업체명)', header: { text: '시설(업체명)' } }, + + // 자체 찌꺼기 처리량 > 고화(1차) - 쿼리에 없음 (임의 생성) + { name: 'c1', fieldName: '고화(1차)', header: { text: '고화(1차)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 자체 찌꺼기 처리량 > 고화 후 처리(2차) - 쿼리에 없음 (임의 생성) + { name: 'c2', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'c3', fieldName: '매립', header: { text: '매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'c4', fieldName: '복토재', header: { text: '복토재' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'c5', fieldName: '시설(업체명)', header: { text: '시설(업체명)' } }, + + // 자체 찌꺼기 처리량 > 건조(1차) + { name: 'DSP_DESIC', fieldName: '건조(1차)', header: { text: '건조(1차)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 자체 찌꺼기 처리량 > 건조 후 처리(2차) - 쿼리에 없음 + { name: 'd1', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'd2', fieldName: '매립', header: { text: '매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'd3', fieldName: '소각', header: { text: '소각' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'd4', fieldName: '연료', header: { text: '연료' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'd5', fieldName: '제품원료', header: { text: '제품원료' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'd6', fieldName: '복토재', header: { text: '복토재' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'd7', fieldName: '퇴비화', header: { text: '퇴비화' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'd8', fieldName: '시설(업체명)', header: { text: '시설(업체명)' }, editable: true }, + + // 자체 찌꺼기 처리량 > 탄화(1차) - 쿼리에 없음 (임의 생성) + { name: 'e1', fieldName: '탄화(1차)', header: { text: '탄화(1차)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 자체 찌꺼기 처리량 > 탄화 후 처리(2차) - 쿼리에 없음 (임의 생성) + { name: 'e2', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'e3', fieldName: '소각', header: { text: '소각' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'e4', fieldName: '연료', header: { text: '연료' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'e5', fieldName: '시설(업체명)', header: { text: '시설(업체명)' } }, + + // 자체 찌꺼기 처리량 > 퇴비화 - 쿼리에 없음 (임의 생성) + { name: 'f1', fieldName: '퇴비화', header: { text: '퇴비화' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 자체 찌꺼기 처리량 > 퇴비화 > 시설(업체명) - 쿼리에 없음 (임의 생성) + { name: 'f2', fieldName: '시설(업체명)', header: { text: '시설(업체명)' } }, + + // 외부위탁 처리량(톤/년) + { name: 'DSP_CONSIGNMENT', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'g1', fieldName: '매립', header: { text: '매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'g2', fieldName: '소각', header: { text: '소각' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'g3', fieldName: '연료', header: { text: '연료' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'g4', fieldName: '제품원료', header: { text: '제품원료' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'g5', fieldName: '복토재', header: { text: '복토재' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'g6', fieldName: '퇴비화', header: { text: '퇴비화' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'g7', fieldName: '시설(업체명)', header: { text: '시설(업체명)' } }, + + // 수도권광역위탁처리량 + { name: 'DSP_WIDE', fieldName: '수도권광역위탁처리량(톤/년)', header: { text: '수도권광역위탁처리량(톤/년)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: Check fields + { name: 'CHK_TOT_AMNT', fieldName: 'CHK_TOT_AMNT', header: { text: 'CHK_TOT_AMNT' }, visible: false }, + { name: 'CHK_P_AMNT', fieldName: 'CHK_P_AMNT', header: { text: 'CHK_P_AMNT' }, visible: false }, + { name: 'CHK_OUT_AMNT', fieldName: 'CHK_OUT_AMNT', header: { text: 'CHK_OUT_AMNT' }, visible: false }, + { name: 'CHK_DSP_MOIRAT', fieldName: 'CHK_DSP_MOIRAT', header: { text: 'CHK_DSP_MOIRAT' }, visible: false }, + { name: 'CHK_DSP_SM', fieldName: 'CHK_DSP_SM', header: { text: 'CHK_DSP_SM' }, visible: false }, + { name: 'CHK_DSP_SELF_SM', fieldName: 'CHK_DSP_SELF_SM', header: { text: 'CHK_DSP_SELF_SM' }, visible: false }, + { name: 'CHK_O_DSP_RCLM', fieldName: 'CHK_O_DSP_RCLM', header: { text: 'CHK_O_DSP_RCLM' }, visible: false }, + { name: 'CHK_O_DSP_INCNR', fieldName: 'CHK_O_DSP_INCNR', header: { text: 'CHK_O_DSP_INCNR' }, visible: false }, + { name: 'CHK_DSP_DESIC', fieldName: 'CHK_DSP_DESIC', header: { text: 'CHK_DSP_DESIC' }, visible: false }, + { name: 'CHK_DSP_CONSIGNMENT', fieldName: 'CHK_DSP_CONSIGNMENT', header: { text: 'CHK_DSP_CONSIGNMENT' }, visible: false }, + { name: 'CHK_DSP_WIDE', fieldName: 'CHK_DSP_WIDE', header: { text: 'CHK_DSP_WIDE' }, visible: false }, + { name: 'CHK_OUT_FCT_NM', fieldName: 'CHK_OUT_FCT_NM', header: { text: 'CHK_OUT_FCT_NM' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO_CD', 'ADST_CD'] + }, + 'BSC_FCT_NM', + { + name: 'group_occur_amount', + header: { text: '찌꺼기발생량(톤/년, 탈수기준)' }, + items: [ + 'TOT_AMNT', + 'P_AMNT', + 'OUT_AMNT' + ] + }, + 'OUT_FCT_NM', + 'a', + 'DSP_MOIRAT', + 'DSP_SM', + { + name: 'group_self_treatment', + header: { text: '자체 찌꺼기 처리량(톤/년)' }, + items: [ + 'DSP_SELF_SM', + 'O_DSP_RCLM', + 'O_DSP_INCNR', + { + name: 'group_incinerate_2nd', + header: { text: '소각 후 처리(2차)' }, + items: [ + 'b1', + 'b2', + 'b3', + 'b4', + 'b5' + ] + }, + 'c1', + { + name: 'group_solidify_2nd', + header: { text: '고화 후 처리(2차)' }, + items: [ + 'c2', + 'c3', + 'c4', + 'c5' + ] + }, + 'DSP_DESIC', + { + name: 'group_drying_2nd', + header: { text: '건조 후 처리(2차)' }, + items: [ + 'd1', + 'd2', + 'd3', + 'd4', + 'd5', + 'd6', + 'd7', + 'd8' + ] + }, + 'e1', + { + name: 'group_carbonize_2nd', + header: { text: '탄화 후 처리(2차)' }, + items: [ + 'e2', + 'e3', + 'e4', + 'e5' + ] + }, + 'f1', + 'f2' + ] + }, + { + name: 'group_external_treatment', + header: { text: '외부위탁 처리량(톤/년)' }, + items: [ + 'DSP_CONSIGNMENT', + 'g1', + 'g2', + 'g3', + 'g4', + 'g5', + 'g6', + 'g7' + ] + }, + 'DSP_WIDE', + 'RMK' + ], + + rowStartNum: 3, + fixedColumns: 2, + tabKey: 'slurgeProcessingFacStatusInp', + tabLabel: '찌꺼기(슬러지)처리시설현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipe/ConnectionStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipe/ConnectionStatusInpColumn.ts new file mode 100644 index 000000000..03a3157da --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipe/ConnectionStatusInpColumn.ts @@ -0,0 +1,63 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 02.하수관로 > tab 6. 시설별 현황관리 +// Tab 6-1: 행정구역별 연결 현황 (오른쪽 그리드) +export const AdminAreaConnectionInpColumn = { + columns: [ + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' } }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'adstDong', fieldName: '행정구역명', header: { text: '행정구역명' } }, + // 연결여부 + { name: 'iscan', fieldName: '연결여부', header: { text: '연결여부' } }, + // 연결하수처리장 + { name: 'bscFctNm', fieldName: '연결하수처리장', header: { text: '연결하수처리장' } }, + ], + columnLayout: [ + { + name: 'adminArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'sgg', 'adstDong'], + }, + 'iscan', + 'bscFctNm', + ], + rowStartNum: 2, + fixedColumns: 1, + tabKey: 'adminAreaConnectionInp', + tabLabel: '행정구역별 연결 현황' +}; + +// Tab 6-2: 하수처리장별 연결 현황 (왼쪽 그리드) +export const TreatPlantConnectionInpColumn = { + columns: [ + // 하수처리장 정보 + { name: 'bscFctNm', fieldName: '하수처리장명', header: { text: '하수처리장명' } }, + { name: 'fctCpc', fieldName: '용량', header: { text: '용량' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'bscFctCd', fieldName: '하수처리장코드', header: { text: '하수처리장코드' } }, + // 연결여부 + { name: 'iscan', fieldName: '연결여부', header: { text: '연결여부' } }, + // 연결지역 + { name: 'nmlist', fieldName: '연결지역', header: { text: '연결지역' } }, + ], + columnLayout: [ + 'bscFctNm', + 'fctCpc', + 'bscFctCd', + 'iscan', + 'nmlist', + ], + rowStartNum: 1, + fixedColumns: 1, + tabKey: 'treatmentPlantConnectionInp', + tabLabel: '하수처리장별 연결 현황' +}; + +export const ConnectionStatusInpColumn = { + tabKey: 'treatmentPlantConnectionInp', + tabLabel: '시설별 현황 관리', + isSplitGrid: true, + left: AdminAreaConnectionInpColumn, + right: TreatPlantConnectionInpColumn, +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipe/FactInstallStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipe/FactInstallStatusInpColumn.ts new file mode 100644 index 000000000..213ceb818 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipe/FactInstallStatusInpColumn.ts @@ -0,0 +1,142 @@ +import { footerInt, footerDecimal2, footerDecimal3 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 02.하수관로 > tab 2. 시설별 설치현황 + +export const FactInstallStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, editable: false }, + + // 하수처리장 정보 + { name: 'bscFctNm', fieldName: '하수처리장명', header: { text: '하수처리장명' }, footer: { text: '합계' }, editable: false }, + { name: 'fctCpc', fieldName: '하수처리시설용량(m³/일)', header: { text: '하수처리시설용량(m³/일)' }, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 처리구역면적(km²) + { name: 'procZoneSm', fieldName: '합계', header: { text: '합계' }, footer: footerDecimal3, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'cmbnProcZoneAr', fieldName: '합류식', header: { text: '합류식' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'sprtProcZoneAr', fieldName: '분류식', header: { text: '분류식' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + + // 분류식화율 + { name: 'sprtRt', fieldName: '분류식화율', header: { text: '분류식화율' }, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 배수설비(개소) + { name: 'drngEqpSm', fieldName: '합계', header: { text: '합계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'cmbnDrngEqp', fieldName: '합류식', header: { text: '합류식' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sprtDrngEqpSm', fieldName: '소계', header: { text: '소계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sprtDrngEqpCnnc', fieldName: '연결', header: { text: '연결' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sprtDrngEqpDcnnc', fieldName: '미연결', header: { text: '미연결' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수관로 > 총시설연장 + { name: 'piplFcltyExtn', fieldName: '총시설연장(m)', header: { text: '총시설연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 하수관로 > 차집/오수간선(m) + { name: 'icgMnnSm', fieldName: '합계', header: { text: '합계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'icgExtn', fieldName: '차집', header: { text: '차집' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'mnnExtn', fieldName: '오수 간선', header: { text: '오수 간선' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 하수관로 > 토실/토구(개소) > 합류식 + { name: 'cmbnSoilholeSite', fieldName: '우수토실', header: { text: '우수토실' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수관로 > 토실/토구(개소) > 분류식 + { name: 'sprtSoilholeSite', fieldName: '우수토실', header: { text: '우수토실' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'sprtSoilspllSite', fieldName: '우수토구', header: { text: '우수토구' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 하수관로 > 지선(m) + { name: 'brnchlnSm', fieldName: '합계', header: { text: '합계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'cmbnBrnchlnExtn', fieldName: '합류식', header: { text: '합류식' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 하수관로 > 지선(m) > 분류식 + { name: 'rainwtrBrnchlnExtn', fieldName: '우수', header: { text: '우수' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'pltwtrBrnchlnExtn', fieldName: '오수', header: { text: '오수' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 비고 + { name: 'rmk', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'adminArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'sgg'], + }, + 'bscFctNm', + 'fctCpc', + { + name: 'procZone', + hideChildHeaders: false, + header: { text: '처리구역면적(km²)' }, + items: ['procZoneSm', 'cmbnProcZoneAr', 'sprtProcZoneAr'], + }, + 'sprtRt', + { + name: 'drainEquip', + hideChildHeaders: false, + header: { text: '배수설비(개소)' }, + items: [ + 'drngEqpSm', + 'cmbnDrngEqp', + { + name: 'sprtDrainEquip', + hideChildHeaders: false, + header: { text: '분류식' }, + items: ['sprtDrngEqpSm', 'sprtDrngEqpCnnc', 'sprtDrngEqpDcnnc'], + }, + ], + }, + { + name: 'sewagePipe', + hideChildHeaders: false, + header: { text: '하수관로' }, + items: [ + 'piplFcltyExtn', + { + name: 'interceptor', + hideChildHeaders: false, + header: { text: '차집/오수간선(m)' }, + items: ['icgMnnSm', 'icgExtn', 'mnnExtn'], + }, + { + name: 'soilHole', + hideChildHeaders: false, + header: { text: '토실/토구(개소)' }, + items: [ + { + name: 'cmbnSoilHole', + hideChildHeaders: false, + header: { text: '합류식' }, + items: ['cmbnSoilholeSite'], + }, + { + name: 'sprtSoilHole', + hideChildHeaders: false, + header: { text: '분류식' }, + items: ['sprtSoilholeSite', 'sprtSoilspllSite'], + }, + ], + }, + { + name: 'branchLine', + hideChildHeaders: false, + header: { text: '지선(m)' }, + items: [ + 'brnchlnSm', + 'cmbnBrnchlnExtn', + { + name: 'sprtBranchLine', + hideChildHeaders: false, + header: { text: '분류식' }, + items: ['rainwtrBrnchlnExtn', 'pltwtrBrnchlnExtn'], + }, + ], + }, + ], + }, + 'rmk', + ], + rowStartNum: 4, + fixedColumns: 3, + tabKey: 'factInstallStatusInp', + tabLabel: '시설별 설치현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipe/ManholeStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipe/ManholeStatusInpColumn.ts new file mode 100644 index 000000000..5732a82df --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipe/ManholeStatusInpColumn.ts @@ -0,0 +1,331 @@ +import { footerInt } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 02.하수관로 > tab 5. 맨홀 현황 + +export const ManholeStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'a1', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'a2', fieldName: '시군구', header: { text: '시군구' }, editable: false }, + + // 집중강우중점관리구역구분 + { name: 'a3', fieldName: '집중강우중점관리구역구분', header: { text: '집중강우중점관리구역구분' }, editable: false, footer: { text: '합계' } }, + + // 연도별총계 > 맨홀뚜껑 재질(개) + { name: 'b1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'b2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'b3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'b4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'b5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 연도별총계 > 추락방지시설설치맨홀(개) + { name: 'b6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2015년 이전 > 맨홀뚜껑 재질(개) + { name: 'c1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'c2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'c3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'c4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'c5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2015년 이전 > 추락방지시설설치맨홀(개) + { name: 'c6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2015년 > 맨홀뚜껑 재질(개) + { name: 'd1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'd2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'd3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'd4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'd5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2015년 > 추락방지시설설치맨홀(개) + { name: 'd6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2016년 > 맨홀뚜껑 재질(개) + { name: 'e1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'e2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'e3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'e4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'e5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2016년 > 추락방지시설설치맨홀(개) + { name: 'e6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2017년 > 맨홀뚜껑 재질(개) + { name: 'f1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'f2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'f3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'f4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'f5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2017년 > 추락방지시설설치맨홀(개) + { name: 'f6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2018년 > 맨홀뚜껑 재질(개) + { name: 'g1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'g2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'g3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'g4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'g5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2018년 > 추락방지시설설치맨홀(개) + { name: 'g6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2019년 > 맨홀뚜껑 재질(개) + { name: 'h1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'h2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'h3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'h4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'h5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2019년 > 추락방지시설설치맨홀(개) + { name: 'h6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2020년 > 맨홀뚜껑 재질(개) + { name: 'i1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'i2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'i3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'i4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'i5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2020년 > 추락방지시설설치맨홀(개) + { name: 'i6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2021년 > 맨홀뚜껑 재질(개) + { name: 'j1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'j2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'j3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'j4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'j5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2021년 > 추락방지시설설치맨홀(개) + { name: 'j6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2022년 > 맨홀뚜껑 재질(개) + { name: 'k1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'k2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'k3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'k4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'k5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2022년 > 추락방지시설설치맨홀(개) + { name: 'k6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2023년 > 맨홀뚜껑 재질(개) + { name: 'l1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'l2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'l3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'l4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'l5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2023년 > 추락방지시설설치맨홀(개) + { name: 'l6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2024년 > 맨홀뚜껑 재질(개) + { name: 'm1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'm2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'm3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'm4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'm5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2024년 > 추락방지시설설치맨홀(개) + { name: 'm6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 2025년 > 맨홀뚜껑 재질(개) + { name: 'n1', fieldName: '계', header: { text: '계' }, footer: footerInt, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'n2', fieldName: '주철', header: { text: '주철' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'n3', fieldName: '주철(조화)', header: { text: '주철(조화)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'n4', fieldName: '콘크리트', header: { text: '콘크리트' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'n5', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + // 2025년 > 추락방지시설설치맨홀(개) + { name: 'n6', fieldName: '추락방지시설설치맨홀(개)', header: { text: '추락방지시설설치맨홀(개)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'z1', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'adminArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['a1', 'a2'], + }, + 'a3', + { + name: 'yearlyTotal', + hideChildHeaders: false, + header: { text: '연도별총계' }, + items: [ + { + name: 'yearlyTotalMaterial', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['b1', 'b2', 'b3', 'b4', 'b5'], + }, + 'b6', + ], + }, + { + name: 'before2015', + hideChildHeaders: false, + header: { text: '2015년 이전' }, + items: [ + { + name: 'before2015Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['c1', 'c2', 'c3', 'c4', 'c5'], + }, + 'c6', + ], + }, + { + name: 'year2015', + hideChildHeaders: false, + header: { text: '2015년' }, + items: [ + { + name: 'year2015Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['d1', 'd2', 'd3', 'd4', 'd5'], + }, + 'd6', + ], + }, + { + name: 'year2016', + hideChildHeaders: false, + header: { text: '2016년' }, + items: [ + { + name: 'year2016Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['e1', 'e2', 'e3', 'e4', 'e5'], + }, + 'e6', + ], + }, + { + name: 'year2017', + hideChildHeaders: false, + header: { text: '2017년' }, + items: [ + { + name: 'year2017Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['f1', 'f2', 'f3', 'f4', 'f5'], + }, + 'f6', + ], + }, + { + name: 'year2018', + hideChildHeaders: false, + header: { text: '2018년' }, + items: [ + { + name: 'year2018Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['g1', 'g2', 'g3', 'g4', 'g5'], + }, + 'g6', + ], + }, + { + name: 'year2019', + hideChildHeaders: false, + header: { text: '2019년' }, + items: [ + { + name: 'year2019Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['h1', 'h2', 'h3', 'h4', 'h5'], + }, + 'h6', + ], + }, + { + name: 'year2020', + hideChildHeaders: false, + header: { text: '2020년' }, + items: [ + { + name: 'year2020Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['i1', 'i2', 'i3', 'i4', 'i5'], + }, + 'i6', + ], + }, + { + name: 'year2021', + hideChildHeaders: false, + header: { text: '2021년' }, + items: [ + { + name: 'year2021Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['j1', 'j2', 'j3', 'j4', 'j5'], + }, + 'j6', + ], + }, + { + name: 'year2022', + hideChildHeaders: false, + header: { text: '2022년' }, + items: [ + { + name: 'year2022Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['k1', 'k2', 'k3', 'k4', 'k5'], + }, + 'k6', + ], + }, + { + name: 'year2023', + hideChildHeaders: false, + header: { text: '2023년' }, + items: [ + { + name: 'year2023Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['l1', 'l2', 'l3', 'l4', 'l5'], + }, + 'l6', + ], + }, + { + name: 'year2024', + hideChildHeaders: false, + header: { text: '2024년' }, + items: [ + { + name: 'year2024Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['m1', 'm2', 'm3', 'm4', 'm5'], + }, + 'm6', + ], + }, + { + name: 'year2025', + hideChildHeaders: false, + header: { text: '2025년' }, + items: [ + { + name: 'year2025Material', + hideChildHeaders: false, + header: { text: '맨홀뚜껑 재질(개)' }, + items: ['n1', 'n2', 'n3', 'n4', 'n5'], + }, + 'n6', + ], + }, + 'z1', + ], + rowStartNum: 3, + fixedColumns: 2, + tabKey: 'manholeStatusInp', + tabLabel: '맨홀 현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipe/PipeDiameterStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipe/PipeDiameterStatusInpColumn.ts new file mode 100644 index 000000000..af009e292 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipe/PipeDiameterStatusInpColumn.ts @@ -0,0 +1,63 @@ +import { footerDecimal2 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 02.하수관로 > tab 4. 관경별 현황 + +export const PipeDiameterStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 관종 + { name: 'swrgPipeCd', fieldName: '관종', header: { text: '관종' }, editable: false }, + + // 총계(m) - 계산 + { name: 'totalDiameter', fieldName: '총계(m)', header: { text: '총계(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 원형(m) + { name: 'under200', fieldName: '200mm 미만', header: { text: '200mm 미만' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'over200Undev300', fieldName: '200mm이상~300mm미만', header: { text: '200mm이상~300mm미만' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'over300Undev500', fieldName: '300mm이상~500mm미만', header: { text: '300mm이상~500mm미만' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'over500Undev500', fieldName: '500mm이상~800mm미만', header: { text: '500mm이상~800mm미만' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'over800', fieldName: '800이상mm', header: { text: '800이상mm' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 사각형(m) + { name: 'box', fieldName: '사각형(m)', header: { text: '사각형(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 기타(측구 개거 등) + { name: 'etc', fieldName: '기타(측구 개거 등)', header: { text: '기타(측구 개거 등)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 비고 + { name: 'rmk', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'adminArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'sgg'], + }, + 'swrgPipeCd', + 'totalDiameter', + { + name: 'circular', + hideChildHeaders: false, + header: { text: '원형(m)' }, + items: [ + 'under200', + 'over200Undev300', + 'over300Undev500', + 'over500Undev500', + 'over800', + ], + }, + 'box', + 'etc', + 'rmk', + ], + rowStartNum: 2, + fixedColumns: 1, + tabKey: 'pipeDiameterStatusInp', + tabLabel: '관경별 현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipe/PipeTypeStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipe/PipeTypeStatusInpColumn.ts new file mode 100644 index 000000000..e1e33a3c8 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipe/PipeTypeStatusInpColumn.ts @@ -0,0 +1,377 @@ +import { footerDecimal2 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 02.하수관로 > tab 3. 관종별 현황 + +export const PipeTypeStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, editable: false }, + + // 관종 + { name: 'swrgPipeCd', fieldName: '관종', header: { text: '관종' }, footer: { text: '합계' }, editable: false }, + + // 총계 + { name: 'totalSum', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'totalLayingExtn', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'totalRemvlExtn', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 1996년 이전 (footer 없음) + { name: 'totalExtn22y', fieldName: '계', header: { text: '계' }, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn22y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn22y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 1996년 + { name: 'totalExtn01y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn01y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn01y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 1997년 + { name: 'totalExtn02y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn02y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn02y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 1998년 + { name: 'totalExtn03y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn03y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn03y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 1999년 + { name: 'totalExtn04y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn04y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn04y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2000년 + { name: 'totalExtn05y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn05y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn05y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2001년 + { name: 'totalExtn06y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn06y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn06y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2002년 + { name: 'totalExtn07y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn07y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn07y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2003년 + { name: 'totalExtn08y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn08y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn08y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2004년 + { name: 'totalExtn09y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn09y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn09y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2005년 + { name: 'totalExtn10y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn10y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn10y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2006년 + { name: 'totalExtn11y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn11y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn11y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2007년 + { name: 'totalExtn12y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn12y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn12y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2008년 + { name: 'totalExtn13y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn13y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn13y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2009년 + { name: 'totalExtn14y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn14y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn14y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2010년 + { name: 'totalExtn15y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn15y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn15y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2011년 + { name: 'totalExtn16y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn16y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn16y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2012년 + { name: 'totalExtn17y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn17y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn17y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2013년 + { name: 'totalExtn18y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn18y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn18y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2014년 + { name: 'totalExtn19y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn19y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn19y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2015년 + { name: 'totalExtn20y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn20y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn20y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2016년 + { name: 'totalExtn21y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn21y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn21y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2017년 + { name: 'totalExtn23y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn23y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn23y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2018년 + { name: 'totalExtn24y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn24y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn24y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2019년 + { name: 'totalExtn25y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn25y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn25y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2020년 + { name: 'totalExtn26y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn26y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn26y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2021년 + { name: 'totalExtn27y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn27y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn27y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2022년 + { name: 'totalExtn28y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn28y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn28y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2023년 + { name: 'totalExtn29y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn29y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn29y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2024년 + { name: 'totalExtn30y', fieldName: '계', header: { text: '계' }, footer: footerDecimal2, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'layingExtn30y', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + { name: 'remvlExtn30y', fieldName: '철거연장(m)', header: { text: '철거연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 2025년 + { name: 'layingExtn', fieldName: '매설연장(m)', header: { text: '매설연장(m)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 비고 + { name: 'rmk', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'adminArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'sgg'], + }, + 'swrgPipeCd', + { + name: 'totalGroup', + hideChildHeaders: false, + header: { text: '총계' }, + items: ['totalSum', 'totalLayingExtn', 'totalRemvlExtn'], + }, + { + name: 'year1996Before', + hideChildHeaders: false, + header: { text: '1996년 이전' }, + items: ['totalExtn22y', 'layingExtn22y', 'remvlExtn22y'], + }, + { + name: 'year1996', + hideChildHeaders: false, + header: { text: '1996년' }, + items: ['totalExtn01y', 'layingExtn01y', 'remvlExtn01y'], + }, + { + name: 'year1997', + hideChildHeaders: false, + header: { text: '1997년' }, + items: ['totalExtn02y', 'layingExtn02y', 'remvlExtn02y'], + }, + { + name: 'year1998', + hideChildHeaders: false, + header: { text: '1998년' }, + items: ['totalExtn03y', 'layingExtn03y', 'remvlExtn03y'], + }, + { + name: 'year1999', + hideChildHeaders: false, + header: { text: '1999년' }, + items: ['totalExtn04y', 'layingExtn04y', 'remvlExtn04y'], + }, + { + name: 'year2000', + hideChildHeaders: false, + header: { text: '2000년' }, + items: ['totalExtn05y', 'layingExtn05y', 'remvlExtn05y'], + }, + { + name: 'year2001', + hideChildHeaders: false, + header: { text: '2001년' }, + items: ['totalExtn06y', 'layingExtn06y', 'remvlExtn06y'], + }, + { + name: 'year2002', + hideChildHeaders: false, + header: { text: '2002년' }, + items: ['totalExtn07y', 'layingExtn07y', 'remvlExtn07y'], + }, + { + name: 'year2003', + hideChildHeaders: false, + header: { text: '2003년' }, + items: ['totalExtn08y', 'layingExtn08y', 'remvlExtn08y'], + }, + { + name: 'year2004', + hideChildHeaders: false, + header: { text: '2004년' }, + items: ['totalExtn09y', 'layingExtn09y', 'remvlExtn09y'], + }, + { + name: 'year2005', + hideChildHeaders: false, + header: { text: '2005년' }, + items: ['totalExtn10y', 'layingExtn10y', 'remvlExtn10y'], + }, + { + name: 'year2006', + hideChildHeaders: false, + header: { text: '2006년' }, + items: ['totalExtn11y', 'layingExtn11y', 'remvlExtn11y'], + }, + { + name: 'year2007', + hideChildHeaders: false, + header: { text: '2007년' }, + items: ['totalExtn12y', 'layingExtn12y', 'remvlExtn12y'], + }, + { + name: 'year2008', + hideChildHeaders: false, + header: { text: '2008년' }, + items: ['totalExtn13y', 'layingExtn13y', 'remvlExtn13y'], + }, + { + name: 'year2009', + hideChildHeaders: false, + header: { text: '2009년' }, + items: ['totalExtn14y', 'layingExtn14y', 'remvlExtn14y'], + }, + { + name: 'year2010', + hideChildHeaders: false, + header: { text: '2010년' }, + items: ['totalExtn15y', 'layingExtn15y', 'remvlExtn15y'], + }, + { + name: 'year2011', + hideChildHeaders: false, + header: { text: '2011년' }, + items: ['totalExtn16y', 'layingExtn16y', 'remvlExtn16y'], + }, + { + name: 'year2012', + hideChildHeaders: false, + header: { text: '2012년' }, + items: ['totalExtn17y', 'layingExtn17y', 'remvlExtn17y'], + }, + { + name: 'year2013', + hideChildHeaders: false, + header: { text: '2013년' }, + items: ['totalExtn18y', 'layingExtn18y', 'remvlExtn18y'], + }, + { + name: 'year2014', + hideChildHeaders: false, + header: { text: '2014년' }, + items: ['totalExtn19y', 'layingExtn19y', 'remvlExtn19y'], + }, + { + name: 'year2015', + hideChildHeaders: false, + header: { text: '2015년' }, + items: ['totalExtn20y', 'layingExtn20y', 'remvlExtn20y'], + }, + { + name: 'year2016', + hideChildHeaders: false, + header: { text: '2016년' }, + items: ['totalExtn21y', 'layingExtn21y', 'remvlExtn21y'], + }, + { + name: 'year2017', + hideChildHeaders: false, + header: { text: '2017년' }, + items: ['totalExtn23y', 'layingExtn23y', 'remvlExtn23y'], + }, + { + name: 'year2018', + hideChildHeaders: false, + header: { text: '2018년' }, + items: ['totalExtn24y', 'layingExtn24y', 'remvlExtn24y'], + }, + { + name: 'year2019', + hideChildHeaders: false, + header: { text: '2019년' }, + items: ['totalExtn25y', 'layingExtn25y', 'remvlExtn25y'], + }, + { + name: 'year2020', + hideChildHeaders: false, + header: { text: '2020년' }, + items: ['totalExtn26y', 'layingExtn26y', 'remvlExtn26y'], + }, + { + name: 'year2021', + hideChildHeaders: false, + header: { text: '2021년' }, + items: ['totalExtn27y', 'layingExtn27y', 'remvlExtn27y'], + }, + { + name: 'year2022', + hideChildHeaders: false, + header: { text: '2022년' }, + items: ['totalExtn28y', 'layingExtn28y', 'remvlExtn28y'], + }, + { + name: 'year2023', + hideChildHeaders: false, + header: { text: '2023년' }, + items: ['totalExtn29y', 'layingExtn29y', 'remvlExtn29y'], + }, + { + name: 'year2024', + hideChildHeaders: false, + header: { text: '2024년' }, + items: ['totalExtn30y', 'layingExtn30y', 'remvlExtn30y'], + }, + 'layingExtn', + 'rmk', + ], + rowStartNum: 2, + fixedColumns: 2, + tabKey: 'pipeTypeStatusInp', + tabLabel: '관종별 현황' + }; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn.ts new file mode 100644 index 000000000..a02919150 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipe/RegionalFactStatusInpColumn.ts @@ -0,0 +1,159 @@ +import { footerInt, footerDecimal1, footerDecimal2, footerDecimal3 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 02.하수관로 > tab 1. 지역별 시설현황 + +export const RegionalFactStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' }, editable: false }, + + // 기본 정보 + { 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' }, + + // 합류식(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' }, + + // 분류식(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' }, + + // 분류식(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: 'mnhleSite', fieldName: '합류식맨홀(개소)', 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: '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: '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: 'rmk', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'adminArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'sgg'], + }, + 'targetYr', + 'piplImprnPlanExtn', + 'piplPlanExtn', + 'piplFcltyExtn', + 'piplSupprt', + { + name: 'combined', + hideChildHeaders: false, + header: { text: '합류식(m)' }, + items: [ + 'cmbnPlanAr', + 'cmbnImprnPlanExtn', + 'cmbnPlanExtn', + 'cmbnFcltyExtn', + { + name: 'cmbnCulvert', + hideChildHeaders: false, + header: { text: '암거' }, + items: ['cmbnRctglExtn', 'cmbnCicleExtn'], + }, + 'cmbnOpswrExtn', + 'cmbnSdgttrExtn', + ], + }, + { + name: 'separated', + hideChildHeaders: false, + header: { text: '분류식(m)' }, + items: [ + { + name: 'pollutedWater', + hideChildHeaders: false, + header: { text: '오수관로' }, + items: [ + 'pltwtrPlanAr', + 'pltwtrImprnPlanExtn', + 'pltwtrPlanExtn', + 'pltwtrFlctyExtn', + { + name: 'pltwtrCulvert', + hideChildHeaders: false, + header: { text: '암거' }, + items: ['pltwtrSqreExtn', 'pltwtrCiclExtn'], + }, + ], + }, + { + name: 'rainWater', + hideChildHeaders: false, + header: { text: '우수관로' }, + items: [ + 'rainwtrPlanAr', + 'rainwtrImprnPlanExtn', + 'rainwtrPlanExtn', + 'rainwtrFlctyExtn', + { + name: 'rainwtrCulvert', + hideChildHeaders: false, + header: { text: '암거' }, + items: ['rainwtrSqreExtn', 'rainwtrCiclExtn'], + }, + 'rainwtrOpswrExtn', + 'rainwtrSdgttrExtn', + ], + }, + ], + }, + 'mnhleSite', + { + name: 'separatedManhole', + hideChildHeaders: false, + header: { text: '분류식' }, + items: ['pltwtrMnhleSite', 'rainwtrMnhleSite'], + }, + 'pltwtrRcvrSite', + 'rainwtrRcvrSite', + 'soilspllSite', + 'soilholeSite', + 'sewerRegstrCmptExtn', + 'sewerRegstrCmptRt', + 'rmk', + ], + rowStartNum: 4, + fixedColumns: 1, + tabKey: 'regionalFactStatusInp', + tabLabel: '지역별 시설현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipeMaintain/PipeDredgingStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipeMaintain/PipeDredgingStatusInpColumn.ts new file mode 100644 index 000000000..983df126e --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipeMaintain/PipeDredgingStatusInpColumn.ts @@ -0,0 +1,82 @@ +import { footerInt, footerDecimal1, footerDecimal2 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 03.하수관로 유지관리 > tab 2. 관로준설 +export const PipeDredgingStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 하수관로 총 시설연장 + { name: 'PIPL_FCLTY_EXTN', fieldName: '하수관로총시설연장(m)', header: { text: '하수관로총시설연장(m)' }, editable: false, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 준설연장 및 개소수 > 관로(m) + { name: 'DRDG_PIPE_SM', fieldName: '합계', header: { text: '합계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DRDG_CMBN_PIPE', fieldName: '합류식', header: { text: '합류식' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 준설연장 및 개소수 > 관로(m) > 분류식 + { name: 'DRDG_RAINWTR_PIPE', fieldName: '우수', header: { text: '우수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DRDG_PLTWTR_PIPE', fieldName: '오수', header: { text: '오수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 준설연장 및 개소수 > 맨홀, 오·우수받이, 토실·토구 + { name: 'MNHLE_SITE', fieldName: '맨홀(개소)', header: { text: '맨홀(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'PLTWTR_RCVR_SITE', fieldName: '오·우수받이(개소)', header: { text: '오·우수받이(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SOILSPLL_SOILHOLE_SITE', fieldName: '토실·토구(개소)', header: { text: '토실·토구(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 계획 & 비율 + { name: 'DRDG_TRGET_EXTN', fieldName: '준설 계획 연장(m)', header: { text: '준설 계획 연장(m)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'DRDG_TRGET_RT', fieldName: '계획대비 준설율(%)', header: { text: '계획대비 준설율(%)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'PIPL_FCLTY_RT', fieldName: '총시설연장대비 준설율(%)', header: { text: '총시설연장대비 준설율(%)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 준설실적 + { name: 'DRDG_ACMSLT_AMOUNT', fieldName: '금액(백만원)', header: { text: '금액(백만원)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'DRDG_ACMSLT_QY', fieldName: '준설량(m³)', header: { text: '준설량(m³)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 준설토사처리 + { name: 'DRDG_ACMSLT_UNTPC', fieldName: '준설토처리비(백만원)', header: { text: '준설토처리비(백만원)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'DRDG_ETND_SM', fieldName: '처리량 계(톤)', header: { text: '처리량 계(톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RCLM', fieldName: '매립', header: { text: '매립' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'OCEAN_DPSL', fieldName: '해양투기', header: { text: '해양투기' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RUSE', fieldName: '재활용', header: { text: '재활용' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'ETC', fieldName: '기타(소각, 고형화, 시멘트원료 등)', header: { text: '기타(소각, 고형화, 시멘트원료 등)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'group_admin', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'PIPL_FCLTY_EXTN', + { + name: 'group_dredge_info', + header: { text: '준설연장 및 개소수' }, + items: [ + { + name: 'group_pipe', + header: { text: '관로(m)' }, + items: [ + 'DRDG_PIPE_SM', 'DRDG_CMBN_PIPE', + { name: 'group_sep', header: { text: '분류식' }, items: ['DRDG_RAINWTR_PIPE', 'DRDG_PLTWTR_PIPE'] } + ] + }, + 'MNHLE_SITE', 'PLTWTR_RCVR_SITE', 'SOILSPLL_SOILHOLE_SITE' + ] + }, + 'DRDG_TRGET_EXTN', 'DRDG_TRGET_RT', 'PIPL_FCLTY_RT', + { + name: 'group_perf', + header: { text: '준설실적' }, + items: ['DRDG_ACMSLT_AMOUNT', 'DRDG_ACMSLT_QY'] + }, + { + name: 'group_soil_treat', + header: { text: '준설토사처리' }, + items: ['DRDG_ACMSLT_UNTPC', 'DRDG_ETND_SM', 'RCLM', 'OCEAN_DPSL', 'RUSE', 'ETC'] + }, + 'RMK' + ], + rowStartNum: 4, + fixedColumns: 1, + tabKey: 'pipeDredgingStatusInp', + tabLabel: '관로준설' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewagePipeMaintain/RepairStatusInpColumn.ts b/apps/st/src/components/util/column/input/sewagePipeMaintain/RepairStatusInpColumn.ts new file mode 100644 index 000000000..5f22b373f --- /dev/null +++ b/apps/st/src/components/util/column/input/sewagePipeMaintain/RepairStatusInpColumn.ts @@ -0,0 +1,115 @@ +import { footerInt, footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 03.하수관로 유지관리 > tab 1. 개보수 +export const RepairStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 개·보수관로 > 전체보수(m) + { name: 'RPAIR_PIPE_SM', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RPAIR_CMBN_PIPE', fieldName: '합류식', header: { text: '합류식' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 개·보수관로 > 전체보수(m) > 분류식 + { name: 'RPAIR_RAINWTR_PIPE', fieldName: '우수', header: { text: '우수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RPAIR_PLTWTR_PIPE', fieldName: '오수', header: { text: '오수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 개·보수관로 > 부분보수(개소) + { name: 'RPAIR_PIPE_SM2', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'RPAIR_CMBN_PIPE2', fieldName: '합류식', header: { text: '합류식' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 개·보수관로 > 부분보수(개소) > 분류식 + { name: 'RPAIR_RAINWTR_PIPE2', fieldName: '우수', header: { text: '우수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'RPAIR_PLTWTR_PIPE2', fieldName: '오수', header: { text: '오수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 맨홀(개소) + { name: 'MNHLE_SITE', fieldName: '합류식맨홀', header: { text: '합류식맨홀' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 맨홀(개소) > 분류식 + { name: 'PLTWTR_MNHLE_SITE', fieldName: '오수맨홀', header: { text: '오수맨홀' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'RAINWTR_MNHLE_SITE', fieldName: '우수맨홀', header: { text: '우수맨홀' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 받이 + { name: 'PLTWTR_RCVR_SITE', fieldName: '오수받이(개소)', header: { text: '오수받이(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'RAINWTR_RCVR_SITE', fieldName: '빗물받이(개소)', header: { text: '빗물받이(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 토실, 토구 + { name: 'SOILSPLL_SITE', fieldName: '토실(개소)', header: { text: '토실(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SOILHOLE_SITE', fieldName: '토구(개소)', header: { text: '토구(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 수밀검사CCTV조사량(m) + { name: 'CCTV', fieldName: '수밀검사CCTV조사량(m)', header: { text: '수밀검사CCTV조사량(m)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + { + name: 'group_repair_main', + header: { text: '개·보수관로' }, + items: [ + { + name: 'group_full_repair', + header: { text: '전체보수(m)' }, + items: [ + 'RPAIR_PIPE_SM', + 'RPAIR_CMBN_PIPE', + { + name: 'group_full_sep', + header: { text: '분류식' }, + items: ['RPAIR_RAINWTR_PIPE', 'RPAIR_PLTWTR_PIPE'] + } + ] + }, + { + name: 'group_part_repair', + header: { text: '부분보수(개소)' }, + items: [ + 'RPAIR_PIPE_SM2', + 'RPAIR_CMBN_PIPE2', + { + name: 'group_part_sep', + header: { text: '분류식' }, + items: ['RPAIR_RAINWTR_PIPE2', 'RPAIR_PLTWTR_PIPE2'] + } + ] + } + ] + }, + { + name: 'group_manhole', + header: { text: '맨홀(개소)' }, + items: [ + 'MNHLE_SITE', + { + name: 'group_mh_sep', + header: { text: '분류식' }, + items: ['PLTWTR_MNHLE_SITE', 'RAINWTR_MNHLE_SITE'] + } + ] + }, + { + name: 'group_inlet', + header: { text: '받이' }, + items: ['PLTWTR_RCVR_SITE', 'RAINWTR_RCVR_SITE'] + }, + { + name: 'group_chamber', + header: { text: '토실,토구' }, + items: ['SOILSPLL_SITE', 'SOILHOLE_SITE'] + }, + 'CCTV', + 'RMK' + ], + rowStartNum: 4, + fixedColumns: 1, + tabKey: 'repairStatusInp', + tabLabel: '개보수' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageReservoirPump/RainfallPumpStationInpColumn.ts b/apps/st/src/components/util/column/input/sewageReservoirPump/RainfallPumpStationInpColumn.ts new file mode 100644 index 000000000..e000f4904 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageReservoirPump/RainfallPumpStationInpColumn.ts @@ -0,0 +1,211 @@ +import { footerInt, footerDecimal1, footerDecimal2, footerDecimal3 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + + // 하수도 통계 관리 > 04.하수저류시설 및 빗물펌프장 > tab 2: 빗물펌프장 +export const RainfallPumpStationInpColumn = { + columns: [ + // Hidden Columns : 시스템 관리를 위한 값 + { name: 'sidoCd', fieldName: '시도코드', header: { text: '시도코드' }, hidden: true }, + { name: 'adstDstrCd', fieldName: '행정구역코드', header: { text: '행정구역코드' }, hidden: true }, + { name: 'adstCd', fieldName: '행정코드', header: { text: '행정코드' }, hidden: true }, + { name: 'swgeStrgeFctSeq', fieldName: '시설SEQ', header: { text: '시설SEQ' }, hidden: true }, + { name: 'yr', fieldName: '년도', header: { text: '년도' }, hidden: true }, + { name: 'odr', fieldName: '차수', header: { text: '차수' }, hidden: true }, + { name: 'bsnmCd', fieldName: '사업자코드', header: { text: '사업자코드' }, hidden: true }, + + // Visible Columns + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'gugun', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } }, + + // 시설명 + { name: 'swgeStrgeNm', fieldName: '시설명', header: { text: '시설명' } }, + + // 위치 + { name: 'addr', fieldName: '위치', header: { text: '위치' } }, + + // 시설물종류 + { name: 'facRes', fieldName: '시설물종류', header: { text: '시설물종류' } }, + + // 가동개시 년월일 yyyy-mm-dd + { name: 'rnDt', fieldName: '가동개시 년월일 yyyy-mm-dd', header: { text: '가동개시 년월일 yyyy-mm-dd' } }, + + // 계획설계빈도 + { name: 'plDsgnFrqnc', fieldName: '계획설계빈도', header: { text: '계획설계빈도' } }, + + // 집수구역면적(㎢) + { name: 'dgrAr', fieldName: '집수구역면적(㎢)', header: { text: '집수구역면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + + // 유수지 + { name: 'revFnnc', fieldName: '유수지유무(유,무)', header: { text: '유수지유무(유,무)' } }, + { name: 'revCpcty', fieldName: '저류랑(m³)', header: { text: '저류랑(m³)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 흡수정 + { name: 'absCpcty', fieldName: '저류랑(m³)', header: { text: '저류랑(m³)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 펌프시설 > 총양수량(m³/min) + { name: 'wpCpcty', fieldName: '총양수량(m³/min)', header: { text: '총양수량(m³/min)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 펌프시설1 + { name: 'pumpCalbr', fieldName: '구경(mm)', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pumpHpCo', fieldName: '대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'pumpCo', fieldName: '펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pumpPreparCo', fieldName: '예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 펌프시설2 + { name: 'pumpCalbr2', fieldName: '구경(mm)', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pumpHpCo2', fieldName: '대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'pumpCo2', fieldName: '펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pumpPreparCo2', fieldName: '예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 펌프시설3 + { name: 'pumpCalbr3', fieldName: '구경(mm)', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pumpHpCo3', fieldName: '대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'pumpCo3', fieldName: '펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pumpPreparCo3', fieldName: '예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 부대시설 + { name: 'dorZeqpFnnc', fieldName: '전처리시설유무(유/무)', header: { text: '전처리시설유무(유/무)' } }, + { name: 'selfEtrqFnnc', fieldName: '탈취설비유무(유/무)', header: { text: '탈취설비유무(유/무)' } }, + { name: 'freFnnc', fieldName: '자가발전유무(유/무)', header: { text: '자가발전유무(유/무)' } }, + + // 방류수역 + { name: 'disWat', fieldName: '방류수역', header: { text: '방류수역' } }, + + // 최종처분량(ton/년) + { name: 'sdmtTreCpcty', fieldName: '침사', header: { text: '침사' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'iprtTreCpcty', fieldName: '협잡물', header: { text: '협잡물' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 최종처분방법 + { name: 'sdmtTreMth', fieldName: '침사', header: { text: '침사' } }, + { name: 'iprtTreMth', fieldName: '협잡물', header: { text: '협잡물' } }, + + // 운영실적 + { name: 'yrstpRnDyn', fieldName: '가동일수(일/년)', header: { text: '가동일수(일/년)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, // 입력값 3자리만 가능 + { name: 'dsplcmntAmnt', fieldName: '총배수량(m³/년)', header: { text: '총배수량(m³/년)' }, footer: footerDecimal2, valueType: ValueType.NUMBER, dataFormat: '#,##0.00' }, + + // 비고 + { name: 'rmk', fieldName: '비고', header: { text: '비고' } }, + { name: 'chckerOpinion', fieldName: '검토자의견', header: { text: '검토자의견' } }, + { name: 'wrterOpinion', fieldName: '사용자의견', header: { text: '사용자의견' } }, + ], + + columnLayout: [ + { + name: 'adminArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'gugun'], + }, + 'swgeStrgeNm', + 'addr', + 'facRes', + 'rnDt', + 'plDsgnFrqnc', + 'dgrAr', + { + name: 'reservoir', + hideChildHeaders: false, + header: { text: '유수지' }, + items: [ + 'revFnnc', + 'revCpcty', + ], + }, + { + name: 'absorptionWell', + hideChildHeaders: false, + header: { text: '흡수정' }, + items: [ + 'absCpcty', + ], + }, + { + name: 'pumpSystem', + hideChildHeaders: false, + header: { text: '펌프시설' }, + items: [ + 'wpCpcty', + { + name: 'pumpSystem1', + hideChildHeaders: false, + header: { text: '펌프시설1' }, + items: [ + 'pumpCalbr', + 'pumpHpCo', + 'pumpCo', + 'pumpPreparCo', + ], + }, + { + name: 'pumpSystem2', + hideChildHeaders: false, + header: { text: '펌프시설2' }, + items: [ + 'pumpCalbr2', + 'pumpHpCo2', + 'pumpCo2', + 'pumpPreparCo2', + ], + }, + { + name: 'pumpSystem3', + hideChildHeaders: false, + header: { text: '펌프시설3' }, + items: [ + 'pumpCalbr3', + 'pumpHpCo3', + 'pumpCo3', + 'pumpPreparCo3', + ], + }, + ], + }, + { + name: 'auxiliaryFacilities', + hideChildHeaders: false, + header: { text: '부대시설' }, + items: [ + 'dorZeqpFnnc', + 'selfEtrqFnnc', + 'freFnnc', + ], + }, + 'disWat', + { + name: 'finalDisposalAmount', + hideChildHeaders: false, + header: { text: '최종처분량(ton/년)' }, + items: [ + 'sdmtTreCpcty', + 'iprtTreCpcty', + ], + }, + { + name: 'finalDisposalMethod', + hideChildHeaders: false, + header: { text: '최종처분방법' }, + items: [ + 'sdmtTreMth', + 'iprtTreMth', + ], + }, + { + name: 'operationResults', + hideChildHeaders: false, + header: { text: '운영실적' }, + items: [ + 'yrstpRnDyn', + 'dsplcmntAmnt', + ], + }, + 'rmk', + 'chckerOpinion', + 'wrterOpinion', + ], + + rowStartNum: 3, + fixedColumns: 2, + tabKey: 'rainfallPumpStationInp', + tabLabel: '빗물펌프장', +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewageReservoirPump/SewageReservoirInpColumn.ts b/apps/st/src/components/util/column/input/sewageReservoirPump/SewageReservoirInpColumn.ts new file mode 100644 index 000000000..8dc69e5e9 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewageReservoirPump/SewageReservoirInpColumn.ts @@ -0,0 +1,213 @@ +import { footerInt, footerDecimal1, footerDecimal3 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + + // 하수도 통계 관리 > 04.하수저류시설 및 빗물펌프장 > tab 1: 하수저류시설 +export const SewageReservoirInpColumn = { + columns: [ + // Hidden Columns : 시스템 관리를 위한 값 + { name: 'sidoCd', fieldName: '시도코드', header: { text: '시도코드' }, hidden: true }, + { name: 'adstDstrCd', fieldName: '행정구역코드', header: { text: '행정구역코드' }, hidden: true }, + { name: 'adstCd', fieldName: '행정코드', header: { text: '행정코드' }, hidden: true }, + { name: 'swgeStrgeFctSeq', fieldName: '시설SEQ', header: { text: '시설SEQ' }, hidden: true }, + + // Visible Columns + // 행정구역 + { name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'gugun', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } }, + + // 기본 정보 + { name: 'swgeStrgeNm', fieldName: '시설명', header: { text: '시설명' } }, + { name: 'addr', fieldName: '위치', header: { text: '위치' } }, + { name: 'rnDt', fieldName: '가동개시 년월일 yyyy-mm-dd', header: { text: '가동개시 년월일 yyyy-mm-dd' } }, + { name: 'designFrequency', fieldName: '계획설계빈도', header: { text: '계획설계빈도' } }, + + // 설치목적 + { name: 'floodingPrevention', fieldName: '침수예방', header: { text: '침수예방' } }, + { name: 'waterQualityReduction', fieldName: '수질오염저감', header: { text: '수질오염저감' } }, + { name: 'sewerageReuseUse', fieldName: '하수재이용용도', header: { text: '하수재이용용도' } }, + + // 시설 구조 + { name: 'facilityStructure', fieldName: '시설구조(일반지하식,지하터널식,기타)', header: { text: '시설구조(일반지하식,지하터널식,기타)' } }, + + // 집수구역면적 + { name: 'catchmentAreaSize', fieldName: '집수구역면적(㎢)', header: { text: '집수구역면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + + // 시설용량 + { name: 'facilityCapacity', fieldName: '시설용량(m³)', header: { text: '시설용량(m³)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 펌프시설 > 총양수량 + { name: 'totalPumpingCapacity', fieldName: '총양수량(m³/min)', header: { text: '총양수량(m³/min)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 펌프시설 1 + { name: 'pump1Diameter', fieldName: '구경(mm)', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pump1PumpingCapacity', fieldName: '대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'pump1Count', fieldName: '펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pump1StandbyCount', fieldName: '예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 펌프시설 2 + { name: 'pump2Diameter', fieldName: '구경(mm)', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pump2PumpingCapacity', fieldName: '대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'pump2Count', fieldName: '펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pump2StandbyCount', fieldName: '예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 펌프시설 3 + { name: 'pump3Diameter', fieldName: '구경(mm)', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pump3PumpingCapacity', fieldName: '대당 양수량(m³/min·대)', header: { text: '대당 양수량(m³/min·대)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'pump3Count', fieldName: '펌프대수', header: { text: '펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pump3StandbyCount', fieldName: '예비펌프대수', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 부대시설 + { name: 'preprocessingFacility', fieldName: '전처리시설유무(유/무)', header: { text: '전처리시설유무(유/무)' } }, + { name: 'odorRemovalEquipment', fieldName: '탈취설비유무(유/무)', header: { text: '탈취설비유무(유/무)' } }, + { name: 'selfGenerationEquipment', fieldName: '자가발전유무(유/무)', header: { text: '자가발전유무(유/무)' } }, + + // 배수 방식 + { name: 'drainageMethod', fieldName: '배수방식(자연배수,강제배수)', header: { text: '배수방식(자연배수,강제배수)' } }, + + // 저류 방식 + { name: 'storageMethod', fieldName: '저류방식(직렬,병렬)', header: { text: '저류방식(직렬,병렬)' } }, + + // 저류수 처리방법 + { name: 'storageWaterTreatmentMethod', fieldName: '저류수처리방법(자체처리,연계처리)', header: { text: '저류수처리방법(자체처리,연계처리)' } }, + + // 방류 수역 + { name: 'dischargeDestination', fieldName: '방류수역(또는 연계처리장명)', header: { text: '방류수역(또는 연계처리장명)' } }, + + // 최종처분량 + { name: 'sedimentDisposalAmount', fieldName: '침사', header: { text: '침사' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'debrisDisposalAmount', fieldName: '협잡물', header: { text: '협잡물' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 최종처분방법 + { name: 'sedimentDisposalMethod', fieldName: '침사', header: { text: '침사' } }, + { name: 'debrisDisposalMethod', fieldName: '협잡물', header: { text: '협잡물' } }, + + // 운영실적 + { name: 'operationDaysPerYear', fieldName: '가동일수(일/년)', header: { text: '가동일수(일/년)' }, valueType: ValueType.NUMBER }, // 3자리 수만 입력 가능 + { name: 'totalDischargePerYear', fieldName: '총배수량(m³/년)', header: { text: '총배수량(m³/년)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'remarks', fieldName: '비고', header: { text: '비고' } }, + ], + + columnLayout: [ + { + name: 'adminArea', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: ['sido', 'gugun'], + }, + 'swgeStrgeNm', + 'addr', + 'rnDt', + 'designFrequency', + + { + name: 'installationPurpose', + hideChildHeaders: false, + header: { text: '설치목적(O,X로 표기, 중복체크가능)' }, + items: [ + 'floodingPrevention', + 'waterQualityReduction', + 'sewerageReuseUse', + ], + }, + 'facilityStructure', + 'catchmentAreaSize', + 'facilityCapacity', + + { + name: 'pumpSystem', + hideChildHeaders: false, + header: { text: '펌프시설' }, + items: [ + 'totalPumpingCapacity', + { + name: 'pumpSystem1', + hideChildHeaders: false, + header: { text: '펌프시설1' }, + items: [ + 'pump1Diameter', + 'pump1PumpingCapacity', + 'pump1Count', + 'pump1StandbyCount', + ], + }, + + { + name: 'pumpSystem2', + hideChildHeaders: false, + header: { text: '펌프시설2' }, + items: [ + 'pump2Diameter', + 'pump2PumpingCapacity', + 'pump2Count', + 'pump2StandbyCount', + ], + }, + + { + name: 'pumpSystem3', + hideChildHeaders: false, + header: { text: '펌프시설3' }, + items: [ + 'pump3Diameter', + 'pump3PumpingCapacity', + 'pump3Count', + 'pump3StandbyCount', + ], + }, + ], + }, + + { + name: 'auxiliaryFacilities', + hideChildHeaders: false, + header: { text: '부대시설' }, + items: [ + 'preprocessingFacility', + 'odorRemovalEquipment', + 'selfGenerationEquipment', + ], + }, + 'drainageMethod', + 'storageMethod', + 'storageWaterTreatmentMethod', + 'dischargeDestination', + + { + name: 'finalDisposalAmount', + hideChildHeaders: false, + header: { text: '최종처분량(ton/년)' }, + items: [ + 'sedimentDisposalAmount', + 'debrisDisposalAmount', + ], + }, + + { + name: 'finalDisposalMethod', + hideChildHeaders: false, + header: { text: '최종처분방법' }, + items: [ + 'sedimentDisposalMethod', + 'debrisDisposalMethod', + ], + }, + + { + name: 'operationResults', + hideChildHeaders: false, + header: { text: '운영실적' }, + items: [ + 'operationDaysPerYear', + 'totalDischargePerYear', + ], + }, + 'remarks', + ], + + rowStartNum: 3, + fixedColumns: 2, + tabKey: 'sewageReservoirInp', + tabLabel: '하수저류시설', +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewerageFinance/CauserBurdenInpColumn.ts b/apps/st/src/components/util/column/input/sewerageFinance/CauserBurdenInpColumn.ts new file mode 100644 index 000000000..419f00d9d --- /dev/null +++ b/apps/st/src/components/util/column/input/sewerageFinance/CauserBurdenInpColumn.ts @@ -0,0 +1,77 @@ +import { footerInt, footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + + // 하수도 통계 관리 > 09.하수도 재정 > tab 4: 원인자 부담금 +export const CauserBurdenInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 부과액 + { name: 'LEVY_CO', fieldName: '건수', header: { text: '건수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'LEVY_AMOUNT', fieldName: '금액(백만원)', header: { text: '금액(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 대상별 징수현황 > 계 + { name: 'TRGET_LEV_STTUS_CO', fieldName: '건수', header: { text: '건수' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'TRGET_LEV_STTUS_AMOUNT', fieldName: '금액(백만원)', header: { text: '금액(백만원)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 대상별 징수현황 > 배수설비설치자 + { name: 'DRNG_EQP_CO', fieldName: '건수', header: { text: '건수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'DRNG_EQP_AMOUNT', fieldName: '금액(백만원)', header: { text: '금액(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 대상별 징수현황 > 타공사·타행위자 + { name: 'CNTRWK_CO', fieldName: '건수', header: { text: '건수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CNTRWK_AMOUNT', fieldName: '금액(백만원)', header: { text: '금액(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // hidden + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' } }, + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' } }, + + // 참조 필드 + { name: 'AMNTBRNCSR', fieldName: 'AMNTBRNCSR', header: { text: 'AMNTBRNCSR' } }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + { + name: 'group_assess', + header: { text: '부과액' }, + items: ['LEVY_CO', 'LEVY_AMOUNT'] + }, + { + name: 'group_collection', + header: { text: '대상별 징수현황' }, + items: [ + { + name: 'coll_group_total', + header: { text: '계' }, + items: ['TRGET_LEV_STTUS_CO', 'TRGET_LEV_STTUS_AMOUNT'] + }, + { + name: 'coll_group_inst', + header: { text: '배수설비설치자(하수도법 제61조 제1항)' }, + items: ['DRNG_EQP_CO', 'DRNG_EQP_AMOUNT'] + }, + { + name: 'coll_group_otr', + header: { text: '타공사·타행위자(하수도법 제61조 제2항)' }, + items: ['CNTRWK_CO', 'CNTRWK_AMOUNT'] + } + ] + }, + 'RMK' + ], + + rowStartNum: 3, + fixedColumns: 1, + tabKey: 'causerBurdenInp', + tabLabel: '원인자 부담금' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewerageFinance/SewerageChargeInpColumn.ts b/apps/st/src/components/util/column/input/sewerageFinance/SewerageChargeInpColumn.ts new file mode 100644 index 000000000..5940acc81 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewerageFinance/SewerageChargeInpColumn.ts @@ -0,0 +1,49 @@ +import { footerInt, footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 09.하수도 재정 > tab 2: 하수도 요금 +export const SewerageChargeInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 요금 + { name: 'FYER_LEVY_QY', fieldName: '연간조정량(m³)(A)', header: { text: '연간조정량(m³)(A)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'LEVY_AMOUNT', fieldName: '하수도사용료수익(원)(B)', header: { text: '하수도사용료수익(원)(B)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'AVRG_UNTPC', fieldName: 'm³당요금(원/m³) C=(B/A)', header: { text: 'm³당요금(원/m³) C=(B/A)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + { name: 'SMRIZE_PRMPC', fieldName: '총괄원가(원)(D)', header: { text: '총괄원가(원)(D)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'SMRIZE_UNIT_PRMPC', fieldName: 'm³당원가(원/m³) E=(D/A)', header: { text: 'm³당원가(원/m³) E=(D/A)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RLTY_RT', fieldName: '요금현실화율(%) F=(C/E*100)', header: { text: '요금현실화율(%) F=(C/E*100)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // hidden + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 참조 필드 + { name: 'SEWER_RNTFEE', fieldName: 'SEWER_RNTFEE', header: { text: 'SEWER_RNTFEE' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'C_LEVY_AMOUNT', fieldName: 'C_LEVY_AMOUNT', header: { text: 'C_LEVY_AMOUNT' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + ], + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'FYER_LEVY_QY', + 'LEVY_AMOUNT', + 'AVRG_UNTPC', + 'SMRIZE_PRMPC', + 'SMRIZE_UNIT_PRMPC', + 'RLTY_RT', + 'RMK' + ], + rowStartNum: 2, + fixedColumns: 1, + tabKey: 'sewerageChargeInp', + tabLabel: '하수도 요금' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewerageFinance/SewerageFinanceSettleInpColumn.ts b/apps/st/src/components/util/column/input/sewerageFinance/SewerageFinanceSettleInpColumn.ts new file mode 100644 index 000000000..24b46e1e6 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewerageFinance/SewerageFinanceSettleInpColumn.ts @@ -0,0 +1,150 @@ +import { footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 09.하수도 재정 > tab 1: 하수도 재정 결산 +export const SewerageFinanceSettleInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 재정별 사업비 + { name: 'FNANC_WCT_SM', fieldName: '계', header: { text: '계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'NTNXPN', fieldName: '중앙정부지원액', header: { text: '중앙정부지원액' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 재정별 사업비 > 지방비 + { name: 'LCLEXPNS', fieldName: '특·광역시, 도', header: { text: '특·광역시, 도' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'LCLTY_CT', fieldName: '시,군,구 지자체', header: { text: '시,군,구 지자체' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 재정별 사업비 + { name: 'SEWER_RNTFEE', fieldName: '하수도사용료', header: { text: '하수도사용료' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'AMNTBRNCSR', fieldName: '원인자부담금', header: { text: '원인자부담금' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'ETC_INCME', fieldName: '기타잡수입', header: { text: '기타잡수입' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'CYFD_AMOUNT', fieldName: '이월액', header: { text: '이월액' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 부채액 + { name: 'DEBT_AMOUNT', fieldName: '부채액(백만원)', header: { text: '부채액(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 용도별사업비 > 계 + { name: 'PRPOS_WCT_SM', fieldName: '계', header: { text: '계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 용도별사업비 > 처리장 + { name: 'PRCPLT_SM', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'PRCPLT_FCLTY', fieldName: '시설비', header: { text: '시설비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'PRCPLT_RPAIR', fieldName: '개보수비', header: { text: '개보수비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'PRCPLT_ORPNS', fieldName: '운영유지비', header: { text: '운영유지비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'PRCPLT_ETC', fieldName: '기타', header: { text: '기타' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 용도별사업비 > 하수관로 + { name: 'SEWAGE_SM', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'SEWAGE_FCLTY', fieldName: '시설비', header: { text: '시설비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'SEWAGE_RPAIR', fieldName: '개보수비', header: { text: '개보수비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'SEWAGE_ORPNS', fieldName: '운영유지비', header: { text: '운영유지비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'SEWAGE_ETC', fieldName: '기타', header: { text: '기타' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 용도별사업비 > 하수저류시설 + { name: 'SWGE_STRGE_SM', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_FCLTY', fieldName: '시설비', header: { text: '시설비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_RPAIR', fieldName: '개보수비', header: { text: '개보수비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_ORPNS', fieldName: '운영유지비', header: { text: '운영유지비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_ETC', fieldName: '기타', header: { text: '기타' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 용도별사업비 > 기타 + { name: 'ETC_SM', fieldName: '소계', header: { text: '소계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'ACDNT_CYFD_AMOUNT', fieldName: '사고이월액', header: { text: '사고이월액' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'UNRCIV_AMOUNT', fieldName: '미수납액', header: { text: '미수납액' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'ETC_AMOUNT', fieldName: '기타', header: { text: '기타' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // hidden + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 참조 필드 + { name: 'B_LEVY_AMOUNT', fieldName: 'B_LEVY_AMOUNT', header: { text: 'B_LEVY_AMOUNT' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'C_LEVY_AMOUNT', fieldName: 'C_LEVY_AMOUNT', header: { text: 'C_LEVY_AMOUNT' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'D_LEVY_AMOUNT', fieldName: 'D_LEVY_AMOUNT', header: { text: 'D_LEVY_AMOUNT' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + ], + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + { + name: 'group_finance', + header: { text: '재정별 사업비(백만원)' }, + items: [ + 'FNANC_WCT_SM', + 'NTNXPN', + { + name: 'group_local_finance', + header: { text: '지방비' }, + items: ['LCLEXPNS', 'LCLTY_CT'] + }, + 'SEWER_RNTFEE', + 'AMNTBRNCSR', + 'ETC_INCME', + 'CYFD_AMOUNT' + ] + }, + 'DEBT_AMOUNT', + { + name: 'group_purpose', + header: { text: '용도별사업비(백만원)' }, + items: [ + 'PRPOS_WCT_SM', + { + name: 'group_treatment', + header: { text: '처리장' }, + items: [ + 'PRCPLT_SM', + 'PRCPLT_FCLTY', + 'PRCPLT_RPAIR', + 'PRCPLT_ORPNS', + 'PRCPLT_ETC' + ] + }, + { + name: 'group_pipe', + header: { text: '하수관로' }, + items: [ + 'SEWAGE_SM', + 'SEWAGE_FCLTY', + 'SEWAGE_RPAIR', + 'SEWAGE_ORPNS', + 'SEWAGE_ETC' + ] + }, + { + name: 'group_storage', + header: { text: '하수저류시설' }, + items: [ + 'SWGE_STRGE_SM', + 'SWGE_STRGE_FCLTY', + 'SWGE_STRGE_RPAIR', + 'SWGE_STRGE_ORPNS', + 'SWGE_STRGE_ETC' + ] + }, + { + name: 'group_etc_purpose', + header: { text: '기타' }, + items: [ + 'ETC_SM', + 'ACDNT_CYFD_AMOUNT', + 'UNRCIV_AMOUNT', + 'ETC_AMOUNT' + ] + } + ] + }, + 'RMK' + ], + rowStartNum: 3, + fixedColumns: 1, + tabKey: 'sewerageFinanceSettleInp', + tabLabel: '하수도재정 결산' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewerageFinance/SewerageUsageFeeInpColumn.ts b/apps/st/src/components/util/column/input/sewerageFinance/SewerageUsageFeeInpColumn.ts new file mode 100644 index 000000000..bd4be4668 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewerageFinance/SewerageUsageFeeInpColumn.ts @@ -0,0 +1,240 @@ +import { footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 09.하수도 재정 > tab 3: 하수도 사용료 +export const SewerageUsageFeeInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 총계 > 부과액 + { name: 'LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 총계 > 부과량 + { name: 'LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 가정용 + { name: 'HOME_LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'HOME_LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'HOME_UNTPC', fieldName: '(원/톤)', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 업무용 + { name: 'JOB_LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'JOB_LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'JOB_UNTPC', fieldName: '(원/톤)', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 영업용(일반용) + { name: 'BSN_LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'BSN_LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'BSN_UNTPC', fieldName: '(원/톤)', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 욕탕1종(대중탕용) + { name: 'BATHS1_LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'BATHS1_LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'BATHS1_UNTPC', fieldName: '(원/톤)', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 욕탕2종 + { name: 'PBBATH_LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'PBBATH_LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'PBBATH_UNTPC', fieldName: '(원/톤)', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 산업 및 공업용 + { name: 'INDUST_LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'INDUST_LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'INDUST_UNTPC', fieldName: '(원/톤)', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 기타 + { name: 'ETC_LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'ETC_LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'ETC_UNTPC', fieldName: '(원/톤)', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // hidden + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' } }, + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' } }, + + // 참조 필드 + { name: 'SEWER_RNTFEE', fieldName: 'SEWER_RNTFEE', header: { text: 'SEWER_RNTFEE' } }, + { name: 'B_LEVY_AMOUNT', fieldName: 'B_LEVY_AMOUNT', header: { text: 'B_LEVY_AMOUNT' } }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + { + name: 'group_total', + header: { text: '총계' }, + items: [ + { + name: 'total_amount', + header: { text: '부과액' }, + items: ['LEVY_AMOUNT'] + }, + { + name: 'total_qty', + header: { text: '부과량' }, + items: ['LEVY_QY'] + } + ] + }, + { + name: 'group_home', + header: { text: '가 정 용' }, + items: [ + { + name: 'home_amount', + header: { text: '부과액' }, + items: ['HOME_LEVY_AMOUNT'] + }, + { + name: 'home_qty', + header: { text: '부과량' }, + items: ['HOME_LEVY_QY'] + }, + { + name: 'home_price', + header: { text: '단가' }, + items: ['HOME_UNTPC'] + } + ] + }, + { + name: 'group_job', + header: { text: '업 무 용' }, + items: [ + { + name: 'job_amount', + header: { text: '부과액' }, + items: ['JOB_LEVY_AMOUNT'] + }, + { + name: 'job_qty', + header: { text: '부과량' }, + items: ['JOB_LEVY_QY'] + }, + { + name: 'job_price', + header: { text: '단가' }, + items: ['JOB_UNTPC'] + } + ] + }, + { + name: 'group_business', + header: { text: '영 업 용(일 반 용)' }, + items: [ + { + name: 'bsn_amount', + header: { text: '부과액' }, + items: ['BSN_LEVY_AMOUNT'] + }, + { + name: 'bsn_qty', + header: { text: '부과량' }, + items: ['BSN_LEVY_QY'] + }, + { + name: 'bsn_price', + header: { text: '단가' }, + items: ['BSN_UNTPC'] + } + ] + }, + { + name: 'group_baths1', + header: { text: '욕 탕 1종(대중탕용)' }, + items: [ + { + name: 'baths1_amount', + header: { text: '부과액' }, + items: ['BATHS1_LEVY_AMOUNT'] + }, + { + name: 'baths1_qty', + header: { text: '부과량' }, + items: ['BATHS1_LEVY_QY'] + }, + { + name: 'baths1_price', + header: { text: '단가' }, + items: ['BATHS1_UNTPC'] + } + ] + }, + { + name: 'group_pbbath', + header: { text: '욕 탕 2종' }, + items: [ + { + name: 'pbbath_amount', + header: { text: '부과액' }, + items: ['PBBATH_LEVY_AMOUNT'] + }, + { + name: 'pbbath_qty', + header: { text: '부과량' }, + items: ['PBBATH_LEVY_QY'] + }, + { + name: 'pbbath_price', + header: { text: '단가' }, + items: ['PBBATH_UNTPC'] + } + ] + }, + { + name: 'group_industry_all', + header: { text: '산업 및 공업용' }, + items: [ + { + name: 'indust_amount', + header: { text: '부과액' }, + items: ['INDUST_LEVY_AMOUNT'] + }, + { + name: 'indust_qty', + header: { text: '부과량' }, + items: ['INDUST_LEVY_QY'] + }, + { + name: 'indust_price', + header: { text: '단가' }, + items: ['INDUST_UNTPC'] + } + ] + }, + { + name: 'group_etc', + header: { text: '기타' }, + items: [ + { + name: 'etc_amount', + header: { text: '부과액' }, + items: ['ETC_LEVY_AMOUNT'] + }, + { + name: 'etc_qty', + header: { text: '부과량' }, + items: ['ETC_LEVY_QY'] + }, + { + name: 'etc_price', + header: { text: '단가' }, + items: ['ETC_UNTPC'] + } + ] + }, + 'RMK' + ], + + rowStartNum: 3, + fixedColumns: 1, + tabKey: 'sewerageUsageFeeInp', + tabLabel: '하수도 사용료' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewerageServiceLevel/ComplaintInpColumn.ts b/apps/st/src/components/util/column/input/sewerageServiceLevel/ComplaintInpColumn.ts new file mode 100644 index 000000000..68624e658 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewerageServiceLevel/ComplaintInpColumn.ts @@ -0,0 +1,80 @@ +import { footerInt, footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 13. 하수도 서비스 수준 > tab 1: 민원 +export const ComplaintInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 행정코드 (hidden) + { name: 'ADST_CD', fieldName: '행정구역코드', header: { text: '행정구역코드' }, visible: false }, + { name: 'ADST_DONG', fieldName: '행정구역명', header: { text: '행정구역명' }, visible: false }, + + // 하수처리인구(명) + { name: 'SWGE_PROC_POPLTN', fieldName: '하수처리인구(명)', header: { text: '하수처리인구(명)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 민원유형(건) + { name: 'CVPL_CM', fieldName: '총계', header: { text: '총계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CVPL_BSML', fieldName: '악취', header: { text: '악취' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CVPL_DCWTR_QLTWTR', fieldName: '하수관로', header: { text: '하수관로' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CVPL_FIVW', fieldName: '배수설비', header: { text: '배수설비' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CVPL_POLLUTN_ACDNT', fieldName: '맨홀', header: { text: '맨홀' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CVPL_SSOS', fieldName: '정화조', header: { text: '정화조' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CVPL_CHRGE', fieldName: '하수도요금', header: { text: '하수도요금' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CVPL_UNKD', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 기준인구당 민원건수(건/10,000명) + { name: 'STDR_POPLTN_PER_CVPL', fieldName: '기준인구당민원건수(건/10,000명)', header: { text: '기준인구당민원건수(건/10,000명)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 필드 + { name: 'WRTER_OPINION', fieldName: '작성자의견', header: { text: '작성자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_SWGE_PROC_POPLTN', fieldName: 'CHK_SWGE_PROC_POPLTN', header: { text: 'CHK_SWGE_PROC_POPLTN' }, visible: false }, + { name: 'CHK_CVPL_CM', fieldName: 'CHK_CVPL_CM', header: { text: 'CHK_CVPL_CM' }, visible: false }, + { name: 'CHK_CVPL_BSML', fieldName: 'CHK_CVPL_BSML', header: { text: 'CHK_CVPL_BSML' }, visible: false }, + { name: 'CHK_CVPL_DCWTR_QLTWTR', fieldName: 'CHK_CVPL_DCWTR_QLTWTR', header: { text: 'CHK_CVPL_DCWTR_QLTWTR' }, visible: false }, + { name: 'CHK_CVPL_FIVW', fieldName: 'CHK_CVPL_FIVW', header: { text: 'CHK_CVPL_FIVW' }, visible: false }, + { name: 'CHK_CVPL_POLLUTN_ACDNT', fieldName: 'CHK_CVPL_POLLUTN_ACDNT', header: { text: 'CHK_CVPL_POLLUTN_ACDNT' }, visible: false }, + { name: 'CHK_CVPL_SSOS', fieldName: 'CHK_CVPL_SSOS', header: { text: 'CHK_CVPL_SSOS' }, visible: false }, + { name: 'CHK_CVPL_CHRGE', fieldName: 'CHK_CVPL_CHRGE', header: { text: 'CHK_CVPL_CHRGE' }, visible: false }, + { name: 'CHK_CVPL_UNKD', fieldName: 'CHK_CVPL_UNKD', header: { text: 'CHK_CVPL_UNKD' }, visible: false }, + { name: 'CHK_STDR_POPLTN_PER_CVPL', fieldName: 'CHK_STDR_POPLTN_PER_CVPL', header: { text: 'CHK_STDR_POPLTN_PER_CVPL' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'SWGE_PROC_POPLTN', + { + name: 'group_complaint_type', + header: { text: '민원유형(건)' }, + items: [ + 'CVPL_CM', + 'CVPL_BSML', + 'CVPL_DCWTR_QLTWTR', + 'CVPL_FIVW', + 'CVPL_POLLUTN_ACDNT', + 'CVPL_SSOS', + 'CVPL_CHRGE', + 'CVPL_UNKD' + ] + }, + 'STDR_POPLTN_PER_CVPL', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 1, + tabKey: 'complaintInp', + tabLabel: '민원' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/sewerageServiceLevel/ResidentFriendlyFactInpColumn.ts b/apps/st/src/components/util/column/input/sewerageServiceLevel/ResidentFriendlyFactInpColumn.ts new file mode 100644 index 000000000..3f59e6b07 --- /dev/null +++ b/apps/st/src/components/util/column/input/sewerageServiceLevel/ResidentFriendlyFactInpColumn.ts @@ -0,0 +1,89 @@ +import { footerInt, footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 13. 하수도 서비스 수준 > tab 2: 주민친화시설 +export const ResidentFriendlyFactInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 시설 기본 정보 + { name: 'BSC_FCT_NM', fieldName: '처리장명', header: { text: '처리장명' }, editable: false }, + { name: 'FCT_CPC', fieldName: '시설용량(m³/일)', header: { text: '시설용량(m³/일)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 처리장면적(㎡) + { name: 'PRCPLT_AR', fieldName: '처리장면적(㎡)', header: { text: '처리장면적(㎡)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 주민친화시설 면적(㎡) + { name: 'TOTAL_AR', fieldName: '총계', header: { text: '총계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'RESTRM_AR', fieldName: '휴게시설', header: { text: '휴게시설' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CHILDPLAY_AR', fieldName: '어린이놀이공간', header: { text: '어린이놀이공간' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ALSFC_AR', fieldName: '체력단련시설', header: { text: '체력단련시설' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'PLGRND_AR', fieldName: '운동시설', header: { text: '운동시설' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'PRKPLCE_AR', fieldName: '주차장', header: { text: '주차장' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'CTLSTT_AR', fieldName: '교육 및 문화시설', header: { text: '교육 및 문화시설' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'NRPRK_AR', fieldName: '습지조성(생태공원)', header: { text: '습지조성(생태공원)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'ETC_AR', fieldName: '기타', header: { text: '기타' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 시설 정보 + { name: 'STPN_SEQ', fieldName: '일련번호', header: { text: '일련번호' }, visible: false }, + { name: 'ADST_CD', fieldName: '행정동코드', header: { text: '행정동코드' }, visible: false }, + { name: 'BSC_FCT_CD', fieldName: '기초시설코드', header: { text: '기초시설코드' }, visible: false }, + + // Hidden: 의견 필드 + { name: 'WRTER_OPINION', fieldName: '작성자의견', header: { text: '작성자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: 활용율 필드 + { name: 'PRCUSE_RT', fieldName: '주민친화시설활용율(%)', header: { text: '주민친화시설활용율(%)' }, visible: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_PRCPLT_AR', fieldName: 'CHK_PRCPLT_AR', header: { text: 'CHK_PRCPLT_AR' }, visible: false }, + { name: 'CHK_TOTAL_AR', fieldName: 'CHK_TOTAL_AR', header: { text: 'CHK_TOTAL_AR' }, visible: false }, + { name: 'CHK_RESTRM_AR', fieldName: 'CHK_RESTRM_AR', header: { text: 'CHK_RESTRM_AR' }, visible: false }, + { name: 'CHK_CHILDPLAY_AR', fieldName: 'CHK_CHILDPLAY_AR', header: { text: 'CHK_CHILDPLAY_AR' }, visible: false }, + { name: 'CHK_ALSFC_AR', fieldName: 'CHK_ALSFC_AR', header: { text: 'CHK_ALSFC_AR' }, visible: false }, + { name: 'CHK_PLGRND_AR', fieldName: 'CHK_PLGRND_AR', header: { text: 'CHK_PLGRND_AR' }, visible: false }, + { name: 'CHK_PRKPLCE_AR', fieldName: 'CHK_PRKPLCE_AR', header: { text: 'CHK_PRKPLCE_AR' }, visible: false }, + { name: 'CHK_CTLSTT_AR', fieldName: 'CHK_CTLSTT_AR', header: { text: 'CHK_CTLSTT_AR' }, visible: false }, + { name: 'CHK_NRPRK_AR', fieldName: 'CHK_NRPRK_AR', header: { text: 'CHK_NRPRK_AR' }, visible: false }, + { name: 'CHK_ETC_AR', fieldName: 'CHK_ETC_AR', header: { text: 'CHK_ETC_AR' }, visible: false }, + { name: 'CHK_PRCUSE_RT', fieldName: 'CHK_PRCUSE_RT', header: { text: 'CHK_PRCUSE_RT' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'BSC_FCT_NM', + 'FCT_CPC', + 'PRCPLT_AR', + { + name: 'group_resident_friendly_facility', + header: { text: '주민친화시설 면적(㎡)' }, + items: [ + 'TOTAL_AR', + 'RESTRM_AR', + 'CHILDPLAY_AR', + 'ALSFC_AR', + 'PLGRND_AR', + 'PRKPLCE_AR', + 'CTLSTT_AR', + 'NRPRK_AR', + 'ETC_AR' + ] + }, + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 3, + tabKey: 'residentFriendlyFactInp', + tabLabel: '주민친화시설' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/waterReuse/PublicSewageTreatWaterReuseInpColumn.ts b/apps/st/src/components/util/column/input/waterReuse/PublicSewageTreatWaterReuseInpColumn.ts new file mode 100644 index 000000000..0e6da19f4 --- /dev/null +++ b/apps/st/src/components/util/column/input/waterReuse/PublicSewageTreatWaterReuseInpColumn.ts @@ -0,0 +1,176 @@ +import { footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 10. 물 재이용 > tab 1: 공공하수처리수 재이용 +export const PublicSewageTreatWaterReuseInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } }, + + // 하수처리장 + { name: 'BSC_FCT_NM', fieldName: '시설명', header: { text: '시설명' }, editable: false }, + { name: 'EQP_PRMS_DT', fieldName: '인가일(년/월/일)', header: { text: '인가일(년/월/일)' }, editable: false }, + { name: 'FCT_CPC', fieldName: '시설용량(㎥/일)', header: { text: '시설용량(㎥/일)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'TPUT_TOTAL', fieldName: '연간하수처리량(천톤/년)', header: { text: '연간하수처리량(천톤/년)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RSWTR_LAW_YN', fieldName: '법적의무대상(대상/미대상)', header: { text: '법적의무대상(대상/미대상)' } }, + + // 재이용시설 > 설치유무 + { name: 'INST_YN', fieldName: '설치유무(유/무)', header: { text: '설치유무(유/무)' } }, + + // 재이용시설 > 재이용시설 설치시 + { name: 'RSWTR_RN_DT', fieldName: '가동개시일(yyyy-mm-dd)', header: { text: '가동개시일(yyyy-mm-dd)' } }, + { name: 'RSWTR_PRMS_DT', fieldName: '설치승인일(yyyy-mm-dd)', header: { text: '설치승인일(yyyy-mm-dd)' } }, + + // 재이용시설 > 재이용시설 설치시 > 재처리시설 + { name: 'RSWTR_CPC', fieldName: '용량(톤/일)', header: { text: '용량(톤/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RSWTR_TRT_NM', fieldName: '공법/기자재', header: { text: '공법/기자재' } }, + + // 재이용시설 > 재이용시설 설치시 + { name: 'RSWTR_PIPE', fieldName: '공급관로길이(km)', header: { text: '공급관로길이(km)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'RSWTR_PUMP', fieldName: '공급펌프(톤/일)', header: { text: '공급펌프(톤/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 하수처리수 재이용현황 > 총계 + { name: 'USE_AMNT_TOTAL', fieldName: '총계', header: { text: '총계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 하수처리수 재이용현황 > 장내용수 + { name: 'USE_AMNT_D01', fieldName: '계', header: { text: '계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S01', fieldName: '세척수', header: { text: '세척수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S02', fieldName: '냉각수', header: { text: '냉각수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S03', fieldName: '청소수', header: { text: '청소수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S04', fieldName: '조경용수', header: { text: '조경용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, // (레거시) 식수대 + { name: 'USE_AMNT_S05', fieldName: '희석용수', header: { text: '희석용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S06', fieldName: '장내중수도', header: { text: '장내중수도' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S07', fieldName: '장내기타용수', header: { text: '장내기타용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 하수처리수 재이용현황 > 장외용수 + { name: 'USE_AMNT_D02', fieldName: '계', header: { text: '계' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S11', fieldName: '청소·화장실용수', header: { text: '청소·화장실용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S12', fieldName: '세척·살수용수', header: { text: '세척·살수용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S13', fieldName: '조경용수', header: { text: '조경용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S14', fieldName: '친수용수', header: { text: '친수용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S15', fieldName: '하천등유지용수', header: { text: '하천등유지용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S16', fieldName: '농업용수', header: { text: '농업용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S17', fieldName: '지하수충전', header: { text: '지하수충전' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'USE_AMNT_S18', fieldName: '공업용수', header: { text: '공업용수' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 재이용률 + { name: 'REUSE_RT', fieldName: '재이용률(%)', header: { text: '재이용률(%)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_RSWTR_LAW_YN', fieldName: 'CHK_RSWTR_LAW_YN', header: { text: 'CHK_RSWTR_LAW_YN' }, visible: false }, + { name: 'CHK_INST_YN', fieldName: 'CHK_INST_YN', header: { text: 'CHK_INST_YN' }, visible: false }, + { name: 'CHK_RSWTR_RN_DT', fieldName: 'CHK_RSWTR_RN_DT', header: { text: 'CHK_RSWTR_RN_DT' }, visible: false }, + { name: 'CHK_RSWTR_PRMS_DT', fieldName: 'CHK_RSWTR_PRMS_DT', header: { text: 'CHK_RSWTR_PRMS_DT' }, visible: false }, + { name: 'CHK_RSWTR_CPC', fieldName: 'CHK_RSWTR_CPC', header: { text: 'CHK_RSWTR_CPC' }, visible: false }, + { name: 'CHK_RSWTR_TRT_NM', fieldName: 'CHK_RSWTR_TRT_NM', header: { text: 'CHK_RSWTR_TRT_NM' }, visible: false }, + { name: 'CHK_RSWTR_PIPE', fieldName: 'CHK_RSWTR_PIPE', header: { text: 'CHK_RSWTR_PIPE' }, visible: false }, + { name: 'CHK_RSWTR_PUMP', fieldName: 'CHK_RSWTR_PUMP', header: { text: 'CHK_RSWTR_PUMP' }, visible: false }, + { name: 'CHK_TPUT_TOTAL', fieldName: 'CHK_TPUT_TOTAL', header: { text: 'CHK_TPUT_TOTAL' }, visible: false }, + { name: 'CHK_USE_AMNT_S01', fieldName: 'CHK_USE_AMNT_S01', header: { text: 'CHK_USE_AMNT_S01' }, visible: false }, + { name: 'CHK_USE_AMNT_S02', fieldName: 'CHK_USE_AMNT_S02', header: { text: 'CHK_USE_AMNT_S02' }, visible: false }, + { name: 'CHK_USE_AMNT_S03', fieldName: 'CHK_USE_AMNT_S03', header: { text: 'CHK_USE_AMNT_S03' }, visible: false }, + { name: 'CHK_USE_AMNT_S04', fieldName: 'CHK_USE_AMNT_S04', header: { text: 'CHK_USE_AMNT_S04' }, visible: false }, + { name: 'CHK_USE_AMNT_S05', fieldName: 'CHK_USE_AMNT_S05', header: { text: 'CHK_USE_AMNT_S05' }, visible: false }, + { name: 'CHK_USE_AMNT_S06', fieldName: 'CHK_USE_AMNT_S06', header: { text: 'CHK_USE_AMNT_S06' }, visible: false }, + { name: 'CHK_USE_AMNT_S07', fieldName: 'CHK_USE_AMNT_S07', header: { text: 'CHK_USE_AMNT_S07' }, visible: false }, + { name: 'CHK_USE_AMNT_S11', fieldName: 'CHK_USE_AMNT_S11', header: { text: 'CHK_USE_AMNT_S11' }, visible: false }, + { name: 'CHK_USE_AMNT_S12', fieldName: 'CHK_USE_AMNT_S12', header: { text: 'CHK_USE_AMNT_S12' }, visible: false }, + { name: 'CHK_USE_AMNT_S13', fieldName: 'CHK_USE_AMNT_S13', header: { text: 'CHK_USE_AMNT_S13' }, visible: false }, + { name: 'CHK_USE_AMNT_S14', fieldName: 'CHK_USE_AMNT_S14', header: { text: 'CHK_USE_AMNT_S14' }, visible: false }, + { name: 'CHK_USE_AMNT_S15', fieldName: 'CHK_USE_AMNT_S15', header: { text: 'CHK_USE_AMNT_S15' }, visible: false }, + { name: 'CHK_USE_AMNT_S16', fieldName: 'CHK_USE_AMNT_S16', header: { text: 'CHK_USE_AMNT_S16' }, visible: false }, + { name: 'CHK_USE_AMNT_S17', fieldName: 'CHK_USE_AMNT_S17', header: { text: 'CHK_USE_AMNT_S17' }, visible: false }, + { name: 'CHK_USE_AMNT_S18', fieldName: 'CHK_USE_AMNT_S18', header: { text: 'CHK_USE_AMNT_S18' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + { + name: 'group_facility', + header: { text: '하수처리장' }, + items: [ + 'BSC_FCT_NM', + 'EQP_PRMS_DT', + 'FCT_CPC', + 'RSWTR_LAW_YN' + ] + }, + { + name: 'group_reuse_facility', + header: { text: '재이용시설' }, + items: [ + 'INST_YN', + { + name: 'group_reuse_install', + header: { text: '재이용시설 설치시' }, + items: [ + 'RSWTR_RN_DT', + 'RSWTR_PRMS_DT', + { + name: 'group_treatment_facility', + header: { text: '처리시설' }, + items: [ + 'RSWTR_CPC', + 'RSWTR_TRT_NM' + ] + }, + 'RSWTR_PIPE', + 'RSWTR_PUMP' + ] + } + ] + }, + 'TPUT_TOTAL', + { + name: 'group_reuse_current', + header: { text: '하수처리수 재이용현황(천톤/년)' }, + items: [ + 'USE_AMNT_TOTAL', + { + name: 'group_indoor_use', + header: { text: '장 내 용 수' }, + items: [ + 'USE_AMNT_D01', + 'USE_AMNT_S01', + 'USE_AMNT_S02', + 'USE_AMNT_S03', + 'USE_AMNT_S04', + 'USE_AMNT_S05', + 'USE_AMNT_S06', + 'USE_AMNT_S07' + ] + }, + { + name: 'group_outdoor_use', + header: { text: '장 외 용 수' }, + items: [ + 'USE_AMNT_D02', + 'USE_AMNT_S11', + 'USE_AMNT_S12', + 'USE_AMNT_S13', + 'USE_AMNT_S14', + 'USE_AMNT_S15', + 'USE_AMNT_S16', + 'USE_AMNT_S17', + 'USE_AMNT_S18' + ] + } + ] + }, + 'REUSE_RT', + 'RMK' + ], + + rowStartNum: 4, + fixedColumns: 0, + tabKey: 'publicSewageTreatWaterReuseInp', + tabLabel: '공공하수처리수 재이용' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/waterReuse/RainFallUtilFactStatusInpColumn.ts b/apps/st/src/components/util/column/input/waterReuse/RainFallUtilFactStatusInpColumn.ts new file mode 100644 index 000000000..10dc53ccd --- /dev/null +++ b/apps/st/src/components/util/column/input/waterReuse/RainFallUtilFactStatusInpColumn.ts @@ -0,0 +1,120 @@ +import { footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 10. 물 재이용 > tab 3: 빗물이용시설현황 +export const RainFallUtilFactStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } }, + + // 행정코드 (hidden) + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' }, visible: false }, + { name: 'ADST_DSTR_CD', fieldName: '행정구역코드', header: { text: '행정구역코드' }, visible: false }, + { name: 'ST_RWR_REUSE_FCT_SEQ', fieldName: '일련번호', header: { text: '일련번호' }, visible: false }, + + // 시설명 + { name: 'RWR_REUSE_FCT_NM', fieldName: '시설명', header: { text: '시설명' } }, + + // 건축물용도 + { name: 'BILD_TP', fieldName: '건축물용도', header: { text: '건축물용도' } }, + + // 위치(주소) + { name: 'ADDR', fieldName: '위치(주소)', header: { text: '위치(주소)' } }, + + // 법적의무대상여부(대상/미대상) + { name: 'LAW_YN', fieldName: '법적의무대상여부(대상/미대상)', header: { text: '법적의무대상여부(대상/미대상)' } }, + + // 설치완료일 yyyy-mm-dd + { name: 'RN_DT', fieldName: '설치완료일 yyyy-mm-dd', header: { text: '설치완료일 yyyy-mm-dd' } }, + + // 설치비(백만원) + { name: 'INSTL_CT', fieldName: '설치비(백만원)', header: { text: '설치비(백만원)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 집수면 종류 + { name: 'CCM', fieldName: '집수면 종류', header: { text: '집수면 종류' } }, + + // 여과등처리시설유무(유:처리시설종류,무:미설치) + { name: 'TRTFC_ENNC', fieldName: '여과등처리시설유무(유:처리시설종류,무:미설치)', header: { text: '여과등처리시설유무(유:처리시설종류,무:미설치)' } }, + + // 저류조용량(m³) + { name: 'SGBS_CPCTY', fieldName: '저류조용량(m³)', header: { text: '저류조용량(m³)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 연간이용량(m³/년) + { name: 'FYER_USEQTY', fieldName: '연간이용량(m³/년)', header: { text: '연간이용량(m³/년)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 이용용도 + { name: 'RWR_PRCUSE_PRPPOS', fieldName: '이용용도', header: { text: '이용용도' } }, + + // 연간운영비(백만원/년) + { name: 'FYER_OPER_CT', fieldName: '연간운영비(백만원/년)', header: { text: '연간운영비(백만원/년)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 필드 + { name: 'WRTER_OPINION', fieldName: '작성자의견', header: { text: '작성자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: 용도별 이용량 (화면에 표시 안 함) + { name: 'FYER_USE_01', fieldName: '빗물사용 1', header: { text: '빗물사용 1' }, visible: false }, + { name: 'FYER_USE_02', fieldName: '빗물사용 2', header: { text: '빗물사용 2' }, visible: false }, + { name: 'FYER_USE_03', fieldName: '빗물사용 3', header: { text: '빗물사용 3' }, visible: false }, + { name: 'FYER_USE_04', fieldName: '빗물사용 4', header: { text: '빗물사용 4' }, visible: false }, + { name: 'FYER_USE_05', fieldName: '빗물사용 5', header: { text: '빗물사용 5' }, visible: false }, + { name: 'FYER_USE_06', fieldName: '빗물사용 6', header: { text: '빗물사용 6' }, visible: false }, + { name: 'FYER_USE_07', fieldName: '빗물사용 7', header: { text: '빗물사용 7' }, visible: false }, + + // Hidden: 인가일 (화면에 표시 안 함) + { name: 'PERMIT_DT', fieldName: '인가일', header: { text: '인가일' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_RWR_REUSE_FCT_NM', fieldName: 'CHK_RWR_REUSE_FCT_NM', header: { text: 'CHK_RWR_REUSE_FCT_NM' }, visible: false }, + { name: 'CHK_ADDR', fieldName: 'CHK_ADDR', header: { text: 'CHK_ADDR' }, visible: false }, + { name: 'CHK_RN_DT', fieldName: 'CHK_RN_DT', header: { text: 'CHK_RN_DT' }, visible: false }, + { name: 'CHK_INSTL_CT', fieldName: 'CHK_INSTL_CT', header: { text: 'CHK_INSTL_CT' }, visible: false }, + { name: 'CHK_CCM', fieldName: 'CHK_CCM', header: { text: 'CHK_CCM' }, visible: false }, + { name: 'CHK_CCM_AR', fieldName: 'CHK_CCM_AR', header: { text: 'CHK_CCM_AR' }, visible: false }, + { name: 'CHK_TRTFC_ENNC', fieldName: 'CHK_TRTFC_ENNC', header: { text: 'CHK_TRTFC_ENNC' }, visible: false }, + { name: 'CHK_SGBS_CPCTY', fieldName: 'CHK_SGBS_CPCTY', header: { text: 'CHK_SGBS_CPCTY' }, visible: false }, + { name: 'CHK_FYER_USEQTY', fieldName: 'CHK_FYER_USEQTY', header: { text: 'CHK_FYER_USEQTY' }, visible: false }, + { name: 'CHK_RWR_PRCUSE_PRPPOS', fieldName: 'CHK_RWR_PRCUSE_PRPPOS', header: { text: 'CHK_RWR_PRCUSE_PRPPOS' }, visible: false }, + { name: 'CHK_FYER_OPER_CT', fieldName: 'CHK_FYER_OPER_CT', header: { text: 'CHK_FYER_OPER_CT' }, visible: false }, + { name: 'CHK_LAW_YN', fieldName: 'CHK_LAW_YN', header: { text: 'CHK_LAW_YN' }, visible: false }, + { name: 'CHK_BILD_TP', fieldName: 'CHK_BILD_TP', header: { text: 'CHK_BILD_TP' }, visible: false }, + { name: 'CHK_PERMIT_DT', fieldName: 'CHK_PERMIT_DT', header: { text: 'CHK_PERMIT_DT' }, visible: false }, + { name: 'CHK_FYER_USE_01', fieldName: 'CHK_FYER_USE_01', header: { text: 'CHK_FYER_USE_01' }, visible: false }, + { name: 'CHK_FYER_USE_02', fieldName: 'CHK_FYER_USE_02', header: { text: 'CHK_FYER_USE_02' }, visible: false }, + { name: 'CHK_FYER_USE_03', fieldName: 'CHK_FYER_USE_03', header: { text: 'CHK_FYER_USE_03' }, visible: false }, + { name: 'CHK_FYER_USE_04', fieldName: 'CHK_FYER_USE_04', header: { text: 'CHK_FYER_USE_04' }, visible: false }, + { name: 'CHK_FYER_USE_05', fieldName: 'CHK_FYER_USE_05', header: { text: 'CHK_FYER_USE_05' }, visible: false }, + { name: 'CHK_FYER_USE_06', fieldName: 'CHK_FYER_USE_06', header: { text: 'CHK_FYER_USE_06' }, visible: false }, + { name: 'CHK_FYER_USE_07', fieldName: 'CHK_FYER_USE_07', header: { text: 'CHK_FYER_USE_07' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'RWR_REUSE_FCT_NM', + 'BILD_TP', + 'ADDR', + 'LAW_YN', + 'RN_DT', + 'INSTL_CT', + 'CCM', + 'TRTFC_ENNC', + 'SGBS_CPCTY', + 'FYER_USEQTY', + 'RWR_PRCUSE_PRPPOS', + 'FYER_OPER_CT', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 0, + tabKey: 'rainFallUtilFactStatusInp', + tabLabel: '빗물이용시설현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/waterReuse/RecycledWaterStatusInpColumn.ts b/apps/st/src/components/util/column/input/waterReuse/RecycledWaterStatusInpColumn.ts new file mode 100644 index 000000000..5ec78024c --- /dev/null +++ b/apps/st/src/components/util/column/input/waterReuse/RecycledWaterStatusInpColumn.ts @@ -0,0 +1,109 @@ +import { footerDecimal1 } from "@/components/util/grid/footerSummary"; +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 > 10. 물 재이용 > tab 2: 중수도 현황 +export const RecycledWaterStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } }, + + // 행정코드 (hidden) + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' }, visible: false }, + { name: 'ADST_DSTR_CD', fieldName: '행정구역코드', header: { text: '행정구역코드' }, visible: false }, + { name: 'RUSWTR_FCT_SEQ', fieldName: '일련번호', header: { text: '일련번호' }, visible: false }, + + // 건축물명/개발사업명 + { name: 'BILD_NM', fieldName: '건축물명/개발사업명', header: { text: '건축물명/개발사업명' } }, + + // 시설물용도/개발사업종류 + { name: 'BILD_TP', fieldName: '시설물용도/개발사업종류', header: { text: '시설물용도/개발사업종류' } }, + + // 주소 + { name: 'ADDR', fieldName: '주소', header: { text: '주소' } }, + + // 법적의무대상여부(대상/미대상) + { name: 'LAW_YN', fieldName: '법적의무대상여부(대상/미대상)', header: { text: '법적의무대상여부(대상/미대상)' } }, + + // 설치완료일(년-월-일) + { name: 'COMP_DT', fieldName: '설치완료일(년-월-일)', header: { text: '설치완료일(년-월-일)' } }, + + // 가동개시일(년-월-일) + { name: 'RN_DT', fieldName: '가동개시일(년-월-일)', header: { text: '가동개시일(년-월-일)' } }, + + // 시설현황 + { name: 'TOTAR', fieldName: '건축연면적(m²)', header: { text: '건축연면적(m²)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + { name: 'PROC_CPCTY', fieldName: '처리용량(m³/일)', header: { text: '처리용량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 물 사용량(m³/일) + { name: 'WATER_USE_CPCTY', fieldName: '물 사용량(m³/일)', header: { text: '물 사용량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 중수도이용량(m³/일) + { name: 'RUSWTR_USE_CPCTY', fieldName: '중수도이용량(m³/일)', header: { text: '중수도이용량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 대체수이용량(m³/일) + { name: 'SUB_USE_CPCTY', fieldName: '대체수이용량(m³/일)', header: { text: '대체수이용량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 중수도용도 + { name: 'RUSWTR_PRPOS', fieldName: '중수도용도', header: { text: '중수도용도' } }, + + // 연간운영비(백만원/년) + { name: 'FYER_OPER_CT', fieldName: '연간운영비(백만원/년)', header: { text: '연간운영비(백만원/년)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 사용자의견, 검토자의견 + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, visible: false }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_BILD_NM', fieldName: 'CHK_BILD_NM', header: { text: 'CHK_BILD_NM' }, visible: false }, + { name: 'CHK_ADDR', fieldName: 'CHK_ADDR', header: { text: 'CHK_ADDR' }, visible: false }, + { name: 'CHK_TOTAR', fieldName: 'CHK_TOTAR', header: { text: 'CHK_TOTAR' }, visible: false }, + { name: 'CHK_PROC_CPCTY', fieldName: 'CHK_PROC_CPCTY', header: { text: 'CHK_PROC_CPCTY' }, visible: false }, + { name: 'CHK_RUSWTR_USE_CPCTY', fieldName: 'CHK_RUSWTR_USE_CPCTY', header: { text: 'CHK_RUSWTR_USE_CPCTY' }, visible: false }, + { name: 'CHK_COMP_DT', fieldName: 'CHK_COMP_DT', header: { text: 'CHK_COMP_DT' }, visible: false }, + { name: 'CHK_RN_DT', fieldName: 'CHK_RN_DT', header: { text: 'CHK_RN_DT' }, visible: false }, + { name: 'CHK_RUSWTR_PRPOS', fieldName: 'CHK_RUSWTR_PRPOS', header: { text: 'CHK_RUSWTR_PRPOS' }, visible: false }, + { name: 'CHK_LAW_YN', fieldName: 'CHK_LAW_YN', header: { text: 'CHK_LAW_YN' }, visible: false }, + { name: 'CHK_BILD_TP', fieldName: 'CHK_BILD_TP', header: { text: 'CHK_BILD_TP' }, visible: false }, + { name: 'CHK_PERMIT_DT', fieldName: 'CHK_PERMIT_DT', header: { text: 'CHK_PERMIT_DT' }, visible: false }, + { name: 'CHK_FYER_OPER_CT', fieldName: 'CHK_FYER_OPER_CT', header: { text: 'CHK_FYER_OPER_CT' }, visible: false }, + { name: 'CHK_WATER_USE_CPCTY', fieldName: 'CHK_WATER_USE_CPCTY', header: { text: 'CHK_WATER_USE_CPCTY' }, visible: false }, + { name: 'CHK_SUB_USE_CPCTY', fieldName: 'CHK_SUB_USE_CPCTY', header: { text: 'CHK_SUB_USE_CPCTY' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'BILD_NM', + 'BILD_TP', + 'ADDR', + 'LAW_YN', + 'COMP_DT', + 'RN_DT', + { + name: 'group_facility_status', + header: { text: '시설현황' }, + items: [ + 'TOTAR', + 'PROC_CPCTY' + ] + }, + 'WATER_USE_CPCTY', + 'RUSWTR_USE_CPCTY', + 'SUB_USE_CPCTY', + 'RUSWTR_PRPOS', + 'FYER_OPER_CT', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 0, + tabKey: 'recycledWaterStatusInp', + tabLabel: '중수도 현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/waterReuse/TreatWaterReuseBusinessApprStatusInpColumn.ts b/apps/st/src/components/util/column/input/waterReuse/TreatWaterReuseBusinessApprStatusInpColumn.ts new file mode 100644 index 000000000..7144c1edc --- /dev/null +++ b/apps/st/src/components/util/column/input/waterReuse/TreatWaterReuseBusinessApprStatusInpColumn.ts @@ -0,0 +1,57 @@ +// 하수도 통계 관리 > 10. 물 재이용 > tab 5: 하·폐수처리수 재이용사업 인가현황 +export const TreatWaterReuseBusinessApprStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + + // 행정코드 (hidden) + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' }, visible: false }, + { name: 'ADST_DSTR_CD', fieldName: '행정구역코드', header: { text: '행정구역코드' }, visible: false }, + { name: 'SIDO_CD', fieldName: '시도코드', header: { text: '시도코드' }, visible: false }, + { name: 'REUSE_CMPN_SEQ', fieldName: '일련번호', header: { text: '일련번호' }, visible: false }, + + // 상호(명칭) + { name: 'CMPNM', fieldName: '상호(명칭)', header: { text: '상호(명칭)' } }, + + // 대표자 + { name: 'RPRSNTV', fieldName: '대표자', header: { text: '대표자' } }, + + // 주소 + { name: 'ADDR', fieldName: '주소', header: { text: '주소' } }, + + // 인가일 + { name: 'CMPN_RGSDE', fieldName: '인가일 yyyy-mm-dd', header: { text: '인가일 yyyy-mm-dd' } }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 필드 + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_CMPNM', fieldName: 'CHK_CMPNM', header: { text: 'CHK_CMPNM' }, visible: false }, + { name: 'CHK_RPRSNTV', fieldName: 'CHK_RPRSNTV', header: { text: 'CHK_RPRSNTV' }, visible: false }, + { name: 'CHK_ADDR', fieldName: 'CHK_ADDR', header: { text: 'CHK_ADDR' }, visible: false }, + { name: 'CHK_CMPN_RGSDE', fieldName: 'CHK_CMPN_RGSDE', header: { text: 'CHK_CMPN_RGSDE' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'CMPNM', + 'RPRSNTV', + 'ADDR', + 'CMPN_RGSDE', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 0, + tabKey: 'treatWaterReuseBusinessApprStatusInp', + tabLabel: '하·폐수처리수 재이용사업 인가현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/input/waterReuse/TreatWaterReuseDesignConstStatusInpColumn.ts b/apps/st/src/components/util/column/input/waterReuse/TreatWaterReuseDesignConstStatusInpColumn.ts new file mode 100644 index 000000000..15a3b12b2 --- /dev/null +++ b/apps/st/src/components/util/column/input/waterReuse/TreatWaterReuseDesignConstStatusInpColumn.ts @@ -0,0 +1,57 @@ +// 하수도 통계 관리 > 10. 물 재이용 > tab 4: 하·폐수처리수 재이용시설 설계시공업 등록현황 +export const TreatWaterReuseDesignConstStatusInpColumn = { + columns: [ + // 행정구역 + { name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false }, // editable 임의로 + + // 행정코드 (hidden) + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' }, visible: false }, + { name: 'ADST_DSTR_CD', fieldName: '행정구역코드', header: { text: '행정구역코드' }, visible: false }, + { name: 'SIDO_CD', fieldName: '시도코드', header: { text: '시도코드' }, visible: false }, + { name: 'PLCST_CMPNY_SEQ', fieldName: '일련번호', header: { text: '일련번호' }, visible: false }, + + // 상호(명칭) + { name: 'CMPNM', fieldName: '상호(명칭)', header: { text: '상호(명칭)' } }, + + // 대표자 + { name: 'RPRSNTV', fieldName: '대표자', header: { text: '대표자' } }, + + // 주소 + { name: 'ADDR', fieldName: '주소', header: { text: '주소' } }, + + // 등록일 yyyy-mm-dd + { name: 'CMPN_RGSDE', fieldName: '등록일 yyyy-mm-dd', header: { text: '등록일 yyyy-mm-dd' } }, + + // 비고 + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + + // Hidden: 의견 필드 + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' }, visible: false }, + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' }, visible: false }, + + // Hidden: Check fields : 데이터 변경 여부를 판단하는 필드로, UI에서 숨김 처리 + { name: 'CHK_CMPNM', fieldName: 'CHK_CMPNM', header: { text: 'CHK_CMPNM' }, visible: false }, + { name: 'CHK_RPRSNTV', fieldName: 'CHK_RPRSNTV', header: { text: 'CHK_RPRSNTV' }, visible: false }, + { name: 'CHK_ADDR', fieldName: 'CHK_ADDR', header: { text: 'CHK_ADDR' }, visible: false }, + { name: 'CHK_CMPN_RGSDE', fieldName: 'CHK_CMPN_RGSDE', header: { text: 'CHK_CMPN_RGSDE' }, visible: false }, + ], + + columnLayout: [ + { + name: 'group_admin', + header: { text: '행정구역' }, + items: ['SIDO', 'GUGUN'] + }, + 'CMPNM', + 'RPRSNTV', + 'ADDR', + 'CMPN_RGSDE', + 'RMK' + ], + + rowStartNum: 2, + fixedColumns: 0, + tabKey: 'treatWaterReuseDesignConstStatusInp', + tabLabel: '하·폐수처리수 재이용시설 설계시공업 등록현황' +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/ExcretaTreatmentFacilityRvwColumn.ts b/apps/st/src/components/util/column/review/ExcretaTreatmentFacilityRvwColumn.ts new file mode 100644 index 000000000..3cf7f9343 --- /dev/null +++ b/apps/st/src/components/util/column/review/ExcretaTreatmentFacilityRvwColumn.ts @@ -0,0 +1,118 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 07.분뇨처리 시설 +const rawServiceLevelList = [ + { + tabKey: 'a', + tabLabel: '민원', + rowStartNum: 2, + fixedColumns: 2, + columns: [ + /* 1. 기본 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 2. 하수처리 인구 */ + { name: 'POPLTN_SM', fieldName: '하수처리인구(명)', header: { text: '하수처리인구\n(명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 3. 민원유형 (단위: 건) */ + { name: 'CVPL_CM', fieldName: '총계(민원)', header: { text: '총계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_DCWTR_QLTWTR', fieldName: '악취', header: { text: '악취' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_BSML', fieldName: '하수관로', header: { text: '하수관로' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_FIVW', fieldName: '배수설비', header: { text: '배수설비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_POLLUTN_ACDNT', fieldName: '맨홀', header: { text: '맨홀' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_SSOS', fieldName: '정화조', header: { text: '정화조' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_CHRGE', fieldName: '하수도요금', header: { text: '하수도요금' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_ETC', fieldName: '기타(민원)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 4. 성과 지표 및 비고 */ + { name: 'STDR_POPLTN_PER_CVPL', fieldName: '기준인구당 민원건수(건/10,000명)', header: { text: '기준인구당\n민원건수\n(건/10,000명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', + 'POPLTN_SM', + { + name: 'complaintTypeGroup', + header: { text: '민원유형(건)' }, + items: [ + 'CVPL_CM', + 'CVPL_DCWTR_QLTWTR', + 'CVPL_BSML', + 'CVPL_FIVW', + 'CVPL_POLLUTN_ACDNT', + 'CVPL_SSOS', + 'CVPL_CHRGE', + 'CVPL_ETC' + ] + }, + 'STDR_POPLTN_PER_CVPL', + 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '주민친화시설', + rowStartNum: 2, + fixedColumns: 5, + columns: [ + /* 1. 기본 및 시설 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'BSC_FCT_NM', fieldName: '처리장명', header: { text: '처리장명' } }, + { name: 'FCT_CPC', fieldName: '시설용량(㎥/일)', header: { text: '시설용량\n(㎥/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 2. 처리장 전체 면적 */ + { name: 'PRCPLT_AR', fieldName: '처리장 면적(㎡)', header: { text: '처리장\n면적(㎡)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 3. 주민친화시설 면적 상세 (단위: ㎡) */ + { name: 'TOTAL_AR', fieldName: '총계(시설)', header: { text: '총계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RESTRM_AR', fieldName: '휴게시설', header: { text: '휴게시설' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CHILDPLAY_AR', fieldName: '어린이놀이공간', header: { text: '어린이놀이공간' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ALSFC_AR', fieldName: '체력단련시설', header: { text: '체력단련시설' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PLGRND_AR', fieldName: '운동시설', header: { text: '운동시설' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PRKPLCE_AR', fieldName: '주차장', header: { text: '주차장' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CTLSTT_AR', fieldName: '교육 및 문화시설', header: { text: '교육 및\n문화시설' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'NRPRK_AR', fieldName: '습지조성(생태공원)', header: { text: '습지조성\n(생태공원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ETC_AR', fieldName: '기타(시설)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 4. 비고 */ + { name: 'RMK', fieldName: '비고', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'BSC_FCT_NM', + 'FCT_CPC', + 'YR_GBN', + 'PRCPLT_AR', + { + name: 'friendlyFacilityGroup', + header: { text: '주민친화시설 면적(㎡)' }, + items: [ + 'TOTAL_AR', + 'RESTRM_AR', + 'CHILDPLAY_AR', + 'ALSFC_AR', + 'PLGRND_AR', + 'PRKPLCE_AR', + 'CTLSTT_AR', + 'NRPRK_AR', + 'ETC_AR' + ] + }, + 'RMK' + ] + } +]; + + +export const ExcretaTreatmentFacilityInfoList = rawServiceLevelList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/PrivateSewageFacilityColumn.ts b/apps/st/src/components/util/column/review/PrivateSewageFacilityColumn.ts new file mode 100644 index 000000000..c626ba504 --- /dev/null +++ b/apps/st/src/components/util/column/review/PrivateSewageFacilityColumn.ts @@ -0,0 +1,139 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 08.개인하수처리시설 +const rawPrivateSewageList = [ + { + tabKey: 'a', + tabLabel: '처리용량별 오수처리시설 현황', + rowStartNum: 3, + fixedColumns: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'STTY_SM', fieldName: '총계', header: { text: '총계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_SM', fieldName: '계(처리구역 내)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_2', fieldName: '2이하(처리구역 내)', header: { text: '2이하' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_3', fieldName: '3~10(처리구역 내)', header: { text: '3~10' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_11', fieldName: '11~20(처리구역 내)', header: { text: '11~20' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_21', fieldName: '21~50(처리구역 내)', header: { text: '21~50' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_51', fieldName: '51~100(처리구역 내)', header: { text: '51~100' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_101', fieldName: '101~500(처리구역 내)', header: { text: '101~500' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_INNER_501', fieldName: '501이상(처리구역 내)', header: { text: '501이상' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_SM', fieldName: '계(처리구역 외)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_2', fieldName: '2이하(처리구역 외)', header: { text: '2이하' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_3', fieldName: '3~10(처리구역 외)', header: { text: '3~10' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_11', fieldName: '11~20(처리구역 외)', header: { text: '11~20' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_21', fieldName: '21~50(처리구역 외)', header: { text: '21~50' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_51', fieldName: '51~100(처리구역 외)', header: { text: '51~100' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_101', fieldName: '101~500(처리구역 외)', header: { text: '101~500' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'STTY_ZONE_OUTER_501', fieldName: '501이상(처리구역 외)', header: { text: '501이상' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', 'STTY_SM', + { + name: 'individualGroup', header: { text: '오수처리시설' }, + items: [ + { + name: 'innerGroup', header: { text: '하수처리구역 내(㎥/일)' }, + items: ['STTY_ZONE_INNER_SM', 'STTY_ZONE_INNER_2', 'STTY_ZONE_INNER_3', 'STTY_ZONE_INNER_11', 'STTY_ZONE_INNER_21', 'STTY_ZONE_INNER_51', 'STTY_ZONE_INNER_101', 'STTY_ZONE_INNER_501'] + }, + { + name: 'outerGroup', header: { text: '하수처리구역 외(㎥/일)' }, + items: ['STTY_ZONE_OUTER_SM', 'STTY_ZONE_OUTER_2', 'STTY_ZONE_OUTER_3', 'STTY_ZONE_OUTER_11', 'STTY_ZONE_OUTER_21', 'STTY_ZONE_OUTER_51', 'STTY_ZONE_OUTER_101', 'STTY_ZONE_OUTER_501'] + } + ] + }, + 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '정화조현황', + rowStartNum: 4, + fixedColumns: 1, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'TOT_FCLTY_CNT', fieldName: '총 시설 수(A+D)', header: { text: '총 시설 수\n(A+D)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_SM', fieldName: '총계 A=(B+C)/2', header: { text: '총계\nA=(B+C)/2' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_NPFL', fieldName: '자연유하', header: { text: '자연유하' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_ENFCT_PUMP', fieldName: '강제펌핑식', header: { text: '강제펌핑식' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_TFM', fieldName: '살수여상', header: { text: '살수여상' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_ARTM', fieldName: '폭기방법', header: { text: '폭기방법' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_CTARM', fieldName: '접촉폭기', header: { text: '접촉폭기' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_ETC', fieldName: '기타(방식)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_SM', fieldName: '계(C)', header: { text: '계(C)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_1', fieldName: '10인조 이하', header: { text: '10인조 이하' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_2', fieldName: '11~20', header: { text: '11~20' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_3', fieldName: '21~30', header: { text: '21~30' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_4', fieldName: '31~50', header: { text: '31~50' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_5', fieldName: '51~199', header: { text: '51~199' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_6', fieldName: '200~499', header: { text: '200~499' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_7', fieldName: '500~999', header: { text: '500~999' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SPZI_PROC_CPC_8', fieldName: '1,000이상', header: { text: '1,000이상' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', 'TOT_FCLTY_CNT', + { + name: 'innerMainGroup', header: { text: '하수처리구역 내' }, + items: [ + 'SPZI_SM', + { + name: 'innerMethodGroup', header: { text: '처리방식별' }, + items: [{ name: 'innerTankGroup', header: { text: '부패탱크' }, items: ['SPZI_NPFL', 'SPZI_ENFCT_PUMP'] }, 'SPZI_TFM', 'SPZI_ARTM', 'SPZI_CTARM', 'SPZI_ETC'] + }, + { + name: 'innerCpcGroup', header: { text: '처리용량별' }, + items: ['SPZI_PROC_CPC_SM', 'SPZI_PROC_CPC_1', 'SPZI_PROC_CPC_2', 'SPZI_PROC_CPC_3', 'SPZI_PROC_CPC_4', 'SPZI_PROC_CPC_5', 'SPZI_PROC_CPC_6', 'SPZI_PROC_CPC_7', 'SPZI_PROC_CPC_8'] + } + ] + }, + 'RMK' + ] + }, + { + tabKey: 'c', + tabLabel: '개인하수도 관리지역 지정공고 현황', + rowStartNum: 3, + fixedColumns: 1, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'MGMT_AR', fieldName: '공고지역(개소)', header: { text: '공고지역\n(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'APPN_SCOPE', fieldName: '지정범위(㎢)', header: { text: '지정범위\n(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'WRRTN_CNT', fieldName: '개소수(정화조)', header: { text: '개소수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'WRRTN_CPC', fieldName: '처리용량(인/일)', header: { text: '처리용량\n(인/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'STTY_CNT', fieldName: '개소수(오수시설)', header: { text: '개소수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'STTY_CPC', fieldName: '처리용량(㎥/일)', header: { text: '처리용량\n(㎥/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', + { + name: 'mgmtMainGroup', header: { text: '개인하수도관리지역공고현황\n(하수도법 제34조의2)' }, + items: [ + 'MGMT_AR', 'APPN_SCOPE', + { name: 'septictankGroup', header: { text: '정화조' }, items: ['WRRTN_CNT', 'WRRTN_CPC'] }, + { name: 'sewageFacGroup', header: { text: '오수시설' }, items: ['STTY_CNT', 'STTY_CPC'] } + ] + }, + 'RMK' + ] + } +]; + +export const PrivateSewageFacilityInfoListRvw = rawPrivateSewageList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/PublicSewageFacilityRvwColumn.ts b/apps/st/src/components/util/column/review/PublicSewageFacilityRvwColumn.ts new file mode 100644 index 000000000..8b3db0d16 --- /dev/null +++ b/apps/st/src/components/util/column/review/PublicSewageFacilityRvwColumn.ts @@ -0,0 +1,149 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 06.공공하수처리시설 +export const rawPublicSewageFacilityInfoList = { + columns: [ + /* 1. 기본 정보 */ + { name: 'sido', fieldName: '시도', header: { text: '시도' } }, + { name: 'sgg', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'ADDR', fieldName: '소재지', header: { text: '소재지' } }, + { name: 'FCT_NM_GROUP', fieldName: '시설명(500m3/일이상/미만)', header: { text: '시설명(500m3/일이상/미만)' } }, + + /* 2. 시설용량 (㎥/일) */ + { name: 'FCT_CPC_GROUP', fieldName: '시설용량(500m3/일이상/미만)_용량', header: { text: '시설용량(500m3/일이상/미만)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'FCT_CPC_PHY', fieldName: '물리적_용량', header: { text: '물리적' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'FCT_CPC_BIO', fieldName: '생물학적_용량', header: { text: '생물학적' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'FCT_CPC_ADV', fieldName: '고도_용량', header: { text: '고도' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 3. 유입하수량 (㎥/일) */ + { name: 'IN_QTY_GROUP', fieldName: '유입하수량(500m3/일이상/미만)', header: { text: '유입하수량(500m3/일이상/미만)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'IN_QTY_PHY', fieldName: '물리적_유입', header: { text: '물리적' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'IN_QTY_BIO', fieldName: '생물학적_유입', header: { text: '생물학적' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'IN_QTY_ADV', fieldName: '고도_유입', header: { text: '고도' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 4. 방류량 (㎥/일) */ + { name: 'OUT_QTY_GROUP', fieldName: '방류량(500m3/일이상/미만)', header: { text: '방류량(500m3/일이상/미만)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OUT_QTY_PHY', fieldName: '물리적_방류', header: { text: '물리적' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OUT_QTY_BIO', fieldName: '생물학적_방류', header: { text: '생물학적' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OUT_QTY_ADV', fieldName: '고도_방류', header: { text: '고도' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 5. 수질 및 처리효율 */ + { name: 'IN_BOD', fieldName: '유입BOD', header: { text: '유입BOD' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OUT_BOD', fieldName: '방류BOD', header: { text: '방류BOD' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'IN_TOC', fieldName: '유입TOC', header: { text: '유입TOC' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OUT_TOC', fieldName: '방류TOC', header: { text: '방류TOC' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'IN_SS', fieldName: '유입SS', header: { text: '유입SS' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OUT_SS', fieldName: '방류SS', header: { text: '방류SS' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'IN_TN', fieldName: '유입T-N', header: { text: '유입T-N' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'OUT_TN', fieldName: '방류T-N', header: { text: '방류T-N' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'IN_TP', fieldName: '유입T-P', header: { text: '유입T-P' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'OUT_TP', fieldName: '방류T-P', header: { text: '방류T-P' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'IN_COLI', fieldName: '유입총대장균군수', header: { text: '유입총대장균군수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OUT_COLI', fieldName: '방대총대장균군수', header: { text: '방대총대장균군수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'TRT_EFF', fieldName: '처리효율(%)', header: { text: '처리효율(%)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'TRT_LOD', fieldName: '처리부하량(kgBOD/D)', header: { text: '처리부하량(kgBOD/D)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'TRT_MTHD', fieldName: '처리방법', header: { text: '처리방법' } }, + + /* 6. 연계처리량 */ + { name: 'LNK_EXC', fieldName: '분뇨', header: { text: '분뇨' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LNK_LVS', fieldName: '축산', header: { text: '축산' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LNK_LCH', fieldName: '침출수', header: { text: '침출수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LNK_ETC', fieldName: '기타_연계', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 7. 상세 시설 정보 */ + { name: 'TEL_NO', fieldName: '전화번호', header: { text: '전화번호' } }, + { name: 'COMP_DT', fieldName: '준공일', header: { text: '준공일' } }, + { name: 'RN_DT', fieldName: '가동개시일', header: { text: '가동개시일' } }, + { name: 'BSNS_CT', fieldName: '사업비(백만원)', header: { text: '사업비(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DSCH_DSF_MTHD', fieldName: '방류수소독방법', header: { text: '방류수소독방법' } }, + + /* 8. 방류수역 */ + { name: 'WTR_SYS', fieldName: '수계', header: { text: '수계' } }, + { name: 'STRM', fieldName: '지류', header: { text: '지류' } }, + { name: 'DET_UNIT_ZONE', fieldName: '세부단위구역', header: { text: '세부단위구역' } }, + { name: 'RGN_GBN', fieldName: '지역구분', header: { text: '지역구분' } }, + { name: 'MID_ZONE_NM', fieldName: '명칭', header: { text: '명칭' } }, + { name: 'MID_ZONE_BOD', fieldName: '목표수질(BOD)', header: { text: '목표수질(BOD)' } }, + + /* 9. 에너지 및 환경 */ + { name: 'ENG_SLF_RT', fieldName: '에너지자립율(%)', header: { text: '에너지자립율(%)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ENG_SLF_QTY', fieldName: '에너지자체생산량(TOE)', header: { text: '에너지자체생산량(TOE)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ENG_TOT_SUM', fieldName: '계(TOE)', header: { text: '계(TOE)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ENG_TOT_PWR', fieldName: '총전력사용량(KWh)', header: { text: '총전력사용량(KWh)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ENG_TOT_SLF', fieldName: '자체에너지사용량(TOE)', header: { text: '자체에너지사용량(TOE)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'CO2_EMISS', fieldName: '하수처리량당CO2배출량(KgCO2/m3)', header: { text: '하수처리량당CO2배출량(KgCO2/m3)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + + /* 10. 운영 및 위탁 */ + { name: 'OPR_MBY', fieldName: '운영주체', header: { text: '운영주체' } }, + { name: 'ENTRPS_NM', fieldName: '위탁업체명', header: { text: '위탁업체명' } }, + { name: 'ENTRPS_CT', fieldName: '위탁비용(백만원/년)', header: { text: '위탁비용(백만원/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ENTRPS_TERM', fieldName: '위탁계약기간', header: { text: '위탁계약기간' } }, + { name: 'CTR_TRT_FCT', fieldName: '중심처리시설', header: { text: '중심처리시설' } }, + { name: 'EMP_CNT', fieldName: '직원총수(명)', header: { text: '직원총수(명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ACC_CNT', fieldName: '안전사고건수', header: { text: '안전사고건수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'groupA', header: { text: '행정구역' }, items: ['sido', 'sgg'] }, + 'FCT_NM_GROUP', 'GBN', 'ADDR', 'FCT_CPC_GROUP', + { + name: 'groupB', + header: { text: '시설용량(㎥/일)' }, + items: ['FCT_CPC_PHY', 'FCT_CPC_BIO', 'FCT_CPC_ADV'], + }, + 'IN_QTY_GROUP', + { + name: 'groupC', + header: { text: '유입하수량(㎥/일)' }, + items: ['IN_QTY_PHY', 'IN_QTY_BIO', 'IN_QTY_ADV'], + }, + 'OUT_QTY_GROUP', + { + name: 'groupD', + header: { text: '방류량(㎥/일)' }, + items: ['OUT_QTY_PHY', 'OUT_QTY_BIO', 'OUT_QTY_ADV'], + }, + 'IN_BOD', 'OUT_BOD', 'IN_TOC', 'OUT_TOC', 'IN_SS', 'OUT_SS', 'IN_TN', 'OUT_TN', 'IN_TP', 'OUT_TP', 'IN_COLI', 'OUT_COLI', + 'TRT_EFF', 'TRT_LOD', 'TRT_MTHD', + { + name: 'groupE', + header: { text: '연계처리량(㎥/일)' }, + items: ['LNK_EXC', 'LNK_LVS', 'LNK_LCH', 'LNK_ETC'], + }, + 'TEL_NO', 'COMP_DT', 'RN_DT', 'BSNS_CT', 'DSCH_DSF_MTHD', + { + name: 'groupF', + header: { text: '방류수역' }, + items: ['WTR_SYS', 'STRM', 'DET_UNIT_ZONE', 'RGN_GBN', + { + name: 'groupG', + header: { text: '중권역' }, + items: ['MID_ZONE_NM', 'MID_ZONE_BOD'], + }, + ], + }, + 'ENG_SLF_RT', 'ENG_SLF_QTY', + { + name: 'groupH', + header: { text: '연간 총 에너지 사용량(TOE)' }, + items: ['ENG_TOT_SUM', 'ENG_TOT_PWR', 'ENG_TOT_SLF'], + }, + 'CO2_EMISS', 'OPR_MBY', + { + name: 'groupI', + header: { text: '위탁현황' }, + items: ['ENTRPS_NM', 'ENTRPS_CT', 'ENTRPS_TERM'], + }, + 'CTR_TRT_FCT', 'EMP_CNT', 'ACC_CNT', 'RMK' + ] +}; + +// 최종 Export 객체 (일괄 editable: false 적용) +export const PublicSewageFacilityInfoList = { + ...rawPublicSewageFacilityInfoList, + columns: rawPublicSewageFacilityInfoList.columns.map(col => ({ + ...col, + editable: false + })) +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts b/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts new file mode 100644 index 000000000..058eb39e3 --- /dev/null +++ b/apps/st/src/components/util/column/review/PumpingStationRvwColumn.ts @@ -0,0 +1,106 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 05.펌프장 +export const rawPumpingStationInfoList = { + columns: [ + /* 1. 행정구역 및 기본정보 */ + { name: 'sido', fieldName: '시도', header: { text: '시도' } }, + { name: 'sgg', fieldName: '구군', header: { text: '구군' } }, + { name: 'PUMP_NM', fieldName: '펌프장명', header: { text: '펌프장명' } }, + { name: 'GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'TRT_FCT_NM', fieldName: '처리장명', header: { text: '처리장명' } }, + { name: 'TYPE_GBN', fieldName: '구분(합류식분류식)', header: { text: '구분(합류식분류식)' } }, + { name: 'ADDR', fieldName: '위치', header: { text: '위치' } }, + { name: 'RN_DT', fieldName: '가동년월일 yyyy-mm-dd', header: { text: '가동년월일\nyyyy-mm-dd' } }, + { name: 'DSN_AR', fieldName: '계획배수면적(km2)', header: { text: '계획배수면적\n(km2)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + + /* 2. 계획배수량 (m3/hr) */ + { name: 'DSN_QTY_A', fieldName: '청천시(A)', header: { text: '청천시(A)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DSN_QTY_B', fieldName: '우천시(B)', header: { text: '우천시(B)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DSN_QTY_DIFF', fieldName: '우수량(B-A)', header: { text: '우수량(B-A)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 3. 총 양수량 (m3/min) */ + { name: 'TOT_PUMP_QTY_O', fieldName: '오수펌프 총양수량', header: { text: '오수펌프\n총양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'TOT_PUMP_QTY_W', fieldName: '우수펌프 총양수량', header: { text: '우수펌프\n총양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 4. 오수펌프 상세 (1, 2, 3) */ + { name: 'PUMP_O1_D', fieldName: '구경(mm)_오수1', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_O1_Q', fieldName: '양수량(m3/min)_오수1', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_O1_C', fieldName: '펌프대수_오수1', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_O1_S', fieldName: '예비대수_오수1', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + { name: 'PUMP_O2_D', fieldName: '구경(mm)_오수2', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_O2_Q', fieldName: '양수량(m3/min)_오수2', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_O2_C', fieldName: '펌프대수_오수2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_O2_S', fieldName: '예비대수_오수2', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + { name: 'PUMP_O3_D', fieldName: '구경(mm)_오수3', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_O3_Q', fieldName: '양수량(m3/min)_오수3', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_O3_C', fieldName: '펌프대수_오수3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_O3_S', fieldName: '예비대수_오수3', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 5. 우수펌프 상세 (1, 2, 3) */ + { name: 'PUMP_W1_D', fieldName: '구경(mm)_우수1', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_W1_Q', fieldName: '양수량(m3/min)_우수1', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_W1_C', fieldName: '펌프대수_우수1', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_W1_S', fieldName: '예비대수_우수1', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + { name: 'PUMP_W2_D', fieldName: '구경(mm)_우수2', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_W2_Q', fieldName: '양수량(m3/min)_우수2', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_W2_C', fieldName: '펌프대수_우수2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_W2_S', fieldName: '예비대수_우수2', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + { name: 'PUMP_W3_D', fieldName: '구경(mm)_우수3', header: { text: '구경(mm)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_W3_Q', fieldName: '양수량(m3/min)_우수3', header: { text: '양수량\n(m3/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_W3_C', fieldName: '펌프대수_우수3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_W3_S', fieldName: '예비대수_우수3', header: { text: '예비대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 6. 운영 정보 */ + { name: 'PWR_USAGE', fieldName: '연간전력사용량(kWh/년)', header: { text: '연간전력사용량\n(kWh/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'groupA', header: { text: '행정구역' }, items: ['sido', 'sgg'] }, + 'PUMP_NM', 'GBN', 'TRT_FCT_NM', 'TYPE_GBN', 'ADDR', 'RN_DT', 'DSN_AR', + { + name: 'groupB', + header: { text: '계획시간대최대배수량(m3/hr)' }, + items: ['DSN_QTY_A', 'DSN_QTY_B', 'DSN_QTY_DIFF'], + }, + { + name: 'groupC', + header: { text: '배수능력' }, + items: [ + 'TOT_PUMP_QTY_O', + { + name: 'pumpO_Detail', + header: { text: '오수펌프 상세' }, + items: [ + { name: 'O1', header: { text: '오수펌프(1)' }, items: ['PUMP_O1_D', 'PUMP_O1_Q', 'PUMP_O1_C', 'PUMP_O1_S'] }, + { name: 'O2', header: { text: '오수펌프(2)' }, items: ['PUMP_O2_D', 'PUMP_O2_Q', 'PUMP_O2_C', 'PUMP_O2_S'] }, + { name: 'O3', header: { text: '오수펌프(3)' }, items: ['PUMP_O3_D', 'PUMP_O3_Q', 'PUMP_O3_C', 'PUMP_O3_S'] } + ] + }, + 'TOT_PUMP_QTY_W', + { + name: 'pumpW_Detail', + header: { text: '우수펌프 상세' }, + items: [ + { name: 'W1', header: { text: '우수펌프(1)' }, items: ['PUMP_W1_D', 'PUMP_W1_Q', 'PUMP_W1_C', 'PUMP_W1_S'] }, + { name: 'W2', header: { text: '우수펌프(2)' }, items: ['PUMP_W2_D', 'PUMP_W2_Q', 'PUMP_W2_C', 'PUMP_W2_S'] }, + { name: 'W3', header: { text: '우수펌프(3)' }, items: ['PUMP_W3_D', 'PUMP_W3_Q', 'PUMP_W3_C', 'PUMP_W3_S'] } + ] + } + ], + }, + 'PWR_USAGE', 'RMK', + ] +}; + +export const PumpingStationInfoList = { + ...rawPumpingStationInfoList, + columns: rawPumpingStationInfoList.columns.map(col => ({ + ...col, + editable: false + })) +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewageExcretaRelatedRvwColumn.ts b/apps/st/src/components/util/column/review/SewageExcretaRelatedRvwColumn.ts new file mode 100644 index 000000000..be414d00f --- /dev/null +++ b/apps/st/src/components/util/column/review/SewageExcretaRelatedRvwColumn.ts @@ -0,0 +1,135 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 12. 하수 및 분뇨 관련 산업 +const rawExcretaRelatedList = [ + { + tabKey: 'a', + tabLabel: '공공기관 하수분야', + rowStartNum: 2, + fixedColumns: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'OCGNZ', fieldName: '직제', header: { text: '직제' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'TOT_WTR_QRM', fieldName: '직원총수', header: { text: '직원총수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ADMINIST_JSSFC', fieldName: '행정직', header: { text: '행정직' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'TCHNLGY_JSSFC_SM', fieldName: '계(기술직)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ENGRK_JSSFC', fieldName: '토목', header: { text: '토목' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'MCHN_JSSFC', fieldName: '기계', header: { text: '기계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ELCTY_JSSFC', fieldName: '전기', header: { text: '전기' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CHMSTRY_JSSFC', fieldName: '화공', header: { text: '화공' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ENVRN_JSSFC', fieldName: '환경', header: { text: '환경' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'TCHNLGY_ETC', fieldName: '기타(기술직)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ETC', fieldName: '기타', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'OCGNZ', 'YR_GBN', 'TOT_WTR_QRM', 'ADMINIST_JSSFC', + { + name: 'techJobGroup', + header: { text: '기술직' }, + items: ['TCHNLGY_JSSFC_SM', 'ENGRK_JSSFC', 'MCHN_JSSFC', 'ELCTY_JSSFC', 'CHMSTRY_JSSFC', 'ENVRN_JSSFC', 'TCHNLGY_ETC'] + }, + 'ETC', 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '공공기관 분뇨분야', + rowStartNum: 2, + fixedColumns: 1, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'OCGNZ', fieldName: '직제', header: { text: '직제' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'TOT_WTR_QRM', fieldName: '직원총수', header: { text: '직원총수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ADMINIST_JSSFC', fieldName: '행정직', header: { text: '행정직' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'TCHNLGY_JSSFC_SM', fieldName: '계(기술직)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ENGRK_JSSFC', fieldName: '토목', header: { text: '토목' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'MCHN_JSSFC', fieldName: '기계', header: { text: '기계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ELCTY_JSSFC', fieldName: '전기', header: { text: '전기' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CHMSTRY_JSSFC', fieldName: '화공', header: { text: '화공' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ENVRN_JSSFC', fieldName: '환경', header: { text: '환경' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'TCHNLGY_ETC', fieldName: '기타(기술직)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ETC', fieldName: '기타', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'OCGNZ', 'YR_GBN', 'TOT_WTR_QRM', 'ADMINIST_JSSFC', + { + name: 'techJobGroup', + header: { text: '기술직' }, + items: ['TCHNLGY_JSSFC_SM', 'ENGRK_JSSFC', 'MCHN_JSSFC', 'ELCTY_JSSFC', 'CHMSTRY_JSSFC', 'ENVRN_JSSFC', 'TCHNLGY_ETC'] + }, + 'ETC', 'RMK' + ] + }, + { + tabKey: 'c', + tabLabel: '분뇨수집·운반업', + rowStartNum: 2, + fixedColumns: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'ECSCS_SM', fieldName: '업체수(개소)', header: { text: '업체수(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ECSCS_BSMN', fieldName: '종사인원(명)', header: { text: '종사인원(명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'VHCLE_SM', fieldName: '계(차량)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'THREE_BELOW', fieldName: '3톤이하', header: { text: '3톤이하' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'FOUR_BELOW', fieldName: '4.5톤이하', header: { text: '4.5톤이하' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'EIGHT_BELOW', fieldName: '8톤이하', header: { text: '8톤이하' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ETC_VHCLE', fieldName: '기타(차량)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, // name 중복 방지를 위해 ETC_VHCLE로 수정 권장 + { name: 'COLCT_TRSP_ACMSLT', fieldName: '수집·운반실적(㎥/년)', header: { text: '수집·운반실적\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', 'ECSCS_SM', 'ECSCS_BSMN', + { + name: 'vehicleGroup', + header: { text: '시설(차량) 확보현황(대수)' }, + items: ['VHCLE_SM', 'THREE_BELOW', 'FOUR_BELOW', 'EIGHT_BELOW', 'ETC_VHCLE'] + }, + 'COLCT_TRSP_ACMSLT', 'RMK' + ] + }, + { + tabKey: 'd', + tabLabel: '개인하수처리관련업', + rowStartNum: 2, + fixedColumns: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'CNSTRCT_ENTRPS', fieldName: '업소수(시공업)', header: { text: '업소수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CNSTRCT_BSMN', fieldName: '종사인원(명)_시공업', header: { text: '종사인원(명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'MNFCTUR_ENTRPS', fieldName: '업소수(제조업)', header: { text: '업소수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'MNFCTUR_BSMN', fieldName: '종사인원(명)_제조업', header: { text: '종사인원(명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'MGMT_ENTRPS', fieldName: '업소수(관리업)', header: { text: '업소수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'MGMT_BSMN', fieldName: '종사인원(명)_관리업', header: { text: '종사인원(명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', + { name: 'constructGroup', header: { text: '개인하수처리시설 설계ㆍ시공업' }, items: ['CNSTRCT_ENTRPS', 'CNSTRCT_BSMN'] }, + { name: 'manufactureGroup', header: { text: '개인하수처리시설 제조업' }, items: ['MNFCTUR_ENTRPS', 'MNFCTUR_BSMN'] }, + { name: 'managementGroup', header: { text: '개인하수처리시설 관리업' }, items: ['MGMT_ENTRPS', 'MGMT_BSMN'] }, + 'RMK' + ] + } +]; + +export const SewageExcretaRelatedInfoListRvw = rawExcretaRelatedList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewageExcretaSlurgeRvwColumn.ts b/apps/st/src/components/util/column/review/SewageExcretaSlurgeRvwColumn.ts new file mode 100644 index 000000000..b9dfcbf98 --- /dev/null +++ b/apps/st/src/components/util/column/review/SewageExcretaSlurgeRvwColumn.ts @@ -0,0 +1,199 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 11. 하수 및 분뇨 찌꺼기(슬러지) 처리 +const rawSludgeList = [ + { + tabKey: 'a', + tabLabel: '찌꺼기 처리시설 현황', + rowStartNum: 4, + fixedColumns: 2, + columns: [ + /* 기본 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'BSC_FCT_NM', fieldName: '하수처리장명', header: { text: '하수\n처리장명' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 찌꺼기발생량 */ + { name: 'TOT_AMNT', fieldName: '합계(발생)', header: { text: '합계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'P_AMNT', fieldName: '자체(발생)', header: { text: '자체' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'O_AMNT', fieldName: '외부유입량(발생)', header: { text: '외부유입량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 처리 정보 */ + { name: 'OUT_FCT_NM', fieldName: '이송처리장', header: { text: '이송처리장' } }, + { name: 'OUT_AMNT', fieldName: '이송처리량(㎥/년)', header: { text: '이송처리량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DSP_MOIRAT', fieldName: '함수율(%,탈수기준)', header: { text: '함수율\n(%,\n탈수기준)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DSP_SM', fieldName: '찌꺼기 처리량 합계(톤/년)', header: { text: '찌꺼기\n처리량\n합계(톤/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 자체 찌꺼기 처리량 */ + { name: 'I_1CH_SM', fieldName: '자체찌꺼기 처리량소계', header: { text: '자체찌꺼기\n처리량소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_REC', fieldName: '매립(자체)', header: { text: '매립' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_INC', fieldName: '소각(자체)', header: { text: '소각' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_INC_2CH_SM', fieldName: '소계(소각후)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_INC_2CH_REC', fieldName: '매립(소각후)', header: { text: '매립' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_INC_2CH_RAW', fieldName: '제품원료(소각후)', header: { text: '제품원료' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_INC_2CH_COV', fieldName: '복토재(소각후)', header: { text: '복토재' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_INC_2CH_FCT', fieldName: '시설(업체명)_소각후', header: { text: '시설(업체명)' } }, + { name: 'I_1CH_SOL', fieldName: '고화(자체)', header: { text: '고화' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_SOL_2CH_SM', fieldName: '소계(고화후)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_SOL_2CH_REC', fieldName: '매립(고화후)', header: { text: '매립' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_SOL_2CH_COV', fieldName: '복토재(고화후)', header: { text: '복토재' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_SOL_2CH_FCT', fieldName: '시설(업체명)_고화후', header: { text: '시설(업체명)' } }, + { name: 'I_1CH_DRY', fieldName: '건조(자체)', header: { text: '건조' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_DRY_2CH_SM', fieldName: '소계(건조후)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_DRY_2CH_REC', fieldName: '매립(건조후)', header: { text: '매립' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_DRY_2CH_INC', fieldName: '소각(건조후)', header: { text: '소각' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_DRY_2CH_FUE', fieldName: '연료(건조후)', header: { text: '연료' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_DRY_2CH_RAW', fieldName: '제품원료(건조후)', header: { text: '제품원료' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_DRY_2CH_COV', fieldName: '복토재(건조후)', header: { text: '복토재' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_DRY_2CH_COM', fieldName: '퇴비화(건조후)', header: { text: '퇴비화' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_DRY_2CH_FCT', fieldName: '시설(업체명)_건조후', header: { text: '시설(업체명)' } }, + { name: 'I_1CH_CAR', fieldName: '탄화(자체)', header: { text: '탄화' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_CAR_2CH_SM', fieldName: '소계(탄화후)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_CAR_2CH_INC', fieldName: '소각(탄화후)', header: { text: '소각' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_CAR_2CH_FUE', fieldName: '연료(탄화후)', header: { text: '연료' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_CAR_2CH_FCT', fieldName: '시설(업체명)_탄화후', header: { text: '시설(업체명)' } }, + { name: 'I_1CH_COM', fieldName: '퇴비화(자체)', header: { text: '퇴비화' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'I_1CH_COM_FCT', fieldName: '시설(업체명)_퇴비화', header: { text: '시설(업체명)' } }, + + /* 외부위탁 처리량 */ + { name: 'O_CON_SM', fieldName: '소계(외부위탁)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'O_CON_REC', fieldName: '매립(외부위탁)', header: { text: '매립' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'O_CON_INC', fieldName: '소각(외부위탁)', header: { text: '소각' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'O_CON_FUE1', fieldName: '연료(외부위탁)', header: { text: '연료' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'O_CON_RAW', fieldName: '제품원료(외부위탁)', header: { text: '제품원료' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'O_CON_COV', fieldName: '복토재(외부위탁)', header: { text: '복토재' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'O_CON_COM', fieldName: '퇴비화(외부위탁)', header: { text: '퇴비화' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'O_CON_FCT_NM', fieldName: '시설(업체명)_외부위탁', header: { text: '시설(업체명)' } }, + + /* 기타 */ + { name: 'OM_1CH_SM', fieldName: '수도권광역 위탁처리량(톤/년)', header: { text: '수도권광역\n위탁처리량\n(톤/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'BSC_FCT_NM', 'YR_GBN', + { name: 'genAmntGroup', header: { text: '찌꺼기발생량(톤/년,탈수기준)' }, items: ['TOT_AMNT', 'P_AMNT', 'O_AMNT'] }, + 'OUT_FCT_NM', 'OUT_AMNT', 'DSP_MOIRAT', 'DSP_SM', + { + name: 'internalProcessGroup', header: { text: '자체 찌꺼기 처리량(톤/년)' }, + items: [ + 'I_1CH_SM', 'I_1CH_REC', 'I_1CH_INC', + { name: 'inc2ndGroup', header: { text: '소각 후 처리(2차)' }, items: ['I_1CH_INC_2CH_SM', 'I_1CH_INC_2CH_REC', 'I_1CH_INC_2CH_RAW', 'I_1CH_INC_2CH_COV', 'I_1CH_INC_2CH_FCT'] }, + 'I_1CH_SOL', + { name: 'sol2ndGroup', header: { text: '고화 후 처리(2차)' }, items: ['I_1CH_SOL_2CH_SM', 'I_1CH_SOL_2CH_REC', 'I_1CH_SOL_2CH_COV', 'I_1CH_SOL_2CH_FCT'] }, + 'I_1CH_DRY', + { name: 'dry2ndGroup', header: { text: '건조 후 처리(2차)' }, items: ['I_1CH_DRY_2CH_SM', 'I_1CH_DRY_2CH_REC', 'I_1CH_DRY_2CH_INC', 'I_1CH_DRY_2CH_FUE', 'I_1CH_DRY_2CH_RAW', 'I_1CH_DRY_2CH_COV', 'I_1CH_DRY_2CH_COM', 'I_1CH_DRY_2CH_FCT'] }, + 'I_1CH_CAR', + { name: 'car2ndGroup', header: { text: '탄화 후 처리(2차)' }, items: ['I_1CH_CAR_2CH_SM', 'I_1CH_CAR_2CH_INC', 'I_1CH_CAR_2CH_FUE', 'I_1CH_CAR_2CH_FCT'] }, + { name: 'compostGroup', header: { text: '퇴비화' }, items: ['I_1CH_COM_FCT'] } + ] + }, + { + name: 'externalProcessGroup', header: { text: '외부(민간)위탁 처리량(톤/년)' }, + items: ['O_CON_SM', 'O_CON_REC', 'O_CON_INC', 'O_CON_FUE1', 'O_CON_RAW', 'O_CON_COV', 'O_CON_COM', 'O_CON_FCT_NM'] + }, + 'OM_1CH_SM', 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '소화조 운영현황', + rowStartNum: 3, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'BSC_FCT_NM', fieldName: '하수처리장명', header: { text: '하수\n처리장명' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'DGSTR_FNNC', fieldName: '소화조 유/무(Y/N)선택', header: { text: '소화조 유/무\n(Y/N)선택' } }, + { name: 'DGSTR_CPC', fieldName: '설계용량(㎥)', header: { text: '설계\n용량\n(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_OPR_CPC', fieldName: '실제운전용량(㎥)', header: { text: '실제운전\n용량\n(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_IN', fieldName: '투입량(㎥/일)', header: { text: '투입량\n(㎥/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_TS', fieldName: '투입 TS 농도(%)', header: { text: '투입 TS 농도\n(%)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_YRSTP_RN_DYN', fieldName: '가동일수(연간)', header: { text: '가동일수\n(연간)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_OCCUR_GAS', fieldName: '발생가스량(㎥/일)', header: { text: '발생가스량\n(㎥/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_SM', fieldName: '계(이용현황)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_SLE', fieldName: '판매', header: { text: '판매' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_ELTGNR', fieldName: '발전', header: { text: '발전' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_ONSLF', fieldName: '자체활용', header: { text: '자체활용' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_ETC', fieldName: '기타(CNG등)', header: { text: '기타(CNG등)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DGSTR_GAS', fieldName: '잉여가스량(㎥/일)', header: { text: '잉여가스량\n(㎥/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'BSC_FCT_NM', 'YR_GBN', + { + name: 'digesterMainGroup', header: { text: '소화조 운영현황' }, + items: [ + 'DGSTR_FNNC', 'DGSTR_CPC', 'DGSTR_OPR_CPC', 'DGSTR_IN', 'DGSTR_TS', 'DGSTR_YRSTP_RN_DYN', 'DGSTR_OCCUR_GAS', + { name: 'gasUsageGroup', header: { text: '소화가스 이용현황(㎥/일)' }, items: ['DGSTR_SM', 'DGSTR_SLE', 'DGSTR_ELTGNR', 'DGSTR_ONSLF', 'DGSTR_ETC'] }, + 'DGSTR_GAS' + ] + }, + 'RMK' + ] + }, + { + tabKey: 'c', + tabLabel: '하수찌꺼기 처리시설 운영현황', + rowStartNum: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'SLG_FCT_NM', fieldName: '찌꺼기처리시설명', header: { text: '찌꺼기처리시설명' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'TRT_METHOD', fieldName: '처리방식', header: { text: '처리방식' } }, + { name: 'SLG_FCT_CPC', fieldName: '시설용량(톤/일)', header: { text: '시설용량\n(톤/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OPR_CPC', fieldName: '연간처리량(톤/년)', header: { text: '연간처리량\n(톤/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ODY_RN_TIME', fieldName: '일평균 가동시간(1~24)', header: { text: '일평균\n가동시간\n(1~24)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'YRSTP_RN_DYN', fieldName: '연중 가동일(1~330)', header: { text: '연중 가동일\n(1~330)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'OPR_RT', fieldName: '가동율', header: { text: '가동율' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'SLG_FCT_NM', 'YR_GBN', + { name: 'sludgeFctOprGroup', header: { text: '처리시설 운영현황' }, items: ['TRT_METHOD', 'SLG_FCT_CPC', 'OPR_CPC', 'ODY_RN_TIME', 'YRSTP_RN_DYN', 'OPR_RT'] }, + 'RMK' + ] + }, + { + tabKey: 'd', + tabLabel: '분뇨찌꺼기 처리현황', + rowStartNum: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'ECSCS_NM', fieldName: '분뇨 처리장명', header: { text: '분 뇨\n처리장명' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'OCTY', fieldName: '발생량(A)=(B)+(C)(㎥/년)', header: { text: '발생량\n(A)=(B)+(C)\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PROCESS_CPCTY_SM', fieldName: '계(B)', header: { text: '계(B)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RUSE', fieldName: '재활용', header: { text: '재활용' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LAND_RCLM', fieldName: '육상매립', header: { text: '육상매립' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'INCNR', fieldName: '소각', header: { text: '소각' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OCEAN_DPSL', fieldName: '해양투기', header: { text: '해양투기' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'FUEL', fieldName: '연료화', header: { text: '연료화' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC', fieldName: '기타', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'CYFD_CPCTY', fieldName: '미처분량(이월량)(C)(㎥/년)', header: { text: '미처분량\n(이월량)\n(C)\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OUT_BSC_FCT_NM', fieldName: '타시설 연계여부', header: { text: '타시설\n연계여부' } }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' } }, + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'ECSCS_NM', 'YR_GBN', 'OCTY', + { name: 'disposalAmntGroup', header: { text: '처 분 량(㎥/년)' }, items: ['PROCESS_CPCTY_SM', 'RUSE', 'LAND_RCLM', 'INCNR', 'OCEAN_DPSL', 'FUEL', 'ETC'] }, + 'CYFD_CPCTY', 'OUT_BSC_FCT_NM', 'RMK' + ] + } +]; + +export const SewageExcretaSludgeInfoListRvw = rawSludgeList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts new file mode 100644 index 000000000..28aa25ce5 --- /dev/null +++ b/apps/st/src/components/util/column/review/SewagePipeMaintainRvwColumn.ts @@ -0,0 +1,137 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 03. 하수관로 유지 관리 +const rawMaintainList = [ + { + tabKey: 'a', + tabLabel: '개보수', + rowStartNum: 4, + fixedColumns: 2, + columns: [ + /* 1. 행정 및 기본 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 2. 전체보수 (단위: m) */ + { name: 'RPAIR_PIPE_SM', fieldName: '계(전체보수)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RPAIR_CMBN_PIPE', fieldName: '합류식(전체보수)', header: { text: '합류식' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RPAIR_RAINWTR_PIPE', fieldName: '우수(전체보수)', header: { text: '우수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RPAIR_PLTWTR_PIPE', fieldName: '오수(전체보수)', header: { text: '오수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 3. 부분보수 (단위: 개소) */ + { name: 'RPAIR_PIPE_SM2', fieldName: '계(부분보수)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RPAIR_CMBN_PIPE2', fieldName: '합류식(부분보수)', header: { text: '합류식' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RPAIR_RAINWTR_PIPE2', fieldName: '우수(부분보수)', header: { text: '우수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RPAIR_PLTWTR_PIPE2', fieldName: '오수(부분보수)', header: { text: '오수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 4. 부속시설 (개소) */ + { name: 'MNHLE_SITE', fieldName: '합류식 맨홀', header: { text: '합류식\n맨홀' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PLTWTR_MNHLE_SITE', fieldName: '오수맨홀', header: { text: '오수맨홀' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RAINWTR_MNHLE_SITE', fieldName: '우수맨홀', header: { text: '우수맨홀' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PLTWTR_RCVR_SITE', fieldName: '오수받이(개소)', header: { text: '오수받이(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RAINWTR_RCVR_SITE', fieldName: '빗물받이(개소)', header: { text: '빗물받이(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SOILHOLE_SITE', fieldName: '토실(개소)', header: { text: '토실(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SOILSPLL_SITE', fieldName: '토구(개소)', header: { text: '토구(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 5. 조사량 및 비고 */ + { name: 'CCTV', fieldName: '수밀검사·CCTV조사량(m)', header: { text: '수밀검사·\nCCTV조사량\n(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', + { + name: 'mtcPipeGroup', header: { text: '개·보수관로' }, + items: [ + { + name: 'totalRepairGroup', header: { text: '전체보수(m)' }, + items: ['RPAIR_PIPE_SM', 'RPAIR_CMBN_PIPE', { name: 'sepTotalGroup', header: { text: '분류식' }, items: ['RPAIR_RAINWTR_PIPE', 'RPAIR_PLTWTR_PIPE'] }] + }, + { + name: 'partRepairGroup', header: { text: '부분보수(개소)' }, + items: ['RPAIR_PIPE_SM2', 'RPAIR_CMBN_PIPE2', { name: 'sepPartGroup', header: { text: '분류식' }, items: ['RPAIR_RAINWTR_PIPE2', 'RPAIR_PLTWTR_PIPE2'] }] + } + ] + }, + 'MNHLE_SITE', + { name: 'sepMnhleGroup', header: { text: '분류식' }, items: ['PLTWTR_MNHLE_SITE', 'RAINWTR_MNHLE_SITE'] }, + 'PLTWTR_RCVR_SITE', 'RAINWTR_RCVR_SITE', + { name: 'soilGroup', header: { text: '토실·토구(개소)' }, items: ['SOILHOLE_SITE', 'SOILSPLL_SITE'] }, + 'CCTV', 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '관로준설', + rowStartNum: 4, + fixedColumns: 2, + columns: [ + /* 1. 행정 및 기본 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 2. 시설 기본 정보 */ + { name: 'PIPL_FCLTY_EXTN', fieldName: '하수관로 총시설연장(m)', header: { text: '하수관로\n총시설연장\n(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 3. 준설연장 및 개소수 */ + { name: 'DRDG_PIPE_SM', fieldName: '합계(준설)', header: { text: '합계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DRDG_CMBN_PIPE', fieldName: '합류식(준설)', header: { text: '합류식' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DRDG_RAINWTR_PIPE', fieldName: '우수(준설)', header: { text: '우수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DRDG_PLTWTR_PIPE', fieldName: '오수(준설)', header: { text: '오수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'MNHLE_SITE_DRDG', fieldName: '맨홀(개소)', header: { text: '맨홀\n(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PLTWTR_RCVR_SITE_DRDG', fieldName: '오·우수받이(개소)', header: { text: '오·우수받이\n(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SOILSPLL_SOILHOLE_SITE', fieldName: '토실·토구(개소)', header: { text: '토실·토구\n(개소)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 4. 준설 계획 및 율 */ + { name: 'DRDG_TRGET_EXTN', fieldName: '준설 계획 연장(m)', header: { text: '준설 계획\n연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DRDG_TRGET_RT', fieldName: '계획대비 준설율(%)', header: { text: '계획대비\n준설율\n(%)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PIPL_FCLTY_RT', fieldName: '준설계획 연장대비 준설율(%)', header: { text: '준설계획\n연장대비\n준설율(%)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 5. 준설실적 */ + { name: 'DRDG_ACMSLT_AMOUNT', fieldName: '금액(백만원)', header: { text: '금액\n(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'DRDG_ACMSLT_QY', fieldName: '준설량(㎥)', header: { text: '준설량\n(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 6. 준설토사처리 */ + { name: 'DRDG_ACMSLT_UNTPC', fieldName: '준설토 처리비(백만원)', header: { text: '준설토\n처리비\n(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'DRDG_ETND_SM', fieldName: '처리량 계(톤)', header: { text: '처리량 계\n(톤)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RCLM', fieldName: '매립', header: { text: '매립' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OCEAN_DPSL', fieldName: '해양투기', header: { text: '해양투기' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RUSE', fieldName: '재활용', header: { text: '재활용' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC', fieldName: '기타(준설)', header: { text: '기타\n(소각, 고형화,\n시멘트원료 등)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 7. 기타 및 의견 */ + { name: 'RMK_DRDG', fieldName: '비고(준설)', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', 'PIPL_FCLTY_EXTN', + { + name: 'drdgGroup', header: { text: '준설연장 및 개소수' }, + items: [ + { + name: 'pipeLenGroup', header: { text: '관로(m)' }, + items: ['DRDG_PIPE_SM', 'DRDG_CMBN_PIPE', { name: 'sepRepairGroup', header: { text: '분류식' }, items: ['DRDG_RAINWTR_PIPE', 'DRDG_PLTWTR_PIPE'] }] + }, + 'MNHLE_SITE_DRDG', 'PLTWTR_RCVR_SITE_DRDG', 'SOILSPLL_SOILHOLE_SITE' + ] + }, + 'DRDG_TRGET_EXTN', 'DRDG_TRGET_RT', 'PIPL_FCLTY_RT', + { name: 'acmsltGroup', header: { text: '준설실적' }, items: ['DRDG_ACMSLT_AMOUNT', 'DRDG_ACMSLT_QY'] }, + { + name: 'processGroup', header: { text: '준설토사처리' }, + items: ['DRDG_ACMSLT_UNTPC', 'DRDG_ETND_SM', 'RCLM', 'OCEAN_DPSL', 'RUSE', 'ETC'] + }, + 'RMK_DRDG' + ] + } +]; + +export const SewagePipeMaintainColumnInfoList = rawMaintainList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts new file mode 100644 index 000000000..7bcb3a41f --- /dev/null +++ b/apps/st/src/components/util/column/review/SewagePipeRvwColumn.ts @@ -0,0 +1,430 @@ +import { ValueType } from "realgrid"; +const baseYear = new Date().getFullYear(); +import { footerIntArrayByDivision, footerDecimal3ArrayByDivision, footerAvgDecimalArrayByDivision } from "@/components/util/grid/footerSummary"; +import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataGrid.type"; + +// 하수도 통계 관리 02. 하수관로 +const rawList = [ + { + tabKey: 'a', + tabLabel: '지역별 시설현황', + rowStartNum: 4, + fixedColumns: 2, + columns: [ + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; + return '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; + return '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, editable: false }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } + ] + }, + + /* 하수정비 기본계획 */ + { name: 'targetYr', fieldName: 'targetYr', header: { text: '하수정보기본계획목표년도' } }, + { name: 'piplImprmnPlanExtn', fieldName: 'piplImprmnPlanExtn', header: { text: '총관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'piplPlanExtn', fieldName: 'piplPlanExtn', header: { text: '총계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'piplFcltyExtn', fieldName: 'piplFcltyExtn', header: { text: '총시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'piplSupprt', fieldName: 'piplSupprt', header: { text: '하수관로\n보급률(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + /* 합류식(m) */ + { name: 'cmbnPlanAr', fieldName: 'cmbnPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'cmbnImprmnPlanExtn', fieldName: 'cmbnImprmnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: '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: 'pltwtrPlanAr', fieldName: 'pltwtrPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'pltwtrImprmnPlanExtn', fieldName: 'pltwtrImprmnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrPlanExtn', fieldName: 'pltwtrPlanExtn', header: { text: '계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrFlctyExtn', fieldName: 'pltwtrFlctyExtn', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrSqreExtn', fieldName: 'pltwtrSqreExtn', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrCiclExtn', fieldName: 'pltwtrCiclExtn', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + /* 분류식 - 우수관로 */ + { name: 'rainwtrPlanAr', fieldName: 'rainwtrPlanAr', header: { text: '관로정비\n계획면적(㎢)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'rainwtrImprmnPlanExtn', fieldName: 'rainwtrImprmnPlanExtn', header: { text: '관로정비\n계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrPlanExtn', fieldName: 'rainwtrPlanExtn', header: { text: '계획연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrFlctyExtn', fieldName: 'rainwtrFlctyExtn', header: { text: '시설연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrSqreExtn', fieldName: 'rainwtrSqreExtn', header: { text: '사각형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrCiclExtn', fieldName: 'rainwtrCiclExtn', header: { text: '원형(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrOpswrExtn', fieldName: 'rainwtrOpswrExtn', header: { text: '개거(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrSdgttrExtn', fieldName: 'rainwtrSdgttrExtn', header: { text: '측구(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + /* 부속시설 */ + { name: 'mnhleSite', fieldName: 'mnhleSite', header: { text: '합류식맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrMnhleSite', fieldName: 'pltwtrMnhleSite', header: { text: '오수맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrMnhleSite', fieldName: 'rainwtrMnhleSite', header: { text: '우수맨홀(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'pltwtrRcvrSite', fieldName: 'pltwtrRcvrSite', header: { text: '오수받이(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'rainwtrRcvrSite', fieldName: 'rainwtrRcvrSite', header: { text: '빗물받이(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'soilspllSite', fieldName: 'soilspllSite', header: { text: '우수토실(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'soilholeSite', fieldName: 'soilholeSite', header: { text: '우수토구(개소)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 대장 및 기타 */ + { name: 'sewerRegstrCmptExtn', fieldName: 'sewerRegstrCmptExtn', header: { text: '하수도대장전산화연장(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sewerRegstrCmptRt', fieldName: 'sewerRegstrCmptRt', header: { text: '하수도대장전산화율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'areaGroup', header: { text: '행정구역' }, items: [ + { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'gugun', + 'adstDong', + ] + }, + 'displayYear', + 'targetYr', 'piplImprmnPlanExtn', 'piplPlanExtn', 'piplFcltyExtn', 'piplSupprt', + { + name: 'combinedGroup', header: { text: '합류식(m)' }, + items: ['cmbnPlanAr', 'cmbnImprmnPlanExtn', 'cmbnPlanExtn', 'cmbnFcltyExtn', + { name: 'cmbnAmGroup', header: { text: '암거' }, items: ['cmbnRctglExtn', 'cmbnCicleExtn'] }, + 'cmbnOpswrExtn', 'cmbnSdgttrExtn' + ], + }, + { + name: 'sepGroup', header: { text: '분류식(m)' }, + items: [ + { + name: 'foulPipeGroup', header: { text: '오수관로' }, + items: ['pltwtrPlanAr', 'pltwtrImprmnPlanExtn', 'pltwtrPlanExtn', 'pltwtrFlctyExtn', + { name: 'foulAmGroup', header: { text: '암거' }, items: ['pltwtrSqreExtn', 'pltwtrCiclExtn'] }] + }, + { + name: 'rainPipeGroup', header: { text: '우수관로' }, + items: ['rainwtrPlanAr', 'rainwtrImprmnPlanExtn', 'rainwtrPlanExtn', 'rainwtrFlctyExtn', + { name: 'rainAmGroup', header: { text: '암거' }, items: ['rainwtrSqreExtn', 'rainwtrCiclExtn'] }, + 'rainwtrOpswrExtn', 'rainwtrSdgttrExtn'] + } + ], + }, + 'mnhleSite', + { name: 'fcltyGroup', header: { text: '부속시설(개소)' }, items: ['pltwtrMnhleSite', 'rainwtrMnhleSite'] }, + 'pltwtrRcvrSite', 'rainwtrRcvrSite', 'soilspllSite', 'soilholeSite', 'sewerRegstrCmptExtn', 'sewerRegstrCmptRt', 'rmk' + ] + }, + { + tabKey: 'b', + tabLabel: '시설별 설치현황', + rowStartNum: 4, + fixedColumns: 3, + columns: [ + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'bscFctNm', fieldName: 'bscFctNm', header: { text: '하수처리장명' }, editable: false }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } + ] + }, + { name: 'fctCpc', fieldName: 'fctCpc', header: { text: '하수처리\n시설용량\n(㎥/일)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 처리구역면적(㎢) */ + { name: 'procZoneSm', fieldName: 'procZoneSm', header: { text: '합계' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'cmbnProcZoneAr', fieldName: 'cmbnProcZoneAr', header: { text: '합류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'sprtProcZoneAr', fieldName: 'sprtProcZoneAr', header: { text: '분류식' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'sepRate', fieldName: 'sepRate', header: { text: '분류식화(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 배수설비(개소) */ + { name: 'drngEqpSm', fieldName: 'drngEqpSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'cmbnDrngEqp', fieldName: 'cmbnDrngEqp', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprtDrngEqpSm', fieldName: 'sprtDrngEqpSm', header: { text: '합계(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprtDrngEqpCnnc', fieldName: 'sprtDrngEqpCnnc', header: { text: '연결' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprtDrngEqpDcnnc', fieldName: 'sprtDrngEqpDcnnc', header: { text: '미연결' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 하수관로 */ + { name: 'piplFcltyExtn', fieldName: 'piplFcltyExtn', header: { text: '총\n시설연장\n(m)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'icgMnnSm', fieldName: 'icgMnnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'icgExtn', fieldName: 'icgExtn', header: { text: '차집' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'mnnExtn', fieldName: 'mnnExtn', header: { text: '오수간선' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + /* 토실/토구(개소) */ + { name: 'cmbnSoilholeSite', fieldName: 'cmbnSoilholeSite', header: { text: '우수토실(합류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprtSoilholeSite', fieldName: 'sprtSoilholeSite', header: { text: '우수토실(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'sprtSoilspllSite', fieldName: 'sprtSoilspllSite', header: { text: '우수토구(분류)' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 지선(m) */ + { name: 'brnchlnSm', fieldName: 'brnchlnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'cmbnBrnchlnExtn', fieldName: 'cmbnBrnchlnExtn', header: { text: '합류식' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'rainwtrBrnchlnExtn', fieldName: 'rainwtrBrnchlnExtn', header: { text: '우수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + { name: 'pltwtrBrnchlnExtn', fieldName: 'pltwtrBrnchlnExtn', header: { text: '오수' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, numberFormat: '#,##0.00' }, + + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'addrGroup', + header: { text: '행정구역' }, + items: [ + { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'gugun', + 'bscFctNm', + ] + }, + + 'fctCpc', + 'displayYear', + { name: 'areaGroup', header: { text: '처리구역면적(㎢)' }, items: ['procZoneSm', 'cmbnProcZoneAr', 'sprtProcZoneAr'] }, + 'sepRate', + { + name: 'drainGroup', header: { text: '배수설비(개소)' }, + items: ['drngEqpSm', 'cmbnDrngEqp', { name: 'sepDrainGroup', header: { text: '분류식' }, items: ['sprtDrngEqpSm', 'sprtDrngEqpCnnc', 'sprtDrngEqpDcnnc'] }], + }, + { + name: 'pipeGroup', header: { text: '하수관로' }, + items: [ + 'piplFcltyExtn', + { name: 'trunkGroup', header: { text: '차집/오수간선(m)' }, items: ['icgMnnSm', 'icgExtn', 'mnnExtn'] }, + { + name: 'siteGroup', header: { text: '토실/토구(개소)' }, + items: [ + { name: 'cmbnSiteGroup', header: { text: '합류식' }, items: ['cmbnSoilholeSite'] }, + { name: 'sepSiteGroup', header: { text: '분류식' }, items: ['sprtSoilholeSite', 'sprtSoilspllSite'] } + ] + }, + { + name: 'branchGroup', header: { text: '지선(m)' }, + items: ['brnchlnSm', 'cmbnBrnchlnExtn', { name: 'sepBranchGroup', header: { text: '우수/오수' }, items: ['rainwtrBrnchlnExtn', 'pltwtrBrnchlnExtn'] }] + } + ], + }, + 'rmk' + ] +}, + { + tabKey: 'c', + tabLabel: '관종별 현황', + rowStartNum: 2, + fixedColumns: 3, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'SWRG_PIPE_NM', fieldName: '관종', header: { text: '관종' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + { name: 'TOTAL_EXTN_SUM', fieldName: '계(총계)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LAYING_EXTN_SUM', fieldName: '매설연장(m)_총계', header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'REMVL_EXTN_SUM', fieldName: '철거연장(m)_총계', header: { text: '철거연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + ...Array.from({ length: 30 }, (_, i) => { + const yNum = (30 - i).toString().padStart(2, '0'); + const yrOffset = 29 - i; + return [ + { name: `TOTAL_EXTN_${yNum}Y`, fieldName: `계(-${yrOffset}년)`, header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: `LAYING_EXTN_${yNum}Y`, fieldName: `매설연장(m)_(-${yrOffset}년)`, header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: `REMVL_EXTN_${yNum}Y`, fieldName: `철거연장(m)_(-${yrOffset}년)`, header: { text: '철거연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' } + ]; + }).flat(), + + { name: 'LAYING_EXTN', fieldName: `매설연장(m)_당해년도`, header: { text: '매설연장(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'SWRG_PIPE_NM', 'YR_GBN', + { name: 'summaryGroup', header: { text: '총계' }, items: ['TOTAL_EXTN_SUM', 'LAYING_EXTN_SUM', 'REMVL_EXTN_SUM'] }, + ...Array.from({ length: 30 }, (_, i) => { + const yNum = (30 - i).toString().padStart(2, '0'); + const yrOffset = 29 - i; + return { name: `yr${yNum}Group`, header: { text: `-${yrOffset}년` }, items: [`TOTAL_EXTN_${yNum}Y`, `LAYING_EXTN_${yNum}Y`, `REMVL_EXTN_${yNum}Y`] }; + }), + { name: 'currentYrGroup', header: { text: `${baseYear}년` }, items: ['LAYING_EXTN'] }, + 'RMK' + ] + }, + { + tabKey: 'd', + tabLabel: '관경별 현황', + rowStartNum: 2, + fixedColumns: 3, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '구군' } }, + { name: 'SWRG_PIPE_NM', fieldName: '관종', header: { text: '관종' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'TOTAL_EXTN_M', fieldName: '총계(m)', header: { text: '총계(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'UNDER_200', fieldName: '200mm 미만', header: { text: '200mm 미만' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OVER_200_UNDEV_300', fieldName: '200mm이상~300mm미만', header: { text: '200mm이상~\n300mm미만' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OVER_300_UNDEV_500', fieldName: '300mm이상~500mm미만', header: { text: '300mm이상~\n500mm미만' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OVER_500_UNDEV_800', fieldName: '500mm이상~800mm미만', header: { text: '500mm이상~\n800mm미만' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'OVER_800', fieldName: '800mm 이상', header: { text: '800mm 이상' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BOX', fieldName: '사각형(m)', header: { text: '사각형(m)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC', fieldName: '기타(측구/개거 등)', header: { text: '기타\n(측구/개거 등)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'SWRG_PIPE_NM', 'YR_GBN', 'TOTAL_EXTN_M', + { name: 'circleGroup', header: { text: '원형(m)' }, items: ['UNDER_200', 'OVER_200_UNDEV_300', 'OVER_300_UNDEV_500', 'OVER_500_UNDEV_800', 'OVER_800'] }, + 'BOX', 'ETC', 'RMK', + ] + } +]; + +export const SewagePipeColumnInfoListRvw = rawList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts new file mode 100644 index 000000000..43aa1c62d --- /dev/null +++ b/apps/st/src/components/util/column/review/SewageReservoirPumpRvwColumn.ts @@ -0,0 +1,194 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 04. 하수저류 시설 및 빗물 펌프장 +const rawReservoirList = [ + { + tabKey: 'a', + tabLabel: '하수저류시설', + rowStartNum: 3, + fixedColumns: 2, + columns: [ + /* 1. 기본 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'SWGE_STRGE_NM', fieldName: '시설명', header: { text: '시설명' } }, + { name: 'ADDR', fieldName: '위치', header: { text: '위치' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 2. 시설 제원 */ + { name: 'RN_DT', fieldName: '가동개시 년월일', header: { text: '가동개시\n년월일' } }, + { name: 'PL_DSGN_FRQNC', fieldName: '계획설계빈도', header: { text: '계획설계빈도' } }, + { name: 'INS_PER1', fieldName: '침수예방', header: { text: '침수예방' } }, + { name: 'INS_PER2', fieldName: '수질오염저감', header: { text: '수질오염저감' } }, + { name: 'INS_PER3', fieldName: '하수 재이용 용도', header: { text: '하수\n재이용\n용도' } }, + { name: 'FAC_RES', fieldName: '시설구조', header: { text: '시설구조(일반지하식,지하터널식,기타)' } }, + { name: 'DGR_AR', fieldName: '집수구역면적(㎢)', header: { text: '집수구역면적(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + { name: 'SWGE_SGBS_CPCTY', fieldName: '시설용량(㎥)', header: { text: '시설용량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 3. 펌프시설 */ + { name: 'TOT_CPCTY', fieldName: '총양수량(㎥/min)', header: { text: '총양수량\n(㎥/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_CALBR', fieldName: '구경(mm)_1', header: { text: '구경(mm)' } }, + { name: 'WP_CPCTY', fieldName: '대당 양수량_1', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_CO', fieldName: '펌프대수_1', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_PREPAR_CO', fieldName: '예비펌프대수_1', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_CALBR2', fieldName: '구경(mm)_2', header: { text: '구경(mm)' } }, + { name: 'WP_CPCTY2', fieldName: '대당 양수량_2', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_CO2', fieldName: '펌프대수_2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_PREPAR_CO2', fieldName: '예비펌프대수_2', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_CALBR3', fieldName: '구경(mm)_3', header: { text: '구경(mm)' } }, + { name: 'WP_CPCTY3', fieldName: '대당 양수량_3', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_CO3', fieldName: '펌프대수_3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_PREPAR_CO3', fieldName: '예비펌프대수_3', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 4. 부대시설 및 방식 */ + { name: 'FRE_FNNC', fieldName: '전처리시설(유/무)', header: { text: '전처리시설(유/무)' } }, + { name: 'DORZEQP_FNNC', fieldName: '탈취설비(유/무)', header: { text: '탈취설비(유/무)' } }, + { name: 'SELF_ETRQ_FNNC', fieldName: '자가발전(유/무)', header: { text: '자가발전(유/무)' } }, + { name: 'DRA_MTH', fieldName: '배수방식(자연배수,강제배수)', header: { text: '배수방식(자연배수,강제배수)' } }, + { name: 'ELEC_MTH', fieldName: '저류방식(직렬,병렬)', header: { text: '저류방식(직렬,병렬)' } }, + { name: 'ELEC_PRO_MAT', fieldName: '저류수 처리방법', header: { text: '저류수\n처리방법' } }, + { name: 'DIS_WAT', fieldName: '방류수역(또는 연계처리장명)', header: { text: '방류수역(또는 연계처리장명)' } }, + + /* 5. 최종처분량 및 방법 */ + { name: 'SDMT_TRE_CPCTY', fieldName: '침사(량)', header: { text: '침사' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'IPRT_TRE_CPCTY', fieldName: '협잡물(량)', header: { text: '협잡물' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SDMT_TRE_MTH', fieldName: '침사(방법)', header: { text: '침사' } }, + { name: 'IPRT_TRE_MTH', fieldName: '협잡물(방법)', header: { text: '협잡물' } }, + + /* 6. 운영실적 */ + { name: 'YRSTP_RN_DYN', fieldName: '가동일수', header: { text: '가동일수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'DSPLCMNT_AMNT', fieldName: '총배수량(㎥/년)', header: { text: '총배수량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'SWGE_STRGE_NM', 'ADDR', 'YR_GBN', 'RN_DT', 'PL_DSGN_FRQNC', + { + name: 'purposeGroup', + header: { text: '설치목적(O,X로 표기, 중복체크 가능)' }, + items: ['INS_PER1', 'INS_PER2', 'INS_PER3'] + }, + 'FAC_RES', 'DGR_AR', 'SWGE_SGBS_CPCTY', + { + name: 'pumpMainGroup', + header: { text: '펌프시설' }, + items: [ + 'TOT_CPCTY', + { name: 'p1Group', header: { text: '펌프시설1' }, items: ['PUMP_CALBR', 'WP_CPCTY', 'PUMP_CO', 'PUMP_PREPAR_CO'] }, + { name: 'p2Group', header: { text: '펌프시설2' }, items: ['PUMP_CALBR2', 'WP_CPCTY2', 'PUMP_CO2', 'PUMP_PREPAR_CO2'] }, + { name: 'p3Group', header: { text: '펌프시설3' }, items: ['PUMP_CALBR3', 'WP_CPCTY3', 'PUMP_CO3', 'PUMP_PREPAR_CO3'] } + ] + }, + { + name: 'subFacGroup', + header: { text: '부대시설' }, + items: ['FRE_FNNC', 'DORZEQP_FNNC', 'SELF_ETRQ_FNNC'] + }, + 'DRA_MTH', 'ELEC_MTH', 'ELEC_PRO_MAT', 'DIS_WAT', + { + name: 'disposalAmtGroup', + header: { text: '최종처분량(ton/년)' }, + items: ['SDMT_TRE_CPCTY', 'IPRT_TRE_CPCTY'] + }, + { + name: 'disposalMthGroup', + header: { text: '최종처분방법' }, + items: ['SDMT_TRE_MTH', 'IPRT_TRE_MTH'] + }, + { + name: 'opGroup', + header: { text: '운영실적' }, + items: ['YRSTP_RN_DYN', 'DSPLCMNT_AMNT'] + }, + 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '빗물펌프장', + rowStartNum: 3, + fixedColumns: 2, + columns: [ + /* 1. 기본 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'SWGE_STRGE_NM', fieldName: '시설명', header: { text: '시설명' } }, + { name: 'ADDR', fieldName: '위치', header: { text: '위치' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 2. 시설 제원 */ + { name: 'FCT_KND', fieldName: '시설물종류', header: { text: '시설물종류' } }, + { name: 'RN_DT', fieldName: '가동개시 년월일', header: { text: '가동개시\n년월일' } }, + { name: 'PL_DSGN_FRQNC', fieldName: '계획설계빈도', header: { text: '계획설계빈도' } }, + { name: 'DGR_AR', fieldName: '집수구역면적(㎢)', header: { text: '집수구역면적(㎢)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.000' }, + + /* 3. 유수지 및 흡수정 */ + { name: 'REV_FNNC', fieldName: '유수지유무(유,무)', header: { text: '유수지유무\n(유,무)' } }, + { name: 'REV_CPCTY', fieldName: '저류량(유수지)', header: { text: '저류량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ABS_CPCTY', fieldName: '저류량(흡수정)', header: { text: '저류량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SWGE_SGBS_CPCTY', fieldName: '시설용량(㎥)', header: { text: '시설용량(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 4. 펌프시설 */ + { name: 'TOT_CPCTY', fieldName: '총양수량(㎥/min)', header: { text: '총양수량\n(㎥/min)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_CALBR', fieldName: '구경(mm)_1', header: { text: '구경(mm)' } }, + { name: 'WP_CPCTY', fieldName: '대당 양수량_1', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_CO', fieldName: '펌프대수_1', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_PREPAR_CO', fieldName: '예비펌프대수_1', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_CALBR2', fieldName: '구경(mm)_2', header: { text: '구경(mm)' } }, + { name: 'WP_CPCTY2', fieldName: '대당 양수량_2', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_CO2', fieldName: '펌프대수_2', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_PREPAR_CO2', fieldName: '예비펌프대수_2', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_CALBR3', fieldName: '구경(mm)_3', header: { text: '구경(mm)' } }, + { name: 'WP_CPCTY3', fieldName: '대당 양수량_3', header: { text: '대당 양수량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PUMP_CO3', fieldName: '펌프대수_3', header: { text: '펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PUMP_PREPAR_CO3', fieldName: '예비펌프대수_3', header: { text: '예비펌프대수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 5. 부대시설 및 기타 */ + { name: 'FRE_FNNC', fieldName: '전처리시설', header: { text: '전처리시설' } }, + { name: 'DORZEQP_FNNC', fieldName: '탈취설비', header: { text: '탈취설비' } }, + { name: 'SELF_ETRQ_FNNC', fieldName: '자가발전', header: { text: '자가발전' } }, + { name: 'DIS_WAT', fieldName: '방류수역', header: { text: '방류수역' } }, + + /* 6. 최종처분량 및 방법 */ + { name: 'SDMT_TRE_CPCTY', fieldName: '침사(량)', header: { text: '침사(량)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'IPRT_TRE_CPCTY', fieldName: '협잡물(량)', header: { text: '협잡물(량)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'SDMT_TRE_MTH', fieldName: '침사(방법)', header: { text: '침사(방법)' } }, + { name: 'IPRT_TRE_MTH', fieldName: '협잡물(방법)', header: { text: '협잡물(방법)' } }, + + /* 7. 운영실적 */ + { name: 'YRSTP_RN_DYN', fieldName: '가동일수', header: { text: '가동일수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'DSPLCMNT_AMNT', fieldName: '총배수량(㎥/년)', header: { text: '총배수량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'SWGE_STRGE_NM', 'ADDR', 'YR_GBN', 'FCT_KND', 'RN_DT', 'PL_DSGN_FRQNC', 'DGR_AR', + { name: 'revGroup', header: { text: '유수지' }, items: ['REV_FNNC', 'REV_CPCTY'] }, + { name: 'absGroup', header: { text: '흡수정' }, items: ['ABS_CPCTY'] }, + 'SWGE_SGBS_CPCTY', + { + name: 'pumpMainGroup', header: { text: '펌프시설' }, + items: [ + 'TOT_CPCTY', + { name: 'p1Group', header: { text: '펌프시설1' }, items: ['PUMP_CALBR', 'WP_CPCTY', 'PUMP_CO', 'PUMP_PREPAR_CO'] }, + { name: 'p2Group', header: { text: '펌프시설2' }, items: ['PUMP_CALBR2', 'WP_CPCTY2', 'PUMP_CO2', 'PUMP_PREPAR_CO2'] }, + { name: 'p3Group', header: { text: '펌프시설3' }, items: ['PUMP_CALBR3', 'WP_CPCTY3', 'PUMP_CO3', 'PUMP_PREPAR_CO3'] } + ] + }, + { name: 'subFacGroup', header: { text: '부대시설' }, items: ['FRE_FNNC', 'DORZEQP_FNNC', 'SELF_ETRQ_FNNC'] }, + 'DIS_WAT', + { name: 'disposalAmtGroup', header: { text: '최종처분량(ton/년)' }, items: ['SDMT_TRE_CPCTY', 'IPRT_TRE_CPCTY'] }, + { name: 'disposalMthGroup', header: { text: '최종처분방법' }, items: ['SDMT_TRE_MTH', 'IPRT_TRE_MTH'] }, + { name: 'opGroup', header: { text: '운영실적' }, items: ['YRSTP_RN_DYN', 'DSPLCMNT_AMNT'] }, + 'RMK' + ] + } +]; + +export const SewageReservoirPumpInfoListRvw = rawReservoirList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewerageFinanceRvwColumn.ts b/apps/st/src/components/util/column/review/SewerageFinanceRvwColumn.ts new file mode 100644 index 000000000..b3dc2c73e --- /dev/null +++ b/apps/st/src/components/util/column/review/SewerageFinanceRvwColumn.ts @@ -0,0 +1,215 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 09. 하수도 재정 +const rawFinanceList = [ + { + tabKey: 'a', + tabLabel: '하수도재정 결산', + rowStartNum: 3, + fixedColumns: 1, + columns: [ + /* 1. 기본 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'ADST_CD', fieldName: '행정코드', header: { text: '행정코드' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 2. 재정별 사업비 (수입) */ + { name: 'FNANC_WCT_SM', fieldName: '계(수입)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'NTNXPN', fieldName: '중앙정부 지원액', header: { text: '중앙정부\n지원액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LCLEXPNS', fieldName: '특․광역시, 도', header: { text: '특․광역시, 도' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LCLTY_CT', fieldName: '시,군,구 지자체', header: { text: '시,군,구 지자체' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SEWER_RNTFEE', fieldName: '하수도 사용료', header: { text: '하수도\n사용료' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'AMNTBRNCSR', fieldName: '원인자 부담금', header: { text: '원인자\n부담금' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC_INCME', fieldName: '기타 잡수입', header: { text: '기타\n잡수입' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'CYFD_AMOUNT', fieldName: '이월액', header: { text: '이월액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 3. 부채액 */ + { name: 'DEBT_AMOUNT', fieldName: '부채액(백만원)', header: { text: '부채액\n(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 4. 용도별 사업비 (지출) */ + { name: 'PRPOS_WCT_SM', fieldName: '계(지출)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PRCPLT_SM', fieldName: '소계(처리장)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PRCPLT_FCLTY', fieldName: '시설비(처리장)', header: { text: '시설비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PRCPLT_RPAIR', fieldName: '개보수비(처리장)', header: { text: '개보수비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PRCPLT_ORPNS', fieldName: '운영 유지비(처리장)', header: { text: '운영\n유지비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PRCPLT_ETC', fieldName: '기타(처리장)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SEWAGE_SM', fieldName: '소계(관로)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SEWAGE_FCLTY', fieldName: '시설비(관로)', header: { text: '시설비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SEWAGE_RPAIR', fieldName: '개보수비(관로)', header: { text: '개보수비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SEWAGE_ORPNS', fieldName: '운영 유지비(관로)', header: { text: '운영\n유지비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SEWAGE_ETC', fieldName: '기타(관로)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_SM', fieldName: '소계(저류시설)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_FCLTY', fieldName: '시설비(저류시설)', header: { text: '시설비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_RPAIR', fieldName: '개보수비(저류시설)', header: { text: '개보수비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_ORPNS', fieldName: '운영 유지비(저류시설)', header: { text: '운영\n유지비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SWGE_STRGE_ETC', fieldName: '기타(저류시설)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC_SM', fieldName: '소계(기타지출)', header: { text: '소계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ACDNT_CYFD_AMOUNT', fieldName: '사고 이월액', header: { text: '사고\n이월액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'UNRCIV_AMOUNT', fieldName: '미수납액', header: { text: '미수납액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC_AMOUNT', fieldName: '기타(지출)', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 5. 비고 */ + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'ADST_CD', + { + name: 'financeGroup', + header: { text: '재정별 사업비(백만원)' }, + items: [ + 'FNANC_WCT_SM', 'NTNXPN', + { name: 'localGroup', header: { text: '지방비' }, items: ['LCLEXPNS', 'LCLTY_CT'] }, + 'SEWER_RNTFEE', 'AMNTBRNCSR', 'ETC_INCME', 'CYFD_AMOUNT' + ] + }, + 'DEBT_AMOUNT', + { + name: 'usageGroup', + header: { text: '용도별사업비(백만원)' }, + items: [ + 'PRPOS_WCT_SM', + { name: 'plantGroup', header: { text: '처리장' }, items: ['PRCPLT_SM', 'PRCPLT_FCLTY', 'PRCPLT_RPAIR', 'PRCPLT_ORPNS', 'PRCPLT_ETC'] }, + { name: 'pipeGroup', header: { text: '하수관로' }, items: ['SEWAGE_SM', 'SEWAGE_FCLTY', 'SEWAGE_RPAIR', 'SEWAGE_ORPNS', 'SEWAGE_ETC'] }, + { name: 'storageGroup', header: { text: '하수저류시설' }, items: ['SWGE_STRGE_SM', 'SWGE_STRGE_FCLTY', 'SWGE_STRGE_RPAIR', 'SWGE_STRGE_ORPNS', 'SWGE_STRGE_ETC'] }, + { name: 'etcUsageGroup', header: { text: '기타' }, items: ['ETC_SM', 'ACDNT_CYFD_AMOUNT', 'UNRCIV_AMOUNT', 'ETC_AMOUNT'] } + ] + }, + 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '하수도 요금', + rowStartNum: 2, + fixedColumns: 1, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'FYER_LEVY_QY', fieldName: '연간조정량(㎥)(A)', header: { text: '연간조정량\n(㎥)\n(A)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LEVY_AMOUNT', fieldName: '하수도사용료수익(원)(B)', header: { text: '하수도사용료수익\n(원)\n(B)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'AVRG_UNTPC', fieldName: '㎥당요금(원/㎥) C=(B/A)', header: { text: '㎥당요금(원/㎥)\nC=(B/A)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SMRIZE_PRMPC', fieldName: '총괄원가(원)(D)', header: { text: '총괄원가(원)\n(D)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SMRIZE_UNIT_PRMPC', fieldName: '㎥당원가(원/㎥) E=(D/A)', header: { text: '㎥당원가(원/㎥)\nE=(D/A)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RLTY_RT', fieldName: '요금현실화율(%) F=(C/E*100)', header: { text: '요금현실화율(%)\nF=(C/E*100)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'FYER_LEVY_QY', 'LEVY_AMOUNT', 'AVRG_UNTPC', 'SMRIZE_PRMPC', 'SMRIZE_UNIT_PRMPC', 'RLTY_RT', 'RMK' + ] + }, + { + tabKey: 'c', + tabLabel: '하수도 사용료', + rowStartNum: 2, + fixedColumns: 1, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'LEVY_AMOUNT', fieldName: '부과액(총계)', header: { text: '부과액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'LEVY_QY', fieldName: '부과량(총계)', header: { text: '부과량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'HOME_LEVY_AMOUNT', fieldName: '부과액(가정용)', header: { text: '부과액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'HOME_LEVY_QY', fieldName: '부과량(가정용)', header: { text: '부과량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'HOME_UNTPC', fieldName: '단가(가정용)', header: { text: '단가' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'JOB_LEVY_AMOUNT', fieldName: '부과액(업무용)', header: { text: '부과액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'JOB_LEVY_QY', fieldName: '부과량(업무용)', header: { text: '부과량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'JOB_UNTPC', fieldName: '단가(업무용)', header: { text: '단가' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BSN_LEVY_AMOUNT', fieldName: '부과액(영업용)', header: { text: '부과액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BSN_LEVY_QY', fieldName: '부과량(영업용)', header: { text: '부과량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BSN_UNTPC', fieldName: '단가(영업용)', header: { text: '단가' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BATHS1_LEVY_AMOUNT', fieldName: '부과액(욕탕1)', header: { text: '부과액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BATHS1_LEVY_QY', fieldName: '부과량(욕탕1)', header: { text: '부과량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BATHS1_UNTPC', fieldName: '단가(욕탕1)', header: { text: '단가' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BATHS2_LEVY_AMOUNT', fieldName: '부과액(욕탕2)', header: { text: '부과액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BATHS2_LEVY_QY', fieldName: '부과량(욕탕2)', header: { text: '부과량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'BATHS2_UNTPC', fieldName: '단가(욕탕2)', header: { text: '단가' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'INDUST_LEVY_AMOUNT', fieldName: '부과액(산업용)', header: { text: '부과액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'INDUST_LEVY_QY', fieldName: '부과량(산업용)', header: { text: '부과량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'INDUST_UNTPC', fieldName: '단가(산업용)', header: { text: '단가' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC_LEVY_AMOUNT', fieldName: '부과액(기타사용료)', header: { text: '부과액' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC_LEVY_QY', fieldName: '부과량(기타사용료)', header: { text: '부과량' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'ETC_UNTPC', fieldName: '단가(기타사용료)', header: { text: '단가' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + { + name: 'totalGroup', header: { text: '총계' }, + items: [{ name: 'tAmtUnit', header: { text: '부과액\n(백만원)' }, items: ['LEVY_AMOUNT'] }, { name: 'tQyUnit', header: { text: '부과량\n(천톤)' }, items: ['LEVY_QY'] }] + }, + { + name: 'homeGroup', header: { text: '가 정 용' }, + items: [{ name: 'hAmtUnit', header: { text: '부과액\n(백만원)' }, items: ['HOME_LEVY_AMOUNT'] }, { name: 'hQyUnit', header: { text: '부과량\n(천톤)' }, items: ['HOME_LEVY_QY'] }, { name: 'hUntUnit', header: { text: '단가\n(원/톤)' }, items: ['HOME_UNTPC'] }] + }, + { + name: 'jobGroup', header: { text: '업 무 용' }, + items: [{ name: 'jAmtUnit', header: { text: '부과액\n(백만원)' }, items: ['JOB_LEVY_AMOUNT'] }, { name: 'jQyUnit', header: { text: '부과량\n(천톤)' }, items: ['JOB_LEVY_QY'] }, { name: 'jUntUnit', header: { text: '단가\n(원/톤)' }, items: ['JOB_UNTPC'] }] + }, + { + name: 'bsnGroup', header: { text: '영 업 용(일 반 용)' }, + items: [{ name: 'bAmtUnit', header: { text: '부과액\n(백만원)' }, items: ['BSN_LEVY_AMOUNT'] }, { name: 'bQyUnit', header: { text: '부과량\n(천톤)' }, items: ['BSN_LEVY_QY'] }, { name: 'bUntUnit', header: { text: '단가\n(원/톤)' }, items: ['BSN_UNTPC'] }] + }, + { + name: 'bath1Group', header: { text: '욕 탕 1종(대중탕용)' }, + items: [{ name: 'bt1AmtUnit', header: { text: '부과액\n(백만원)' }, items: ['BATHS1_LEVY_AMOUNT'] }, { name: 'bt1QyUnit', header: { text: '부과량\n(천톤)' }, items: ['BATHS1_LEVY_QY'] }, { name: 'bt1UntUnit', header: { text: '단가\n(원/톤)' }, items: ['BATHS1_UNTPC'] }] + }, + { + name: 'bath2Group', header: { text: '욕 탕 2종' }, + items: [{ name: 'bt2AmtUnit', header: { text: '부과액\n(백만원)' }, items: ['BATHS2_LEVY_AMOUNT'] }, { name: 'bt2QyUnit', header: { text: '부과량\n(천톤)' }, items: ['BATHS2_LEVY_QY'] }, { name: 'bt2UntUnit', header: { text: '단가\n(원/톤)' }, items: ['BATHS2_UNTPC'] }] + }, + { + name: 'industGroup', header: { text: '산업용 및 공업용' }, + items: [{ name: 'iAmtUnit', header: { text: '부과액\n(백만원)' }, items: ['INDUST_LEVY_AMOUNT'] }, { name: 'iQyUnit', header: { text: '부과량\n(천톤)' }, items: ['INDUST_LEVY_QY'] }, { name: 'iUntUnit', header: { text: '단가\n(원/톤)' }, items: ['INDUST_UNTPC'] }] + }, + { + name: 'etcGroup', header: { text: '기타' }, + items: [{ name: 'eAmtUnit', header: { text: '부과액\n(백만원)' }, items: ['ETC_LEVY_AMOUNT'] }, { name: 'eQyUnit', header: { text: '부과량\n(천톤)' }, items: ['ETC_LEVY_QY'] }, { name: 'eUntUnit', header: { text: '단가\n(원/톤)' }, items: ['ETC_UNTPC'] }] + }, + 'RMK' + ] + }, + { + tabKey: 'd', + tabLabel: '원인자부담금', + rowStartNum: 3, + fixedColumns: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'LEVY_CO', fieldName: '건수(부과액)', header: { text: '건수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'LEVY_AMOUNT', fieldName: '금액(백만원)(부과액)', header: { text: '금액(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'TRGET_LEV_STTUS_CO', fieldName: '건수(계)', header: { text: '건수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'TRGET_LEV_STTUS_AMOUNT', fieldName: '금액(백만원)(계)', header: { text: '금액(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'DRNG_EQP_CO', fieldName: '건수(배수설비)', header: { text: '건수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'DRNG_EQP_AMOUNT', fieldName: '금액(백만원)(배수설비)', header: { text: '금액(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'CNTRWK_CO', fieldName: '건수(타공사)', header: { text: '건수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CNTRWK_AMOUNT', fieldName: '금액(백만원)(타공사)', header: { text: '금액(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', + { name: 'levyMainGroup', header: { text: '부과액' }, items: ['LEVY_CO', 'LEVY_AMOUNT'] }, + { + name: 'collectGroup', header: { text: '대상별 징수현황' }, + items: [ + { name: 'collectTotal', header: { text: '계' }, items: ['TRGET_LEV_STTUS_CO', 'TRGET_LEV_STTUS_AMOUNT'] }, + { name: 'contractorGroup', header: { text: '배수설비설치자\n(하수도법 제61조 제1항)' }, items: ['DRNG_EQP_CO', 'DRNG_EQP_AMOUNT'] }, + { name: 'otherGroup', header: { text: '타공사·타행위자\n(하수도법 제61조 제2항)' }, items: ['CNTRWK_CO', 'CNTRWK_AMOUNT'] } + ] + }, + 'RMK' + ] + } +]; + +export const SewerageFinanceInfoListRvw = rawFinanceList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts b/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts new file mode 100644 index 000000000..bf1af2259 --- /dev/null +++ b/apps/st/src/components/util/column/review/SeweragePenetrationRateRvwColumn.ts @@ -0,0 +1,186 @@ +import { ValueType } from "realgrid"; +import { footerIntArrayByDivision, footerDecimal3ArrayByDivision, footerAvgDecimalArrayByDivision } from "@/components/util/grid/footerSummary"; +import type { GridView, DataColumn, ColumnFooter } from "@/components/type/DataGrid.type"; + +export const SeweragePenetrationRateInfoList = { + columns: [ + { + name: 'sido', + fieldName: 'sido', + header: { text: '시도' }, + mergeCells: true, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; + return '합계'; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + if (divisionValues.length > divisionIndex) return divisionValues[divisionIndex] + '합계'; + return '합계'; + } + } + ] + }, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, mergeCells: true, editable: false, sortdisable: true }, + { name: 'adstDong', fieldName: 'adstDong', header: { text: '행정구역명' }, mergeCells: true, editable: false, sortdisable: true }, + { + name: 'displayYear', + fieldName: 'displayYear', + header: { text: '구분' }, + editable: false, + sortdisable: true, + footer: [ + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 0; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + }, + { + valueCallback: (grid: GridView, column: DataColumn, footerIndex: number, columnFooter: ColumnFooter, value: number | string | undefined) => { + const divisionIndex = 1; + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, 'displayYear'); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + const divisionValues = Array.from(uniqueValues); + return divisionValues.length > divisionIndex ? divisionValues[divisionIndex] + '합계' : ''; + } + } + ] + }, + { name: 'rvbsn', fieldName: 'rvbsn', header: { text: '수계' } }, + { name: 'bstrm', fieldName: 'bstrm', header: { text: '지류' } }, + { name: 'mdbsn', fieldName: 'mdbsn', header: { text: '세부단위유역' } }, + { name: 'lgbsn', fieldName: 'lgbsn', header: { text: '중권역' } }, + { name: 'mdmbsn', fieldName: 'mdmbsn', header: { text: '소권역' } }, + { name: 'speclCntrplnAr', fieldName: 'speclCntrplnAr', header: { text: '특별대책지역' } }, + { name: 'popltnSm', fieldName: 'popltnSm', header: { text: '총인구' }, footer: footerIntArrayByDivision, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'arSm', fieldName: 'arSm', header: { text: '총면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'swgeProcZoneInnerSm', fieldName: 'swgeProcZoneInnerSm', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0', styleName: 'rg-cell-total' }, + + // 공공하수처리인구 + { name: 'pblswrgPopltnSm', fieldName: 'pblswrgPopltnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pblswrgPrmTrt', fieldName: 'pblswrgPrmTrt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pblswrgScdTrt', fieldName: 'pblswrgScdTrt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'pblswrgTertTrt', fieldName: 'pblswrgTertTrt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + // 폐수처리인구(명) + { name: 'wstrPopltnSm', fieldName: 'wstrPopltnSm', header: { text: '합계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'wstrPrmTrt', fieldName: 'wstrPrmTrt', header: { text: '1차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'wstrScdTrt', fieldName: 'wstrScdTrt', header: { text: '2차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'wstrTertTrt', fieldName: 'wstrTertTrt', header: { text: '3차처리' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + + { name: 'notConectPopltn', fieldName: 'notConectPopltn', header: { text: '미접속인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'swgeProcZoneInnerAr', fieldName: 'swgeProcZoneInnerAr', header: { text: '면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'swgeProcZoneOuterSm', fieldName: 'swgeProcZoneOuterSm', header: { text: '계' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'townUnprocPopltn', fieldName: 'townUnprocPopltn', header: { text: '미처리인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'townSwttPopltn', fieldName: 'townSwttPopltn', header: { text: '오수처리인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'townWrrtnPopltn', fieldName: 'townWrrtnPopltn', header: { text: '정화조인구' }, footer: footerIntArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0' }, + { name: 'swgeProcZoneOuterAr', fieldName: 'swgeProcZoneOuterAr', header: { text: '면적(㎢)' }, footer: footerDecimal3ArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'pblswrgPopltnSuprt', fieldName: 'pblswrgPopltnSuprt', header: { text: '공공하수처리구역인구보급율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'adtrtPopltnSuprt', fieldName: 'adtrtPopltnSuprt', header: { text: '고도처리인구보급율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'swrgInstlrt', fieldName: 'swrgInstlrt', header: { text: '하수도설치율(%)' }, footer: footerAvgDecimalArrayByDivision, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' }, + { name: 'rmk', fieldName: 'rmk', header: { text: '비고' } }, + ], + columnLayout: [ + { + name: 'groupA', + hideChildHeaders: false, + header: { text: '행정구역' }, + items: [ + { column: 'sido', footerUserSpans: [{ colspan: 4 }, { colspan: 4 }] }, + 'gugun', + 'adstDong', + ] + }, + 'displayYear', + 'rvbsn', + 'bstrm', + { + name: 'groupB', + hideChildHeaders: false, + header: { text: '수계영향권별분류' }, + items: ['mdbsn', 'lgbsn', 'mdmbsn'], + }, + 'speclCntrplnAr', + 'popltnSm', + 'arSm', + { + name: 'groupD', + hideChildHeaders: false, + header: { text: '하수처리구역내' }, + items: [ + 'swgeProcZoneInnerSm', + { + name: 'pblswrgGroup', + hideChildHeaders: false, + header: { text: '공공하수처리인구(명)' }, + items: ['pblswrgPopltnSm', 'pblswrgPrmTrt', 'pblswrgScdTrt', 'pblswrgTertTrt'], + }, + { + name: 'wstrGroup', + hideChildHeaders: false, + header: { text: '폐수처리인구(명)' }, + items: ['wstrPopltnSm', 'wstrPrmTrt', 'wstrScdTrt', 'wstrTertTrt'], + }, + 'notConectPopltn', + 'swgeProcZoneInnerAr' + ], + }, + { + name: 'groupE', + hideChildHeaders: false, + header: { text: '하수처리구역외' }, + items: ['swgeProcZoneOuterSm', 'townUnprocPopltn', 'townSwttPopltn', 'townWrrtnPopltn', 'swgeProcZoneOuterAr'], + }, + 'pblswrgPopltnSuprt', + 'adtrtPopltnSuprt', + 'swrgInstlrt', + 'rmk', + ], + fixedColumns: 2, + rowStartNum: 3 +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/SewerageServiceLevelRvwColumn.ts b/apps/st/src/components/util/column/review/SewerageServiceLevelRvwColumn.ts new file mode 100644 index 000000000..c673bbda5 --- /dev/null +++ b/apps/st/src/components/util/column/review/SewerageServiceLevelRvwColumn.ts @@ -0,0 +1,117 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 13. 하수도 서비스 수준 +const rawServiceLevelList = [ + { + tabKey: 'a', + tabLabel: '민원', + rowStartNum: 2, + fixedColumns: 2, + columns: [ + /* 1. 기본 정보 */ + { name: 'SIDO', fieldName: 'SIDO', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: 'GUGUN', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: 'YR_GBN', header: { text: '구분' } }, + + /* 2. 하수처리 인구 (정수 반영) */ + { name: 'POPLTN_SM', fieldName: 'POPLTN_SM', header: { text: '하수처리인구\n(명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 3. 민원유형 (단위: 건 / 정수 반영) */ + { name: 'CVPL_CM', fieldName: 'CVPL_CM', header: { text: '총계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_DCWTR_QLTWTR', fieldName: 'CVPL_DCWTR_QLTWTR', header: { text: '악취' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_BSML', fieldName: 'CVPL_BSML', header: { text: '하수관로' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_FIVW', fieldName: 'CVPL_FIVW', header: { text: '배수설비' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_POLLUTN_ACDNT', fieldName: 'CVPL_POLLUTN_ACDNT', header: { text: '맨홀' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_SSOS', fieldName: 'CVPL_SSOS', header: { text: '정화조' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_CHRGE', fieldName: 'CVPL_CHRGE', header: { text: '하수도요금' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CVPL_ETC', fieldName: 'CVPL_ETC', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 4. 성과 지표 및 비고 (소수점 1자리 반영) */ + { name: 'STDR_POPLTN_PER_CVPL', fieldName: 'STDR_POPLTN_PER_CVPL', header: { text: '기준인구당\n민원건수\n(건/10,000명)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: 'RMK', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', + 'POPLTN_SM', + { + name: 'complaintTypeGroup', + header: { text: '민원유형(건)' }, + items: [ + 'CVPL_CM', + 'CVPL_DCWTR_QLTWTR', + 'CVPL_BSML', + 'CVPL_FIVW', + 'CVPL_POLLUTN_ACDNT', + 'CVPL_SSOS', + 'CVPL_CHRGE', + 'CVPL_ETC' + ] + }, + 'STDR_POPLTN_PER_CVPL', + 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '주민친화시설', + rowStartNum: 2, + fixedColumns: 5, + columns: [ + /* 1. 기본 및 시설 정보 */ + { name: 'SIDO', fieldName: 'SIDO', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: 'GUGUN', header: { text: '시군구' } }, + { name: 'BSC_FCT_NM', fieldName: 'BSC_FCT_NM', header: { text: '처리장명' } }, + { name: 'FCT_CPC', fieldName: 'FCT_CPC', header: { text: '시설용량\n(㎥/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'YR_GBN', fieldName: 'YR_GBN', header: { text: '구분' } }, + + /* 2. 처리장 전체 면적 (소수점 1자리 반영) */ + { name: 'PRCPLT_AR', fieldName: 'PRCPLT_AR', header: { text: '처리장\n면적(㎡)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 3. 주민친화시설 면적 상세 (단위: ㎡ / 정수 반영) */ + { name: 'TOTAL_AR', fieldName: 'TOTAL_AR', header: { text: '총계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'RESTRM_AR', fieldName: 'RESTRM_AR', header: { text: '휴게시설' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CHILDPLAY_AR', fieldName: 'CHILDPLAY_AR', header: { text: '어린이놀이공간' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ALSFC_AR', fieldName: 'ALSFC_AR', header: { text: '체력단련시설' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PLGRND_AR', fieldName: 'PLGRND_AR', header: { text: '운동시설' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'PRKPLCE_AR', fieldName: 'PRKPLCE_AR', header: { text: '주차장' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'CTLSTT_AR', fieldName: 'CTLSTT_AR', header: { text: '교육 및\n문화시설' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'NRPRK_AR', fieldName: 'NRPRK_AR', header: { text: '습지조성\n(생태공원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + { name: 'ETC_AR', fieldName: 'ETC_AR', header: { text: '기타' }, valueType: ValueType.NUMBER, numberFormat: '#,##0' }, + + /* 4. 비고 */ + { name: 'RMK', fieldName: 'RMK', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'BSC_FCT_NM', + 'FCT_CPC', + 'YR_GBN', + 'PRCPLT_AR', + { + name: 'friendlyFacilityGroup', + header: { text: '주민친화시설 면적(㎡)' }, + items: [ + 'TOTAL_AR', + 'RESTRM_AR', + 'CHILDPLAY_AR', + 'ALSFC_AR', + 'PLGRND_AR', + 'PRKPLCE_AR', + 'CTLSTT_AR', + 'NRPRK_AR', + 'ETC_AR' + ] + }, + 'RMK' + ] + } +]; + +export const SewerageServiceLevelInfoListRvw = rawServiceLevelList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/StatsInputStatusRvwColumn.ts b/apps/st/src/components/util/column/review/StatsInputStatusRvwColumn.ts new file mode 100644 index 000000000..a5408cc7f --- /dev/null +++ b/apps/st/src/components/util/column/review/StatsInputStatusRvwColumn.ts @@ -0,0 +1,120 @@ +import { ValueType } from "realgrid"; + +/** + * 하수도 통계 검토 00. 통계 입력 현황 + */ +const StatsInputStatusInfoColumnRaw = { + columns: [ + // 기본 정보 + { name: 'chk', fieldName: 'chk', header: { text: '체크' }, width: 40 }, + { name: 'sido', fieldName: 'sido', header: { text: '시도' }, width: 80,mergeCells: true}, + { name: 'gugun', fieldName: 'gugun', header: { text: '시군구' }, width: 100 }, + { name: 'status', fieldName: 'status', header: { text: '진행상태' }, width: 120 }, + + // 01. 하수도보급율 (supply) + { name: 'supplyCharger', fieldName: 'supplyCharger', header: { text: '제출자' } }, + { name: 'supplyCttpc', fieldName: 'supplyCttpc', header: { text: '연락처' } }, + { name: 'supplyStatusNm', fieldName: 'supplyStatusNm', header: { text: '지자체진행상태' } }, + { name: 'supplyStatus', fieldName: 'supplyStatus', header: { text: '진행상태' } }, + { name: 'supplyCnt', fieldName: 'supplyCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 02. 하수관로 (facility) - 기존 3번 + { name: 'facilityCharger', fieldName: 'facilityCharger', header: { text: '제출자' } }, + { name: 'facilityCttpc', fieldName: 'facilityCttpc', header: { text: '연락처' } }, + { name: 'facilityStatusNm', fieldName: 'facilityStatusNm', header: { text: '지자체진행상태' } }, + { name: 'facilityStatus', fieldName: 'facilityStatus', header: { text: '진행상태' } }, + { name: 'facilityCnt', fieldName: 'facilityCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 03. 하수관로유지관리 (pipe) - 기존 4번 + { name: 'pipeCharger', fieldName: 'pipeCharger', header: { text: '제출자' } }, + { name: 'pipeCttpc', fieldName: 'pipeCttpc', header: { text: '연락처' } }, + { name: 'pipeStatusNm', fieldName: 'pipeStatusNm', header: { text: '지자체진행상태' } }, + { name: 'pipeCnt', fieldName: 'pipeCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 04. 하수저류시설 (storage) - 기존 5번 + { name: 'storageCharger', fieldName: 'storageCharger', header: { text: '제출자' } }, + { name: 'storageCttpc', fieldName: 'storageCttpc', header: { text: '연락처' } }, + { name: 'storageStatusNm', fieldName: 'storageStatusNm', header: { text: '지자체진행상태' } }, + { name: 'storageCnt', fieldName: 'storageCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 05. 펌프장 (pump) - 기존 6번 + { name: 'pumpCharger', fieldName: 'pumpCharger', header: { text: '제출자' } }, + { name: 'pumpCttpc', fieldName: 'pumpCttpc', header: { text: '연락처' } }, + { name: 'pumpStatusNm', fieldName: 'pumpStatusNm', header: { text: '지자체진행상태' } }, + { name: 'pumpCnt', fieldName: 'pumpCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 06. 공공하수처리시설 (treat) - 기존 7번 + { name: 'treatCharger', fieldName: 'treatCharger', header: { text: '제출자' } }, + { name: 'treatCttpc', fieldName: 'treatCttpc', header: { text: '연락처' } }, + { name: 'treatStatusNm', fieldName: 'treatStatusNm', header: { text: '지자체진행상태' } }, + { name: 'treatCnt', fieldName: 'treatCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 07. 분뇨처리시설 (small) - 기존 8번 + { name: 'smallCharger', fieldName: 'smallCharger', header: { text: '제출자' } }, + { name: 'smallCttpc', fieldName: 'smallCttpc', header: { text: '연락처' } }, + { name: 'smallStatusNm', fieldName: 'smallStatusNm', header: { text: '지자체진행상태' } }, + { name: 'smallCnt', fieldName: 'smallCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 08. 개인하수처리시설 (private) - 기존 9번 + { name: 'privateCharger', fieldName: 'privateCharger', header: { text: '제출자' } }, + { name: 'privateCttpc', fieldName: 'privateCttpc', header: { text: '연락처' } }, + { name: 'privateStatusNm', fieldName: 'privateStatusNm', header: { text: '지자체진행상태' } }, + { name: 'privateCnt', fieldName: 'privateCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 09. 하수도재정 (finance) - 기존 10번 + { name: 'financeCharger', fieldName: 'financeCharger', header: { text: '제출자' } }, + { name: 'financeCttpc', fieldName: 'financeCttpc', header: { text: '연락처' } }, + { name: 'financeStatusNm', fieldName: 'financeStatusNm', header: { text: '지자체진행상태' } }, + { name: 'financeCnt', fieldName: 'financeCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 10. 물재이용 (reuse) - 기존 11번 + { name: 'reuseCharger', fieldName: 'reuseCharger', header: { text: '제출자' } }, + { name: 'reuseCttpc', fieldName: 'reuseCttpc', header: { text: '연락처' } }, + { name: 'reuseStatusNm', fieldName: 'reuseStatusNm', header: { text: '지자체진행상태' } }, + { name: 'reuseCnt', fieldName: 'reuseCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 11. 하수및분뇨찌꺼기 (sludge) - 기존 12번 + { name: 'sludgeCharger', fieldName: 'sludgeCharger', header: { text: '제출자' } }, + { name: 'sludgeCttpc', fieldName: 'sludgeCttpc', header: { text: '연락처' } }, + { name: 'sludgeStatusNm', fieldName: 'sludgeStatusNm', header: { text: '지자체진행상태' } }, + { name: 'sludgeCnt', fieldName: 'sludgeCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 12. 하수및분뇨관련산업 (excreta) - 기존 13번 + { name: 'excretaCharger', fieldName: 'excretaCharger', header: { text: '제출자' } }, + { name: 'excretaCttpc', fieldName: 'excretaCttpc', header: { text: '연락처' } }, + { name: 'excretaStatusNm', fieldName: 'excretaStatusNm', header: { text: '지자체진행상태' } }, + { name: 'excretaCnt', fieldName: 'excretaCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + + // 13. 하수도서비스수준 (complaint) - 기존 15번 + { name: 'complaintCharger', fieldName: 'complaintCharger', header: { text: '제출자' } }, + { name: 'complaintCttpc', fieldName: 'complaintCttpc', header: { text: '연락처' } }, + { name: 'complaintStatusNm', fieldName: 'complaintStatusNm', header: { text: '지자체진행상태' } }, + { name: 'complaintCnt', fieldName: 'complaintCnt', header: { text: '건수' }, valueType: ValueType.NUMBER }, + ], + + columnLayout: [ + { name: 'addrGroup', header: { text: '구분' }, items: ['sido', 'gugun'] }, + 'status', + { name: 'group01', header: { text: '01. 하수도보급율' }, items: ['supplyCharger', 'supplyCttpc', 'supplyStatusNm', 'supplyStatus', 'supplyCnt'] }, + { name: 'group02', header: { text: '02. 하수관로' }, items: ['facilityCharger', 'facilityCttpc', 'facilityStatusNm', 'facilityStatus', 'facilityCnt'] }, + { name: 'group03', header: { text: '03. 하수관로유지관리' }, items: ['pipeCharger', 'pipeCttpc', 'pipeStatusNm', 'pipeCnt'] }, + { name: 'group04', header: { text: '04. 하수저류시설' }, items: ['storageCharger', 'storageCttpc', 'storageStatusNm', 'storageCnt'] }, + { name: 'group05', header: { text: '05. 펌프장' }, items: ['pumpCharger', 'pumpCttpc', 'pumpStatusNm', 'pumpCnt'] }, + { name: 'group06', header: { text: '06. 공공하수처리시설' }, items: ['treatCharger', 'treatCttpc', 'treatStatusNm', 'treatCnt'] }, + { name: 'group07', header: { text: '07. 분뇨처리시설' }, items: ['smallCharger', 'smallCttpc', 'smallStatusNm', 'smallCnt'] }, + { name: 'group08', header: { text: '08. 개인하수처리시설' }, items: ['privateCharger', 'privateCttpc', 'privateStatusNm', 'privateCnt'] }, + { name: 'group09', header: { text: '09. 하수도재정' }, items: ['financeCharger', 'financeCttpc', 'financeStatusNm', 'financeCnt'] }, + { name: 'group10', header: { text: '10. 물재이용' }, items: ['reuseCharger', 'reuseCttpc', 'reuseStatusNm', 'reuseCnt'] }, + { name: 'group11', header: { text: '11. 하수및분뇨찌꺼기' }, items: ['sludgeCharger', 'sludgeCttpc', 'sludgeStatusNm', 'sludgeCnt'] }, + { name: 'group12', header: { text: '12. 하수및분뇨관련산업' }, items: ['excretaCharger', 'excretaCttpc', 'excretaStatusNm', 'excretaCnt'] }, + { name: 'group13', header: { text: '13. 하수도서비스수준' }, items: ['complaintCharger', 'complaintCttpc', 'complaintStatusNm', 'complaintCnt'] } + ] +}; + +export const StatsInputStatusInfoList = { + ...StatsInputStatusInfoColumnRaw, + columns: StatsInputStatusInfoColumnRaw.columns.map(col => ({ + ...col, + editable: false + })) +}; \ No newline at end of file diff --git a/apps/st/src/components/util/column/review/WaterReuseRvwColumn.ts b/apps/st/src/components/util/column/review/WaterReuseRvwColumn.ts new file mode 100644 index 000000000..04026197f --- /dev/null +++ b/apps/st/src/components/util/column/review/WaterReuseRvwColumn.ts @@ -0,0 +1,224 @@ +import { ValueType } from "realgrid"; + +// 하수도 통계 관리 10. 물 재이용 +const rawWaterReuseList = [ + { + tabKey: 'a', + tabLabel: '공공하수처리수 재이용', + rowStartNum: 4, + fixedColumns: 2, + columns: [ + /* 1. 기본 및 행정 정보 */ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + + /* 2. 하수처리장 기본 정보 */ + { name: 'BSC_FCT_NM', fieldName: '시설명', header: { text: '시설명' } }, + { name: 'EQP_PRMS_DT', fieldName: '인가일(년/월/일)', header: { text: '인가일\n(년/월/일)' } }, + { name: 'FCT_CPC', fieldName: '시설용량(㎥/일)', header: { text: '시설용량\n(㎥/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'TPUT_TOTAL', fieldName: '연간 하수처리량(천톤/년)', header: { text: '연간\n하수처리량\n(천톤/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RSWTR_LAW_YN', fieldName: '법적의무대상(대상/미대상)', header: { text: '법적의무대상\n(대상/미대상)' } }, + + /* 3. 재이용시설 현황 */ + { name: 'INST_YN', fieldName: '설치유무(유/무)', header: { text: '설치유무\n(유/무)' } }, + { name: 'RSWTR_RN_DT', fieldName: '가동개시일 yyyy-mm-dd', header: { text: '가동개시일\nyyyy-mm-dd' } }, + { name: 'RSWTR_PRMS_DT', fieldName: '설치승인일 yyyy-mm-dd', header: { text: '설치승인일\nyyyy-mm-dd' } }, + { name: 'RSWTR_CPC', fieldName: '용량(톤/일)', header: { text: '용량(톤/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RSWTR_TRT_NM', fieldName: '공법/기자재', header: { text: '공법/기자재' } }, + { name: 'RSWTR_PIPE', fieldName: '공급관로길이(km)', header: { text: '공급관로길이\n(km)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RSWTR_PUMP', fieldName: '공급펌프(톤/일)', header: { text: '공급펌프\n(톤/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 4. 재이용 실적 - 총계 및 장내용수 */ + { name: 'USE_AMNT_TOTAL', fieldName: '총계', header: { text: '총계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_D01', fieldName: '계(장내)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S01', fieldName: '세척수', header: { text: '세척수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S02', fieldName: '냉각수', header: { text: '냉각수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S03', fieldName: '청소수', header: { text: '청소수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S04', fieldName: '조경용수(장내)', header: { text: '조경용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S05', fieldName: '희석용수', header: { text: '희석용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S06', fieldName: '장내중수도', header: { text: '장내중수도' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S07', fieldName: '장내기타용수', header: { text: '장내기타용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 5. 재이용 실적 - 장외용수 */ + { name: 'USE_AMNT_D02', fieldName: '계(장외)', header: { text: '계' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S11', fieldName: '청소·화장실 용수', header: { text: '청소·화장실\n용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S12', fieldName: '세척·살수용수', header: { text: '세척·살수용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S13', fieldName: '조경용수(장외)', header: { text: '조경용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S14', fieldName: '친수용수', header: { text: '친수용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S15', fieldName: '하천등 유지용수', header: { text: '하천등 유지용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S16', fieldName: '농업용수', header: { text: '농업용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S17', fieldName: '지하수충전', header: { text: '지하수충전' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'USE_AMNT_S18', fieldName: '공업용수', header: { text: '공업용수' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + + /* 6. 지표 및 비고 */ + { name: 'REUSE_RT', fieldName: '재이용률(%)', header: { text: '재이용률\n(%)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', + { + name: 'sewagePlantGroup', + header: { text: '하수처리장' }, + items: ['BSC_FCT_NM', 'EQP_PRMS_DT', 'FCT_CPC', 'TPUT_TOTAL', 'RSWTR_LAW_YN'] + }, + { + name: 'reuseFctGroup', + header: { text: '재이용시설' }, + items: [ + 'INST_YN', + { + name: 'installDetailGroup', + header: { text: '재이용시설 설치시' }, + items: [ + 'RSWTR_RN_DT', + 'RSWTR_PRMS_DT', + { + name: 'reProcessGroup', + header: { text: '재처리시설' }, + items: ['RSWTR_CPC', 'RSWTR_TRT_NM'] + }, + 'RSWTR_PIPE', + 'RSWTR_PUMP' + ] + } + ] + }, + { + name: 'reuseStatusGroup', + header: { text: '하수처리수 재이용현황(천톤/년)' }, + items: [ + 'USE_AMNT_TOTAL', + { + name: 'internalUseGroup', + header: { text: '장 내 용 수' }, + items: [ + 'USE_AMNT_D01', 'USE_AMNT_S01', 'USE_AMNT_S02', 'USE_AMNT_S03', + 'USE_AMNT_S04', 'USE_AMNT_S05', 'USE_AMNT_S06', 'USE_AMNT_S07' + ] + }, + { + name: 'externalUseGroup', + header: { text: '장 외 용 수' }, + items: [ + 'USE_AMNT_D02', 'USE_AMNT_S11', 'USE_AMNT_S12', 'USE_AMNT_S13', + 'USE_AMNT_S14', 'USE_AMNT_S15', 'USE_AMNT_S16', 'USE_AMNT_S17', 'USE_AMNT_S18' + ] + } + ] + }, + 'REUSE_RT', + 'RMK' + ] + }, + { + tabKey: 'b', + tabLabel: '중수도 현황', + rowStartNum: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'BILD_NM', fieldName: '건축물명/개발사업명', header: { text: '건축물명/\n개발사업명' } }, + { name: 'ADDR', fieldName: '주소', header: { text: '주소' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'BILD_TP', fieldName: '시설물용도/개발사업종류', header: { text: '시설물용도/\n개발사업종류' } }, + { name: 'LAW_YN', fieldName: '법적의무 대상여부(대상/미대상)', header: { text: '법적의무\n대상여부\n(대상/미대상)' } }, + { name: 'COMP_DT', fieldName: '설치완료일 yyyy-mm-dd', header: { text: '설치완료일\nyyyy-mm-dd' } }, + { name: 'RN_DT', fieldName: '가동개시일 yyyy-mm-dd', header: { text: '가동개시일\nyyyy-mm-dd' } }, + { name: 'TOTAR', fieldName: '건축연면적(㎡)', header: { text: '건축연면적\n(㎡)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'PROC_CPCTY', fieldName: '처리용량(㎥/일)', header: { text: '처리용량\n(㎥/일)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'WATER_USE_CPCTY', fieldName: '물 사용량(㎥/년)', header: { text: '물 사용량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RUSWTR_USE_SM', fieldName: '중수도 이용량(㎥/년)', header: { text: '중수도\n이용량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'SUB_USE_CPCTY', fieldName: '대체수 이용량(㎥/년)', header: { text: '대체수\n이용량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RUSWTR_PRPOS', fieldName: '중수도용도', header: { text: '중수도용도' } }, + { name: 'FYER_OPER_CT', fieldName: '연간운영비(백만원/년)', header: { text: '연간운영비\n(백만원/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'BILD_NM', 'ADDR', 'YR_GBN', 'BILD_TP', 'LAW_YN', 'COMP_DT', 'RN_DT', + { + name: 'fctStatusGroup', + header: { text: '시설현황' }, + items: ['TOTAR', 'PROC_CPCTY'] + }, + 'WATER_USE_CPCTY', 'RUSWTR_USE_SM', 'SUB_USE_CPCTY', 'RUSWTR_PRPOS', 'FYER_OPER_CT', 'RMK' + ] + }, + { + tabKey: 'c', + tabLabel: '빗물이용시설 현황', + rowStartNum: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'RWR_REUSE_FCT_NM', fieldName: '시설명', header: { text: '시설명' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'BILD_TP', fieldName: '건축물용도', header: { text: '건축물용도' } }, + { name: 'ADDR', fieldName: '위치(주소)', header: { text: '위치\n(주소)' } }, + { name: 'LAW_YN', fieldName: '법적의무 대상여부(대상/미대상)', header: { text: '법적의무\n대상여부\n(대상/미대상)' } }, + { name: 'RN_DT', fieldName: '설치완료일 yyyy-mm-dd', header: { text: '설치완료일\nyyyy-mm-dd' } }, + { name: 'INSTL_CT', fieldName: '설치비(백만원)', header: { text: '설치비\n(백만원)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'CCM', fieldName: '집수면 종류', header: { text: '집수면 종류' } }, + { name: 'TRTFC_ENNC', fieldName: '여과등 처리시설 유무', header: { text: '여과등\n처리시설\n유무' } }, + { name: 'SGBS_CPCTY', fieldName: '저류조 용량(㎥)', header: { text: '저류조 용량\n(㎥)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'FYER_USEQTY', fieldName: '연간 이용량(㎥/년)', header: { text: '연간 이용량\n(㎥/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RWR_PRCUSE_PRPPOS', fieldName: '이용용도', header: { text: '이용용도' } }, + { name: 'FYER_OPER_CT', fieldName: '연간운영비(백만원/년)', header: { text: '연간운영비\n(백만원/년)' }, valueType: ValueType.NUMBER, numberFormat: '#,##0.0' }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'RWR_REUSE_FCT_NM', 'YR_GBN', 'BILD_TP', 'ADDR', 'LAW_YN', 'RN_DT', 'INSTL_CT', 'CCM', 'TRTFC_ENNC', 'SGBS_CPCTY', 'FYER_USEQTY', 'RWR_PRCUSE_PRPPOS', 'FYER_OPER_CT', 'RMK' + ] + }, + { + tabKey: 'd', + tabLabel: '하ㆍ폐수처리수 재이용시설 시공업 등록현황', + rowStartNum: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'CMPNM', fieldName: '상호(명칭)', header: { text: '상호(명칭)' } }, + { name: 'RPRSNTV', fieldName: '대표자', header: { text: '대표자' } }, + { name: 'ADDR', fieldName: '주소', header: { text: '주소' } }, + { name: 'CMPN_RGSDE', fieldName: '등록일 yyyy-mm-dd', header: { text: '등록일\nyyyy-mm-dd' } }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } }, + { name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' } }, + { name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' } }, + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', 'CMPNM', 'RPRSNTV', 'ADDR', 'CMPN_RGSDE', 'RMK' + ] + }, + { + tabKey: 'e', + tabLabel: '하ㆍ폐수처리수 재이용시설 시공업 인가현황', + rowStartNum: 2, + columns: [ + { name: 'SIDO', fieldName: '시도', header: { text: '시도' } }, + { name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' } }, + { name: 'YR_GBN', fieldName: '구분', header: { text: '구분' } }, + { name: 'CMPNM', fieldName: '상호(명칭)', header: { text: '상호(명칭)' } }, + { name: 'RPRSNTV', fieldName: '대표자', header: { text: '대표자' } }, + { name: 'ADDR', fieldName: '주소', header: { text: '주소' } }, + { name: 'CMPN_RGSDE', fieldName: '인가일(년/월/일)', header: { text: '인가일\n(년/월/일)' } }, + { name: 'RMK', fieldName: '비고', header: { text: '비고' } } + ], + columnLayout: [ + { name: 'addrGroup', header: { text: '행정구역' }, items: ['SIDO', 'GUGUN'] }, + 'YR_GBN', 'CMPNM', 'RPRSNTV', 'ADDR', 'CMPN_RGSDE', 'RMK' + ] + } +]; + +export const WaterReuseInfoList = rawWaterReuseList.map(tab => ({ + ...tab, + columns: tab.columns.map(col => ({ + ...col, + editable: false + })) +})); \ No newline at end of file diff --git a/apps/st/src/components/util/grid/computedFieldCallbacks.ts b/apps/st/src/components/util/grid/computedFieldCallbacks.ts new file mode 100644 index 000000000..a19b9f7ea --- /dev/null +++ b/apps/st/src/components/util/grid/computedFieldCallbacks.ts @@ -0,0 +1,99 @@ +import type { DataFieldValueCallback, ComputedFieldConfig } from "@/components/type/DataGrid.type"; + +/** 값 → 숫자 변환 (null/undefined/빈문자열 → 0) */ +function toNum(v: unknown): number { + if (v == null || v === "") return 0; + if (typeof v === "number") return isNaN(v) ? 0 : v; + const n = parseFloat(String(v).replace(/,/g, "")); + return isNaN(n) ? 0 : n; +} + +/** 합계용 valueCallback 생성 */ +export function createSumValueCallback(fieldNames: string[]): DataFieldValueCallback { + return (_prod, _dataRow, _fieldName, fieldNamesArr, values) => { + let sum = 0; + for (const f of fieldNames) { + const idx = fieldNamesArr.indexOf(f); + if (idx >= 0) sum += toNum(values[idx]); + } + return sum; + }; +} + +/** 평균용 valueCallback 생성 */ +export function createAvgValueCallback(fieldNames: string[]): DataFieldValueCallback { + return (_prod, _dataRow, _fieldName, fieldNamesArr, values) => { + let sum = 0; + let count = 0; + for (const f of fieldNames) { + const idx = fieldNamesArr.indexOf(f); + if (idx >= 0) { + const val = toNum(values[idx]); + sum += val; + count += 1; + } + } + return count > 0 ? sum / count : 0; + }; +} + +// 공공하수처리구역인구보급률(%), 고도처리인구보급률(%) valueCallback +export function createCoverageRateValueCallback( + numeratorFields: string[], + denominatorFields: string[] +): DataFieldValueCallback { + return (_prod, _dataRow, _fieldName, fieldNamesArr, values) => { + const getSum = (fields: string[]) => { + let sum = 0; + for (const f of fields) { + const idx = fieldNamesArr.indexOf(f); + if (idx >= 0) sum += toNum(values[idx]); + } + return sum; + }; + const total2 = getSum(numeratorFields); + const total1 = getSum(denominatorFields); + return total1 === 0 ? 0 : (total2 / total1) * 100; + }; +} + +// 하수도 설치율(%) valueCallback +export function createSwrgInstlrtRateValueCallback( + numeratorFields: string[], + denominatorFields: string[], + thirdFields: string[], +): DataFieldValueCallback { + return (_prod, _dataRow, _fieldName, fieldNamesArr, values) => { + const getSum = (fields: string[]) => { + let sum = 0; + for (const f of fields) { + const idx = fieldNamesArr.indexOf(f); + if (idx >= 0) sum += toNum(values[idx]); + } + return sum; + }; + const sum1 = getSum(numeratorFields); + const sum2 = getSum(denominatorFields); + + const piplSupprt = toNum(values[fieldNamesArr.indexOf(thirdFields[0] || 'piplSupprt')]); + + const total1 = (sum1 === 0 ? 0 : Math.round(sum2 / sum1 * 100)); + + return total1 * piplSupprt / 100; + }; +} + +/** 연산 타입에 맞는 valueCallback 반환 */ +export function getComputedValueCallback(config: ComputedFieldConfig): DataFieldValueCallback { + switch (config.type) { + case 'sum': + return createSumValueCallback(config.fields); + case 'avg': + return createAvgValueCallback(config.fields); + case 'pblswrgPopltnSuprtRate': + case 'adtrtPopltnSuprtRate': + return createCoverageRateValueCallback(config.numeratorFields, config.denominatorFields); + case 'swrgInstlrtRate': + return createSwrgInstlrtRateValueCallback(config.numeratorFields, config.denominatorFields, config.thirdFields); + } +} diff --git a/apps/st/src/components/util/grid/footerSummary.ts b/apps/st/src/components/util/grid/footerSummary.ts new file mode 100644 index 000000000..0b9bd148b --- /dev/null +++ b/apps/st/src/components/util/grid/footerSummary.ts @@ -0,0 +1,252 @@ +import type { GridView, DataColumn } from "@/components/type/DataGrid.type"; + +// 그리드 푸터 합계 계산 함수 (계산 로직) +export const getFooterSummary = (grid: GridView, column: DataColumn) => { + // 데이터 소스에서 직접 합계 계산 + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + let sum = 0; + + for (let i = 0; i < rowCount; i++) { + const cellValue = dataSource.getValue(i, column.fieldName); + + // 문자열인 경우 숫자로 변환 + const numericValue = typeof cellValue === 'string' + ? Number(String(cellValue).replace(/,/g, '')) + : Number(cellValue); + + if (!isNaN(numericValue) && numericValue !== null && numericValue !== undefined) { + sum += numericValue; + } + } + + return sum; +}; + +// 평균 계산 함수 +export const getFooterAvgSummary = (grid: GridView, column: DataColumn) => { + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + + let sum = 0; + let avg = 0; + + for (let i = 0; i < rowCount; i++) { + const cellValue = dataSource.getValue(i, column.fieldName); + + const numericValue = typeof cellValue === 'string' + ? Number(String(cellValue).replace(/,/g, '')) + : Number(cellValue); + + if (!isNaN(numericValue) && numericValue !== null && numericValue !== undefined) { + sum += numericValue; + } + } + + avg = sum / rowCount; + + return Math.floor(avg * 10) / 10; +} + +// 구분 필드의 고유값들을 찾는 함수 (첫 번째, 두 번째). 기본 필드명 'displayYear' +const getDivisionValues = (grid: GridView, divisionFieldName: string = 'displayYear'): string[] => { + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + const uniqueValues = new Set(); + + for (let i = 0; i < rowCount; i++) { + const divisionValue = dataSource.getValue(i, divisionFieldName); + if (divisionValue !== null && divisionValue !== undefined && divisionValue !== '') { + uniqueValues.add(String(divisionValue)); + } + } + + // Set을 배열로 변환하고 순서 유지 + return Array.from(uniqueValues); +}; + +// 구분 필드 값에 따라 필터링하여 합계 계산하는 함수. 기본 필드명 'displayYear' +// divisionIndex: 0 = 첫 번째 고유값, 1 = 두 번째 고유값 +export const getFooterSummaryByDivision = ( + grid: GridView, + column: DataColumn, + divisionIndex: number, + divisionFieldName: string = 'displayYear' +) => { + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + let sum = 0; + + // "구분" 필드의 고유값 찾기 + const divisionValues = getDivisionValues(grid, divisionFieldName); + if (divisionValues.length <= divisionIndex) { + return 0; // 해당 인덱스의 고유값이 없으면 0 반환 + } + + const targetDivision = divisionValues[divisionIndex]; + + for (let i = 0; i < rowCount; i++) { + // "구분" 필드 값 확인 + const divisionValue = dataSource.getValue(i, divisionFieldName); + if (String(divisionValue) !== targetDivision) { + continue; // 해당 "구분" 값이 아니면 스킵 + } + + const cellValue = dataSource.getValue(i, column.fieldName); + + // 문자열인 경우 숫자로 변환 + const numericValue = typeof cellValue === 'string' + ? Number(String(cellValue).replace(/,/g, '')) + : Number(cellValue); + + if (!isNaN(numericValue) && numericValue !== null && numericValue !== undefined) { + sum += numericValue; + } + } + + return sum; +}; + +// 구분 필드 값에 따라 필터링하여 평균 계산하는 함수. 기본 필드명 'displayYear' +// divisionIndex: 0 = 첫 번째 고유값, 1 = 두 번째 고유값 +export const getFooterAvgSummaryByDivision = ( + grid: GridView, + column: DataColumn, + divisionIndex: number, + divisionFieldName: string = 'displayYear' +) => { + const dataSource = grid.getDataSource(); + const rowCount = dataSource.getRowCount(); + let sum = 0; + let count = 0; + + // "구분" 필드의 고유값 찾기 + const divisionValues = getDivisionValues(grid, divisionFieldName); + if (divisionValues.length <= divisionIndex) { + return 0; // 해당 인덱스의 고유값이 없으면 0 반환 + } + + const targetDivision = divisionValues[divisionIndex]; + + for (let i = 0; i < rowCount; i++) { + // "구분" 필드 값 확인 + const divisionValue = dataSource.getValue(i, divisionFieldName); + if (String(divisionValue) !== targetDivision) { + continue; // 해당 "구분" 값이 아니면 스킵 + } + + const cellValue = dataSource.getValue(i, column.fieldName); + + // 문자열인 경우 숫자로 변환 + const numericValue = typeof cellValue === 'string' + ? Number(String(cellValue).replace(/,/g, '')) + : Number(cellValue); + + if (!isNaN(numericValue) && numericValue !== null && numericValue !== undefined) { + sum += numericValue; + count += 1; + } + } + + if (count === 0) { + return 0; + } + + const avg = sum / count; + return Math.floor(avg * 10) / 10; +}; + +// Footer 설정 객체 생성 함수 +const createSumFooter = (format: string) => ({ + expression: 'sum' as const, + numberFormat: format, + valueCallback: (grid: GridView, column: DataColumn) => { + return getFooterSummary(grid, column); + }, +}); + +const createAvgFooter = (format: string) => ({ + expression: 'avg' as const, + numberFormat: format, + valueCallback: (grid: GridView, column: DataColumn) => { + return getFooterAvgSummary(grid, column); + }, +}); + +// 구분 값에 따라 필터링하는 Footer 배열 생성 함수 (2줄). 기본 필드명 'displayYear' +const createSumFooterArrayByDivision = (format: string, divisionFieldName: string = 'displayYear') => [ + { + numberFormat: format, + valueCallback: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: unknown, + value: number | string | undefined + ) => getFooterSummaryByDivision(grid, column, footerIndex, divisionFieldName), + }, + { + numberFormat: format, + valueCallback: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: unknown, + value: number | string | undefined + ) => getFooterSummaryByDivision(grid, column, footerIndex, divisionFieldName), + }, +]; + +// 구분 값에 따라 필터링하는 평균 Footer 배열 생성 함수 (2줄). 기본 필드명 'displayYear' +const createAvgFooterArrayByDivision = (format: string, divisionFieldName: string = 'displayYear') => [ + { + numberFormat: format, + valueCallback: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: unknown, + value: number | string | undefined + ) => getFooterAvgSummaryByDivision(grid, column, footerIndex, divisionFieldName), + }, + { + numberFormat: format, + valueCallback: ( + grid: GridView, + column: DataColumn, + footerIndex: number, + columnFooter: unknown, + value: number | string | undefined + ) => getFooterAvgSummaryByDivision(grid, column, footerIndex, divisionFieldName), + }, +]; + +// 1. 정수형 : #,##0 +export const footerInt = createSumFooter('#,##0'); + +// 2. 소수점 1자리 : #,##0.0 +export const footerDecimal1 = createSumFooter('#,##0.0'); + +// 3. 소수점 2자리 : #,##0.00 +export const footerDecimal2 = createSumFooter('#,##0.00'); + +// 4. 소수점 3자리 : #,##0.000 +export const footerDecimal3 = createSumFooter('#,##0.000'); + +// "구분" 값에 따라 필터링하는 Footer 배열 (정수형, 2줄) +export const footerIntArrayByDivision = createSumFooterArrayByDivision('#,##0'); + +// "구분" 값에 따라 필터링하는 Footer 배열 (소수점 1자리, 2줄) +export const footerDecimal1ArrayByDivision = createSumFooterArrayByDivision('#,##0.0'); + +// "구분" 값에 따라 필터링하는 Footer 배열 (소수점 2자리, 2줄) +export const footerDecimal2ArrayByDivision = createSumFooterArrayByDivision('#,##0.00'); + +// "구분" 값에 따라 필터링하는 Footer 배열 (소수점 3자리, 2줄) +export const footerDecimal3ArrayByDivision = createSumFooterArrayByDivision('#,##0.000'); + +// 률(%) 평균 값(기본 소수점 1자리) +export const footerAvgDecimal = createAvgFooter('#,##0.0'); + +// "구분" 값에 따라 필터링하는 평균 Footer 배열 (소수점 1자리, 2줄) +export const footerAvgDecimalArrayByDivision = createAvgFooterArrayByDivision('#,##0.0'); \ No newline at end of file diff --git a/apps/st/src/components/util/grid/gridFunction.ts b/apps/st/src/components/util/grid/gridFunction.ts new file mode 100644 index 000000000..28755a7f8 --- /dev/null +++ b/apps/st/src/components/util/grid/gridFunction.ts @@ -0,0 +1,16 @@ +/** + * 객체 배열을 그리드 row 형식으로 변환 (null/undefined → ""). + * 어떤 엔티티 타입이든 공통 사용 가능. + */ +export function toGridRows( + items: T[] +): Record[] { + return items.map((item) => { + const row: Record = {}; + for (const [key, value] of Object.entries(item)) { + row[key] = + value === null || value === undefined ? "" : (value as string | number); + } + return row; + }); +}; \ No newline at end of file diff --git a/apps/st/src/entities/code/@x/posting.ts b/apps/st/src/entities/code/@x/posting.ts new file mode 100644 index 000000000..0525684d9 --- /dev/null +++ b/apps/st/src/entities/code/@x/posting.ts @@ -0,0 +1 @@ +export { CodeSelect } from "../ui/code-select"; diff --git a/apps/st/src/entities/code/api/code-service.ts b/apps/st/src/entities/code/api/code-service.ts new file mode 100644 index 000000000..0d1055f6a --- /dev/null +++ b/apps/st/src/entities/code/api/code-service.ts @@ -0,0 +1,14 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; +import type { CodeService, ICode } from "../model/code-interface"; + +export class CodeApiService implements CodeService { + public async getCode(upCd: string): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.CODE}/${upCd}`, + ); + return response.data; + } +} + +export const CodeApi = new CodeApiService(); diff --git a/apps/st/src/entities/code/api/lwpocode-service.ts b/apps/st/src/entities/code/api/lwpocode-service.ts new file mode 100644 index 000000000..818ddb120 --- /dev/null +++ b/apps/st/src/entities/code/api/lwpocode-service.ts @@ -0,0 +1,73 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; +import { + LwpoCodeFormSchema, + type LwpoCodeService, + type LwpoCodeList, + type LwpoCodeDetail, + type LwpoCodeParams, + type LwpoCodeFormData, +} from "../model/lwpocode-interface"; + +export class LwpoCodeApiService implements LwpoCodeService { + public async getLwpoCodeList(params?: LwpoCodeParams): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.LWPO_CODE}`, + { params }, + ); + return response.data; + } + + public async getUpCodeLwpoCodeList(upCd: string): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/up-cd/${upCd}`, + ); + return response.data; + } + + public async lwpoCodeDetail( + upCd: string, + lwpoCd: string, + ): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`, + ); + return response.data; + } + + public async createLwpoCode(data: LwpoCodeFormData): Promise { + const validatedData = LwpoCodeFormSchema.parse(data); + const response = await client.post( + `${ENDPOINT.CMS_SERVICE.LWPO_CODE}`, + validatedData, + ); + return response.data; + } + + public async updateLwpoCode( + upCd: string, + lwpoCd: string, + data: LwpoCodeFormData, + ): Promise { + const validatedData = LwpoCodeFormSchema.parse(data); + const response = await client.put( + `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`, + validatedData, + ); + return response.data; + } + + public async deleteLwpoCode(upCd: string, lwpoCd: string): Promise { + await client.delete( + `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`, + ); + } + + public async codeRefreshAll(): Promise { + await client.post( + `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/cache/refresh-all`, + ); + } +} + +export const LwpoCodeApi = new LwpoCodeApiService(); diff --git a/apps/st/src/entities/code/api/upcode-service.ts b/apps/st/src/entities/code/api/upcode-service.ts new file mode 100644 index 000000000..dcccd9534 --- /dev/null +++ b/apps/st/src/entities/code/api/upcode-service.ts @@ -0,0 +1,47 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; +import { + upCodeFormSchema, + type UpCodeService, + type UpCodeList, + type UpCodeDetail, + type UpCodeParams, + type UpCodeFormData, +} from "../model/upcode-interface"; + +export class UpCodeApiService implements UpCodeService { + public async getUpCodeList(params?: UpCodeParams): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.UP_CODE}`, + { params }, + ); + return response.data; + } + + public async upCodeDetail(upCd: string): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.UP_CODE}/${upCd}`, + ); + return response.data; + } + + public async createUpCode(data: UpCodeFormData): Promise { + const validatedData = upCodeFormSchema.parse(data); + const response = await client.post( + `${ENDPOINT.CMS_SERVICE.UP_CODE}`, + validatedData, + ); + return response.data; + } + + public async updateUpCode(upCd: string, data: UpCodeFormData): Promise { + const validatedData = upCodeFormSchema.parse(data); + const response = await client.put( + `${ENDPOINT.CMS_SERVICE.UP_CODE}/${upCd}`, + validatedData, + ); + return response.data; + } +} + +export const UpCodeApi = new UpCodeApiService(); diff --git a/apps/st/src/entities/code/index.ts b/apps/st/src/entities/code/index.ts new file mode 100644 index 000000000..e166e2c29 --- /dev/null +++ b/apps/st/src/entities/code/index.ts @@ -0,0 +1,19 @@ +export { CodeApi } from "./api/code-service"; +export type { ICode } from "./model/code-interface"; +export { CodeSelect } from "./ui/code-select"; + +export { UpCodeApi } from "./api/upcode-service"; +export { + upCodeFormSchema, + type UpCode, + type UpCodeFormData, + type UpCodeParams, +} from "./model/upcode-interface"; + +export { LwpoCodeApi } from "./api/lwpocode-service"; +export { + LwpoCodeFormSchema, + type LwpoCode, + type LwpoCodeFormData, + type LwpoCodeParams, +} from "./model/lwpocode-interface"; diff --git a/apps/st/src/entities/code/model/code-interface.ts b/apps/st/src/entities/code/model/code-interface.ts new file mode 100644 index 000000000..4562e2559 --- /dev/null +++ b/apps/st/src/entities/code/model/code-interface.ts @@ -0,0 +1,10 @@ +export interface ICode { + lwpoCd: string; + upCd: string; + lwpoCdNm: string; + unit: string; +} + +export interface CodeService { + getCode(upCd: string): Promise; +} diff --git a/apps/st/src/entities/code/model/lwpocode-interface.ts b/apps/st/src/entities/code/model/lwpocode-interface.ts new file mode 100644 index 000000000..2538c1c30 --- /dev/null +++ b/apps/st/src/entities/code/model/lwpocode-interface.ts @@ -0,0 +1,69 @@ +import { z } from "zod"; +import type { PageableParams, PageableList } from "@/shared/model"; + +export interface LwpoCodeParams extends PageableParams { + upCd?: string; + lwpoCd?: string; + lwpoCdNm?: string; + useYn?: string; +} + +export interface LwpoCode { + lwpoCd: string; + upCd: string; + lwpoCdNm: string; + lwpoCdExpln: string; + unit: string; + prntLwpoCd: string; + useYn: string; + sortSeq: number; + regDt: string; + rgTr: string; + rgTrNm: string; + mdfcnDt: string; + mdFr: string; +} + +export interface LwpoCodeDetail extends LwpoCodeFormData { + lwpoCd: string; + upCd: string; + lwpoCdNm: string; + lwpoCdExpln: string; + unit: string; + prntLwpoCd: string; + useYn: string; + sortSeq: 0; +} + +export const LwpoCodeFormSchema = z.object({ + lwpoCd: z.string().max(10).nonempty(), + upCd: z.string().max(10).nonempty(), + lwpoCdNm: z.string().max(100).nonempty(), + lwpoCdExpln: z.string().max(1000).nullish(), + unit: z.string().max(20).nullish(), + prntLwpoCd: z.string().max(10).nullish(), + useYn: z.string(), + sortSeq: z.number(), + delYn: z.string(), +}); + +export type LwpoCodeFormData = z.infer; +export type LwpoCodeList = PageableList; + +export interface LwpoCodeService { + getLwpoCodeList(params: LwpoCodeParams): Promise; + getUpCodeLwpoCodeList(upCd: string): Promise; + lwpoCodeDetail(upCd: string, lwpoCd: string): Promise; + updateLwpoCode( + upCd: string, + lwpoCd: string, + data: LwpoCodeFormData, + ): Promise; + createLwpoCode(data: LwpoCodeFormData): Promise; + deleteLwpoCode( + upCd: string, + lwpoCd: string, + data: LwpoCodeFormData, + ): Promise; + codeRefreshAll(): Promise; +} diff --git a/apps/st/src/entities/code/model/upcode-interface.ts b/apps/st/src/entities/code/model/upcode-interface.ts new file mode 100644 index 000000000..73bf4f3ae --- /dev/null +++ b/apps/st/src/entities/code/model/upcode-interface.ts @@ -0,0 +1,52 @@ +import { z } from "zod"; +import type { PageableParams, PageableList } from "@/shared/model"; + +export interface UpCodeParams extends PageableParams { + keyword?: string; + upCd?: string; + cdSe?: string; + useYn?: string; + siteId?: string; +} + +export interface UpCode { + upCd: string; + upCdNm: string; + upCdExpln: string; + cdSe: string; + siteId: string; + useYn: string; + regDt: string; +} + +export interface UpCodeDetail extends UpCodeFormData { + upCd: string; + upCdNm: string; + upCdExpln: string; + cdSe: string; + siteId: string; + useYn: string; + delYn: string; + regDt: string; + rgTrNm: string; +} + +export const upCodeFormSchema = z.object({ + upCd: z.string().max(10).nonempty(), + upCdNm: z.string().max(100).nonempty(), + upCdExpln: z.string().max(1000).nullish(), + cdSe: z.string().max(10).nonempty(), + siteId: z.string().max(2).nullish(), + useYn: z.string(), + delYn: z.string(), +}); + +export type UpCodeFormData = z.infer; +export type UpCodeList = PageableList; + +export interface UpCodeService { + getUpCodeList(params: UpCodeParams): Promise; + upCodeDetail(upCodeId: string): Promise; + updateUpCode(upCodeId: string, data: UpCodeFormData): Promise; + createUpCode(data: UpCodeFormData): Promise; +} diff --git a/apps/st/src/entities/code/ui/code-select.tsx b/apps/st/src/entities/code/ui/code-select.tsx new file mode 100644 index 000000000..08df4ce51 --- /dev/null +++ b/apps/st/src/entities/code/ui/code-select.tsx @@ -0,0 +1,47 @@ +import { useQuery } from "@tanstack/react-query"; +import { + cn, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@common/components"; +import { ENDPOINT } from "@/shared/config"; +import { CodeApi } from "../api/code-service"; + +type CodeSelectProps = { + upCd: string; + placeholder?: string; + className?: string; +} & React.ComponentPropsWithoutRef; + +function CodeSelect({ + upCd, + placeholder = "선택", + className, + ...props +}: CodeSelectProps) { + const { data: code } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.CODE, upCd], + queryFn: () => CodeApi.getCode(upCd), + enabled: !!upCd, + }); + + return ( + + ); +} + +export { CodeSelect }; diff --git a/apps/st/src/entities/statistics/api/statistics-input-service.ts b/apps/st/src/entities/statistics/api/statistics-input-service.ts new file mode 100644 index 000000000..f8fdc0850 --- /dev/null +++ b/apps/st/src/entities/statistics/api/statistics-input-service.ts @@ -0,0 +1,43 @@ +import axios from "axios"; +import { ENDPOINT } from "@/shared/config"; + +import { + type StatisticsInputService, + type SewerageSupplyRateRequestParams, + type SewerageSupplyRateApiResponse, + type CheckInputPeriodResponse, + type SewerageSupplyRateSaveRequest, + type SewerageSupplyRateSaveApiResponse, +} from "../model/statistics-input-interface"; + +export class StatisticsInputAPiService implements StatisticsInputService { + public async getSewerageSupplyRateList(params: SewerageSupplyRateRequestParams): Promise { + const response = await axios.get ( + `${ENDPOINT.ST_SERVICE.INPUT}/sewerage-supply-rate`, + { + params: params + } + ); + + return response.data; + } + + public async checkInputPeriod(params: string): Promise { + const response = await axios.get ( + `${ENDPOINT.ST_SERVICE.INPUTCOMMON}/check-input-period?year=${params}`, + ); + + return response.data; + } + + public async saveSewerageSupplyRate(params: SewerageSupplyRateSaveRequest): Promise { + const response = await axios.post ( + `${ENDPOINT.ST_SERVICE.INPUT}/sewerage-supply-rate`, + params + ); + + return response.data; + } +} + +export const statisticsInputAPi = new StatisticsInputAPiService(); \ 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 new file mode 100644 index 000000000..89718aaf0 --- /dev/null +++ b/apps/st/src/entities/statistics/api/statistics-management-service.ts @@ -0,0 +1,99 @@ +import axios from "axios"; +import { ENDPOINT } from "@/shared/config"; + + +import { + type StatsInputStatusReviewApiResponse +} from "../model/statistics-input-review-interface"; +import { + type SewagePipeReviewRegionalApiResponse +} from "../model/statistics-sewage-pipe-review-interface"; +import { + type SewerageSupplyRateReviewRequestParams, + type SewerageSupplyRateReviewApiResponse, +} from "../model/statistics-sewerage-penetration-review-interface"; +import { + type SewagePipeFacilityApiResponse +} from "../model/statistics-sewage-pipe-review-interface"; + +export class StatisticsManagementApiService { + /** + * 00. 통계 입력 현황 목록 조회 + * @param params (yr, bsnmCd, sido, gugun) + */ + public async getStatsInputStatusList( + params: { yr?: string; bsnmCd?: string; sido?: string; gugun?: string } + ): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/input-status`, + { params } + ); + return response.data; + } + + /** + * 입력 기간 확인 (공통) + * @param year 연도 + */ + public async checkInputPeriod(year: string | number): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.INPUTCOMMON}/check-input-period`, + { params: { year } } + ); + return response.data; + } + + /** + * 01. 하수도 보급률 검토 목록 조회 + * @param params (sido, gugun, yr, bsnmCd) + */ + public async getSewerageSupplyRateReviewList( + params: SewerageSupplyRateReviewRequestParams + ): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/supply-rate`, + { params } + ); + return response.data; + } + + /** + * 02. 하수관로 지역별 시설현황 목록 조회 (Tab1) + * @param params (sido, gugun, yr, bsnmCd) + */ + public async getSewagePipeReviewRegionalList( + params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + } + ): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe/regional-status`, + { params } + ); + return response.data; + } + /** + * 02. 하수관로 시설별 설치현황 목록 조회 (Tab2) + * @param params (sido, gugun, yr, bsnmCd) + */ + public async getSewagePipeFacilityList( + params: { + yr?: string; + bsnmCd?: string; + sido?: string; + gugun?: string; + } + ): Promise { + const response = await axios.get( + `${ENDPOINT.ST_SERVICE.REVIEW}/sewer-pipe/facility-status`, + { params } + ); + return response.data; + } +} + +// 통합 인스턴스 수출 +export const statisticsManagementApi = new StatisticsManagementApiService(); \ No newline at end of file diff --git a/apps/st/src/entities/statistics/api/statistics-service.ts b/apps/st/src/entities/statistics/api/statistics-service.ts index dfec7d694..8455e68c5 100644 --- a/apps/st/src/entities/statistics/api/statistics-service.ts +++ b/apps/st/src/entities/statistics/api/statistics-service.ts @@ -3,16 +3,16 @@ import { ENDPOINT } from "@/shared/config"; import { type StatisticsService, - type Sido, + type SearchCondition, type ApiResponse, type Sgg } from "../model/statistics-interface"; export class StatisticsAPiService implements StatisticsService { - public async getSidoList(): Promise> { - const response = await axios.get>( - `${ENDPOINT.ST_SERVICE.COMMON}/sido`, + public async getSidoList(): Promise> { + const response = await axios.get>( + `${ENDPOINT.ST_SERVICE.COMMON}/search-condition`, ); return response.data; diff --git a/apps/st/src/entities/statistics/api/verification-target-management-service.ts b/apps/st/src/entities/statistics/api/verification-target-management-service.ts new file mode 100644 index 000000000..5bbcd714c --- /dev/null +++ b/apps/st/src/entities/statistics/api/verification-target-management-service.ts @@ -0,0 +1,95 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; + +import type { + VerificationTargetManagementService, + VerificationTargetManagementSearchParams, + VerificationTargetManagementListApiResponse, + VerificationTargetManagementDetailApiResponse, + VerificationTargetManagementSaveRequest, + VerificationTargetManagementSaveApiResponse, + VerificationTargetManagementUpdateRequest, + VerificationTargetManagementUpdateApiResponse, + VerificationTargetManagementDeleteApiResponse, +} from "../model/verification-target-management-interface"; + +export class VerificationTargetManagementApiService implements VerificationTargetManagementService { + /** + * 검증 대상 목록 조회 + * @param params 검색 조건 (vrfcMthdCd, statsCd, tblNm, colNm, vrfcTrgtNm, useYn, page, size, sort) + */ + public async getVerificationTargetManagementList( + params: VerificationTargetManagementSearchParams, + ): Promise { + const response = + await client.get( + `${ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG}`, + { params }, + ); + return response.data; + } + + /** + * 검증 대상 상세 조회 + * @param vrfcTrgtSn 검증 대상 일련번호 + */ + public async getVerificationTargetManagementById( + vrfcTrgtSn: number, + ): Promise { + const response = + await client.get( + `${ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG}/${vrfcTrgtSn}`, + ); + return response.data; + } + + /** + * 검증 대상 등록 + * @param request 등록 요청 데이터 + */ + public async saveVerificationTargetManagement( + request: VerificationTargetManagementSaveRequest, + ): Promise { + const response = + await client.post( + `${ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG}`, + request, + ); + return response.data; + } + + /** + * 검증 대상 수정 + * @param vrfcTrgtSn 검증 대상 일련번호 + * @param request 수정 요청 데이터 + */ + public async updateVerificationTargetManagement( + vrfcTrgtSn: number, + request: VerificationTargetManagementUpdateRequest, + ): Promise { + const response = + await client.put( + `${ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG}/${vrfcTrgtSn}`, + request, + ); + return response.data; + } + + /** + * 검증 대상 삭제 + * @param vrfcTrgtSn 검증 대상 일련번호 + */ + public async deleteVerificationTargetManagement( + vrfcTrgtSn: number, + ): Promise { + const response = + await client.delete( + `${ENDPOINT.STATVERIFY_SERVICE.VRFCTGT_MNG}/${vrfcTrgtSn}`, + ); + return response.data; + } +} + +// 통합 인스턴스 수출 +export const verificationTargetManagementApi = + new VerificationTargetManagementApiService(); diff --git a/apps/st/src/entities/statistics/model/statistics-input-interface.ts b/apps/st/src/entities/statistics/model/statistics-input-interface.ts new file mode 100644 index 000000000..3fd0ba0c8 --- /dev/null +++ b/apps/st/src/entities/statistics/model/statistics-input-interface.ts @@ -0,0 +1,198 @@ +import type { ApiResponse } from "./statistics-interface"; + +// 하수도 보급률 데이터 항목 +export interface SewerageSupplyRateStatusInfo { + locgStatus: string; + locgDt: string; + locgCharger: string; + locgCttpc: string; + prvnStatus: string; + dcsnStatus: string; + wrterOpinionSm: string | null; + chckerOpinionSm: string | null; + returnOpinionSm: string | null; +} + +export interface SewerageSupplyRateCommonInfo { + bsnmArea: number; + bsnmCd: string; + bsnmFrgnrPoplSm: number; + bsnmPoplSm: number; + bsnmTotalPopl: number; + piplFcltyExtn: number; + piplPlanExtn: number; + piplSupprt: number; + sido: string; + yr: string; +} + +/** 검증 결과 한 건 (필드별 메시지) */ +export interface VerificationResultItem { + type: string; + rsn: string; +} + +/** 필드명 → 검증 결과 배열. 예: { popltnSm: [{ type, rsn }], wstrPrmTrt: [...] } */ +export type SewerageSupplyRateVerificationResult = Record; + +export interface SewerageSupplyRateItem { + sido: string; + gugun: string; + adstDong: string; + rgnNm: string; + adstCd: string; + yr: string; + bsnmCd: string; + rvbsn: string; + lgbsn: string; + mdbsn: string; + mdmbsn: string; + totalPopl: number; + poplSm: number; + frgnrPoplSm: number; + area: number; + bsnmTotalPopl: number; + bsnmPoplSm: number; + bsnmFrgnrPoplSm: number; + bsnmArea: number; + piplPlanExtn: number; + piplFcltyExtn: number; + piplSupprt: number; + wrssm: string | null; + bstrm: string; + speclCntrplnAr: string | null; + popltnSm: number; + arSm: number; + swgeProcZoneInnerSm: number; + pblswrgPopltnSm: number; + pblswrgPrmTrt: number; + pblswrgScdTrt: number; + pblswrgTertTrt: number; + wstrPopltnSm: number; + wstrPrmTrt: number; + wstrScdTrt: number; + wstrTertTrt: number; + swgeProcZoneInnerAr: number; + swgeProcZoneOuterSm: number; + townUnprocPopltn: number; + townSwttPopltn: number; + townWrrtnPopltn: number; + uptownUnprPopltn: number; + uptownSwttPopltn: number; + uptownWrrtnPopltn: number; + swgeProcZoneOuterAr: number; + pblswrgPopltnSuprt: number; + adtrtPopltnSuprt: number; + swrgInstlrt: number; + wrterOpinion: string | null; + chckerOpinion: string | null; + notConectPopltn: number; + rmk: string; + chkWrssm: string; + chkBstrm: string; + chkSpeclCntrplnAr: string; + chkPopltnSm: string; + chkArSm: string; + chkSwgeProcZoneInnerSm: string; + chkPblswrgPopltnSm: string; + chkPblswrgPrmTrt: string; + chkPblswrgScdTrt: string; + chkPblswrgTertTrt: string; + chkWstrPopltnSm: string; + chkWstrPrmTrt: string; + chkWstrScdTrt: string; + chkWstrTertTrt: string; + chkSwgeProcZoneInnerAr: string; + chkSwgeProcZoneOuterSm: string; + chkTownUnprocPopltn: string; + chkTownSwttPopltn: string; + chkTownWrrtnPopltn: string; + chkUptownUnprPopltn: string; + chkUptownSwttPopltn: string; + chkUptownWrrtnPopltn: string; + chkSwgeProcZoneOuterAr: string; + chkPblswrgPopltnSuprt: string; + chkAdtrtPopltnSuprt: string; + chkSwrgInstlrt: string; + chkNotConectPopltn: string; + verificationResult?: SewerageSupplyRateVerificationResult; +} + +export interface SewerageSupplyRateResponseData { + statusInfo: SewerageSupplyRateStatusInfo; + sewerageSupplyRateList: SewerageSupplyRateItem[]; + commonInfo: SewerageSupplyRateCommonInfo; +} + +export type SewerageSupplyRateApiResponse = ApiResponse & { + message: string; +} + +export interface SewerageSupplyRateRequestParams { + sido?: string; + gugun?: string; + bsnmCd?: string; + yr?: string; + mode?: string; +} + +/** 하수도 보급률 저장 API 요청 body (한 행) */ +export interface SewerageSupplyRateSaveItem { + gugun: string | null; + adstCd: string; + adstDong: string; + bstrm: string; + speclCntrplnAr: string | null; + pblswrgPrmTrt: number; + pblswrgScdTrt: number; + pblswrgTertTrt: number; + wstrPrmTrt: number; + wstrScdTrt: number; + wstrTertTrt: number; + notConectPopltn: number; + swgeProcZoneInnerAr: number; + townUnprocPopltn: number; + townSwttPopltn: number; + townWrrtnPopltn: number; + swgeProcZoneOuterAr: number; + rmk: string; + popltnSm: number; + arSm: number; + swgeProcZoneInnerSm: number; + pblswrgPopltnSm: number; + wstrPopltnSm: number; + swgeProcZoneOuterSm: number; + pblswrgPopltnSuprt: number; + adtrtPopltnSuprt: number; + swrgInstlrt: number; +} + +export interface SewerageSupplyRateSaveRequest { + yr: string; + sido: string; + bsnmCd: string; + userId: string; + saveList: SewerageSupplyRateSaveItem[]; +} + +export interface SewerageSupplyRateSaveData { + hasMismatch?: boolean; + mismatchIdList?: string[]; + httpStatus?: number; + code?: string; +} + +export type SewerageSupplyRateSaveApiResponse = ApiResponse; + +// 하수도 통계 입력 기간 조회 +export interface CheckInputPeriodResponse { + status: string; + message: string; + data: boolean; +} + +export interface StatisticsInputService { + getSewerageSupplyRateList(params: SewerageSupplyRateRequestParams): Promise; + checkInputPeriod(params: string): Promise; + saveSewerageSupplyRate(params: SewerageSupplyRateSaveRequest): Promise; +} \ No newline at end of file diff --git a/apps/st/src/entities/statistics/model/statistics-input-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-input-review-interface.ts new file mode 100644 index 000000000..93f1a4651 --- /dev/null +++ b/apps/st/src/entities/statistics/model/statistics-input-review-interface.ts @@ -0,0 +1,112 @@ +import type { ApiResponse } from "./statistics-interface"; + +/** + * 검토-00.통계 입력현황 아이템 인터페이스 + */ +export interface StatsInputStatusReviewItem { + chk: string; + sido: string; + gugun: string; + yr: string; + bsnmCd: string; + status: string; + + // 01. 하수도보급율 (supply) + supplyCharger: string; + supplyCttpc: string; + supplyStatusNm: string; + supplyStatus: string; + supplyCnt: number; + + // 02. 하수관로 (facility - 기존 3번) + facilityCharger: string; + facilityCttpc: string; + facilityStatusNm: string; + facilityStatus: string; + facilityCnt: number; + + // 03. 하수관로유지관리 (pipe - 기존 4번) + pipeCharger: string; + pipeCttpc: string; + pipeStatusNm: string; + pipeCnt: number; + + // 04. 하수저류시설 (storage - 기존 5번) + storageCharger: string; + storageCttpc: string; + storageStatusNm: string; + storageCnt: number; + + // 05. 펌프장 (pump - 기존 6번) + pumpCharger: string; + pumpCttpc: string; + pumpStatusNm: string; + pumpCnt: number; + + // 06. 공공하수처리시설 (treat - 기존 7번) + treatCharger: string; + treatCttpc: string; + treatStatusNm: string; + treatCnt: number; + + // 07. 분뇨처리시설 (small - 기존 8번) + smallCharger: string; + smallCttpc: string; + smallStatusNm: string; + smallCnt: number; + + // 08. 개인하수처리시설 (private - 기존 9번) + privateCharger: string; + privateCttpc: string; + privateStatusNm: string; + privateCnt: number; + + // 09. 하수도재정 (finance - 기존 10번) + financeCharger: string; + financeCttpc: string; + financeStatusNm: string; + financeCnt: number; + + // 10. 물재이용 (reuse - 기존 11번) + reuseCharger: string; + reuseCttpc: string; + reuseStatusNm: string; + reuseCnt: number; + + // 11. 하수및분뇨찌꺼기 (sludge - 기존 12번) + sludgeCharger: string; + sludgeCttpc: string; + sludgeStatusNm: string; + sludgeCnt: number; + + // 12. 하수및분뇨관련산업 (excreta - 기존 13번) + excretaCharger: string; + excretaCttpc: string; + excretaStatusNm: string; + excretaCnt: number; + + // 13. 하수도서비스수준 (complaint - 기존 15번) + complaintCharger: string; + complaintCttpc: string; + complaintStatusNm: string; + complaintCnt: number; +} + +export interface StatsInputStatusReviewResponseData { + sewerageSupplyRateList: StatsInputStatusReviewItem[]; +} + + +export type StatsInputStatusReviewApiResponse = ApiResponse & { + message: string; +}; + + +export interface StatsInputStatusReviewService { + getStatsInputStatusList(params: { + yr?: String; + bsnmCd?: string; + sido?: string; + gugun?: string; + }): 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 d687df5c2..b909eba92 100644 --- a/apps/st/src/entities/statistics/model/statistics-interface.ts +++ b/apps/st/src/entities/statistics/model/statistics-interface.ts @@ -1,19 +1,27 @@ export interface Sido { adstDstrCd: string; sido: string; + bsnmCd: string; +} + +export interface SearchCondition { + yearList: string[]; + sidoList: Sido[]; } export interface Sgg { adstDstrCd: string; gugun: string; + bsnmCd: string; } export interface ApiResponse { status: string; data: T; + message?: string; } export interface StatisticsService { - getSidoList(): Promise>; + getSidoList(): Promise>; getSggList(sidoName: string): 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 new file mode 100644 index 000000000..0d82096ad --- /dev/null +++ b/apps/st/src/entities/statistics/model/statistics-sewage-pipe-review-interface.ts @@ -0,0 +1,152 @@ +import type { ApiResponse } from "./statistics-interface"; + +/** + * 02. 하수관로 tab1.지역별 시설현황 아이템 인터페이스 (Tab1) + */ +export interface SewagePipeReviewrRegionalItem { + // 기본 정보 및 행 제어 + sido: string; // 시도 + gugun: string; // 시군구 + adstDong: string; // 행정구역명 + adstCd: string; // 행정코드 + yr: string; // 연도 + rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 + displayYear: string; // 구분 표시용 (2024년확정 등) + + // 하수정비 기본계획 + targetYr: number; // 하수정보기본계획목표년도 + piplImprmnPlanExtn: number; // 총관로정비 계획연장(m) + piplPlanExtn: number; // 총계획연장(m) + piplFcltyExtn: number; // 총시설연장(m) + piplSupprt: number; // 하수관로 보급률(%) + + // 합류식 (CMBN) + cmbnPlanAr: number; // 관로정비 계획면적(㎢) + cmbnImprmnPlanExtn: number; // 관로정비 계획연장(m) + cmbnPlanExtn: number; // 계획연장(m) + cmbnFcltyExtn: number; // 시설연장(m) + cmbnRctglExtn: number; // 사각형(m) + cmbnCicleExtn: number; // 원형(m) + cmbnOpswrExtn: number; // 개거(m) + cmbnSdgttrExtn: number; // 측구(m) + + // 분류식 - 오수관로 (PLTWTR) + pltwtrPlanAr: number; // 관로정비 계획면적(㎢) + pltwtrImprmnPlanExtn: number; // 관로정비 계획연장(m) + pltwtrPlanExtn: number; // 계획연장(m) + pltwtrFlctyExtn: number; // 시설연장(m) + pltwtrSqreExtn: number; // 사각형(m) + pltwtrCiclExtn: number; // 원형(m) + + // 분류식 - 우수관로 (RAINWTR) + rainwtrPlanAr: number; // 관로정비 계획면적(㎢) + rainwtrImprmnPlanExtn: number; // 관로정비 계획연장(m) + rainwtrPlanExtn: number; // 계획연장(m) + rainwtrFlctyExtn: number; // 시설연장(m) + rainwtrSqreExtn: number; // 사각형(m) + rainwtrCiclExtn: number; // 원형(m) + rainwtrOpswrExtn: number; // 개거(m) + rainwtrSdgttrExtn: number; // 측구(m) + + // 부속시설 (개소) + mnhleSite: number; // 합류식맨홀 + pltwtrMnhleSite: number; // 오수맨홀 + rainwtrMnhleSite: number; // 우수맨홀 + pltwtrRcvrSite: number; // 오수받이 + rainwtrRcvrSite: number; // 빗물받이 + soilspllSite: number; // 우수토실 + soilholeSite: number; // 우수토구 + + // 대장 및 기타 + sewerRegstrCmptExtn: number; // 하수도대장 전산화연장(m) + sewerRegstrCmptRt: number; // 하수도대장 전산화율(%) + rmk: string; // 비고 +} + +export interface SewagePipeReviewResponseData { + sewagePipeList: SewagePipeReviewrRegionalItem[]; +} + + +export type SewagePipeReviewRegionalApiResponse = ApiResponse & { + message: string; +}; + +export interface SewagePipeReviewService { + + getSewagePipeReviewList(params: { + yr?: string; // 조회 연도 + bsnmCd?: string; // 사업장 코드 + sido?: string; // 시도 + gugun?: string; // 구군 + }): Promise; +} + + +export interface SewagePipeReviewFacilityItem { + // 1. 행정구역 및 기본 정보 + sido: string; // 시도 + gugun: string; // 시군구 + adstCd: string; // 행정코드 + adstDong: string; // 행정구역명 + yr: string; // 연도 + rowType: 'OLD' | 'CURR'; // 전년도/당해년도 구분 + displayYear: string; // 구분 표시용 (2024년확정 등) + + // 2. 시설 정보 + bscFctNm: string; // 하수처리장명 + fctCpc: number; // 하수처리시설용량(㎥/일) + + // 3. 처리구역면적(㎢) + procZoneSm: number; // 합계(면적) + cmbnProcZoneAr: number; // 합류식(면적) + sprtProcZoneAr: number; // 분류식(면적) + sepRate: number; // 분류식화 (%) + + // 4. 배수설비(개소) + drngEqpSm: number; // 합계(배수) + cmbnDrngEqp: number; // 합류식(배수) + sprtDrngEqpSm: number; // 합계(분류배수) + sprtDrngEqpCnnc: number; // 연결 + sprtDrngEqpDcnnc: number; // 미연결 + + // 5. 하수관로 (m) + piplFcltyExtn: number; // 총 시설연장(m) + icgMnnSm: number; // 합계(차집/오수간선) + icgExtn: number; // 차집 + mnnExtn: number; // 오수간선 + + // 6. 토실/토구 (개소) + cmbnSoilholeSite: number; // 우수토실(합류) + sprtSoilholeSite: number; // 우수토실(분류) + sprtSoilspllSite: number; // 우수토구(분류) + + // 7. 지선 (m) + brnchlnSm: number; // 합계(지선) + cmbnBrnchlnExtn: number; // 합류식(지선) + rainwtrBrnchlnExtn: number; // 우수(지선) + pltwtrBrnchlnExtn: number; // 오수(지선) + + // 비고 + rmk: string; // 비고 +} + + +export interface SewagePipeFacilityResponseData { + facilityPipeList: SewagePipeReviewFacilityItem[]; +} + +export type SewagePipeFacilityApiResponse = ApiResponse & { + message: string; +}; + + +export interface SewagePipeFacilityService { + + getSewagePipeFacilityList(params: { + yr?: string; // 조회 연도 + bsnmCd?: string; // 사업장 코드 + sido?: string; // 시도 + gugun?: string; // 구군 + }): Promise; +} \ No newline at end of file diff --git a/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts b/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts new file mode 100644 index 000000000..8fbf7ea1f --- /dev/null +++ b/apps/st/src/entities/statistics/model/statistics-sewerage-penetration-review-interface.ts @@ -0,0 +1,88 @@ +import type { ApiResponse } from "./statistics-interface"; + +// 검토 01.하수도 보급률 데이터 항목 +export interface SewerageSupplyRateReviewItem { + + sido: string; + gugun: string; + adstDong: string; + displayYear: string; + rowType: 'OLD' | 'CURR'; + adstCd: string; + bsnmCd: string; + yr: number; + + /* ====================================================================== + * 수계 및 지역 정보 + * ====================================================================== */ + rvbsn: string; + lgbsn: string; + mdbsn: string; + mdmbsn: string; + wrssm: string | null; + bstrm: string; + speclCntrplnAr: string | null; + + /* ====================================================================== + * 인구 및 면적 데이터 (공통 필드명) + * ====================================================================== */ + popltnSm: number; // 총인구 + arSm: number; // 총면적(㎢) + + /* 하수처리구역내 (groupD) */ + swgeProcZoneInnerSm: number; // 계 + pblswrgPopltnSm: number; // 공공하수처리인구-합계 + pblswrgPrmTrt: number; // 1차처리 + pblswrgScdTrt: number; // 2차처리 + pblswrgTertTrt: number; // 3차처리 + + wstrPopltnSm: number; // 폐수처리인구-합계 + wstrPrmTrt: number; // 1차처리 + wstrScdTrt: number; // 2차처리 + wstrTertTrt: number; // 3차처리 + + notConectPopltn: number; // 미접속인구 + swgeProcZoneInnerAr: number; // 면적(㎢) + + /* 하수처리구역외 (groupE) */ + swgeProcZoneOuterSm: number; // 계 + townUnprocPopltn: number; // 미처리인구 (Town + Uptown 합산값) + townSwttPopltn: number; // 오수처리인구 (Town + Uptown 합산값) + townWrrtnPopltn: number; // 정화조인구 (Town + Uptown 합산값) + swgeProcZoneOuterAr: number; // 면적(㎢) + + /* ====================================================================== + * 보급률 및 기타 + * ====================================================================== */ + pblswrgPopltnSuprt: number; // 공공하수보급률(%) + adtrtPopltnSuprt: number; // 고도처리보급률(%) + swrgInstlrt: number; // 하수도설치율(%) + rmk: string | null; // 비고 + + /* ====================================================================== + * Flag (필요 시 유지) + * ====================================================================== */ + lcnt: number | null; + ocnt: number | null; + +} + +export interface SewerageSupplyRateReviewResponseData { + sewerageSupplyRateList: SewerageSupplyRateReviewItem[]; +} + +export type SewerageSupplyRateReviewApiResponse = ApiResponse & { + message: string; +}; + + +export interface SewerageSupplyRateReviewRequestParams { + sido?: string; + gugun?: string; + yr?: string; + bsnmCd?: string; +} + +export interface SewerageSupplyRateReviewService { + getSewerageSupplyRateReviewList(params: SewerageSupplyRateReviewRequestParams): Promise; +} \ No newline at end of file diff --git a/apps/st/src/entities/statistics/model/verification-article-column.ts b/apps/st/src/entities/statistics/model/verification-article-column.ts new file mode 100644 index 000000000..c62156730 --- /dev/null +++ b/apps/st/src/entities/statistics/model/verification-article-column.ts @@ -0,0 +1,197 @@ +import { ValueType } from "realgrid"; +import type { ColumnInfo } from "@rsone/components"; + +export const hbArticleColumnInfo: ColumnInfo = { + columns: [ + { + name: "statsNm", + fieldName: "statsNm", + header: { text: "통계항목" }, + editable: false, + sortdisable: false, + }, + { + name: "vrfcTrgtNm", + fieldName: "vrfcTrgtNm", + header: { text: "검증명" }, + editable: false, + sortdisable: false, + }, + { + name: "tblNm", + fieldName: "tblNm", + header: { text: "테이블명" }, + editable: false, + sortdisable: false, + }, + { + name: "colNm", + fieldName: "colNm", + header: { text: "컬럼명" }, + editable: false, + sortdisable: false, + }, + { + name: "pctlCrtrVl", + fieldName: "pctlCrtrVl", + header: { text: "Percentile" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0.##", + }, + { + name: "scopCntCntVl", + fieldName: "scopCntCntVl", + header: { text: "A" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0.###", + }, + { + name: "thrsCntVl", + fieldName: "thrsCntVl", + header: { text: "C" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0.###", + }, + { + name: "rgtrNm", + fieldName: "rgtrNm", + header: { text: "등록자" }, + editable: false, + sortdisable: false, + }, + { + name: "regDt", + fieldName: "regDt", + header: { text: "등록일시" }, + editable: false, + sortdisable: false, + }, + ], + columnLayout: [ + "statsNm", + "vrfcTrgtNm", + "tblNm", + "colNm", + "pctlCrtrVl", + "scopCntCntVl", + "thrsCntVl", + "rgtrNm", + "regDt", + ], +}; + +export const imrArticleColumnInfo: ColumnInfo = { + columns: [ + { + name: "statsNm", + fieldName: "statsNm", + header: { text: "통계항목" }, + editable: false, + sortdisable: false, + }, + { + name: "vrfcTrgtNm", + fieldName: "vrfcTrgtNm", + header: { text: "검증명" }, + editable: false, + sortdisable: false, + }, + { + name: "tblNm", + fieldName: "tblNm", + header: { text: "테이블명" }, + editable: false, + sortdisable: false, + }, + { + name: "colNm", + fieldName: "colNm", + header: { text: "컬럼명" }, + editable: false, + sortdisable: false, + }, + { + name: "rgtrNm", + fieldName: "rgtrNm", + header: { text: "등록자" }, + editable: false, + sortdisable: false, + }, + { + name: "regDt", + fieldName: "regDt", + header: { text: "등록일시" }, + editable: false, + sortdisable: false, + }, + ], + columnLayout: [ + "statsNm", + "vrfcTrgtNm", + "tblNm", + "colNm", + "rgtrNm", + "regDt", + ], +}; + +export const validationArticleColumnInfo: ColumnInfo = { + columns: [ + { + name: "statsNm", + fieldName: "statsNm", + header: { text: "통계항목" }, + editable: false, + sortdisable: false, + }, + { + name: "vrfcTrgtNm", + fieldName: "vrfcTrgtNm", + header: { text: "검증명" }, + editable: false, + sortdisable: false, + }, + { + name: "tblNm", + fieldName: "tblNm", + header: { text: "테이블명" }, + editable: false, + sortdisable: false, + }, + { + name: "colNm", + fieldName: "colNm", + header: { text: "컬럼명" }, + editable: false, + sortdisable: false, + }, + { + name: "rgtrNm", + fieldName: "rgtrNm", + header: { text: "등록자" }, + editable: false, + sortdisable: false, + }, + { + name: "regDt", + fieldName: "regDt", + header: { text: "등록일시" }, + editable: false, + sortdisable: false, + }, + ], + columnLayout: [ + "statsNm", + "vrfcTrgtNm", + "tblNm", + "colNm", + "rgtrNm", + "regDt", + ], +}; diff --git a/apps/st/src/entities/statistics/model/verification-article-interface.ts b/apps/st/src/entities/statistics/model/verification-article-interface.ts new file mode 100644 index 000000000..98b2d5274 --- /dev/null +++ b/apps/st/src/entities/statistics/model/verification-article-interface.ts @@ -0,0 +1,57 @@ +/** H-B 탭 검증 항목 */ +export interface HBArticleItem { + /** 통계 항목명 */ + statsItmNm: string; + /** 검증 항목명 */ + vrfcItmNm: string; + /** 테이블명 */ + tblNm: string; + /** 컬럼명 */ + colNm: string; + /** Percentile 값 */ + percentileVal: number; + /** A 값 */ + aVal: number; + /** C 값 */ + cVal: number; + /** 등록자명 */ + regNm: string; + /** 등록 일시 */ + regDt: string; +} + +/** I-MR 탭 검증 항목 */ +export interface IMRArticleItem { + /** 통계 항목명 */ + statsItmNm: string; + /** 검증명 */ + vrfcNm: string; + /** 테이블명 */ + tblNm: string; + /** 컬럼명 */ + colNm: string; + /** 등록자명 */ + regNm: string; + /** 등록 일시 */ + regDt: string; +} + +/** Validation 탭 검증 항목 */ +export interface ValidationArticleItem { + /** 순번 */ + no: string; + /** 통계항목명 */ + statsItmNm: string; + /** 검증명 */ + vrfcNm: string; + /** 테이블명 */ + tblNm: string; + /** 컬럼명 */ + colNm: string; + /** 비교 테이블명 */ + cmpTblNm: string; + /** 비교 컬럼명 */ + cmpColNm: string; + /** 기본규칙 */ + bscRul: string; +} diff --git a/apps/st/src/entities/statistics/model/verification-article-mock.ts b/apps/st/src/entities/statistics/model/verification-article-mock.ts new file mode 100644 index 000000000..272efeb16 --- /dev/null +++ b/apps/st/src/entities/statistics/model/verification-article-mock.ts @@ -0,0 +1,150 @@ +import { fakerKO as faker } from "@faker-js/faker"; +import type { + HBArticleItem, + IMRArticleItem, + ValidationArticleItem, +} from "./verification-article-interface"; + +const HB_STATS_ITEMS = [ + "하수도 보급률", + "하수관로", + "하수처리시설 및 방류량보고", + "펌프장", + "공공하수처리시설", + "분뇨처리시설", + "개인하수처리시설", + "하수도재정", + "물 재이용", +]; + +const HB_VERIFICATION_ITEMS = [ + "행정구역 보급률", + "유역환경청별 보급률", + "관로연장", + "처리용량", + "방류량", + "펌프용량", +]; + +const IMR_STATS_ITEMS = [ + "하수도 보급률", + "하수관로", + "하수처리시설 및 방류량보고", + "펌프장", + "공공하수처리시설", + "분뇨처리시설", + "개인하수처리시설", + "하수도재정", + "물 재이용", +]; + +const VALIDATION_STATS_ITEMS = [ + "하수관로 유지관리", + "하수저류시설 및 빗물펌프장", + "공공하수처리시설", + "분뇨처리시설", + "개인하수처리시설", + "하수도재정", +]; + +const VERIFICATION_NAMES = [ + "제정별 사업비", + "관로길이", + "공란검증", + "범위검증", + "논리검증", + "유지보수", +]; + +const TABLE_NAMES = [ + "tb_stats_drng_sys", + "tb_stats_ppline", + "tb_stats_fclt", + "tb_stats_pump_stt", + "tb_stats_sewg_trtm", +]; + +const COLUMN_NAMES = [ + "drng_sys_rate", + "ppline_len", + "fclt_cpct", + "pump_cpct", + "trtm_qty", + "popl_cnt", +]; + +const BASIC_RULES = [ + "값 > 0", + "값 >= 0", + "값 != NULL", + "범위: 0-100", + "A > B", +]; + +function formatDateTime(date: Date): string { + const y = date.getFullYear(); + const m = String(date.getMonth() + 1).padStart(2, "0"); + const d = String(date.getDate()).padStart(2, "0"); + const h = String(date.getHours()).padStart(2, "0"); + const min = String(date.getMinutes()).padStart(2, "0"); + return `${y}-${m}-${d} ${h}:${min}`; +} + +/** H-B 탭 목데이터 생성 */ +export function createHBArticleMock(count = 10): HBArticleItem[] { + faker.seed(100); + return Array.from({ length: count }, (_, index) => ({ + statsItmNm: faker.helpers.arrayElement(HB_STATS_ITEMS), + vrfcItmNm: faker.helpers.arrayElement(HB_VERIFICATION_ITEMS), + tblNm: faker.helpers.arrayElement(TABLE_NAMES), + colNm: faker.helpers.arrayElement(COLUMN_NAMES), + percentileVal: faker.number.float({ + min: 0, + max: 100, + fractionDigits: 2, + }), + aVal: faker.number.float({ min: 0, max: 10, fractionDigits: 3 }), + cVal: faker.number.float({ min: 0, max: 10, fractionDigits: 3 }), + regNm: faker.person.fullName(), + regDt: formatDateTime(faker.date.recent({ days: 90 })), + })); +} + +/** I-MR 탭 목데이터 생성 */ +export function createIMRArticleMock(count = 10): IMRArticleItem[] { + faker.seed(200); + return Array.from({ length: count }, (_, index) => ({ + statsItmNm: faker.helpers.arrayElement(IMR_STATS_ITEMS), + vrfcNm: faker.helpers.arrayElement(VERIFICATION_NAMES), + tblNm: faker.helpers.arrayElement(TABLE_NAMES), + colNm: faker.helpers.arrayElement(COLUMN_NAMES), + regNm: faker.person.fullName(), + regDt: formatDateTime(faker.date.recent({ days: 90 })), + })); +} + +/** Validation 탭 목데이터 생성 */ +export function createValidationArticleMock( + count = 6, +): ValidationArticleItem[] { + faker.seed(300); + return Array.from({ length: count }, (_, index) => ({ + no: `${index + 1}`, + statsItmNm: faker.helpers.arrayElement(VALIDATION_STATS_ITEMS), + vrfcNm: faker.helpers.arrayElement(VERIFICATION_NAMES), + tblNm: faker.helpers.arrayElement(TABLE_NAMES), + colNm: faker.helpers.arrayElement(COLUMN_NAMES), + cmpTblNm: faker.helpers.arrayElement(TABLE_NAMES), + cmpColNm: faker.helpers.arrayElement(COLUMN_NAMES), + bscRul: faker.helpers.arrayElement(BASIC_RULES), + })); +} + +/** H-B 탭 기본 목데이터 */ +export const hbArticleMockData = createHBArticleMock(10); + +/** I-MR 탭 기본 목데이터 */ +export const imrArticleMockData = createIMRArticleMock(10); + +/** Validation 탭 기본 목데이터 */ +export const validationArticleMockData = createValidationArticleMock(6); diff --git a/apps/st/src/entities/statistics/model/verification-history-column.ts b/apps/st/src/entities/statistics/model/verification-history-column.ts new file mode 100644 index 000000000..aea9b7f4f --- /dev/null +++ b/apps/st/src/entities/statistics/model/verification-history-column.ts @@ -0,0 +1,120 @@ +import { ValueType } from "realgrid"; +import type { ColumnInfo } from "@rsone/components"; + +/** 검증 이력 그리드 컬럼 설정 */ +export const verificationHistoryColumnInfo: ColumnInfo = { + columns: [ + { + name: "executedAt", + fieldName: "executedAt", + header: { text: "검증 실행 일시" }, + editable: false, + sortdisable: false, + }, + { + name: "progressStatus", + fieldName: "progressStatus", + header: { text: "진행 상태" }, + editable: false, + sortdisable: false, + }, + { + name: "endedAt", + fieldName: "endedAt", + header: { text: "종료 일시" }, + editable: false, + sortdisable: false, + }, + { + name: "verificationYear", + fieldName: "verificationYear", + header: { text: "검증년도" }, + editable: false, + sortdisable: false, + }, + { + name: "mu", + fieldName: "mu", + header: { text: "μ" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0.###", + }, + { + name: "percentile", + fieldName: "percentile", + header: { text: "Percentile" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0.###", + }, + { + name: "a", + fieldName: "a", + header: { text: "A" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0.###", + }, + { + name: "c", + fieldName: "c", + header: { text: "C" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0.###", + }, + { + name: "target", + fieldName: "target", + header: { text: "검증 대상" }, + editable: false, + sortdisable: false, + }, + { + name: "normalCount", + fieldName: "normalCount", + header: { text: "정상건수" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0", + }, + { + name: "excludedCount", + fieldName: "excludedCount", + header: { text: "제외건수" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0", + }, + { + name: "abnormalCount", + fieldName: "abnormalCount", + header: { text: "이상건수" }, + editable: false, + sortdisable: false, + valueType: ValueType.NUMBER, + dataFormat: "#,##0", + }, + ], + columnLayout: [ + "executedAt", + "progressStatus", + "endedAt", + "verificationYear", + "mu", + "percentile", + "a", + "c", + "target", + "normalCount", + "excludedCount", + "abnormalCount", + ], +}; diff --git a/apps/st/src/entities/statistics/model/verification-history-interface.ts b/apps/st/src/entities/statistics/model/verification-history-interface.ts new file mode 100644 index 000000000..869399cba --- /dev/null +++ b/apps/st/src/entities/statistics/model/verification-history-interface.ts @@ -0,0 +1,27 @@ +/** 검증 이력 한 건 (그리드 행 데이터) */ +export interface VerificationHistoryItem { + /** 검증 실행 일시 */ + executedAt: string; + /** 진행 상태 */ + progressStatus: string; + /** 종료 일시 */ + endedAt: string; + /** 검증년도 */ + verificationYear: string; + /** μ */ + mu: number; + /** Percentile */ + percentile: number; + /** A */ + a: number; + /** C */ + c: number; + /** 검증 대상 */ + target: string; + /** 정상건수 */ + normalCount: number; + /** 제외건수 */ + excludedCount: number; + /** 이상건수 */ + abnormalCount: number; +} diff --git a/apps/st/src/entities/statistics/model/verification-history-mock.ts b/apps/st/src/entities/statistics/model/verification-history-mock.ts new file mode 100644 index 000000000..90c152be7 --- /dev/null +++ b/apps/st/src/entities/statistics/model/verification-history-mock.ts @@ -0,0 +1,67 @@ +import { fakerKO as faker } from "@faker-js/faker"; +import type { VerificationHistoryItem } from "./verification-history-interface"; + +const VERIFICATION_TARGETS = [ + "하수도 보급률", + "하수관로", + "하수관로 유지관리", + "하수저류시설 및 빗물펌프장", + "펌프장", + "공공하수처리시설", + "분뇨처리시설", + "개인하수처리시설", + "하수도재정", + "물 재이용", + "하수도 서비스 수준", +]; + +const PROGRESS_STATUSES = ["대기", "진행중", "완료", "실패"]; + +function formatDateTime(date: Date): string { + const y = date.getFullYear(); + const m = String(date.getMonth() + 1).padStart(2, "0"); + const d = String(date.getDate()).padStart(2, "0"); + const h = String(date.getHours()).padStart(2, "0"); + const min = String(date.getMinutes()).padStart(2, "0"); + return `${y}-${m}-${d} ${h}:${min}`; +} + +/** 검증 이력 목데이터 생성 (그리드 행 형식) */ +export function createVerificationHistoryMock( + count = 10, +): Record[] { + faker.seed(42); + return Array.from({ length: count }, () => { + const executedAt = faker.date.recent({ days: 90 }); + const durationMinutes = faker.number.int({ min: 1, max: 120 }); + const endedAt = new Date( + executedAt.getTime() + durationMinutes * 60 * 1000, + ); + const status = faker.helpers.arrayElement(PROGRESS_STATUSES); + const normalCount = faker.number.int({ min: 0, max: 500 }); + const excludedCount = faker.number.int({ min: 0, max: 50 }); + const abnormalCount = faker.number.int({ min: 0, max: 30 }); + const item: VerificationHistoryItem = { + executedAt: formatDateTime(executedAt), + progressStatus: status, + endedAt: formatDateTime(endedAt), + verificationYear: String(executedAt.getFullYear()), + mu: faker.number.float({ min: 0, max: 1, fractionDigits: 3 }), + percentile: faker.number.float({ + min: 0, + max: 100, + fractionDigits: 2, + }), + a: faker.number.float({ min: 0, max: 10, fractionDigits: 3 }), + c: faker.number.float({ min: 0, max: 10, fractionDigits: 3 }), + target: faker.helpers.arrayElement(VERIFICATION_TARGETS), + normalCount, + excludedCount, + abnormalCount, + }; + return { ...item } as Record; + }); +} + +/** 검증 이력 기본 목데이터 (10건) */ +export const verificationHistoryMockData = createVerificationHistoryMock(10); diff --git a/apps/st/src/entities/statistics/model/verification-target-management-interface.ts b/apps/st/src/entities/statistics/model/verification-target-management-interface.ts new file mode 100644 index 000000000..08d771256 --- /dev/null +++ b/apps/st/src/entities/statistics/model/verification-target-management-interface.ts @@ -0,0 +1,105 @@ +import type { PageableList } from "@/shared/model"; +import type { ApiResponse } from "./statistics-interface"; + +// 검증 대상 관리 응답 DTO +export interface VerificationTargetManagementResponse { + vrfcTrgtSn: number; // 검증 대상 일련번호 + vrfcMthdCd: string; // 검증 방법 코드 + vrfcMthdNm: string; // 검증 방법 명 + statsCd: string; // 통계 코드 + statsNm: string; // 통계 항목 명 + schmNm: string; // 스키마 명 + tblNm: string; // 테이블 명 + colNm: string; // 컬럼 명 + pkColNm: string; // pk 컬럼 명 + ipcrCntVl: number | null; // 중요도 계수 값 (mu) + pctlCrtrVl: number | null; // 백분위 기준 값 (percentile) + scopCntCntVl: number | null; // 범위 조정 계수 값 (A) + thrsCntVl: number | null; // 임계 계수 값 (C) + useYn: string; // 사용 여부 + vrfcTrgtNm: string; // 검증대상명 + rgtr: string | null; // 등록자 ID + regDt: string | null; // 등록 일시 + mdfr: string | null; // 수정자 ID + rgtrNm: string | null; // 등록자명 + mdfrNm: string | null; // 수정자명 + mdfcn: string | null; // 수정 일시 +} + +// 검증 대상 관리 검색 DTO +export interface VerificationTargetManagementSearchParams { + vrfcMthdCd?: string; // 검증 방법 코드 + statsCd?: string; // 통계 코드 + tblNm?: string; // 테이블 명 + colNm?: string; // 컬럼 명 + vrfcTrgtNm?: string; // 검증대상명 + useYn?: string; // 사용 여부 + page?: number; // 페이지 번호 (0부터 시작) + size?: number; // 페이지 크기 + sort?: string; // 정렬 조건 (예: "vrfcTrgtSn,desc") +} + +// 검증 대상 관리 저장 요청 DTO +export interface VerificationTargetManagementSaveRequest { + vrfcMthdCd: string; // 검증 방법 코드 (필수, 최대 10자) + statsCd: string; // 통계 코드 (필수, 최대 10자) + schmNm: string; // 스키마 명 (필수, 최대 150자) + tblNm: string; // 테이블 명 (필수, 최대 150자) + colNm: string; // 컬럼 명 (필수, 최대 150자) + pkColNm: string; // pk 컬럼 명 (필수, 최대 150자) + ipcrCntVl?: number | null; // 중요도 계수 값 (mu) + pctlCrtrVl?: number | null; // 백분위 기준 값 (percentile) + scopCntCntVl?: number | null; // 범위 조정 계수 값 (A) + thrsCntVl?: number | null; // 임계 계수 값 (C) + useYn?: string; // 사용 여부 (Y/N, 최대 1자) + vrfcTrgtNm?: string; // 검증대상명 (최대 150자) +} + +// 검증 대상 관리 수정 요청 DTO +export interface VerificationTargetManagementUpdateRequest { + vrfcMthdCd: string; // 검증 방법 코드 (필수, 최대 10자) + statsCd: string; // 통계 코드 (필수, 최대 10자) + schmNm: string; // 스키마 명 (필수, 최대 150자) + tblNm: string; // 테이블 명 (필수, 최대 150자) + colNm: string; // 컬럼 명 (필수, 최대 150자) + pkColNm: string; // pk 컬럼 명 (필수, 최대 150자) + ipcrCntVl?: number | null; // 중요도 계수 값 (mu) + pctlCrtrVl?: number | null; // 백분위 기준 값 (percentile) + scopCntCntVl?: number | null; // 범위 조정 계수 값 (A) + thrsCntVl?: number | null; // 임계 계수 값 (C) + useYn?: string; // 사용 여부 (Y/N, 최대 1자) + vrfcTrgtNm?: string; // 검증대상명 (최대 150자) +} + +// API 응답 타입 +export type VerificationTargetManagementListApiResponse = + PageableList; +export type VerificationTargetManagementDetailApiResponse = + ApiResponse; +export type VerificationTargetManagementSaveApiResponse = ApiResponse; +export type VerificationTargetManagementUpdateApiResponse = ApiResponse; +export type VerificationTargetManagementDeleteApiResponse = ApiResponse; + +// 서비스 인터페이스 +export interface VerificationTargetManagementService { + getVerificationTargetManagementList( + params: VerificationTargetManagementSearchParams, + ): Promise; + + getVerificationTargetManagementById( + vrfcTrgtSn: number, + ): Promise; + + saveVerificationTargetManagement( + request: VerificationTargetManagementSaveRequest, + ): Promise; + + updateVerificationTargetManagement( + vrfcTrgtSn: number, + request: VerificationTargetManagementUpdateRequest, + ): Promise; + + deleteVerificationTargetManagement( + vrfcTrgtSn: number, + ): Promise; +} diff --git a/apps/st/src/entities/statistics/model/verification-target-management-schema.ts b/apps/st/src/entities/statistics/model/verification-target-management-schema.ts new file mode 100644 index 000000000..976c5b397 --- /dev/null +++ b/apps/st/src/entities/statistics/model/verification-target-management-schema.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; + +export const verificationTargetManagementSchema = z.object({ + vrfcTrgtSn: z.number().optional(), + vrfcMthdCd: z.string().optional(), + vrfcMthdNm: z.string().optional().nullable(), + statsCd: z.string().min(1, "통계항목을 선택해주세요"), + statsNm: z.string().optional().nullable(), + schmNm: z.string().min(1, "스키마명을 입력해주세요"), + tblNm: z.string().min(1, "테이블명을 입력해주세요"), + colNm: z.string().min(1, "컬럼명을 입력해주세요"), + pkColNm: z.string().min(1, "PK 키를 입력해주세요"), + ipcrCntVl: z + .number() + .min(0, "중요도 계수는 0 이상이어야 합니다") + .max(1, "중요도 계수는 1 이하여야 합니다") + .nullable() + .optional(), + pctlCrtrVl: z + .number() + .min(0, "백분위수 기준값은 0 이상이어야 합니다") + .max(0.5, "백분위수 기준값은 0.5 이하여야 합니다") + .nullable() + .optional(), + scopCntCntVl: z + .number() + .min(0, "스케일 조정 계수는 0 이상이어야 합니다") + .max(1, "스케일 조정 계수는 1 이하여야 합니다") + .nullable() + .optional(), + thrsCntVl: z + .number() + .int("임계 계수는 정수여야 합니다") + .min(0, "임계 계수는 0 이상이어야 합니다") + .max(100, "임계 계수는 100 이하여야 합니다") + .nullable() + .optional(), + useYn: z.string().optional(), + vrfcTrgtNm: z.string().optional().nullable(), + rgtr: z.string().optional().nullable(), + regDt: z.string().optional().nullable(), + mdfr: z.string().optional().nullable(), + rgtrNm: z.string().optional().nullable(), + mdfrNm: z.string().optional().nullable(), + mdfcn: z.string().optional().nullable(), +}); + +export type VerificationTargetManagementFormData = z.infer< + typeof verificationTargetManagementSchema +>; diff --git a/apps/st/src/pages/statistics/index.ts b/apps/st/src/pages/statistics/index.ts index 7a969422f..c419d5df7 100644 --- a/apps/st/src/pages/statistics/index.ts +++ b/apps/st/src/pages/statistics/index.ts @@ -1 +1 @@ -export { default as statisticsPage } from "./ui/statistics-page"; \ No newline at end of file +export { default as StatisticsPage } from "./ui/statistics-page"; diff --git a/apps/st/src/pages/statistics/ui/statistics-page.tsx b/apps/st/src/pages/statistics/ui/statistics-page.tsx index 3efa3b04f..7513b0ffe 100644 --- a/apps/st/src/pages/statistics/ui/statistics-page.tsx +++ b/apps/st/src/pages/statistics/ui/statistics-page.tsx @@ -6,6 +6,8 @@ import { useTabStore } from "@/store/tab-store"; import Dashboard from "@/components/Dashboard"; import { SkeletonPage } from "@/shared/ui/skeleton-page"; +import "@rsone/components/index.css"; + const StatisticsPage = () => { const { tabs, activeTabId } = useTabStore(); @@ -38,7 +40,7 @@ const StatisticsPage = () => { {tabs.map((tab) => { // 렌더링 시점에 컴포넌트가 없으면 바로 로드 if (!componentCache.current.has(tab.id)) { - const componentName = tab.id; + const componentName = tab.urlPath; const parentComponentName = tab.parentEngNm; const DynamicComponent = dynamic( diff --git a/apps/st/src/shared/config/api.ts b/apps/st/src/shared/config/api.ts index 61c2bec0e..1b9cf74ec 100644 --- a/apps/st/src/shared/config/api.ts +++ b/apps/st/src/shared/config/api.ts @@ -3,70 +3,76 @@ import { PROXY_HOST } from "./env"; export const BASE_URL = `${PROXY_HOST}/server`; export const ENDPOINT = { - ATTACH_SERVICE: { - TUS_UPLOAD: "/attach-service/api/v1/tus/upload", - EDITOR_UPLOAD: "/attach-service/api/v1/upload/editor", - IMAGES: "/attach-service/api/v1/images", - MOVIE_THUMBNAIL: "/attach-service/api/v1/movie/thumbnail", - ATTACHMENTS: "/attach-service/api/v1/atfl/attachments", - DOWNLOAD: "/attach-service/api/v1/atflcd/download", - STREAM_VIDEO: "/attach-service/api/v1/stream/video", - }, - USER_SERVICE: { - LOGIN: "/user-service/login", - USERS: "/user-service/api/v1/users", - SILENT_REFRESH: "/user-service/api/v1/users/token/refresh", - AUTHORIZATIONS: "/user-service/api/v1/authorizations", - ROLE_AUTHORIZATIONS: "/user-service/api/v1/role-authorizations", - ROLES: "/user-service/api/v1/roles", - LOGINLOG: "/user-service/api/v1/login-logs", - PRIVACYLOG: "/user-service//api/v1/prvc-inq-logs", - }, - CMS_SERVICE: { - DASHBOARD: "/cms-service/api/v1/dashboard", - SITES: "/cms-service/api/v1/sites", - IPS: "/cms-service/api/v1/site-ips", - DOMAINS: "/cms-service/api/v1/site-dmns", - POSTINGS: "/cms-service/api/v1/site-pstgs", - CODE: "/cms-service/api/v1/code/cache", - MENUS: "/cms-service/api/v1/menus", - MENU_ROLES: "/cms-service/api/v1/menu-roles", - MENU_AUTHRTS: "/cms-service/api/v1/menu-authrts", - MENU_TEMPORARY_STORAGE: "/cms-service/api/v1/menu-tmpr-strg", - MENU_HISTORY: "/cms-service/api/v1/menu-hstry", - CONTENTS: "/cms-service/api/v1/contents", - CONTENTS_DETAILS: "/cms-service/api/v1/contents-details", - ORGANIZATIONS: "/cms-service/api/v1/ognzs", - USER_ORGANIZATION: "/cms-service/api/v1/user-ognz", - IMAGES: "/cms-service/api/v1/images", - BANNERS: "/cms-service/api/v1/bnrs", - TEMPLATE: "/cms-service/api/v1/tmplt", - TERMS: "/cms-service/api/v1/trms", - LWPO_CODE: "/cms-service/api/v1/lwpo-cds", - UP_CODE: "/cms-service/api/v1/up-codes", - POPUPS: "/cms-service/api/v1/popups", - SCHEDULES: "/cms-service/api/v1/schdls", - SURVEY: "/cms-service/api/v1/srvy", - SURVEY_QUESTION: "/cms-service/api/v1/srvy-qitem", - SURVEY_ARTICLE: "/cms-service/api/v1/srvy-artcl", - ZIPS: "/cms-service/api/v1/zips", - GROUPS: "/cms-service/api/v1/groups", - GROUP_USERS: "/cms-service/api/v1/group-users", - MANAGER_IP: "/cms-service/api/v1/mgrip", - APILOG: "/cms-service/api/v1/api-logs", - SITE_AUTHORITY: "/cms-service/api/v1/site-authrt", - CONNECTION_LOG: "/cms-service/api/v1/cntnlog", - }, - BOARD_SERVICE: { - BBS: "/board-service/api/v1/bbs", - BBS_TEMPLATES: "/board-service/api/v1/bbsTmplt", - POSTS: "/board-service/api/v1/posts", - POSTS_COMMENTS: "/board-service/api/v1/posts-cmnts", - POST_EVALUATION: "/board-service/api/v1/pstEvl", - }, - ST_SERVICE: { - COMMON: "/st-service/api/v1/common", - } + ATTACH_SERVICE: { + TUS_UPLOAD: "/attach-service/api/v1/tus/upload", + EDITOR_UPLOAD: "/attach-service/api/v1/upload/editor", + IMAGES: "/attach-service/api/v1/images", + MOVIE_THUMBNAIL: "/attach-service/api/v1/movie/thumbnail", + ATTACHMENTS: "/attach-service/api/v1/atfl/attachments", + DOWNLOAD: "/attach-service/api/v1/atflcd/download", + STREAM_VIDEO: "/attach-service/api/v1/stream/video", + }, + USER_SERVICE: { + LOGIN: "/user-service/login", + USERS: "/user-service/api/v1/users", + SILENT_REFRESH: "/user-service/api/v1/users/token/refresh", + AUTHORIZATIONS: "/user-service/api/v1/authorizations", + ROLE_AUTHORIZATIONS: "/user-service/api/v1/role-authorizations", + ROLES: "/user-service/api/v1/roles", + LOGINLOG: "/user-service/api/v1/login-logs", + PRIVACYLOG: "/user-service//api/v1/prvc-inq-logs", + }, + CMS_SERVICE: { + DASHBOARD: "/cms-service/api/v1/dashboard", + SITES: "/cms-service/api/v1/sites", + IPS: "/cms-service/api/v1/site-ips", + DOMAINS: "/cms-service/api/v1/site-dmns", + POSTINGS: "/cms-service/api/v1/site-pstgs", + CODE: "/cms-service/api/v1/code/cache", + MENUS: "/cms-service/api/v1/menus", + MENU_ROLES: "/cms-service/api/v1/menu-roles", + MENU_AUTHRTS: "/cms-service/api/v1/menu-authrts", + MENU_TEMPORARY_STORAGE: "/cms-service/api/v1/menu-tmpr-strg", + MENU_HISTORY: "/cms-service/api/v1/menu-hstry", + CONTENTS: "/cms-service/api/v1/contents", + CONTENTS_DETAILS: "/cms-service/api/v1/contents-details", + ORGANIZATIONS: "/cms-service/api/v1/ognzs", + USER_ORGANIZATION: "/cms-service/api/v1/user-ognz", + IMAGES: "/cms-service/api/v1/images", + BANNERS: "/cms-service/api/v1/bnrs", + TEMPLATE: "/cms-service/api/v1/tmplt", + TERMS: "/cms-service/api/v1/trms", + LWPO_CODE: "/cms-service/api/v1/lwpo-cds", + UP_CODE: "/cms-service/api/v1/up-codes", + POPUPS: "/cms-service/api/v1/popups", + SCHEDULES: "/cms-service/api/v1/schdls", + SURVEY: "/cms-service/api/v1/srvy", + SURVEY_QUESTION: "/cms-service/api/v1/srvy-qitem", + SURVEY_ARTICLE: "/cms-service/api/v1/srvy-artcl", + ZIPS: "/cms-service/api/v1/zips", + GROUPS: "/cms-service/api/v1/groups", + GROUP_USERS: "/cms-service/api/v1/group-users", + MANAGER_IP: "/cms-service/api/v1/mgrip", + APILOG: "/cms-service/api/v1/api-logs", + SITE_AUTHORITY: "/cms-service/api/v1/site-authrt", + CONNECTION_LOG: "/cms-service/api/v1/cntnlog", + }, + BOARD_SERVICE: { + BBS: "/board-service/api/v1/bbs", + BBS_TEMPLATES: "/board-service/api/v1/bbsTmplt", + POSTS: "/board-service/api/v1/posts", + POSTS_COMMENTS: "/board-service/api/v1/posts-cmnts", + POST_EVALUATION: "/board-service/api/v1/pstEvl", + }, + ST_SERVICE: { + COMMON: "/st-management-service/api/v1/common", + INPUT: "/st-input-service/api/v1/input", + REVIEW: "/st-management-service/api/v1/review", + INPUTCOMMON: "/st-input-service/api/v1/common", + }, + STATVERIFY_SERVICE: { + VRFCTGT_MNG: "/statverify-service/api/v1/vrfc-trgt-mng", + }, }; export const JWT_EXPIRATION_TIME = 1800000; diff --git a/apps/st/src/shared/ui/statistics-page-layout.tsx b/apps/st/src/shared/ui/statistics-page-layout.tsx index 1597a7af0..b34ebb5eb 100644 --- a/apps/st/src/shared/ui/statistics-page-layout.tsx +++ b/apps/st/src/shared/ui/statistics-page-layout.tsx @@ -7,12 +7,10 @@ function StatisticsPageLayout({ children }: { children: React.ReactNode }) { const pageTitle = tabs.find((t) => t.menuItem.menuEngNm === activeTabId); - const menuPaths = pageTitle?.path - ?.split(">") - .map((path) => path.trim()); + const menuPaths = pageTitle?.path?.split(">").map((path) => path.trim()); return ( -
+
{ return null; } - const handleCloseTab = (e: React.MouseEvent | React.KeyboardEvent, tabId: string) => { + const handleCloseTab = ( + e: React.MouseEvent | React.KeyboardEvent, + tabId: string, + ) => { e.stopPropagation(); removeTab(tabId); }; @@ -22,22 +25,22 @@ const TabBar = () => { className="w-full" variant="outline" > - + {tabs.map((tab) => ( - + {tab.label} handleCloseTab(e, tab.id)} aria-label={`${tab.label} 탭 닫기`} - className="flex items-center justify-center flex-shrink-0 leading-none hover:text-[#2094fa]" + className="flex flex-shrink-0 items-center justify-center leading-none hover:text-[#2094fa]" > @@ -46,7 +49,6 @@ const TabBar = () => { ); -} +}; export { TabBar }; - diff --git a/apps/st/src/store/tab-store.ts b/apps/st/src/store/tab-store.ts index f5b49bb29..6c48a5074 100644 --- a/apps/st/src/store/tab-store.ts +++ b/apps/st/src/store/tab-store.ts @@ -4,7 +4,8 @@ import type { MenuItem } from "@/entities/menu"; export interface Tab { id: string; // 고유 ID (menuEngNm) label: string; // 탭에 표시될 이름 - path: string; // URL 경로 + path: string; // 메뉴 경로 + urlPath: string; // url 경로 parentEngNm: string; // 부모 menuEngNm menuItem: MenuItem; // 메뉴 정보 } @@ -43,6 +44,7 @@ const useTabStoreHook = create((set, get) => ({ id: tabId, label: menuItem.menuKornNm, path: menuItem.menuPath, + urlPath: menuItem.urlPath, parentEngNm: menuList?.find((m) => m.menuCd === menuItem.parentId)?.menuEngNm || '', menuItem, }; @@ -112,5 +114,4 @@ const useTabStoreHook = create((set, get) => ({ })); export const useTabStore = useTabStoreHook; -export const getTabStoreState = () => useTabStoreHook.getState(); - +export const getTabStoreState = () => useTabStoreHook.getState(); \ No newline at end of file diff --git a/apps/st/tsconfig.json b/apps/st/tsconfig.json index 5b8c29899..e91347649 100644 --- a/apps/st/tsconfig.json +++ b/apps/st/tsconfig.json @@ -27,7 +27,8 @@ "@/*": ["./*"], "@common/components": ["../../../packages/common/components/src/"], "@common/config": ["../../../packages/common/config/dist/"], - "@common/network": ["../../../packages/common/network/"] + "@common/network": ["../../../packages/common/network/"], + "@rsone/components": ["../../../packages/rsone/dist/"] } }, "include": [ diff --git a/package.json b/package.json index cd7bc8007..89d886d0c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "dev:dm": "turbo run dev --filter=dm", "dev:dm_new": "turbo run dev --filter=dm_new", "preview:components": "turbo run storybook --filter=@common/components", - "preinstall": "npx only-allow pnpm" + "preinstall": "npx only-allow pnpm", + "prepare": "husky" }, "dependencies": { "chart.js": "^4.4.8", @@ -39,6 +40,8 @@ "@types/node": "^22.13.1", "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", + "husky": "^9.1.7", + "lint-staged": "^16.2.7", "turbo": "2.4.2" }, "pnpm": { @@ -47,7 +50,6 @@ "@types/react-dom": "^19.2.3", "react": "^19.2.1", "react-dom": "^19.2.1", - "lodash.isequal": "^4.5.0", "source-map": "^0.7.4" }, diff --git a/packages/common/components/src/ui/footer/index.tsx b/packages/common/components/src/ui/footer/index.tsx index 029b25910..2430820ff 100644 --- a/packages/common/components/src/ui/footer/index.tsx +++ b/packages/common/components/src/ui/footer/index.tsx @@ -20,7 +20,7 @@ type BannerImageProps = { lnkgUrlAddr: string; }; -const BannerImage = ({ atflCd, bnrSn, lnkgUrlAddr }: BannerImageProps) => { +const BannerImage = ({ atflCd, lnkgUrlAddr }: BannerImageProps) => { const { data: imageUrl, isLoading } = useQuery({ queryKey: [ENDPOINT.ATTACH_SERVICE.IMAGES, atflCd], queryFn: () => getImageUrlByAtflCd(atflCd), @@ -29,13 +29,13 @@ const BannerImage = ({ atflCd, bnrSn, lnkgUrlAddr }: BannerImageProps) => { const handleClick = () => { if (lnkgUrlAddr) { - window.open(lnkgUrlAddr, '_blank'); + window.open(lnkgUrlAddr, "_blank"); } }; if (isLoading) { return ( -
+
로딩 중...
); @@ -43,18 +43,22 @@ const BannerImage = ({ atflCd, bnrSn, lnkgUrlAddr }: BannerImageProps) => { if (!imageUrl) { return ( -
+
이미지 없음
); } return ( -
- 배너 이미지 + 배너 이미지
); }; @@ -70,25 +74,33 @@ export function Footer() { queryFn: () => getBannerList(siteId), }); -// MAIN 타입 배너만 필터링 - const mainBanners = bannerList?.filter((banner) => banner.bnrTypeCd === "BNRFTER") ?? []; - + // MAIN 타입 배너만 필터링 + const mainBanners = + bannerList?.filter((banner) => banner.bnrTypeCd === "BNRFTER") ?? []; const plugin = useRef(Autoplay({ delay: 2000, stopOnInteraction: true })); return ( -