[st] - 입력단 메뉴 작업중

This commit is contained in:
2026-06-15 10:38:33 +09:00
parent 49e42757bc
commit e3eb542e59
43 changed files with 7637 additions and 947 deletions
@@ -43,8 +43,10 @@ function buildFieldsFromColumns(columns: { fieldName: string; valueType?: ValueT
const hasNumeratorDenominator = "numeratorFields" in col.computed && col.computed.numeratorFields.length > 0 && col.computed.denominatorFields.length > 0;
const hasMaxOfFieldAndSum = "baseField" in col.computed && "sumFields" in col.computed && col.computed.sumFields.length > 0;
const hasDifferenceOfSums = "minuendFields" in col.computed && "subtrahendFields" in col.computed && col.computed.minuendFields.length > 0;
const hasHalfSumOfSums = col.computed.type === "halfSumOfSums" && "firstSumFields" in col.computed && "secondSumFields" in col.computed && col.computed.firstSumFields.length > 0 && col.computed.secondSumFields.length > 0;
const hasSumOfTwoHalfSumOfSums = col.computed.type === "sumOfTwoHalfSumOfSums" && "firstHalfSum" in col.computed && "secondHalfSum" in col.computed && col.computed.firstHalfSum.firstSumFields.length > 0 && col.computed.firstHalfSum.secondSumFields.length > 0 && col.computed.secondHalfSum.firstSumFields.length > 0 && col.computed.secondHalfSum.secondSumFields.length > 0;
const hasSumOfMaxGroups = "groups" in col.computed && Array.isArray(col.computed.groups) && col.computed.groups.length > 0;
if (hasFields || hasNumeratorDenominator || hasMaxOfFieldAndSum || hasDifferenceOfSums || hasSumOfMaxGroups) {
if (hasFields || hasNumeratorDenominator || hasMaxOfFieldAndSum || hasDifferenceOfSums || hasHalfSumOfSums || hasSumOfTwoHalfSumOfSums || hasSumOfMaxGroups) {
field.valueCallback = getComputedValueCallback(col.computed) as (prod: unknown, dataRow: number, fieldName: string, fieldNames: string[], values: unknown[]) => number;
}
}
+84 -76
View File
@@ -21,6 +21,7 @@ import type {
import { getComputedValueCallback } from "@/components/util/grid/computedFieldCallbacks";
import {
getExcelImportColumnFieldNames,
prepareGridColumnsForExcelExport,
restoreGridColumnsAfterExcelExport,
shouldPrepareColumnsForExcelExport,
@@ -33,7 +34,7 @@ declare module "realgrid" {
setOptions(options: {
footer?: { visible?: boolean };
summaryMode?: "aggregate" | "statistical" | "none";
checkBar?: { visible?: boolean };
checkBar?: { visible?: boolean; exclusive?: boolean };
}): void;
}
}
@@ -461,8 +462,10 @@ function getDecimalPlacesFromDataFormat(dataFormat?: string): number | null {
if (!dataFormat) return null;
const match = dataFormat.match(/\.(0+|#+)/);
const decimalToken = match?.[1];
if (!decimalToken) return null;
return decimalToken.length;
if (decimalToken) return decimalToken.length;
// #,##0 등 정수 포맷 — 소수부 없음 → 0자리 절삭(내림)
if (/[#0]/.test(dataFormat)) return 0;
return null;
}
function truncateByDecimalPlaces(value: number, decimalPlaces: number): number {
@@ -527,6 +530,20 @@ function buildFieldsFromColumns(
"minuendFields" in col.computed &&
"subtrahendFields" in col.computed &&
col.computed.minuendFields.length > 0;
const hasHalfSumOfSums =
col.computed.type === "halfSumOfSums" &&
"firstSumFields" in col.computed &&
"secondSumFields" in col.computed &&
col.computed.firstSumFields.length > 0 &&
col.computed.secondSumFields.length > 0;
const hasSumOfTwoHalfSumOfSums =
col.computed.type === "sumOfTwoHalfSumOfSums" &&
"firstHalfSum" in col.computed &&
"secondHalfSum" in col.computed &&
col.computed.firstHalfSum.firstSumFields.length > 0 &&
col.computed.firstHalfSum.secondSumFields.length > 0 &&
col.computed.secondHalfSum.firstSumFields.length > 0 &&
col.computed.secondHalfSum.secondSumFields.length > 0;
const hasSumOfMaxGroups =
col.computed.type === "sumOfMaxOfFieldAndSumGroups" &&
"groups" in col.computed &&
@@ -536,13 +553,27 @@ function buildFieldsFromColumns(
col.computed.type === "pumpGrossPpqty" &&
"pumpGroups" in col.computed &&
col.computed.pumpGroups.length > 0;
const hasBodPrcsRt =
col.computed.type === "bodPrcsRt" &&
"inflwField" in col.computed &&
"dschgField" in col.computed;
const hasQuotientRatioPercent =
col.computed.type === "quotientRatioPercent" &&
"numeratorQuotient" in col.computed &&
"denominatorQuotient" in col.computed &&
col.computed.numeratorQuotient.length === 2 &&
col.computed.denominatorQuotient.length === 2;
if (
hasFields ||
hasNumeratorDenominator ||
hasMaxOfFieldAndSum ||
hasDifferenceOfSums ||
hasHalfSumOfSums ||
hasSumOfTwoHalfSumOfSums ||
hasSumOfMaxGroups ||
hasPumpGrossPpqty
hasPumpGrossPpqty ||
hasBodPrcsRt ||
hasQuotientRatioPercent
) {
const computedCallback = getComputedValueCallback(
col.computed,
@@ -629,6 +660,7 @@ const DataGrid = ({
const onItemAllCheckedRef =
useRef<typeof onItemAllChecked>(onItemAllChecked);
const isSyncingChecksFromRowDataRef = useRef(false);
const columnsFieldsSigRef = useRef("");
columnsRef.current = columns;
rowDataRef.current = rowData;
cellStyleCallbackRef.current = cellStyleCallback;
@@ -681,20 +713,6 @@ const DataGrid = ({
.find((s) => s.menuEngNm === activeTabId)?.menuKornNm ||
"export";
// 엑셀 import 시 매칭을 위해 헤더에 fieldName 포함 (예: "합계 (swgeProcZoneInnerSm)")
const originalHeaders: Map<string, string> = 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[],
@@ -788,20 +806,6 @@ const DataGrid = ({
excelExportVisibilitySnapshot,
);
}
// 헤더 원복
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;
@@ -903,36 +907,11 @@ const DataGrid = ({
: headerStartRow;
const dataStartRow = maxHeaderRowIndex + 1;
// 엑셀 컬럼 인덱스 → 그리드 fieldName 매핑
const headerToFieldNameMap = new Map<string, string>();
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);
});
// 엑셀 N번째 열 → 그리드 N번째 fieldName (보내기 컬럼 순서 기준)
const excelColumnFieldNames = getExcelImportColumnFieldNames(
columns,
columnLayout,
);
// 데이터 행 읽기
const dataRows: Record<string, string | number>[] = [];
@@ -950,12 +929,8 @@ const DataGrid = ({
worksheet[
XLSX.utils.encode_cell({ r: row, c: col })
];
const headerName =
headers[colIndex] || `Column${colIndex + 1}`;
// 헤더 텍스트를 fieldName으로 변환
const fieldName =
headerToFieldNameMap.get(headerName) ||
headerName;
const fieldName = excelColumnFieldNames[colIndex];
if (!fieldName) continue;
let cellValue: string | number = "";
if (
@@ -1039,6 +1014,21 @@ const DataGrid = ({
const dataProvider = gridRef.current.dataProvider;
applyDefaultGridEditOptions(gridView as GridViewWithEditOptions);
const columnsFieldsSig = columns.map((c) => c.fieldName).join("\u0001");
if (columnsFieldsSig !== columnsFieldsSigRef.current) {
columnsFieldsSigRef.current = columnsFieldsSig;
const dpForFields = dataProvider as {
setFields?: (f: unknown[]) => void;
setRows?: (r: Record<string, string | number>[]) => void;
};
try {
dpForFields.setFields?.(buildFieldsFromColumns(columns));
dpForFields.setRows?.(rowDataRef.current);
} catch (e) {
console.warn("setFields sync:", e);
}
}
// mergeCells: true인 컬럼이 있으면 onSorting에서 클라이언트 정렬로 처리
const hasMergeCells = columns.some((col) => col.mergeCells === true);
@@ -1105,6 +1095,11 @@ const DataGrid = ({
tooltip: resolveColumnTooltip(column),
}),
);
gv.setColumnProperty?.(
column.name,
"editable",
column.editable !== false,
);
applyColumnListEditorProperties(gv, column);
});
if (columns.some((c) => isDropDownEditorColumn(c))) {
@@ -1152,7 +1147,7 @@ const DataGrid = ({
// 헤더 체크박스 표시 여부 설정
gridView.setOptions({
checkBar: { visible: showHeaderCheckbox },
checkBar: { visible: showHeaderCheckbox, exclusive: false },
rowIndicator: { visible: false },
});
@@ -1758,6 +1753,22 @@ const DataGrid = ({
layout={columnLayout}
rows={rowData}
onRGDataColumnsChanged={(grid) => {
const dp = gridRef.current?.dataProvider as
| {
setFields?: (f: unknown[]) => void;
setRows?: (
r: Record<string, string | number>[],
) => void;
}
| undefined;
try {
dp?.setFields?.(
buildFieldsFromColumns(columnsRef.current),
);
dp?.setRows?.(rowDataRef.current);
} catch (e) {
console.warn("onRGDataColumnsChanged setFields:", e);
}
reapplyListEditorsOnGrid(
grid as GridViewWithSetColumnProperty,
columnsRef.current,
@@ -1797,6 +1808,9 @@ const DataGrid = ({
dataProvider.setFields(
buildFieldsFromColumns(columns),
);
columnsFieldsSigRef.current = columns
.map((c) => c.fieldName)
.join("\u0001");
}
if (dataProvider?.setRows)
dataProvider.setRows(rowData);
@@ -1978,15 +1992,9 @@ const DataGrid = ({
{columns.map((column) => {
const baseStyleName = column.styleName;
const columnReactKey =
column.values?.length &&
isDropDownEditorColumn(column)
? `${column.name}-dropdown-${column.values.length}`
: column.name;
return (
<RGDataColumn
key={columnReactKey}
key={column.name}
name={column.name}
fieldName={column.fieldName}
valueType={
@@ -116,7 +116,7 @@ const getSidoListFetcher = async (): Promise<ApiResponse<SearchCondition>> => {
const getSggAllListFetcher = async (
key: [string, string],
): Promise<ApiResponse<Sgg[]>> => {
return statisticsApi.getSggAllList(key[1]);
return statisticsApi.getSggList(key[1]);
};
type SidoSggFacilityNameSearchFormProps = {
@@ -292,17 +292,12 @@ const SidoSggFacilityNameSearchForm = ({
return;
}
const ctpvNm = String(row.ctpvNm ?? sido);
const sggNm = String(
row.sggNm ?? (gugun !== "ALL" && gugun ? gugun : ""),
);
const params: SeweragePipeFacilityAdminAreaListRequest = {
statsYr: statsYr.trim(),
swtrmtFcltCd,
sewerBzmnCd: initialSearchValues?.bsnmCd || '',
ctpvNm,
...(doNameList.includes(ctpvNm) ? { sggNm } : {}),
ctpvNm: initialSidoValue || '',
...(doNameList.includes(initialSidoValue) ? { sggNm: initialGugunValue } : {}),
};
try {
+11 -49
View File
@@ -17,6 +17,7 @@ import SplitDataGrid from "./SplitDataGrid";
import { getComputedValueCallback } from "@/components/util/grid/computedFieldCallbacks"
import {
getExcelImportColumnFieldNames,
prepareGridColumnsForExcelExport,
restoreGridColumnsAfterExcelExport,
shouldPrepareColumnsForExcelExport,
@@ -222,8 +223,10 @@ function buildFieldsFromColumns(columns: { fieldName: string; valueType?: ValueT
const hasNumeratorDenominator = "numeratorFields" in col.computed && col.computed.numeratorFields.length > 0 && col.computed.denominatorFields.length > 0;
const hasMaxOfFieldAndSum = "baseField" in col.computed && "sumFields" in col.computed && col.computed.sumFields.length > 0;
const hasDifferenceOfSums = "minuendFields" in col.computed && "subtrahendFields" in col.computed && col.computed.minuendFields.length > 0;
const hasHalfSumOfSums = col.computed.type === "halfSumOfSums" && "firstSumFields" in col.computed && "secondSumFields" in col.computed && col.computed.firstSumFields.length > 0 && col.computed.secondSumFields.length > 0;
const hasSumOfTwoHalfSumOfSums = col.computed.type === "sumOfTwoHalfSumOfSums" && "firstHalfSum" in col.computed && "secondHalfSum" in col.computed && col.computed.firstHalfSum.firstSumFields.length > 0 && col.computed.firstHalfSum.secondSumFields.length > 0 && col.computed.secondHalfSum.firstSumFields.length > 0 && col.computed.secondHalfSum.secondSumFields.length > 0;
const hasSumOfMaxGroups = "groups" in col.computed && Array.isArray(col.computed.groups) && col.computed.groups.length > 0;
if (hasFields || hasNumeratorDenominator || hasMaxOfFieldAndSum || hasDifferenceOfSums || hasSumOfMaxGroups) {
if (hasFields || hasNumeratorDenominator || hasMaxOfFieldAndSum || hasDifferenceOfSums || hasHalfSumOfSums || hasSumOfTwoHalfSumOfSums || hasSumOfMaxGroups) {
field.valueCallback = getComputedValueCallback(col.computed) as (prod: unknown, dataRow: number, fieldName: string, fieldNames: string[], values: unknown[]) => number;
}
}
@@ -373,20 +376,6 @@ const TabDataGrid = ({
const columns = columnInfoItem.columns || [];
const columnLayout = columnInfoItem.columnLayout || [];
// 엑셀 import 시 매칭을 위해 헤더에 fieldName 포함 (예: "합계 (swgeProcZoneInnerSm)")
const originalHeaders: Map<string, string> = 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 => {
@@ -452,15 +441,6 @@ const TabDataGrid = ({
if (excelExportVisibilitySnapshot) {
restoreGridColumnsAfterExcelExport(gridView, excelExportVisibilitySnapshot);
}
// 헤더 원복
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;
@@ -546,29 +526,12 @@ const TabDataGrid = ({
const maxHeaderRowIndex = headerRowIndexes.length > 0 ? Math.max(...headerRowIndexes) : headerStartRow;
const dataStartRow = maxHeaderRowIndex + 1;
// 엑셀 컬럼 인덱스 → 그리드 fieldName 매핑
const headerToFieldNameMap = new Map<string, string>();
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 columnLayout = columnInfoItem.columnLayout || [];
const excelColumnFieldNames = getExcelImportColumnFieldNames(
columns,
columnLayout,
);
// 데이터 행 읽기
const dataRows: Record<string, string | number>[] = [];
@@ -579,9 +542,8 @@ const TabDataGrid = ({
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;
const fieldName = excelColumnFieldNames[colIndex];
if (!fieldName) continue;
let cellValue: string | number = '';
if (cell && cell.v !== undefined && cell.v !== null) {
@@ -181,6 +181,8 @@ export interface VerificationResultHistoryDialogProps {
} | null;
title?: string;
emptyMessage?: string;
/** 예외 제출 취소 API 성공 후 부모(입력 화면)에서 메인 데이터를 다시 조회할 때 사용 */
onExceptionResetSubmitted?: () => void | Promise<void>;
}
export function VerificationResultHistoryDialog({
@@ -189,6 +191,7 @@ export function VerificationResultHistoryDialog({
queryContext,
title = "검증 결과 내역",
emptyMessage = "표시할 검증 결과가 없습니다.",
onExceptionResetSubmitted,
}: VerificationResultHistoryDialogProps) {
const stableQueryContext = useMemo(() => {
if (!queryContext) return null;
@@ -459,12 +462,28 @@ export function VerificationResultHistoryDialog({
alert("예외 제출 취소 처리되었습니다.");
setCheckedVrfcByTab((prev) => ({ ...prev, [tab]: new Map() }));
await loadTabPage(tab, tabPages[tab].pageIndex);
try {
await onExceptionResetSubmitted?.();
} catch {
alert(
"예외 제출 취소는 완료되었으나 화면 데이터를 다시 불러오지 못했습니다. 조회로 새로고침 해주세요.",
);
}
} catch {
alert("예외 제출 취소 처리 중 오류가 발생했습니다.");
} finally {
setResetSubmitting(false);
}
}, [activeTab, alert, checkedVrfcByTab, entriesByTab, loadTabPage, stableQueryContext, tabPages]);
}, [
activeTab,
alert,
checkedVrfcByTab,
entriesByTab,
loadTabPage,
onExceptionResetSubmitted,
stableQueryContext,
tabPages,
]);
const renderActiveTabPanel = (tab: VerificationHistoryTabKey) => {
const entries = entriesByTab[tab];
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -210,7 +210,7 @@ const PublicSewageFacilityInp = () => {
const currentData =
st60001GridGetRowsRef.current?.() ?? rowDataMap.get('ST00060001') ?? [];
if (!treatAsNoApplicable && (!currentData || currentData.length === 0)) {
alert('제출할 데이터가 없습니다.');
alert('해당사항 없음을 체크해주세요.');
return;
}
const verificationBlocked = getVerificationPeriodActionBlockedMessage(periodCheckList);
@@ -291,15 +291,15 @@ const PublicSewageFacilityInp = () => {
const currentData =
st60001GridGetRowsRef.current?.() ?? rowDataMap.get('ST00060001') ?? [];
if (!treatAsNoApplicable && (!currentData || currentData.length === 0)) {
alert('제출할 데이터가 없습니다.');
const submitList = treatAsNoApplicable ? [] : buildFacilitySaveList(currentData);
if (!treatAsNoApplicable && submitList.length === 0) {
alert('해당사항 없음을 체크해주세요.');
return;
}
try {
showGlobalProgress({ label: '서버에 요청 중...', progress: 0 });
const userInfo = await getUserInfo();
const submitList = treatAsNoApplicable ? [] : buildFacilitySaveList(currentData);
const activeTabStatus = tabStatusInfoMap.get(activeTab) ?? null;
const statsCdForTab = tabStatsCdMap.get(activeTab) ?? activeTab;
const requestData = {
@@ -530,19 +530,19 @@ const PublicSewageFacilityInp = () => {
if (!(await confirm('저장 하시겠습니까?'))) return;
if (activeTab === 'ST00060001') {
const noApplicable = getNoApplicableForRequest();
const treatAsNoApplicable = noApplicable || isNotApplicable;
const currentData =
st60001GridGetRowsRef.current?.() ?? rowDataMap.get('ST00060001') ?? [];
const saveList = treatAsNoApplicable ? [] : buildFacilitySaveList(currentData);
if (!treatAsNoApplicable && saveList.length === 0) {
alert('해당사항 없음을 체크해주세요.');
return;
}
try {
showGlobalProgress({ label: '저장 진행 중...', progress: 0 });
const userInfo = await getUserInfo();
const noApplicable = getNoApplicableForRequest();
const treatAsNoApplicable = noApplicable || isNotApplicable;
const currentData =
st60001GridGetRowsRef.current?.() ?? rowDataMap.get('ST00060001') ?? [];
if (!treatAsNoApplicable && (!currentData || currentData.length === 0)) {
alert('저장할 데이터가 없습니다.');
return;
}
const saveList = treatAsNoApplicable ? [] : buildFacilitySaveList(currentData);
const param: PublicSewageFacilitySaveRequest = {
statsYr: lastSearchedValues.year ?? '',
ctpvNm: lastSearchedValues.sido ?? '',
@@ -1309,6 +1309,11 @@ const PublicSewageFacilityInp = () => {
open={verificationHistoryOpen}
onOpenChange={setVerificationHistoryOpen}
queryContext={verificationQueryContext}
onExceptionResetSubmitted={async () => {
const ctx = lastSearchedValues ?? searchValues;
if (!ctx || !searchParamRef.current) return;
await loadPublicSewageFacilityActiveTabData(activeTab, searchParamRef.current, ctx);
}}
/>
<SubmitDailog
open={showDailog}
File diff suppressed because it is too large Load Diff
@@ -2119,6 +2119,12 @@ const SewagePipeInp = () => {
}
: null
}
onExceptionResetSubmitted={async () => {
const values = lastSearchedValues ?? searchValues;
if (!values?.year || !values?.sido || !values?.bsnmCd) return;
const refreshedParam = buildSewagePipeSearchParam(values);
await loadSewagePipeActiveTabData(activeTab, refreshedParam, values, true, false);
}}
/>
<SubmitDailog
open={showDailog}
@@ -80,6 +80,12 @@ const SewagePipeMaintainInpTabList = [
const firstTabKey = RepairStatusInpColumn.tabKey;
const SEWAGE_PIPE_MAINTAIN_COLUMN_GUIDE_TAB_KEYS = Array.from(
new Set(
SewagePipeMaintainInpTabList.map((tab) => tab.tabKey).filter(Boolean),
),
);
const toGridColumnInfo = (tab: (typeof SewagePipeMaintainInpTabList)[number]): ColumnInfo => ({
columns: tab.columns ?? [],
columnLayout: tab.columnLayout ?? [],
@@ -302,6 +308,9 @@ const SewagePipeMaintainInp = () => {
const [rowDataMap, setRowDataMap] = useState<
Map<string, Record<string, string | number>[]>
>(new Map());
const [columnGuidesByTab, setColumnGuidesByTab] = useState<
Record<string, Record<string, string>>
>({});
const searchDoneRef = useRef(false);
const periodEnterableRef = useRef(true);
@@ -328,6 +337,37 @@ const SewagePipeMaintainInp = () => {
}
}, [activeTabId, inputFocusNonce]);
useEffect(() => {
if (activeTabId !== STATISTICS_INPUT_URL_PATH.SEWAGE_PIPE_MAINTAIN) return;
let cancelled = false;
void (async () => {
const entries = await Promise.all(
SEWAGE_PIPE_MAINTAIN_COLUMN_GUIDE_TAB_KEYS.map(async (tabKey) => {
try {
const res = await statisticsApi.getColumnGuides(tabKey);
if (res.status !== "success" || !Array.isArray(res.data)) {
return [tabKey, {}] as const;
}
const next: Record<string, string> = {};
for (const item of res.data) {
const key = item.engColNm?.trim();
const guide = item.columnGuide?.trim();
if (key && guide) next[key] = guide;
}
return [tabKey, next] as const;
} catch {
return [tabKey, {}] as const;
}
}),
);
if (cancelled) return;
setColumnGuidesByTab(Object.fromEntries(entries));
})();
return () => {
cancelled = true;
};
}, [activeTabId]);
const commitToolbarSnapshotForLoadedTab = (
tabKey: string,
statusInfo: SewerageStatusInfo | null,
@@ -951,22 +991,22 @@ const SewagePipeMaintainInp = () => {
tabStatusInfoMap.get(tabKey) ?? null,
inputPeriodEnterable,
) || isAdminInfo;
const columns = (tab.columns ?? []).map((col: ColumnConfig) =>
canEdit
? col
: {
...col,
editable: false as const,
styleName: col.styleName ?? "rg-cell-readonly",
},
);
const rawColumns = tab.columns ?? [];
const base = canEdit
? rawColumns
: rawColumns.map((col) => ({ ...col, editable: false as const }));
const columns = base
.map((col) => {
const guide = columnGuidesByTab[tabKey]?.[col.fieldName]?.trim();
return guide ? { ...col, tooltip: guide } : col;
});
map.set(tabKey, {
columns,
columnLayout: tab.columnLayout ?? [],
});
}
return map;
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo]);
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, columnGuidesByTab]);
const searchContextForToolbar = lastSearchedValues ?? searchValues;
const activeTabStatus = tabStatusInfoMap.get(activeTab) ?? null;
@@ -1120,7 +1160,7 @@ const SewagePipeMaintainInp = () => {
return (
<TabsContent key={tabKey} value={tabKey}>
<DataGrid
key={tabKey}
key={`${tabKey}-${tabEnterableForGrid ? "enterable" : "readonly"}`}
columnInfo={
columnInfoByTab.get(tabKey) ??
toGridColumnInfo(info)
@@ -1163,6 +1203,17 @@ const SewagePipeMaintainInp = () => {
open={verificationHistoryOpen}
onOpenChange={setVerificationHistoryOpen}
queryContext={verificationQueryContext}
onExceptionResetSubmitted={async () => {
const values = lastSearchedValues ?? searchValues;
if (!values || !searchParamRef.current) return;
await loadActiveTabData(
activeTabRef.current,
searchParamRef.current,
values,
true,
false,
);
}}
/>
<ConfirmDialog isOpen={false} />
<SubmitDailog
@@ -1176,6 +1227,17 @@ const SewagePipeMaintainInp = () => {
open={verificationResultDialogOpen}
onOpenChange={setVerificationResultDialogOpen}
queryContext={verificationQueryContext}
onExceptionSubmitted={async () => {
const values = lastSearchedValues ?? searchValues;
if (!values || !searchParamRef.current) return;
await loadActiveTabData(
activeTabRef.current,
searchParamRef.current,
values,
true,
false,
);
}}
/>
</>
);
@@ -1,5 +1,6 @@
import {
useCallback,
useEffect,
useMemo,
useRef,
useState,
@@ -25,8 +26,11 @@ import SaveButton from "@/components/button/SaveButton";
import SubmitButton from "@/components/button/SumitButton";
import VerificationResultButton from "@/components/button/VerificationResultButton";
import DataGrid, { applyDropDownColumnToGrid } from "@/components/module/DataGrid";
import { openVerificationResultDialogIfNeeded } from "@/components/module/post-submit-verification-results";
import SearchForm from "@/components/module/SearchForm";
import { VerificationResultDialog } from "@/components/module/VerificationResultDialog";
import { VerificationResultHistoryDialog } from "@/components/module/VerificationResultHistoryDialog";
import SubmitDailog from "./SubmitDailog";
import type { SearchFormValues } from "@/components/type/SearchForm.type";
import type {
CellStyleCallbackParams,
@@ -45,22 +49,27 @@ import {
toCompactYmd,
} from "@/components/util/grid/ymdFormat";
import { statisticsInputSewageReservoirPumpApi } from "@/entities/statistics/api/input/statistics-input-sewage-reservoir-pump-service";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import { isInputPeriodCurrent } from "@/entities/statistics/model/input/statistics-sewage-supply-rate-input-interface";
import {
SEWAGE_RESERVOIR_STATS_CD,
type SewageReservoirItem,
type SewageReservoirRequestParams,
type SewageReservoirSaveItem,
type RainfallPumpStationItem,
type RainfallPumpStationSaveItem,
type SewageReservoirVerificationResult,
} from "@/entities/statistics/model/input/statistics-input-sewage-reservoir-pump-interface";
import type { StatisticsInputSubmitInfoFormData } from "@/entities/statistics/model/statistics-input-submit-info-schema";
import type {
ApiResponse,
cancelSubmitRequest,
ImrStatusResponse,
Sgg,
SewerageStatusInfo,
} from "@/entities/statistics/model/statistics-interface";
import { useAlertStore, useStatisticsInputToolbarGroupGate } from "@/shared/lib";
import { useAlertStore, useGlobalProgressStore, useStatisticsInputToolbarGroupGate } from "@/shared/lib";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
import { useAdminStore } from "@/store/admin-store";
@@ -80,6 +89,12 @@ const firstTabKey = SewageReservoirPumpInpTabList[0]?.tabKey ?? SEWAGE_RESERVOIR
const rainfallPumpTabKey =
RainfallPumpStationInpColumn.tabKey ?? "rainfallPumpStationInp";
const SEWAGE_RESERVOIR_PUMP_COLUMN_GUIDE_TAB_KEYS = Array.from(
new Set(
SewageReservoirPumpInpTabList.map((tab) => tab.tabKey).filter(Boolean),
),
);
type GridRowWithVerification = Record<string, string | number> & {
verificationResult?: SewageReservoirVerificationResult;
};
@@ -210,11 +225,7 @@ function buildSggNmColumn(
sggOptions: Sgg[],
): ColumnConfig {
if (!canEdit) {
return {
...col,
editable: false as const,
styleName: col.styleName ?? "rg-cell-readonly",
};
return { ...col, editable: false as const };
}
if (sggOptions.length === 0) {
return { ...col, editable: true };
@@ -272,31 +283,7 @@ function toGridNumber(value: string | number | null | undefined): number {
return Number.isFinite(n) ? n : 0;
}
/** API 조회 항목 → 저장/삭제 API 형식 (조회 직후 스냅샷용) */
function buildSewageReservoirSaveItemFromApiItem(
item: SewageReservoirItem,
): SewageReservoirSaveItem {
return buildSewageReservoirSaveItem(
item as unknown as Record<string, string | number>,
);
}
function buildSewageReservoirDeleteList(
loadedSnapshot: SewageReservoirSaveItem[],
currentRows: Record<string, string | number>[],
): SewageReservoirSaveItem[] {
const currentFcltSnSet = new Set(
currentRows
.map((row) => String(row.fcltSn ?? "").trim())
.filter((sn) => sn !== ""),
);
return loadedSnapshot.filter((item) => {
const sn = String(item.fcltSn ?? "").trim();
return sn !== "" && !currentFcltSnSet.has(sn);
});
}
/** 시군구명(`sggNm`) 기준 행정구역 코드·명 */
/** 시군구명(`sggNm`) 기준 `admdstCd`(bsnmCd)·`admdstNm`(시군구명) */
function resolveSewageReservoirAdmdst(
sggNm: string,
sggOptions: Sgg[],
@@ -304,7 +291,7 @@ function resolveSewageReservoirAdmdst(
const trimmed = sggNm.trim();
const matched = sggOptions.find((s) => s.gugun === trimmed);
if (matched) {
return { admdstCd: matched.adstDstrCd, admdstNm: matched.gugun };
return { admdstCd: matched.bsnmCd, admdstNm: matched.gugun };
}
return { admdstCd: "", admdstNm: trimmed };
}
@@ -318,10 +305,12 @@ function buildSewageReservoirSaveItem(
String(row.sggNm ?? ""),
sggOptions,
);
const fcltSn = String(row.fcltSn ?? "").trim();
return {
admdstCd,
admdstNm,
fcltSn: String(row.fcltSn ?? ""),
// 항목 추가 직후 저장(신규) — 그리드 fcltSn 없음 → API에는 "1"
fcltSn: fcltSn,
fcltNm: String(row.fcltNm ?? ""),
fcltPstnCn: String(row.fcltPstnCn ?? ""),
oprtngStrtYmd: toCompactYmd(row.oprtngStrtYmd),
@@ -345,9 +334,9 @@ function buildSewageReservoirSaveItem(
pumpFcltN3PerPpqty: toGridNumber(row.pumpFcltN3PerPpqty),
pumpFcltN3PumpCnt: toGridNumber(row.pumpFcltN3PumpCnt),
pumpFcltN3RsrvPumpCnt: toGridNumber(row.pumpFcltN3RsrvPumpCnt),
prcsgFcltYn: String(row.prcsgFcltYn ?? ""),
ddrztnEqpmYn: String(row.ddrztnEqpmYn ?? ""),
oslfEtgtYn: String(row.oslfEtgtYn ?? ""),
prcsgFcltYn: String(row.prcsgFcltYn ? (row.prcsgFcltYn === '무' ? 'N' : 'Y') : ""),
ddrztnEqpmYn: String(row.ddrztnEqpmYn ? (row.prcsgFcltYn === '무' ? 'N' : 'Y') : ""),
oslfEtgtYn: String(row.oslfEtgtYn ? (row.prcsgFcltYn === '무' ? 'N' : 'Y') : ""),
mltvMthCn: nullableTrimmedString(row.mltvMthCn),
impdMthCn: nullableTrimmedString(row.impdMthCn),
impdPrcsMthdCn: nullableTrimmedString(row.impdPrcsMthdCn),
@@ -362,6 +351,56 @@ function buildSewageReservoirSaveItem(
};
}
/** 그리드 행 → ST00040002 저장/삭제 API 항목 */
function buildRainfallPumpStationSaveItem(
row: Record<string, string | number>,
sggOptions: Sgg[] = [],
): RainfallPumpStationSaveItem {
const { admdstCd, admdstNm } = resolveSewageReservoirAdmdst(
String(row.sggNm ?? ""),
sggOptions,
);
const fcltSn = String(row.fcltSn ?? "").trim();
return {
admdstCd,
admdstNm,
fcltSn: fcltSn,
fcltNm: String(row.fcltNm ?? ""),
fcltPstnCn: String(row.fcltPstnCn ?? ""),
fcltyKndCn: String(row.fcltyKndCn ?? ""),
oprtngStrtYmd: toCompactYmd(row.oprtngStrtYmd),
planDesignFreqCnt: toGridNumber(row.planDesignFreqCnt),
wtrStrgZoneArea: toGridNumber(row.wtrStrgZoneArea),
rsvrYn: String(row.rsvrYn ? (row.rsvrYn === "무" ? "N" : "Y") : ""),
rsvrImpndQnt: toGridNumber(row.rsvrImpndQnt),
abstnRgnImpdQnt: toGridNumber(row.abstnRgnImpdQnt),
grssPpqty: toGridNumber(row.grssPpqty),
pumpFcltN1DmtrExpln: String(row.pumpFcltN1DmtrExpln ?? ""),
pumpFcltN1PerPpqty: toGridNumber(row.pumpFcltN1PerPpqty),
pumpFcltN1PumpCnt: toGridNumber(row.pumpFcltN1PumpCnt),
pumpFcltN1RsrvPumpCnt: toGridNumber(row.pumpFcltN1RsrvPumpCnt),
pumpFcltN2DmtrExpln: String(row.pumpFcltN2DmtrExpln ?? ""),
pumpFcltN2PerPpqty: toGridNumber(row.pumpFcltN2PerPpqty),
pumpFcltN2PumpCnt: toGridNumber(row.pumpFcltN2PumpCnt),
pumpFcltN2RsrvPumpCnt: toGridNumber(row.pumpFcltN2RsrvPumpCnt),
pumpFcltN3DmtrExpln: String(row.pumpFcltN3DmtrExpln ?? ""),
pumpFcltN3PerPpqty: toGridNumber(row.pumpFcltN3PerPpqty),
pumpFcltN3PumpCnt: toGridNumber(row.pumpFcltN3PumpCnt),
pumpFcltN3RsrvPumpCnt: toGridNumber(row.pumpFcltN3RsrvPumpCnt),
prcsgFcltYn: String(row.prcsgFcltYn ? (row.prcsgFcltYn === "무" ? "N" : "Y") : ""),
ddrztnEqpmYn: String(row.ddrztnEqpmYn ? (row.prcsgFcltYn === "무" ? "N" : "Y") : ""),
oslfEtgtYn: String(row.oslfEtgtYn ? (row.prcsgFcltYn === "무" ? "N" : "Y") : ""),
dschgWtrsExpln: String(row.dschgWtrsExpln ?? ""),
prcptnLastDspsQnt: toGridNumber(row.prcptnLastDspsQnt),
ctmnLastDspsQnt: toGridNumber(row.ctmnLastDspsQnt),
prcptnLastDspsMthdExpln: String(row.prcptnLastDspsMthdExpln ?? ""),
ctmnLastDspsMthdExpln: String(row.ctmnLastDspsMthdExpln ?? ""),
oprtngDayCnt: toGridNumber(row.oprtngDayCnt),
grssMltvQnt: toGridNumber(row.grssMltvQnt),
rmrk: nullableTrimmedString(row.rmrk),
};
}
function mapRainfallPumpStationListToGridRows(
list: RainfallPumpStationItem[],
ctpvNm: string,
@@ -386,20 +425,72 @@ function mapRainfallPumpStationListToGridRows(
});
}
const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
async function waitForImrJobCompleted(
jobId: string,
getStatus: (id: string) => Promise<ImrStatusResponse>,
options?: {
pollIntervalMs?: number;
maxAttempts?: number;
onProgress?: (jobProgress: number) => void;
},
): Promise<void> {
const pollIntervalMs = options?.pollIntervalMs ?? 2000;
const maxAttempts = options?.maxAttempts ?? 150;
for (let i = 0; i < maxAttempts; i++) {
const res = await getStatus(jobId);
options?.onProgress?.(Math.max(0, Math.min(100, Number(res.job_prog) || 0)));
if (res.status === "COMPLETED" && Number(res.job_prog) === 100) return;
if (res.status === "FAILED" || res.status === "ERROR" || res.status === "CANCELLED") {
throw new Error(res.error_msg || `IMR 검증이 ${res.status} 상태로 종료되었습니다.`);
}
await sleep(pollIntervalMs);
}
throw new Error("IMR 검증 완료 대기 시간이 초과되었습니다.");
}
// 하수도 통계 관리 > 04. 하수저류 시설 및 빗물 펌프장
const SewageReservoirPumpInp = () => {
const { setMessage: alert } = useAlertStore((state) => state);
const { confirm } = useConfirm();
const { isAdminInfo } = useAdminStore();
const toolbarGroupAllowed = useStatisticsInputToolbarGroupGate();
const showGlobalProgress = useGlobalProgressStore((state) => state.show);
const setGlobalProgress = useGlobalProgressStore((state) => state.setProgress);
const setGlobalProgressLabel = useGlobalProgressStore((state) => state.setLabel);
const hideGlobalProgress = useGlobalProgressStore((state) => state.hide);
const submitFunc = () => {
console.log("submit");
void (async () => {
const tabKey = activeTabRef.current;
if (
tabKey !== SEWAGE_RESERVOIR_STATS_CD &&
tabKey !== rainfallPumpTabKey
) {
alert("제출할 수 없는 탭입니다.");
return;
}
if (!lastSearchedValues) {
alert("먼저 조회를 진행해주세요.");
return;
}
if (!buildGugunOkForToolbar(lastSearchedValues)) {
alert("시군구를 선택해주세요.");
return;
}
const noApplicable = isNotApplicableByTab.get(tabKey) ?? false;
const currentData = getCurrentRowsForTab(tabKey);
if (!noApplicable && currentData.length === 0) {
alert("해당사항 없음을 체크해주세요.");
return;
}
if (await confirm("제출 하시겠습니까?")) {
setShowSubmitDialog(true);
}
})();
};
/** 마지막 조회 시 서버에 있던 하수저류시설 목록 (deleteList 비교 기준) */
const loadedSewageReservoirSnapshotRef = useRef<SewageReservoirSaveItem[]>([]);
const cnacelSubmitFunc = () => {
void (async () => {
try {
@@ -530,24 +621,35 @@ const SewageReservoirPumpInp = () => {
.filter((idx) => idx >= 0),
);
const removedRows = currentRows.filter((_, idx) =>
checkedIndexSet.has(idx),
);
const nextRows = currentRows.filter((_, idx) => !checkedIndexSet.has(idx));
if (nextRows.length === currentRows.length) {
if (removedRows.length === 0) {
alert("삭제할 항목을 선택해주세요.");
return;
}
if (tabKey === SEWAGE_RESERVOIR_STATS_CD) {
setSewageReservoirDeleteList((prev) => [...prev, ...removedRows]);
} else if (tabKey === rainfallPumpTabKey) {
setRainfallPumpStationDeleteList((prev) => [...prev, ...removedRows]);
}
setRowDataMap((prev) => {
const next = new Map(prev);
next.set(tabKey, nextRows);
return next;
});
};
const saveFunc = () => {
void (async () => {
const tabKey = activeTabRef.current;
if (tabKey !== SEWAGE_RESERVOIR_STATS_CD) {
if (
tabKey !== SEWAGE_RESERVOIR_STATS_CD &&
tabKey !== rainfallPumpTabKey
) {
alert("저장할 수 없는 탭입니다.");
return;
}
@@ -564,41 +666,63 @@ const SewageReservoirPumpInp = () => {
commitGridForTab(tabKey);
const noApplicable = isNotApplicableByTab.get(tabKey) ?? false;
const currentData = getCurrentRowsForTab(tabKey);
const isReservoirTab = tabKey === SEWAGE_RESERVOIR_STATS_CD;
const saveList = noApplicable
? []
: currentData.map((row) =>
buildSewageReservoirSaveItem(row, sggOptions),
);
const deleteList = buildSewageReservoirDeleteList(
loadedSewageReservoirSnapshotRef.current,
currentData,
);
if (!noApplicable && saveList.length === 0 && deleteList.length === 0) {
alert("저장할 변경 사항이 없습니다.");
: isReservoirTab
? currentData.map((row) =>
buildSewageReservoirSaveItem(row, sggOptions),
)
: currentData.map((row) =>
buildRainfallPumpStationSaveItem(row, sggOptions),
);
const deleteList = isReservoirTab
? sewageReservoirDeleteList
.filter((row) => String(row.fcltSn ?? "").trim() !== "")
.map((row) => buildSewageReservoirSaveItem(row, sggOptions))
: rainfallPumpStationDeleteList
.filter((row) => String(row.fcltSn ?? "").trim() !== "")
.map((row) => buildRainfallPumpStationSaveItem(row, sggOptions));
if (!noApplicable && saveList.length === 0) {
alert("해당사항 없음을 체크해주세요.");
return;
}
const requestBase = {
statsYr: lastSearchedValues.year ?? "",
ctpvNm: lastSearchedValues.sido ?? "",
sggNm:
lastSearchedValues.gugun === "ALL"
? ""
: (lastSearchedValues.gugun ?? ""),
sewerBzmnCd: lastSearchedValues.bsnmCd ?? "",
...(isAdminInfo ? { superAdmin: "superAdmin" } : {}),
...(noApplicable ? { noApplicable: true } : {}),
};
try {
setIsLoading(true);
const userInfo = await getUserInfo();
const response =
await statisticsInputSewageReservoirPumpApi.saveSewageReservoir({
statsYr: lastSearchedValues.year ?? "",
ctpvNm: lastSearchedValues.sido ?? "",
sggNm:
lastSearchedValues.gugun === "ALL"
? ""
: (lastSearchedValues.gugun ?? ""),
sewerBzmnCd: lastSearchedValues.bsnmCd ?? "",
const response = isReservoirTab
? await statisticsInputSewageReservoirPumpApi.saveSewageReservoir({
...requestBase,
userId: userInfo.userUnqId,
...(isAdminInfo ? { superAdmin: "superAdmin" } : {}),
...(noApplicable ? { noApplicable: true } : {}),
saveList,
deleteList,
saveList: saveList as SewageReservoirSaveItem[],
deleteList: deleteList as SewageReservoirSaveItem[],
})
: await statisticsInputSewageReservoirPumpApi.saveRainfallPumpStation({
...requestBase,
userId: userInfo.userUnqId,
saveList: saveList as RainfallPumpStationSaveItem[],
deleteList: deleteList as RainfallPumpStationSaveItem[],
});
if (response.status === "success") {
if (isReservoirTab) {
setSewageReservoirDeleteList([]);
} else {
setRainfallPumpStationDeleteList([]);
}
await loadActiveTabData(tabKey, lastSearchedValues, false, false);
alert("저장되었습니다.");
} else {
@@ -612,6 +736,180 @@ const SewageReservoirPumpInp = () => {
})();
};
const executeSubmit = async (submitInfo: StatisticsInputSubmitInfoFormData) => {
const tabKey = activeTabRef.current;
if (
tabKey !== SEWAGE_RESERVOIR_STATS_CD &&
tabKey !== rainfallPumpTabKey
) {
alert("제출할 수 없는 탭입니다.");
return;
}
if (!lastSearchedValues) {
alert("먼저 조회를 진행해주세요.");
return;
}
if (!buildGugunOkForToolbar(lastSearchedValues)) {
alert("시군구를 선택해주세요.");
return;
}
commitGridForTab(tabKey);
const noApplicable = isNotApplicableByTab.get(tabKey) ?? false;
const currentData = getCurrentRowsForTab(tabKey);
const isReservoirTab = tabKey === SEWAGE_RESERVOIR_STATS_CD;
const submitList = noApplicable
? []
: isReservoirTab
? currentData.map((row) => buildSewageReservoirSaveItem(row, sggOptions))
: currentData.map((row) => buildRainfallPumpStationSaveItem(row, sggOptions));
const deleteList = isReservoirTab
? sewageReservoirDeleteList
.filter((row) => String(row.fcltSn ?? "").trim() !== "")
.map((row) => buildSewageReservoirSaveItem(row, sggOptions))
: rainfallPumpStationDeleteList
.filter((row) => String(row.fcltSn ?? "").trim() !== "")
.map((row) => buildRainfallPumpStationSaveItem(row, sggOptions));
const activeTabStatus = tabStatusInfoMap.get(tabKey) ?? null;
const statsCdForTab = tabStatsCdMap.get(tabKey) ?? tabKey;
const verificationQuery = {
sewerBzmnCd: lastSearchedValues.bsnmCd ?? "",
ctpvNm: lastSearchedValues.sido ?? "",
sggNm:
lastSearchedValues.gugun === "ALL"
? ""
: (lastSearchedValues.gugun ?? ""),
statsYr: lastSearchedValues.year ?? "",
statsCd: statsCdForTab,
};
const reloadSubmittedTab = async () => {
if (isReservoirTab) {
setSewageReservoirDeleteList([]);
} else {
setRainfallPumpStationDeleteList([]);
}
await loadActiveTabData(tabKey, lastSearchedValues, false, false);
};
if (!noApplicable && submitList.length === 0) {
alert("해당사항 없음을 체크해주세요.");
return;
}
const submitRequestBase = {
statsYr: lastSearchedValues.year ?? "",
ctpvNm: lastSearchedValues.sido ?? "",
sggNm:
lastSearchedValues.gugun === "ALL"
? ""
: (lastSearchedValues.gugun ?? ""),
sewerBzmnCd: lastSearchedValues.bsnmCd ?? "",
...(noApplicable ? { noApplicable: true } : {}),
laePicNm: submitInfo.laePicNm,
laeKbrdrJbgdNm: submitInfo.laeKbrdrJbgdNm,
laeKbrdrDeptNm: submitInfo.laeKbrdrDeptNm,
laePicTelNo: submitInfo.laePicTelNo,
laeIdfrNm: submitInfo.laeIdfrNm,
laeIdfrJbgdNm: submitInfo.laeIdfrJbgdNm,
laeIdfrDeptNm: submitInfo.laeIdfrDeptNm,
laeIdfrTelNo: submitInfo.laeIdfrTelNo,
};
try {
showGlobalProgress({ label: "서버에 요청 중...", progress: 0 });
const userInfo = await getUserInfo();
setGlobalProgressLabel("일반 검증 진행 중...");
const response = isReservoirTab
? await statisticsInputSewageReservoirPumpApi.submitSewageReservoir({
...submitRequestBase,
userId: userInfo.userUnqId,
submitList: submitList as SewageReservoirSaveItem[],
deleteList: deleteList as SewageReservoirSaveItem[],
})
: await statisticsInputSewageReservoirPumpApi.submitRainfallPumpStation({
...submitRequestBase,
userId: userInfo.userUnqId,
submitList: submitList as RainfallPumpStationSaveItem[],
deleteList: deleteList as RainfallPumpStationSaveItem[],
});
if (response.status !== "success") {
alert(response.message ?? "데이터 제출 중 오류가 발생했습니다.");
return;
}
const finalStatus = response.data?.finalStatus;
const nvpassed = response.data?.nvpassed;
if (finalStatus === "5") {
setGlobalProgress(50);
setGlobalProgressLabel("IMR 검증 진행 중...");
const imrParam = {
user_id: userInfo.userUnqId,
sewer_bzmn_cd: lastSearchedValues.bsnmCd ?? "",
stats_cd: statsCdForTab,
stats_yr: lastSearchedValues.year ?? "",
lae_sbmsn_stts_cd:
activeTabStatus?.laeSbmsnSttsCd === "4" ? "4" : "2",
gen_verify_stts_cd: nvpassed ? "1" : "2",
};
try {
const imrResponse = await statisticsApi.callImrService(imrParam);
if (imrResponse.job_id) {
await waitForImrJobCompleted(
imrResponse.job_id,
(id) => statisticsApi.getImrStatus(id),
{
onProgress: (jobProgress) => {
setGlobalProgress(50 + Math.round(jobProgress / 2));
},
},
);
}
setGlobalProgress(100);
await reloadSubmittedTab();
await openVerificationResultDialogIfNeeded(
verificationQuery,
setVerificationResultDialogOpen,
{ notify: alert },
);
} catch (e) {
await reloadSubmittedTab();
await openVerificationResultDialogIfNeeded(
verificationQuery,
setVerificationResultDialogOpen,
{ notify: alert, notifySubmitComplete: false },
);
const msg =
e instanceof Error && e.message
? e.message
: "IMR 검증 중 오류가 발생했습니다.\n관리자에게 문의하세요.";
alert(msg);
}
} else {
setGlobalProgress(100);
await reloadSubmittedTab();
await openVerificationResultDialogIfNeeded(
verificationQuery,
setVerificationResultDialogOpen,
{ notify: alert },
);
}
} catch {
alert("데이터 제출 중 오류가 발생했습니다.");
} finally {
hideGlobalProgress();
}
};
const [sewageReservoirDeleteList, setSewageReservoirDeleteList] = useState<
Record<string, string | number>[]
>([]);
const [rainfallPumpStationDeleteList, setRainfallPumpStationDeleteList] =
useState<Record<string, string | number>[]>([]);
const [activeTab, setActiveTab] = useState(firstTabKey);
const [rowDataMap, setRowDataMap] = useState<
Map<string, Record<string, string | number>[]>
@@ -634,7 +932,13 @@ const SewageReservoirPumpInp = () => {
>(new Map());
const [tabStatsCdMap, setTabStatsCdMap] = useState<Map<string, string>>(new Map());
const [verificationHistoryOpen, setVerificationHistoryOpen] = useState(false);
const [verificationResultDialogOpen, setVerificationResultDialogOpen] =
useState(false);
const [showSubmitDialog, setShowSubmitDialog] = useState(false);
const [sggOptions, setSggOptions] = useState<Sgg[]>([]);
const [columnGuidesByTab, setColumnGuidesByTab] = useState<
Record<string, Record<string, string>>
>({});
const reservoirGridRef = useRef<RealGridReact | null>(null);
const rainfallPumpGridRef = useRef<RealGridReact | null>(null);
const reservoirGridGetRowsRef =
@@ -643,6 +947,36 @@ const SewageReservoirPumpInp = () => {
useRef<(() => Record<string, string | number>[]) | null>(null);
const sggOptionsSidoRef = useRef<string | null>(null);
useEffect(() => {
let cancelled = false;
void (async () => {
const entries = await Promise.all(
SEWAGE_RESERVOIR_PUMP_COLUMN_GUIDE_TAB_KEYS.map(async (tabKey) => {
try {
const res = await statisticsApi.getColumnGuides(tabKey);
if (res.status !== "success" || !Array.isArray(res.data)) {
return [tabKey, {}] as const;
}
const next: Record<string, string> = {};
for (const item of res.data) {
const key = item.engColNm?.trim();
const guide = item.columnGuide?.trim();
if (key && guide) next[key] = guide;
}
return [tabKey, next] as const;
} catch {
return [tabKey, {}] as const;
}
}),
);
if (cancelled) return;
setColumnGuidesByTab(Object.fromEntries(entries));
})();
return () => {
cancelled = true;
};
}, []);
const searchDoneRef = useRef(false);
const periodEnterableRef = useRef(true);
const activeTabRef = useRef(activeTab);
@@ -732,9 +1066,7 @@ const SewageReservoirPumpInp = () => {
const { commonInfo, statusInfo, sewageReservoirList } = response.data;
const list = sewageReservoirList ?? [];
loadedSewageReservoirSnapshotRef.current = list
.filter((item) => String(item.fcltSn ?? "").trim() !== "")
.map(buildSewageReservoirSaveItemFromApiItem);
setSewageReservoirDeleteList([]);
const gridRows = mapSewageReservoirListToGridRows(
list,
commonInfo.ctpvNm,
@@ -771,6 +1103,7 @@ const SewageReservoirPumpInp = () => {
const { commonInfo, statusInfo, rainfallPumpStationList } = response.data;
const list = rainfallPumpStationList ?? [];
setRainfallPumpStationDeleteList([]);
const gridRows = mapRainfallPumpStationListToGridRows(
list,
commonInfo.ctpvNm,
@@ -837,7 +1170,8 @@ const SewageReservoirPumpInp = () => {
}, []);
const handleReset = () => {
loadedSewageReservoirSnapshotRef.current = [];
setSewageReservoirDeleteList([]);
setRainfallPumpStationDeleteList([]);
setRowDataMap(new Map());
setTabStatusInfoMap(new Map());
setTabStatsCdMap(new Map());
@@ -860,6 +1194,25 @@ const SewageReservoirPumpInp = () => {
return;
}
try {
const periodResponse = await statisticsInputSewSupplyRateApi.checkInputPeriod(
values.year || "",
);
if (periodResponse.status !== "success") {
alert(periodResponse.message);
return;
}
const periods = Array.isArray(periodResponse.data)
? periodResponse.data
: [];
const periodOk = isInputPeriodCurrent(periods);
periodEnterableRef.current = periodOk;
setInputPeriodEnterable(periodOk);
} catch {
alert("입력 기간 확인 중 오류가 발생했습니다.");
return;
}
const yearChangedFromLastSearch =
lastSearchedValues != null &&
(lastSearchedValues.year ?? "") !== (values.year ?? "");
@@ -957,12 +1310,13 @@ const SewageReservoirPumpInp = () => {
baseShowEnterableToolbarButtons && toolbarGroupAllowed;
const showActionToolbarCard =
baseShowActionToolbarCard && toolbarGroupAllowed;
// 항목추가/제거 버튼은 "데이터가 있든 없든", "과거 데이터(입력 불가 상태)여도"
// 조회를 하고나면 항상 보여야 합니다.
const isReservoirOrRainfallTab =
activeTab === SEWAGE_RESERVOIR_STATS_CD || activeTab === rainfallPumpTabKey;
const showArticleToolbarCard =
hasSearched && isReservoirOrRainfallTab && toolbarGroupAllowed;
hasSearched &&
isReservoirOrRainfallTab &&
toolbarGroupAllowed &&
(showSaveInToolbar || showEnterableToolbarButtons);
const isNotApplicableForActiveTab = isNotApplicableByTab.get(activeTab) ?? false;
const showNotApplicableForActiveTab =
loadedTabKeysRef.current.has(activeTab) &&
@@ -1012,20 +1366,6 @@ const SewageReservoirPumpInp = () => {
const sggNm =
ctx.gugun && ctx.gugun !== "ALL" ? ctx.gugun : "";
if (isRainfallPumpTab) {
const newRow = createEmptyRainfallPumpStationRow(ctx.sido, sggNm);
setRowDataMap((prev) => {
const next = new Map(prev);
const current = next.get(rainfallPumpTabKey) ?? [];
next.set(rainfallPumpTabKey, [...current, newRow]);
return next;
});
const statusInfo = tabStatusInfoMap.get(rainfallPumpTabKey) ?? null;
commitToolbarSnapshotForLoadedTab(rainfallPumpTabKey, statusInfo, true, ctx);
return;
}
let list = sggOptions;
if (sggOptionsSidoRef.current !== ctx.sido || list.length === 0) {
list = await loadSggOptions(ctx.sido);
@@ -1036,24 +1376,23 @@ const SewageReservoirPumpInp = () => {
return;
}
const tabKey = SEWAGE_RESERVOIR_STATS_CD;
const labels = list.map((s) => s.gugun).filter(Boolean);
const newRow = createEmptySewageReservoirRow(ctx.sido, sggNm);
const tabKey = activeTabKey;
const newRow = isReservoirTab
? createEmptySewageReservoirRow(ctx.sido, sggNm)
: createEmptyRainfallPumpStationRow(ctx.sido, sggNm);
commitGridForTab(tabKey);
const currentRows = getCurrentRowsForTab(tabKey);
flushSync(() => {
setSggOptions(list);
setRowDataMap((prev) => {
const next = new Map(prev);
const current = next.get(tabKey) ?? [];
next.set(tabKey, [...current, newRow]);
next.set(tabKey, [...currentRows, newRow]);
return next;
});
});
// 드롭다운 컬럼은 columnInfoByTab(buildSggNmColumn) 렌더링으로 반영한다.
// 행 추가 직후 setColumnProperty를 강제 재적용하면 타이밍 이슈로
// `fieldIndex is out of bounds`가 발생할 수 있어 제거한다.
const statusInfo = tabStatusInfoMap.get(tabKey) ?? null;
commitToolbarSnapshotForLoadedTab(tabKey, statusInfo, true, ctx);
};
@@ -1068,24 +1407,29 @@ const SewageReservoirPumpInp = () => {
inputPeriodEnterable,
) || isAdminInfo;
const isReservoirTab = tabKey === SEWAGE_RESERVOIR_STATS_CD;
const columns = (tab.columns ?? []).map((col: ColumnConfig) => {
if (isReservoirTab && col.fieldName === "ctpvNm") {
return {
...col,
editable: false as const,
styleName: col.styleName ?? "rg-cell-readonly",
};
const isRainfallPumpTab = tabKey === rainfallPumpTabKey;
const rawColumns = tab.columns ?? [];
const base = canEdit
? rawColumns
: rawColumns.map((col) => ({ ...col, editable: false as const }));
const columns = base.map((col: ColumnConfig) => {
if (
(isReservoirTab || isRainfallPumpTab) &&
col.fieldName === "ctpvNm"
) {
return { ...col, editable: false as const };
}
if (isReservoirTab && col.fieldName === "sggNm") {
return buildSggNmColumn(col, canEdit, sggOptions);
if (
(isReservoirTab || isRainfallPumpTab) &&
col.fieldName === "sggNm" &&
canEdit
) {
return buildSggNmColumn(col, true, sggOptions);
}
return canEdit
? col
: {
...col,
editable: false as const,
styleName: col.styleName ?? "rg-cell-readonly",
};
return col;
}).map((col) => {
const guide = columnGuidesByTab[tabKey]?.[col.fieldName]?.trim();
return guide ? { ...col, tooltip: guide } : col;
});
map.set(tabKey, {
columns,
@@ -1093,7 +1437,7 @@ const SewageReservoirPumpInp = () => {
});
}
return map;
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, sggOptions]);
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, sggOptions, columnGuidesByTab]);
const verificationCellStyle = ({
fieldName,
@@ -1220,7 +1564,7 @@ const SewageReservoirPumpInp = () => {
return (
<TabsContent key={tabKey} value={tabKey}>
<DataGrid
key={tabKey}
key={`${tabKey}-${tabEnterableForGrid ? "enterable" : "readonly"}`}
getGridRef={
isReservoirTab
? reservoirGridRef
@@ -1265,7 +1609,7 @@ const SewageReservoirPumpInp = () => {
showHeaderCheckbox
statusInfo={tabStatusInfo}
isExcelImport={
tabRowDataExists(rowDataMap, tabKey) &&
loadedTabKeysRef.current.has(tabKey) &&
tabEnterableForGrid &&
gugunOk
}
@@ -1281,6 +1625,28 @@ const SewageReservoirPumpInp = () => {
open={verificationHistoryOpen}
onOpenChange={setVerificationHistoryOpen}
queryContext={verificationQueryContext}
onExceptionResetSubmitted={async () => {
const values = lastSearchedValues ?? searchValues;
if (!values) return;
await loadActiveTabData(activeTabRef.current, values, false, false);
}}
/>
<SubmitDailog
open={showSubmitDialog}
onOpenChange={setShowSubmitDialog}
statusInfo={activeTabStatus}
onConfirm={executeSubmit}
isLoading={isLoading}
/>
<VerificationResultDialog
open={verificationResultDialogOpen}
onOpenChange={setVerificationResultDialogOpen}
queryContext={verificationQueryContext}
onExceptionSubmitted={async () => {
const values = lastSearchedValues ?? searchValues;
if (!values) return;
await loadActiveTabData(activeTabRef.current, values, false, false);
}}
/>
<ConfirmDialog isOpen={false} />
</>
@@ -1,34 +1,539 @@
import { useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import SearchForm from "@/components/module/SearchForm";
import TabDataGrid from "@/components/module/TabDataGrid";
import SubmitButton from "@/components/button/SumitButton";
import SaveButton from "@/components/button/SaveButton";
import SubmitExceptionButton from "@/components/button/SubmitExceptionButton";
import { useConfirm } from "@frontend-opensource/use-react-hooks";
import { useAlertStore } from "@/shared/lib";
import { statisticsInputSewSupplyRateApi } from "@/entities/statistics/api/input/statistics-input-sew-supply-rate-service";
import { statisticsInputSewerageFinanceApi } from "@/entities/statistics/api/input/statistics-input-sewerage-finance-service";
import { statisticsApi } from "@/entities/statistics/api/statistics-service";
import type {
CauserBurdenItem,
SewerageChargeItem,
SewerageFinanceRequestParams,
SewerageFinanceSettleItem,
SewerageFinanceVerificationResult,
SewerageUsageFeeItem,
} from "@/entities/statistics/model/input/statistics-input-sewerage-finance-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 { LoadingWithAnimation, Tabs, TabsContent, TabsList, TabsTrigger } from "@common/components";
import { getUserInfo } from "../../../../../../packages/common/components/src/api";
import CancelSubmitButton from "@/components/button/CancelSubmitButton";
import LastYearDataButton from "@/components/button/LastYearDataButton";
import SaveButton from "@/components/button/SaveButton";
import SubmitButton from "@/components/button/SumitButton";
import VerificationResultButton from "@/components/button/VerificationResultButton";
import DataGrid from "@/components/module/DataGrid";
import SearchForm from "@/components/module/SearchForm";
import { VerificationResultDialog } from "@/components/module/VerificationResultDialog";
import { VerificationResultHistoryDialog } from "@/components/module/VerificationResultHistoryDialog";
import type { ColumnConfig, ColumnInfo } from "@/components/type/DataGrid.type";
import type { SearchFormValues } from "@/components/type/SearchForm.type";
import { doList } from "@/components/util/column/input/DoList";
import { CauserBurdenInpColumn } from "@/components/util/column/input/sewerageFinance/CauserBurdenInpColumn";
import { SewerageChargeInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageChargeInpColumn";
import { SewerageFinanceSettleInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageFinanceSettleInpColumn";
import { SewerageUsageFeeInpColumn } from "@/components/util/column/input/sewerageFinance/SewerageUsageFeeInpColumn";
import { toGridRows } from "@/components/util/grid/gridFunction";
import { useAdminStore } from "@/store/admin-store";
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"
const SewerageFinanceInpTabList = [
SewerageFinanceSettleInpColumn,
SewerageChargeInpColumn,
SewerageUsageFeeInpColumn,
CauserBurdenInpColumn,
] as const;
const firstTabKey = SewerageFinanceSettleInpColumn.tabKey;
const SEWERAGE_FINANCE_COLUMN_GUIDE_TAB_KEYS = Array.from(
new Set(SewerageFinanceInpTabList.map((tab) => tab.tabKey).filter(Boolean)),
);
type GridRowWithVerification = Record<string, string | number> & {
verificationResult?: SewerageFinanceVerificationResult;
};
type TabToolbarSnapshot = {
showSaveInToolbar: boolean;
showEnterableToolbarButtons: boolean;
showActionToolbarCard: boolean;
};
const toGridColumnInfo = (tab: (typeof SewerageFinanceInpTabList)[number]): ColumnInfo => ({
columns: tab.columns ?? [],
columnLayout: tab.columnLayout ?? [],
});
function buildSewerageFinanceSearchParam(
values: SearchFormValues,
overrides?: { mode?: string },
): SewerageFinanceRequestParams {
return {
statsYr: values.year,
sewerBzmnCd: values.bsnmCd,
ctpvNm: values.sido,
sggNm: values.gugun === "ALL" ? "" : values.gugun,
...(overrides?.mode ? { mode: overrides.mode } : {}),
};
}
const computeTabEnterable = (
statusInfo: SewerageStatusInfo | null | undefined,
periodEnterable: boolean,
): boolean => {
if (statusInfo?.laeSbmsnSttsCd) {
if (["2", "3"].includes(statusInfo.laeSbmsnSttsCd)) {
return false;
}
return periodEnterable;
}
return periodEnterable;
};
function buildGugunOkForToolbar(values: SearchFormValues | null): boolean {
return doList.includes(values?.bsnmCd || "")
? Boolean(values?.gugun && values.gugun !== "ALL")
: true;
}
function computeTabToolbarSnapshot(
statusInfo: SewerageStatusInfo | null,
hasRowData: boolean,
treatAsSearched: boolean,
searchContext: SearchFormValues | null,
periodEnterable: boolean,
isAdminInfo: boolean,
): TabToolbarSnapshot {
const gugunOk = buildGugunOkForToolbar(searchContext);
const enterable = computeTabEnterable(statusInfo, periodEnterable);
const isSubmitted = statusInfo?.laeSbmsnSttsCd === "2";
const showSaveInToolbar = (enterable || isAdminInfo) && gugunOk;
const showEnterableToolbarButtons = enterable && gugunOk;
const showSubmittedInInputPeriodToolbar = isSubmitted && periodEnterable && gugunOk;
const showActionToolbarCard =
(hasRowData || treatAsSearched) &&
(showSaveInToolbar ||
showEnterableToolbarButtons ||
showSubmittedInInputPeriodToolbar ||
(isSubmitted && isAdminInfo));
return { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard };
}
function tabRowDataExists(
m: Map<string, Record<string, string | number>[]>,
tabKey: string,
): boolean {
const rows = m.get(tabKey);
return Array.isArray(rows) && rows.length > 0;
}
function mapRegionalListToGridRows<
T extends { verificationResult?: SewerageFinanceVerificationResult },
>(list: T[], ctpvNm: string): GridRowWithVerification[] {
return list.map((item) => {
const { verificationResult, ...rest } = item;
const row = toGridRows([{ ctpvNm, ...rest }])[0] as GridRowWithVerification;
if (verificationResult) row.verificationResult = verificationResult;
return row;
});
}
// 하수도 통계 관리 > 09. 하수도재정
const SewerageFinanceInp = () => {
const { setMessage: alert } = useAlertStore((state) => state);
const { confirm } = useConfirm();
const { isAdminInfo } = useAdminStore();
// tab list
const SewerageFinanceInpTabList = [
SewerageFinanceSettleInpColumn,
SewerageChargeInpColumn,
SewerageUsageFeeInpColumn,
CauserBurdenInpColumn
];
const [isLoading, setIsLoading] = useState(false);
const [activeTab, setActiveTab] = useState<string>(firstTabKey);
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(
new Map(),
);
const [searchValues, setSearchValues] = useState<SearchFormValues | null>(null);
const [lastSearchedValues, setLastSearchedValues] = useState<SearchFormValues | null>(null);
const [hasSearched, setHasSearched] = useState(false);
const [inputPeriodEnterable, setInputPeriodEnterable] = useState(true);
const [tabStatusInfoMap, setTabStatusInfoMap] = useState<
Map<string, SewerageStatusInfo | null>
>(new Map());
const [tabStatsCdMap, setTabStatsCdMap] = useState<Map<string, string>>(new Map());
const [toolbarSnapshotByTab, setToolbarSnapshotByTab] = useState<
Map<string, TabToolbarSnapshot>
>(new Map());
const [columnGuidesByTab, setColumnGuidesByTab] = useState<
Record<string, Record<string, string>>
>({});
const [verificationHistoryOpen, setVerificationHistoryOpen] = useState(false);
const [verificationResultDialogOpen, setVerificationResultDialogOpen] = useState(false);
const submitExceptionFunc = () => {
// 예외 제출 로직
const searchParamRef = useRef<SewerageFinanceRequestParams | null>(null);
const searchDoneRef = useRef(false);
const periodEnterableRef = useRef(true);
const activeTabRef = useRef(activeTab);
const getGridDataRef = useRef<(() => Record<string, string | number>[]) | null>(null);
activeTabRef.current = activeTab;
useEffect(() => {
let cancelled = false;
void (async () => {
const entries = await Promise.all(
SEWERAGE_FINANCE_COLUMN_GUIDE_TAB_KEYS.map(async (tabKey) => {
try {
const res = await statisticsApi.getColumnGuides(tabKey);
if (res.status !== "success" || !Array.isArray(res.data)) {
return [tabKey, {}] as const;
}
const next: Record<string, string> = {};
for (const item of res.data) {
const key = item.engColNm?.trim();
const guide = item.columnGuide?.trim();
if (key && guide) next[key] = guide;
}
return [tabKey, next] as const;
} catch {
return [tabKey, {}] as const;
}
}),
);
if (cancelled) return;
setColumnGuidesByTab(Object.fromEntries(entries));
})();
return () => {
cancelled = true;
};
}, []);
const commitToolbarSnapshotForLoadedTab = (
tabKey: string,
statusInfo: SewerageStatusInfo | null,
hasRowData: boolean,
searchContext: SearchFormValues,
) => {
setToolbarSnapshotByTab((prev) => {
const next = new Map(prev);
next.set(
tabKey,
computeTabToolbarSnapshot(
statusInfo,
hasRowData,
searchDoneRef.current,
searchContext,
periodEnterableRef.current,
isAdminInfo,
),
);
return next;
});
};
const lastYearDataFunc = () => {
// 지난연도 데이터 가져오기 로직
const applyRowMap = (
mergeIntoExistingMap: boolean,
apply: (m: Map<string, Record<string, string | number>[]>) => void,
) => {
if (mergeIntoExistingMap) {
setRowDataMap((prev) => {
const next = new Map(prev);
apply(next);
return next;
});
} else {
const next = new Map<string, Record<string, string | number>[]>();
apply(next);
setRowDataMap(next);
}
};
const loadActiveTabData = async (
tabKey: string,
param: SewerageFinanceRequestParams,
searchContext: SearchFormValues,
mergeIntoExistingMap: boolean,
updateLastSearchedValues: boolean,
overrides?: { mode?: string },
): Promise<boolean> => {
const requestParam = overrides?.mode ? { ...param, mode: overrides.mode } : param;
if (tabKey === SewerageFinanceSettleInpColumn.tabKey) {
const response =
await statisticsInputSewerageFinanceApi.getSewerageFinanceSettleList(requestParam);
if (response.status !== "success" || !response.data) {
alert(response.message || "데이터 조회 중 오류가 발생했습니다.");
return false;
}
const { commonInfo, statusInfo, sewerageFinanceSettleList } = response.data;
const gridRows = mapRegionalListToGridRows(
(sewerageFinanceSettleList ?? []) as SewerageFinanceSettleItem[],
commonInfo.ctpvNm,
);
applyRowMap(mergeIntoExistingMap, (m) => {
m.set(SewerageFinanceSettleInpColumn.tabKey, gridRows);
});
setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, statusInfo));
setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd));
if (updateLastSearchedValues) setLastSearchedValues(searchContext);
commitToolbarSnapshotForLoadedTab(tabKey, statusInfo, gridRows.length > 0, searchContext);
return true;
}
if (tabKey === SewerageChargeInpColumn.tabKey) {
const response =
await statisticsInputSewerageFinanceApi.getSewerageChargeList(requestParam);
if (response.status !== "success" || !response.data) {
alert(response.message || "데이터 조회 중 오류가 발생했습니다.");
return false;
}
const { commonInfo, statusInfo, sewerageChargeList } = response.data;
const gridRows = mapRegionalListToGridRows(
(sewerageChargeList ?? []) as SewerageChargeItem[],
commonInfo.ctpvNm,
);
applyRowMap(mergeIntoExistingMap, (m) => {
m.set(SewerageChargeInpColumn.tabKey, gridRows);
});
setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, statusInfo));
setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd));
if (updateLastSearchedValues) setLastSearchedValues(searchContext);
commitToolbarSnapshotForLoadedTab(tabKey, statusInfo, gridRows.length > 0, searchContext);
return true;
}
if (tabKey === SewerageUsageFeeInpColumn.tabKey) {
const response =
await statisticsInputSewerageFinanceApi.getSewerageUsageFeeList(requestParam);
if (response.status !== "success" || !response.data) {
alert(response.message || "데이터 조회 중 오류가 발생했습니다.");
return false;
}
const { commonInfo, statusInfo, sewerageUsageFeeList } = response.data;
const gridRows = mapRegionalListToGridRows(
(sewerageUsageFeeList ?? []) as SewerageUsageFeeItem[],
commonInfo.ctpvNm,
);
applyRowMap(mergeIntoExistingMap, (m) => {
m.set(SewerageUsageFeeInpColumn.tabKey, gridRows);
});
setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, statusInfo));
setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd));
if (updateLastSearchedValues) setLastSearchedValues(searchContext);
commitToolbarSnapshotForLoadedTab(tabKey, statusInfo, gridRows.length > 0, searchContext);
return true;
}
if (tabKey === CauserBurdenInpColumn.tabKey) {
const response =
await statisticsInputSewerageFinanceApi.getCauserBurdenList(requestParam);
if (response.status !== "success" || !response.data) {
alert(response.message || "데이터 조회 중 오류가 발생했습니다.");
return false;
}
const { commonInfo, statusInfo, causerBurdenList } = response.data;
const gridRows = mapRegionalListToGridRows(
(causerBurdenList ?? []) as CauserBurdenItem[],
commonInfo.ctpvNm,
);
applyRowMap(mergeIntoExistingMap, (m) => {
m.set(CauserBurdenInpColumn.tabKey, gridRows);
});
setTabStatusInfoMap((prev) => new Map(prev).set(tabKey, statusInfo));
setTabStatsCdMap((prev) => new Map(prev).set(tabKey, commonInfo.statsCd));
if (updateLastSearchedValues) setLastSearchedValues(searchContext);
commitToolbarSnapshotForLoadedTab(tabKey, statusInfo, gridRows.length > 0, searchContext);
return true;
}
alert("해당 탭 조회 API가 없습니다.");
return false;
};
const getTabGridRows = (tabKey: string): Record<string, string | number>[] =>
getGridDataRef.current?.() ?? rowDataMap.get(tabKey) ?? [];
const handleReset = () => {
setRowDataMap(new Map());
setTabStatusInfoMap(new Map());
setTabStatsCdMap(new Map());
setToolbarSnapshotByTab(new Map());
setActiveTab(firstTabKey);
activeTabRef.current = firstTabKey;
setLastSearchedValues(null);
setHasSearched(false);
setInputPeriodEnterable(true);
searchParamRef.current = null;
searchDoneRef.current = false;
periodEnterableRef.current = true;
};
const handleSearch = async (values: SearchFormValues) => {
if (!values.sido || values.sido === "ALL") {
alert("시도를 선택해주세요.");
return;
}
try {
const periodResponse = await statisticsInputSewSupplyRateApi.checkInputPeriod(
values.year || "",
);
if (periodResponse.status !== "success") {
alert(periodResponse.message);
return;
}
const periods = Array.isArray(periodResponse.data) ? periodResponse.data : [];
const periodOk = isInputPeriodCurrent(periods);
periodEnterableRef.current = periodOk;
setInputPeriodEnterable(periodOk);
const yearChangedFromLastSearch =
lastSearchedValues != null &&
(lastSearchedValues.year ?? "") !== (values.year ?? "");
if (yearChangedFromLastSearch) {
setRowDataMap(new Map());
setTabStatusInfoMap(new Map());
setTabStatsCdMap(new Map());
setToolbarSnapshotByTab(new Map());
activeTabRef.current = firstTabKey;
setActiveTab(firstTabKey);
}
setIsLoading(true);
searchDoneRef.current = true;
setHasSearched(true);
const searchParam = buildSewerageFinanceSearchParam(values);
searchParamRef.current = searchParam;
await loadActiveTabData(
activeTabRef.current,
searchParam,
values,
!yearChangedFromLastSearch,
true,
);
} catch {
alert("데이터 조회 중 오류가 발생했습니다.");
} finally {
setIsLoading(false);
}
};
const handleActiveTabChange = async (tabKey: string) => {
const prevTabKey = activeTabRef.current;
const latestRowsInPrevTab = getTabGridRows(prevTabKey);
if (latestRowsInPrevTab.length > 0 || rowDataMap.has(prevTabKey)) {
setRowDataMap((prev) => {
const next = new Map(prev);
next.set(prevTabKey, latestRowsInPrevTab);
return next;
});
}
activeTabRef.current = tabKey;
setActiveTab(tabKey);
if (!hasSearched || !lastSearchedValues || !searchParamRef.current) return;
if (tabRowDataExists(rowDataMap, tabKey)) return;
try {
setIsLoading(true);
await loadActiveTabData(
tabKey,
searchParamRef.current,
lastSearchedValues,
true,
false,
);
} catch {
alert("데이터 조회 중 오류가 발생했습니다.");
} finally {
setIsLoading(false);
}
};
const lastYearDataFunc = async () => {
const values = lastSearchedValues ?? searchValues;
if (!values?.sido || values.sido === "ALL") {
alert("시도를 선택해주세요.");
return;
}
if (!hasSearched) {
alert("먼저 데이터를 조회해주세요.");
return;
}
try {
setIsLoading(true);
const param = buildSewerageFinanceSearchParam(values, { mode: "PRE" });
await loadActiveTabData(
activeTabRef.current,
param,
values,
true,
false,
{ mode: "PRE" },
);
} catch {
alert("데이터 조회 중 오류가 발생했습니다.");
} finally {
setIsLoading(false);
}
};
const cnacelSubmitFunc = () => {
void (async () => {
try {
if (!(await confirm("제출된 내용을 취소하시겠습니까?"))) return;
if (!lastSearchedValues || !searchParamRef.current) {
alert("먼저 조회를 진행해주세요.");
return;
}
const userInfo = await getUserInfo();
const tabKey = activeTabRef.current;
const statsCdForTab = tabStatsCdMap.get(tabKey);
if (!statsCdForTab) {
alert("먼저 조회를 진행해주세요.");
return;
}
const requestData: cancelSubmitRequest = {
sewerBzmnCd: lastSearchedValues.bsnmCd ?? "",
ctpvNm: lastSearchedValues.sido ?? "",
sggNm:
lastSearchedValues.gugun === "ALL"
? ""
: (lastSearchedValues.gugun ?? ""),
statsYr: lastSearchedValues.year ?? "",
mdfrId: userInfo.userUnqId,
statsCd: statsCdForTab,
};
const response = await statisticsApi.cancelSubmit(requestData);
if (response.status === "success") {
setIsLoading(true);
await loadActiveTabData(
tabKey,
searchParamRef.current,
lastSearchedValues,
false,
false,
);
alert("제출 취소되었습니다.");
} else {
alert(response.message ?? "제출 취소 중 오류가 발생했습니다.");
}
} catch {
alert("제출 취소 중 오류가 발생했습니다.");
} finally {
setIsLoading(false);
}
})();
};
const submitFunc = () => {
@@ -39,26 +544,249 @@ const SewerageFinanceInp = () => {
// 저장 로직
};
const [rowDataMap, setRowDataMap] = useState<Map<string, Record<string, string | number>[]>>(new Map());
const openVerificationHistoryDialog = () => {
const ctx = lastSearchedValues ?? searchValues;
const statsCd = tabStatsCdMap.get(activeTab);
if (!ctx?.year || !ctx?.sido || !ctx?.bsnmCd || !statsCd) {
alert("먼저 조회를 진행해주세요.");
return;
}
setVerificationHistoryOpen(true);
};
const verificationQueryContext = (() => {
const ctx = lastSearchedValues ?? searchValues;
const statsCd = tabStatsCdMap.get(activeTab);
if (!ctx?.year || !ctx?.sido || !ctx?.bsnmCd || !statsCd) return null;
return {
sewerBzmnCd: ctx.bsnmCd,
ctpvNm: ctx.sido,
sggNm: ctx.gugun === "ALL" ? "" : (ctx.gugun ?? ""),
statsYr: ctx.year,
statsCd,
};
})();
const columnInfoByTab = useMemo(() => {
const map = new Map<string, ColumnInfo>();
for (const tab of SewerageFinanceInpTabList) {
const tabKey = tab.tabKey;
const canEdit =
computeTabEnterable(
tabStatusInfoMap.get(tabKey) ?? null,
inputPeriodEnterable,
) || isAdminInfo;
const rawColumns = (tab.columns ?? []) as ColumnConfig[];
const base = canEdit
? rawColumns
: rawColumns.map((col) => ({ ...col, editable: false as const }));
const columns = base.map((col) => {
const guide = columnGuidesByTab[tabKey]?.[col.fieldName]?.trim();
return guide ? { ...col, tooltip: guide } : col;
});
map.set(tabKey, {
columns,
columnLayout: tab.columnLayout ?? [],
});
}
return map;
}, [tabStatusInfoMap, inputPeriodEnterable, isAdminInfo, columnGuidesByTab]);
const activeTabStatus = tabStatusInfoMap.get(activeTab) ?? null;
const activeTabToolbar =
toolbarSnapshotByTab.get(activeTab) ??
computeTabToolbarSnapshot(
activeTabStatus,
tabRowDataExists(rowDataMap, activeTab),
hasSearched,
lastSearchedValues,
inputPeriodEnterable,
isAdminInfo,
);
const { showSaveInToolbar, showEnterableToolbarButtons, showActionToolbarCard } =
activeTabToolbar;
const verificationCellStyle = ({
fieldName,
row,
}: {
fieldName: string;
row: Record<string, string | number>;
}): string | undefined => {
const verification = (row as GridRowWithVerification).verificationResult;
if (!verification) return;
const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) {
const hasImr = errors.some((e) => e.vrfcCd === "IMR" || e.vrfcCd === "HB");
return hasImr ? "rg-cell-verify-error-imr" : "rg-cell-verify-error";
}
};
const verificationCellTooltip = ({
fieldName,
row,
}: {
fieldName: string;
row: Record<string, string | number>;
}): string | undefined => {
const verification = (row as GridRowWithVerification).verificationResult;
if (!verification) return;
const errors = verification[fieldName];
if (Array.isArray(errors) && errors.length > 0) {
return errors
.map((e) => {
const prefix =
e.vrfcCd === "IMR"
? "IMR검증 - "
: e.vrfcCd === "NV"
? "일반검증 - "
: "HB검증 - ";
return `${prefix}${e.rsnExpln}(검증 기준값: ${e.compVlCn} / 현재 입력값: ${e.nowVlCn})`;
})
.filter(Boolean)
.join("\n");
}
};
return (
<>
<SearchForm />
<div className="card !py-0">
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
<SubmitExceptionButton SubmitExceptionFunc={submitExceptionFunc} />
<LastYearDataButton getLastYearDataFunc={lastYearDataFunc} />
<SubmitButton submitFunc={submitFunc} />
<SaveButton saveFunc={saveFunc} />
<div className="relative">
<SearchForm
onSubmit={handleSearch}
onReset={handleReset}
onValuesChange={setSearchValues}
/>
{showActionToolbarCard && (
<div className="card !py-0">
<div className="flex justify-end items-center gap-[0.6rem] m-[0.6rem]">
<VerificationResultButton
VerificationResultButtonFunc={openVerificationHistoryDialog}
/>
{showEnterableToolbarButtons && (
<>
<LastYearDataButton
getLastYearDataFunc={() => void lastYearDataFunc()}
/>
<SubmitButton submitFunc={submitFunc} />
</>
)}
{activeTabStatus?.laeSbmsnSttsCd === "2" && (
<CancelSubmitButton cnacelSubmitFunc={cnacelSubmitFunc} />
)}
{showSaveInToolbar && <SaveButton saveFunc={saveFunc} />}
</div>
</div>
)}
{isLoading && (
<div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
<div className="relative size-[5rem]">
<LoadingWithAnimation color="primary" />
</div>
</div>
)}
<div className="flex flex-col gap-[0.6rem] mx-[0.6rem]">
<Tabs
value={activeTab}
onValueChange={(v) => void handleActiveTabChange(v)}
className="w-full"
variant="default"
>
<TabsList>
{SewerageFinanceInpTabList.map((info) => (
<TabsTrigger key={info.tabKey} value={info.tabKey}>
{info.tabLabel || info.tabKey}
</TabsTrigger>
))}
</TabsList>
{SewerageFinanceInpTabList.map((info) => {
const tabKey = info.tabKey;
const rowData = rowDataMap.get(tabKey) ?? [];
const tabEnterableForGrid =
computeTabEnterable(
tabStatusInfoMap.get(tabKey) ?? null,
inputPeriodEnterable,
) || isAdminInfo;
const gugunOk = buildGugunOkForToolbar(lastSearchedValues);
const tabStatusInfo = tabStatusInfoMap.get(tabKey) ?? null;
return (
<TabsContent key={tabKey} value={tabKey}>
<DataGrid
key={`${tabKey}-${tabEnterableForGrid ? "enterable" : "readonly"}`}
columnInfo={
columnInfoByTab.get(tabKey) ?? toGridColumnInfo(info)
}
rowStartNum={info.rowStartNum}
excelExportFileSuffix={info.tabLabel || tabKey}
rowData={rowData}
setRowData={(updater) => {
setRowDataMap((prev) => {
const next = new Map(prev);
const cur = next.get(tabKey) ?? [];
const n =
typeof updater === "function"
? updater(cur)
: updater;
next.set(tabKey, n);
return next;
});
}}
showHeaderCheckbox={false}
fixedColumns={info.fixedColumns}
enableSort={false}
statusInfo={tabStatusInfo}
isExcelImport={
tabRowDataExists(rowDataMap, tabKey) &&
tabEnterableForGrid &&
gugunOk
}
isExcelExport
cellStyleCallback={verificationCellStyle}
cellTooltipCallback={verificationCellTooltip}
getGridDataRef={
activeTab === tabKey ? getGridDataRef : undefined
}
/>
</TabsContent>
);
})}
</Tabs>
</div>
</div>
<TabDataGrid
columnInfo={SewerageFinanceInpTabList}
rowDataMap={rowDataMap}
setRowDataMap={setRowDataMap}
<VerificationResultHistoryDialog
open={verificationHistoryOpen}
onOpenChange={setVerificationHistoryOpen}
queryContext={verificationQueryContext}
onExceptionResetSubmitted={async () => {
const values = lastSearchedValues ?? searchValues;
if (!values || !searchParamRef.current) return;
await loadActiveTabData(
activeTabRef.current,
searchParamRef.current,
values,
true,
false,
);
}}
/>
<VerificationResultDialog
open={verificationResultDialogOpen}
onOpenChange={setVerificationResultDialogOpen}
queryContext={verificationQueryContext}
onExceptionSubmitted={async () => {
const values = lastSearchedValues ?? searchValues;
if (!values || !searchParamRef.current) return;
await loadActiveTabData(
activeTabRef.current,
searchParamRef.current,
values,
true,
false,
);
}}
/>
</>
);
};
export default SewerageFinanceInp;
export default SewerageFinanceInp;
@@ -288,7 +288,8 @@ const SeweragePenetrationRateInp = () => {
} else {
alert(response.message);
}
} catch {
} catch (error) {
console.log(error);
alert('데이터 조회 중 오류가 발생했습니다.');
setRowData([]);
setStatusInfo(null);
@@ -790,11 +791,13 @@ const SeweragePenetrationRateInp = () => {
</div>
</div>
)}
{isLoading && !globalProgressVisible && <div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
<div className="relative size-[5rem]">
<LoadingWithAnimation color="primary" />
{isLoading && !globalProgressVisible &&
<div className="absolute inset-0 z-50 [data-theme='black']:bg-transparent rounded-lg p-10 flex justify-center items-center">
<div className="relative size-[5rem]">
<LoadingWithAnimation color="primary" />
</div>
</div>
</div>}
}
<DataGrid
key={(isEnterable || isAdminInfo) ? 'enterable' : 'readonly'}
columnInfo={columnInfo}
@@ -859,6 +862,11 @@ const SeweragePenetrationRateInp = () => {
}
: null
}
onExceptionResetSubmitted={async () => {
const values = lastSearchedValues ?? searchValues;
if (!values) return;
await handleSearch(values);
}}
/>
<VerificationResultDialog
open={verificationResultDialogOpen}
+22 -1
View File
@@ -116,12 +116,22 @@ export type DataFieldValueCallback = (
/** 계산 필드 설정 (computedFieldCallbacks.ts 참고) */
export type ComputedFieldConfig =
| { fields: string[]; type: "sum" | "avg" | "max" | "difference" }
| { fields: string[]; type: "sum" | "avg" | "max" | "difference" | "quotient" }
| {
minuendFields: string[];
subtrahendFields: string[];
type: "differenceOfSums";
}
| {
firstSumFields: string[];
secondSumFields: string[];
type: "halfSumOfSums";
}
| {
firstHalfSum: { firstSumFields: string[]; secondSumFields: string[] };
secondHalfSum: { firstSumFields: string[]; secondSumFields: string[] };
type: "sumOfTwoHalfSumOfSums";
}
| {
baseField: string;
sumFields: string[];
@@ -157,6 +167,17 @@ export type ComputedFieldConfig =
perPpqtyField: string;
}>;
type: "pumpGrossPpqty";
}
| {
inflwField: string;
dschgField: string;
type: "bodPrcsRt";
}
| {
/** (quotient[0]/quotient[1]) / (denominatorQuotient[0]/denominatorQuotient[1]) × 100 */
numeratorQuotient: [string, string];
denominatorQuotient: [string, string];
type: "quotientRatioPercent";
};
export type ColumnConfig = {
@@ -8,58 +8,83 @@ import { ValueType } from "realgrid";
export const ExcretaTreatFactInpColumn = {
columns: [
// 행정구역
{ name: 'sido', fieldName: '시도', header: { text: '시도' }, editable: false },
{ name: 'gugun', fieldName: '시군구', header: { text: '시군구' }, footer: { text: '합계' } },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false },
{ name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' } },
// 기본 정보
{ name: 'ecscs_nm', fieldName: '시설명', header: { text: '시설명' } },
{ name: 'locplcs', fieldName: '소재지', header: { text: '소재지' } },
{ name: 'telno', fieldName: '전화번호', header: { text: '전화번호' } },
{ name: 'fcltNm', fieldName: 'fcltNm', header: { text: '시설명' } },
{ name: 'fcltPstnCn', fieldName: 'fcltPstnCn', header: { text: '소재지' } },
{ name: 'telNo', fieldName: 'telNo', 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: 'cmptnStrtYmd',
fieldName: 'cmptnStrtYmd',
header: { text: '준공일 yyyy-mm-dd' },
datetimeFormat: 'yyyy-MM-dd',
editor: {
type: 'date' as const,
dropDownWhenClick: true,
datetimeFormat: 'yyyy-MM-dd',
},
},
{
name: 'oprtngStrtYmd',
fieldName: 'oprtngStrtYmd',
header: { text: '가동개시일 yyyy-mm-dd' },
datetimeFormat: 'yyyy-MM-dd',
editor: {
type: 'date' as const,
dropDownWhenClick: true,
datetimeFormat: '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: 'wholPjtcoAmt', fieldName: 'wholPjtcoAmt', header: { text: '사업비(백만원)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'prcsFcltCpct', fieldName: 'prcsFcltCpct', header: { text: '시설용량(m³/일)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'cpct', fieldName: 'cpct', header: { text: '처리량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'oprtngDayCnt', fieldName: 'oprtngDayCnt', 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: 'prcsMthdExpln', fieldName: 'prcsMthdExpln', header: { text: '처리공법' } },
{ name: 'linkTmplntCn', fieldName: 'linkTmplntCn', header: { text: '연계처리장명' } },
{ name: 'linkPrcsQnt', fieldName: 'linkPrcsQnt', 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: 'inflwBodWqVl', fieldName: 'inflwBodWqVl', header: { text: 'BOD' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'inflwTocWqVl', fieldName: 'inflwTocWqVl', header: { text: 'TOC' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'inflwSsWqVl', fieldName: 'inflwSsWqVl', header: { text: 'SS' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'inflwTnWqVl', fieldName: 'inflwTnWqVl', header: { text: 'T-N' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
{ name: 'inflwTpWqVl', fieldName: 'inflwTpWqVl', header: { text: 'T-P' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
{ name: 'inflwClfgCnt', fieldName: 'inflwClfgCnt', 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: 'dschgBodWqVl', fieldName: 'dschgBodWqVl', header: { text: 'BOD' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'dschgTocWqVl', fieldName: 'dschgTocWqVl', header: { text: 'TOC' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'dschgSsWqVl', fieldName: 'dschgSsWqVl', header: { text: 'SS' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'dschgTnWqVl', fieldName: 'dschgTnWqVl', header: { text: 'T-N' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
{ name: 'dschgTpWqVl', fieldName: 'dschgTpWqVl', header: { text: 'T-P' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
{ name: 'dschgClfgCnt', fieldName: 'dschgClfgCnt', 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: 'wtsysNm', fieldName: 'wtsysNm', header: { text: '수계' } },
{ name: 'trbtrNm', fieldName: 'trbtrNm', header: { text: '지류' } },
{ name: 'msirbCn', fieldName: 'msirbCn', header: { text: '중권역' } },
{ name: 'ssirbCn', fieldName: 'ssirbCn', 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: 'operMthdCdCn', fieldName: 'operMthdCdCn', header: { text: '운영주체(자체/공기업/민간위탁)' } },
{ name: 'wholNope', fieldName: 'wholNope', header: { text: '직원총수(명)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'sftyAcdntEvntcsCnt', fieldName: 'sftyAcdntEvntcsCnt', header: { text: '안전사고건수(건/인/년)' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
// 비고
{ name: 'rmk', fieldName: '비고', header: { text: '비고' } },
{ name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } },
// Hidden Columns : 시스템 관리를 위한 값
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
{ name: 'fcltSn', fieldName: 'fcltSn', header: { text: '시설일련번호' }, visible: false, },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false },
],
columnLayout: [
@@ -67,41 +92,51 @@ export const ExcretaTreatFactInpColumn = {
name: 'adminGroup',
hideChildHeaders: false,
header: { text: '행정구역' },
items: ['sido', 'gugun'],
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
'ecscs_nm',
'locplcs',
'telno',
'comp_dt',
'rn_dt',
'wct',
'ecscs_cpcty',
'process_cpcty',
'opr_daycnt',
'trt_msrc',
'cntc_prcplt',
'assct_trt_cpc',
'fcltNm',
'fcltPstnCn',
'telNo',
'cmptnStrtYmd',
'oprtngStrtYmd',
'wholPjtcoAmt',
'prcsFcltCpct',
'cpct',
'oprtngDayCnt',
'prcsMthdExpln',
'linkTmplntCn',
'linkPrcsQnt',
{
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'],
items: ['inflwBodWqVl', 'inflwTocWqVl', 'inflwSsWqVl', 'inflwTnWqVl', 'inflwTpWqVl', 'inflwClfgCnt'],
},
{
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'],
items: ['dschgBodWqVl', 'dschgTocWqVl', 'dschgSsWqVl', 'dschgTnWqVl', 'dschgTpWqVl', 'dschgClfgCnt'],
},
{
name: 'dischargeGroup',
hideChildHeaders: false,
header: { text: '방류수역' },
items: ['rvbsn', 'bstrm', 'lgbsn', 'mdmbsn'],
items: ['wtsysNm', 'trbtrNm', 'msirbCn', 'ssirbCn'],
},
'oper_mth',
'cntc_prcplt_cpc',
'safe_acdnt_co',
'rmk',
]
'operMthdCdCn',
'wholNope',
'sftyAcdntEvntcsCnt',
'rmrk',
'admdstCd',
'fcltSn',
'admdstNm'
],
rowStartNum: 2,
fixedColumns: 2,
tabKey: 'ST00070001',
};
@@ -8,7 +8,7 @@ import { footerDecimal1, footerDecimal3,footerInt } from "@/components/util/grid
export const PublicSewageFactColumn = {
columns: [
// 행정구역
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, editable: false, styleName: 'rg-cell-readonly' },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false, styleName: 'rg-cell-readonly' },
{ name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, editable: false, footer: { text: '합계' }, styleName: 'rg-cell-readonly' },
// 시설명
@@ -18,7 +18,20 @@ export const PublicSewageFactColumn = {
{ name: 'fcltPstnCn', fieldName: 'fcltPstnCn', header: { text: '소재지' }, editable: false, styleName: 'rg-cell-readonly' },
// 시설용량
{ name: 'prcsFcltCpct', fieldName: 'prcsFcltCpct', header: { text: '시설용량(500m³/일 이상/미만)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-total' },
{
name: 'prcsFcltCpct',
fieldName: 'prcsFcltCpct',
header: { text: '시설용량(500m³/일 이상/미만)' },
editable: false,
footer: footerDecimal1,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
fields: ['prcsFcltPhysCpct', 'prcsFcltBoilCpct', 'prcsFcltAltdCpct'],
type: 'sum' as const,
},
},
// (m³/일)
{ name: 'prcsFcltPhysCpct', fieldName: 'prcsFcltPhysCpct', header: { text: '물리적' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
@@ -56,8 +69,22 @@ export const PublicSewageFactColumn = {
{ name: 'dschgGrssClfgVl', fieldName: 'dschgGrssClfgVl', header: { text: '방류총대장균군수' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
// 처리특성
{ name: 'prcsRt', fieldName: 'prcsRt', header: { text: '처리효율(%)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-total' },
{ name: 'prcsLodQnt', fieldName: 'prcsLodQnt', header: { text: '처리부하량(kgBOD/D)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-total' },
{
name: 'prcsRt',
fieldName: 'prcsRt',
header: { text: '처리효율(%)' },
editable: false,
footer: footerDecimal1,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
inflwField: 'inflwBodVl',
dschgField: 'dschgBodVl',
type: 'bodPrcsRt' as const,
},
},
{ name: 'prcsLodQnt', fieldName: 'prcsLodQnt', header: { text: '처리부하량(kgBOD/D)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
{ name: 'prcsMthdExpln', fieldName: 'prcsMthdExpln', header: { text: '처리방법' }, editable: false, styleName: 'rg-cell-readonly' },
// 연계처리량
@@ -86,7 +113,20 @@ export const PublicSewageFactColumn = {
{ name: 'goalWqNo', fieldName: 'goalWqNo', header: { text: '목표수질(BOD)' }, editable: false, styleName: 'rg-cell-readonly' },
// 에너지 자립률
{ name: 'engySrlneRt', fieldName: 'engySrlneRt', header: { text: '에너지자립률(%)' }, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
{
name: 'engySrlneRt',
fieldName: 'engySrlneRt',
header: { text: '에너지자립률(%)' },
editable: false,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
numeratorFields: ['engyItslfPrdctnQnt'],
denominatorFields: ['anlEngyWholUseQnt'],
type: 'pblswrgPopltnSuprtRate' as const,
},
},
// 에너지 자체 생산량
{ name: 'engyItslfPrdctnQnt', fieldName: 'engyItslfPrdctnQnt', header: { text: '에너지자체생산량(TOE)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
@@ -97,7 +137,7 @@ export const PublicSewageFactColumn = {
{ name: 'itslfEngyUseQnt', fieldName: 'itslfEngyUseQnt', header: { text: '자체 에너지사용량(TOE)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0', styleName: 'rg-cell-readonly' },
// 하수처리량당 CO2배출량
{ name: 'swtrmtEmsnQnt', fieldName: 'swtrmtEmsnQnt', header: { text: '하수처리량당 CO2배출량(kgCO2/m³)' }, editable: false, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000', styleName: 'rg-cell-total' },
{ name: 'swtrmtEmsnQnt', fieldName: 'swtrmtEmsnQnt', header: { text: '하수처리량당 CO2배출량(kgCO2/m³)' }, editable: false, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000', styleName: 'rg-cell-readonly' },
// 운영주체
{ name: 'operMnbdCn', fieldName: 'operMnbdCn', header: { text: '운영주체(자체/공기업/민간대행)' }, editable: false, styleName: 'rg-cell-readonly' },
@@ -123,7 +163,10 @@ export const PublicSewageFactColumn = {
name: 'administrative',
hideChildHeaders: false,
header: { text: '행정구역' },
items: ['ctpvNm', 'sggNm'],
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
'swtrmtFcltNm',
'fcltPstnCn',
@@ -1,6 +1,33 @@
import type { ColumnConfig } from "@/components/type/DataGrid.type";
import { footerInt, footerDecimal1, footerDecimal3 } from "@/components/util/grid/footerSummary";
import { ValueType } from "realgrid";
/** 펌프장 구분(`pumpSeNm`) */
export const PUMPING_STATION_PUMP_SE_VALUES = ["합류식", "분류식"] as const;
function dropdownColumn(
col: Pick<ColumnConfig, "name" | "fieldName" | "header"> &
Partial<ColumnConfig>,
options: readonly string[],
): ColumnConfig {
const values = [...options];
return {
...col,
values,
labels: values,
lookupDisplay: true,
editor: {
type: "dropdown",
domainOnly: true,
textReadOnly: true,
commitOnSelect: true,
dropDownWhenClick: true,
values,
labels: values,
},
};
}
/**
* 하수도 통계 관리 > 05. 펌프장
* 단일 Tab
@@ -14,18 +41,70 @@ export const PumpingStationInpColumn = {
// 기본 정보
{ name: 'swtrmtFcltNm', fieldName: 'swtrmtFcltNm', header: { text: '처리장명' } },
{ name: 'fcltNm', fieldName: 'fcltNm', header: { text: '시설명' } },
{ name: 'pumpSeNm', fieldName: 'pumpSeNm', header: { text: '구분(합류식 분류식)' } },
dropdownColumn(
{ name: 'pumpSeNm', fieldName: 'pumpSeNm', header: { text: '구분(합류식 분류식)' } },
PUMPING_STATION_PUMP_SE_VALUES,
),
{ name: 'fcltPstnCn', fieldName: 'fcltPstnCn', header: { text: '위치' } },
{ name: 'oprtngStrtYmd', fieldName: 'oprtngStrtYmd', header: { text: '가동 년월일 yyyy-mm-dd' } },
{
name: 'oprtngStrtYmd',
fieldName: 'oprtngStrtYmd',
header: { text: '가동 년월일 yyyy-mm-dd' },
datetimeFormat: 'yyyy-MM-dd',
editor: {
type: 'date' as const,
dropDownWhenClick: true,
datetimeFormat: 'yyyy-MM-dd',
},
},
{ name: 'planMltvArea', fieldName: 'planMltvArea', header: { text: '계획배수면적(㎢)' }, footer: footerDecimal3, valueType: ValueType.NUMBER, dataFormat: '#,##0.000' },
// 계획시간 대 최대배수량
{ name: 'sndyArea', fieldName: 'sndyArea', header: { text: '청천시(A)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'rainArea', fieldName: 'rainArea', header: { text: '우천시(B)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'exlnQnt', fieldName: 'exlnQnt', header: { text: '우수량(B-A)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{
name: 'exlnQnt',
fieldName: 'exlnQnt',
header: { text: '우수량(B-A)' },
footer: footerDecimal1,
editable: false,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
computed: { fields: ['rainArea', 'sndyArea'], type: 'difference' as const },
styleName: 'rg-cell-total',
},
// 배수능력 > 총 양수량 (오수)
{ name: 'drtwPumpGrssPpqty', fieldName: 'drtwPumpGrssPpqty', header: { text: '총양수량(m³/min)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{
name: 'drtwPumpGrssPpqty',
fieldName: 'drtwPumpGrssPpqty',
header: { text: '총양수량(m³/min)' },
footer: footerDecimal1,
editable: false,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
type: 'pumpGrossPpqty' as const,
pumpGroups: [
{
pumpCntField: 'drtwPumpN1Cnt',
rsrvPumpCntField: 'drtwPumpN1RsrvCnt',
perPpqtyField: 'drtwPumpN1Ppqty',
},
{
pumpCntField: 'drtwPumpN2Cnt',
rsrvPumpCntField: 'drtwPumpN2RsrvCnt',
perPpqtyField: 'drtwPumpN2Ppqty',
},
{
pumpCntField: 'drtwPumpN3Cnt',
rsrvPumpCntField: 'drtwPumpN3RsrvCnt',
perPpqtyField: 'drtwPumpN3Ppqty',
},
],
},
},
// 배수능력 > 오수펌프(1)
{ name: 'drtwPumpN1DmtrArea', fieldName: 'drtwPumpN1DmtrArea', header: { text: '구경(mm)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
@@ -46,7 +125,36 @@ export const PumpingStationInpColumn = {
{ name: 'drtwPumpN3RsrvCnt', fieldName: 'drtwPumpN3RsrvCnt', header: { text: '예비펌프대수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
// 배수능력 > 총 양수량 (우수)
{ name: 'exlnPumpGrssPpqty', fieldName: 'exlnPumpGrssPpqty', header: { text: '총양수량(m³/min)' }, footer: footerDecimal1, editable: false, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{
name: 'exlnPumpGrssPpqty',
fieldName: 'exlnPumpGrssPpqty',
header: { text: '총양수량(m³/min)' },
footer: footerDecimal1,
editable: false,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
type: 'pumpGrossPpqty' as const,
pumpGroups: [
{
pumpCntField: 'exlnPumpN1Cnt',
rsrvPumpCntField: 'exlnPumpN1RsrvCnt',
perPpqtyField: 'exlnPumpN1Ppqty',
},
{
pumpCntField: 'exlnPumpN2Cnt',
rsrvPumpCntField: 'exlnPumpN2RsrvCnt',
perPpqtyField: 'exlnPumpN2Ppqty',
},
{
pumpCntField: 'exlnPumpN3Cnt',
rsrvPumpCntField: 'exlnPumpN3RsrvCnt',
perPpqtyField: 'exlnPumpN3Ppqty',
},
],
},
},
// 배수능력 > 우수펌프(1)
{ name: 'exlnPumpN1DmtrArea', fieldName: 'exlnPumpN1DmtrArea', header: { text: '구경(mm)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
@@ -83,7 +191,10 @@ export const PumpingStationInpColumn = {
name: 'administrativeArea',
hideChildHeaders: false,
header: { text: '행정구역' },
items: ['ctpvNm', 'sggNm'],
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
'swtrmtFcltNm',
'fcltNm',
@@ -147,5 +258,8 @@ export const PumpingStationInpColumn = {
'admdstCd',
'fcltSn',
'admdstNm'
]
],
rowStartNum: 3,
fixedColumns: 3,
tabKey: 'ST00050001',
};
@@ -5,66 +5,64 @@ import { ValueType } from "realgrid";
export const PrivateSewageDesigStatusInpColumn = {
columns: [
// 행정구역
{ name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false },
{ name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false, styleName: 'rg-cell-readonly' },
{ name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, editable: false, styleName: 'rg-cell-readonly' },
// 개인하수도관리지역공고현황
{ name: '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: 'indvSwagePbancRgnCnt', fieldName: 'indvSwagePbancRgnCnt', header: { text: '공고지역(개소)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'indvSwageDsgnScpLen', fieldName: 'indvSwageDsgnScpLen', 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: 'spctnkGrssFcltCnt', fieldName: 'spctnkGrssFcltCnt', header: { text: '개소수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'spctnkQnt', fieldName: 'spctnkQnt', 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: 'drtwPrcsFcltGrssFcltCnt', fieldName: 'drtwPrcsFcltGrssFcltCnt', header: { text: '개소수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'drtwPrcsFcltQnt', fieldName: 'drtwPrcsFcltQnt', header: { text: '처리용량(m³/일)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
// 비고
{ name: 'RMK', fieldName: '비고', header: { text: '비고' } },
{ name: 'rmrk', fieldName: 'rmrk', 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: '검토자의견' } },
// hidden
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false },
],
columnLayout: [
{
name: 'group_admin',
header: { text: '행정구역' },
items: ['SIDO', 'GUGUN']
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
{
name: 'group_notice',
header: { text: '개인하수도관리지역공고현황 (하수도법제34조의2)' },
items: [
'MGMT_AR',
'APPN_SCOPE',
'indvSwagePbancRgnCnt',
'indvSwageDsgnScpLen',
{
name: 'group_septic',
header: { text: '정화조' },
items: [
'STTY_CNT',
'STTY_CPC'
'spctnkGrssFcltCnt',
'spctnkQnt'
]
},
{
name: 'group_sewage',
header: { text: '오수시설' },
items: [
'WRRTN_CNT',
'WRRTN_CPC'
'drtwPrcsFcltGrssFcltCnt',
'drtwPrcsFcltQnt'
]
}
]
},
'RMK'
'rmrk',
'admdstCd',
'admdstNm'
],
rowStartNum: 3,
fixedColumns: 1,
@@ -5,182 +5,316 @@ import { ValueType } from "realgrid";
export const SepticTankStatusInpColumn = {
columns: [
// 행정구역
{ name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false },
{ name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false, styleName: 'rg-cell-readonly' },
{ name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, editable: false, styleName: 'rg-cell-readonly' },
// 총 시설 수
{ name: 'TOT_FCLTY_CNT', fieldName: '총 시설 수 (A+D)', header: { text: '총 시설 수 (A+D)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
// 총 시설 수 — (B+C)/2 + (E+F)/2 = A + D
{
name: 'grssFcltCnt',
fieldName: 'grssFcltCnt',
header: { text: '총 시설 수 (A+D)' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
firstHalfSum: {
firstSumFields: [
'staaInsdSttkNprsflCnt',
'step1StaaInsdSttkFrcCnt',
'staaInsdSprktpFltrtbCnt',
'staaInsdAertMthdCnt',
'staaInsdCntcAertCnt',
'staaInsdEtcCnt',
],
secondSumFields: [
'step1StaaInsdNope',
'step2StaaInsdNope',
'step3StaaInsdNope',
'step4StaaInsdNope',
'step5StaaInsdNope',
'step6StaaInsdNope',
'step7StaaInsdNope',
'step8StaaInsdNope',
],
},
secondHalfSum: {
firstSumFields: [
'staaExcpSttkNprsflCnt',
'step1StaaExcpSttkFrcCnt',
'staaExcpSprktpFltrtbCnt',
'staaExcpAertMthdCnt',
'staaExcpCntcAertCnt',
'staaExcpEtcCnt',
],
secondSumFields: [
'step1StaaExcpNope',
'step2StaaExcpNope',
'step3StaaExcpNope',
'step4StaaExcpNope',
'step5StaaExcpNope',
'step6StaaExcpNope',
'step7StaaExcpNope',
'step8StaaExcpNope',
],
},
type: 'sumOfTwoHalfSumOfSums' as const,
},
},
// 하수처리구역 내 > 총계
{ name: 'SPZI_SM', fieldName: '총계 A=(B+C)/2', header: { text: '총계 A=(B+C)/2' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{
name: 'staaInsdWhol',
fieldName: 'staaInsdWhol',
header: { text: '총계 A=(B+C)/2' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
firstSumFields: [
'staaInsdSttkNprsflCnt',
'step1StaaInsdSttkFrcCnt',
'staaInsdSprktpFltrtbCnt',
'staaInsdAertMthdCnt',
'staaInsdCntcAertCnt',
'staaInsdEtcCnt',
],
secondSumFields: [
'step1StaaInsdNope',
'step2StaaInsdNope',
'step3StaaInsdNope',
'step4StaaInsdNope',
'step5StaaInsdNope',
'step6StaaInsdNope',
'step7StaaInsdNope',
'step8StaaInsdNope',
],
type: 'halfSumOfSums' as const,
},
},
// 하수처리구역 내 > 처리방식별
{ name: 'SPZI_MTHD_SM', fieldName: '계(B)', header: { text: '계(B)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{
name: 'staaInsdPrcsMthByWhol',
fieldName: 'staaInsdPrcsMthByWhol',
header: { text: '계(B)' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
fields: [
'staaInsdSttkNprsflCnt',
'step1StaaInsdSttkFrcCnt',
'staaInsdSprktpFltrtbCnt',
'staaInsdAertMthdCnt',
'staaInsdCntcAertCnt',
'staaInsdEtcCnt',
],
type: 'sum' as const,
},
},
// 하수처리구역 내 > 처리방식별 > 부패탱크
{ 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: 'staaInsdSttkNprsflCnt', fieldName: 'staaInsdSttkNprsflCnt', header: { text: '자연유하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step1StaaInsdSttkFrcCnt', fieldName: 'step1StaaInsdSttkFrcCnt', 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: 'staaInsdSprktpFltrtbCnt', fieldName: 'staaInsdSprktpFltrtbCnt', header: { text: '살수여상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'staaInsdAertMthdCnt', fieldName: 'staaInsdAertMthdCnt', header: { text: '폭기방법' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'staaInsdCntcAertCnt', fieldName: 'staaInsdCntcAertCnt', header: { text: '접촉폭기' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'staaInsdEtcCnt', fieldName: 'staaInsdEtcCnt', 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: 'staaInsdPrcsCpctByWhol',
fieldName: 'staaInsdPrcsCpctByWhol',
header: { text: '계(C)' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
fields: [
'step1StaaInsdNope',
'step2StaaInsdNope',
'step3StaaInsdNope',
'step4StaaInsdNope',
'step5StaaInsdNope',
'step6StaaInsdNope',
'step7StaaInsdNope',
'step8StaaInsdNope',
],
type: 'sum' as const,
},
},
{ name: 'step1StaaInsdNope', fieldName: 'step1StaaInsdNope', header: { text: '10인조이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step2StaaInsdNope', fieldName: 'step2StaaInsdNope', header: { text: '11~20' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step3StaaInsdNope', fieldName: 'step3StaaInsdNope', header: { text: '21~30' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step4StaaInsdNope', fieldName: 'step4StaaInsdNope', header: { text: '31~50' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step5StaaInsdNope', fieldName: 'step5StaaInsdNope', header: { text: '51~199' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step6StaaInsdNope', fieldName: 'step6StaaInsdNope', header: { text: '200~499' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step7StaaInsdNope', fieldName: 'step7StaaInsdNope', header: { text: '500~999' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step8StaaInsdNope', fieldName: 'step8StaaInsdNope', 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: 'staaExcpWhol',
fieldName: 'staaExcpWhol',
header: { text: '총계 D=(E+F)/2' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
firstSumFields: [
'staaExcpSttkNprsflCnt',
'step1StaaExcpSttkFrcCnt',
'staaExcpSprktpFltrtbCnt',
'staaExcpAertMthdCnt',
'staaExcpCntcAertCnt',
'staaExcpEtcCnt',
],
secondSumFields: [
'step1StaaExcpNope',
'step2StaaExcpNope',
'step3StaaExcpNope',
'step4StaaExcpNope',
'step5StaaExcpNope',
'step6StaaExcpNope',
'step7StaaExcpNope',
'step8StaaExcpNope',
],
type: 'halfSumOfSums' as const,
},
},
// 하수처리구역 외 > 처리방식별
{ name: 'SPZO_MTHD_SM', fieldName: '계(E)', header: { text: '계(E)' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{
name: 'staaExcpPrcsMthByWhol',
fieldName: 'staaExcpPrcsMthByWhol',
header: { text: '계(E)' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
fields: [
'staaExcpSttkNprsflCnt',
'step1StaaExcpSttkFrcCnt',
'staaExcpSprktpFltrtbCnt',
'staaExcpAertMthdCnt',
'staaExcpCntcAertCnt',
'staaExcpEtcCnt',
],
type: 'sum' as const,
},
},
// 하수처리구역 외 > 처리방식별 > 부패탱크
{ 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: 'staaExcpSttkNprsflCnt', fieldName: 'staaExcpSttkNprsflCnt', header: { text: '자연유하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step1StaaExcpSttkFrcCnt', fieldName: 'step1StaaExcpSttkFrcCnt', 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: 'staaExcpSprktpFltrtbCnt', fieldName: 'staaExcpSprktpFltrtbCnt', header: { text: '살수여상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'staaExcpAertMthdCnt', fieldName: 'staaExcpAertMthdCnt', header: { text: '폭기방법' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'staaExcpCntcAertCnt', fieldName: 'staaExcpCntcAertCnt', header: { text: '접촉폭기' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'staaExcpEtcCnt', fieldName: 'staaExcpEtcCnt', 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: 'staaExcpPrcsCpctByWhol',
fieldName: 'staaExcpPrcsCpctByWhol',
header: { text: '계(F)' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
fields: [
'step1StaaExcpNope',
'step2StaaExcpNope',
'step3StaaExcpNope',
'step4StaaExcpNope',
'step5StaaExcpNope',
'step6StaaExcpNope',
'step7StaaExcpNope',
'step8StaaExcpNope',
],
type: 'sum' as const,
},
},
{ name: 'step1StaaExcpNope', fieldName: 'step1StaaExcpNope', header: { text: '10인조이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step2StaaExcpNope', fieldName: 'step2StaaExcpNope', header: { text: '11~20' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step3StaaExcpNope', fieldName: 'step3StaaExcpNope', header: { text: '21~30' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step4StaaExcpNope', fieldName: 'step4StaaExcpNope', header: { text: '31~50' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step5StaaExcpNope', fieldName: 'step5StaaExcpNope', header: { text: '51~199' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step6StaaExcpNope', fieldName: 'step6StaaExcpNope', header: { text: '200~499' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step7StaaExcpNope', fieldName: 'step7StaaExcpNope', header: { text: '500~999' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step8StaaExcpNope', fieldName: 'step8StaaExcpNope', header: { text: '1,000 이상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
// 비고
{ name: 'RMK', fieldName: '비고', header: { text: '비고' } },
{ name: 'rmrk', fieldName: 'rmrk', 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: '' } },
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false },
],
columnLayout: [
{
name: 'group_admin',
header: { text: '행정구역' },
items: ['SIDO', 'GUGUN']
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
'TOT_FCLTY_CNT',
'grssFcltCnt',
{
name: 'group_spzi',
header: { text: '하수처리구역 내' },
items: [
'SPZI_SM',
'staaInsdWhol',
{
name: 'group_spzi_mthd',
header: { text: '처리방식별' },
items: [
'SPZI_MTHD_SM',
'staaInsdPrcsMthByWhol',
{
name: 'group_spzi_rot',
header: { text: '부패탱크' },
items: [
'SPZI_ROT_NPFL_CNT',
'SPZI_ROT_ENFCT_PUMP_1'
'staaInsdSttkNprsflCnt',
'step1StaaInsdSttkFrcCnt'
]
},
'SPZI_WTROT_NPFL_CNT',
'SPZI_TFM',
'SPZI_ARTM',
'SPZI_CTARM'
'staaInsdSprktpFltrtbCnt',
'staaInsdAertMthdCnt',
'staaInsdCntcAertCnt',
'staaInsdEtcCnt'
]
},
{
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'
'staaInsdPrcsCpctByWhol',
'step1StaaInsdNope',
'step2StaaInsdNope',
'step3StaaInsdNope',
'step4StaaInsdNope',
'step5StaaInsdNope',
'step6StaaInsdNope',
'step7StaaInsdNope',
'step8StaaInsdNope'
]
}
]
@@ -189,47 +323,49 @@ export const SepticTankStatusInpColumn = {
name: 'group_spzo',
header: { text: '하수처리구역 외' },
items: [
'SPZO_SM',
'staaExcpWhol',
{
name: 'group_spzo_mthd',
header: { text: '처리방식별' },
items: [
'SPZO_MTHD_SM',
'staaExcpPrcsMthByWhol',
{
name: 'group_spzo_rot',
header: { text: '부패탱크' },
items: [
'SPZO_ROT_NPFL_CNT',
'SPZO_ROT_ENFCT_PUMP_1'
'staaExcpSttkNprsflCnt',
'step1StaaExcpSttkFrcCnt'
]
},
'SPZO_WTROT_NPFL_CNT',
'SPZO_TFM',
'SPZO_ARTM',
'SPZO_CTARM'
'staaExcpSprktpFltrtbCnt',
'staaExcpAertMthdCnt',
'staaExcpCntcAertCnt',
'staaExcpEtcCnt'
]
},
{
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'
'staaExcpPrcsCpctByWhol',
'step1StaaExcpNope',
'step2StaaExcpNope',
'step3StaaExcpNope',
'step4StaaExcpNope',
'step5StaaExcpNope',
'step6StaaExcpNope',
'step7StaaExcpNope',
'step8StaaExcpNope'
]
}
]
},
'RMK'
'rmrk',
'admdstCd',
'admdstNm'
],
rowStartNum: 4,
fixedColumns: 1,
tabKey: 'septicTankStatusInp',
tabKey: 'ST00080002',
tabLabel: '정화조 현황'
};
@@ -5,65 +5,119 @@ import { ValueType } from "realgrid";
export const SewageTreatFactStatusInpColumn = {
columns: [
// 행정구역
{ name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false },
{ name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false, styleName: 'rg-cell-readonly' },
{ name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' }, editable: false, styleName: 'rg-cell-readonly' },
// 총계
{ name: 'STTY_SM', fieldName: '총계', header: { text: '총계' }, editable: false, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{
name: 'wholDrtwPrcsFcltCnt',
fieldName: 'wholDrtwPrcsFcltCnt',
header: { text: '총계' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
fields: [
'step1StaaPrcsQnt',
'step2StaaPrcsQnt',
'step3StaaPrcsQnt',
'step4StaaPrcsQnt',
'step5StaaPrcsQnt',
'step6StaaPrcsQnt',
'step7StaaPrcsQnt',
'step1StaaExcpPrcsQnt',
'step2StaaExcpPrcsQnt',
'step3StaaExcpPrcsQnt',
'step4StaaExcpPrcsQnt',
'step5StaaExcpPrcsQnt',
'step6StaaExcpPrcsQnt',
'step7StaaExcpPrcsQnt',
],
type: 'sum' as const,
},
},
// 오수처리시설 > 하수처리구역 내(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' },
{
name: 'wholStaaCnt',
fieldName: 'wholStaaCnt',
header: { text: '계' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
fields: [
'step1StaaPrcsQnt',
'step2StaaPrcsQnt',
'step3StaaPrcsQnt',
'step4StaaPrcsQnt',
'step5StaaPrcsQnt',
'step6StaaPrcsQnt',
'step7StaaPrcsQnt',
],
type: 'sum' as const,
},
},
{ name: 'step1StaaPrcsQnt', fieldName: 'step1StaaPrcsQnt', header: { text: '2이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step2StaaPrcsQnt', fieldName: 'step2StaaPrcsQnt', header: { text: '3~10' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step3StaaPrcsQnt', fieldName: 'step3StaaPrcsQnt', header: { text: '11~20' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step4StaaPrcsQnt', fieldName: 'step4StaaPrcsQnt', header: { text: '21~50' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step5StaaPrcsQnt', fieldName: 'step5StaaPrcsQnt', header: { text: '51~100' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step6StaaPrcsQnt', fieldName: 'step6StaaPrcsQnt', header: { text: '101~500' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step7StaaPrcsQnt', fieldName: 'step7StaaPrcsQnt', 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: 'staaExcpWhol',
fieldName: 'staaExcpWhol',
header: { text: '계' },
editable: false,
footer: footerInt,
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
styleName: 'rg-cell-total',
computed: {
fields: [
'step1StaaExcpPrcsQnt',
'step2StaaExcpPrcsQnt',
'step3StaaExcpPrcsQnt',
'step4StaaExcpPrcsQnt',
'step5StaaExcpPrcsQnt',
'step6StaaExcpPrcsQnt',
'step7StaaExcpPrcsQnt',
],
type: 'sum' as const,
},
},
{ name: 'step1StaaExcpPrcsQnt', fieldName: 'step1StaaExcpPrcsQnt', header: { text: '2이하' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step2StaaExcpPrcsQnt', fieldName: 'step2StaaExcpPrcsQnt', header: { text: '3~10' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step3StaaExcpPrcsQnt', fieldName: 'step3StaaExcpPrcsQnt', header: { text: '11~20' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step4StaaExcpPrcsQnt', fieldName: 'step4StaaExcpPrcsQnt', header: { text: '21~50' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step5StaaExcpPrcsQnt', fieldName: 'step5StaaExcpPrcsQnt', header: { text: '51~100' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step6StaaExcpPrcsQnt', fieldName: 'step6StaaExcpPrcsQnt', header: { text: '101~500' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'step7StaaExcpPrcsQnt', fieldName: 'step7StaaExcpPrcsQnt', header: { text: '501이상' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
// 비고
{ name: 'RMK', fieldName: '비고', header: { text: '비고' } },
{ name: 'rmrk', fieldName: 'rmrk', 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: '' } },
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false },
],
columnLayout: [
{
name: 'group_admin',
header: { text: '행정구역' },
items: ['SIDO', 'GUGUN']
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
'STTY_SM',
'wholDrtwPrcsFcltCnt',
{
name: 'group_stty',
header: { text: '오수처리시설' },
@@ -72,36 +126,38 @@ export const SewageTreatFactStatusInpColumn = {
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'
'wholStaaCnt',
'step1StaaPrcsQnt',
'step2StaaPrcsQnt',
'step3StaaPrcsQnt',
'step4StaaPrcsQnt',
'step5StaaPrcsQnt',
'step6StaaPrcsQnt',
'step7StaaPrcsQnt'
]
},
{
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'
'staaExcpWhol',
'step1StaaExcpPrcsQnt',
'step2StaaExcpPrcsQnt',
'step3StaaExcpPrcsQnt',
'step4StaaExcpPrcsQnt',
'step5StaaExcpPrcsQnt',
'step6StaaExcpPrcsQnt',
'step7StaaExcpPrcsQnt'
]
}
]
},
'RMK'
'rmrk',
'admdstCd',
'admdstNm'
],
rowStartNum: 3,
fixedColumns: 1,
tabKey: 'sewageTreatFactStatusInp',
tabKey: 'ST00080001',
tabLabel: '처리용량별 오수처리시설 현황'
};
@@ -5,46 +5,72 @@ import { ValueType } from "realgrid";
export const CauserBurdenInpColumn = {
columns: [
// 행정구역
{ name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false },
{ name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false },
{ name: 'sggNm', fieldName: 'sggNm', header: { 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: 'levyEvntcsCnt', fieldName: 'levyEvntcsCnt', header: { text: '건수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'levyAmt', fieldName: 'levyAmt', 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: 'trgtByWholClctnEvntcsCnt',
fieldName: 'trgtByWholClctnEvntcsCnt',
header: { text: '건수' },
editable: false,
footer: footerInt,
styleName: 'rg-cell-total',
valueType: ValueType.NUMBER,
dataFormat: '#,##0',
computed: {
fields: ['mltvEqpmEvntcsCnt', 'othrCstrnOthrActrCnt'],
type: 'sum' as const,
},
},
{
name: 'trgtByWholClctnAmt',
fieldName: 'trgtByWholClctnAmt',
header: { text: '금액(백만원)' },
editable: false,
footer: footerDecimal1,
styleName: 'rg-cell-total',
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
computed: {
fields: ['mltvEqpmAmt', 'othrCstrnOthrActrAmt'],
type: 'sum' as const,
},
},
// 대상별 징수현황 > 배수설비설치자
{ 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: 'mltvEqpmEvntcsCnt', fieldName: 'mltvEqpmEvntcsCnt', header: { text: '건수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'mltvEqpmAmt', fieldName: 'mltvEqpmAmt', 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: 'othrCstrnOthrActrCnt', fieldName: 'othrCstrnOthrActrCnt', header: { text: '건수' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'othrCstrnOthrActrAmt', fieldName: 'othrCstrnOthrActrAmt', header: { text: '금액(백만원)' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
// 비고
{ name: 'RMK', fieldName: '비고', header: { text: '비고' } },
{ name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } },
// hidden
{ name: 'CHCKER_OPINION', fieldName: '검토자의견', header: { text: '검토자의견' } },
{ name: 'WRTER_OPINION', fieldName: '사용자의견', header: { text: '사용자의견' } },
// 참조 필드
{ name: 'AMNTBRNCSR', fieldName: 'AMNTBRNCSR', header: { text: 'AMNTBRNCSR' } },
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false },
],
columnLayout: [
{
name: 'group_admin',
header: { text: '행정구역' },
items: ['SIDO', 'GUGUN']
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
{
name: 'group_assess',
header: { text: '부과액' },
items: ['LEVY_CO', 'LEVY_AMOUNT']
items: ['levyEvntcsCnt', 'levyAmt']
},
{
name: 'group_collection',
@@ -53,25 +79,27 @@ export const CauserBurdenInpColumn = {
{
name: 'coll_group_total',
header: { text: '계' },
items: ['TRGET_LEV_STTUS_CO', 'TRGET_LEV_STTUS_AMOUNT']
items: ['trgtByWholClctnEvntcsCnt', 'trgtByWholClctnAmt']
},
{
name: 'coll_group_inst',
header: { text: '배수설비설치자(하수도법 제61조 제1항)' },
items: ['DRNG_EQP_CO', 'DRNG_EQP_AMOUNT']
items: ['mltvEqpmEvntcsCnt', 'mltvEqpmAmt']
},
{
name: 'coll_group_otr',
header: { text: '타공사·타행위자(하수도법 제61조 제2항)' },
items: ['CNTRWK_CO', 'CNTRWK_AMOUNT']
items: ['othrCstrnOthrActrCnt', 'othrCstrnOthrActrAmt']
}
]
},
'RMK'
'rmrk',
'admdstCd',
'admdstNm'
],
rowStartNum: 3,
fixedColumns: 1,
tabKey: 'causerBurdenInp',
tabKey: 'ST00090004',
tabLabel: '원인자 부담금'
};
@@ -5,45 +5,86 @@ import { ValueType } from "realgrid";
export const SewerageChargeInpColumn = {
columns: [
// 행정구역
{ name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false },
{ name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false },
{ name: 'sggNm', fieldName: 'sggNm', header: { 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: 'anlLevyQnt', fieldName: 'anlLevyQnt', header: { text: '연간조정량(m³)(A)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'levyAmt', fieldName: 'levyAmt', header: { text: '하수도사용료수익(원)(B)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{
name: 'avgUntprcAmt',
fieldName: 'avgUntprcAmt',
header: { text: 'm³당요금(원/m³) C=(B/A)' },
editable: false,
footer: footerDecimal1,
styleName: 'rg-cell-total',
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
computed: {
fields: ['levyAmt', 'anlLevyQnt'],
type: 'quotient' as const,
},
},
{ 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: 'grssPrmcoAmt', fieldName: 'grssPrmcoAmt', header: { text: '총괄원가(원)(D)' }, footer: footerInt, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{
name: 'grssUnitPrmcoAmt',
fieldName: 'grssUnitPrmcoAmt',
header: { text: 'm³당원가(원/m³) E=(D/A)' },
editable: false,
footer: footerDecimal1,
styleName: 'rg-cell-total',
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
computed: {
fields: ['grssPrmcoAmt', 'anlLevyQnt'],
type: 'quotient' as const,
},
},
{
name: 'rlztnRt',
fieldName: 'rlztnRt',
header: { text: '요금현실화율(%) F=(C/E*100)' },
editable: false,
footer: footerDecimal1,
styleName: 'rg-cell-total',
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
computed: {
numeratorQuotient: ['levyAmt', 'anlLevyQnt'] as [string, string],
denominatorQuotient: ['grssPrmcoAmt', 'anlLevyQnt'] as [string, string],
type: 'quotientRatioPercent' as const,
},
},
// 비고
{ name: 'RMK', fieldName: '비고', header: { text: '비고' } },
{ name: 'rmrk', 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' },
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false },
],
columnLayout: [
{
name: 'group_admin',
header: { text: '행정구역' },
items: ['SIDO', 'GUGUN']
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
'FYER_LEVY_QY',
'LEVY_AMOUNT',
'AVRG_UNTPC',
'SMRIZE_PRMPC',
'SMRIZE_UNIT_PRMPC',
'RLTY_RT',
'RMK'
'anlLevyQnt',
'levyAmt',
'avgUntprcAmt',
'grssPrmcoAmt',
'grssUnitPrmcoAmt',
'rlztnRt',
'rmrk',
'admdstCd',
'admdstNm'
],
rowStartNum: 2,
fixedColumns: 1,
tabKey: 'sewerageChargeInp',
tabKey: 'ST00090002',
tabLabel: '하수도 요금'
};
@@ -5,146 +5,238 @@ import { ValueType } from "realgrid";
export const SewerageFinanceSettleInpColumn = {
columns: [
// 행정구역
{ name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false },
{ name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false },
{ name: 'sggNm', fieldName: 'sggNm', header: { 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: 'fnnByWholPjtcoAmt',
fieldName: 'fnnByWholPjtcoAmt',
header: { text: '계' },
editable: false,
footer: footerDecimal1,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
fields: [
'cnterGovSprtAmt',
'mctpvLcexpAmt',
'wareaSggLclAmt',
'sewerUseAmt',
'orgprBrdnAmt',
'etcIncmAmt',
'crfwAmt',
],
type: 'sum' as const,
},
},
{ name: 'cnterGovSprtAmt', fieldName: 'cnterGovSprtAmt', 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: 'mctpvLcexpAmt', fieldName: 'mctpvLcexpAmt', header: { text: '특·광역시, 도' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'wareaSggLclAmt', fieldName: 'wareaSggLclAmt', 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: 'sewerUseAmt', fieldName: 'sewerUseAmt', header: { text: '하수도사용료' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'orgprBrdnAmt', fieldName: 'orgprBrdnAmt', header: { text: '원인자부담금' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'etcIncmAmt', fieldName: 'etcIncmAmt', header: { text: '기타잡수입' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'crfwAmt', fieldName: 'crfwAmt', 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: 'lbltAmt', fieldName: 'lbltAmt', 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: 'usgByWholPjtcoAmt',
fieldName: 'usgByWholPjtcoAmt',
header: { text: '계' },
editable: false,
footer: footerDecimal1,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
},
// 용도별사업비 > 처리장
{ 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: 'tmplntWholAmt',
fieldName: 'tmplntWholAmt',
header: { text: '소계' },
editable: false,
footer: footerDecimal1,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
fields: ['tmplntFcltAmt', 'tmplntMendngAmt', 'tmplntOperKeepAmt', 'tmplntEtcAmt'],
type: 'sum' as const,
},
},
{ name: 'tmplntFcltAmt', fieldName: 'tmplntFcltAmt', header: { text: '시설비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'tmplntMendngAmt', fieldName: 'tmplntMendngAmt', header: { text: '개보수비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'tmplntOperKeepAmt', fieldName: 'tmplntOperKeepAmt', header: { text: '운영유지비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'tmplntEtcAmt', fieldName: 'tmplntEtcAmt', 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: 'wholSwagePplAmt',
fieldName: 'wholSwagePplAmt',
header: { text: '소계' },
editable: false,
footer: footerDecimal1,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
fields: [
'swagePplFcltAmt',
'swagePplMendngAmt',
'swagePplOperKeepAmt',
'swagePplEtcAmt',
],
type: 'sum' as const,
},
},
{ name: 'swagePplFcltAmt', fieldName: 'swagePplFcltAmt', header: { text: '시설비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'swagePplMendngAmt', fieldName: 'swagePplMendngAmt', header: { text: '개보수비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'swagePplOperKeepAmt', fieldName: 'swagePplOperKeepAmt', header: { text: '운영유지비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'swagePplEtcAmt', fieldName: 'swagePplEtcAmt', 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: 'wholSwageImpdFcltAmt',
fieldName: 'wholSwageImpdFcltAmt',
header: { text: '소계' },
editable: false,
footer: footerDecimal1,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
fields: [
'swageImpdFcltAmt',
'swageImpdMendngAmt',
'swageImpdOperKeepAmt',
'swageImpdFcltEtcAmt',
],
type: 'sum' as const,
},
},
{ name: 'swageImpdFcltAmt', fieldName: 'swageImpdFcltAmt', header: { text: '시설비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'swageImpdMendngAmt', fieldName: 'swageImpdMendngAmt', header: { text: '개보수비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'swageImpdOperKeepAmt', fieldName: 'swageImpdOperKeepAmt', header: { text: '운영유지비' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'swageImpdFcltEtcAmt', fieldName: 'swageImpdFcltEtcAmt', 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: 'etcWholAmt',
fieldName: 'etcWholAmt',
header: { text: '소계' },
editable: false,
footer: footerDecimal1,
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
styleName: 'rg-cell-total',
computed: {
fields: ['etcAcdntCrfwAmt', 'etcNrcpAmt', 'etcAmt'],
type: 'sum' as const,
},
},
{ name: 'etcAcdntCrfwAmt', fieldName: 'etcAcdntCrfwAmt', header: { text: '사고이월액' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'etcNrcpAmt', fieldName: 'etcNrcpAmt', header: { text: '미수납액' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{ name: 'etcAmt', fieldName: 'etcAmt', header: { text: '기타' }, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
// 비고
{ name: 'RMK', fieldName: '비고', header: { text: '비고' } },
{ name: 'rmrk', fieldName: 'rmrk', 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' },
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false },
],
columnLayout: [
{
name: 'group_admin',
header: { text: '행정구역' },
items: ['SIDO', 'GUGUN']
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
{
name: 'group_finance',
header: { text: '재정별 사업비(백만원)' },
items: [
'FNANC_WCT_SM',
'NTNXPN',
'fnnByWholPjtcoAmt',
'cnterGovSprtAmt',
{
name: 'group_local_finance',
header: { text: '지방비' },
items: ['LCLEXPNS', 'LCLTY_CT']
items: ['mctpvLcexpAmt', 'wareaSggLclAmt']
},
'SEWER_RNTFEE',
'AMNTBRNCSR',
'ETC_INCME',
'CYFD_AMOUNT'
'sewerUseAmt',
'orgprBrdnAmt',
'etcIncmAmt',
'crfwAmt'
]
},
'DEBT_AMOUNT',
'lbltAmt',
{
name: 'group_purpose',
header: { text: '용도별사업비(백만원)' },
items: [
'PRPOS_WCT_SM',
'usgByWholPjtcoAmt',
{
name: 'group_treatment',
header: { text: '처리장' },
items: [
'PRCPLT_SM',
'PRCPLT_FCLTY',
'PRCPLT_RPAIR',
'PRCPLT_ORPNS',
'PRCPLT_ETC'
'tmplntWholAmt',
'tmplntFcltAmt',
'tmplntMendngAmt',
'tmplntOperKeepAmt',
'tmplntEtcAmt'
]
},
{
name: 'group_pipe',
header: { text: '하수관로' },
items: [
'SEWAGE_SM',
'SEWAGE_FCLTY',
'SEWAGE_RPAIR',
'SEWAGE_ORPNS',
'SEWAGE_ETC'
'wholSwagePplAmt',
'swagePplFcltAmt',
'swagePplMendngAmt',
'swagePplOperKeepAmt',
'swagePplEtcAmt'
]
},
{
name: 'group_storage',
header: { text: '하수저류시설' },
items: [
'SWGE_STRGE_SM',
'SWGE_STRGE_FCLTY',
'SWGE_STRGE_RPAIR',
'SWGE_STRGE_ORPNS',
'SWGE_STRGE_ETC'
'wholSwageImpdFcltAmt',
'swageImpdFcltAmt',
'swageImpdMendngAmt',
'swageImpdOperKeepAmt',
'swageImpdFcltEtcAmt'
]
},
{
name: 'group_etc_purpose',
header: { text: '기타' },
items: [
'ETC_SM',
'ACDNT_CYFD_AMOUNT',
'UNRCIV_AMOUNT',
'ETC_AMOUNT'
'etcWholAmt',
'etcAcdntCrfwAmt',
'etcNrcpAmt',
'etcAmt'
]
}
]
},
'RMK'
'rmrk',
'admdstCd',
'admdstNm'
],
rowStartNum: 3,
fixedColumns: 1,
tabKey: 'sewerageFinanceSettleInp',
tabKey: 'ST00090001',
tabLabel: '하수도재정 결산'
};
@@ -5,67 +5,108 @@ import { ValueType } from "realgrid";
export const SewerageUsageFeeInpColumn = {
columns: [
// 행정구역
{ name: 'SIDO', fieldName: '시도', header: { text: '시도' }, editable: false },
{ name: 'GUGUN', fieldName: '시군구', header: { text: '시군구' }, editable: false, footer: { text: '합계' } },
{ name: 'ctpvNm', fieldName: 'ctpvNm', header: { text: '시도' }, footer: { text: '합계' }, editable: false },
{ name: 'sggNm', fieldName: 'sggNm', header: { text: '시군구' } },
// 총계 > 부과액
{ name: 'LEVY_AMOUNT', fieldName: '(백만원)', header: { text: '(백만원)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{
name: 'levyAmt',
fieldName: 'levyAmt',
header: { text: '(백만원)' },
editable: false,
footer: footerDecimal1,
styleName: 'rg-cell-total',
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
computed: {
fields: [
'hshusLevyAmt',
'taskFrLevyAmt',
'fbuLevyAmt',
'bthhsFrSpcs1LevyAmt',
'bthhsFrSpcs2LevyAmt',
'induLevyAmt',
'etcLevyAmt',
],
type: 'sum' as const,
},
},
// 총계 > 부과량
{ name: 'LEVY_QY', fieldName: '(천톤)', header: { text: '(천톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
{
name: 'levyQnt',
fieldName: 'levyQnt',
header: { text: '(천톤)' },
editable: false,
footer: footerDecimal1,
styleName: 'rg-cell-total',
valueType: ValueType.NUMBER,
dataFormat: '#,##0.0',
computed: {
fields: [
'hshusLevyQnt',
'taskFrLevyQnt',
'fbuLevyQnt',
'bthhsFrSpcs1LevyQnt',
'bthhsFrSpcs2LevyQnt',
'induLevyQnt',
'etcLevyQnt',
],
type: 'sum' as const,
},
},
// 가정용
{ 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: '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: 'hshusUntprcAmt', fieldName: 'hshusUntprcAmt', 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: '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: 'taskFrUntprcAmt', fieldName: 'taskFrUntprcAmt', 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' },
{ 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: 'fbuUntprcAmt', fieldName: 'fbuUntprcAmt', 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' },
{ 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: 'bthhsFrSpcs1UntprcAmt', fieldName: 'bthhsFrSpcs1UntprcAmt', 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: '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: 'bthhsFrSpcs2UntprcAmt', fieldName: 'bthhsFrSpcs2UntprcAmt', 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: '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: 'induUntprcAmt', fieldName: 'induUntprcAmt', 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: '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: 'etcLevyUntprcAmt', fieldName: 'etcLevyUntprcAmt', header: { text: '(원/톤)' }, editable: false, footer: footerDecimal1, valueType: ValueType.NUMBER, dataFormat: '#,##0.0' },
// 비고
{ name: 'RMK', fieldName: '비고', header: { text: '비고' } },
{ name: 'rmrk', fieldName: 'rmrk', 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' } },
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, },
{ name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false },
],
columnLayout: [
{
name: 'group_admin',
header: { text: '행정구역' },
items: ['SIDO', 'GUGUN']
items: [
{ column: 'ctpvNm', footerUserSpans: [{ colspan: 2 }] },
'sggNm',
],
},
{
name: 'group_total',
@@ -74,12 +115,12 @@ export const SewerageUsageFeeInpColumn = {
{
name: 'total_amount',
header: { text: '부과액' },
items: ['LEVY_AMOUNT']
items: ['levyAmt']
},
{
name: 'total_qty',
header: { text: '부과량' },
items: ['LEVY_QY']
items: ['levyQnt']
}
]
},
@@ -90,17 +131,17 @@ export const SewerageUsageFeeInpColumn = {
{
name: 'home_amount',
header: { text: '부과액' },
items: ['HOME_LEVY_AMOUNT']
items: ['hshusLevyAmt']
},
{
name: 'home_qty',
header: { text: '부과량' },
items: ['HOME_LEVY_QY']
items: ['hshusLevyQnt']
},
{
name: 'home_price',
header: { text: '단가' },
items: ['HOME_UNTPC']
items: ['hshusUntprcAmt']
}
]
},
@@ -111,17 +152,17 @@ export const SewerageUsageFeeInpColumn = {
{
name: 'job_amount',
header: { text: '부과액' },
items: ['JOB_LEVY_AMOUNT']
items: ['taskFrLevyAmt']
},
{
name: 'job_qty',
header: { text: '부과량' },
items: ['JOB_LEVY_QY']
items: ['taskFrLevyQnt']
},
{
name: 'job_price',
header: { text: '단가' },
items: ['JOB_UNTPC']
items: ['taskFrUntprcAmt']
}
]
},
@@ -132,17 +173,17 @@ export const SewerageUsageFeeInpColumn = {
{
name: 'bsn_amount',
header: { text: '부과액' },
items: ['BSN_LEVY_AMOUNT']
items: ['fbuLevyAmt']
},
{
name: 'bsn_qty',
header: { text: '부과량' },
items: ['BSN_LEVY_QY']
items: ['fbuLevyQnt']
},
{
name: 'bsn_price',
header: { text: '단가' },
items: ['BSN_UNTPC']
items: ['fbuUntprcAmt']
}
]
},
@@ -153,17 +194,17 @@ export const SewerageUsageFeeInpColumn = {
{
name: 'baths1_amount',
header: { text: '부과액' },
items: ['BATHS1_LEVY_AMOUNT']
items: ['bthhsFrSpcs1LevyAmt']
},
{
name: 'baths1_qty',
header: { text: '부과량' },
items: ['BATHS1_LEVY_QY']
items: ['bthhsFrSpcs1LevyQnt']
},
{
name: 'baths1_price',
header: { text: '단가' },
items: ['BATHS1_UNTPC']
items: ['bthhsFrSpcs1UntprcAmt']
}
]
},
@@ -174,17 +215,17 @@ export const SewerageUsageFeeInpColumn = {
{
name: 'pbbath_amount',
header: { text: '부과액' },
items: ['PBBATH_LEVY_AMOUNT']
items: ['bthhsFrSpcs2LevyAmt']
},
{
name: 'pbbath_qty',
header: { text: '부과량' },
items: ['PBBATH_LEVY_QY']
items: ['bthhsFrSpcs2LevyQnt']
},
{
name: 'pbbath_price',
header: { text: '단가' },
items: ['PBBATH_UNTPC']
items: ['bthhsFrSpcs2UntprcAmt']
}
]
},
@@ -195,17 +236,17 @@ export const SewerageUsageFeeInpColumn = {
{
name: 'indust_amount',
header: { text: '부과액' },
items: ['INDUST_LEVY_AMOUNT']
items: ['induLevyAmt']
},
{
name: 'indust_qty',
header: { text: '부과량' },
items: ['INDUST_LEVY_QY']
items: ['induLevyQnt']
},
{
name: 'indust_price',
header: { text: '단가' },
items: ['INDUST_UNTPC']
items: ['induUntprcAmt']
}
]
},
@@ -216,25 +257,27 @@ export const SewerageUsageFeeInpColumn = {
{
name: 'etc_amount',
header: { text: '부과액' },
items: ['ETC_LEVY_AMOUNT']
items: ['etcLevyAmt']
},
{
name: 'etc_qty',
header: { text: '부과량' },
items: ['ETC_LEVY_QY']
items: ['etcLevyQnt']
},
{
name: 'etc_price',
header: { text: '단가' },
items: ['ETC_UNTPC']
items: ['etcLevyUntprcAmt']
}
]
},
'RMK'
'rmrk',
'admdstCd',
'admdstNm'
],
rowStartNum: 3,
fixedColumns: 1,
tabKey: 'sewerageUsageFeeInp',
tabKey: 'ST00090003',
tabLabel: '하수도 사용료'
};
@@ -43,6 +43,65 @@ export function createAvgValueCallback(fieldNames: string[]): DataFieldValueCall
};
}
function sumFieldValues(
fields: string[],
fieldNamesArr: string[],
values: unknown[],
): number {
let sum = 0;
for (const f of fields) {
const idx = fieldNamesArr.indexOf(f);
if (idx >= 0) sum += toNum(values[idx]);
}
return sum;
}
/** halfSumOfSums 한 건 — (sum(first) + sum(second)) / 2, 소수 내림 */
function computeHalfSumOfSums(
firstSumFields: string[],
secondSumFields: string[],
fieldNamesArr: string[],
values: unknown[],
): number {
const firstSum = sumFieldValues(firstSumFields, fieldNamesArr, values);
const secondSum = sumFieldValues(secondSumFields, fieldNamesArr, values);
return Math.floor((firstSum + secondSum) / 2);
}
export type HalfSumOfSumsGroup = {
firstSumFields: string[];
secondSumFields: string[];
};
/** 두 그룹 합계의 평균 — (sum(first) + sum(second)) / 2 */
export function createHalfSumOfSumsValueCallback(
firstSumFields: string[],
secondSumFields: string[],
): DataFieldValueCallback {
return (_prod, _dataRow, _fieldName, fieldNamesArr, values) =>
computeHalfSumOfSums(firstSumFields, secondSumFields, fieldNamesArr, values);
}
/** halfSumOfSums 2건의 합 — (B+C)/2 + (E+F)/2 */
export function createSumOfTwoHalfSumOfSumsValueCallback(
firstGroup: HalfSumOfSumsGroup,
secondGroup: HalfSumOfSumsGroup,
): DataFieldValueCallback {
return (_prod, _dataRow, _fieldName, fieldNamesArr, values) =>
computeHalfSumOfSums(
firstGroup.firstSumFields,
firstGroup.secondSumFields,
fieldNamesArr,
values,
) +
computeHalfSumOfSums(
secondGroup.firstSumFields,
secondGroup.secondSumFields,
fieldNamesArr,
values,
);
}
/** 차이값: fields[0] − fields[1] (예: 매설연장 − 철거연장) */
export function createDifferenceValueCallback(fields: string[]): DataFieldValueCallback {
const a = fields[0] ?? "";
@@ -179,6 +238,21 @@ export function createSwrgInstlrtRateValueCallback(
};
}
/** 처리효율: (유입BOD − 방류BOD) / 유입BOD */
export function createBodPrcsRtValueCallback(
inflwField: string,
dschgField: string,
): DataFieldValueCallback {
return (_prod, _dataRow, _fieldName, fieldNamesArr, values) => {
const inflwIdx = fieldNamesArr.indexOf(inflwField);
const dschgIdx = fieldNamesArr.indexOf(dschgField);
const inflw = inflwIdx >= 0 ? toNum(values[inflwIdx]) : 0;
const dschg = dschgIdx >= 0 ? toNum(values[dschgIdx]) : 0;
if (inflw === 0) return 0;
return (inflw - dschg) / inflw;
};
}
/** 총양수량: Σ(펌프대수 + 예비펌프대수) × 대당 양수량 */
export function createPumpGrossPpqtyValueCallback(
pumpGroups: Array<{
@@ -202,6 +276,44 @@ export function createPumpGrossPpqtyValueCallback(
};
}
/** (a/b) / (c/d) × 100 — 각 quotient 분모 0이면 0 */
export function createQuotientRatioPercentValueCallback(
numeratorQuotient: [string, string],
denominatorQuotient: [string, string],
): DataFieldValueCallback {
const [numField, numDenField] = numeratorQuotient;
const [denNumField, denDenField] = denominatorQuotient;
return (_prod, _dataRow, _fieldName, fieldNamesArr, values) => {
const getVal = (field: string) => {
const idx = fieldNamesArr.indexOf(field);
return idx >= 0 ? toNum(values[idx]) : 0;
};
const numDen = getVal(numDenField);
const denDen = getVal(denDenField);
const denNum = getVal(denNumField);
if (numDen === 0 || denDen === 0 || denNum === 0) return 0;
const numerator = getVal(numField) / numDen;
const denominator = denNum / denDen;
if (denominator === 0) return 0;
return (numerator / denominator) * 100;
};
}
/** 나눗셈: fields[0] / fields[1] (분모 0이면 0) */
export function createQuotientValueCallback(fields: string[]): DataFieldValueCallback {
const numeratorField = fields[0] ?? "";
const denominatorField = fields[1] ?? "";
return (_prod, _dataRow, _fieldName, fieldNamesArr, values) => {
if (!numeratorField || !denominatorField) return 0;
const numIdx = fieldNamesArr.indexOf(numeratorField);
const denIdx = fieldNamesArr.indexOf(denominatorField);
const numerator = numIdx >= 0 ? toNum(values[numIdx]) : 0;
const denominator = denIdx >= 0 ? toNum(values[denIdx]) : 0;
if (denominator === 0) return 0;
return numerator / denominator;
};
}
/** 연산 타입에 맞는 valueCallback 반환 */
export function getComputedValueCallback(config: ComputedFieldConfig): DataFieldValueCallback {
switch (config.type) {
@@ -213,11 +325,28 @@ export function getComputedValueCallback(config: ComputedFieldConfig): DataField
return createMaxValueCallback(config.fields);
case 'difference':
return createDifferenceValueCallback(config.fields);
case 'quotient':
return createQuotientValueCallback(config.fields);
case 'quotientRatioPercent':
return createQuotientRatioPercentValueCallback(
config.numeratorQuotient,
config.denominatorQuotient,
);
case 'differenceOfSums':
return createDifferenceOfSumsValueCallback(
config.minuendFields,
config.subtrahendFields,
);
case 'halfSumOfSums':
return createHalfSumOfSumsValueCallback(
config.firstSumFields,
config.secondSumFields,
);
case 'sumOfTwoHalfSumOfSums':
return createSumOfTwoHalfSumOfSumsValueCallback(
config.firstHalfSum,
config.secondHalfSum,
);
case 'maxOfFieldAndSum':
return createMaxOfFieldAndSumValueCallback(
config.baseField,
@@ -234,5 +363,7 @@ export function getComputedValueCallback(config: ComputedFieldConfig): DataField
return createSwrgInstlrtRateValueCallback(config.numeratorFields, config.denominatorFields, config.thirdFields);
case 'pumpGrossPpqty':
return createPumpGrossPpqtyValueCallback(config.pumpGroups);
case 'bodPrcsRt':
return createBodPrcsRtValueCallback(config.inflwField, config.dschgField);
}
}
+59 -1
View File
@@ -1,6 +1,64 @@
import type { ColumnConfig } from "@/components/type/DataGrid.type";
import type {
ColumnConfig,
ColumnLayoutItem,
} from "@/components/type/DataGrid.type";
import type { GridView } from "realgrid";
function flattenColumnLayoutNames(layout: ColumnLayoutItem[]): string[] {
const result: string[] = [];
for (const item of layout) {
if (typeof item === "string") {
result.push(item);
continue;
}
if (item && typeof item === "object") {
if ("column" in item && typeof item.column === "string") {
result.push(item.column);
continue;
}
if ("items" in item && Array.isArray(item.items)) {
result.push(
...flattenColumnLayoutNames(
item.items as ColumnLayoutItem[],
),
);
}
}
}
return result;
}
/** 엑셀 가져오기 — N번째 열을 그리드 N번째 fieldName에 매핑 (보내기 컬럼 순서와 동일) */
export function getExcelImportColumnFieldNames(
columns: ColumnConfig[],
columnLayout?: ColumnLayoutItem[],
): string[] {
const excludedNames = new Set(
columns.filter((c) => c.excludeFromExcelExport).map((c) => c.name),
);
const fieldByName = new Map(
columns
.filter((c) => c.fieldName)
.map((c) => [c.name, c.fieldName as string]),
);
const layoutNames =
columnLayout && columnLayout.length > 0
? flattenColumnLayoutNames(columnLayout)
: columns.map((c) => c.name);
const seen = new Set<string>();
const fieldNames: string[] = [];
for (const name of layoutNames) {
if (excludedNames.has(name) || seen.has(name)) continue;
const fieldName = fieldByName.get(name);
if (!fieldName) continue;
seen.add(name);
fieldNames.push(fieldName);
}
return fieldNames;
}
export type ExcelExportVisibilitySnapshot = Map<string, boolean>;
/** 엑셀보내기 직전: 제외 컬럼 숨김, 그리드용 숨김(visible:false) 컬럼은 export에만 표시 */
@@ -0,0 +1,53 @@
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import {
type ExcretaTreatmentFacilityApiResponse,
type ExcretaTreatmentFacilityRequestParams,
type ExcretaTreatmentFacilitySaveRequest,
type ExcretaTreatmentFacilitySaveResponse,
type ExcretaTreatmentFacilitySubmitRequest,
type ExcretaTreatmentFacilitySubmitResponse,
type StatisticsInputExcretaTreatmentFacilityService,
} from "../../model/input/statistics-input-excreta-treatment-facility-interface";
export class StatisticsInputExcretaTreatmentFacilityApiService
implements StatisticsInputExcretaTreatmentFacilityService
{
/** 분뇨처리시설 조회 — ST00070001 */
public async getExcretaTreatmentFacilityList(
params: ExcretaTreatmentFacilityRequestParams,
): Promise<ExcretaTreatmentFacilityApiResponse> {
const response = await stClient.get<ExcretaTreatmentFacilityApiResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/excreta-treatment-facility`,
withAuthHeader({ params }),
);
return response.data;
}
/** 분뇨처리시설 저장 — ST00070001 */
public async saveExcretaTreatmentFacilityList(
request: ExcretaTreatmentFacilitySaveRequest,
): Promise<ExcretaTreatmentFacilitySaveResponse> {
const response = await stClient.put<ExcretaTreatmentFacilitySaveResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/excreta-treatment-facility/save`,
request,
);
return response.data;
}
/** 분뇨처리시설 제출 — ST00070001 */
public async submitExcretaTreatmentFacilityList(
request: ExcretaTreatmentFacilitySubmitRequest,
): Promise<ExcretaTreatmentFacilitySubmitResponse> {
const response = await stClient.put<ExcretaTreatmentFacilitySubmitResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/excreta-treatment-facility/submit`,
request,
);
return response.data;
}
}
export const statisticsInputExcretaTreatmentFacilityApi =
new StatisticsInputExcretaTreatmentFacilityApiService();
@@ -0,0 +1,133 @@
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import {
type PrivateSewageDesigStatusApiResponse,
type PrivateSewageDesigStatusRequestParams,
type PrivateSewageDesigStatusSaveRequest,
type PrivateSewageDesigStatusSaveResponse,
type PrivateSewageDesigStatusSubmitRequest,
type PrivateSewageDesigStatusSubmitResponse,
type SepticTankStatusApiResponse,
type SepticTankStatusRequestParams,
type SepticTankStatusSaveRequest,
type SepticTankStatusSaveResponse,
type SepticTankStatusSubmitRequest,
type SepticTankStatusSubmitResponse,
type SewageTreatFactStatusApiResponse,
type SewageTreatFactStatusRequestParams,
type SewageTreatFactStatusSaveRequest,
type SewageTreatFactStatusSaveResponse,
type SewageTreatFactStatusSubmitRequest,
type SewageTreatFactStatusSubmitResponse,
type StatisticsInputPrivateSewageFacilityService,
} from "../../model/input/statistics-input-private-sewage-facility-interface";
const BASE = `${ENDPOINT.ST_SERVICE.INPUT}/private-sewage-facility`;
export class StatisticsInputPrivateSewageFacilityApiService
implements StatisticsInputPrivateSewageFacilityService
{
/** 처리용량별 오수처리시설 현황 조회 — ST00080001 */
public async getSewageTreatFactStatusList(
params: SewageTreatFactStatusRequestParams,
): Promise<SewageTreatFactStatusApiResponse> {
const response = await stClient.get<SewageTreatFactStatusApiResponse>(
`${BASE}/sewage-treat-fact-status`,
withAuthHeader({ params }),
);
return response.data;
}
/** 처리용량별 오수처리시설 현황 저장 — ST00080001 */
public async saveSewageTreatFactStatus(
request: SewageTreatFactStatusSaveRequest,
): Promise<SewageTreatFactStatusSaveResponse> {
const response = await stClient.put<SewageTreatFactStatusSaveResponse>(
`${BASE}/sewage-treat-fact-status/save`,
request,
);
return response.data;
}
/** 처리용량별 오수처리시설 현황 제출 — ST00080001 */
public async submitSewageTreatFactStatus(
request: SewageTreatFactStatusSubmitRequest,
): Promise<SewageTreatFactStatusSubmitResponse> {
const response = await stClient.put<SewageTreatFactStatusSubmitResponse>(
`${BASE}/sewage-treat-fact-status/submit`,
request,
);
return response.data;
}
/** 정화조 현황 조회 — ST00080002 */
public async getSepticTankStatusList(
params: SepticTankStatusRequestParams,
): Promise<SepticTankStatusApiResponse> {
const response = await stClient.get<SepticTankStatusApiResponse>(
`${BASE}/septic-tank-status`,
withAuthHeader({ params }),
);
return response.data;
}
/** 정화조 현황 저장 — ST00080002 */
public async saveSepticTankStatus(
request: SepticTankStatusSaveRequest,
): Promise<SepticTankStatusSaveResponse> {
const response = await stClient.put<SepticTankStatusSaveResponse>(
`${BASE}/septic-tank-status/save`,
request,
);
return response.data;
}
/** 정화조 현황 제출 — ST00080002 */
public async submitSepticTankStatus(
request: SepticTankStatusSubmitRequest,
): Promise<SepticTankStatusSubmitResponse> {
const response = await stClient.put<SepticTankStatusSubmitResponse>(
`${BASE}/septic-tank-status/submit`,
request,
);
return response.data;
}
/** 개인하수도 관리지역 지정공고 현황 조회 — ST00080003 */
public async getPrivateSewageDesigStatusList(
params: PrivateSewageDesigStatusRequestParams,
): Promise<PrivateSewageDesigStatusApiResponse> {
const response = await stClient.get<PrivateSewageDesigStatusApiResponse>(
`${BASE}/desig-status`,
withAuthHeader({ params }),
);
return response.data;
}
/** 개인하수도 관리지역 지정공고 현황 저장 — ST00080003 */
public async savePrivateSewageDesigStatus(
request: PrivateSewageDesigStatusSaveRequest,
): Promise<PrivateSewageDesigStatusSaveResponse> {
const response = await stClient.put<PrivateSewageDesigStatusSaveResponse>(
`${BASE}/desig-status/save`,
request,
);
return response.data;
}
/** 개인하수도 관리지역 지정공고 현황 제출 — ST00080003 */
public async submitPrivateSewageDesigStatus(
request: PrivateSewageDesigStatusSubmitRequest,
): Promise<PrivateSewageDesigStatusSubmitResponse> {
const response = await stClient.put<PrivateSewageDesigStatusSubmitResponse>(
`${BASE}/desig-status/submit`,
request,
);
return response.data;
}
}
export const statisticsInputPrivateSewageFacilityApi =
new StatisticsInputPrivateSewageFacilityApiService();
@@ -0,0 +1,50 @@
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import {
type PumpingStationApiResponse,
type PumpingStationRequestParams,
type PumpingStationSaveRequest,
type PumpingStationSaveResponse,
type PumpingStationSubmitRequest,
type PumpingStationSubmitResponse,
type StatisticsInputPumpingStationService,
} from "../../model/input/statistics-input-pumping-station-interface";
export class StatisticsInputPumpingStationApiService implements StatisticsInputPumpingStationService {
/** 펌프장 조회 — ST00050001 */
public async getPumpingStationList(
params: PumpingStationRequestParams,
): Promise<PumpingStationApiResponse> {
const response = await stClient.get<PumpingStationApiResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/pumping-station`,
withAuthHeader({ params }),
);
return response.data;
}
/** 펌프장 저장 — ST00050001 */
public async savePumpingStationList(
request: PumpingStationSaveRequest,
): Promise<PumpingStationSaveResponse> {
const response = await stClient.put<PumpingStationSaveResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/pumping-station/save`,
request,
);
return response.data;
}
/** 펌프장 제출 — ST00050001 */
public async submitPumpingStationList(
request: PumpingStationSubmitRequest,
): Promise<PumpingStationSubmitResponse> {
const response = await stClient.put<PumpingStationSubmitResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/pumping-station/submit`,
request,
);
return response.data;
}
}
export const statisticsInputPumpingStationApi = new StatisticsInputPumpingStationApiService();
@@ -1,5 +1,6 @@
import { ENDPOINT } from "@/shared/config";
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import {
type StatisticsInputSewSupplyRateService,
@@ -15,7 +16,7 @@ export class StatisticsInputSewSupplyRateApiService implements StatisticsInputSe
public async getSewerageSupplyRateList(params: SewerageSupplyRateRequestParams): Promise<SewerageSupplyRateApiResponse> {
const response = await stClient.get<SewerageSupplyRateApiResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewerage-supply-rate`,
{ params }
withAuthHeader({ params }),
);
return response.data;
}
@@ -1,4 +1,5 @@
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import type {
@@ -20,7 +21,7 @@ export class SewagePipeMaintainApiService implements SewagePipeMaintainService {
public async getSewagePipeMaintainRepair(param: SewagePipeMaintainRequestParams): Promise<SewagePipeMaintainRepairResponse> {
const response = await stClient.get<SewagePipeMaintainRepairResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe-maintain/repair`,
{ params: param }
withAuthHeader({ params: param })
);
return response.data;
};
@@ -28,7 +29,7 @@ export class SewagePipeMaintainApiService implements SewagePipeMaintainService {
public async getSewagePipeMaintainDredging(param: SewagePipeMaintainRequestParams): Promise<SewagePipeMaintainDredgingResponse> {
const response = await stClient.get<SewagePipeMaintainDredgingResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe-maintain/dredging`,
{ params: param }
withAuthHeader({ params: param })
);
return response.data;
};
@@ -1,4 +1,5 @@
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import {
@@ -7,7 +8,13 @@ import {
type SewageReservoirRequestParams,
type SewageReservoirSaveRequest,
type SewageReservoirSaveResponse,
type SewageReservoirSubmitRequest,
type SewageReservoirSubmitResponse,
type RainfallPumpStationApiResponse,
type RainfallPumpStationSaveRequest,
type RainfallPumpStationSaveResponse,
type RainfallPumpStationSubmitRequest,
type RainfallPumpStationSubmitResponse,
} from "../../model/input/statistics-input-sewage-reservoir-pump-interface";
export class StatisticsInputSewageReservoirPumpApiService implements StatisticsInputSewageReservoirPumpService {
@@ -15,7 +22,7 @@ export class StatisticsInputSewageReservoirPumpApiService implements StatisticsI
public async getSewageReservoirList(params: SewageReservoirRequestParams): Promise<SewageReservoirApiResponse> {
const response = await stClient.get<SewageReservoirApiResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-reservoir-pump/sewage-reservoir`,
{ params },
withAuthHeader({ params }),
);
return response.data;
}
@@ -26,7 +33,7 @@ export class StatisticsInputSewageReservoirPumpApiService implements StatisticsI
): Promise<RainfallPumpStationApiResponse> {
const response = await stClient.get<RainfallPumpStationApiResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-reservoir-pump/rainfall-pump`,
{ params },
withAuthHeader({ params }),
);
return response.data;
}
@@ -41,6 +48,39 @@ export class StatisticsInputSewageReservoirPumpApiService implements StatisticsI
);
return response.data;
}
/** 하수저류시설 제출 — ST00040001 */
public async submitSewageReservoir(
request: SewageReservoirSubmitRequest,
): Promise<SewageReservoirSubmitResponse> {
const response = await stClient.put<SewageReservoirSubmitResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-reservoir-pump/sewage-reservoir/submit`,
request,
);
return response.data;
}
/** 빗물펌프장 저장 — ST00040002 */
public async saveRainfallPumpStation(
request: RainfallPumpStationSaveRequest,
): Promise<RainfallPumpStationSaveResponse> {
const response = await stClient.put<RainfallPumpStationSaveResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-reservoir-pump/rainfall-pump/save`,
request,
);
return response.data;
}
/** 빗물펌프장 제출 — ST00040002 */
public async submitRainfallPumpStation(
request: RainfallPumpStationSubmitRequest,
): Promise<RainfallPumpStationSubmitResponse> {
const response = await stClient.put<RainfallPumpStationSubmitResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-reservoir-pump/rainfall-pump/submit`,
request,
);
return response.data;
}
}
export const statisticsInputSewageReservoirPumpApi = new StatisticsInputSewageReservoirPumpApiService();
@@ -0,0 +1,68 @@
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import {
type CauserBurdenApiResponse,
type CauserBurdenRequestParams,
type SewerageChargeApiResponse,
type SewerageChargeRequestParams,
type SewerageFinanceSettleApiResponse,
type SewerageFinanceSettleRequestParams,
type SewerageUsageFeeApiResponse,
type SewerageUsageFeeRequestParams,
type StatisticsInputSewerageFinanceService,
} from "../../model/input/statistics-input-sewerage-finance-interface";
const BASE = `${ENDPOINT.ST_SERVICE.INPUT}/sewerage-finance`;
export class StatisticsInputSewerageFinanceApiService
implements StatisticsInputSewerageFinanceService
{
/** 하수도재정 결산 조회 — ST00090001 */
public async getSewerageFinanceSettleList(
params: SewerageFinanceSettleRequestParams,
): Promise<SewerageFinanceSettleApiResponse> {
const response = await stClient.get<SewerageFinanceSettleApiResponse>(
`${BASE}/settle`,
withAuthHeader({ params }),
);
return response.data;
}
/** 하수도 요금 조회 — ST00090002 */
public async getSewerageChargeList(
params: SewerageChargeRequestParams,
): Promise<SewerageChargeApiResponse> {
const response = await stClient.get<SewerageChargeApiResponse>(
`${BASE}/charge`,
withAuthHeader({ params }),
);
return response.data;
}
/** 하수도 사용료 조회 — ST00090003 */
public async getSewerageUsageFeeList(
params: SewerageUsageFeeRequestParams,
): Promise<SewerageUsageFeeApiResponse> {
const response = await stClient.get<SewerageUsageFeeApiResponse>(
`${BASE}/usage-fee`,
withAuthHeader({ params }),
);
return response.data;
}
/** 원인자 부담금 조회 — ST00090004 */
public async getCauserBurdenList(
params: CauserBurdenRequestParams,
): Promise<CauserBurdenApiResponse> {
const response = await stClient.get<CauserBurdenApiResponse>(
`${BASE}/causer-burden`,
withAuthHeader({ params }),
);
return response.data;
}
}
export const statisticsInputSewerageFinanceApi =
new StatisticsInputSewerageFinanceApiService();
@@ -1,4 +1,5 @@
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import type {
@@ -20,7 +21,7 @@ export class StatisticsInputPublicSewageFacilityApiService implements Statistics
public async getPublicSewageFacility(param: PublicSewageFacilityRequestParams): Promise<PublicSewageFacilityResponse> {
const response = await stClient.get<PublicSewageFacilityResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/public-sewage-facility/facility`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -28,7 +29,7 @@ export class StatisticsInputPublicSewageFacilityApiService implements Statistics
public async getPublicSewageMainFacility(param: PublicSewageFacilityRequestParams): Promise<PublicSewageMainFacilityResponse> {
const response = await stClient.get<PublicSewageMainFacilityResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/public-sewage-facility/main-facility`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -38,7 +39,7 @@ export class StatisticsInputPublicSewageFacilityApiService implements Statistics
): Promise<PublicSewageMappingTargetsResponse> {
const response = await stClient.get<PublicSewageMappingTargetsResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/public-sewage-facility/main-facility/mapping-targets`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -1,5 +1,6 @@
import { ENDPOINT } from "@/shared/config";
import { stClient } from "@/shared/api/client";
import { withAuthHeader } from "@/shared/api/with-auth-header";
import { ENDPOINT } from "@/shared/config";
import type {
SeweragePipeFacilityAdminAreaListRequest,
SeweragePipeFacilityAdminAreaListResponse,
@@ -39,7 +40,7 @@ export class StatisticsInputSewPipeApiService implements StatisticsInputSewPipeS
public async getRegionalFactStatus(param: SeweragePipeRequestParams): Promise<SeweragePipeInputRegionalResponse> {
const response = await stClient.get<SeweragePipeInputRegionalResponse> (
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe/regional-facility-status`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -47,7 +48,7 @@ export class StatisticsInputSewPipeApiService implements StatisticsInputSewPipeS
public async getFactInstallStatus(param: SeweragePipeRequestParams): Promise<SeweragePipeInputFactInstallResponse> {
const response = await stClient.get<SeweragePipeInputFactInstallResponse> (
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe/facility-install-status`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -55,7 +56,7 @@ export class StatisticsInputSewPipeApiService implements StatisticsInputSewPipeS
public async getPipeTypeStatus(param: SeweragePipeRequestParams): Promise<SeweragePipeInputPipeTypeResponse> {
const response = await stClient.get<SeweragePipeInputPipeTypeResponse> (
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe/pipe-type-status`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -63,7 +64,7 @@ export class StatisticsInputSewPipeApiService implements StatisticsInputSewPipeS
public async getPipeDiameterStatus(param: SeweragePipeRequestParams): Promise<SeweragePipeInputPipeDiameterResponse> {
const response = await stClient.get<SeweragePipeInputPipeDiameterResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe/pipe-diameter-status`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -71,7 +72,7 @@ export class StatisticsInputSewPipeApiService implements StatisticsInputSewPipeS
public async getManholeStatus(param: SeweragePipeRequestParams): Promise<SeweragePipeInputManholeResponse> {
const response = await stClient.get<SeweragePipeInputManholeResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe/manhole-status`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -79,7 +80,7 @@ export class StatisticsInputSewPipeApiService implements StatisticsInputSewPipeS
public async getConnectionStatus(param: SeweragePipeRequestParams): Promise<SeweragePipeInputConnectionStatusResponse> {
const response = await stClient.get<SeweragePipeInputConnectionStatusResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe/facility-connection-status`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -87,7 +88,7 @@ export class StatisticsInputSewPipeApiService implements StatisticsInputSewPipeS
public async getFacilitiesList(param: SeweragePipeFacilitiesListRequest): Promise<SeweragePipeFacilitiesListResponse> {
const response = await stClient.get<SeweragePipeFacilitiesListResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe/facility-connection-status/popup/facilities`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -95,7 +96,7 @@ export class StatisticsInputSewPipeApiService implements StatisticsInputSewPipeS
public async getFacilityAdminAreaList(param: SeweragePipeFacilityAdminAreaListRequest): Promise<SeweragePipeFacilityAdminAreaListResponse> {
const response = await stClient.get<SeweragePipeFacilityAdminAreaListResponse>(
`${ENDPOINT.ST_SERVICE.INPUT}/sewage-pipe/facility-connection-status/popup/areas`,
{ params: param },
withAuthHeader({ params: param }),
);
return response.data;
}
@@ -0,0 +1,166 @@
import type { ApiResponse, SewerageStatusInfo } from "../statistics-interface";
/** 분뇨처리시설(ST00070001) — `ExcretaTreatFactInpColumn` */
export const EXCRETA_TREATMENT_FACILITY_STATS_CD = "ST00070001" as const;
/** 검증 결과 한 건 */
export interface ExcretaTreatmentFacilityVerificationResultItem {
vrfcCd: string;
rsnExpln: string;
nowVlCn: string;
compVlCn: string;
}
/** 필드명 → 검증 결과 배열 */
export type ExcretaTreatmentFacilityVerificationResult = Record<
string,
ExcretaTreatmentFacilityVerificationResultItem[]
>;
/** 분뇨처리시설 조회 `data.commonInfo` */
export interface ExcretaTreatmentFacilityCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: ExcretaTreatmentFacilityVerificationResult;
}
/**
* 분뇨처리시설 조회 `data.excretaTreatmentFacilityList[]` 한 행.
* `ExcretaTreatFactInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface ExcretaTreatmentFacilityItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
fcltSn: string;
fcltNm: string;
fcltPstnCn: string;
telNo: string;
cmptnStrtYmd: string;
oprtngStrtYmd: string;
wholPjtcoAmt: number;
prcsFcltCpct: number;
cpct: number;
oprtngDayCnt: number;
prcsMthdExpln: string;
linkTmplntCn: string;
linkPrcsQnt: number;
inflwBodWqVl: number;
inflwTocWqVl: number;
inflwSsWqVl: number;
inflwTnWqVl: number;
inflwTpWqVl: number;
inflwClfgCnt: number;
dschgBodWqVl: number;
dschgTocWqVl: number;
dschgSsWqVl: number;
dschgTnWqVl: number;
dschgTpWqVl: number;
dschgClfgCnt: number;
wtsysNm: string;
trbtrNm: string;
msirbCn: string;
ssirbCn: string;
operMthdCdCn: string;
wholNope: number;
sftyAcdntEvntcsCnt: number;
rmrk: string | null;
verificationResult?: ExcretaTreatmentFacilityVerificationResult;
}
export interface ExcretaTreatmentFacilityResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: ExcretaTreatmentFacilityCommonInfo;
excretaTreatmentFacilityList: ExcretaTreatmentFacilityItem[];
}
export type ExcretaTreatmentFacilityApiResponse =
ApiResponse<ExcretaTreatmentFacilityResponseData> & {
message: string;
};
/** 분뇨처리시설(ST00070001) 조회 요청 파라미터 */
export interface ExcretaTreatmentFacilityRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
fcltNm?: string;
}
/**
* 분뇨처리시설(ST00070001) 저장 — `saveList` / `deleteList` 항목.
* `sggNm`·검증결과는 저장 요청에서 제외.
*/
export type ExcretaTreatmentFacilitySaveItem = Omit<
ExcretaTreatmentFacilityItem,
"sggNm" | "verificationResult"
>;
/** 분뇨처리시설(ST00070001) 저장 API 요청 */
export interface ExcretaTreatmentFacilitySaveRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
superAdmin?: string;
noApplicable?: boolean;
saveList: ExcretaTreatmentFacilitySaveItem[];
deleteList: ExcretaTreatmentFacilitySaveItem[];
}
export interface ExcretaTreatmentFacilitySaveResponse {
status: string;
message?: string;
data?: string;
}
export type ExcretaTreatmentFacilitySubmitItem = ExcretaTreatmentFacilitySaveItem;
/** 분뇨처리시설(ST00070001) 제출 API 요청 */
export interface ExcretaTreatmentFacilitySubmitRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
laePicNm: string;
laePicTelNo: string;
laeKbrdrDeptNm: string;
laeKbrdrJbgdNm: string;
laeIdfrNm: string;
laeIdfrTelNo: string;
laeIdfrDeptNm: string;
laeIdfrJbgdNm: string;
superAdmin?: string;
noApplicable?: boolean;
submitList: ExcretaTreatmentFacilitySubmitItem[];
deleteList: ExcretaTreatmentFacilitySubmitItem[];
}
export interface ExcretaTreatmentFacilitySubmitResponse {
status: string;
message?: string;
data?: {
finalStatus: string;
nvpassed: boolean;
};
}
export interface StatisticsInputExcretaTreatmentFacilityService {
getExcretaTreatmentFacilityList(
params: ExcretaTreatmentFacilityRequestParams,
): Promise<ExcretaTreatmentFacilityApiResponse>;
saveExcretaTreatmentFacilityList(
request: ExcretaTreatmentFacilitySaveRequest,
): Promise<ExcretaTreatmentFacilitySaveResponse>;
submitExcretaTreatmentFacilityList(
request: ExcretaTreatmentFacilitySubmitRequest,
): Promise<ExcretaTreatmentFacilitySubmitResponse>;
}
@@ -0,0 +1,453 @@
import type { ApiResponse, SewerageStatusInfo } from "../statistics-interface";
/** 처리용량별 오수처리시설 현황(ST00080001) — `SewageTreatFactStatusInpColumn.tabKey` */
export const SEWAGE_TREAT_FACT_STATUS_STATS_CD = "ST00080001" as const;
/** 검증 결과 한 건 */
export interface PrivateSewageFacilityVerificationResultItem {
vrfcCd: string;
rsnExpln: string;
nowVlCn: string;
compVlCn: string;
}
/** 필드명 → 검증 결과 배열 */
export type PrivateSewageFacilityVerificationResult = Record<
string,
PrivateSewageFacilityVerificationResultItem[]
>;
/** ST00080001 조회 `data.commonInfo` */
export interface SewageTreatFactStatusCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: PrivateSewageFacilityVerificationResult;
}
/**
* ST00080001 조회 `data.sewageTreatFactStatusList[]` 한 행.
* `SewageTreatFactStatusInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface SewageTreatFactStatusItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
wholDrtwPrcsFcltCnt: number;
wholStaaCnt: number;
step1StaaPrcsQnt: number;
step2StaaPrcsQnt: number;
step3StaaPrcsQnt: number;
step4StaaPrcsQnt: number;
step5StaaPrcsQnt: number;
step6StaaPrcsQnt: number;
step7StaaPrcsQnt: number;
staaExcpWhol: number;
step1StaaExcpPrcsQnt: number;
step2StaaExcpPrcsQnt: number;
step3StaaExcpPrcsQnt: number;
step4StaaExcpPrcsQnt: number;
step5StaaExcpPrcsQnt: number;
step6StaaExcpPrcsQnt: number;
step7StaaExcpPrcsQnt: number;
rmrk: string | null;
verificationResult?: PrivateSewageFacilityVerificationResult;
}
export interface SewageTreatFactStatusResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: SewageTreatFactStatusCommonInfo;
sewageTreatFactStatusList: SewageTreatFactStatusItem[];
}
export type SewageTreatFactStatusApiResponse = ApiResponse<SewageTreatFactStatusResponseData> & {
message: string;
};
/** ST00080001 조회 요청 파라미터 */
export interface SewageTreatFactStatusRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
}
/** 정화조 현황(ST00080002) — `SepticTankStatusInpColumn.tabKey` */
export const SEPTIC_TANK_STATUS_STATS_CD = "ST00080002" as const;
/** ST00080002 조회 `data.commonInfo` */
export interface SepticTankStatusCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: PrivateSewageFacilityVerificationResult;
}
/**
* ST00080002 조회 `data.septicTankStatusList[]` 한 행.
* `SepticTankStatusInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface SepticTankStatusItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
grssFcltCnt: number;
staaInsdWhol: number;
staaInsdPrcsMthByWhol: number;
staaInsdSttkNprsflCnt: number;
step1StaaInsdSttkFrcCnt: number;
staaInsdSprktpFltrtbCnt: number;
staaInsdAertMthdCnt: number;
staaInsdCntcAertCnt: number;
staaInsdEtcCnt: number;
staaInsdPrcsCpctByWhol: number;
step1StaaInsdNope: number;
step2StaaInsdNope: number;
step3StaaInsdNope: number;
step4StaaInsdNope: number;
step5StaaInsdNope: number;
step6StaaInsdNope: number;
step7StaaInsdNope: number;
step8StaaInsdNope: number;
staaExcpWhol: number;
staaExcpPrcsMthByWhol: number;
staaExcpSttkNprsflCnt: number;
step1StaaExcpSttkFrcCnt: number;
staaExcpSprktpFltrtbCnt: number;
staaExcpAertMthdCnt: number;
staaExcpCntcAertCnt: number;
staaExcpEtcCnt: number;
staaExcpPrcsCpctByWhol: number;
step1StaaExcpNope: number;
step2StaaExcpNope: number;
step3StaaExcpNope: number;
step4StaaExcpNope: number;
step5StaaExcpNope: number;
step6StaaExcpNope: number;
step7StaaExcpNope: number;
step8StaaExcpNope: number;
rmrk: string | null;
verificationResult?: PrivateSewageFacilityVerificationResult;
}
export interface SepticTankStatusResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: SepticTankStatusCommonInfo;
septicTankStatusList: SepticTankStatusItem[];
}
export type SepticTankStatusApiResponse = ApiResponse<SepticTankStatusResponseData> & {
message: string;
};
/** ST00080002 조회 요청 파라미터 */
export interface SepticTankStatusRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
}
/** 개인하수도 관리지역 지정공고 현황(ST00080003) — `PrivateSewageDesigStatusInpColumn` */
export const PRIVATE_SEWAGE_DESIG_STATUS_STATS_CD = "ST00080003" as const;
/** ST00080003 조회 `data.commonInfo` */
export interface PrivateSewageDesigStatusCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: PrivateSewageFacilityVerificationResult;
}
/**
* ST00080003 조회 `data.privateSewageDesigStatusList[]` 한 행.
* `PrivateSewageDesigStatusInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface PrivateSewageDesigStatusItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
indvSwagePbancRgnCnt: number;
indvSwageDsgnScpLen: number;
spctnkGrssFcltCnt: number;
spctnkQnt: number;
drtwPrcsFcltGrssFcltCnt: number;
drtwPrcsFcltQnt: number;
rmrk: string | null;
verificationResult?: PrivateSewageFacilityVerificationResult;
}
export interface PrivateSewageDesigStatusResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: PrivateSewageDesigStatusCommonInfo;
privateSewageDesigStatusList: PrivateSewageDesigStatusItem[];
}
export type PrivateSewageDesigStatusApiResponse =
ApiResponse<PrivateSewageDesigStatusResponseData> & {
message: string;
};
/** ST00080003 조회 요청 파라미터 */
export interface PrivateSewageDesigStatusRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
}
/**
* ST00080001 저장·제출 API `saveList` / `submitList` 한 행.
* `sggNm`·계산필드(`wholDrtwPrcsFcltCnt`, `wholStaaCnt`, `staaExcpWhol`)·검증결과는 제외.
*/
export interface SewageTreatFactStatusSaveItem {
admdstCd: string;
admdstNm: string;
step1StaaPrcsQnt: number;
step2StaaPrcsQnt: number;
step3StaaPrcsQnt: number;
step4StaaPrcsQnt: number;
step5StaaPrcsQnt: number;
step6StaaPrcsQnt: number;
step7StaaPrcsQnt: number;
step1StaaExcpPrcsQnt: number;
step2StaaExcpPrcsQnt: number;
step3StaaExcpPrcsQnt: number;
step4StaaExcpPrcsQnt: number;
step5StaaExcpPrcsQnt: number;
step6StaaExcpPrcsQnt: number;
step7StaaExcpPrcsQnt: number;
rmrk: string | null;
}
/** ST00080001 저장 API 요청 */
export interface SewageTreatFactStatusSaveRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
superAdmin?: string;
noApplicable?: boolean;
saveList: SewageTreatFactStatusSaveItem[];
}
export interface SewageTreatFactStatusSaveResponse {
status: string;
message?: string;
data?: string;
}
/** ST00080001 제출 API 요청 */
export interface SewageTreatFactStatusSubmitRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
laePicNm: string;
laePicTelNo: string;
laeKbrdrDeptNm: string;
laeKbrdrJbgdNm: string;
laeIdfrNm: string;
laeIdfrTelNo: string;
laeIdfrDeptNm: string;
laeIdfrJbgdNm: string;
superAdmin?: string;
noApplicable?: boolean;
submitList: SewageTreatFactStatusSaveItem[];
}
export interface SewageTreatFactStatusSubmitResponse {
status: string;
message?: string;
data?: {
finalStatus: string;
nvpassed: boolean;
};
}
/**
* ST00080002 저장·제출 API `saveList` / `submitList` 한 행.
* `sggNm`·계산필드(`grssFcltCnt`, `staaInsdWhol`, `staaInsdPrcsMthByWhol`, `staaInsdPrcsCpctByWhol`,
* `staaExcpWhol`, `staaExcpPrcsMthByWhol`, `staaExcpPrcsCpctByWhol`)·검증결과는 제외.
*/
export interface SepticTankStatusSaveItem {
admdstCd: string;
admdstNm: string;
staaInsdSttkNprsflCnt: number;
step1StaaInsdSttkFrcCnt: number;
staaInsdSprktpFltrtbCnt: number;
staaInsdAertMthdCnt: number;
staaInsdCntcAertCnt: number;
staaInsdEtcCnt: number;
step1StaaInsdNope: number;
step2StaaInsdNope: number;
step3StaaInsdNope: number;
step4StaaInsdNope: number;
step5StaaInsdNope: number;
step6StaaInsdNope: number;
step7StaaInsdNope: number;
step8StaaInsdNope: number;
staaExcpSttkNprsflCnt: number;
step1StaaExcpSttkFrcCnt: number;
staaExcpSprktpFltrtbCnt: number;
staaExcpAertMthdCnt: number;
staaExcpCntcAertCnt: number;
staaExcpEtcCnt: number;
step1StaaExcpNope: number;
step2StaaExcpNope: number;
step3StaaExcpNope: number;
step4StaaExcpNope: number;
step5StaaExcpNope: number;
step6StaaExcpNope: number;
step7StaaExcpNope: number;
step8StaaExcpNope: number;
rmrk: string | null;
}
/** ST00080002 저장 API 요청 */
export interface SepticTankStatusSaveRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
superAdmin?: string;
noApplicable?: boolean;
saveList: SepticTankStatusSaveItem[];
}
export interface SepticTankStatusSaveResponse {
status: string;
message?: string;
data?: string;
}
/** ST00080002 제출 API 요청 */
export interface SepticTankStatusSubmitRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
laePicNm: string;
laePicTelNo: string;
laeKbrdrDeptNm: string;
laeKbrdrJbgdNm: string;
laeIdfrNm: string;
laeIdfrTelNo: string;
laeIdfrDeptNm: string;
laeIdfrJbgdNm: string;
superAdmin?: string;
noApplicable?: boolean;
submitList: SepticTankStatusSaveItem[];
}
export interface SepticTankStatusSubmitResponse {
status: string;
message?: string;
data?: {
finalStatus: string;
nvpassed: boolean;
};
}
/**
* ST00080003 저장·제출 API `saveList` / `submitList` 한 행.
* `sggNm`·검증결과는 제외.
*/
export interface PrivateSewageDesigStatusSaveItem {
admdstCd: string;
admdstNm: string;
indvSwagePbancRgnCnt: number;
indvSwageDsgnScpLen: number;
spctnkGrssFcltCnt: number;
spctnkQnt: number;
drtwPrcsFcltGrssFcltCnt: number;
drtwPrcsFcltQnt: number;
rmrk: string | null;
}
/** ST00080003 저장 API 요청 */
export interface PrivateSewageDesigStatusSaveRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
superAdmin?: string;
noApplicable?: boolean;
saveList: PrivateSewageDesigStatusSaveItem[];
}
export interface PrivateSewageDesigStatusSaveResponse {
status: string;
message?: string;
data?: string;
}
/** ST00080003 제출 API 요청 */
export interface PrivateSewageDesigStatusSubmitRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
laePicNm: string;
laePicTelNo: string;
laeKbrdrDeptNm: string;
laeKbrdrJbgdNm: string;
laeIdfrNm: string;
laeIdfrTelNo: string;
laeIdfrDeptNm: string;
laeIdfrJbgdNm: string;
superAdmin?: string;
noApplicable?: boolean;
submitList: PrivateSewageDesigStatusSaveItem[];
}
export interface PrivateSewageDesigStatusSubmitResponse {
status: string;
message?: string;
data?: {
finalStatus: string;
nvpassed: boolean;
};
}
export interface StatisticsInputPrivateSewageFacilityService {
getSewageTreatFactStatusList(
params: SewageTreatFactStatusRequestParams,
): Promise<SewageTreatFactStatusApiResponse>;
saveSewageTreatFactStatus(
request: SewageTreatFactStatusSaveRequest,
): Promise<SewageTreatFactStatusSaveResponse>;
submitSewageTreatFactStatus(
request: SewageTreatFactStatusSubmitRequest,
): Promise<SewageTreatFactStatusSubmitResponse>;
getSepticTankStatusList(
params: SepticTankStatusRequestParams,
): Promise<SepticTankStatusApiResponse>;
saveSepticTankStatus(
request: SepticTankStatusSaveRequest,
): Promise<SepticTankStatusSaveResponse>;
submitSepticTankStatus(
request: SepticTankStatusSubmitRequest,
): Promise<SepticTankStatusSubmitResponse>;
getPrivateSewageDesigStatusList(
params: PrivateSewageDesigStatusRequestParams,
): Promise<PrivateSewageDesigStatusApiResponse>;
savePrivateSewageDesigStatus(
request: PrivateSewageDesigStatusSaveRequest,
): Promise<PrivateSewageDesigStatusSaveResponse>;
submitPrivateSewageDesigStatus(
request: PrivateSewageDesigStatusSubmitRequest,
): Promise<PrivateSewageDesigStatusSubmitResponse>;
}
@@ -0,0 +1,174 @@
import type { ApiResponse, SewerageStatusInfo } from "../statistics-interface";
/** 펌프장(ST00050001) — `PumpingStationInpColumn` tabKey */
export const PUMPING_STATION_STATS_CD = "ST00050001" as const;
/** 검증 결과 한 건 */
export interface PumpingStationVerificationResultItem {
vrfcCd: string;
rsnExpln: string;
nowVlCn: string;
compVlCn: string;
}
/** 필드명 → 검증 결과 배열 */
export type PumpingStationVerificationResult = Record<
string,
PumpingStationVerificationResultItem[]
>;
/** 펌프장 조회 `data.commonInfo` */
export interface PumpingStationCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: PumpingStationVerificationResult;
}
/**
* 펌프장 조회 `data.pumpingStationList[]` 한 행.
* `PumpingStationInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface PumpingStationItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
fcltSn: string;
swtrmtFcltNm: string;
fcltNm: string;
pumpSeNm: string;
fcltPstnCn: string;
oprtngStrtYmd: string;
planMltvArea: number;
sndyArea: number;
rainArea: number;
exlnQnt: number;
drtwPumpGrssPpqty: number;
drtwPumpN1DmtrArea: number;
drtwPumpN1Ppqty: number;
drtwPumpN1Cnt: number;
drtwPumpN1RsrvCnt: number;
drtwPumpN2DmtrArea: number;
drtwPumpN2Ppqty: number;
drtwPumpN2Cnt: number;
drtwPumpN2RsrvCnt: number;
drtwPumpN3DmtrArea: number;
drtwPumpN3Ppqty: number;
drtwPumpN3Cnt: number;
drtwPumpN3RsrvCnt: number;
exlnPumpGrssPpqty: number;
exlnPumpN1DmtrArea: number;
exlnPumpN1Ppqty: number;
exlnPumpN1Cnt: number;
exlnPumpN1RsrvCnt: number;
exlnPumpN2DmtrArea: number;
exlnPumpN2Ppqty: number;
exlnPumpN2Cnt: number;
exlnPumpN2RsrvCnt: number;
exlnPumpN3DmtrArea: number;
exlnPumpN3Ppqty: number;
exlnPumpN3Cnt: number;
exlnPumpN3RsrvCnt: number;
anlElpwrUseQnt: number;
rmrk: string | null;
verificationResult?: PumpingStationVerificationResult;
}
export interface PumpingStationResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: PumpingStationCommonInfo;
pumpingStationList: PumpingStationItem[];
}
export type PumpingStationApiResponse = ApiResponse<PumpingStationResponseData> & {
message: string;
};
/** 펌프장(ST00050001) 조회 요청 파라미터 */
export interface PumpingStationRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
fcltNm?: string;
}
/**
* 펌프장(ST00050001) 저장 — `saveList` / `deleteList` 항목.
* `sggNm`·계산필드·검증결과는 저장 요청에서 제외.
*/
export type PumpingStationSaveItem = Omit<
PumpingStationItem,
| "sggNm"
| "verificationResult"
| "exlnQnt"
| "drtwPumpGrssPpqty"
| "exlnPumpGrssPpqty"
>;
/** 펌프장(ST00050001) 저장 API 요청 */
export interface PumpingStationSaveRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
superAdmin?: string;
noApplicable?: boolean;
saveList: PumpingStationSaveItem[];
deleteList: PumpingStationSaveItem[];
}
export interface PumpingStationSaveResponse {
status: string;
message?: string;
data?: string;
}
export type PumpingStationSubmitItem = PumpingStationSaveItem;
/** 펌프장(ST00050001) 제출 API 요청 */
export interface PumpingStationSubmitRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
laePicNm: string;
laePicTelNo: string;
laeKbrdrDeptNm: string;
laeKbrdrJbgdNm: string;
laeIdfrNm: string;
laeIdfrTelNo: string;
laeIdfrDeptNm: string;
laeIdfrJbgdNm: string;
superAdmin?: string;
noApplicable?: boolean;
submitList: PumpingStationSubmitItem[];
deleteList: PumpingStationSubmitItem[];
}
export interface PumpingStationSubmitResponse {
status: string;
message?: string;
data?: {
finalStatus: string;
nvpassed: boolean;
};
}
export interface StatisticsInputPumpingStationService {
getPumpingStationList(
params: PumpingStationRequestParams,
): Promise<PumpingStationApiResponse>;
savePumpingStationList(
request: PumpingStationSaveRequest,
): Promise<PumpingStationSaveResponse>;
submitPumpingStationList(
request: PumpingStationSubmitRequest,
): Promise<PumpingStationSubmitResponse>;
}
@@ -194,10 +194,101 @@ export interface SewageReservoirSaveResponse {
data?: string;
}
/** 하수저류시설(ST00040001) 제출 API 요청 */
export interface SewageReservoirSubmitRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
laePicNm: string;
laePicTelNo: string;
laeKbrdrDeptNm: string;
laeKbrdrJbgdNm: string;
laeIdfrNm: string;
laeIdfrTelNo: string;
laeIdfrDeptNm: string;
laeIdfrJbgdNm: string;
noApplicable?: boolean;
submitList: SewageReservoirSaveItem[];
deleteList: SewageReservoirSaveItem[];
}
export interface SewageReservoirSubmitResponse {
status: string;
message?: string;
data?: {
finalStatus: string;
nvpassed: boolean;
};
}
/**
* 빗물펌프장(ST00040002) 저장 — `saveList` / `deleteList` 항목.
* `sggNm`·검증결과는 저장 요청에서 제외.
*/
export type RainfallPumpStationSaveItem = Omit<
RainfallPumpStationItem,
"sggNm" | "verificationResult"
>;
/**
* 빗물펌프장(ST00040002) 저장 API 요청
* (요청 shape은 예시 JSON과 동일)
*/
export interface RainfallPumpStationSaveRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
superAdmin?: string;
noApplicable?: boolean;
saveList: RainfallPumpStationSaveItem[];
deleteList: RainfallPumpStationSaveItem[];
}
/** 빗물펌프장(ST00040002) 저장 응답 */
export type RainfallPumpStationSaveResponse = SewageReservoirSaveResponse;
/** 빗물펌프장(ST00040002) 제출 API 요청 */
export interface RainfallPumpStationSubmitRequest {
statsYr: string;
ctpvNm: string;
sggNm: string;
sewerBzmnCd: string;
userId: string;
laePicNm: string;
laePicTelNo: string;
laeKbrdrDeptNm: string;
laeKbrdrJbgdNm: string;
laeIdfrNm: string;
laeIdfrTelNo: string;
laeIdfrDeptNm: string;
laeIdfrJbgdNm: string;
noApplicable?: boolean;
submitList: RainfallPumpStationSaveItem[];
deleteList: RainfallPumpStationSaveItem[];
}
/** 빗물펌프장(ST00040002) 제출 응답 */
export type RainfallPumpStationSubmitResponse = SewageReservoirSubmitResponse;
export interface StatisticsInputSewageReservoirPumpService {
getSewageReservoirList(params: SewageReservoirRequestParams): Promise<SewageReservoirApiResponse>;
getRainfallPumpStationList(
params: SewageReservoirRequestParams,
): Promise<RainfallPumpStationApiResponse>;
saveSewageReservoir(request: SewageReservoirSaveRequest): Promise<SewageReservoirSaveResponse>;
submitSewageReservoir(
request: SewageReservoirSubmitRequest,
): Promise<SewageReservoirSubmitResponse>;
/** 빗물펌프장 저장 — ST00040002 */
saveRainfallPumpStation(
request: RainfallPumpStationSaveRequest,
): Promise<RainfallPumpStationSaveResponse>;
/** 빗물펌프장 제출 — ST00040002 */
submitRainfallPumpStation(
request: RainfallPumpStationSubmitRequest,
): Promise<RainfallPumpStationSubmitResponse>;
}
@@ -0,0 +1,277 @@
import type { ApiResponse, SewerageStatusInfo } from "../statistics-interface";
/** 하수도재정 결산(ST00090001) — `SewerageFinanceSettleInpColumn.tabKey` */
export const SEWERAGE_FINANCE_SETTLE_STATS_CD = "ST00090001" as const;
/** 검증 결과 한 건 */
export interface SewerageFinanceVerificationResultItem {
vrfcCd: string;
rsnExpln: string;
nowVlCn: string;
compVlCn: string;
}
/** 필드명 → 검증 결과 배열 */
export type SewerageFinanceVerificationResult = Record<
string,
SewerageFinanceVerificationResultItem[]
>;
/** ST00090001 조회 `data.commonInfo` */
export interface SewerageFinanceSettleCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: SewerageFinanceVerificationResult;
}
/**
* ST00090001 조회 `data.sewerageFinanceSettleList[]` 한 행.
* `SewerageFinanceSettleInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface SewerageFinanceSettleItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
fnnByWholPjtcoAmt: number;
cnterGovSprtAmt: number;
mctpvLcexpAmt: number;
wareaSggLclAmt: number;
sewerUseAmt: number;
orgprBrdnAmt: number;
etcIncmAmt: number;
crfwAmt: number;
lbltAmt: number;
usgByWholPjtcoAmt: number;
tmplntWholAmt: number;
tmplntFcltAmt: number;
tmplntMendngAmt: number;
tmplntOperKeepAmt: number;
tmplntEtcAmt: number;
wholSwagePplAmt: number;
swagePplFcltAmt: number;
swagePplMendngAmt: number;
swagePplOperKeepAmt: number;
swagePplEtcAmt: number;
wholSwageImpdFcltAmt: number;
swageImpdFcltAmt: number;
swageImpdMendngAmt: number;
swageImpdOperKeepAmt: number;
swageImpdFcltEtcAmt: number;
etcWholAmt: number;
etcAcdntCrfwAmt: number;
etcNrcpAmt: number;
etcAmt: number;
rmrk: string | null;
verificationResult?: SewerageFinanceVerificationResult;
}
export interface SewerageFinanceSettleResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: SewerageFinanceSettleCommonInfo;
sewerageFinanceSettleList: SewerageFinanceSettleItem[];
}
export type SewerageFinanceSettleApiResponse = ApiResponse<SewerageFinanceSettleResponseData> & {
message: string;
};
/** ST00090001 조회 요청 파라미터 */
export interface SewerageFinanceSettleRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
}
/** 하수도 요금(ST00090002) — `SewerageChargeInpColumn.tabKey` */
export const SEWERAGE_CHARGE_STATS_CD = "ST00090002" as const;
/** ST00090002 조회 `data.commonInfo` */
export interface SewerageChargeCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: SewerageFinanceVerificationResult;
}
/**
* ST00090002 조회 `data.sewerageChargeList[]` 한 행.
* `SewerageChargeInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface SewerageChargeItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
anlLevyQnt: number;
levyAmt: number;
avgUntprcAmt: number;
grssPrmcoAmt: number;
grssUnitPrmcoAmt: number;
rlztnRt: number;
rmrk: string | null;
verificationResult?: SewerageFinanceVerificationResult;
}
export interface SewerageChargeResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: SewerageChargeCommonInfo;
sewerageChargeList: SewerageChargeItem[];
}
export type SewerageChargeApiResponse = ApiResponse<SewerageChargeResponseData> & {
message: string;
};
/** ST00090002 조회 요청 파라미터 */
export interface SewerageChargeRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
}
/** 하수도 사용료(ST00090003) — `SewerageUsageFeeInpColumn.tabKey` */
export const SEWERAGE_USAGE_FEE_STATS_CD = "ST00090003" as const;
/** ST00090003 조회 `data.commonInfo` */
export interface SewerageUsageFeeCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: SewerageFinanceVerificationResult;
}
/**
* ST00090003 조회 `data.sewerageUsageFeeList[]` 한 행.
* `SewerageUsageFeeInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface SewerageUsageFeeItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
levyAmt: number;
levyQnt: number;
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;
verificationResult?: SewerageFinanceVerificationResult;
}
export interface SewerageUsageFeeResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: SewerageUsageFeeCommonInfo;
sewerageUsageFeeList: SewerageUsageFeeItem[];
}
export type SewerageUsageFeeApiResponse = ApiResponse<SewerageUsageFeeResponseData> & {
message: string;
};
/** ST00090003 조회 요청 파라미터 */
export interface SewerageUsageFeeRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
}
/** 원인자 부담금(ST00090004) — `CauserBurdenInpColumn.tabKey` */
export const CAUSER_BURDEN_STATS_CD = "ST00090004" as const;
/** ST00090004 조회 `data.commonInfo` */
export interface CauserBurdenCommonInfo {
statsYr: string;
ctpvNm: string;
sewerBzmnCd: string;
statsCd: string;
verificationResult?: SewerageFinanceVerificationResult;
}
/**
* ST00090004 조회 `data.causerBurdenList[]` 한 행.
* `CauserBurdenInpColumn` fieldName과 동일 (`ctpvNm` 그리드 값은 `commonInfo.ctpvNm` 시도명).
*/
export interface CauserBurdenItem {
admdstCd: string;
sggNm: string;
admdstNm: string;
levyEvntcsCnt: number;
levyAmt: number;
trgtByWholClctnEvntcsCnt: number;
trgtByWholClctnAmt: number;
mltvEqpmEvntcsCnt: number;
mltvEqpmAmt: number;
othrCstrnOthrActrCnt: number;
othrCstrnOthrActrAmt: number;
rmrk: string | null;
verificationResult?: SewerageFinanceVerificationResult;
}
export interface CauserBurdenResponseData {
statusInfo: SewerageStatusInfo;
commonInfo: CauserBurdenCommonInfo;
causerBurdenList: CauserBurdenItem[];
}
export type CauserBurdenApiResponse = ApiResponse<CauserBurdenResponseData> & {
message: string;
};
/** ST00090004 조회 요청 파라미터 */
export interface CauserBurdenRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
}
/** 하수도재정 조회 공통 요청 파라미터 */
export interface SewerageFinanceRequestParams {
ctpvNm?: string;
sggNm?: string;
sewerBzmnCd?: string;
statsYr?: string;
mode?: string;
}
export interface StatisticsInputSewerageFinanceService {
getSewerageFinanceSettleList(
params: SewerageFinanceSettleRequestParams,
): Promise<SewerageFinanceSettleApiResponse>;
getSewerageChargeList(
params: SewerageChargeRequestParams,
): Promise<SewerageChargeApiResponse>;
getSewerageUsageFeeList(
params: SewerageUsageFeeRequestParams,
): Promise<SewerageUsageFeeApiResponse>;
getCauserBurdenList(
params: CauserBurdenRequestParams,
): Promise<CauserBurdenApiResponse>;
}
+1
View File
@@ -1 +1,2 @@
export { client } from "./client";
export { withAuthHeader } from "./with-auth-header";
@@ -0,0 +1,16 @@
import type { AxiosRequestConfig } from "axios";
import { getToken } from "@/entities/auth/lib/token-manager";
import { CLAIM_NAME } from "@/shared/config";
export function withAuthHeader<T extends AxiosRequestConfig>(config: T = {} as T): T {
const authorization = getToken(CLAIM_NAME);
if (!authorization) return config;
return {
...config,
headers: {
...config.headers,
[CLAIM_NAME]: authorization,
},
};
}