@@ -216,10 +737,22 @@ const PublicSewageFacilityInp = () => {
rightColumnInfo={getGridColumnInfo(tab.right)}
leftFixedColumns={tab.left.fixedColumns}
rightFixedColumns={tab.right.fixedColumns}
- showHeaderCheckbox={false}
+ showHeaderCheckbox={true}
enableSort={false}
leftRowData={rowDataMap.get(leftKey) ?? []}
rightRowData={rowDataMap.get(rightKey) ?? []}
+ leftOnRowClick={
+ tab.tabKey === 'ST00060002'
+ ? (row) => {
+ void handleMainFacilityRowClick(row);
+ }
+ : undefined
+ }
+ leftCellStyleCallback={
+ tab.tabKey === 'ST00060002'
+ ? leftMainFacilityCellStyleCallback
+ : undefined
+ }
setLeftRowData={(updater) => {
setRowDataMap((prev) => {
const next = new Map(prev);
@@ -256,6 +789,7 @@ const PublicSewageFacilityInp = () => {
columnInfo={gridColumnInfo}
rowStartNum={tab.rowStartNum}
fixedColumns={tab.fixedColumns}
+ statusInfo={activeTabStatus}
rowData={rowDataMap.get(tab.tabKey) ?? []}
setRowData={(updater) => {
setRowDataMap((prev) => {
@@ -277,6 +811,14 @@ const PublicSewageFacilityInp = () => {
})}
+
>
);
};
diff --git a/apps/st/src/components/statistics/input/SewagePipeInp.tsx b/apps/st/src/components/statistics/input/SewagePipeInp.tsx
index e833c60bd..fb39754ce 100644
--- a/apps/st/src/components/statistics/input/SewagePipeInp.tsx
+++ b/apps/st/src/components/statistics/input/SewagePipeInp.tsx
@@ -1756,7 +1756,7 @@ const SewagePipeInp = () => {
/>
{showEnterableToolbarButtons && (
<>
-
void getLastYearDataFunc()} />
+ {activeTab !== 'ST00020002' && void getLastYearDataFunc()} />}
void submitFunc(false)} />
>
)}
diff --git a/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx b/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx
index ad1f4faa8..071d86bca 100644
--- a/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx
+++ b/apps/st/src/components/statistics/input/SeweragePenetrationRateInp.tsx
@@ -295,9 +295,9 @@ const SeweragePenetrationRateInp = () => {
statsCd: statsCd,
};
- // if (isAdminInfo) {
- // params.superAdmin = 'superAdmin';
- // }
+ if (isAdminInfo) {
+ params.superAdmin = 'superAdmin';
+ }
try {
setIsLoading(true);
diff --git a/apps/st/src/components/statistics/total/SewagePipeTot.tsx b/apps/st/src/components/statistics/total/SewagePipeTot.tsx
index 0ee0aac2b..2553fce19 100644
--- a/apps/st/src/components/statistics/total/SewagePipeTot.tsx
+++ b/apps/st/src/components/statistics/total/SewagePipeTot.tsx
@@ -11,16 +11,21 @@ import type { SearchFormValues } from "@/components/type/SearchForm.type";
import { SewagePipeColumnInfoListTot } from "@/components/util/column/total/SewagePipeTotColumn";
import { toGridRows } from "@/components/util/grid/gridFunction";
import type { SewagePipeTotalRequest } from "@/entities/statistics/model/statistics-total/statistics-sewage-pipe-total-interface";
+import CellColorInfo from "./CellColorInfo";
const firstTabKey = SewagePipeColumnInfoListTot[0]?.tabKey ?? "ST00020001";
function buildSewagePipeTotSearchParam(values: SearchFormValues): SewagePipeTotalRequest {
+ const isSummaryEnabled = values.isSummary !== 'ALL';
+ const summaryYearCnt = isSummaryEnabled ? Number(values.isSummary) : undefined;
+
return {
ctpvNm: values.sido === "ALL" ? "" : values.sido,
sggNm: values.gugun === "ALL" ? "" : values.gugun,
sewerBzmnCd: values.bsnmCd,
statsYr: values.year,
rowDataYn: values.isDetail,
+ ...(isSummaryEnabled ? { summaryYearCnt } : {}),
};
}
@@ -164,7 +169,7 @@ const SewagePipeTot = () => {
return (
-
+
{isLoading && (
@@ -172,6 +177,7 @@ const SewagePipeTot = () => {
)}
+
{
fixedColumns={info.fixedColumns}
enableSort={false}
cellStyleCallback={({ row }) => {
- const rowType = String(row.rowType ?? "");
- if (rowType === "DETAIL") return undefined;
- if (rowType === "BIZ_SUM") return "rg-cell-rowtype-biz-sum";
- return "rg-cell-rowtype-other";
+ const rowType = String(row.rowType ?? '');
+ if (rowType === 'DETAIL') return undefined;
+ if (rowType === 'BIZ_SUM') return 'rg-cell-rowtype-biz-sum';
+ if (rowType === 'SUMMARY') return 'rg-cell-rowtype-summary';
+ return 'rg-cell-rowtype-other';
}}
/>
diff --git a/apps/st/src/components/statistics/verification/generalVerification/DetailComponent.tsx b/apps/st/src/components/statistics/verification/generalVerification/DetailComponent.tsx
index c27387e85..1643a9f89 100644
--- a/apps/st/src/components/statistics/verification/generalVerification/DetailComponent.tsx
+++ b/apps/st/src/components/statistics/verification/generalVerification/DetailComponent.tsx
@@ -1,6 +1,11 @@
import { useEffect, useRef, useState } from 'react';
+import { useConfirm } from '@frontend-opensource/use-react-hooks';
+
+import { useAlertStore } from '@/shared/lib';
import { NoData } from '@/shared/ui/no-data';
+import { generalverificationApiService } from '@/entities/statistics/api/general-verification-service';
+import type { VerifyDetailData, VerifyDetailResponseDto } from '@/entities/statistics/model/general-verification-interface';
import {
Button,
Table,
@@ -9,17 +14,13 @@ import {
TableHead,
TableRow,
} from "@common/components";
-import FormulaComponents from './FormulaComponents';
import { LoadingWithAnimation } from '@common/components';
-import FomulaDialog from './FomulaDialog';
-import { useAlertStore } from '@/shared/lib';
-import { useConfirm } from '@frontend-opensource/use-react-hooks';
-
-import { generalverificationApiService } from '@/entities/statistics/api/general-verification-service';
-import type { VerifyDetailData, VerifyDetailResponseDto } from '@/entities/statistics/model/general-verification-interface';
import { getUserInfo } from '../../../../../../../packages/common/components/src/api';
+import FomulaDialog from './FomulaDialog';
+import FormulaComponents from './FormulaComponents';
+
interface DetailComponentProps {
selectedVrfcRow: number | null;
}
@@ -107,19 +108,16 @@ const DetailComponent = ({ selectedVrfcRow }: DetailComponentProps) => {
}
}
- // 여러 항목일 때 마지막이 단항 연산자면: 이전 항목들 연산자는 무조건 null
+ // 여러 항목일 때 마지막이 단항 연산자면:
+ // 이전 항목들의 연산자는 '?'일 때만 등록 허용 (자동 null 보정하지 않음)
if (rows.length > 1 && lastIsUnary) {
- for (let i = 0; i < rows.length - 1; i++) {
- const prev = rows[i];
- if (prev) prev.cmprOpert = null;
- }
- setFormulaList((prev) => {
- if (prev.length <= 1) return prev;
- const next = prev.map((item, idx) =>
- idx < prev.length - 1 && item != null ? { ...item, cmprOpert: null } : item,
+ const invalidUnaryPrevIdx = rows.slice(0, -1).findIndex((r) => r.cmprOpert !== '?');
+ if (invalidUnaryPrevIdx !== -1) {
+ alert(
+ `마지막 항목이 단항 연산자(is_null, !is_null, floor)일 때는 이전 항목의 연산자를 '?'로 선택해야 합니다.\n(순번: ${invalidUnaryPrevIdx + 1})`,
);
- return next;
- });
+ return;
+ }
}
// 마지막 항목의 연산자는 (단항 연산자 케이스 제외) 무조건 null 처리
diff --git a/apps/st/src/components/type/DataGrid.type.ts b/apps/st/src/components/type/DataGrid.type.ts
index 432cf68e4..1fef46df3 100644
--- a/apps/st/src/components/type/DataGrid.type.ts
+++ b/apps/st/src/components/type/DataGrid.type.ts
@@ -365,6 +365,10 @@ export type SplitDataGridProps = {
setRightRowData: React.Dispatch<
React.SetStateAction[]>
>;
+ /** 좌측 분할 그리드 행 클릭 이벤트 */
+ leftOnRowClick?: (rowData: Record) => void;
+ /** 좌측 분할 그리드 셀 스타일 콜백 */
+ leftCellStyleCallback?: CellStyleCallback;
/** 전체 정렬 기능 on/off (기본값: false) */
enableSort?: boolean;
};
diff --git a/apps/st/src/components/util/column/input/PublicSewageFactInpColumn/PublicSewageFactColumn.ts b/apps/st/src/components/util/column/input/PublicSewageFactInpColumn/PublicSewageFactColumn.ts
index a97ba549f..8cb23828f 100644
--- a/apps/st/src/components/util/column/input/PublicSewageFactInpColumn/PublicSewageFactColumn.ts
+++ b/apps/st/src/components/util/column/input/PublicSewageFactInpColumn/PublicSewageFactColumn.ts
@@ -1,6 +1,7 @@
-import { footerInt, footerDecimal1, footerDecimal3 } from "@/components/util/grid/footerSummary";
import { ValueType } from "realgrid";
+import { footerDecimal1, footerDecimal3,footerInt } from "@/components/util/grid/footerSummary";
+
/**
* 하수도 통계 관리 > 06. 공공하수처리시설
*/
@@ -112,6 +113,7 @@ export const PublicSewageFactColumn = {
{ name: 'sftyAcdntEvntcsCnt', fieldName: 'sftyAcdntEvntcsCnt', header: { text: '안전사고건수' }, valueType: ValueType.NUMBER, dataFormat: '#,##0' },
{ name: 'rmrk', fieldName: 'rmrk', header: { text: '비고' } },
{ name: 'admdstCd', fieldName: 'admdstCd', header: { text: '행정구역코드' }, visible: false, editable: false, styleName: 'rg-cell-readonly' },
+ { name: 'admdstNm', fieldName: 'admdstNm', header: { text: '행정구역명' }, visible: false, editable: false, styleName: 'rg-cell-readonly' },
{ name: 'fcltSn', fieldName: 'fcltSn', header: { text: '처리시설일련번호' }, visible: false, editable: false, valueType: ValueType.TEXT, styleName: 'rg-cell-readonly' },
{ name: 'swtrmtFcltCd', fieldName: 'swtrmtFcltCd', header: { text: '하수처리시설코드' }, visible: false, editable: false, styleName: 'rg-cell-readonly' },
],
diff --git a/apps/st/src/entities/statistics/api/input/statistics-public-sewage-facility-input-service.ts b/apps/st/src/entities/statistics/api/input/statistics-public-sewage-facility-input-service.ts
index d2a900077..d77b875c3 100644
--- a/apps/st/src/entities/statistics/api/input/statistics-public-sewage-facility-input-service.ts
+++ b/apps/st/src/entities/statistics/api/input/statistics-public-sewage-facility-input-service.ts
@@ -1,9 +1,16 @@
-import { ENDPOINT } from "@/shared/config";
import { stClient } from "@/shared/api/client";
+import { ENDPOINT } from "@/shared/config";
+
import type {
- PublicSewageMainFacilityResponse,
PublicSewageFacilityRequestParams,
PublicSewageFacilityResponse,
+ PublicSewageFacilitySaveRequest,
+ PublicSewageFacilitySaveResponse,
+ PublicSewageFacilitySubmitRequest,
+ PublicSewageFacilitySubmitResponse,
+ PublicSewageMainFacilityResponse,
+ PublicSewageMappingTargetsRequestParams,
+ PublicSewageMappingTargetsResponse,
StatisticsInputPublicSewageFacilityService,
} from "../../model/input/statistics-public-sewage-facility-input-interface";
@@ -23,6 +30,36 @@ export class StatisticsInputPublicSewageFacilityApiService implements Statistics
);
return response.data;
}
+
+ public async getMappingTargets(
+ param: PublicSewageMappingTargetsRequestParams,
+ ): Promise {
+ const response = await stClient.get(
+ `${ENDPOINT.ST_SERVICE.INPUT}/public-sewage-facility/main-facility/mapping-targets`,
+ { params: param },
+ );
+ return response.data;
+ }
+
+ public async savePublicSewageFacility(
+ param: PublicSewageFacilitySaveRequest,
+ ): Promise {
+ const response = await stClient.post(
+ `${ENDPOINT.ST_SERVICE.INPUT}/public-sewage-facility/facility/save`,
+ param,
+ );
+ return response.data;
+ }
+
+ public async submitPublicSewageFacility(
+ param: PublicSewageFacilitySubmitRequest,
+ ): Promise {
+ const response = await stClient.post(
+ `${ENDPOINT.ST_SERVICE.INPUT}/public-sewage-facility/facility/submit`,
+ param,
+ );
+ return response.data;
+ }
}
export const statisticsInputPublicSewageFacilityApiService = new StatisticsInputPublicSewageFacilityApiService();
diff --git a/apps/st/src/entities/statistics/model/input/statistics-public-sewage-facility-input-interface.ts b/apps/st/src/entities/statistics/model/input/statistics-public-sewage-facility-input-interface.ts
index e56755f83..19c86e20c 100644
--- a/apps/st/src/entities/statistics/model/input/statistics-public-sewage-facility-input-interface.ts
+++ b/apps/st/src/entities/statistics/model/input/statistics-public-sewage-facility-input-interface.ts
@@ -139,7 +139,116 @@ export interface PublicSewageMainFacilityResponse {
data: PublicSewageMainFacilityResponseData;
}
+/** ST00060002 메인시설 클릭 시 우측 매핑대상 조회 요청 */
+export interface PublicSewageMappingTargetsRequestParams {
+ sewerBzmnCd: string;
+ ctpvNm: string;
+ sggNm: string;
+ statsYr: string;
+ fcltSn: string;
+}
+
+/** ST00060002 메인시설 클릭 시 우측 매핑대상 조회 항목 */
+export interface PublicSewageMappingTargetItem {
+ fcltSn: string;
+ admdstNm: string;
+ swtrmtFcltCd: string;
+ swtrmtFcltNm: string;
+ fcltPstnCn: string;
+ mappedYn: string;
+ mainFcltSn: string;
+ isMainYn: string;
+}
+
+/** ST00060002 메인시설 클릭 시 우측 매핑대상 조회 응답 */
+export interface PublicSewageMappingTargetsResponse {
+ status: string;
+ message?: string;
+ data: PublicSewageMappingTargetItem[];
+}
+
+/** ST00060001 공공하수처리시설 저장 — saveList 항목 */
+export interface PublicSewageFacilitySaveItem {
+ admdstCd: string;
+ admdstNm: string;
+ swtrmtFcltCd: string;
+ swtrmtFcltNm: string;
+ fcltSn: string;
+ fcltPstnCn: string | null;
+
+ inflwSwagePhysQnt: number;
+ inflwSwageBoilQnt: number;
+ inflwSwageAltdQnt: number;
+
+ prcsPhysCpct: number;
+ prcsBoilCpct: number;
+ prcsAltdCpct: number;
+
+ prxyCtrtCn: string | null;
+ sftyAcdntEvntcsCnt: number;
+ rmrk: string | null;
+}
+
+/** ST00060001 공공하수처리시설 저장 API 요청 */
+export interface PublicSewageFacilitySaveRequest {
+ statsYr: string;
+ ctpvNm: string;
+ sggNm: string;
+ sewerBzmnCd: string;
+ userId: string;
+ superAdmin: string;
+
+ /**
+ * 저장 요청에서 "해당없음" 처리 여부가 함께 전달되는 경우를 고려합니다.
+ * (백엔드 스펙에 따라 필수 여부는 달라질 수 있어 optional로 둡니다.)
+ */
+ noApplicable?: boolean;
+
+ saveList: PublicSewageFacilitySaveItem[];
+}
+
+export interface PublicSewageFacilitySaveResponse {
+ data?: string;
+ message?: string;
+ status: string;
+}
+
+/** 공공하수처리시설 입력 제출 공통 본문 (`submitList` 제외) */
+export interface PublicSewageFacilitySubmitRequestBase {
+ statsYr: string;
+ ctpvNm: string;
+ sggNm: string;
+ sewerBzmnCd: string;
+ userId: string;
+ noApplicable?: boolean;
+ laePicNm: string;
+ laePicTelNo: string;
+ laeKbrdrDeptNm: string;
+ laeKbrdrJbgdNm: string;
+ laeIdfrNm: string;
+ laeIdfrTelNo: string;
+ laeIdfrDeptNm: string;
+ laeIdfrJbgdNm: string;
+}
+
+/** ST00060001 공공하수처리시설 제출 API 요청 (`submitList` 행은 저장과 동일) */
+export interface PublicSewageFacilitySubmitRequest extends PublicSewageFacilitySubmitRequestBase {
+ submitList: PublicSewageFacilitySaveItem[];
+}
+
+export interface PublicSewageFacilitySubmitResponse {
+ data: {
+ finalStatus: string;
+ nvpassed: boolean;
+ }
+ message?: string;
+ status: string;
+}
+
export interface StatisticsInputPublicSewageFacilityService {
getPublicSewageFacility(param: PublicSewageFacilityRequestParams): Promise;
getPublicSewageMainFacility(param: PublicSewageFacilityRequestParams): Promise;
+ getMappingTargets(param: PublicSewageMappingTargetsRequestParams): Promise;
+ savePublicSewageFacility(param: PublicSewageFacilitySaveRequest): Promise;
+ submitPublicSewageFacility(param: PublicSewageFacilitySubmitRequest): Promise;
}