From 46fcc6470862abb8be1643a3f578455185af4a86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Wed, 18 Mar 2026 22:54:29 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[receiving]=20=EC=88=98=EC=9E=85?= =?UTF-8?q?=EA=B2=80=EC=82=AC=20=EB=AA=A8=EB=8B=AC=EC=97=90=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=9E=85=EB=A0=A5/=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=ED=86=A0=EA=B8=80=20=EB=B2=84=ED=8A=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테스트입력: 전체 항목에 합격값 자동 채움 (tolerance/criteria 기반) - 초기화: 입력값 전체 리셋 - 수입검사 타이틀 옆 눈에 띄는 색상 버튼 --- .../ImportInspectionInputModal.tsx | 93 ++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx b/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx index 63d0e7d2..470b893d 100644 --- a/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx +++ b/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx @@ -233,6 +233,9 @@ export function ImportInspectionInputModal({ const [overallResult, setOverallResult] = useState<'pass' | 'fail' | null>(null); const [remark, setRemark] = useState(''); + // Test fill toggle + const [isTestFilled, setIsTestFilled] = useState(false); + // Photos const [newPhotos, setNewPhotos] = useState([]); const [existingPhotos, setExistingPhotos] = useState([]); @@ -453,6 +456,78 @@ export function ImportInspectionInputModal({ setCurrentTab(0); }, []); + // ===== 테스트 데이터 채우기 (전체 합격값) ===== + const generatePassingValue = useCallback( + (item: InspectionItem): string => { + const raw = rawDataMap.get(item.id); + const base = baseValueMap.get(item.id); + + // 1. 기준값이 있으면 그대로 사용 (공차 범위 중앙) + if (base != null) return String(base); + + // 2. Tolerance 기반 + if (raw?.tolerance) { + switch (raw.tolerance.type) { + case 'range': { + const min = parseFloat(String(raw.tolerance.min || 0)); + const max = parseFloat(String(raw.tolerance.max || 0)); + return String(Math.round(((min + max) / 2) * 100) / 100); + } + case 'limit': { + const lv = parseFloat(String(raw.tolerance.value || 0)); + if (raw.tolerance.op === 'gte') return String(lv); + if (raw.tolerance.op === 'gt') return String(Math.round((lv + 1) * 100) / 100); + if (raw.tolerance.op === 'lte') return String(lv); + if (raw.tolerance.op === 'lt') return String(Math.round((lv - 1) * 100) / 100); + break; + } + } + } + + // 3. Criteria 기반 + if (raw?.criteria) { + const { min, max } = raw.criteria; + if (min != null && max != null) return String(Math.round(((min + max) / 2) * 100) / 100); + if (min != null) return String(min); + if (max != null) return String(max); + } + + return '100'; + }, + [rawDataMap, baseValueMap] + ); + + const fillTestData = useCallback(() => { + if (!template) return; + const targetItems = template.inspectionItems.filter(i => i.isFirstInItem !== false); + const newMeas: Record> = {}; + const newOkng: Record> = {}; + + for (const item of targetItems) { + for (let n = 0; n < item.measurementCount; n++) { + if (item.measurementType === 'okng') { + if (!newOkng[item.id]) newOkng[item.id] = {}; + newOkng[item.id][n] = 'ok'; + } else if (item.measurementType === 'substitute') { + if (!newMeas[item.id]) newMeas[item.id] = {}; + newMeas[item.id][n] = '정상'; + } else { + if (!newMeas[item.id]) newMeas[item.id] = {}; + newMeas[item.id][n] = generatePassingValue(item); + } + } + } + + setMeasurements(newMeas); + setOkngValues(newOkng); + setIsTestFilled(true); + }, [template, generatePassingValue]); + + const clearTestData = useCallback(() => { + resetForm(); + setIsTestFilled(false); + }, [resetForm]); + // ===== 단일 측정값의 자동 판정 ===== const getMeasurementResult = useCallback( (itemId: string, nIndex: number): 'ok' | 'ng' | null => { @@ -760,7 +835,23 @@ export function ImportInspectionInputModal({ - 수입검사 +
+ 수입검사 + {template && ( + + )} +
수입검사 항목 입력