[st] - feat: 입력 04 작업 중 & 수정 요청 사항 적용
This commit is contained in:
@@ -457,10 +457,29 @@ function sortRowsGroupPreserving(
|
||||
}
|
||||
|
||||
/** columnInfo → RealGrid DataField 배열 (computed → valueCallback 포함, setFields용) */
|
||||
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;
|
||||
}
|
||||
|
||||
function truncateByDecimalPlaces(value: number, decimalPlaces: number): number {
|
||||
if (!Number.isFinite(value)) return 0;
|
||||
if (decimalPlaces < 0) return value;
|
||||
const factor = 10 ** decimalPlaces;
|
||||
const scaled = value * factor;
|
||||
// 절삭(truncate): 반올림 없이 소수점 이하를 버린다.
|
||||
const truncated = scaled >= 0 ? Math.floor(scaled) : Math.ceil(scaled);
|
||||
return truncated / factor;
|
||||
}
|
||||
|
||||
function buildFieldsFromColumns(
|
||||
columns: {
|
||||
fieldName: string;
|
||||
valueType?: ValueType;
|
||||
dataFormat?: string;
|
||||
datetimeFormat?: string;
|
||||
editor?: { type?: string; datetimeFormat?: string };
|
||||
computed?: import("../type/DataGrid.type").ComputedFieldConfig;
|
||||
@@ -509,17 +528,23 @@ function buildFieldsFromColumns(
|
||||
"subtrahendFields" in col.computed &&
|
||||
col.computed.minuendFields.length > 0;
|
||||
const hasSumOfMaxGroups =
|
||||
col.computed.type === "sumOfMaxOfFieldAndSumGroups" &&
|
||||
"groups" in col.computed &&
|
||||
Array.isArray(col.computed.groups) &&
|
||||
col.computed.groups.length > 0;
|
||||
const hasPumpGrossPpqty =
|
||||
col.computed.type === "pumpGrossPpqty" &&
|
||||
"pumpGroups" in col.computed &&
|
||||
col.computed.pumpGroups.length > 0;
|
||||
if (
|
||||
hasFields ||
|
||||
hasNumeratorDenominator ||
|
||||
hasMaxOfFieldAndSum ||
|
||||
hasDifferenceOfSums ||
|
||||
hasSumOfMaxGroups
|
||||
hasSumOfMaxGroups ||
|
||||
hasPumpGrossPpqty
|
||||
) {
|
||||
field.valueCallback = getComputedValueCallback(
|
||||
const computedCallback = getComputedValueCallback(
|
||||
col.computed,
|
||||
) as (
|
||||
prod: unknown,
|
||||
@@ -528,6 +553,24 @@ function buildFieldsFromColumns(
|
||||
fieldNames: string[],
|
||||
values: unknown[],
|
||||
) => number;
|
||||
const decimalPlaces = getDecimalPlacesFromDataFormat(col.dataFormat);
|
||||
field.valueCallback = (
|
||||
prod: unknown,
|
||||
dataRow: number,
|
||||
fieldName: string,
|
||||
fieldNames: string[],
|
||||
values: unknown[],
|
||||
) => {
|
||||
const computedValue = computedCallback(
|
||||
prod,
|
||||
dataRow,
|
||||
fieldName,
|
||||
fieldNames,
|
||||
values,
|
||||
);
|
||||
if (decimalPlaces == null) return computedValue;
|
||||
return truncateByDecimalPlaces(computedValue, decimalPlaces);
|
||||
};
|
||||
}
|
||||
}
|
||||
return field;
|
||||
@@ -1046,6 +1089,14 @@ const DataGrid = ({
|
||||
}
|
||||
columns.forEach((column) => {
|
||||
const gv = gridView as GridViewWithSetColumnProperty;
|
||||
const exists =
|
||||
typeof (
|
||||
gridView as { columnByName?: (name: string) => unknown }
|
||||
).columnByName === "function" &&
|
||||
(gridView as { columnByName: (name: string) => unknown }).columnByName(
|
||||
column.name,
|
||||
) != null;
|
||||
if (!exists) return;
|
||||
gv.setColumnProperty?.(
|
||||
column.name,
|
||||
"header",
|
||||
@@ -1181,10 +1232,63 @@ const DataGrid = ({
|
||||
const hasFooterUserSpans = checkFooterUserSpans(columnLayout);
|
||||
|
||||
if (hasFooterUserSpans) {
|
||||
const validColumnNames = new Set(columns.map((c) => c.name));
|
||||
const sanitizeColumnLayout = (
|
||||
layout: unknown[],
|
||||
): unknown[] => {
|
||||
const result: unknown[] = [];
|
||||
for (const item of layout) {
|
||||
if (typeof item === "string") {
|
||||
if (validColumnNames.has(item)) {
|
||||
result.push(item);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!item || typeof item !== "object") continue;
|
||||
|
||||
if ("column" in item) {
|
||||
const columnName = (item as { column?: unknown }).column;
|
||||
if (
|
||||
typeof columnName === "string" &&
|
||||
validColumnNames.has(columnName)
|
||||
) {
|
||||
result.push(item);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("items" in item && Array.isArray((item as { items?: unknown[] }).items)) {
|
||||
const nextItems = sanitizeColumnLayout(
|
||||
(item as { items: unknown[] }).items,
|
||||
);
|
||||
if (nextItems.length > 0) {
|
||||
result.push({
|
||||
...(item as Record<string, unknown>),
|
||||
items: nextItems,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push(item);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// setColumnLayout은 그리드가 완전히 렌더링된 후 호출해야 함
|
||||
setTimeout(() => {
|
||||
if (gridRef.current?.gridView && columnLayout) {
|
||||
gridRef.current.gridView.setColumnLayout?.(columnLayout);
|
||||
const safeLayout = sanitizeColumnLayout(columnLayout as unknown[]);
|
||||
if (safeLayout.length === 0) return;
|
||||
try {
|
||||
(
|
||||
gridRef.current.gridView.setColumnLayout as
|
||||
| ((layout: unknown) => void)
|
||||
| undefined
|
||||
)?.(safeLayout);
|
||||
} catch (e) {
|
||||
console.warn("setColumnLayout skipped due to invalid columns:", e);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import DataGrid from "@/components/module/DataGrid";
|
||||
import { VerificationResultHistoryPagination } from "@/components/module/VerificationResultHistoryPagination";
|
||||
import type { CellStyleCallbackParams, ColumnInfo } from "@/components/type/DataGrid.type";
|
||||
|
||||
/** 통계 입력 현황 > 행 클릭 시 예외처리(prcsYn=3) 내역만 조회 */
|
||||
/** 통계 입력 현황 > 행 클릭 시 사용자예외처리(prcsYn=2) 내역만 조회 */
|
||||
export interface ExceptionProcessingHistoryQueryContext {
|
||||
sewerBzmnCd: string;
|
||||
ctpvNm: string;
|
||||
@@ -92,13 +92,15 @@ function exceptionPrcsYnNmCellStyle({ fieldName, row }: CellStyleCallbackParams)
|
||||
const exceptionHistoryColumnInfo: ColumnInfo = {
|
||||
columns: [
|
||||
{ name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false },
|
||||
{ name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false },
|
||||
{ name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역" }, editable: false },
|
||||
{ name: "vrfcTrgtNm", fieldName: "vrfcTrgtNm", header: { text: "검증대상" }, editable: false },
|
||||
{ name: "rsnExpln", fieldName: "rsnExpln", header: { text: "사유" }, editable: false },
|
||||
{ name: "nowVlCn", fieldName: "nowVlCn", header: { text: "입력값" }, editable: false },
|
||||
{ name: "compVlCn", fieldName: "compVlCn", header: { text: "기준값" }, editable: false },
|
||||
{ name: "prcsYnNm", fieldName: "prcsYnNm", header: { text: "처리여부" }, editable: false },
|
||||
{ name: "pbcpAprvYn", fieldName: "pbcpAprvYn", header: { text: "공단승인여부" }, editable: false },
|
||||
{ name: "stVrfRjtComNm", fieldName: "stVrfRjtComNm", header: { text: "반려상태" }, editable: false },
|
||||
{ name: "prcsOpnnExpln", fieldName: "prcsOpnnExpln", header: { text: "처리의견" }, editable: false },
|
||||
{ name: "rjctOpnnCn", fieldName: "rjctOpnnCn", header: { text: "반려의견" }, editable: false },
|
||||
{ name: "regDt", fieldName: "regDt", header: { text: "등록일시" }, editable: false },
|
||||
{ name: "mdfcnDt", fieldName: "mdfcnDt", header: { text: "갱신일시" }, editable: false },
|
||||
{
|
||||
@@ -114,13 +116,15 @@ const exceptionHistoryColumnInfo: ColumnInfo = {
|
||||
],
|
||||
columnLayout: [
|
||||
"ctpvNm",
|
||||
"sggNm",
|
||||
"admdstNm",
|
||||
"vrfcTrgtNm",
|
||||
"rsnExpln",
|
||||
"nowVlCn",
|
||||
"compVlCn",
|
||||
"prcsYnNm",
|
||||
"pbcpAprvYn",
|
||||
"stVrfRjtComNm",
|
||||
"prcsOpnnExpln",
|
||||
"rjctOpnnCn",
|
||||
"regDt",
|
||||
"mdfcnDt",
|
||||
"individualReject",
|
||||
@@ -190,9 +194,9 @@ export function ExceptionProcessingHistoryDialog({
|
||||
sggNm: queryContext.sggNm,
|
||||
statsYr: queryContext.statsYr,
|
||||
statsCd: queryContext.statsCd,
|
||||
pbcpAprvYn: "N",
|
||||
vrfcMthdCd,
|
||||
prcsYnList: PRCS_YN_LIST,
|
||||
rejectCodeList: "0,1,2",
|
||||
page: pageIndex + 1,
|
||||
size: 30,
|
||||
};
|
||||
@@ -308,14 +312,16 @@ export function ExceptionProcessingHistoryDialog({
|
||||
const mapRows = (entries: VerificationResultReportItem[]): ExceptionHistoryGridRow[] =>
|
||||
entries.map((item) => ({
|
||||
ctpvNm: item.ctpvNm,
|
||||
sggNm: item.sggNm,
|
||||
admdstNm: item.admdstNm ?? item.sggNm ?? "-",
|
||||
vrfcTrgtNm: item.vrfcTrgtNm,
|
||||
rsnExpln: item.rsnExpln,
|
||||
nowVlCn: item.nowVlCn ?? "-",
|
||||
compVlCn: item.compVlCn ?? "-",
|
||||
prcsYnNm: item.prcsYnNm ?? "-",
|
||||
stVrfRjtComNm: item.stVrfRjtComNm ?? "-",
|
||||
prcsOpnnExpln: item.prcsOpnnExpln ?? "-",
|
||||
rjctOpnnCn: item.rjctOpnnCn ?? "-",
|
||||
prcsYn: item.prcsYn ?? "",
|
||||
pbcpAprvYn: item.pbcpAprvYn,
|
||||
regDt: (item.regDt ?? "").slice(0, 16),
|
||||
mdfcnDt: (item.mdfcnDt ?? "").slice(0, 16),
|
||||
individualReject: "개별 반려",
|
||||
|
||||
@@ -41,7 +41,7 @@ const getSggListFetcher = async (
|
||||
key: [string, string, string, string],
|
||||
): Promise<ApiResponse<Sgg[]>> => {
|
||||
const gugunSkipYn = doList.includes(key[3]) ? "N" : "Y";
|
||||
return statisticsApi.getSggAllList(key[1], {
|
||||
return statisticsApi.getSggList(key[1], {
|
||||
instSeCd: key[2],
|
||||
gugunSkipYn,
|
||||
});
|
||||
|
||||
@@ -92,13 +92,12 @@ const verificationSubmitResultColumnInfo: ColumnInfo = {
|
||||
{ name: "vrfcMthdNm", fieldName: "vrfcMthdNm", header: { text: "구분" }, editable: false },
|
||||
{ name: "vrfcMthdCd", fieldName: "vrfcMthdCd", header: { text: "검증유형코드" }, editable: false, visible: false },
|
||||
{ name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false },
|
||||
{ name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false },
|
||||
{ name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역" }, editable: false },
|
||||
{ name: "vrfcTrgtNm", fieldName: "vrfcTrgtNm", header: { text: "검증대상" }, editable: false },
|
||||
{ name: "rsnExpln", fieldName: "rsnExpln", header: { text: "사유" }, editable: false },
|
||||
{ name: "nowVlCn", fieldName: "nowVlCn", header: { text: "입력값" }, editable: false },
|
||||
{ name: "compVlCn", fieldName: "compVlCn", header: { text: "기준값" }, editable: false },
|
||||
{ name: "prcsYn", fieldName: "prcsYn", header: { text: "처리여부" }, editable: false },
|
||||
{ name: "pbcpAprvYn", fieldName: "pbcpAprvYn", header: { text: "공단승인여부" }, editable: false },
|
||||
{ name: "regDt", fieldName: "regDt", header: { text: "등록일시" }, editable: false },
|
||||
{ name: "mdfcnDt", fieldName: "mdfcnDt", header: { text: "갱신일시" }, editable: false },
|
||||
{
|
||||
@@ -111,13 +110,12 @@ const verificationSubmitResultColumnInfo: ColumnInfo = {
|
||||
columnLayout: [
|
||||
"vrfcMthdNm",
|
||||
"ctpvNm",
|
||||
"sggNm",
|
||||
"admdstNm",
|
||||
"vrfcTrgtNm",
|
||||
"rsnExpln",
|
||||
"nowVlCn",
|
||||
"compVlCn",
|
||||
"prcsYn",
|
||||
"pbcpAprvYn",
|
||||
"regDt",
|
||||
"mdfcnDt",
|
||||
"prcsOpnnExpln",
|
||||
@@ -202,13 +200,12 @@ export function VerificationResultDialog({
|
||||
vrfcMthdCd,
|
||||
vrfcMthdNm: VRFC_MTHD_NAME_MAP[vrfcMthdCd] ?? item.vrfcMthdNm,
|
||||
ctpvNm: item.ctpvNm,
|
||||
sggNm: item.sggNm,
|
||||
admdstNm: item.admdstNm ?? item.sggNm ?? "-",
|
||||
vrfcTrgtNm: item.vrfcTrgtNm,
|
||||
rsnExpln: item.rsnExpln,
|
||||
nowVlCn: item.nowVlCn ?? "-",
|
||||
compVlCn: item.compVlCn ?? "-",
|
||||
prcsYn: PRCS_YN_LABEL[item.prcsYn] ?? item.prcsYn,
|
||||
pbcpAprvYn: item.pbcpAprvYn,
|
||||
prcsYn: item.prcsYnNm ?? PRCS_YN_LABEL[item.prcsYn] ?? item.prcsYn,
|
||||
regDt: (item.regDt ?? "").slice(0, 16),
|
||||
mdfcnDt: (item.mdfcnDt ?? "").slice(0, 16),
|
||||
prcsOpnnExpln: item.prcsOpnnExpln ?? "",
|
||||
@@ -226,9 +223,9 @@ export function VerificationResultDialog({
|
||||
sggNm: stableQueryContext.sggNm,
|
||||
statsYr: stableQueryContext.statsYr,
|
||||
statsCd: stableQueryContext.statsCd,
|
||||
pbcpAprvYn: "N",
|
||||
vrfcMthdCd,
|
||||
prcsYnList: "0",
|
||||
rejectCodeList: "0,1,2",
|
||||
page: page + 1,
|
||||
size: 10000,
|
||||
};
|
||||
|
||||
@@ -137,12 +137,15 @@ function verificationPrcsYnNmCellStyle({ fieldName, row }: CellStyleCallbackPara
|
||||
const verificationResultColumnInfo: ColumnInfo = {
|
||||
columns: [
|
||||
{ name: "ctpvNm", fieldName: "ctpvNm", header: { text: "시도" }, editable: false },
|
||||
{ name: "sggNm", fieldName: "sggNm", header: { text: "시군구" }, editable: false },
|
||||
{ name: "admdstNm", fieldName: "admdstNm", header: { text: "행정구역" }, editable: false },
|
||||
{ name: "vrfcTrgtNm", fieldName: "vrfcTrgtNm", header: { text: "검증대상" }, editable: false },
|
||||
{ name: "rsnExpln", fieldName: "rsnExpln", header: { text: "사유" }, editable: false },
|
||||
{ name: "nowVlCn", fieldName: "nowVlCn", header: { text: "입력값" }, editable: false },
|
||||
{ name: "compVlCn", fieldName: "compVlCn", header: { text: "기준값" }, editable: false },
|
||||
{ name: "prcsYnNm", fieldName: "prcsYnNm", header: { text: "처리여부" }, editable: false },
|
||||
{ name: "stVrfRjtComNm", fieldName: "stVrfRjtComNm", header: { text: "반려상태" }, editable: false },
|
||||
{ name: "prcsOpnnExpln", fieldName: "prcsOpnnExpln", header: { text: "처리의견" }, editable: false },
|
||||
{ name: "rjctOpnnCn", fieldName: "rjctOpnnCn", header: { text: "반려의견" }, editable: false },
|
||||
{ name: "regDt", fieldName: "regDt", header: { text: "등록일시" }, editable: false },
|
||||
{ name: "mdfcnDt", fieldName: "mdfcnDt", header: { text: "갱신일시" }, editable: false },
|
||||
{ name: "prcsYn", fieldName: "prcsYn", header: { text: "검증결과상태코드" }, editable: false, visible: false },
|
||||
@@ -150,12 +153,15 @@ const verificationResultColumnInfo: ColumnInfo = {
|
||||
],
|
||||
columnLayout: [
|
||||
"ctpvNm",
|
||||
"sggNm",
|
||||
"admdstNm",
|
||||
"vrfcTrgtNm",
|
||||
"rsnExpln",
|
||||
"nowVlCn",
|
||||
"compVlCn",
|
||||
"prcsYnNm",
|
||||
"stVrfRjtComNm",
|
||||
"prcsOpnnExpln",
|
||||
"rjctOpnnCn",
|
||||
"regDt",
|
||||
"mdfcnDt",
|
||||
"prcsYn",
|
||||
@@ -245,9 +251,9 @@ export function VerificationResultHistoryDialog({
|
||||
sggNm: stableQueryContext.sggNm,
|
||||
statsYr: stableQueryContext.statsYr,
|
||||
statsCd: stableQueryContext.statsCd,
|
||||
pbcpAprvYn: "N",
|
||||
vrfcMthdCd,
|
||||
prcsYnList: "0,2,3",
|
||||
prcsYnList: "0,2",
|
||||
rejectCodeList: "0,1,2",
|
||||
page: pageIndex + 1,
|
||||
size: PAGE_SIZE,
|
||||
};
|
||||
@@ -376,14 +382,16 @@ export function VerificationResultHistoryDialog({
|
||||
vrfcSn: item.vrfcSn,
|
||||
__checked: isChecked ? 1 : 0,
|
||||
ctpvNm: item.ctpvNm,
|
||||
sggNm: item.sggNm,
|
||||
admdstNm: item.admdstNm ?? item.sggNm ?? "-",
|
||||
vrfcTrgtNm: item.vrfcTrgtNm,
|
||||
rsnExpln: item.rsnExpln,
|
||||
nowVlCn: item.nowVlCn ?? "-",
|
||||
compVlCn: item.compVlCn ?? "-",
|
||||
prcsYnNm: item.prcsYnNm ?? "-",
|
||||
stVrfRjtComNm: item.stVrfRjtComNm ?? "-",
|
||||
prcsOpnnExpln: item.prcsOpnnExpln ?? "-",
|
||||
rjctOpnnCn: item.rjctOpnnCn ?? "-",
|
||||
prcsYn: item.prcsYn ?? "",
|
||||
pbcpAprvYn: item.pbcpAprvYn,
|
||||
regDt: (item.regDt ?? "").slice(0, 16),
|
||||
mdfcnDt: (item.mdfcnDt ?? "").slice(0, 16),
|
||||
};
|
||||
|
||||
@@ -34,8 +34,8 @@ export async function hasAnyPostSubmitVerificationResult(
|
||||
sggNm: ctx.sggNm,
|
||||
statsYr: ctx.statsYr,
|
||||
statsCd: ctx.statsCd,
|
||||
pbcpAprvYn: "N" as const,
|
||||
prcsYnList: "0",
|
||||
rejectCodeList: "0,1,2",
|
||||
page: 1,
|
||||
size: 1,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user