Merge remote-tracking branch 'origin/iipbs/st/dev' into feature/sein
This commit is contained in:
@@ -1,54 +1,32 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { Suspense, useCallback, useEffect, useMemo, useState } from "react";
|
import { Suspense, useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
import { usePathname } from "next/navigation";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
||||||
getTabStoreState as getGridTabStoreState,
|
getTabStoreState as getGridTabStoreState,
|
||||||
|
|
||||||
useTabStore as gridTabStore,
|
useTabStore as gridTabStore,
|
||||||
|
|
||||||
} from "@rsone/components";
|
} from "@rsone/components";
|
||||||
|
|
||||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { ENDPOINT } from "@/shared/config";
|
import { ENDPOINT } from "@/shared/config";
|
||||||
|
|
||||||
import { getCookie, useAlertStore, useMenuStore } from "@/shared/lib";
|
import { getCookie, useAlertStore, useMenuStore } from "@/shared/lib";
|
||||||
|
import { isBbsNoticeMenu } from "@/shared/lib/bbs-notice-menu";
|
||||||
|
import {
|
||||||
|
menuMatchesStatisticsTabId,
|
||||||
|
resolveStatisticsTabId,
|
||||||
|
} from "@/shared/lib/statistics-menu-url";
|
||||||
import { useStatisticsTabUrlSync } from "@/shared/lib/use-statistics-tab-url-sync";
|
import { useStatisticsTabUrlSync } from "@/shared/lib/use-statistics-tab-url-sync";
|
||||||
|
|
||||||
import { isVerificationSelectionReportMenu } from "@/shared/lib/verification-selection-report";
|
import { isVerificationSelectionReportMenu } from "@/shared/lib/verification-selection-report";
|
||||||
|
|
||||||
import { StatisticsPageLayout } from "@/shared/ui/statistics-page-layout";
|
import { StatisticsPageLayout } from "@/shared/ui/statistics-page-layout";
|
||||||
|
|
||||||
import { tokenManager } from "@/entities/auth";
|
import { tokenManager } from "@/entities/auth";
|
||||||
|
|
||||||
import type { MenuItem } from "@/entities/menu";
|
import type { MenuItem } from "@/entities/menu";
|
||||||
|
|
||||||
import { MenuApi } from "@/entities/menu";
|
import { MenuApi } from "@/entities/menu";
|
||||||
|
|
||||||
import { BaseLayout } from "@common/components";
|
import { BaseLayout } from "@common/components";
|
||||||
|
|
||||||
import { getConfig } from "@common/config";
|
import { getConfig } from "@common/config";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { getTabStoreState, useTabStore } from "@/store/tab-store";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import VerificationSelectionReport from "@/components/statistics/VerificationSelectionReport";
|
import VerificationSelectionReport from "@/components/statistics/VerificationSelectionReport";
|
||||||
|
import { getTabStoreState, useTabStore } from "@/store/tab-store";
|
||||||
|
|
||||||
|
|
||||||
const appConfig = getConfig();
|
const appConfig = getConfig();
|
||||||
|
|
||||||
@@ -58,42 +36,23 @@ const appSiteId = getCookie("site-id-key") ?? "";
|
|||||||
|
|
||||||
const isLoggedIn = !!userId;
|
const isLoggedIn = !!userId;
|
||||||
|
|
||||||
|
function WithBaseLayoutInner({ children }: { children: React.ReactNode }) {
|
||||||
|
|
||||||
function WithBaseLayoutInner({
|
|
||||||
|
|
||||||
children,
|
|
||||||
|
|
||||||
}: {
|
|
||||||
|
|
||||||
children: React.ReactNode;
|
|
||||||
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** 탭 추가 없이 메뉴만 눌렀을 때 패널 유지 (다른 메뉴 클릭해도 유지) */
|
/** 탭 추가 없이 메뉴만 눌렀을 때 패널 유지 (다른 메뉴 클릭해도 유지) */
|
||||||
|
|
||||||
const [isVerificationSelectionReportPanelOpen, setReportPanelOpen] =
|
const [isVerificationSelectionReportPanelOpen, setReportPanelOpen] =
|
||||||
|
|
||||||
useState(false);
|
useState(false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const setCurrentMenuInfo = useMenuStore(
|
const setCurrentMenuInfo = useMenuStore(
|
||||||
|
|
||||||
(state) => state.setCurrentMenuInfo,
|
(state) => state.setCurrentMenuInfo,
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const currentMenuInfo = useMenuStore((state) => state.currentMenuInfo);
|
const currentMenuInfo = useMenuStore((state) => state.currentMenuInfo);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const addTab = useTabStore((state) => state.addTab);
|
const addTab = useTabStore((state) => state.addTab);
|
||||||
|
|
||||||
const setActiveTab = useTabStore((state) => state.setActiveTab);
|
const setActiveTab = useTabStore((state) => state.setActiveTab);
|
||||||
@@ -108,16 +67,11 @@ function WithBaseLayoutInner({
|
|||||||
|
|
||||||
const addTabForGrid = gridTabStore((state) => state.addTab);
|
const addTabForGrid = gridTabStore((state) => state.addTab);
|
||||||
|
|
||||||
const setActiveTabForGrid = gridTabStore((state) => state.setActiveTab);
|
|
||||||
|
|
||||||
const setMenuListForGrid = gridTabStore((state) => state.setMenuList);
|
const setMenuListForGrid = gridTabStore((state) => state.setMenuList);
|
||||||
|
|
||||||
const alert = useAlertStore((state) => state.setMessage);
|
const alert = useAlertStore((state) => state.setMessage);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { syncTabToUrl } = useStatisticsTabUrlSync({
|
const { syncTabToUrl } = useStatisticsTabUrlSync({
|
||||||
|
|
||||||
pathname,
|
pathname,
|
||||||
|
|
||||||
menuList,
|
menuList,
|
||||||
@@ -129,41 +83,27 @@ function WithBaseLayoutInner({
|
|||||||
addTabForGrid,
|
addTabForGrid,
|
||||||
|
|
||||||
setCurrentMenuInfo,
|
setCurrentMenuInfo,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const { data: menuListData } = useQuery({
|
const { data: menuListData } = useQuery({
|
||||||
|
|
||||||
queryKey: [ENDPOINT.CMS_SERVICE.MENU_ROLES],
|
queryKey: [ENDPOINT.CMS_SERVICE.MENU_ROLES],
|
||||||
|
|
||||||
queryFn: () => MenuApi.getMenuRoles(appSiteId),
|
queryFn: () => MenuApi.getMenuRoles(appSiteId),
|
||||||
|
|
||||||
enabled: isLoggedIn,
|
enabled: isLoggedIn,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
if (menuListData) {
|
if (menuListData) {
|
||||||
|
|
||||||
setMenuList(menuListData);
|
setMenuList(menuListData);
|
||||||
|
|
||||||
setMenuListForGrid(menuListData);
|
setMenuListForGrid(menuListData);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [menuListData, setMenuList, setMenuListForGrid]);
|
}, [menuListData, setMenuList, setMenuListForGrid]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 새로고침 후 persist로 앱 탭만 복원된 경우 rsone 그리드 스토어에 탭을 맞춤
|
// 새로고침 후 persist로 앱 탭만 복원된 경우 rsone 그리드 스토어에 탭을 맞춤
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
if (!menuList) return;
|
if (!menuList) return;
|
||||||
|
|
||||||
const appTabs = getTabStoreState().tabs;
|
const appTabs = getTabStoreState().tabs;
|
||||||
@@ -172,20 +112,13 @@ function WithBaseLayoutInner({
|
|||||||
|
|
||||||
if (getGridTabStoreState().tabs.length > 0) return;
|
if (getGridTabStoreState().tabs.length > 0) return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (const tab of appTabs) {
|
for (const tab of appTabs) {
|
||||||
|
|
||||||
getGridTabStoreState().addTab(tab.menuItem);
|
getGridTabStoreState().addTab(tab.menuItem);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const activeId = getTabStoreState().activeTabId;
|
const activeId = getTabStoreState().activeTabId;
|
||||||
|
|
||||||
if (activeId) {
|
if (activeId) {
|
||||||
|
|
||||||
setActiveTab(activeId);
|
setActiveTab(activeId);
|
||||||
|
|
||||||
const activeTab = appTabs.find((t) => t.id === activeId);
|
const activeTab = appTabs.find((t) => t.id === activeId);
|
||||||
@@ -193,155 +126,104 @@ function WithBaseLayoutInner({
|
|||||||
const gridActiveId = activeTab?.menuItem.menuEngNm;
|
const gridActiveId = activeTab?.menuItem.menuEngNm;
|
||||||
|
|
||||||
if (gridActiveId) {
|
if (gridActiveId) {
|
||||||
|
|
||||||
getGridTabStoreState().setActiveTab(gridActiveId);
|
getGridTabStoreState().setActiveTab(gridActiveId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [menuList, tabs, setActiveTab]);
|
}, [menuList, tabs, setActiveTab]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 활성 탭의 메뉴를 찾아서 urlPath를 가져옴. 탭이 전부 닫히면 ''를 넘겨 LNB에서 메뉴 강조 제거
|
// 활성 탭의 메뉴를 찾아서 urlPath를 가져옴. 탭이 전부 닫히면 ''를 넘겨 LNB에서 메뉴 강조 제거
|
||||||
|
|
||||||
const currentPath = useMemo(() => {
|
const currentPath = useMemo(() => {
|
||||||
|
|
||||||
if (tabs.length === 0) return "";
|
if (tabs.length === 0) return "";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (activeTabId && menuList) {
|
if (activeTabId && menuList) {
|
||||||
|
|
||||||
// menuList에서 활성 탭의 메뉴 찾기
|
// menuList에서 활성 탭의 메뉴 찾기
|
||||||
|
|
||||||
const findMenuByEngNm = (items: MenuItem[]): MenuItem | null => {
|
const findMenuByEngNm = (items: MenuItem[]): MenuItem | null => {
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
|
if (menuMatchesStatisticsTabId(item, activeTabId)) {
|
||||||
if (item.urlPath === activeTabId) {
|
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
|
|
||||||
const found = findMenuByEngNm(item.children);
|
const found = findMenuByEngNm(item.children);
|
||||||
|
|
||||||
if (found) return found;
|
if (found) return found;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const activeMenu = findMenuByEngNm(menuList);
|
const activeMenu = findMenuByEngNm(menuList);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (activeMenu?.urlPath) {
|
if (activeMenu?.urlPath) {
|
||||||
|
|
||||||
return activeMenu.urlPath;
|
return activeMenu.urlPath;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 탭에서 직접 찾기
|
// 탭에서 직접 찾기
|
||||||
|
|
||||||
if (activeTabId) {
|
if (activeTabId) {
|
||||||
|
|
||||||
const currentTabs = getTabStoreState().tabs;
|
const currentTabs = getTabStoreState().tabs;
|
||||||
|
|
||||||
const activeTab = currentTabs.find((t) => t.id === activeTabId);
|
const activeTab = currentTabs.find((t) => t.id === activeTabId);
|
||||||
|
|
||||||
if (activeTab?.menuItem?.urlPath) {
|
if (activeTab?.menuItem?.urlPath) {
|
||||||
|
|
||||||
return activeTab.menuItem.urlPath;
|
return activeTab.menuItem.urlPath;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// currentMenuInfo에서 가져오기
|
// currentMenuInfo에서 가져오기
|
||||||
|
|
||||||
if (currentMenuInfo?.urlPath) {
|
if (currentMenuInfo?.urlPath) {
|
||||||
|
|
||||||
return currentMenuInfo.urlPath;
|
return currentMenuInfo.urlPath;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 기본값으로 pathname 사용
|
// 기본값으로 pathname 사용
|
||||||
|
|
||||||
return pathname ?? "";
|
return pathname ?? "";
|
||||||
|
|
||||||
}, [tabs.length, activeTabId, menuList, currentMenuInfo, pathname]);
|
}, [tabs.length, activeTabId, menuList, currentMenuInfo, pathname]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleMenuClick = useCallback(
|
const handleMenuClick = useCallback(
|
||||||
|
|
||||||
(item: MenuItem) => {
|
(item: MenuItem) => {
|
||||||
|
if (item.urlPath.includes("/cms/")) return;
|
||||||
|
|
||||||
setCurrentMenuInfo(item);
|
setCurrentMenuInfo(item);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (isVerificationSelectionReportMenu(item)) {
|
if (isVerificationSelectionReportMenu(item)) {
|
||||||
|
|
||||||
setReportPanelOpen(true);
|
setReportPanelOpen(true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isBbsNoticeMenu(item)) {
|
||||||
|
if (item.urlPath) {
|
||||||
|
router.push(item.urlPath);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const addTabResult: boolean = addTab(item);
|
const addTabResult: boolean = addTab(item);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// packages/rsone의 스토어에도 동기화
|
// packages/rsone의 스토어에도 동기화
|
||||||
|
|
||||||
if (addTabResult) {
|
if (addTabResult) {
|
||||||
|
|
||||||
addTabForGrid(item);
|
addTabForGrid(item);
|
||||||
|
|
||||||
if (item.urlPath) {
|
if (item.urlPath) {
|
||||||
|
syncTabToUrl(resolveStatisticsTabId(item.urlPath));
|
||||||
syncTabToUrl(item.urlPath);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!addTabResult) {
|
if (!addTabResult) {
|
||||||
|
|
||||||
alert(`최대 추가 할 수 있는 화면 수(10개)를 \n초과 하였습니다.
|
alert(`최대 추가 할 수 있는 화면 수(10개)를 \n초과 하였습니다.
|
||||||
|
|
||||||
기존 화면을 닫은 후 이용해주세요.`);
|
기존 화면을 닫은 후 이용해주세요.`);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[
|
[
|
||||||
|
|
||||||
setCurrentMenuInfo,
|
setCurrentMenuInfo,
|
||||||
|
|
||||||
addTab,
|
addTab,
|
||||||
@@ -354,70 +236,38 @@ function WithBaseLayoutInner({
|
|||||||
|
|
||||||
syncTabToUrl,
|
syncTabToUrl,
|
||||||
|
|
||||||
|
router,
|
||||||
],
|
],
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
|
|
||||||
queryClient={queryClient}
|
queryClient={queryClient}
|
||||||
|
|
||||||
tokenManager={tokenManager}
|
tokenManager={tokenManager}
|
||||||
|
|
||||||
currentPath={currentPath}
|
currentPath={currentPath}
|
||||||
|
|
||||||
handleMenuClick={handleMenuClick}
|
handleMenuClick={handleMenuClick}
|
||||||
|
|
||||||
>
|
>
|
||||||
|
<div className="flex h-full flex-1">
|
||||||
<div className="flex flex-1 h-full">
|
|
||||||
|
|
||||||
{isVerificationSelectionReportPanelOpen && (
|
{isVerificationSelectionReportPanelOpen && (
|
||||||
|
|
||||||
<VerificationSelectionReport
|
<VerificationSelectionReport
|
||||||
|
|
||||||
onClose={() => setReportPanelOpen(false)}
|
onClose={() => setReportPanelOpen(false)}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<StatisticsPageLayout>{children}</StatisticsPageLayout>
|
<StatisticsPageLayout>{children}</StatisticsPageLayout>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default function WithBaseLayout({
|
export default function WithBaseLayout({
|
||||||
|
|
||||||
children,
|
children,
|
||||||
|
|
||||||
}: {
|
}: {
|
||||||
|
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
|
|
||||||
<WithBaseLayoutInner>{children}</WithBaseLayoutInner>
|
<WithBaseLayoutInner>{children}</WithBaseLayoutInner>
|
||||||
|
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,19 @@ import { statisticsInputSewerageFinanceApi } from "@/entities/statistics/api/inp
|
|||||||
import { statisticsApi } from "@/entities/statistics/api/statistics-service";
|
import { statisticsApi } from "@/entities/statistics/api/statistics-service";
|
||||||
import type {
|
import type {
|
||||||
CauserBurdenItem,
|
CauserBurdenItem,
|
||||||
|
CauserBurdenSaveItem,
|
||||||
|
CauserBurdenSaveRequest,
|
||||||
SewerageChargeItem,
|
SewerageChargeItem,
|
||||||
|
SewerageChargeSaveItem,
|
||||||
|
SewerageChargeSaveRequest,
|
||||||
SewerageFinanceRequestParams,
|
SewerageFinanceRequestParams,
|
||||||
SewerageFinanceSettleItem,
|
SewerageFinanceSettleItem,
|
||||||
|
SewerageFinanceSettleSaveItem,
|
||||||
|
SewerageFinanceSettleSaveRequest,
|
||||||
SewerageFinanceVerificationResult,
|
SewerageFinanceVerificationResult,
|
||||||
SewerageUsageFeeItem,
|
SewerageUsageFeeItem,
|
||||||
|
SewerageUsageFeeSaveItem,
|
||||||
|
SewerageUsageFeeSaveRequest,
|
||||||
} from "@/entities/statistics/model/input/statistics-input-sewerage-finance-interface";
|
} from "@/entities/statistics/model/input/statistics-input-sewerage-finance-interface";
|
||||||
import { isInputPeriodCurrent } from "@/entities/statistics/model/input/statistics-sewage-supply-rate-input-interface";
|
import { isInputPeriodCurrent } from "@/entities/statistics/model/input/statistics-sewage-supply-rate-input-interface";
|
||||||
import type { cancelSubmitRequest, SewerageStatusInfo } from "@/entities/statistics/model/statistics-interface";
|
import type { cancelSubmitRequest, SewerageStatusInfo } from "@/entities/statistics/model/statistics-interface";
|
||||||
@@ -141,6 +149,163 @@ function mapRegionalListToGridRows<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeGridString(value: unknown): string {
|
||||||
|
if (value === null || value === undefined) return "";
|
||||||
|
return typeof value === "string" ? value : String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeGridRmrk(value: unknown): string | null {
|
||||||
|
if (value === null || value === undefined) return null;
|
||||||
|
const s = typeof value === "string" ? value : String(value);
|
||||||
|
return s.trim() === "" ? null : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildColumnFormatNumber(columns: { fieldName?: string; dataFormat?: string }[]) {
|
||||||
|
const columnFormatMap = new Map<string, string>();
|
||||||
|
columns.forEach((col) => {
|
||||||
|
if (col.fieldName && col.dataFormat) {
|
||||||
|
columnFormatMap.set(col.fieldName, col.dataFormat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (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;
|
||||||
|
const decimalPlaces = format.match(/\.(\d+)/)?.[1]?.length ?? 0;
|
||||||
|
return decimalPlaces > 0 ? parseFloat(num.toFixed(decimalPlaces)) : Math.round(num);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveSewerageFinanceTab(tabKey: string) {
|
||||||
|
return {
|
||||||
|
isSettleTab: tabKey === SewerageFinanceSettleInpColumn.tabKey,
|
||||||
|
isChargeTab: tabKey === SewerageChargeInpColumn.tabKey,
|
||||||
|
isUsageFeeTab: tabKey === SewerageUsageFeeInpColumn.tabKey,
|
||||||
|
isCauserBurdenTab: tabKey === CauserBurdenInpColumn.tabKey,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSewerageFinanceSettleSaveList(
|
||||||
|
currentData: Record<string, string | number>[],
|
||||||
|
): SewerageFinanceSettleSaveItem[] {
|
||||||
|
const formatNumber = buildColumnFormatNumber(SewerageFinanceSettleInpColumn.columns);
|
||||||
|
|
||||||
|
return currentData.map((d) => ({
|
||||||
|
admdstCd: normalizeGridString(d.admdstCd),
|
||||||
|
sggNm: normalizeGridString(d.sggNm),
|
||||||
|
admdstNm: normalizeGridString(d.admdstNm),
|
||||||
|
cnterGovSprtAmt: formatNumber(d.cnterGovSprtAmt, "cnterGovSprtAmt"),
|
||||||
|
mctpvLcexpAmt: formatNumber(d.mctpvLcexpAmt, "mctpvLcexpAmt"),
|
||||||
|
wareaSggLclAmt: formatNumber(d.wareaSggLclAmt, "wareaSggLclAmt"),
|
||||||
|
sewerUseAmt: formatNumber(d.sewerUseAmt, "sewerUseAmt"),
|
||||||
|
orgprBrdnAmt: formatNumber(d.orgprBrdnAmt, "orgprBrdnAmt"),
|
||||||
|
etcIncmAmt: formatNumber(d.etcIncmAmt, "etcIncmAmt"),
|
||||||
|
crfwAmt: formatNumber(d.crfwAmt, "crfwAmt"),
|
||||||
|
lbltAmt: formatNumber(d.lbltAmt, "lbltAmt"),
|
||||||
|
tmplntFcltAmt: formatNumber(d.tmplntFcltAmt, "tmplntFcltAmt"),
|
||||||
|
tmplntMendngAmt: formatNumber(d.tmplntMendngAmt, "tmplntMendngAmt"),
|
||||||
|
tmplntOperKeepAmt: formatNumber(d.tmplntOperKeepAmt, "tmplntOperKeepAmt"),
|
||||||
|
tmplntEtcAmt: formatNumber(d.tmplntEtcAmt, "tmplntEtcAmt"),
|
||||||
|
swagePplFcltAmt: formatNumber(d.swagePplFcltAmt, "swagePplFcltAmt"),
|
||||||
|
swagePplMendngAmt: formatNumber(d.swagePplMendngAmt, "swagePplMendngAmt"),
|
||||||
|
swagePplOperKeepAmt: formatNumber(d.swagePplOperKeepAmt, "swagePplOperKeepAmt"),
|
||||||
|
swagePplEtcAmt: formatNumber(d.swagePplEtcAmt, "swagePplEtcAmt"),
|
||||||
|
swageImpdFcltAmt: formatNumber(d.swageImpdFcltAmt, "swageImpdFcltAmt"),
|
||||||
|
swageImpdMendngAmt: formatNumber(d.swageImpdMendngAmt, "swageImpdMendngAmt"),
|
||||||
|
swageImpdOperKeepAmt: formatNumber(d.swageImpdOperKeepAmt, "swageImpdOperKeepAmt"),
|
||||||
|
swageImpdFcltEtcAmt: formatNumber(d.swageImpdFcltEtcAmt, "swageImpdFcltEtcAmt"),
|
||||||
|
etcAcdntCrfwAmt: formatNumber(d.etcAcdntCrfwAmt, "etcAcdntCrfwAmt"),
|
||||||
|
etcNrcpAmt: formatNumber(d.etcNrcpAmt, "etcNrcpAmt"),
|
||||||
|
etcAmt: formatNumber(d.etcAmt, "etcAmt"),
|
||||||
|
rmrk: normalizeGridRmrk(d.rmrk),
|
||||||
|
fnnByWholPjtcoAmt: formatNumber(d.fnnByWholPjtcoAmt, "fnnByWholPjtcoAmt"),
|
||||||
|
usgByWholPjtcoAmt: formatNumber(d.usgByWholPjtcoAmt, "usgByWholPjtcoAmt"),
|
||||||
|
tmplntWholAmt: formatNumber(d.tmplntWholAmt, "tmplntWholAmt"),
|
||||||
|
wholSwagePplAmt: formatNumber(d.wholSwagePplAmt, "wholSwagePplAmt"),
|
||||||
|
wholSwageImpdFcltAmt: formatNumber(d.wholSwageImpdFcltAmt, "wholSwageImpdFcltAmt"),
|
||||||
|
etcWholAmt: formatNumber(d.etcWholAmt, "etcWholAmt"),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSewerageChargeSaveList(
|
||||||
|
currentData: Record<string, string | number>[],
|
||||||
|
): SewerageChargeSaveItem[] {
|
||||||
|
const formatNumber = buildColumnFormatNumber(SewerageChargeInpColumn.columns);
|
||||||
|
|
||||||
|
return currentData.map((d) => ({
|
||||||
|
admdstCd: normalizeGridString(d.admdstCd),
|
||||||
|
sggNm: normalizeGridString(d.sggNm),
|
||||||
|
admdstNm: normalizeGridString(d.admdstNm),
|
||||||
|
anlLevyQnt: formatNumber(d.anlLevyQnt, "anlLevyQnt"),
|
||||||
|
levyAmt: formatNumber(d.levyAmt, "levyAmt"),
|
||||||
|
grssPrmcoAmt: formatNumber(d.grssPrmcoAmt, "grssPrmcoAmt"),
|
||||||
|
rmrk: normalizeGridRmrk(d.rmrk),
|
||||||
|
avgUntprcAmt: formatNumber(d.avgUntprcAmt, "avgUntprcAmt"),
|
||||||
|
grssUnitPrmcoAmt: formatNumber(d.grssUnitPrmcoAmt, "grssUnitPrmcoAmt"),
|
||||||
|
rlztnRt: formatNumber(d.rlztnRt, "rlztnRt"),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildSewerageUsageFeeSaveList(
|
||||||
|
currentData: Record<string, string | number>[],
|
||||||
|
): SewerageUsageFeeSaveItem[] {
|
||||||
|
const formatNumber = buildColumnFormatNumber(SewerageUsageFeeInpColumn.columns);
|
||||||
|
|
||||||
|
return currentData.map((d) => ({
|
||||||
|
admdstCd: normalizeGridString(d.admdstCd),
|
||||||
|
sggNm: normalizeGridString(d.sggNm),
|
||||||
|
admdstNm: normalizeGridString(d.admdstNm),
|
||||||
|
hshusLevyAmt: formatNumber(d.hshusLevyAmt, "hshusLevyAmt"),
|
||||||
|
hshusLevyQnt: formatNumber(d.hshusLevyQnt, "hshusLevyQnt"),
|
||||||
|
hshusUntprcAmt: formatNumber(d.hshusUntprcAmt, "hshusUntprcAmt"),
|
||||||
|
taskFrLevyAmt: formatNumber(d.taskFrLevyAmt, "taskFrLevyAmt"),
|
||||||
|
taskFrLevyQnt: formatNumber(d.taskFrLevyQnt, "taskFrLevyQnt"),
|
||||||
|
taskFrUntprcAmt: formatNumber(d.taskFrUntprcAmt, "taskFrUntprcAmt"),
|
||||||
|
fbuLevyAmt: formatNumber(d.fbuLevyAmt, "fbuLevyAmt"),
|
||||||
|
fbuLevyQnt: formatNumber(d.fbuLevyQnt, "fbuLevyQnt"),
|
||||||
|
fbuUntprcAmt: formatNumber(d.fbuUntprcAmt, "fbuUntprcAmt"),
|
||||||
|
bthhsFrSpcs1LevyAmt: formatNumber(d.bthhsFrSpcs1LevyAmt, "bthhsFrSpcs1LevyAmt"),
|
||||||
|
bthhsFrSpcs1LevyQnt: formatNumber(d.bthhsFrSpcs1LevyQnt, "bthhsFrSpcs1LevyQnt"),
|
||||||
|
bthhsFrSpcs1UntprcAmt: formatNumber(d.bthhsFrSpcs1UntprcAmt, "bthhsFrSpcs1UntprcAmt"),
|
||||||
|
bthhsFrSpcs2LevyAmt: formatNumber(d.bthhsFrSpcs2LevyAmt, "bthhsFrSpcs2LevyAmt"),
|
||||||
|
bthhsFrSpcs2LevyQnt: formatNumber(d.bthhsFrSpcs2LevyQnt, "bthhsFrSpcs2LevyQnt"),
|
||||||
|
bthhsFrSpcs2UntprcAmt: formatNumber(d.bthhsFrSpcs2UntprcAmt, "bthhsFrSpcs2UntprcAmt"),
|
||||||
|
induLevyAmt: formatNumber(d.induLevyAmt, "induLevyAmt"),
|
||||||
|
induLevyQnt: formatNumber(d.induLevyQnt, "induLevyQnt"),
|
||||||
|
induUntprcAmt: formatNumber(d.induUntprcAmt, "induUntprcAmt"),
|
||||||
|
etcLevyAmt: formatNumber(d.etcLevyAmt, "etcLevyAmt"),
|
||||||
|
etcLevyQnt: formatNumber(d.etcLevyQnt, "etcLevyQnt"),
|
||||||
|
etcLevyUntprcAmt: formatNumber(d.etcLevyUntprcAmt, "etcLevyUntprcAmt"),
|
||||||
|
rmrk: normalizeGridRmrk(d.rmrk),
|
||||||
|
levyAmt: formatNumber(d.levyAmt, "levyAmt"),
|
||||||
|
levyQnt: formatNumber(d.levyQnt, "levyQnt"),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildCauserBurdenSaveList(
|
||||||
|
currentData: Record<string, string | number>[],
|
||||||
|
): CauserBurdenSaveItem[] {
|
||||||
|
const formatNumber = buildColumnFormatNumber(CauserBurdenInpColumn.columns);
|
||||||
|
|
||||||
|
return currentData.map((d) => ({
|
||||||
|
admdstCd: normalizeGridString(d.admdstCd),
|
||||||
|
sggNm: normalizeGridString(d.sggNm),
|
||||||
|
admdstNm: normalizeGridString(d.admdstNm),
|
||||||
|
levyEvntcsCnt: formatNumber(d.levyEvntcsCnt, "levyEvntcsCnt"),
|
||||||
|
levyAmt: formatNumber(d.levyAmt, "levyAmt"),
|
||||||
|
mltvEqpmEvntcsCnt: formatNumber(d.mltvEqpmEvntcsCnt, "mltvEqpmEvntcsCnt"),
|
||||||
|
mltvEqpmAmt: formatNumber(d.mltvEqpmAmt, "mltvEqpmAmt"),
|
||||||
|
othrCstrnOthrActrCnt: formatNumber(d.othrCstrnOthrActrCnt, "othrCstrnOthrActrCnt"),
|
||||||
|
othrCstrnOthrActrAmt: formatNumber(d.othrCstrnOthrActrAmt, "othrCstrnOthrActrAmt"),
|
||||||
|
rmrk: normalizeGridRmrk(d.rmrk),
|
||||||
|
trgtByWholClctnAmt: formatNumber(d.trgtByWholClctnAmt, "trgtByWholClctnAmt"),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
// 하수도 통계 관리 > 09. 하수도재정
|
// 하수도 통계 관리 > 09. 하수도재정
|
||||||
const SewerageFinanceInp = () => {
|
const SewerageFinanceInp = () => {
|
||||||
const { setMessage: alert } = useAlertStore((state) => state);
|
const { setMessage: alert } = useAlertStore((state) => state);
|
||||||
@@ -541,7 +706,144 @@ const SewerageFinanceInp = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const saveFunc = () => {
|
const saveFunc = () => {
|
||||||
// 저장 로직
|
void (async () => {
|
||||||
|
const tabKey = activeTabRef.current;
|
||||||
|
const { isSettleTab, isChargeTab, isUsageFeeTab, isCauserBurdenTab } =
|
||||||
|
resolveSewerageFinanceTab(tabKey);
|
||||||
|
if (!isSettleTab && !isChargeTab && !isUsageFeeTab && !isCauserBurdenTab) {
|
||||||
|
alert("저장할 수 없는 탭입니다.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lastSearchedValues || !searchParamRef.current) {
|
||||||
|
alert("먼저 조회를 진행해주세요.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buildGugunOkForToolbar(lastSearchedValues)) {
|
||||||
|
alert("시군구를 선택해주세요.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await confirm("저장 하시겠습니까?"))) return;
|
||||||
|
|
||||||
|
const currentData = getTabGridRows(tabKey);
|
||||||
|
if (!currentData.length) {
|
||||||
|
alert("저장할 데이터가 없습니다.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseRequest = {
|
||||||
|
statsYr: lastSearchedValues.year ?? "",
|
||||||
|
ctpvNm: lastSearchedValues.sido ?? "",
|
||||||
|
sggNm:
|
||||||
|
lastSearchedValues.gugun === "ALL"
|
||||||
|
? ""
|
||||||
|
: (lastSearchedValues.gugun ?? ""),
|
||||||
|
sewerBzmnCd: lastSearchedValues.bsnmCd ?? "",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const userInfo = await getUserInfo();
|
||||||
|
|
||||||
|
if (isSettleTab) {
|
||||||
|
const param: SewerageFinanceSettleSaveRequest = {
|
||||||
|
...baseRequest,
|
||||||
|
userId: userInfo.userUnqId,
|
||||||
|
saveList: buildSewerageFinanceSettleSaveList(currentData),
|
||||||
|
...(isAdminInfo ? { superAdmin: "superAdmin" } : {}),
|
||||||
|
};
|
||||||
|
const response =
|
||||||
|
await statisticsInputSewerageFinanceApi.saveSewerageFinanceSettle(param);
|
||||||
|
if (response.status === "success") {
|
||||||
|
await loadActiveTabData(
|
||||||
|
tabKey,
|
||||||
|
searchParamRef.current,
|
||||||
|
lastSearchedValues,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
alert("저장되었습니다.");
|
||||||
|
} else {
|
||||||
|
alert(response.message || "데이터 저장 중 오류가 발생했습니다.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isChargeTab) {
|
||||||
|
const param: SewerageChargeSaveRequest = {
|
||||||
|
...baseRequest,
|
||||||
|
userId: userInfo.userUnqId,
|
||||||
|
saveList: buildSewerageChargeSaveList(currentData),
|
||||||
|
...(isAdminInfo ? { superAdmin: "superAdmin" } : {}),
|
||||||
|
};
|
||||||
|
const response =
|
||||||
|
await statisticsInputSewerageFinanceApi.saveSewerageCharge(param);
|
||||||
|
if (response.status === "success") {
|
||||||
|
await loadActiveTabData(
|
||||||
|
tabKey,
|
||||||
|
searchParamRef.current,
|
||||||
|
lastSearchedValues,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
alert("저장되었습니다.");
|
||||||
|
} else {
|
||||||
|
alert(response.message || "데이터 저장 중 오류가 발생했습니다.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUsageFeeTab) {
|
||||||
|
const param: SewerageUsageFeeSaveRequest = {
|
||||||
|
...baseRequest,
|
||||||
|
userId: userInfo.userUnqId,
|
||||||
|
saveList: buildSewerageUsageFeeSaveList(currentData),
|
||||||
|
...(isAdminInfo ? { superAdmin: "superAdmin" } : {}),
|
||||||
|
};
|
||||||
|
const response =
|
||||||
|
await statisticsInputSewerageFinanceApi.saveSewerageUsageFee(param);
|
||||||
|
if (response.status === "success") {
|
||||||
|
await loadActiveTabData(
|
||||||
|
tabKey,
|
||||||
|
searchParamRef.current,
|
||||||
|
lastSearchedValues,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
alert("저장되었습니다.");
|
||||||
|
} else {
|
||||||
|
alert(response.message || "데이터 저장 중 오류가 발생했습니다.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const param: CauserBurdenSaveRequest = {
|
||||||
|
...baseRequest,
|
||||||
|
userId: userInfo.userUnqId,
|
||||||
|
saveList: buildCauserBurdenSaveList(currentData),
|
||||||
|
...(isAdminInfo ? { superAdmin: "superAdmin" } : {}),
|
||||||
|
};
|
||||||
|
const response = await statisticsInputSewerageFinanceApi.saveCauserBurden(param);
|
||||||
|
if (response.status === "success") {
|
||||||
|
await loadActiveTabData(
|
||||||
|
tabKey,
|
||||||
|
searchParamRef.current,
|
||||||
|
lastSearchedValues,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
alert("저장되었습니다.");
|
||||||
|
} else {
|
||||||
|
alert(response.message || "데이터 저장 중 오류가 발생했습니다.");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
alert("데이터 저장 중 오류가 발생했습니다.");
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
};
|
};
|
||||||
|
|
||||||
const openVerificationHistoryDialog = () => {
|
const openVerificationHistoryDialog = () => {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export const SewerageChargeInpColumn = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 비고
|
// 비고
|
||||||
{ name: 'rmrk', fieldName: '비고', header: { text: '비고' } },
|
{ name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } },
|
||||||
|
|
||||||
// hidden
|
// hidden
|
||||||
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
|
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
|
||||||
|
|||||||
+7
-7
@@ -59,37 +59,37 @@ export const SewerageUsageFeeInpColumn = {
|
|||||||
// 가정용
|
// 가정용
|
||||||
{ name: 'hshusLevyAmt', fieldName: 'hshusLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'hshusLevyAmt', fieldName: 'hshusLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'hshusLevyQnt', fieldName: 'hshusLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'hshusLevyQnt', fieldName: 'hshusLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'hshusUntprcAmt', fieldName: 'hshusUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'hshusUntprcAmt', fieldName: 'hshusUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
|
||||||
|
|
||||||
// 업무용
|
// 업무용
|
||||||
{ name: 'taskFrLevyAmt', fieldName: 'taskFrLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'taskFrLevyAmt', fieldName: 'taskFrLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'taskFrLevyQnt', fieldName: 'taskFrLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'taskFrLevyQnt', fieldName: 'taskFrLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'taskFrUntprcAmt', fieldName: 'taskFrUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'taskFrUntprcAmt', fieldName: 'taskFrUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
|
||||||
|
|
||||||
// 영업용(일반용)
|
// 영업용(일반용)
|
||||||
{ name: 'fbuLevyAmt', fieldName: 'fbuLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'fbuLevyAmt', fieldName: 'fbuLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'fbuLevyQnt', fieldName: 'fbuLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'fbuLevyQnt', fieldName: 'fbuLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'fbuUntprcAmt', fieldName: 'fbuUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'fbuUntprcAmt', fieldName: 'fbuUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
|
||||||
|
|
||||||
// 욕탕1종(대중탕용)
|
// 욕탕1종(대중탕용)
|
||||||
{ name: 'bthhsFrSpcs1LevyAmt', fieldName: 'bthhsFrSpcs1LevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'bthhsFrSpcs1LevyAmt', fieldName: 'bthhsFrSpcs1LevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'bthhsFrSpcs1LevyQnt', fieldName: 'bthhsFrSpcs1LevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'bthhsFrSpcs1LevyQnt', fieldName: 'bthhsFrSpcs1LevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'bthhsFrSpcs1UntprcAmt', fieldName: 'bthhsFrSpcs1UntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'bthhsFrSpcs1UntprcAmt', fieldName: 'bthhsFrSpcs1UntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
|
||||||
|
|
||||||
// 욕탕2종
|
// 욕탕2종
|
||||||
{ name: 'bthhsFrSpcs2LevyAmt', fieldName: 'bthhsFrSpcs2LevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'bthhsFrSpcs2LevyAmt', fieldName: 'bthhsFrSpcs2LevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'bthhsFrSpcs2LevyQnt', fieldName: 'bthhsFrSpcs2LevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'bthhsFrSpcs2LevyQnt', fieldName: 'bthhsFrSpcs2LevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'bthhsFrSpcs2UntprcAmt', fieldName: 'bthhsFrSpcs2UntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'bthhsFrSpcs2UntprcAmt', fieldName: 'bthhsFrSpcs2UntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
|
||||||
|
|
||||||
// 산업 및 공업용
|
// 산업 및 공업용
|
||||||
{ name: 'induLevyAmt', fieldName: 'induLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'induLevyAmt', fieldName: 'induLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'induLevyQnt', fieldName: 'induLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'induLevyQnt', fieldName: 'induLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'induUntprcAmt', fieldName: 'induUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'induUntprcAmt', fieldName: 'induUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
|
||||||
|
|
||||||
// 기타
|
// 기타
|
||||||
{ name: 'etcLevyAmt', fieldName: 'etcLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'etcLevyAmt', fieldName: 'etcLevyAmt', header: { text: '(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'etcLevyQnt', fieldName: 'etcLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'etcLevyQnt', fieldName: 'etcLevyQnt', header: { text: '(천톤)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
||||||
{ name: 'etcLevyUntprcAmt', fieldName: 'etcLevyUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
|
{ name: 'etcLevyUntprcAmt', fieldName: 'etcLevyUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
|
||||||
|
|
||||||
// 비고
|
// 비고
|
||||||
{ name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } },
|
{ name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } },
|
||||||
|
|||||||
+52
@@ -5,12 +5,20 @@ import { ENDPOINT } from "@/shared/config";
|
|||||||
import {
|
import {
|
||||||
type CauserBurdenApiResponse,
|
type CauserBurdenApiResponse,
|
||||||
type CauserBurdenRequestParams,
|
type CauserBurdenRequestParams,
|
||||||
|
type CauserBurdenSaveRequest,
|
||||||
|
type CauserBurdenSaveResponse,
|
||||||
type SewerageChargeApiResponse,
|
type SewerageChargeApiResponse,
|
||||||
type SewerageChargeRequestParams,
|
type SewerageChargeRequestParams,
|
||||||
|
type SewerageChargeSaveRequest,
|
||||||
|
type SewerageChargeSaveResponse,
|
||||||
type SewerageFinanceSettleApiResponse,
|
type SewerageFinanceSettleApiResponse,
|
||||||
type SewerageFinanceSettleRequestParams,
|
type SewerageFinanceSettleRequestParams,
|
||||||
|
type SewerageFinanceSettleSaveRequest,
|
||||||
|
type SewerageFinanceSettleSaveResponse,
|
||||||
type SewerageUsageFeeApiResponse,
|
type SewerageUsageFeeApiResponse,
|
||||||
type SewerageUsageFeeRequestParams,
|
type SewerageUsageFeeRequestParams,
|
||||||
|
type SewerageUsageFeeSaveRequest,
|
||||||
|
type SewerageUsageFeeSaveResponse,
|
||||||
type StatisticsInputSewerageFinanceService,
|
type StatisticsInputSewerageFinanceService,
|
||||||
} from "../../model/input/statistics-input-sewerage-finance-interface";
|
} from "../../model/input/statistics-input-sewerage-finance-interface";
|
||||||
|
|
||||||
@@ -30,6 +38,17 @@ export class StatisticsInputSewerageFinanceApiService
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 하수도재정 결산 저장 — ST00090001 */
|
||||||
|
public async saveSewerageFinanceSettle(
|
||||||
|
request: SewerageFinanceSettleSaveRequest,
|
||||||
|
): Promise<SewerageFinanceSettleSaveResponse> {
|
||||||
|
const response = await stClient.put<SewerageFinanceSettleSaveResponse>(
|
||||||
|
`${BASE}/settle/save`,
|
||||||
|
request,
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
/** 하수도 요금 조회 — ST00090002 */
|
/** 하수도 요금 조회 — ST00090002 */
|
||||||
public async getSewerageChargeList(
|
public async getSewerageChargeList(
|
||||||
params: SewerageChargeRequestParams,
|
params: SewerageChargeRequestParams,
|
||||||
@@ -41,6 +60,17 @@ export class StatisticsInputSewerageFinanceApiService
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 하수도 요금 저장 — ST00090002 */
|
||||||
|
public async saveSewerageCharge(
|
||||||
|
request: SewerageChargeSaveRequest,
|
||||||
|
): Promise<SewerageChargeSaveResponse> {
|
||||||
|
const response = await stClient.put<SewerageChargeSaveResponse>(
|
||||||
|
`${BASE}/charge/save`,
|
||||||
|
request,
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
/** 하수도 사용료 조회 — ST00090003 */
|
/** 하수도 사용료 조회 — ST00090003 */
|
||||||
public async getSewerageUsageFeeList(
|
public async getSewerageUsageFeeList(
|
||||||
params: SewerageUsageFeeRequestParams,
|
params: SewerageUsageFeeRequestParams,
|
||||||
@@ -52,6 +82,17 @@ export class StatisticsInputSewerageFinanceApiService
|
|||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 하수도 사용료 저장 — ST00090003 */
|
||||||
|
public async saveSewerageUsageFee(
|
||||||
|
request: SewerageUsageFeeSaveRequest,
|
||||||
|
): Promise<SewerageUsageFeeSaveResponse> {
|
||||||
|
const response = await stClient.put<SewerageUsageFeeSaveResponse>(
|
||||||
|
`${BASE}/usage-fee/save`,
|
||||||
|
request,
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
/** 원인자 부담금 조회 — ST00090004 */
|
/** 원인자 부담금 조회 — ST00090004 */
|
||||||
public async getCauserBurdenList(
|
public async getCauserBurdenList(
|
||||||
params: CauserBurdenRequestParams,
|
params: CauserBurdenRequestParams,
|
||||||
@@ -62,6 +103,17 @@ export class StatisticsInputSewerageFinanceApiService
|
|||||||
);
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 원인자 부담금 저장 — ST00090004 */
|
||||||
|
public async saveCauserBurden(
|
||||||
|
request: CauserBurdenSaveRequest,
|
||||||
|
): Promise<CauserBurdenSaveResponse> {
|
||||||
|
const response = await stClient.put<CauserBurdenSaveResponse>(
|
||||||
|
`${BASE}/causer-burden/save`,
|
||||||
|
request,
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const statisticsInputSewerageFinanceApi =
|
export const statisticsInputSewerageFinanceApi =
|
||||||
|
|||||||
+189
@@ -86,6 +86,63 @@ export interface SewerageFinanceSettleRequestParams {
|
|||||||
mode?: string;
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ST00090001 저장 API `saveList[]` 한 행.
|
||||||
|
* `SewerageFinanceSettleInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 요청 `ctpvNm` 시도명).
|
||||||
|
*/
|
||||||
|
export interface SewerageFinanceSettleSaveItem {
|
||||||
|
admdstCd: string;
|
||||||
|
sggNm: string;
|
||||||
|
admdstNm: string;
|
||||||
|
cnterGovSprtAmt: number;
|
||||||
|
mctpvLcexpAmt: number;
|
||||||
|
wareaSggLclAmt: number;
|
||||||
|
sewerUseAmt: number;
|
||||||
|
orgprBrdnAmt: number;
|
||||||
|
etcIncmAmt: number;
|
||||||
|
crfwAmt: number;
|
||||||
|
lbltAmt: number;
|
||||||
|
tmplntFcltAmt: number;
|
||||||
|
tmplntMendngAmt: number;
|
||||||
|
tmplntOperKeepAmt: number;
|
||||||
|
tmplntEtcAmt: number;
|
||||||
|
swagePplFcltAmt: number;
|
||||||
|
swagePplMendngAmt: number;
|
||||||
|
swagePplOperKeepAmt: number;
|
||||||
|
swagePplEtcAmt: number;
|
||||||
|
swageImpdFcltAmt: number;
|
||||||
|
swageImpdMendngAmt: number;
|
||||||
|
swageImpdOperKeepAmt: number;
|
||||||
|
swageImpdFcltEtcAmt: number;
|
||||||
|
etcAcdntCrfwAmt: number;
|
||||||
|
etcNrcpAmt: number;
|
||||||
|
etcAmt: number;
|
||||||
|
rmrk: string | null;
|
||||||
|
fnnByWholPjtcoAmt: number;
|
||||||
|
usgByWholPjtcoAmt: number;
|
||||||
|
tmplntWholAmt: number;
|
||||||
|
wholSwagePplAmt: number;
|
||||||
|
wholSwageImpdFcltAmt: number;
|
||||||
|
etcWholAmt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ST00090001 저장 API 요청 */
|
||||||
|
export interface SewerageFinanceSettleSaveRequest {
|
||||||
|
statsYr: string;
|
||||||
|
ctpvNm: string;
|
||||||
|
sggNm: string;
|
||||||
|
sewerBzmnCd: string;
|
||||||
|
userId: string;
|
||||||
|
superAdmin?: string;
|
||||||
|
saveList: SewerageFinanceSettleSaveItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SewerageFinanceSettleSaveResponse {
|
||||||
|
status: string;
|
||||||
|
message?: string;
|
||||||
|
data?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/** 하수도 요금(ST00090002) — `SewerageChargeInpColumn.tabKey` */
|
/** 하수도 요금(ST00090002) — `SewerageChargeInpColumn.tabKey` */
|
||||||
export const SEWERAGE_CHARGE_STATS_CD = "ST00090002" as const;
|
export const SEWERAGE_CHARGE_STATS_CD = "ST00090002" as const;
|
||||||
|
|
||||||
@@ -135,6 +192,40 @@ export interface SewerageChargeRequestParams {
|
|||||||
mode?: string;
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ST00090002 저장 API `saveList[]` 한 행.
|
||||||
|
* `SewerageChargeInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 요청 `ctpvNm` 시도명).
|
||||||
|
*/
|
||||||
|
export interface SewerageChargeSaveItem {
|
||||||
|
admdstCd: string;
|
||||||
|
sggNm: string;
|
||||||
|
admdstNm: string;
|
||||||
|
anlLevyQnt: number;
|
||||||
|
levyAmt: number;
|
||||||
|
grssPrmcoAmt: number;
|
||||||
|
rmrk: string | null;
|
||||||
|
avgUntprcAmt: number;
|
||||||
|
grssUnitPrmcoAmt: number;
|
||||||
|
rlztnRt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ST00090002 저장 API 요청 */
|
||||||
|
export interface SewerageChargeSaveRequest {
|
||||||
|
statsYr: string;
|
||||||
|
ctpvNm: string;
|
||||||
|
sggNm: string;
|
||||||
|
sewerBzmnCd: string;
|
||||||
|
userId: string;
|
||||||
|
superAdmin?: string;
|
||||||
|
saveList: SewerageChargeSaveItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SewerageChargeSaveResponse {
|
||||||
|
status: string;
|
||||||
|
message?: string;
|
||||||
|
data?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/** 하수도 사용료(ST00090003) — `SewerageUsageFeeInpColumn.tabKey` */
|
/** 하수도 사용료(ST00090003) — `SewerageUsageFeeInpColumn.tabKey` */
|
||||||
export const SEWERAGE_USAGE_FEE_STATS_CD = "ST00090003" as const;
|
export const SEWERAGE_USAGE_FEE_STATS_CD = "ST00090003" as const;
|
||||||
|
|
||||||
@@ -201,6 +292,57 @@ export interface SewerageUsageFeeRequestParams {
|
|||||||
mode?: string;
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ST00090003 저장 API `saveList[]` 한 행.
|
||||||
|
* `SewerageUsageFeeInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 요청 `ctpvNm` 시도명).
|
||||||
|
*/
|
||||||
|
export interface SewerageUsageFeeSaveItem {
|
||||||
|
admdstCd: string;
|
||||||
|
sggNm: string;
|
||||||
|
admdstNm: string;
|
||||||
|
hshusLevyAmt: number;
|
||||||
|
hshusLevyQnt: number;
|
||||||
|
hshusUntprcAmt: number;
|
||||||
|
taskFrLevyAmt: number;
|
||||||
|
taskFrLevyQnt: number;
|
||||||
|
taskFrUntprcAmt: number;
|
||||||
|
fbuLevyAmt: number;
|
||||||
|
fbuLevyQnt: number;
|
||||||
|
fbuUntprcAmt: number;
|
||||||
|
bthhsFrSpcs1LevyAmt: number;
|
||||||
|
bthhsFrSpcs1LevyQnt: number;
|
||||||
|
bthhsFrSpcs1UntprcAmt: number;
|
||||||
|
bthhsFrSpcs2LevyAmt: number;
|
||||||
|
bthhsFrSpcs2LevyQnt: number;
|
||||||
|
bthhsFrSpcs2UntprcAmt: number;
|
||||||
|
induLevyAmt: number;
|
||||||
|
induLevyQnt: number;
|
||||||
|
induUntprcAmt: number;
|
||||||
|
etcLevyAmt: number;
|
||||||
|
etcLevyQnt: number;
|
||||||
|
etcLevyUntprcAmt: number;
|
||||||
|
rmrk: string | null;
|
||||||
|
levyAmt: number;
|
||||||
|
levyQnt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ST00090003 저장 API 요청 */
|
||||||
|
export interface SewerageUsageFeeSaveRequest {
|
||||||
|
statsYr: string;
|
||||||
|
ctpvNm: string;
|
||||||
|
sggNm: string;
|
||||||
|
sewerBzmnCd: string;
|
||||||
|
userId: string;
|
||||||
|
superAdmin?: string;
|
||||||
|
saveList: SewerageUsageFeeSaveItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SewerageUsageFeeSaveResponse {
|
||||||
|
status: string;
|
||||||
|
message?: string;
|
||||||
|
data?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/** 원인자 부담금(ST00090004) — `CauserBurdenInpColumn.tabKey` */
|
/** 원인자 부담금(ST00090004) — `CauserBurdenInpColumn.tabKey` */
|
||||||
export const CAUSER_BURDEN_STATS_CD = "ST00090004" as const;
|
export const CAUSER_BURDEN_STATS_CD = "ST00090004" as const;
|
||||||
|
|
||||||
@@ -252,6 +394,41 @@ export interface CauserBurdenRequestParams {
|
|||||||
mode?: string;
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ST00090004 저장 API `saveList[]` 한 행.
|
||||||
|
* `CauserBurdenInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 요청 `ctpvNm` 시도명).
|
||||||
|
*/
|
||||||
|
export interface CauserBurdenSaveItem {
|
||||||
|
admdstCd: string;
|
||||||
|
sggNm: string;
|
||||||
|
admdstNm: string;
|
||||||
|
levyEvntcsCnt: number;
|
||||||
|
levyAmt: number;
|
||||||
|
mltvEqpmEvntcsCnt: number;
|
||||||
|
mltvEqpmAmt: number;
|
||||||
|
othrCstrnOthrActrCnt: number;
|
||||||
|
othrCstrnOthrActrAmt: number;
|
||||||
|
rmrk: string | null;
|
||||||
|
trgtByWholClctnAmt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ST00090004 저장 API 요청 */
|
||||||
|
export interface CauserBurdenSaveRequest {
|
||||||
|
statsYr: string;
|
||||||
|
ctpvNm: string;
|
||||||
|
sggNm: string;
|
||||||
|
sewerBzmnCd: string;
|
||||||
|
userId: string;
|
||||||
|
superAdmin?: string;
|
||||||
|
saveList: CauserBurdenSaveItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CauserBurdenSaveResponse {
|
||||||
|
status: string;
|
||||||
|
message?: string;
|
||||||
|
data?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/** 하수도재정 조회 공통 요청 파라미터 */
|
/** 하수도재정 조회 공통 요청 파라미터 */
|
||||||
export interface SewerageFinanceRequestParams {
|
export interface SewerageFinanceRequestParams {
|
||||||
ctpvNm?: string;
|
ctpvNm?: string;
|
||||||
@@ -265,13 +442,25 @@ export interface StatisticsInputSewerageFinanceService {
|
|||||||
getSewerageFinanceSettleList(
|
getSewerageFinanceSettleList(
|
||||||
params: SewerageFinanceSettleRequestParams,
|
params: SewerageFinanceSettleRequestParams,
|
||||||
): Promise<SewerageFinanceSettleApiResponse>;
|
): Promise<SewerageFinanceSettleApiResponse>;
|
||||||
|
saveSewerageFinanceSettle(
|
||||||
|
request: SewerageFinanceSettleSaveRequest,
|
||||||
|
): Promise<SewerageFinanceSettleSaveResponse>;
|
||||||
getSewerageChargeList(
|
getSewerageChargeList(
|
||||||
params: SewerageChargeRequestParams,
|
params: SewerageChargeRequestParams,
|
||||||
): Promise<SewerageChargeApiResponse>;
|
): Promise<SewerageChargeApiResponse>;
|
||||||
|
saveSewerageCharge(
|
||||||
|
request: SewerageChargeSaveRequest,
|
||||||
|
): Promise<SewerageChargeSaveResponse>;
|
||||||
getSewerageUsageFeeList(
|
getSewerageUsageFeeList(
|
||||||
params: SewerageUsageFeeRequestParams,
|
params: SewerageUsageFeeRequestParams,
|
||||||
): Promise<SewerageUsageFeeApiResponse>;
|
): Promise<SewerageUsageFeeApiResponse>;
|
||||||
|
saveSewerageUsageFee(
|
||||||
|
request: SewerageUsageFeeSaveRequest,
|
||||||
|
): Promise<SewerageUsageFeeSaveResponse>;
|
||||||
getCauserBurdenList(
|
getCauserBurdenList(
|
||||||
params: CauserBurdenRequestParams,
|
params: CauserBurdenRequestParams,
|
||||||
): Promise<CauserBurdenApiResponse>;
|
): Promise<CauserBurdenApiResponse>;
|
||||||
|
saveCauserBurden(
|
||||||
|
request: CauserBurdenSaveRequest,
|
||||||
|
): Promise<CauserBurdenSaveResponse>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ import { SkeletonPage } from "@/shared/ui/skeleton-page";
|
|||||||
import "@rsone/components/index.css";
|
import "@rsone/components/index.css";
|
||||||
|
|
||||||
import Dashboard from "@/components/statistics/Dashboard";
|
import Dashboard from "@/components/statistics/Dashboard";
|
||||||
|
import { isBbsNoticeMenu } from "@/shared/lib/bbs-notice-menu";
|
||||||
|
import {
|
||||||
|
parseStatisticsMenuUrlPath,
|
||||||
|
resolveStatisticsCategory,
|
||||||
|
} from "@/shared/lib/statistics-menu-url";
|
||||||
import { isVerificationSelectionReportMenu } from "@/shared/lib/verification-selection-report";
|
import { isVerificationSelectionReportMenu } from "@/shared/lib/verification-selection-report";
|
||||||
import { useAdminStore } from "@/store/admin-store";
|
import { useAdminStore } from "@/store/admin-store";
|
||||||
import { useTabStore } from "@/store/tab-store";
|
import { useTabStore } from "@/store/tab-store";
|
||||||
@@ -18,7 +23,9 @@ const StatisticsPage = () => {
|
|||||||
const tabsForBody = useMemo(
|
const tabsForBody = useMemo(
|
||||||
() =>
|
() =>
|
||||||
tabs.filter(
|
tabs.filter(
|
||||||
(tab) => !isVerificationSelectionReportMenu(tab.menuItem),
|
(tab) =>
|
||||||
|
!isVerificationSelectionReportMenu(tab.menuItem) &&
|
||||||
|
!isBbsNoticeMenu(tab.menuItem),
|
||||||
),
|
),
|
||||||
[tabs],
|
[tabs],
|
||||||
);
|
);
|
||||||
@@ -57,13 +64,17 @@ const StatisticsPage = () => {
|
|||||||
{tabsForBody.map((tab) => {
|
{tabsForBody.map((tab) => {
|
||||||
// 렌더링 시점에 컴포넌트가 없으면 바로 로드
|
// 렌더링 시점에 컴포넌트가 없으면 바로 로드
|
||||||
if (!componentCache.current.has(tab.id)) {
|
if (!componentCache.current.has(tab.id)) {
|
||||||
const componentName = tab.urlPath;
|
const { componentName } = parseStatisticsMenuUrlPath(tab.urlPath);
|
||||||
const parentComponentName = tab.parentEngNm;
|
const category = resolveStatisticsCategory(
|
||||||
|
tab.urlPath,
|
||||||
|
tab.parentEngNm,
|
||||||
|
);
|
||||||
|
const resolvedComponentName = componentName || tab.urlPath;
|
||||||
|
|
||||||
const DynamicComponent = dynamic(
|
const DynamicComponent = dynamic(
|
||||||
() =>
|
() =>
|
||||||
import(
|
import(
|
||||||
`@/components/statistics${parentComponentName ? `/${parentComponentName}` : ""}/${componentName}`
|
`@/components/statistics/${category}/${resolvedComponentName}`
|
||||||
),
|
),
|
||||||
{ ssr: false, loading: () => <SkeletonPage /> },
|
{ ssr: false, loading: () => <SkeletonPage /> },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import type { MenuItem } from "@/entities/menu";
|
||||||
|
|
||||||
|
export const BBS_NOTICE_MENU_MARKER = "bbsnotice";
|
||||||
|
|
||||||
|
export function isBbsNoticeMenu(item: MenuItem): boolean {
|
||||||
|
const marker = BBS_NOTICE_MENU_MARKER;
|
||||||
|
return (
|
||||||
|
item.urlPath?.toLowerCase().includes(marker) ||
|
||||||
|
item.menuEngNm?.toLowerCase().includes(marker) ||
|
||||||
|
item.menuPath?.toLowerCase().includes(marker)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import type { MenuItem } from "@/entities/menu";
|
||||||
|
|
||||||
|
export type ParsedStatisticsMenuUrl = {
|
||||||
|
categoryFromPath: string | null;
|
||||||
|
componentName: string | null;
|
||||||
|
rawUrlPath: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 메뉴 `urlPath`에서 통계 화면 카테고리·컴포넌트명을 파싱합니다. */
|
||||||
|
export function parseStatisticsMenuUrlPath(urlPath: string): ParsedStatisticsMenuUrl {
|
||||||
|
const trimmed = (urlPath ?? "").trim();
|
||||||
|
if (!trimmed) {
|
||||||
|
return { categoryFromPath: null, componentName: null, rawUrlPath: trimmed };
|
||||||
|
}
|
||||||
|
|
||||||
|
let pathPart = trimmed;
|
||||||
|
let queryString = "";
|
||||||
|
const queryIndex = trimmed.indexOf("?");
|
||||||
|
if (queryIndex >= 0) {
|
||||||
|
pathPart = trimmed.slice(0, queryIndex);
|
||||||
|
queryString = trimmed.slice(queryIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabParam = new URLSearchParams(queryString).get("tab")?.trim() || null;
|
||||||
|
const segments = pathPart.replace(/^\/+/, "").split("/").filter(Boolean);
|
||||||
|
|
||||||
|
let categoryFromPath: string | null = null;
|
||||||
|
if (segments[0] === "statistics" && segments.length >= 2) {
|
||||||
|
categoryFromPath = segments[1] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let componentName = tabParam;
|
||||||
|
if (!componentName) {
|
||||||
|
if (!pathPart.includes("/") && !queryString) {
|
||||||
|
componentName = trimmed;
|
||||||
|
} else if (segments.length === 1 && segments[0] !== "statistics") {
|
||||||
|
componentName = segments[0] ?? null;
|
||||||
|
} else if (segments[0] === "statistics" && segments.length >= 3) {
|
||||||
|
componentName = segments[segments.length - 1] ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { categoryFromPath, componentName, rawUrlPath: trimmed };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 동적 import용 카테고리 폴더명 (`input`, `review` 등) */
|
||||||
|
export function resolveStatisticsCategory(urlPath: string, parentEngNm: string): string {
|
||||||
|
const { categoryFromPath } = parseStatisticsMenuUrlPath(urlPath);
|
||||||
|
return categoryFromPath || parentEngNm || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 탭 ID·URL `?tab=` 값 — 컴포넌트 파일명(확장자 제외) */
|
||||||
|
export function resolveStatisticsTabId(urlPath: string): string {
|
||||||
|
const { componentName, rawUrlPath } = parseStatisticsMenuUrlPath(urlPath);
|
||||||
|
return componentName || rawUrlPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** `@/components/statistics/{category}/{Component}` 경로 */
|
||||||
|
export function buildStatisticsComponentImportPath(
|
||||||
|
urlPath: string,
|
||||||
|
parentEngNm: string,
|
||||||
|
): string {
|
||||||
|
const { componentName } = parseStatisticsMenuUrlPath(urlPath);
|
||||||
|
const category = resolveStatisticsCategory(urlPath, parentEngNm);
|
||||||
|
const name = componentName || urlPath;
|
||||||
|
return `@/components/statistics/${category}/${name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function menuMatchesStatisticsTabId(menu: MenuItem, tabId: string): boolean {
|
||||||
|
if (!tabId) return false;
|
||||||
|
if (menu.urlPath === tabId) return true;
|
||||||
|
return resolveStatisticsTabId(menu.urlPath) === tabId;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { MenuItem } from "@/entities/menu";
|
import type { MenuItem } from "@/entities/menu";
|
||||||
import type { SearchFormValues } from "@/components/type/SearchForm.type";
|
import type { SearchFormValues } from "@/components/type/SearchForm.type";
|
||||||
import { doNameList } from "@/components/util/column/input/DoList";
|
import { doNameList } from "@/components/util/column/input/DoList";
|
||||||
|
import { menuMatchesStatisticsTabId } from "@/shared/lib/statistics-menu-url";
|
||||||
import {
|
import {
|
||||||
SEWAGE_PIPE_INP_TAB_KEYS,
|
SEWAGE_PIPE_INP_TAB_KEYS,
|
||||||
SEWAGE_PIPE_MAINTAIN_INP_TAB_KEYS,
|
SEWAGE_PIPE_MAINTAIN_INP_TAB_KEYS,
|
||||||
@@ -97,7 +98,7 @@ export function findMenuItemByUrlPath(
|
|||||||
urlPath: string,
|
urlPath: string,
|
||||||
): MenuItem | null {
|
): MenuItem | null {
|
||||||
for (const item of menus) {
|
for (const item of menus) {
|
||||||
if (item.urlPath === urlPath) return item;
|
if (menuMatchesStatisticsTabId(item, urlPath)) return item;
|
||||||
if (item.children?.length) {
|
if (item.children?.length) {
|
||||||
const found = findMenuItemByUrlPath(item.children, urlPath);
|
const found = findMenuItemByUrlPath(item.children, urlPath);
|
||||||
if (found) return found;
|
if (found) return found;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useEffect, useRef } from "react";
|
|||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
import type { MenuItem } from "@/entities/menu";
|
import type { MenuItem } from "@/entities/menu";
|
||||||
|
import { isBbsNoticeMenu } from "@/shared/lib/bbs-notice-menu";
|
||||||
import { findMenuItemByUrlPath } from "@/shared/lib/stats-cd-input-navigation";
|
import { findMenuItemByUrlPath } from "@/shared/lib/stats-cd-input-navigation";
|
||||||
import { getTabStoreState } from "@/store/tab-store";
|
import { getTabStoreState } from "@/store/tab-store";
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ export function useStatisticsTabUrlSync({
|
|||||||
if (getTabStoreState().activeTabId === tabParam) return;
|
if (getTabStoreState().activeTabId === tabParam) return;
|
||||||
|
|
||||||
const menu = findMenuItemByUrlPath(menuList, tabParam);
|
const menu = findMenuItemByUrlPath(menuList, tabParam);
|
||||||
if (!menu) return;
|
if (!menu || isBbsNoticeMenu(menu)) return;
|
||||||
|
|
||||||
setCurrentMenuInfo(menu);
|
setCurrentMenuInfo(menu);
|
||||||
const ok = addTab(menu);
|
const ok = addTab(menu);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { TabBar } from "./tab-bar";
|
|||||||
function StatisticsPageLayout({ children }: { children: React.ReactNode }) {
|
function StatisticsPageLayout({ children }: { children: React.ReactNode }) {
|
||||||
const { activeTabId, tabs } = useTabStore();
|
const { activeTabId, tabs } = useTabStore();
|
||||||
|
|
||||||
const pageTitle = tabs.find((t) => t.menuItem.urlPath === activeTabId);
|
const pageTitle = tabs.find((t) => t.id === activeTabId);
|
||||||
|
|
||||||
const menuPaths = pageTitle?.path?.split(">").map((path) => path.trim());
|
const menuPaths = pageTitle?.path?.split(">").map((path) => path.trim());
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { createJSONStorage, persist } from "zustand/middleware";
|
|||||||
import type { MenuItem } from "@/entities/menu";
|
import type { MenuItem } from "@/entities/menu";
|
||||||
import { MenuAuthorityApi } from "@/entities/menu-authority";
|
import { MenuAuthorityApi } from "@/entities/menu-authority";
|
||||||
import type { PageMenuAuthority } from "@/entities/menu-authority/model/menu-authority-interface";
|
import type { PageMenuAuthority } from "@/entities/menu-authority/model/menu-authority-interface";
|
||||||
|
import { isBbsNoticeMenu } from "@/shared/lib/bbs-notice-menu";
|
||||||
|
import { resolveStatisticsTabId } from "@/shared/lib/statistics-menu-url";
|
||||||
|
|
||||||
export interface Tab {
|
export interface Tab {
|
||||||
id: string; // 고유 ID (urlPath)
|
id: string; // 고유 ID (urlPath)
|
||||||
@@ -101,11 +103,18 @@ function tabForPersist(tab: Tab): Tab {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizePersistedTab(tab: Tab): Tab {
|
||||||
|
const tabId = resolveStatisticsTabId(tab.urlPath || tab.id);
|
||||||
|
return tabId === tab.id ? tab : { ...tab, id: tabId };
|
||||||
|
}
|
||||||
|
|
||||||
function sanitizePersistedTabsAndActive(
|
function sanitizePersistedTabsAndActive(
|
||||||
tabs: Tab[],
|
tabs: Tab[],
|
||||||
activeTabId: string | null,
|
activeTabId: string | null,
|
||||||
): { tabs: Tab[]; activeTabId: string | null } {
|
): { tabs: Tab[]; activeTabId: string | null } {
|
||||||
let nextTabs = Array.isArray(tabs) ? tabs : [];
|
let nextTabs = Array.isArray(tabs)
|
||||||
|
? tabs.filter((tab) => !isBbsNoticeMenu(tab.menuItem)).map(normalizePersistedTab)
|
||||||
|
: [];
|
||||||
if (nextTabs.length > MAX_TABS) nextTabs = nextTabs.slice(0, MAX_TABS);
|
if (nextTabs.length > MAX_TABS) nextTabs = nextTabs.slice(0, MAX_TABS);
|
||||||
|
|
||||||
if (nextTabs.length === 0) {
|
if (nextTabs.length === 0) {
|
||||||
@@ -130,8 +139,12 @@ const useTabStoreHook = create<TabStore>()(
|
|||||||
activeTabId: null,
|
activeTabId: null,
|
||||||
menuList: null,
|
menuList: null,
|
||||||
addTab: (menuItem: MenuItem) => {
|
addTab: (menuItem: MenuItem) => {
|
||||||
|
if (isBbsNoticeMenu(menuItem)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const { tabs, menuList } = get();
|
const { tabs, menuList } = get();
|
||||||
const tabId = menuItem.urlPath || "";
|
const tabId = resolveStatisticsTabId(menuItem.urlPath || "");
|
||||||
|
|
||||||
const existingTab = tabs.find((tab) => tab.id === tabId);
|
const existingTab = tabs.find((tab) => tab.id === tabId);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user