diff --git a/apps/st/src/components/statistics/verification/generalVerification/DetailComponent.tsx b/apps/st/src/components/statistics/verification/generalVerification/DetailComponent.tsx index f976488f0..0f9da9e01 100644 --- a/apps/st/src/components/statistics/verification/generalVerification/DetailComponent.tsx +++ b/apps/st/src/components/statistics/verification/generalVerification/DetailComponent.tsx @@ -69,11 +69,28 @@ const DetailComponent = ({ selectedVrfcRow }: DetailComponentProps) => { cmprOpert: row?.cmprOpert ?? null, })); - if (rows.length < 2) { - alert('수식 항목은 최소 2개 이상 등록해야 합니다.'); + const UNARY_TERMINAL_OPERATORS = new Set(['is_null', '!is_null', 'floor']); + const lastOperator = rows.at(-1)?.cmprOpert ?? null; + const lastIsUnary = rows.length > 0 && lastOperator != null && UNARY_TERMINAL_OPERATORS.has(lastOperator); + const isSingleUnaryFormula = rows.length === 1 && lastIsUnary; + + // 단항 연산자일 때만 row 1개 허용 + if (rows.length === 1 && !isSingleUnaryFormula) { + alert('해당 연산자는 최소 2개 항목이 필요합니다.'); return; } + // 단항 연산자(is_null, !is_null, floor)는 반드시 맨 마지막 항목에만 허용 + if (rows.length > 1) { + const unaryAtWrongIdx = rows.findIndex( + (r, idx) => idx < rows.length - 1 && r.cmprOpert != null && UNARY_TERMINAL_OPERATORS.has(r.cmprOpert), + ); + if (unaryAtWrongIdx !== -1) { + alert(`단항 연산자(is_null, !is_null, floor)는 맨 마지막 항목에만 사용할 수 있습니다.\n(순번: ${unaryAtWrongIdx + 1})`); + return; + } + } + const invalidIdx = rows.findIndex( (r) => r.kornArtopnEqtnCn.trim().length === 0 || r.engArtopnEqtnCn.trim().length === 0, ); @@ -82,8 +99,8 @@ const DetailComponent = ({ selectedVrfcRow }: DetailComponentProps) => { return; } - // 마지막을 제외한 항목들은 연산자(cmprOpert)가 반드시 있어야 함 - if (rows.length > 1) { + // 마지막이 단항 연산자가 아닐 때만: 마지막을 제외한 항목들은 연산자(cmprOpert) 필수 + if (rows.length > 1 && !lastIsUnary) { const invalidOpertIdx = rows.slice(0, -1).findIndex((r) => r.cmprOpert == null); if (invalidOpertIdx !== -1) { alert(`연산자가 선택되지 않은 항목이 있습니다.\n(순번: ${invalidOpertIdx + 1})`); @@ -91,8 +108,23 @@ const DetailComponent = ({ selectedVrfcRow }: DetailComponentProps) => { } } - // 마지막 항목의 연산자는 무조건 null 처리 - if (rows.length > 0) { + // 여러 항목일 때 마지막이 단항 연산자면: 이전 항목들 연산자는 무조건 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, + ); + return next; + }); + } + + // 마지막 항목의 연산자는 (단항 연산자 케이스 제외) 무조건 null 처리 + if (rows.length > 1 && !lastIsUnary) { const lastRow = rows[rows.length - 1]; if (lastRow) lastRow.cmprOpert = null; setFormulaList((prev) => {