# 중간검사 성적서 시스템 구현 계획

> **작성일**: 2026-02-07
> **목적**: 작업자 화면에서 개소별 중간검사 데이터를 저장하고, 검사성적서보기 시 문서 템플릿 기반 성적서로 합쳐서 표시하는 시스템 구축
> **기준 문서**: `docs/dev_plans/document-management-system-plan.md`, `docs/specs/database-schema.md`
> **상태**: 📋 계획 수립 완료 → 사용자 검토 대기

---

## 🚀 새 세션 시작 가이드

> **이 섹션은 새 세션에서 이 문서만 보고 작업을 시작할 수 있도록 작성되었습니다.**

### 프로젝트 정보

| 항목 | 내용 |
|------|------|
| **작업 프로젝트** | `react` (프론트엔드) + `api` (백엔드) |
| **react 절대 경로** | `/Users/kent/Works/@KD_SAM/SAM/react/` |
| **api 절대 경로** | `/Users/kent/Works/@KD_SAM/SAM/api/` |
| **mng 절대 경로** | `/Users/kent/Works/@KD_SAM/SAM/mng/` (양식 관리 참조) |
| **기술 스택** | Next.js 15 (react) / Laravel 12 (api) |
| **로컬 URL** | `https://dev.sam.kr/production/worker-screen` |
| **관련 계획서** | `docs/dev_plans/document-management-system-plan.md` (문서관리 시스템 80% 완료) |

### Git 저장소

```bash
# react (프론트엔드) - 독립 Git 저장소
cd /Users/kent/Works/@KD_SAM/SAM/react
git status && git branch

# api (백엔드) - 독립 Git 저장소
cd /Users/kent/Works/@KD_SAM/SAM/api
git status && git branch
```

> **주의**: SAM/ 루트는 Git 저장소가 아님. api/, mng/, react/ 각각 독립 Git 저장소.

### 세션 시작 체크리스트

```
1. 이 문서를 읽는다 (📍 현재 진행 상태 섹션 확인)
2. react/CLAUDE.md 를 읽는다 (프론트엔드 프로젝트 규칙)
3. 마지막 완료 작업 확인 → 다음 작업 결정
4. 해당 Phase의 상세 절차(섹션 5)를 읽는다
5. 작업 시작 전 사용자에게 "Phase X.X 시작할까요?" 확인
```

### 핵심 파일 (작업 빈도순)

**Frontend (react)**

| 파일 | 설명 |
|------|------|
| `react/src/components/production/WorkerScreen/index.tsx` | 작업자 화면 메인 (중간검사 버튼 핸들러) |
| `react/src/components/production/WorkerScreen/InspectionInputModal.tsx` | 중간검사 입력 모달 (개소별 데이터 입력) |
| `react/src/components/production/WorkerScreen/types.ts` | InspectionData, WorkItemData, InspectionDataMap 타입 |
| `react/src/components/production/WorkerScreen/actions.ts` | 작업자 화면 서버 액션 |
| `react/src/components/production/WorkOrders/documents/InspectionReportModal.tsx` | 중간검사 성적서 모달 (문서 래퍼) |
| `react/src/components/production/WorkOrders/documents/ScreenInspectionContent.tsx` | 스크린 검사 성적서 콘텐츠 |
| `react/src/components/production/WorkOrders/documents/SlatInspectionContent.tsx` | 슬랫 검사 성적서 콘텐츠 |
| `react/src/components/production/WorkOrders/documents/BendingInspectionContent.tsx` | 절곡 검사 성적서 콘텐츠 |
| `react/src/components/production/WorkOrders/actions.ts` | saveInspectionData 서버 액션 (628-668줄) |
| `react/src/components/document-system/configs/qms/index.ts` | QMS 문서 Config 6종 |

**Backend (api)**

| 파일 | 설명 |
|------|------|
| `api/app/Http/Controllers/Api/V1/InspectionController.php` | 검사 CRUD API (89줄) |
| `api/app/Services/InspectionService.php` | 검사 비즈니스 로직 (402줄) |
| `api/routes/api/v1/production.php` | 생산 관련 라우트 |

**MNG (양식 관리)**

| 파일 | 설명 |
|------|------|
| `mng/app/Models/DocumentTemplate.php` | 양식 템플릿 모델 |
| `mng/app/Models/Documents/Document.php` | 문서 인스턴스 모델 |
| `mng/resources/views/document-templates/edit.blade.php` | 양식 편집 UI |

### 현재 코드 구조 (핵심 타입/인터페이스)

**InspectionData (프론트 - 검사 입력 데이터)**

```typescript
// react/src/components/production/WorkerScreen/InspectionInputModal.tsx:35-56
export type InspectionProcessType = 'screen' | 'slat' | 'slat_jointbar' | 'bending' | 'bending_wip';

export interface InspectionData {
  productName: string;
  specification: string;
  bendingStatus?: 'good' | 'bad' | null;      // 절곡상태
  processingStatus?: 'good' | 'bad' | null;   // 가공상태
  sewingStatus?: 'good' | 'bad' | null;       // 재봉상태
  assemblyStatus?: 'good' | 'bad' | null;     // 조립상태
  length?: number | null;
  width?: number | null;
  height1?: number | null;
  height2?: number | null;
  length3?: number | null;
  gap4?: number | null;
  gapStatus?: 'ok' | 'ng' | null;
  gapPoints?: { left: number | null; right: number | null }[];
  judgment: 'pass' | 'fail' | null;
  nonConformingContent: string;
}
```

**InspectionDataMap (프론트 - 아이템별 검사 데이터 맵)**

```typescript
// react/src/components/production/WorkOrders/documents/InspectionReportModal.tsx:37
export type InspectionDataMap = Map<string, InspectionData>;
// key: workItem.id (또는 selectedOrder.id), value: InspectionData
```

**WorkItemData (프론트 - 작업 아이템)**

```typescript
// react/src/components/production/WorkerScreen/types.ts:32-58
export interface WorkItemData {
  id: string;
  itemNo: number;
  itemCode: string;
  itemName: string;
  floor: string;
  code: string;
  width: number;
  height: number;
  quantity: number;
  processType: ProcessTab;  // 'screen' | 'slat' | 'bending'
  steps: WorkStepData[];
  isWip?: boolean;
  isJointBar?: boolean;
  cuttingInfo?: CuttingInfo;        // 스크린 전용
  slatInfo?: SlatInfo;              // 슬랫 전용
  slatJointBarInfo?: SlatJointBarInfo;  // 조인트바 전용
  bendingInfo?: BendingInfo;        // 절곡 전용
  wipInfo?: WipInfo;                // 재공품 전용
  materialInputs?: MaterialListItem[];
}
```

**WorkOrderItem 모델 (백엔드)**

```php
// api/app/Models/Production/WorkOrderItem.php
class WorkOrderItem extends Model {
    use Auditable, BelongsToTenant;

    protected $fillable = [
        'tenant_id', 'work_order_id', 'source_order_item_id',
        'item_id', 'item_name', 'specification',
        'quantity', 'unit', 'sort_order', 'status', 'options',
    ];

    protected $casts = ['options' => 'array'];  // ← JSON 컬럼, inspection_data 저장 대상

    // options['result'] 패턴이 이미 존재 (작업 완료 결과 저장)
    // 동일 패턴으로 options['inspection_data'] 추가 예정
    public function getResult(): ?array { return $this->options['result'] ?? null; }
    public function setResult(array $result): void {
        $options = $this->options ?? [];
        $options['result'] = array_merge($options['result'] ?? [], $result);
        $this->options = $options;
    }
}
```

**InspectionReportModal - 공정별 라우팅 로직**

```typescript
// react/src/components/production/WorkOrders/documents/InspectionReportModal.tsx:185-201
switch (processType) {
  case 'screen':
    return <ScreenInspectionContent {...commonProps} />;
  case 'slat':
    if (isJointBar || order.items?.some(item => item.productName?.includes('조인트바'))) {
      return <SlatJointBarInspectionContent {...commonProps} />;
    }
    return <SlatInspectionContent {...commonProps} />;
  case 'bending':
    return <BendingInspectionContent {...commonProps} />;
  case 'bending_wip':
    return <BendingWipInspectionContent {...commonProps} />;
}
```

**WorkerScreen - 검사 핸들러 (핵심 흐름)**

```typescript
// react/src/components/production/WorkerScreen/index.tsx
// 1) 중간검사 입력: handleInspectionClick (802줄) → InspectionInputModal 오픈
// 2) 검사 완료: handleInspectionComplete (862줄) → inspectionDataMap에 저장 (메모리만!)
// 3) 성적서 보기: handleInspection (851줄) → InspectionReportModal 오픈
//    - workItems + inspectionDataMap을 props로 전달

const [inspectionDataMap, setInspectionDataMap] = useState<Map<string, InspectionData>>(new Map());

const handleInspectionComplete = useCallback((data: InspectionData) => {
  if (selectedOrder) {
    setInspectionDataMap((prev) => {
      const next = new Map(prev);
      next.set(selectedOrder.id, data);  // ← 현재: 메모리에만 저장, API 호출 없음!
      return next;
    });
  }
}, [selectedOrder]);
```

**기존 saveInspectionData 서버 액션 (미완성)**

```typescript
// react/src/components/production/WorkOrders/actions.ts:628-668
export async function saveInspectionData(
  workOrderId: string, processType: string, data: unknown
): Promise<{ success: boolean; error?: string }> {
  // POST /api/v1/work-orders/{workOrderId}/inspection
  // ⚠️ 문제: 백엔드에 이 엔드포인트가 존재하지 않음!
  // production.php 라우트에 /work-orders/{id}/inspection 없음
}
```

### 백엔드 라우트 구조 (현재)

```php
// api/routes/api/v1/production.php (43-74줄)
Route::prefix('work-orders')->group(function () {
    // 기본 CRUD: index, stats, store, show, update, destroy
    // 상태 관리: updateStatus, assign, toggleBendingField
    // 이슈: addIssue, resolveIssue
    // 품목: updateItemStatus
    // 자재: materials, registerMaterialInput, materialInputHistory
    // 단계 진행: stepProgress, toggleStepProgress
    // ⚠️ 검사(inspection) 관련 라우트 없음 → Phase 1에서 추가 필요
});

// 별도 검사 API (InspectionController) - 범용 검사, 작업지시와 직접 연결 아님
Route::prefix('inspections')->group(function () {
    Route::get('', [InspectionController::class, 'index']);     // 목록
    Route::post('', [InspectionController::class, 'store']);    // 생성
    Route::get('/{id}', [InspectionController::class, 'show']); // 상세
    // ...
});
```

### 백엔드 컨트롤러/서비스 구조 (현재)

```php
// WorkOrderController: 18개 메서드 (inspection 관련 없음)
// WorkOrderService: 16개 메서드 (1493줄, inspection 관련 없음)
// → Phase 1에서 3개 메서드 추가 필요:
//   storeItemInspection, getInspectionData, getInspectionReport
```

### 문서 템플릿 DB 구조 (이미 존재)

```
document_templates                    # 양식 마스터
├── document_template_approval_lines  # 결재라인 (작성/검토/승인)
├── document_template_basic_fields    # 기본필드 (품명, LOT NO 등)
├── document_template_sections        # 섹션 (검사기준서 섹션)
│   └── document_template_section_items # 섹션 항목 (검사항목)
└── document_template_columns         # 데이터 테이블 컬럼

documents                             # 문서 인스턴스
├── document_approvals                # 결재 이력
├── document_data                     # 필드 데이터 (EAV, field_key/field_value)
└── document_attachments              # 첨부 파일
```

---

## 📍 현재 진행 상태

| 항목 | 내용 |
|------|------|
| **마지막 완료 작업** | 분석 완료 - 중간검사 모달/문서관리 시스템/성적서 컴포넌트 전체 분석 |
| **다음 작업** | Phase 1.1 - 백엔드 API 설계 |
| **진행률** | 0/14 (0%) |
| **마지막 업데이트** | 2026-02-07 |

---

## 1. 개요

### 1.1 배경

현재 중간검사 시스템은 다음 상태입니다:

**개소별 검사 입력 (InspectionInputModal)**
- 스타일 수입검사 모달과 통일 완료 (2026-02-07)
- 공정별 입력 항목: 스크린(6항목), 슬랫(5항목), 조인트바(6항목), 절곡(3항목+간격5포인트), 재공품(3항목+간격)
- 데이터 저장: **프론트 메모리(InspectionDataMap)에만 보관**, 백엔드 저장 미구현

**검사 성적서 보기 (InspectionReportModal)**
- 4종 하드코딩 컴포넌트: Screen/Slat/Bending/BendingWip InspectionContent
- 조인트바 자동 감지 (SlatJointBarInspectionContent)
- 문서 템플릿 시스템 미활용 (레이아웃 코드 내 고정)
- workItems 기반 동적 행 생성 + inspectionDataMap에서 데이터 매핑

**문서관리 시스템 (80% 완료)**
- mng.sam.kr/document-templates에서 양식 CRUD 가능
- API: documents/resolve (카테고리+아이템 기반 조회), documents/upsert (저장)
- EAV 패턴: document_data 테이블 (field_key/field_value)
- 수입검사 성적서는 이미 문서관리 시스템 연동 완료

**문제점**
1. 개소별 검사 데이터가 프론트 메모리에만 존재 → 새로고침 시 소실
2. 성적서 레이아웃이 하드코딩 → 양식 변경 시 코드 수정 필요
3. 검사 이력 관리 불가 → 언제 누가 어떤 데이터를 입력했는지 추적 불가

### 1.2 핵심 원칙

```
┌─────────────────────────────────────────────────────────────────┐
│  🎯 하이브리드 방식                                               │
├─────────────────────────────────────────────────────────────────┤
│  1. 개소별 데이터 → work_order_items.options JSON에 저장          │
│  2. 성적서 레이아웃 → 문서 템플릿 시스템(mng)에서 관리              │
│  3. 성적서 보기 → 템플릿 레이아웃 + 개소 데이터 결합하여 렌더링      │
│  4. 기존 InspectionContent 컴포넌트 → Config 기반으로 점진 전환     │
└─────────────────────────────────────────────────────────────────┘
```

### 1.3 수입검사 성적서와의 비교

| 구분 | 수입검사 성적서 | 중간검사 성적서 (목표) |
|------|----------------|----------------------|
| **데이터 소스** | 1입고 = 1문서 | N개소 = 1문서 (합산) |
| **데이터 수집** | 한 번에 입력 | 개소별로 따로 입력 후 합산 |
| **데이터 저장** | document_data (EAV) | work_order_items.options (JSON) |
| **레이아웃** | 문서 템플릿 시스템 | 문서 템플릿 시스템 (동일) |
| **측정 항목** | 자재별 고정 | 공정별 다름 (스크린/슬랫/절곡/조인트바) |
| **자동 판정** | 있음 (N1~Nn 탭) | 있음 (행별 + 종합) |
| **문서 유형** | 1종 | 5종 (스크린/슬랫/조인트바/절곡/재공품) |

### 1.4 변경 승인 정책

| 분류 | 예시 | 승인 |
|------|------|------|
| ✅ 즉시 가능 | 프론트 컴포넌트 수정, 서버 액션 추가, 타입 정의 | 불필요 |
| ⚠️ 컨펌 필요 | API 엔드포인트 추가, work_order_items.options 구조 변경, 문서 템플릿 등록 | **필수** |
| 🔴 금지 | 테이블 구조 변경, 기존 API 삭제, 수입검사 로직 변경 | 별도 협의 |

### 1.5 준수 규칙

- `docs/quickstart/quick-start.md` - 빠른 시작 가이드
- `docs/standards/quality-checklist.md` - 품질 체크리스트
- `react/CLAUDE.md` - 프론트엔드 프로젝트 규칙
- `docs/dev_plans/document-management-system-plan.md` - 문서관리 시스템 계획서

---

## 2. 현황 분석

### 2.1 현재 동작하는 검사 흐름 (문제점 포함)

```
[현재 흐름 - 데이터가 메모리에만 존재]

1. 작업자 화면 진입 (dev.sam.kr/production/worker-screen)
   ↓
2. 작업지시 선택 → 개소(아이템) 카드 목록 표시
   ↓
3. 개소 카드의 "중간검사" 단계(pill) 클릭
   ↓ handleInspectionClick (index.tsx:802)
4. InspectionInputModal 오픈 (공정별 입력 항목)
   ↓ 작업자가 검사 데이터 입력 후 "검사 완료"
5. handleInspectionComplete (index.tsx:862)
   ↓ inspectionDataMap.set(selectedOrder.id, data)
   ⚠️ 메모리에만 저장! → 새로고침하면 소실
   ↓
6. "검사성적서 보기" 버튼 클릭
   ↓ handleInspection (index.tsx:851)
7. InspectionReportModal 오픈
   - workItems + inspectionDataMap props 전달
   - 공정별 InspectionContent 컴포넌트 렌더링
   ↓
8. DocumentViewer로 문서 형태 표시/인쇄
```

### 2.2 기존 코드에서 활용할 수 있는 패턴

| 패턴 | 위치 | 설명 |
|------|------|------|
| `options['result']` 패턴 | WorkOrderItem.php:119-132 | options JSON에 구조화된 데이터 저장/조회 |
| `saveInspectionData` 서버 액션 | WorkOrders/actions.ts:628-668 | POST 구조 이미 존재 (백엔드 미구현) |
| `InspectionDataMap` | InspectionReportModal.tsx:37 | 아이템ID→검사데이터 Map 구조 |
| `InspectionContentRef.getInspectionData()` | InspectionReportModal.tsx:143 | 성적서에서 데이터 추출 인터페이스 |
| `DocumentViewer` preset="inspection" | InspectionReportModal.tsx:216 | 검사 문서 뷰어 프리셋 |

### 2.3 관련 API 현황

| API | 상태 | 비고 |
|-----|------|------|
| `GET /work-orders` | ✅ 존재 | 목록 조회 |
| `GET /work-orders/{id}` | ✅ 존재 | 상세 (items 포함) |
| `PATCH /work-orders/{id}/items/{itemId}/status` | ✅ 존재 | 품목 상태 변경 |
| `POST /work-orders/{id}/inspection` | ❌ 없음 | saveInspectionData가 호출하려는 URL |
| `POST /work-orders/{id}/items/{itemId}/inspection` | ❌ 없음 | Phase 1.2에서 구현 |
| `GET /work-orders/{id}/inspection-data` | ❌ 없음 | Phase 1.3에서 구현 |
| `GET /work-orders/{id}/inspection-report` | ❌ 없음 | Phase 1.4에서 구현 |
| `GET /documents/resolve` | ✅ 존재 | 문서 템플릿 조회 (Phase 1.4에서 활용) |

---

## 3. 대상 범위

### Phase 의존 관계

```
Phase 1 (백엔드 API)
  ↓ Phase 2가 Phase 1에 의존 (API가 있어야 프론트 연동)
Phase 2 (프론트 저장 연동)
  ↓ Phase 3은 Phase 1-2와 독립 (mng에서 양식 등록)
Phase 3 (mng 템플릿 등록)
  ↓ Phase 4가 Phase 1+3에 의존 (API + 템플릿 모두 필요)
Phase 4 (프론트 성적서 연동)
```

### Phase 1: 백엔드 - 개소별 검사 데이터 저장 API

| # | 작업 항목 | 상태 | 완료 기준 | 비고 |
|---|----------|:----:|----------|------|
| 1.1 | API 엔드포인트 설계 | ⏳ | 엔드포인트 목록 + 요청/응답 스키마 확정 | ⚠️ 컨펌 필요 |
| 1.2 | 개소별 검사 데이터 저장 API 구현 | ⏳ | POST /work-orders/{id}/items/{itemId}/inspection 동작 | work_order_items.options에 inspection_data 필드 추가 |
| 1.3 | 개소별 검사 데이터 조회 API 구현 | ⏳ | GET /work-orders/{id}/inspection-data 동작 | 전체 개소 검사 데이터 한번에 반환 |
| 1.4 | 성적서 문서 데이터 조회 API 구현 | ⏳ | GET /work-orders/{id}/inspection-report 동작 | 템플릿 + 개소 데이터 결합 응답 |

### Phase 2: 프론트 - 개소별 검사 데이터 저장 연동

| # | 작업 항목 | 상태 | 완료 기준 | 비고 |
|---|----------|:----:|----------|------|
| 2.1 | 서버 액션 추가 (저장/조회) | ⏳ | saveItemInspection, getInspectionData 서버 액션 동작 | |
| 2.2 | InspectionInputModal - 저장 연동 | ⏳ | "검사 완료" 클릭 시 API 호출 + 성공/실패 피드백 | |
| 2.3 | WorkerScreen - 저장된 데이터 로드 | ⏳ | 화면 진입 시 기존 검사 데이터 자동 로드 | inspectionDataMap 초기화 |
| 2.4 | InspectionInputModal - 기존 데이터 표시 | ⏳ | 이미 검사한 개소 재클릭 시 저장된 데이터 표시 | |

### Phase 3: 문서 템플릿 등록 (mng)

| # | 작업 항목 | 상태 | 완료 기준 | 비고 |
|---|----------|:----:|----------|------|
| 3.1 | 스크린 중간검사 양식 등록 | ⏳ | mng.sam.kr/document-templates에서 양식 확인 | ⚠️ 컨펌 필요 |
| 3.2 | 슬랫 중간검사 양식 등록 | ⏳ | 위와 동일 | |
| 3.3 | 절곡 중간검사 양식 등록 | ⏳ | 위와 동일 | |
| 3.4 | 조인트바 중간검사 양식 등록 | ⏳ | 위와 동일 | |

### Phase 4: 프론트 - 성적서 보기 템플릿 연동

| # | 작업 항목 | 상태 | 완료 기준 | 비고 |
|---|----------|:----:|----------|------|
| 4.1 | InspectionReportModal - API 연동 | ⏳ | 템플릿 + 검사 데이터 API에서 로드 | |
| 4.2 | InspectionContent 컴포넌트 리팩토링 | ⏳ | Config 기반으로 전환 (기존 하드코딩 제거) | 점진적 전환 |

---

## 4. 아키텍처 설계

### 3.1 데이터 흐름

```
[개소별 중간검사]                             [검사 성적서 보기]

작업자 화면                                  작업자 화면
  ↓ "중간검사" 클릭                           ↓ "검사성적서보기" 클릭
InspectionInputModal                        InspectionReportModal
  ↓ 검사 완료                                 ↓
POST /work-orders/{id}/                     GET /work-orders/{id}/
  items/{itemId}/inspection                   inspection-report
  ↓                                           ↓
work_order_items.options                    {
  .inspection_data = {                        template: { 레이아웃 JSON },
    processingStatus: 'good',                 items: [
    sewingStatus: 'good',                       { itemId, itemName, inspectionData },
    length: 1200,                               { itemId, itemName, inspectionData },
    judgment: 'pass',                           ...
    ...                                       ],
  }                                           summary: { total, pass, fail }
                                            }
                                              ↓
                                            공정별 InspectionContent 렌더링
                                            (템플릿 레이아웃 + 개소 데이터 결합)
```

### 3.2 work_order_items.options JSON 구조 (확장)

```json
{
  "floor": "3F",
  "code": "SC-001",
  "width": 1200,
  "height": 800,
  "cutting_info": { ... },
  "slat_info": { ... },
  "bending_info": { ... },
  "wip_info": { ... },
  "inspection_data": {
    "inspected_at": "2026-02-07T14:30:00Z",
    "inspected_by": "user_id",
    "inspected_by_name": "홍길동",
    "process_type": "screen",
    "data": {
      "processingStatus": "good",
      "sewingStatus": "good",
      "assemblyStatus": "good",
      "length": 1200,
      "width": 800,
      "gapStatus": "ok",
      "gapPoints": [
        { "left": 5.0, "right": 5.0 }
      ]
    },
    "judgment": "pass",
    "non_conforming_content": ""
  }
}
```

### 3.3 API 설계

**1) 개소별 검사 데이터 저장**

```
POST /api/v1/work-orders/{workOrderId}/items/{itemId}/inspection

Request:
{
  "process_type": "screen",
  "inspection_data": {
    "processingStatus": "good",
    "sewingStatus": "good",
    "assemblyStatus": "good",
    "length": 1200,
    "width": 800,
    "gapStatus": "ok",
    "gapPoints": [{ "left": 5.0, "right": 5.0 }]
  },
  "judgment": "pass",
  "non_conforming_content": ""
}

Response:
{
  "success": true,
  "data": {
    "item_id": "item-uuid",
    "inspection_data": { ... },
    "inspected_at": "2026-02-07T14:30:00Z"
  }
}
```

**2) 작업지시 전체 검사 데이터 조회**

```
GET /api/v1/work-orders/{workOrderId}/inspection-data

Response:
{
  "success": true,
  "data": {
    "work_order_id": "wo-uuid",
    "process_type": "screen",
    "items": [
      {
        "item_id": "item-1",
        "item_name": "SC-001-3F",
        "has_inspection": true,
        "inspection_data": { ... },
        "judgment": "pass",
        "inspected_at": "2026-02-07T14:30:00Z",
        "inspected_by_name": "홍길동"
      },
      {
        "item_id": "item-2",
        "item_name": "SC-002-3F",
        "has_inspection": false,
        "inspection_data": null,
        "judgment": null,
        "inspected_at": null,
        "inspected_by_name": null
      }
    ],
    "summary": {
      "total": 6,
      "inspected": 4,
      "pass": 3,
      "fail": 1,
      "pending": 2
    }
  }
}
```

**3) 검사 성적서 데이터 조회 (문서 형태)**

```
GET /api/v1/work-orders/{workOrderId}/inspection-report

Response:
{
  "success": true,
  "data": {
    "work_order_id": "wo-uuid",
    "process_type": "screen",
    "template": {
      "id": "template-uuid",
      "title": "스크린 중간검사 성적서",
      "approval_lines": [...],
      "basic_fields": [...],
      "sections": [...],
      "columns": [...]
    },
    "document_data": {
      "basic_fields": {
        "product_name": "블라인드 A형",
        "specification": "1200x800",
        "lot_no": "LOT-2026-001",
        "inspection_date": "2026-02-07",
        "inspector": "홍길동"
      },
      "inspection_rows": [
        {
          "row_no": 1,
          "item_id": "item-1",
          "item_name": "SC-001-3F",
          "processing_status": "양호",
          "sewing_status": "양호",
          "assembly_status": "양호",
          "length_design": 1200,
          "length_measured": 1200,
          "width_design": 800,
          "width_measured": 800,
          "gap_standard": "5±1",
          "gap_result": "OK",
          "judgment": "적"
        }
      ],
      "summary": {
        "total": 6,
        "pass": 5,
        "fail": 1,
        "overall_judgment": "합격",
        "non_conforming_content": "item-3: 길이 규격 초과"
      }
    },
    "inspection_setting": {
      "schematic_image": "/img/inspection/screen-schematic.png",
      "inspection_standard_image": "/img/inspection/screen-standard.png"
    }
  }
}
```

### 3.4 공정별 검사 항목 매핑

**스크린 (screen)**

| 검사항목 | 입력 타입 | options.inspection_data 키 | 성적서 컬럼 |
|---------|----------|---------------------------|------------|
| 가공상태 결모양 | good/bad | processingStatus | 가공상태 |
| 재봉상태 결모양 | good/bad | sewingStatus | 재봉상태 |
| 조립상태 | good/bad | assemblyStatus | 조립상태 |
| 길이 | number | length | 길이 (도면치수 vs 측정값) |
| 나비 | number | width | 나비 (도면치수 vs 측정값) |
| 간격 | ok/ng | gapStatus | 간격 (기준치 vs OK/NG) |

**슬랫 (slat)**

| 검사항목 | 입력 타입 | options.inspection_data 키 | 성적서 컬럼 |
|---------|----------|---------------------------|------------|
| 가공상태 | good/bad | processingStatus | 가공상태 |
| 조립상태 | good/bad | assemblyStatus | 조립상태 |
| ① 높이 | number | height1 | 높이① (16.5±1) |
| ② 높이 | number | height2 | 높이② (14.5±1) |
| 길이 | number | length | 길이 |

**조인트바 (slat_jointbar)**

| 검사항목 | 입력 타입 | options.inspection_data 키 | 성적서 컬럼 |
|---------|----------|---------------------------|------------|
| 가공상태 | good/bad | processingStatus | 가공상태 |
| 조립상태 | good/bad | assemblyStatus | 조립상태 |
| ① 높이 | number | height1 | 높이① |
| ② 높이 | number | height2 | 높이② |
| ③ 길이 | number | length | 길이 |
| ④ 간격 | number | gapValue | 간격 |

**절곡 (bending)**

| 검사항목 | 입력 타입 | options.inspection_data 키 | 성적서 컬럼 |
|---------|----------|---------------------------|------------|
| 절곡상태 | good/bad | bendingStatus | 절곡상태 |
| 길이 | number | length | 길이 |
| 간격 (5포인트) | number x 10 | gapPoints[].left/right | 간격 좌1~좌5, 우1~우5 |

**재공품 (bending_wip)**

| 검사항목 | 입력 타입 | options.inspection_data 키 | 성적서 컬럼 |
|---------|----------|---------------------------|------------|
| 절곡상태 | good/bad | bendingStatus | 절곡상태 |
| 길이 | number | length | 길이 |
| 나비 | number | width | 나비 |
| 간격 | ok/ng | gapStatus | 간격 |

---

## 5. 기술 결정사항

### 4.1 확정 결정

| # | 결정 사항 | 선택 | 근거 |
|---|----------|------|------|
| 1 | 데이터 저장 위치 | work_order_items.options JSON | 이미 공정별 데이터(cutting_info, slat_info 등) 저장에 사용 중, 추가 테이블 불필요 |
| 2 | 레이아웃 관리 | 문서 템플릿 시스템 (mng) | 문서관리 시스템 80% 완료, 양식 변경 시 코드 수정 없이 가능 |
| 3 | 성적서 렌더링 | 기존 InspectionContent 컴포넌트 유지 + API 데이터 주입 | 이미 동작하는 렌더링 로직 활용, 점진적으로 Config 기반 전환 |
| 4 | 자동 판정 로직 | 프론트엔드에서 계산 (현재 방식 유지) | 공정별 판정 기준이 프론트에 이미 구현됨 |
| 5 | 검사 이력 | inspection_data에 inspected_at, inspected_by 포함 | 별도 이력 테이블 불필요, JSON 내에서 추적 |

### 4.2 검토 필요 항목

| # | 항목 | 선택지 | 현재 판단 | 비고 |
|---|------|--------|----------|------|
| 1 | Phase 3 (템플릿 등록) 시점 | A) Phase 1-2와 병행 / B) Phase 1-2 완료 후 | B | Phase 1-2로 데이터 저장/조회 먼저 안정화 |
| 2 | 검사 기준 이미지 관리 | A) mng에서 등록 / B) API에서 등록 | A | 문서관리 시스템 계획서 Phase 3.4에서 이미 처리 |
| 3 | 기존 하드코딩 컴포넌트 전환 범위 | A) 전체 전환 / B) 점진적 전환 | B | Phase 4에서 점진적 전환, 기존 기능 유지 우선 |

---

## 6. 상세 작업 절차

### Phase 1: 백엔드 - 개소별 검사 데이터 저장 API

#### 1.1 API 엔드포인트 설계

**작업 내용:**
1. `api/routes/api/v1/production.php`에 라우트 추가:
   - `POST /work-orders/{workOrderId}/items/{itemId}/inspection`
   - `GET /work-orders/{workOrderId}/inspection-data`
   - `GET /work-orders/{workOrderId}/inspection-report`
2. 요청/응답 스키마 확정 (섹션 3.3 참조)
3. FormRequest 클래스 생성

**관련 파일:**
- `api/routes/api/v1/production.php` (라우트 추가)
- `api/app/Http/Requests/Api/V1/` (FormRequest 생성)

#### 1.2 개소별 검사 데이터 저장 API 구현

**작업 내용:**
1. WorkOrderController에 `storeItemInspection` 메서드 추가
2. WorkOrderService에 `saveItemInspection` 메서드 추가:
   - work_order_items 조회 (workOrderId + itemId)
   - options JSON에서 기존 데이터 읽기
   - inspection_data 필드 추가/업데이트
   - inspected_at, inspected_by 자동 기록
3. 유효성 검증: process_type 필수, inspection_data 공정별 스키마 검증

**관련 파일:**
- `api/app/Http/Controllers/Api/V1/WorkOrderController.php`
- `api/app/Services/WorkOrderService.php`

#### 1.3 개소별 검사 데이터 조회 API 구현

**작업 내용:**
1. WorkOrderController에 `getInspectionData` 메서드 추가
2. WorkOrderService에 `getInspectionData` 메서드 추가:
   - 해당 작업지시의 모든 work_order_items 조회
   - 각 item의 options.inspection_data 추출
   - 요약 정보 계산 (total, inspected, pass, fail, pending)

#### 1.4 성적서 문서 데이터 조회 API 구현

**작업 내용:**
1. WorkOrderController에 `getInspectionReport` 메서드 추가
2. WorkOrderService에 `getInspectionReport` 메서드 추가:
   - 공정 타입에 맞는 문서 템플릿 조회 (documents/resolve API 활용)
   - work_order_items의 inspection_data 수집
   - 템플릿 레이아웃 + 검사 데이터 + 기본 정보 결합
   - inspection_setting (도해/검사기준 이미지) 포함

### Phase 2: 프론트 - 개소별 검사 데이터 저장 연동

#### 2.1 서버 액션 추가

**작업 내용:**
1. `react/src/components/production/WorkerScreen/actions.ts`에 추가:
   - `saveItemInspection(workOrderId, itemId, data)` - 개소별 저장
   - `getWorkOrderInspectionData(workOrderId)` - 전체 검사 데이터 조회
   - `getInspectionReport(workOrderId)` - 성적서 데이터 조회

**관련 파일:**
- `react/src/components/production/WorkerScreen/actions.ts`

#### 2.2 InspectionInputModal - 저장 연동

**작업 내용:**
1. onComplete 콜백에서 saveItemInspection 서버 액션 호출
2. 저장 성공/실패 toast 알림
3. 저장 중 로딩 상태 표시
4. 에러 시 재시도 가능

**관련 파일:**
- `react/src/components/production/WorkerScreen/InspectionInputModal.tsx`
- `react/src/components/production/WorkerScreen/index.tsx` (handleInspectionClick)

#### 2.3 WorkerScreen - 저장된 데이터 로드

**작업 내용:**
1. 화면 진입 시 getWorkOrderInspectionData 호출
2. 응답 데이터로 inspectionDataMap 초기화
3. 이미 검사 완료된 개소 시각적 표시 (아이콘/배지)

**관련 파일:**
- `react/src/components/production/WorkerScreen/index.tsx`

#### 2.4 InspectionInputModal - 기존 데이터 표시

**작업 내용:**
1. inspectionDataMap에 해당 itemId 데이터가 있으면 폼에 자동 채움
2. 기존 검사 데이터 수정 가능 (재검사)
3. 최초 검사 vs 재검사 구분 표시

**관련 파일:**
- `react/src/components/production/WorkerScreen/InspectionInputModal.tsx`

### Phase 3: 문서 템플릿 등록 (mng)

#### 3.1~3.4 공정별 양식 등록

**작업 내용 (공정별 동일 패턴):**
1. mng.sam.kr/document-templates에서 새 양식 생성
2. 카테고리: `intermediate-inspection` / 서브카테고리: `screen` (또는 slat/bending/jointbar)
3. 결재라인 설정: 작성자 → 검토 → 승인
4. 기본필드: 제품명, 규격, 수주처, 현장명, LOT NO, 검사일자, 검사자
5. 섹션1: 중간검사 기준서 (도해 이미지 + 검사항목 테이블)
6. 섹션2: 중간검사 DATA (동적 행, 공정별 컬럼 정의)
7. 섹션3: 부적합 내용 + 종합 판정
8. 도해/검사기준 이미지 등록

### Phase 4: 프론트 - 성적서 보기 템플릿 연동

#### 4.1 InspectionReportModal - API 연동

**작업 내용:**
1. getInspectionReport 서버 액션으로 데이터 로드
2. 템플릿 레이아웃 정보 활용 (결재라인, 기본필드, 섹션 구조)
3. 기존 props 기반 데이터 → API 응답 데이터로 전환
4. 로딩/에러 상태 처리

**관련 파일:**
- `react/src/components/production/WorkOrders/documents/InspectionReportModal.tsx`

#### 4.2 InspectionContent 컴포넌트 리팩토링

**작업 내용:**
1. 기존 하드코딩된 레이아웃을 템플릿 데이터 기반으로 전환
2. 공통 렌더링 로직 추출 (테이블 생성, 판정 로직, 결재란)
3. 공정별 차이점만 Config로 분리
4. 기존 기능 100% 유지 (회귀 방지)

**관련 파일:**
- `react/src/components/production/WorkOrders/documents/ScreenInspectionContent.tsx`
- `react/src/components/production/WorkOrders/documents/SlatInspectionContent.tsx`
- `react/src/components/production/WorkOrders/documents/BendingInspectionContent.tsx`
- `react/src/components/production/WorkOrders/documents/BendingWipInspectionContent.tsx`
- `react/src/components/production/WorkOrders/documents/SlatJointBarInspectionContent.tsx`

---

## 7. 컨펌 대기 목록

| # | 항목 | 변경 내용 | 영향 범위 | 상태 |
|---|------|----------|----------|------|
| 1 | API 엔드포인트 3개 추가 | work-orders/{id}/items/{itemId}/inspection, inspection-data, inspection-report | api | ⏳ Phase 1.1에서 확정 |
| 2 | work_order_items.options 구조 확장 | inspection_data 필드 추가 | api, react | ⏳ Phase 1.2에서 확정 |
| 3 | 중간검사 문서 템플릿 4종 등록 | mng 양식 관리에서 등록 | mng | ⏳ Phase 3에서 확정 |

---

## 8. 변경 이력

| 날짜 | 항목 | 변경 내용 | 파일 | 승인 |
|------|------|----------|------|------|
| 2026-02-07 | 초안 | 계획 문서 초안 작성 | - | - |
| 2026-02-07 | 보완 | 자기완결성 보강: Git 정보, 코드 스니펫(타입/모델/라우트/핸들러), 현황 분석(동작 흐름/활용 패턴/API 현황), Phase 의존 관계 추가 | - | - |

---

## 9. 참고 문서

- **문서관리 시스템 계획**: `docs/dev_plans/document-management-system-plan.md` (80% 완료)
- **수입검사 양식 계획**: `docs/dev_plans/incoming-inspection-templates-plan.md`
- **수입검사 연동 계획**: `docs/dev_plans/incoming-inspection-document-integration-plan.md`
- **DB 스키마**: `docs/specs/database-schema.md`
- **빠른 시작**: `docs/quickstart/quick-start.md`
- **품질 체크리스트**: `docs/standards/quality-checklist.md`

### 기존 코드 참조

- **수입검사 성적서 (참고 모델)**: `react/src/components/material/ReceivingManagement/ImportInspectionInputModal.tsx`
- **문서 뷰어**: `react/src/components/document-system/DocumentViewer.tsx`
- **QMS Config**: `react/src/components/document-system/configs/qms/index.ts`
- **검사 서비스**: `api/app/Services/InspectionService.php`

---

## 10. 검증 결과

> 작업 완료 후 이 섹션에 검증 결과 추가

### 9.1 테스트 케이스

| # | 시나리오 | 입력 | 예상 결과 | 실제 결과 | 상태 |
|---|---------|------|----------|----------|------|
| 1 | 스크린 개소 검사 저장 | 모든 항목 양호 입력 | API 200, options.inspection_data 저장됨 | | ⏳ |
| 2 | 저장된 검사 데이터 로드 | 화면 재진입 | inspectionDataMap에 기존 데이터 표시 | | ⏳ |
| 3 | 이미 검사한 개소 재클릭 | 검사 완료된 item 클릭 | 기존 데이터 폼에 표시 | | ⏳ |
| 4 | 검사성적서보기 | 모든 개소 검사 완료 후 클릭 | 템플릿 레이아웃 + 전체 데이터 표시 | | ⏳ |
| 5 | 일부 개소만 검사 후 성적서 | 6개 중 3개만 검사 | 검사된 3개만 데이터, 3개는 빈 행 | | ⏳ |
| 6 | 종합 판정 자동 계산 | 1개 부적 + 나머지 적합 | 종합: 불합격, 부적합 내용 표시 | | ⏳ |

### 9.2 성공 기준

| 기준 | 달성 | 비고 |
|------|------|------|
| 개소별 검사 데이터가 서버에 저장됨 | ⏳ | 새로고침 후에도 유지 |
| 저장된 데이터가 InspectionInputModal에 자동 로드됨 | ⏳ | |
| 검사성적서보기에서 모든 개소 데이터가 합쳐져 표시됨 | ⏳ | |
| 문서 템플릿 레이아웃 적용됨 | ⏳ | 결재란, 기본정보, 섹션 구조 |
| 기존 하드코딩 성적서와 동일한 출력물 | ⏳ | 회귀 방지 |
| 자동 판정 로직 정상 동작 | ⏳ | 행별 + 종합 |

---

## 11. 자기완결성 점검 결과

### 10.1 체크리스트 검증

| # | 검증 항목 | 상태 | 비고 |
|---|----------|:----:|------|
| 1 | 작업 목적이 명확한가? | ✅ | 섹션 1.1 배경에 명시 |
| 2 | 성공 기준이 정의되어 있는가? | ✅ | 섹션 10.2 성공 기준 6개 |
| 3 | 작업 범위가 구체적인가? | ✅ | Phase 1-4, 14개 작업 항목 |
| 4 | 의존성이 명시되어 있는가? | ✅ | Phase 의존 관계 + 문서관리 시스템 80% 완료 전제 |
| 5 | 참고 파일 경로가 정확한가? | ✅ | 절대 경로 포함 핵심 파일 목록 |
| 6 | 단계별 절차가 실행 가능한가? | ✅ | 섹션 6 상세 작업 절차 |
| 7 | 검증 방법이 명시되어 있는가? | ✅ | 섹션 10.1 테스트 케이스 6개 |
| 8 | 모호한 표현이 없는가? | ✅ | API 스키마, 데이터 구조, 검사 항목 매핑, 코드 스니펫 모두 구체적 |
| 9 | 현재 코드 구조가 이해 가능한가? | ✅ | 핵심 타입/인터페이스 + 백엔드 모델/라우트 코드 포함 |
| 10 | 현재 동작 흐름이 파악 가능한가? | ✅ | 섹션 2.1 현재 흐름도 + 문제점 명시 |

### 11.2 새 세션 시뮬레이션 테스트

| 질문 | 답변 가능 | 참조 섹션 |
|------|:--------:|----------|
| Q1. 이 작업의 목적은 무엇인가? | ✅ | 1.1 배경 |
| Q2. 현재 시스템이 어떻게 동작하는가? | ✅ | 2.1 현재 동작 흐름 + 코드 스니펫 |
| Q3. 어디서부터 시작해야 하는가? | ✅ | 📍 현재 진행 상태 + 6. 상세 작업 절차 |
| Q4. 어떤 파일을 수정해야 하는가? | ✅ | 핵심 파일 목록 + Phase별 관련 파일 |
| Q5. 기존 코드의 타입/인터페이스는? | ✅ | 현재 코드 구조 (InspectionData, WorkItemData, WorkOrderItem) |
| Q6. 백엔드에 뭐가 있고 뭐가 없는가? | ✅ | 2.3 API 현황 + 백엔드 라우트/컨트롤러 구조 |
| Q7. 작업 완료 확인 방법은? | ✅ | 10.1 테스트 케이스 + 10.2 성공 기준 |
| Q8. 막혔을 때 참고 문서는? | ✅ | 9. 참고 문서 |

**결과**: 8/8 통과 → ✅ 자기완결성 확보

---

## 12. 세션 및 메모리 관리 정책

### 11.1 세션 시작 시

```
1. 이 문서의 📍 현재 진행 상태 확인
2. 해당 Phase 상세 절차 읽기
3. 관련 파일 읽기
4. "Phase X.X 시작할까요?" 확인
```

### 11.2 작업 중

```
- 변경 이력 섹션에 실시간 기록
- Phase/항목별 상태 업데이트 (⏳ → 🔄 → ✅)
- 컨펌 필요사항 → 컨펌 대기 목록에 추가
```

### 11.3 세션 종료 시

```
- 📍 현재 진행 상태 업데이트
- 변경 이력에 최종 업데이트 기록
```

---

*이 문서는 /sc:plan 스킬로 생성되었습니다. (2026-02-07)*