# 문서 시스템 개선 계획 — 검사 단위 구조 정비 > **⚠️ 이 문서는 아카이브 참조용입니다. 통합 계획은 [`integrated-master-plan.md`](./integrated-master-plan.md)를 참조하세요.** > **작성일**: 2026-02-26 > **버전**: v2 (리뷰 반영) > **목적**: 공정별 중간검사 단위(개소별/항목별/수주별) 구조를 정비하고, 하드코딩된 절곡 검사 콘텐츠를 동적 BOM 기반으로 전환 > **기준 문서**: [`document-system-master.md`](./document-system-master.md), [`document-system-mid-inspection.md`](./document-system-mid-inspection.md) > **상태**: 📦 통합 계획으로 이관 (2026-02-27) > **관련 계획**: [`product-code-traceability-plan.md`](./product-code-traceability-plan.md) (Phase 1 선행 — product_code 전파 누락 **버그 수정**) > **리뷰 문서**: [`document-system-improvement-review.md`](./document-system-improvement-review.md) (정책 결정 16건) --- ## 📍 현재 진행 상태 | 항목 | 내용 | |------|------| | **마지막 완료 작업** | SuperClaude 페르소나 리뷰 16건 정책 결정 + TemplateInspectionContent bending save/restore 구현 | | **다음 작업** | Phase 1 - 절곡 BOM 매핑 구조 분석 | | **진행률** | 0/4 Phase (0%) — 선행 작업 일부 완료 | | **마지막 업데이트** | 2026-02-27 | ### 선행 완료 커밋 (react/) | 커밋 | 내용 | |------|------| | `7b8b5cf5` | feat: TemplateInspectionContent 절곡 bending save/restore 지원 | | `54716e63` | feat: InspectionReportModal에서 documentRecords prop 전달 | | `36052f3e` | fix: bending 개소별 저장 fallback 조건 수정 | --- ## 1. 개요 ### 1.1 배경 SAM ERP의 문서 시스템은 mng(양식 관리) → api(데이터 CRUD) → react(동적 렌더링) 3계층으로 구성되어 있다. 중간검사(PQC), 제품검사(FQC), 수입검사(IQC), 작업일지 등의 공장 문서를 처리하며, 현재 Phase 5.1(중간검사) 5/6 완료 상태이다. **핵심 문제**: 공정별 검사 단위가 통일되지 않아 데이터 구조와 UI 설계에 혼선이 발생하고 있다. | 공정 | 현재 검사 단위 | 적합한 검사 단위 | GAP | |------|:------------:|:--------------:|:---:| | 스크린 | 개소별 (WorkOrderItem당 1행) | 개소별 | ✅ 없음 | | 슬랫 | 개소별 | 개소별 | ✅ 없음 | | 조인트바 | 단일행 (슬랫 하위) | 단일행 | ✅ 없음 | | **절곡** | **하드코딩 7항목 (KWE01 고정)** | **항목별 (BOM 기반 동적)** | **🔴 GAP** | | 절곡 재공품 | 고정값 4항목 | 항목별 | 🟡 GAP | **3관점 검사 지원 방향** (I3 정책 결정): - **구성품별**: 절곡의 주 입력 단위. BOM 항목별 검사 (가이드레일, 케이스, 하단마감재 등) - **개소별**: 부분 출하 시 필요. WorkOrderItem(틀) 단위 검사 - **수주별**: 전체 현황 조회. 수주 소속 전체 개소를 한 문서로 통합 (읽기 전용 뷰) > 각 관점마다 **작업일지 + 검사 성적서** 보기 지원. 화면 구성·데이터 매핑·UI 설계는 기획자와 별도 협의 후 진행. ### 1.2 용어 정의 | 용어 | 설명 | 예시 | |------|------|------| | **개소별 검사** | WorkOrderItem(1틀=1개소) 단위로 1행씩 검사 | 스크린: 10개소 = 10행 | | **항목별 검사** | 구성품(BOM 항목) 단위로 검사 | 절곡: 가이드레일, 케이스, 하단마감재 등 | | **수주별 검사** | 수주(Order) 전체를 하나의 검사 단위로 처리 | 50개소 전체를 1문서로 (읽기 전용 뷰) | | **3관점 검사** | 구성품별/개소별/수주별 세 가지 관점에서 검사 데이터를 조회·입력하는 구조 | 절곡 공정 | | **INITIAL_PRODUCTS** | BendingInspectionContent.tsx에 하드코딩된 7개 구성품 (**레거시, 동결**) | KWE01 전용 | | **DEFAULT_GAP_PROFILES** | TemplateInspectionContent.tsx의 구성품별 간격 포인트 기본값 (**Single Source of Truth**) | I1 정책 결정 | | **BOM** | Bill of Materials, 제품별 구성품 목록 | items 테이블 기반 | | **EAV** | Entity-Attribute-Value 패턴 (document_data 테이블) | section_id/column_id/row_index/field_key | | **inspection-config** | 작업지시 ID만으로 공정 타입 + 구성품 목록을 반환하는 범용 API | I5 정책 결정 | ### 1.3 핵심 데이터 흐름 — 검사 문서 생성 ``` WorkOrder (작업지시) ├─ process_id → Process (공정) │ └─ ProcessStep (needs_inspection=true) │ └─ document_template_id → DocumentTemplate (중간검사 양식) │ ├─ items: WorkOrderItem[] (개소 = 틀) │ ├─ [0] source_order_item_id → OrderItem → OrderNode.options │ ├─ [1] ... │ └─ options: {floor, code, width, height, product_code, ...} │ └─ Document (중간검사 문서) ├─ linkable_type = 'WorkOrder', linkable_id = work_order_id ├─ template_id → DocumentTemplate └─ document_data (EAV) ├─ 기본필드: 품명, 규격, LOT NO, 발주처, 현장명 ... ├─ 검사 데이터: │ ├─ 스크린/슬랫: row_index = 개소, field_key = s{sec}_r{row}_c{col} │ ├─ 절곡 (TemplateInspectionContent): │ │ ├─ row_index = 개소 (C1: 스크린/슬랫과 통일) │ │ └─ field_key = b{productIdx}_ok, b{idx}_p{pt}_n1 등 (구성품 인코딩) │ └─ 절곡 레거시 (BendingInspectionContent): options.inspection_data JSON └─ Footer: 부적합내용, 종합판정 데이터 경로 (C2 정책 결정): ├─ Path A: InspectionInputModal → work_order_items.options.inspection_data (개소별 빠른 입력) └─ Path B: TemplateInspectionContent → document_data EAV (검사 성적서) → 두 경로 독립 동작, 마이그레이션 불필요 ``` ### 1.4 기준 원칙 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 🎯 핵심 원칙 │ ├─────────────────────────────────────────────────────────────────┤ │ 1. 기존 동작 보존: 스크린/슬랫/조인트바 개소별 검사는 건드리지 않음│ │ 2. TemplateInspectionContent 통합: 신규 개발은 여기서 (C3) │ │ 3. BendingInspectionContent 레거시 동결: 유지만, 신규 기능 X (C3)│ │ 4. row_index = 개소 통일: 구성품은 field_key 인코딩 (C1) │ │ 5. EAV 전환 + options 병행: 두 경로 독립 운용 (C2) │ │ 6. 3관점 검사: 구성품별(주입력)/개소별/수주별 지원 (I3) │ │ 7. 롤백 = 템플릿 유무: document_template_id NULL → 레거시 (I4) │ │ 8. 점진적 전환: 레거시/템플릿 모드 병행 유지 │ └─────────────────────────────────────────────────────────────────┘ ``` ### 1.5 변경 승인 정책 | 분류 | 예시 | 승인 | |------|------|------| | ✅ 즉시 가능 | React 컴포넌트 내부 리팩토링, 하드코딩 → API 조회 전환 | 불필요 | | ⚠️ 컨펌 필요 | API 엔드포인트 추가, document_data 저장 구조 변경, 양식 시더 수정 | **필수** | | 🔴 금지 | 기존 스크린/슬랫 검사 로직 변경, document_data 스키마 변경 | 별도 협의 | ### 1.6 v2 핵심 변경 사항 (리뷰 반영) | 정책 | 요약 | 영향 | |------|------|------| | **C1** | row_index=개소 통일, 구성품은 field_key 인코딩 | document_data 저장 구조 | | **C2** | EAV 전환, options 경로 병행 | 마이그레이션 불필요 | | **C3** | TemplateInspectionContent 통합, BendingInspectionContent 레거시 동결 | Phase 2 방향 전환 | | **C4** | BOM 동적화 시 스냅샷+식별자 기반 field_key | 추후 Phase | | **C5** | product_code 전파 누락 = 버그 수정 (fallback 아님) | 선행 의존 | | **I1** | DEFAULT_GAP_PROFILES 기준 통일 | 5130 대조 후 보정 | | **I2** | createInspectionDocument에 lockForUpdate+transaction | 별도 작업 | | **I3** | 3관점(구성품/개소/수주) 지원 | 화면 설계 별도 기획 | | **I4** | 기각 — 템플릿 유무로 이미 롤백 가능 | 추가 작업 없음 | | **I5** | `inspection-config` 범용 API (공정 자동 판별) | API 설계 변경 | | **I6** | 테스트 케이스 보강 | 검증 계획 확대 | | **I7** | 입력=개소별, 출력=수주별 읽기 전용 뷰 | Phase 4 방향 | | **M1** | 신규 API에 BelongsToTenant 필수 | SAM 기본 원칙 | | **M2** | 성공 기준에 API 응답 < 200ms | 성능 지표 추가 | | **M3** | 마스터 문서 위치 — 구현 시점에 명시 | 추후 | | **M4** | 타입 통일 불필요 — 레거시 동결, 신규는 TemplateInspectionContent | 추가 작업 없음 | > 상세 내용: [`document-system-improvement-review.md`](./document-system-improvement-review.md) --- ## 2. 현황 분석 ### 2.1 레거시 5130 시스템 분석 5130 시스템은 `output/` 디렉토리에 공정별 문서를 관리한다. **문서 유형 (5130/output/)**: | 파일 | 문서 유형 | 검사 단위 | 데이터 저장 | |------|----------|:--------:|-----------| | `view_inspection_screen.php` | 스크린 중간검사 | 수주별 | `recordscreen` JSON 컬럼 | | `view_inspection_slatMid.php` | 슬랫 중간검사 | 수주별 | `recordslatMid` JSON 컬럼 | | `view_inspection_bending.php` | 절곡 중간검사 | 수주별 | `recordbending` JSON 컬럼 | | `view_workorder.php` | 작업일지 | 작업지시별 | 전용 테이블 | | `view_delivery.php` | 납품서 | 수주별 | — | | `view_inspection_product.php` | 제품검사 | 수주별 | — | **핵심 발견**: - 5130에서는 **모든 중간검사가 수주별(per-수주)** 단위 - JSON 컬럼(`recordscreen`, `recordslatMid`, `recordbending`)에 전체 개소 데이터를 한 번에 저장 - 절곡 검사는 구성품 목록이 제품코드(KSS01/KSS02/KWE01)와 마감유형(S1/S2/S3)에 따라 다름 **수입검사 (5130/instock/)**: - `i_*.php` 형식의 23개 자재별 수입검사 양식 - SAM에서 mng 시더로 이관 완료 (IncomingInspectionTemplateSeeder) ### 2.2 현재 SAM 문서 시스템 — 완성 현황 | 영역 | 상태 | 핵심 파일 | 비고 | |------|:----:|----------|------| | mng 양식 관리 (4탭 CRUD) | ✅ | `edit.blade.php` | 기본정보/기본필드/검사기준서/컬럼 | | mng 문서 상세보기 | ✅ | `show.blade.php` | 검사문서+작업일지 동적 렌더링 | | API DocumentTemplate 조회 | ✅ | `DocumentTemplateController` | 6모델 Eager Loading | | API Document CRUD + 결재 | ✅ | `DocumentController`, `DocumentService` | resolve/upsert 패턴 | | API 중간검사 생성 | ✅ | `WorkOrderService::createInspectionDocument` | 정규화+레거시 형식 지원 | | API 작업일지 생성/조회 | ✅ | `WorkOrderService::getWorkLog/createWorkLog` | 템플릿 기반 | | React TemplateInspectionContent | ✅ | 양식 기반 동적 렌더링 + **bending save/restore** | 범용 (통합 방향) | | React 레거시 검사 콘텐츠 | ✅ | Screen/Slat/Bending*.tsx | 하드코딩 기반 (**동결**) | | React InspectionInputModal | ✅ | 작업자 화면 검사 입력 | 동적/레거시 병행 | | React WorkLogModal | ✅ | 작업자 화면 작업일지 | 양식 연동 | | columns 자동 파생 (방안1) | ✅ | `generateColumnsFromItems()` | 검사기준서→컬럼 자동 | | 검사기준서↔컬럼 연동 | ✅ | `section_fields` 필수화 | Phase 5.0 | | 결재 워크플로우 | ⏳ | API ready, 프론트 미연동 | Phase 5.1.6 | | React 전환 결정 | ⏳ | Phase 4.4 미완료 | 프론트 담당자 협의 필요 | ### 2.3 공정별 검사 구조 상세 분석 #### 스크린 (ScreenInspectionContent) — 개소별 ✅ ``` 행(row) = WorkOrderItem (개소별 1행) ├─ 검사항목: 가공상태(check), 재봉상태(check), 조립상태(check), │ 길이(complex), 나비(complex), 간격(check) ├─ 행 수: work_order_items.length (개소 수) ├─ 각 행에 width/height 치수 자동 반영 (WorkOrderItem.options) └─ mng 양식 ID: 12 ``` #### 슬랫 (SlatInspectionContent) — 개소별 ✅ ``` 행(row) = WorkOrderItem (개소별 1행) ├─ 검사항목: 가공상태(check), 조립상태(check), │ 높이1(complex), 높이2(complex), 길이(complex) ├─ 행 수: work_order_items.length (개소 수) └─ mng 양식 ID: 11 ``` #### 절곡 — 🔴 동적 전환 필요 ``` 레거시 (AS-IS) — BendingInspectionContent (동결): 행(row) = INITIAL_PRODUCTS (7개 하드코딩, KWE01 전용) ├─ 가이드레일 벽면형, 가이드레일 측면형, 케이스, │ 하단마감재, 하단L-BAR, 연기차단재W50, 연기차단재W80 ├─ 저장: work_order_items.options.inspection_data (JSON, Path A) ├─ 제품코드별 구성품이 다른데 KWE01만 대응 └─ mng 양식 ID: 13 신규 (TO-BE) — TemplateInspectionContent (C3 통합 방향): 행(row) = WorkOrderItem (개소별), 구성품은 field_key에 인코딩 (C1) ├─ buildBendingProducts()로 동적 구성품 생성 (이미 구현) ├─ DEFAULT_GAP_PROFILES 기준치 사용 (I1: Single Source of Truth) ├─ 저장: document_data EAV (Path B) │ ├─ row_index = 개소(WorkOrderItem) 인덱스 │ └─ field_key = b{productIdx}_ok, b{idx}_p{pointIdx}_n1 등 ├─ API: /work-orders/{id}/inspection-config (I5: 공정 자동 판별) └─ bending save/restore 구현 완료 (커밋 7b8b5cf5, 36052f3e) ``` #### 3관점 검사 구조 (I3 방향) ``` 절곡 공정 검사: ├─ 구성품별 (주 입력): BOM 항목별 검사 데이터 입력 │ ├─ 작업일지: 구성품별 생산 기록 │ └─ 검사 성적서: 구성품별 품질 검사 │ ├─ 개소별 (부분 출하): WorkOrderItem 단위 조회+부분 입력 │ ├─ 작업일지: 개소별 작업 기록 │ └─ 검사 성적서: 개소별 검사 현황 │ └─ 수주별 (전체 조회): 수주 소속 전체를 한 문서로 (읽기 전용 뷰) ├─ 작업일지: 수주 전체 작업 현황 └─ 검사 성적서: 수주 전체 검사 현황 ※ 화면 구성·데이터 매핑·UI 설계는 기획자와 별도 협의 ``` ### 2.4 핵심 GAP 상세 — 절곡 INITIAL_PRODUCTS (레거시 동결) **파일**: `react/src/components/production/WorkOrders/documents/BendingInspectionContent.tsx` (L71-135) > **C3 정책 결정**: 이 파일은 **레거시로 동결**. 신규 개발은 TemplateInspectionContent에서 진행. | # | 항목 ID | category | productName | productType | gapPoints 수 | |---|---------|----------|-------------|-------------|:----------:| | 1 | guide-rail-wall | KWE01 | 가이드레일 | 벽면형 | 5 | | 2 | guide-rail-side | KWE01 | 가이드레일 | 측면형 | 5 | | 3 | case | KWE01 | 케이스 | 500X380 | 4 | | 4 | bottom-finish | KWE01 | 하단마감재 | 60X40 | 2 | | 5 | bottom-l-bar | KWE01 | 하단L-BAR | 17X60 | 1 | | 6 | smoke-w50 | KWE01 | 연기차단재 | W50 가이드레일용 | 2 | | 7 | smoke-w80 | KWE01 | 연기차단재 | W80 케이스용 | 2 | **기존 문제** (BendingInspectionContent): 1. KWE01 전용 — 다른 제품코드 미지원 2. 마감유형(S1/S2/S3) 미반영 3. 치수 하드코딩 4. 동적 변경 불가 **해결 방향** (TemplateInspectionContent): - `buildBendingProducts()` (L209-274)로 동적 구성품 생성 — 이미 구현 - `DEFAULT_GAP_PROFILES` (L176-206)로 기준치 관리 - API에서 BOM 기반 구성품 로딩 시 `buildBendingProducts()` 대체 --- ## 3. 대상 범위 ### 3.1 Phase 1: 절곡 검사 항목 동적화 기반 구축 ⏳ **목표**: 절곡 구성품(검사 항목) 정보를 API에서 제공하는 구조 마련 | # | 작업 항목 | 상태 | 비고 | |---|----------|:----:|------| | 1.1 | 절곡 제품코드별 구성품(BOM) 데이터 구조 분석 | ⏳ | items/BOM 테이블에서 KWE01/KSS01/KSS02 구성품 확인 | | 1.2 | 마감유형(S1/S2/S3)별 차이 분석 | ⏳ | 5130 레거시 참조 | | 1.3 | **inspection-config 범용 API 설계** | ⏳ | `GET /api/v1/work-orders/{id}/inspection-config` (I5) | | 1.4 | DEFAULT_GAP_PROFILES 기준치 5130 대조 확인 | ⏳ | I1: Single Source of Truth 보정 | ### 3.2 Phase 2: TemplateInspectionContent 절곡 동적 확장 ⏳ **목표**: API 기반 동적 구성품 로딩으로 `buildBendingProducts()` 고정 로직 대체 > **C3 통합 방향**: BendingInspectionContent 대신 TemplateInspectionContent에서 진행 | # | 작업 항목 | 상태 | 비고 | |---|----------|:----:|------| | 2.1 | inspection-config API 구현 (공정 자동 판별) | ⏳ | BelongsToTenant 필수 (M1) | | 2.2 | TemplateInspectionContent API 연동 (buildBendingProducts 대체) | ⏳ | DEFAULT_GAP_PROFILES → API 기준치 | | 2.3 | document_data EAV 저장/복원 검증 | ⏳ | C1 field_key 인코딩 패턴 | | 2.4 | 기존 절곡 검사 데이터 하위 호환 확인 | ⏳ | 레거시(Path A) + 신규(Path B) 독립 동작 | | 2.5 | createInspectionDocument 트랜잭션 보강 | ⏳ | I2: lockForUpdate + DB::transaction | ### 3.3 Phase 3: 절곡 재공품 양식 + 기타 정비 ⏳ **목표**: 절곡 재공품(BendingWip) 검사 양식 추가, 결재 워크플로우 연동 | # | 작업 항목 | 상태 | 비고 | |---|----------|:----:|------| | 3.1 | 절곡 재공품 mng 양식 시더 추가 (또는 절곡 양식 통합) | ⏳ | BendingWipInspectionContent 대응 | | 3.2 | 결재 워크플로우 프론트 연동 (Phase 5.1.6) | ⏳ | 작성→검토→승인 3단계 | | 3.3 | Phase 4.4 — React 기존 하드코딩 컴포넌트 전환 결정 | ⏳ | 프론트 담당자 협의 | ### 3.4 Phase 4: 3관점 검사 + 수주별 뷰 설계 (추후) ⏭️ **목표**: 구성품별/개소별/수주별 3관점 검사 구조 설계 및 수주별 읽기 전용 뷰 구현 > **⚠️ Phase 2 완료 후 별도 일정. 화면 설계는 기획자와 협의 필요.** | # | 작업 항목 | 상태 | 비고 | |---|----------|:----:|------| | 4.1 | 3관점 검사 데이터 모델 상세 설계 | ⏭️ | 구성품별↔개소별↔수주별 매핑 (I3) | | 4.2 | 수주별 읽기 전용 뷰 설계 | ⏭️ | 입력=개소별, 출력=수주별 (I7) | | 4.3 | 5130 recordscreen JSON → EAV 변환 규칙 | ⏭️ | 이관 설계 | | 4.4 | 기획자 협의 — 화면 구성, UI/UX | ⏭️ | 3관점 각각의 화면 레이아웃 | --- ## 4. 상세 작업 내용 ### 4.1 Phase 1 상세: 절곡 검사 항목 동적화 기반 #### 4.1.1 절곡 구성품 데이터 소스 분석 현재 제품별 구성품(BOM)이 어디에 정의되어 있는지 확인 필요: ``` 분석 대상: 1. items 테이블 — type='finished_goods' 또는 'component'인 항목 2. bom_items 테이블 — 제품→구성품 관계 3. order_nodes.options.bending_info — 수주 시 절곡 정보 4. 5130/estimate/common/common_addrowJS.php — 레거시 구성품 정의 5. mng 절곡 양식(ID:13)의 section_items — 검사기준서 항목 6. TemplateInspectionContent DEFAULT_GAP_PROFILES — 현재 기준치 (I1) ``` #### 4.1.2 구성품 결정 로직 (설계안) ``` 입력: work_order_id ↓ 1차: 작업지시 → 공정 자동 판별 (inspection-config API) ↓ 2차: product_code → BOM 테이블에서 하위 구성품 조회 ↓ (BOM 미등록 시) 3차: DEFAULT_GAP_PROFILES 기본값 사용 (TemplateInspectionContent) ↓ (템플릿 미설정 시 = 레거시) 4차: INITIAL_PRODUCTS fallback (BendingInspectionContent, KWE01 하위호환) ``` #### 4.1.3 API 설계안 (I5 정책 결정 반영) ``` GET /api/v1/work-orders/{id}/inspection-config ※ BelongsToTenant 스코프 필수 적용 (M1) ※ 공정 타입 자동 판별 — 프론트에서 공정 하드코딩 불필요 Response: { "data": { "work_order_id": 123, "process_type": "bending", // 자동 판별 "product_code": "FG-KQTS01", "finish_type": "S1", "template_id": 60, "items": [ { "id": "guide-rail-wall", "category": "KWE01", "product_name": "가이드레일", "product_type": "벽면형", "length_design": "3000", "width_design": "N/A", "gap_points": [ { "point": "①", "design_value": "30" }, { "point": "②", "design_value": "78" }, ... ] }, ... ] } } 비절곡 공정 Response (스크린/슬랫): { "data": { "work_order_id": 456, "process_type": "screen", "product_code": "FG-KQTS01", "template_id": 12, "items": [] // 비절곡은 구성품 목록 불필요 } } ``` ### 4.2 Phase 2 상세: TemplateInspectionContent 절곡 동적 확장 #### 4.2.1 현재 코드 구조 (TemplateInspectionContent — 이미 구현된 부분) ```typescript // TemplateInspectionContent.tsx // 구성품 간격 기준치 (I1: Single Source of Truth) const DEFAULT_GAP_PROFILES = { /* L176-206 */ }; // 동적 구성품 생성 (order.bendingInfo 기반) function buildBendingProducts(order): BendingProduct[] { /* L209-274 */ } // bending 감지 const isBending = order.processType === 'bending' || columns에 point sub_labels 존재; // bending save: field_key = b{idx}_ok, b{idx}_p{pt}_n1 등 // bending restore: documentRecords에서 field_key 패턴 매칭으로 복원 ``` #### 4.2.2 변경 방향 (TO-BE) ```typescript // TemplateInspectionContent.tsx (Phase 2 변경) // AS-IS: buildBendingProducts()가 order.bendingInfo에서 고정 로직으로 구성품 생성 // TO-BE: inspection-config API에서 BOM 기반 구성품 목록 수신 interface InspectionConfig { process_type: string; product_code: string; items: BendingInspectionItem[]; // API에서 수신 } // 컴포넌트 내부 const configItems = useInspectionConfig(workOrderId); // API 호출 const bendingProducts = configItems ?? buildBendingProducts(order); // fallback ``` #### 4.2.3 document_data 저장 구조 (C1 정책 결정 반영) ``` row_index 의미: 모든 공정에서 "개소(WorkOrderItem)" 통일 (C1) 스크린/슬랫 (기존): row_index = WorkOrderItem 인덱스 (0, 1, 2, ...) field_key = s{section}_r{row}_c{column}_sub{index} 절곡 — TemplateInspectionContent (C1 인코딩 패턴): row_index = WorkOrderItem 인덱스 (개소) — 스크린/슬랫과 동일 field_key 패턴: ├─ b{productIdx}_ok → 구성품 OK/NG 판정 ├─ b{productIdx}_ng → NG 상세 ├─ b{productIdx}_value → 길이/너비 측정값 ├─ b{productIdx}_judgment → 종합 판정 ├─ b{productIdx}_p{pointIdx}_n1 → 간격 포인트 측정값 1 ├─ b{productIdx}_p{pointIdx}_n2 → 간격 포인트 측정값 2 └─ b{productIdx}_n{n} → 추가 측정값 ※ 이미 TemplateInspectionContent save/restore에 구현 완료 (커밋 7b8b5cf5) ※ productIdx는 buildBendingProducts() 반환 배열의 인덱스 BOM 동적화 시 (C4 추후): ├─ field_key → b{productId}_... 형태로 전환 (순서 독립적) ├─ document.options에 bom_snapshot 저장 └─ 인덱스 기반 → 식별자 기반 매핑 ``` **하위호환 (C2)**: - 기존 절곡 검사 데이터는 `work_order_items.options.inspection_data` (Path A)에 저장 - 신규 데이터는 `document_data` EAV (Path B)에 저장 - 두 경로가 독립적으로 동작하므로 마이그레이션 불필요 ### 4.3 Phase 4 구조 설계 — 3관점 검사 + 수주별 뷰 #### 4.3.1 3관점 검사 모델 (I3 정책 결정) ``` 구성품별 (주 입력): ├─ 단위: BOM 항목 (가이드레일, 케이스, 하단마감재 등) ├─ 입력: 구성품별 OK/NG, 측정값, 간격 포인트 ├─ 화면: 작업일지 + 검사 성적서 └─ 데이터: document_data EAV (field_key 인코딩) 개소별 (부분 출하): ├─ 단위: WorkOrderItem (1틀=1개소) ├─ 입력: 개소별 검사 데이터 조회 + 부분 입력 가능 ├─ 화면: 작업일지 + 검사 성적서 └─ 데이터: row_index로 필터링 수주별 (전체 조회 — I7): ├─ 단위: 수주(Order) 전체 ├─ 입력: 읽기 전용 뷰 (입력은 개소별에서) ├─ 화면: 작업일지 + 검사 성적서 통합 조회 └─ 데이터: 여러 WorkOrder의 document_data 통합 렌더링 ※ 화면 구성·데이터 매핑·UI 설계는 기획자와 별도 협의 ``` #### 4.3.2 수주별 읽기 전용 뷰 (I7 정책 결정) ``` 수주별 뷰 설계 방향: ├─ 입력은 개소별 (현행 워크플로우 유지) ├─ 수주별은 읽기 전용 통합 조회 ├─ 기존 per-개소 Document 데이터를 수주 단위로 합산 렌더링 ├─ 별도 수주별 Document 생성 불필요 (뷰 레벨 통합) └─ 데이터 중복 없음 구현 방안: ├─ 수주 ID → 소속 WorkOrder 목록 조회 ├─ 각 WorkOrder의 Document.document_data 수집 ├─ 통합 렌더링 (개소 순서대로) └─ 인쇄 시 수주별 양식으로 출력 ``` --- ## 5. DB 관계도 — 문서 시스템 전체 ``` document_templates (양식 마스터) ├── sections → section_items (검사기준서 항목) ├── columns (테이블 컬럼 정의, 자동 파생 가능) ├── basic_fields (기본필드: 품명, LOT NO 등) ├── section_fields (동적 필드 정의) ├── approval_lines (결재라인) ├── field_presets (필드 프리셋) └── links (외부 키 매핑) documents (문서 인스턴스) ├── template_id → document_templates ├── linkable_type + linkable_id (polymorphic) │ ├── WorkOrder (중간검사: per-작업지시, 내부 per-개소 행) │ ├── OrderItem (제품검사: per-개소) │ ├── Material (수입검사: per-자재) │ └── Order (수주별 검사: per-수주, 추후 — 뷰 레벨 통합 우선 I7) ├── document_data (EAV: section_id/column_id/row_index/field_key/field_value) │ └── 절곡 field_key: b{productIdx}_ok, b{idx}_p{pt}_n1 등 (C1) ├── document_approvals (결재 상태) └── document_attachments (첨부파일) process_steps ├── document_template_id → 공정별 검사 양식 매핑 │ └── NULL이면 레거시 컴포넌트 사용 (I4: 롤백 메커니즘) └── needs_inspection = true work_orders ├── items: work_order_items[] │ ├── options JSON: {floor, code, width, height, product_code, ...} │ │ └── product_code: product-code-traceability-plan Phase 1에서 버그 수정 (C5) │ ├── source_order_item_id → order_items │ └── 검사 데이터 저장 경로: │ ├── Path A: options.inspection_data (InspectionInputModal, 개소별) │ └── Path B: document_data EAV (TemplateInspectionContent, 검사 성적서) └── documents (morphMany) — 중간검사/작업일지 ``` --- ## 6. 5130 레거시 문서 참조표 ### 6.1 중간검사 문서 (5130/output/) | 레거시 파일 | SAM 양식 ID | SAM 컴포넌트 | 전환 상태 | |------------|:---------:|-------------|:--------:| | `view_inspection_screen.php` | 12 | ScreenInspectionContent | ✅ | | `view_inspection_slatMid.php` | 11 | SlatInspectionContent | ✅ | | — (조인트바는 슬랫 하위) | 10 | SlatJointBarInspectionContent | ✅ | | `view_inspection_bending.php` | 13 | ~~BendingInspectionContent~~ → **TemplateInspectionContent** | 🔄 동적 확장 중 | | — | — | BendingWipInspectionContent | ⏳ 양식 미존재 | ### 6.2 기타 문서 (5130/output/) | 레거시 파일 | SAM 대응 | 상태 | |------------|---------|:----:| | `view_workorder.php` | WorkLogModal/Content | ✅ Phase 5.3 | | `view_delivery.php` | 납품서 (미착수) | ⏭️ | | `view_inspection_product.php` | ProductInspectionDocument | ✅ Phase 5.2 | ### 6.3 수입검사 (5130/instock/) - 23개 자재별 양식 (`i_*.php`) → mng IncomingInspectionTemplateSeeder로 이관 - 상세: [`incoming-inspection-templates-plan.md`](./incoming-inspection-templates-plan.md) --- ## 7. 컨펌 대기 목록 | # | 항목 | 변경 내용 | 영향 범위 | 상태 | |---|------|----------|----------|------| | 1 | Phase 1 실행 승인 | 절곡 구성품 데이터 소스 분석 + API 설계 | 분석만, 코드 변경 없음 | ⚠️ 대기 | | 2 | ~~절곡 구성품 로딩 방식~~ | ~~BOM 기반 vs 양식 내 구성품 템플릿~~ | — | ✅ C3에서 결정 | | 3 | ~~절곡 재공품 양식 방향~~ | ~~별도 양식 신규 vs 절곡 양식 통합~~ | — | ⏳ Phase 3 | | 4 | ~~수주별 검사 방향~~ | ~~Option A/B/C~~ | — | ✅ I7에서 결정 | | 5 | 3관점 검사 화면 설계 | 구성품별/개소별/수주별 UI/UX | 기획자 협의 필요 | ⏭️ Phase 4 | --- ## 8. 작업 절차 요약 ``` 선행: product-code-traceability-plan Phase 1 완료 (C5: product_code 전파 버그 수정) 선행: createInspectionDocument 트랜잭션 보강 (I2: lockForUpdate + DB::transaction) ↓ Phase 1 (기반 구축) ─── 분석 + 설계, 코드 변경 최소 ├── Step 1: items/BOM 테이블에서 절곡 구성품 데이터 분석 ├── Step 2: KWE01/KSS01/KSS02별 구성품 차이 파악 ├── Step 3: DEFAULT_GAP_PROFILES 기준치 5130 대조 (I1) └── Step 4: inspection-config 범용 API 설계 (I5) → 컨펌 Phase 2 (TemplateInspectionContent 동적 확장) ─── 핵심 구현 (C3) ├── Step 1: inspection-config API 구현 (BelongsToTenant 필수 M1) ├── Step 2: TemplateInspectionContent buildBendingProducts → API 연동 ├── Step 3: document_data EAV 저장/복원 검증 (C1 field_key) ├── Step 4: 레거시(Path A) + 신규(Path B) 독립 동작 확인 (C2) └── Step 5: 기존 데이터 정상 표시 확인 Phase 3 (정비) ─── 기타 미완료 항목 ├── Step 1: 절곡 재공품 양식 추가 ├── Step 2: 결재 워크플로우 프론트 연동 └── Step 3: Phase 4.4 협의 (React 전환 결정) Phase 4 (3관점 검사 + 수주별 뷰) ─── 기획자 협의 후 진행 ⏭️ ├── Step 1: 기획자와 3관점 화면 설계 협의 (I3) ├── Step 2: 수주별 읽기 전용 뷰 구현 (I7) └── Step 3: 개소별↔구성품별↔수주별 데이터 매핑 ``` --- ## 9. 성공 기준 | 기준 | 측정 방법 | 수치 목표 | |------|----------|----------| | 절곡 검사 구성품 동적 로딩 | KWE01, KSS01, KSS02 제품코드별 다른 구성품 표시 | 3종 이상 지원 | | 마감유형별 구성품 차이 반영 | S1/S2/S3 마감유형 선택 시 구성품 변경 | 정상 변경 | | 기존 절곡 검사 데이터 호환 | 기저장 KWE01 검사 데이터 정상 조회 (Path A + Path B) | 100% 호환 | | ~~INITIAL_PRODUCTS 하드코딩 제거~~ | ~~BendingInspectionContent에서 하드코딩 상수 미사용~~ | C3: 레거시 동결 | | TemplateInspectionContent 동적화 | buildBendingProducts → API 기반 구성품 로딩 | 완전 전환 | | 스크린/슬랫 검사 회귀 없음 | 기존 개소별 검사 정상 동작 | 에러 0건 | | document_data 저장 정합성 | C1 field_key 인코딩 저장/조회 일치 | 100% | | **inspection-config API 응답 성능** | **구성품 목록 API 응답 시간** | **< 200ms (M2)** | --- ## 10. 핵심 파일 경로 ### React (절곡 검사 관련) | 파일 | 역할 | 주요 라인 | v2 상태 | |------|------|----------|:------:| | `react/.../documents/TemplateInspectionContent.tsx` | 양식 기반 동적 렌더링 + **bending save/restore** | L176-274 DEFAULT_GAP_PROFILES, buildBendingProducts | **통합 방향 (C3)** | | `react/.../documents/BendingInspectionContent.tsx` | 절곡 중간검사 성적서 | L71-135 INITIAL_PRODUCTS | **레거시 동결 (C3)** | | `react/.../documents/BendingWipInspectionContent.tsx` | 절곡 재공품 검사 | — | Phase 3 | | `react/.../documents/InspectionReportModal.tsx` | 중간검사 모달 (래퍼) | L386-418 activeTemplate 분기 | documentRecords 전달 완료 | | `react/.../documents/inspection-shared.tsx` | 공유 유틸/컴포넌트 | — | — | | `react/.../WorkerScreen/InspectionInputModal.tsx` | 작업자 화면 검사 입력 | ~950행 | Path A (options) 유지 | | `react/.../documents/ScreenInspectionContent.tsx` | 스크린 중간검사 (참조용) | 개소별 패턴 | 변경 없음 | | `react/.../documents/SlatInspectionContent.tsx` | 슬랫 중간검사 (참조용) | 개소별 패턴 | 변경 없음 | ### API | 파일 | 역할 | 주요 메서드 | v2 비고 | |------|------|-----------|--------| | `api/app/Services/WorkOrderService.php` | 검사 문서 생성/조회 | createInspectionDocument, resolveInspectionDocument | I2: 트랜잭션 보강 필요 | | `api/app/Services/DocumentService.php` | 문서 CRUD | create, update, formatTemplateForReact, resolve, upsert | — | | `api/app/Http/Controllers/V1/DocumentController.php` | 문서 API | — | — | | `api/app/Models/Documents/Document.php` | 문서 모델 | linkable morphTo, data() HasMany | — | ### mng | 파일 | 역할 | |------|------| | `mng/database/seeders/MidInspectionTemplateSeeder.php` | 중간검사 양식 시더 (4종) | | `mng/resources/views/document-templates/edit.blade.php` | 양식 편집 UI | | `mng/resources/views/documents/show.blade.php` | 문서 상세보기 | ### 5130 레거시 (참조용) | 파일 | 역할 | |------|------| | `5130/output/view_inspection_bending.php` | 절곡 중간검사 성적서 | | `5130/output/_row.php` | output 테이블 구조 (recordbending JSON) | | `5130/estimate/common/common_addrowJS.php` | 제품별 구성품 정의 로직 | --- ## 11. 변경 이력 | 날짜 | 항목 | 변경 내용 | 파일 | 승인 | |------|------|----------|------|------| | 2026-02-26 | 문서 초안 (v1) | 4개 분석 에이전트 결과 종합, 계획 수립 | - | - | | 2026-02-26 | bending save/restore | TemplateInspectionContent 절곡 저장/복원 구현 | react/ 3건 커밋 | ✅ | | 2026-02-27 | 리뷰 정책 결정 | SuperClaude 페르소나 리뷰 16건 전체 완료 | review.md | ✅ | | 2026-02-27 | **v2 반영** | 16건 정책 결정 계획서 반영: C3 통합 방향, C1 field_key 인코딩, I5 inspection-config API, I3 3관점 검사, I7 수주별 읽기 전용 뷰, M2 성능 기준 등 | plan.md | - | --- ## 12. 세션 및 메모리 관리 정책 ### 12.1 세션 시작 시 ``` 1. 이 문서(document-system-improvement-plan.md) 읽기 2. 진행 상태 테이블 확인 → 마지막 완료 작업 파악 3. 리뷰 문서(document-system-improvement-review.md) 정책 결정 확인 4. 마스터 문서(document-system-master.md) 현행 Phase 상태 확인 5. 다음 작업 시작 ``` ### 12.2 작업 중 관리 - Phase 완료 시 이 문서의 상태 테이블 업데이트 - 마스터 문서(document-system-master.md)도 동기화 업데이트 (M3) - 컨펌 필요 사항 발생 시 컨펌 대기 목록에 추가 ### 12.3 세션 종료 시 - 변경 이력 섹션에 최종 업데이트 기록 --- ## 13. 검증 결과 > 작업 완료 후 이 섹션에 검증 결과 추가 ### 13.1 Phase 1 검증 | 조사 항목 | 결과 | 판단 | |----------|------|------| | KWE01 BOM 구성품 수 | | ⏳ | | KSS01 BOM 구성품 수 | | ⏳ | | KSS02 BOM 구성품 수 | | ⏳ | | 마감유형별 차이점 | | ⏳ | | DEFAULT_GAP_PROFILES 5130 대조 (I1) | | ⏳ | ### 13.2 Phase 2 검증 | 테스트 | 예상 결과 | 실제 결과 | 상태 | |--------|----------|----------|------| | KWE01 제품코드 → 구성품 표시 | buildBendingProducts 결과와 동일 | | ⏳ | | KSS01 제품코드 → 다른 구성품 표시 | KSS01 전용 구성품 | | ⏳ | | KSS02 제품코드 → 다른 구성품 표시 | KSS02 전용 구성품 | | ⏳ | | 마감유형 S1/S2/S3 각각 | 유형별 구성품 차이 반영 | | ⏳ | | 구성품 수 7개 미만/초과 | 정상 렌더링 | | ⏳ | | API 미응답 시 fallback | buildBendingProducts 기본값 사용 | | ⏳ | | BOM 미등록 시 | DEFAULT_GAP_PROFILES 기본값 사용 | | ⏳ | | API 타임아웃 시 | 에러 처리 + fallback | | ⏳ | | 빈 배열 반환 시 | 빈 테이블 or fallback | | ⏳ | | 저장→조회→재저장 사이클 | 데이터 무손실 | | ⏳ | | 기존 절곡 검사 데이터 조회 (Path A) | 정상 표시 (레거시 경로) | | ⏳ | | 신규 절곡 검사 데이터 저장/조회 (Path B) | EAV 정상 동작 | | ⏳ | | mng show.blade.php 렌더링 | 검사 성적서 정상 표시 | | ⏳ | | 인쇄 레이아웃 | 양식에 맞는 인쇄 출력 | | ⏳ | | inspection-config API 응답 시간 | < 200ms | | ⏳ | | 스크린/슬랫 검사 회귀 | 변화 없음 | | ⏳ | | 트랜잭션 동시 접근 (I2) | race condition 없음 | | ⏳ | ### 13.3 Phase 3 검증 | 테스트 | 예상 결과 | 실제 결과 | 상태 | |--------|----------|----------|------| | 절곡 재공품 양식 정상 동작 | 양식 편집/미리보기 OK | | ⏳ | | 결재 워크플로우 3단계 | 작성→검토→승인 | | ⏳ | --- ## 14. 자기완결성 점검 결과 ### 14.1 체크리스트 검증 | # | 검증 항목 | 상태 | 비고 | |---|----------|:----:|------| | 1 | 작업 목적이 명확한가? | ✅ | 절곡 항목별 검사 동적화 + 3관점 검사 구조 (I3) | | 2 | 성공 기준이 정의되어 있는가? | ✅ | 섹션 9 - 성능 지표 포함 (M2) | | 3 | 작업 범위가 구체적인가? | ✅ | Phase 1-3 구현, Phase 4 설계 | | 4 | 의존성이 명시되어 있는가? | ✅ | C5 버그 수정, I2 트랜잭션 보강 | | 5 | 참고 파일 경로가 정확한가? | ✅ | v2 상태 컬럼 추가 | | 6 | 단계별 절차가 실행 가능한가? | ✅ | API 설계안 + 코드 변경 방향 포함 | | 7 | 검증 방법이 명시되어 있는가? | ✅ | I6 보강 테스트 케이스 포함 | | 8 | 모호한 표현이 없는가? | ✅ | 용어 정의 확대, 정책 결정 근거 명시 | ### 14.2 새 세션 시뮬레이션 테스트 | 질문 | 답변 가능 | 참조 섹션 | |------|:--------:|----------| | Q1. 이 작업의 목적은 무엇인가? | ✅ | 1.1 배경 | | Q2. 어디서부터 시작해야 하는가? | ✅ | 3.1 Phase 1 + 8. 작업 절차 | | Q3. 어떤 파일을 수정해야 하는가? | ✅ | 10. 핵심 파일 경로 (v2 상태 포함) | | Q4. 작업 완료 확인 방법은? | ✅ | 9. 성공 기준 + 13. 검증 결과 | | Q5. 막혔을 때 참고 문서는? | ✅ | 마스터 문서 + 리뷰 문서 + 10. 파일 경로 | | Q6. 리뷰 정책 결정은 어디서 확인하나? | ✅ | 1.6 핵심 변경 사항 + 리뷰 문서 링크 | | Q7. 기존 검사에 영향이 있는가? | ✅ | 1.4 기준 원칙 #1, I4 롤백 메커니즘 | | Q8. 두 데이터 경로(Path A/B)는 어떻게 동작하는가? | ✅ | 1.3 데이터 흐름 + 4.2.3 저장 구조 | --- ## 15. 참고 문서 | 문서 | 경로 | 용도 | |------|------|------| | 문서 시스템 마스터 | `docs/dev_plans/document-system-master.md` | 전체 Phase 진행 관리 | | **리뷰 정책 결정** | `docs/dev_plans/document-system-improvement-review.md` | **16건 정책 결정 상세** | | 중간검사 계획 | `docs/dev_plans/document-system-mid-inspection.md` | Phase 5.1 상세 | | 작업일지 계획 | `docs/dev_plans/document-system-work-log.md` | Phase 5.3 상세 | | 제품코드 추적성 | `docs/dev_plans/product-code-traceability-plan.md` | product_code 전파 버그 수정 (C5 선행) | | 수입검사 양식 | `docs/dev_plans/incoming-inspection-templates-plan.md` | 23개 양식 이관 | | DB 스키마 | `docs/specs/database-schema.md` | 테이블 구조 | | mng 규칙 | `mng/CLAUDE.md` | mng 프로젝트 규칙 | | API 규칙 | `API_RULES.md` | Service-First, FormRequest | --- *이 문서는 /plan 스킬로 생성되었습니다. v2: SuperClaude 페르소나 리뷰 16건 정책 결정 반영 (2026-02-27)*