diff --git a/frontend/components/pop/hardcoded/production/WorkOrderList.tsx b/frontend/components/pop/hardcoded/production/WorkOrderList.tsx index 781e2adf..3a0e3d7a 100644 --- a/frontend/components/pop/hardcoded/production/WorkOrderList.tsx +++ b/frontend/components/pop/hardcoded/production/WorkOrderList.tsx @@ -916,7 +916,9 @@ export function WorkOrderList() { const filteredProcesses = useMemo(() => { if (selectedProcess === "__all__") return []; // 공정 미선택 시 빈 목록 return masterProcesses.filter((proc) => { - if (proc.process_code !== selectedProcess) return false; + const isRework = proc.is_rework === "Y" || proc.is_rework === "true" || proc.is_rework === "1"; + // 재작업 카드는 공정 필터 무시 (모든 공정에서 표시) + if (!isRework && proc.process_code !== selectedProcess) return false; if (selectedEquipment !== "__all__") { const wi = instructionMap[proc.wo_id]; if (!wi) return false; @@ -932,7 +934,9 @@ export function WorkOrderList() { /* ---- Tab counts ---- */ const tabCounts = useMemo(() => { const preFiltered = masterProcesses.filter((proc) => { - if (selectedProcess !== "__all__" && proc.process_code !== selectedProcess) return false; + const isRework = proc.is_rework === "Y" || proc.is_rework === "true" || proc.is_rework === "1"; + // 재작업 카드는 공정 필터 무시 (모든 공정에서 표시) + if (selectedProcess !== "__all__" && !isRework && proc.process_code !== selectedProcess) return false; if (selectedEquipment !== "__all__") { const wi = instructionMap[proc.wo_id]; if (!wi) return false; @@ -1043,6 +1047,35 @@ export function WorkOrderList() { }); }; + /* ---- Helper: get split order label (접수 #N) ---- */ + const splitOrderMap = useMemo(() => { + // 같은 wo_id + seq_no를 가진 SPLIT들을 그룹화하여 순서 부여 + const groups: Record = {}; + for (const proc of allProcesses) { + if (!proc.parent_process_id) continue; // 마스터 행은 제외 + if (proc.status !== "in_progress" && proc.status !== "completed") continue; + const key = `${proc.wo_id}__${proc.seq_no}`; + if (!groups[key]) groups[key] = []; + groups[key].push(proc); + } + + const result: Record = {}; + for (const key of Object.keys(groups)) { + const splits = groups[key]; + if (splits.length <= 1) continue; // 1개면 순서 표시 불필요 + // accepted_at 기준 정렬 (없으면 started_at, 그마저 없으면 id) + splits.sort((a, b) => { + const ta = a.accepted_at ? new Date(a.accepted_at).getTime() : (a.started_at ? new Date(a.started_at).getTime() : 0); + const tb = b.accepted_at ? new Date(b.accepted_at).getTime() : (b.started_at ? new Date(b.started_at).getTime() : 0); + return ta - tb || a.id.localeCompare(b.id); + }); + for (let i = 0; i < splits.length; i++) { + result[splits[i].id] = { order: i + 1, total: splits.length }; + } + } + return result; + }, [allProcesses]); + /* ---- Helper: get previous process info ---- */ const getPrevProcessInfo = (proc: WorkOrderProcess) => { const siblings = (processesByWo[proc.wo_id] || []) @@ -1244,6 +1277,9 @@ export function WorkOrderList() { // Additional available for in_progress const additionalAvailable = Math.max(0, planQty - inputQty); + // Split order label + const splitInfo = splitOrderMap[proc.id]; + // Rework info: origin process + rework round let reworkRound = 1; let originProcessName = proc.process_name || proc.process_code; @@ -1298,6 +1334,11 @@ export function WorkOrderList() { )}

{wi?.work_instruction_no || "작업지시"} + {splitInfo && ( + + (접수 #{splitInfo.order}) + + )}

diff --git a/frontend/public/pop-settings-preview.html b/frontend/public/pop-settings-preview.html new file mode 100644 index 00000000..633b6923 --- /dev/null +++ b/frontend/public/pop-settings-preview.html @@ -0,0 +1,1339 @@ + + + + + +POP 화면 설정 관리 v2 + + + + +
+ +
+
+ +
+
+
+ + VEXPLOR +
+
+ topseal_admin + +
+
+
+ +
+ +
+ + + + + +
+
+
📋 최근 활동
+
+
+
+
+ 구매입고 #2024-0127 완료 +
+ 10분 전 +
+
+
+
+ SMT 공정 작업 시작 +
+ 25분 전 +
+
+
+
+ 판매출고 #2024-0089 대기중 +
+ 1시간 전 +
+
+
+
+
+
+ + + + + + + + + + + + +
+
+ + +
+
+

화면 설정

+
홈 화면
+
+
+
+
⚙️
+
설정할 영역을 클릭하세요
+
왼쪽 POP 화면에서 설정 가능한 영역에
마우스를 올리면 파란 테두리가 표시됩니다
+
+ +
+ +
+
+ + + + \ No newline at end of file