docs: [통합계획] 제품코드 추적성 + 검사 단위 구조 통합 계획 수립
- integrated-master-plan.md: 7 Phase 통합 마스터 (의존성 맵, 진행 관리) - integrated-phase-0-1.md: 사전 조사 + product_code 전파 수정 상세 - integrated-phase-2.md: 절곡 분석/설계 + 견적/품질 개선 상세 - integrated-phase-3.md: 절곡 검사 동적 구현 상세 - 원본 2개 문서 아카이브 전환 (통합 문서 링크 추가) - INDEX.md 통합 문서 등록
This commit is contained in:
6
INDEX.md
6
INDEX.md
@@ -155,6 +155,12 @@ docs/
|
||||
| [SAM_ERP_회계관리_Storyboard_D1.6.md](plans/SAM_ERP_회계관리_Storyboard_D1.6.md) | ERP 회계관리 스토리보드 D1.6 (65p PDF → 마크다운 변환) |
|
||||
| [SAM_General_Rule_Storyboard_D1.0.md](plans/SAM_General_Rule_Storyboard_D1.0.md) | General Rule 스토리보드 D1.0 (43p PDF → 마크다운 변환, UIUX 공통 규칙) |
|
||||
| [production-deployment-plan.md](plans/production-deployment-plan.md) | 운영 환경 배포 계획 (CI/CD, 서버 아키텍처) |
|
||||
| **[integrated-master-plan.md](plans/integrated-master-plan.md)** | **통합 개선 계획 — 제품코드 추적성 + 검사 단위 구조 (마스터)** |
|
||||
| [integrated-phase-0-1.md](plans/integrated-phase-0-1.md) | 통합 Phase 0-1: 사전 조사 + product_code 전파 수정 |
|
||||
| [integrated-phase-2.md](plans/integrated-phase-2.md) | 통합 Phase 2: 절곡 검사 분석/설계 + 견적/품질 개선 |
|
||||
| [integrated-phase-3.md](plans/integrated-phase-3.md) | 통합 Phase 3: 절곡 검사 동적 구현 |
|
||||
| [product-code-traceability-plan.md](plans/product-code-traceability-plan.md) | 제품코드 추적성 계획 (아카이브 — 통합 계획 참조) |
|
||||
| [document-system-improvement-plan.md](plans/document-system-improvement-plan.md) | 검사 단위 구조 정비 계획 (아카이브 — 통합 계획 참조) |
|
||||
|
||||
### features/ - 기능별 문서
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# 문서 시스템 개선 계획 — 검사 단위 구조 정비
|
||||
|
||||
> **⚠️ 이 문서는 아카이브 참조용입니다. 통합 계획은 [`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)
|
||||
> **상태**: 🔄 v2 리뷰 반영 완료, 실행 대기
|
||||
> **상태**: 📦 통합 계획으로 이관 (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건)
|
||||
|
||||
|
||||
378
plans/integrated-master-plan.md
Normal file
378
plans/integrated-master-plan.md
Normal file
@@ -0,0 +1,378 @@
|
||||
# 통합 개선 계획 — 제품코드 추적성 + 검사 단위 구조 정비
|
||||
|
||||
> **작성일**: 2026-02-27
|
||||
> **목적**: 두 개선 계획(제품코드 추적성, 검사 단위 구조)을 하나의 순차적 실행 계획으로 통합
|
||||
> **상태**: 🔄 통합 계획 수립 완료, Phase 0 실행 대기
|
||||
> **원본 문서**:
|
||||
> - [`product-code-traceability-plan.md`](./product-code-traceability-plan.md) (아카이브 참조)
|
||||
> - [`document-system-improvement-plan.md`](./document-system-improvement-plan.md) (아카이브 참조)
|
||||
> - [`document-system-improvement-review.md`](./document-system-improvement-review.md) (정책 결정 16건)
|
||||
|
||||
---
|
||||
|
||||
## 📍 현재 진행 상태
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **마지막 완료 작업** | 통합 계획 수립 + 원본 2개 문서 분석 |
|
||||
| **다음 작업** | Phase 0 - 사전 데이터 조사 |
|
||||
| **진행률** | 0/7 Phase (0%) |
|
||||
| **마지막 업데이트** | 2026-02-27 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 왜 통합이 필요한가
|
||||
|
||||
두 계획은 **의존성이 교차**한다:
|
||||
|
||||
- 검사 단위 구조 정비(절곡 동적화)는 `work_order_items.options`에 `product_code`가 있어야 동작
|
||||
- `product_code` 전파 버그를 먼저 수정하지 않으면 검사 API(`inspection-config`)가 불완전
|
||||
- 별도로 작업하면 순서 혼선, 중복 작업, 회귀 위험 발생
|
||||
|
||||
**통합 효과**:
|
||||
- 의존성 순서를 강제하여 작업 꼬임 방지
|
||||
- 병렬 가능 작업 식별으로 효율 극대화
|
||||
- 진행 상태를 한 곳에서 관리
|
||||
|
||||
---
|
||||
|
||||
## 2. 통합 Phase 총괄
|
||||
|
||||
| Phase | 명칭 | 원본 | 의존성 | 상태 | 상세 |
|
||||
|:-----:|------|------|--------|:----:|------|
|
||||
| **0** | 사전 데이터 조사 | product-code P0 | 없음 | ⏳ | [Phase 0-1 상세](./integrated-phase-0-1.md) |
|
||||
| **1** | product_code 전파 버그 수정 | product-code P1 | Phase 0 | ⏳ | [Phase 0-1 상세](./integrated-phase-0-1.md) |
|
||||
| **2A** | 절곡 검사 분석/설계 | document-system P1 | 없음 (**Phase 1과 병렬**) | ⏳ | [Phase 2 상세](./integrated-phase-2.md) |
|
||||
| **2B** | 견적/수주 정합성 + 품질 FK | product-code P2+P3 | Phase 1 | ⏳ | [Phase 2 상세](./integrated-phase-2.md) |
|
||||
| **3** | 절곡 검사 동적 구현 | document-system P2 | Phase 1 + 2A | ⏳ | [Phase 3 상세](./integrated-phase-3.md) |
|
||||
| **4** | 절곡 재공품 + 결재 워크플로우 | document-system P3 | Phase 3 | ⏭️ | 마스터 요약만 |
|
||||
| **5** | 완제품 마스터 + 출하 연결 | product-code P4 | Phase 2B | ⏭️ | 마스터 요약만 |
|
||||
| **6** | 3관점 검사 + 수주별 뷰 | document-system P4 | Phase 3 + 기획자 | ⏭️ | 마스터 요약만 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 의존성 다이어그램
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 실행 타임라인 │
|
||||
└─────────────────────────────────────────────┘
|
||||
|
||||
Phase 0 ─── Phase 1 ──┬── Phase 2B ──── Phase 5
|
||||
(조사) (P/C 수정) │ (견적/품질) (FG 마스터)
|
||||
│
|
||||
Phase 2A ──────────────┼── Phase 3 ──── Phase 4 ──── Phase 6
|
||||
(절곡 분석) │ (절곡 구현) (재공품) (3관점)
|
||||
│
|
||||
※ Phase 1 + 2A 병렬 가능
|
||||
※ Phase 2B + 3 준비 부분 병렬 가능
|
||||
※ Phase 4 + 5 독립 (부분 병렬 가능)
|
||||
|
||||
크리티컬 패스: Phase 0 → 1 → 3 → 4 → 6
|
||||
```
|
||||
|
||||
### 병렬 실행 가능 조합
|
||||
|
||||
| 조합 | 설명 | 조건 |
|
||||
|------|------|------|
|
||||
| Phase 1 + 2A | product_code 수정 + 절곡 분석 동시 진행 | 2A는 코드 변경 없음 (분석만) |
|
||||
| Phase 2B + 3 시작 | 견적/품질 + 절곡 구현 | Phase 1 완료 필수 |
|
||||
| Phase 4 + 5 | 절곡 재공품 + FG 마스터 | 각각 Phase 3, 2B 완료 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 공통 원칙
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 🎯 통합 핵심 원칙 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 1. 컬럼 추가 정책: FK/조인키만 컬럼, 나머지는 options JSON │
|
||||
│ 2. 기존 데이터 보존: 파괴적 변경 없이 점진적 개선 │
|
||||
│ 3. 역추적 가능: 어떤 단계에서든 원래 제품코드로 돌아갈 수 있어야 함│
|
||||
│ 4. 네이밍 통일: Backend JSON=snake_case, Frontend=camelCase │
|
||||
│ 5. 기존 동작 보존: 스크린/슬랫/조인트바 검사는 건드리지 않음 │
|
||||
│ 6. TemplateInspectionContent 통합: 신규 개발은 여기서 (C3) │
|
||||
│ 7. BendingInspectionContent 레거시 동결: 유지만, 신규 기능 X │
|
||||
│ 8. row_index = 개소 통일: 구성품은 field_key 인코딩 (C1) │
|
||||
│ 9. EAV + options 병행: 두 데이터 경로 독립 운용 (C2) │
|
||||
│ 10. 롤백 = 템플릿 유무: document_template_id NULL → 레거시 (I4) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 변경 승인 정책
|
||||
|
||||
| 분류 | 예시 | 승인 |
|
||||
|------|------|------|
|
||||
| ✅ 즉시 가능 | options JSON 필드 추가, React 컴포넌트 내부 리팩토링, 프론트 표시 변경 | 불필요 |
|
||||
| ⚠️ 컨펌 필요 | 서비스 로직 변경, 마이그레이션, API 엔드포인트 추가, 양식 시더 수정 | **필수** |
|
||||
| 🔴 금지 | 기존 테이블 컬럼 삭제, 기존 스크린/슬랫 검사 로직 변경 | 별도 협의 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 핵심 데이터 흐름 (통합 TO-BE)
|
||||
|
||||
```
|
||||
견적(quotes)
|
||||
└─ product_code 컬럼 ✅ (Phase 2B)
|
||||
└─ calculation_inputs → items[].productCode
|
||||
│
|
||||
▼ (createFromQuote)
|
||||
수주(orders)
|
||||
└─ order_nodes.options → ✅ product_code, product_name
|
||||
│
|
||||
▼ (createProductionOrder)
|
||||
작업지시(work_orders)
|
||||
├─ work_order_items.options → ✅ product_code (Phase 1 수정)
|
||||
├─ inspection-config API → ✅ 공정 자동 판별 + BOM 기반 구성품 (Phase 3)
|
||||
├─ TemplateInspectionContent → ✅ 동적 절곡 검사 (Phase 3)
|
||||
└─ document_data EAV → ✅ C1 field_key 인코딩
|
||||
│
|
||||
▼
|
||||
품질검사(inspections)
|
||||
└─ ✅ work_order_id FK (Phase 2B)
|
||||
│
|
||||
▼
|
||||
출하(shipments)
|
||||
└─ ✅ product_code 포함 (Phase 5)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Phase별 요약
|
||||
|
||||
### Phase 0: 사전 데이터 조사 ⏳
|
||||
|
||||
**목표**: 마이그레이션 영향 범위 파악 (읽기 전용, 위험 없음)
|
||||
|
||||
- SQL 4개 실행: order_nodes product_code 보유율, work_order_items source 비율, soft delete 건수, lot_no 중복
|
||||
- 결과에 따라 Phase 1 보정 전략 조정
|
||||
|
||||
→ [상세: integrated-phase-0-1.md](./integrated-phase-0-1.md)
|
||||
|
||||
---
|
||||
|
||||
### Phase 1: product_code 전파 버그 수정 ⏳
|
||||
|
||||
**목표**: 모든 work_order_items 생성/수정 경로에서 product_code, product_name 전달
|
||||
|
||||
- 백엔드 5개 코드 경로 수정 (OrderService, WorkOrderService)
|
||||
- 기존 데이터 보정 마이그레이션 (스냅샷 백업 후)
|
||||
- 프론트 WorkerScreen/ProductionDashboard에 제품코드 표시
|
||||
- **배포 순서**: 백엔드 → 마이그레이션 → 프론트
|
||||
|
||||
→ [상세: integrated-phase-0-1.md](./integrated-phase-0-1.md)
|
||||
|
||||
---
|
||||
|
||||
### Phase 2A: 절곡 검사 분석/설계 ⏳ (**Phase 1과 병렬 가능**)
|
||||
|
||||
**목표**: 절곡 구성품(검사 항목) 정보를 API에서 제공하는 구조 설계
|
||||
|
||||
- items/BOM 테이블에서 KWE01/KSS01/KSS02 구성품 확인
|
||||
- 마감유형(S1/S2/S3)별 차이 분석
|
||||
- DEFAULT_GAP_PROFILES 기준치 5130 대조
|
||||
- inspection-config 범용 API 설계
|
||||
|
||||
→ [상세: integrated-phase-2.md](./integrated-phase-2.md)
|
||||
|
||||
---
|
||||
|
||||
### Phase 2B: 견적/수주 정합성 + 품질 FK ⏳
|
||||
|
||||
**목표**: quotes.product_code 활용 + inspections ↔ work_orders FK 연결
|
||||
|
||||
- 견적 저장 시 quotes.product_code 저장
|
||||
- inspections 테이블에 work_order_id FK 마이그레이션
|
||||
- 기존 데이터 보정 (lot_no 기반 역추적)
|
||||
- **Phase 2B 내부에서 견적/품질 작업은 병렬 가능** (독립 경로)
|
||||
|
||||
→ [상세: integrated-phase-2.md](./integrated-phase-2.md)
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: 절곡 검사 동적 구현 ⏳
|
||||
|
||||
**목표**: API 기반 동적 구성품 로딩으로 고정 로직 대체
|
||||
|
||||
- inspection-config API 구현 (BelongsToTenant 필수)
|
||||
- TemplateInspectionContent buildBendingProducts → API 연동
|
||||
- document_data EAV 저장/복원 검증 (C1 field_key)
|
||||
- createInspectionDocument 트랜잭션 보강 (I2)
|
||||
- 레거시(Path A) + 신규(Path B) 독립 동작 확인
|
||||
|
||||
→ [상세: integrated-phase-3.md](./integrated-phase-3.md)
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: 절곡 재공품 + 결재 워크플로우 ⏭️
|
||||
|
||||
**목표**: BendingWip 양식 추가 + 결재 프론트 연동
|
||||
|
||||
| # | 작업 항목 | 비고 |
|
||||
|---|----------|------|
|
||||
| 4.1 | 절곡 재공품 mng 양식 시더 추가 | BendingWipInspectionContent 대응 |
|
||||
| 4.2 | 결재 워크플로우 프론트 연동 | 작성→검토→승인 3단계 |
|
||||
| 4.3 | React 기존 하드코딩 컴포넌트 전환 결정 | 프론트 담당자 협의 |
|
||||
|
||||
> 실행 시점에 상세 문서 별도 작성
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: 완제품 마스터 + 출하 연결 ⏭️
|
||||
|
||||
**목표**: FG 품목 등록 + 출하 시 제품코드 포함 + orders.item_id
|
||||
|
||||
| # | 작업 항목 | 비고 |
|
||||
|---|----------|------|
|
||||
| 5.1 | 완제품(FG) 품목 자동 등록 방안 설계 | 견적 확정 시 or 수주 확정 시 |
|
||||
| 5.2 | orders.item_id 설정 | FG 품목 등록 후 가능 |
|
||||
| 5.3 | shipment_items에 product_code 포함 | 부분 출하 시 개소별 매핑 고려 |
|
||||
| 5.4 | work_order_items.product_code 컬럼 승격 검토 | 통계 쿼리 성능용 |
|
||||
| 5.5 | E2E 추적 검증 | 견적→출하→품질 전 구간 |
|
||||
|
||||
> 실행 시점에 상세 문서 별도 작성
|
||||
|
||||
---
|
||||
|
||||
### Phase 6: 3관점 검사 + 수주별 뷰 ⏭️
|
||||
|
||||
**목표**: 구성품별/개소별/수주별 3관점 검사 구조 + 수주별 읽기 전용 뷰
|
||||
|
||||
| # | 작업 항목 | 비고 |
|
||||
|---|----------|------|
|
||||
| 6.1 | 기획자와 3관점 화면 설계 협의 (I3) | 화면 구성·데이터 매핑·UI 설계 |
|
||||
| 6.2 | 수주별 읽기 전용 뷰 구현 (I7) | 입력=개소별, 출력=수주별 |
|
||||
| 6.3 | 개소별↔구성품별↔수주별 데이터 매핑 | |
|
||||
| 6.4 | 5130 recordscreen JSON → EAV 변환 | 이관 설계 |
|
||||
|
||||
> 기획자 협의 후 상세 문서 별도 작성
|
||||
|
||||
---
|
||||
|
||||
## 7. 통합 성공 기준
|
||||
|
||||
### Phase 0-1 (product_code)
|
||||
|
||||
| 기준 | 수치 목표 |
|
||||
|------|----------|
|
||||
| WorkerScreen 제품코드 표시 | 100% |
|
||||
| 신규 작업지시 product_code 포함 | NOT NULL |
|
||||
| 기존 데이터 보정율 (source_order_item_id 있는 건) | 90% 이상 |
|
||||
| 기존 기능 회귀 | 에러 0건 |
|
||||
| API 성능 영향 | 5% 미만 |
|
||||
|
||||
### Phase 2A-2B (분석/견적/품질)
|
||||
|
||||
| 기준 | 수치 목표 |
|
||||
|------|----------|
|
||||
| KWE01/KSS01/KSS02 구성품 분석 완료 | 3종 이상 |
|
||||
| DEFAULT_GAP_PROFILES 5130 대조 | 완료 |
|
||||
| quotes.product_code 저장 | 정상 동작 |
|
||||
| inspections.work_order_id FK 보정 정확도 | 95% 이상 |
|
||||
|
||||
### Phase 3 (절곡 동적 구현)
|
||||
|
||||
| 기준 | 수치 목표 |
|
||||
|------|----------|
|
||||
| 제품코드별 다른 구성품 표시 | 3종 이상 지원 |
|
||||
| 마감유형별 구성품 변경 | 정상 동작 |
|
||||
| 기존 절곡 데이터 호환 (Path A + B) | 100% |
|
||||
| inspection-config API 응답 시간 | < 200ms |
|
||||
| 스크린/슬랫 회귀 | 에러 0건 |
|
||||
| document_data 저장 정합성 | 100% |
|
||||
|
||||
---
|
||||
|
||||
## 8. 통합 컨펌 대기 목록
|
||||
|
||||
| # | Phase | 항목 | 변경 내용 | 상태 |
|
||||
|---|:-----:|------|----------|:----:|
|
||||
| 1 | 0 | 사전 조사 실행 | SQL 4개 (읽기 전용) | ⚠️ 대기 |
|
||||
| 2 | 1 | product_code 전파 수정 | 5개 코드 경로 options 복사 변경 | ⚠️ 대기 |
|
||||
| 3 | 1 | 데이터 보정 마이그레이션 | 기존 work_order_items 역추적 보정 | ⚠️ 대기 |
|
||||
| 4 | 2A | inspection-config API 설계 | 범용 API 엔드포인트 추가 | ⚠️ 대기 |
|
||||
| 5 | 2B | inspections.work_order_id FK | 마이그레이션 + 로직 수정 | ⚠️ 대기 |
|
||||
| 6 | 3 | inspection-config API 구현 | 공정 자동 판별 + BOM 구성품 | ⚠️ 대기 |
|
||||
| 7 | 5 | 완제품 마스터 자동 등록 | items 테이블에 FG 품목 생성 | ⚠️ 대기 |
|
||||
| 8 | 6 | 3관점 검사 화면 설계 | 기획자 협의 필요 | ⏭️ |
|
||||
|
||||
---
|
||||
|
||||
## 9. 롤백 전략 (통합)
|
||||
|
||||
| Phase | 위험도 | 롤백 방법 |
|
||||
|:-----:|:------:|----------|
|
||||
| 0 | 없음 | 읽기 전용 |
|
||||
| 1 (options 추가) | 낮음 | options에서 `product_code`, `product_name` 키 제거 스크립트 |
|
||||
| 1 (데이터 보정) | 중간 | `work_order_items_backup_product_code` 백업 테이블에서 복원 |
|
||||
| 2B (inspections FK) | 중간 | `work_order_id` 컬럼 drop 마이그레이션 (down 메서드) |
|
||||
| 3 (절곡 동적화) | 낮음 | document_template_id NULL → 레거시 컴포넌트 자동 복귀 (I4) |
|
||||
| 5 (FG 품목) | 높음 | `auto_generated` 플래그 기반 식별 후 삭제 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 참고 파일 (통합)
|
||||
|
||||
### 백엔드
|
||||
|
||||
| 파일 | 역할 | 관련 Phase |
|
||||
|------|------|:----------:|
|
||||
| `api/app/Services/OrderService.php` | 수주→작업지시 변환 (L1410) | 1 |
|
||||
| `api/app/Services/WorkOrderService.php` | 작업지시 서비스 (L287, L311, L416) | 1, 3 |
|
||||
| `api/app/Services/Quote/QuoteService.php` | 견적 서비스 | 2B |
|
||||
| `api/app/Services/InspectionService.php` | 품질검사 서비스 | 2B |
|
||||
| `api/app/Services/DocumentService.php` | 문서 CRUD | 3 |
|
||||
|
||||
### 프론트엔드
|
||||
|
||||
| 파일 | 역할 | 관련 Phase |
|
||||
|------|------|:----------:|
|
||||
| `react/.../WorkerScreen/actions.ts` | 작업자 화면 서버 액션 | 1 |
|
||||
| `react/.../WorkerScreen/index.tsx` | 작업자 화면 메인 | 1 |
|
||||
| `react/.../documents/TemplateInspectionContent.tsx` | 양식 기반 동적 렌더링 (**통합 방향**) | 3 |
|
||||
| `react/.../documents/BendingInspectionContent.tsx` | 절곡 레거시 (**동결**) | — |
|
||||
| `react/.../documents/InspectionReportModal.tsx` | 검사 모달 래퍼 | 3 |
|
||||
|
||||
### 참고 문서
|
||||
|
||||
| 문서 | 경로 | 용도 |
|
||||
|------|------|------|
|
||||
| 원본: 제품코드 추적성 | `docs/plans/product-code-traceability-plan.md` | 상세 코드/쿼리 참조 |
|
||||
| 원본: 검사 단위 구조 | `docs/plans/document-system-improvement-plan.md` | 상세 설계/정책 참조 |
|
||||
| 리뷰 정책 결정 | `docs/plans/document-system-improvement-review.md` | 16건 정책 결정 |
|
||||
| 문서 시스템 마스터 | `docs/plans/document-system-master.md` | 전체 Phase 관리 |
|
||||
| API 규칙 | `API_RULES.md` | Service-First, FormRequest |
|
||||
| DB 스키마 | `docs/specs/database-schema.md` | 테이블 구조 |
|
||||
|
||||
---
|
||||
|
||||
## 11. 변경 이력
|
||||
|
||||
| 날짜 | 항목 | 변경 내용 |
|
||||
|------|------|----------|
|
||||
| 2026-02-27 | 통합 문서 작성 | product-code + document-system 2개 계획을 7 Phase 통합 계획으로 병합 |
|
||||
|
||||
---
|
||||
|
||||
## 12. 세션 관리 정책
|
||||
|
||||
### 세션 시작 시
|
||||
```
|
||||
1. 이 문서(integrated-master-plan.md) 읽기
|
||||
2. 진행 상태 테이블 확인 → 마지막 완료 작업 파악
|
||||
3. 해당 Phase 상세 문서 읽기
|
||||
4. 다음 작업 시작
|
||||
```
|
||||
|
||||
### 작업 중 관리
|
||||
- Phase 완료 시 이 문서의 진행 상태 테이블 업데이트
|
||||
- 해당 Phase 상세 문서도 업데이트
|
||||
- 컨펌 필요 사항 발생 시 컨펌 대기 목록에 추가
|
||||
|
||||
### 세션 종료 시
|
||||
- 변경 이력 섹션에 최종 업데이트 기록
|
||||
|
||||
---
|
||||
|
||||
*이 문서는 `product-code-traceability-plan.md`와 `document-system-improvement-plan.md`를 통합한 마스터 계획입니다.*
|
||||
305
plans/integrated-phase-0-1.md
Normal file
305
plans/integrated-phase-0-1.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# Phase 0-1: 사전 조사 + product_code 전파 수정
|
||||
|
||||
> **통합 계획**: [`integrated-master-plan.md`](./integrated-master-plan.md)
|
||||
> **원본**: [`product-code-traceability-plan.md`](./product-code-traceability-plan.md) Phase 0, 1
|
||||
> **상태**: ⏳ 실행 대기
|
||||
> **의존성**: 없음 (최초 시작 Phase)
|
||||
|
||||
---
|
||||
|
||||
## 📍 진행 상태
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| **다음 작업** | Phase 0 - SQL 4개 실행 |
|
||||
| **진행률** | 0% |
|
||||
| **마지막 업데이트** | 2026-02-27 |
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: 사전 데이터 조사
|
||||
|
||||
**목표**: 마이그레이션 영향 범위 파악 (읽기 전용, 위험 없음)
|
||||
|
||||
### 작업 항목
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 0.1 | `order_nodes.options`에 `product_code` 보유율 조사 | ⏳ | SQL 쿼리 |
|
||||
| 0.2 | `work_order_items`에서 `source_order_item_id` NULL 비율 조사 | ⏳ | 보정 불가 건수 파악 |
|
||||
| 0.3 | soft deleted된 `order_items`/`order_nodes` 건수 조사 | ⏳ | withTrashed 필요 여부 |
|
||||
| 0.4 | `stock_lots.lot_no` 중복 건수 조사 | ⏳ | Phase 2B 역추적 신뢰성 |
|
||||
|
||||
### 조사 쿼리
|
||||
|
||||
```sql
|
||||
-- 0.1: order_nodes의 product_code 보유율
|
||||
SELECT COUNT(*) as total,
|
||||
SUM(CASE WHEN JSON_EXTRACT(options, '$.product_code') IS NOT NULL THEN 1 ELSE 0 END) as has_code,
|
||||
ROUND(SUM(CASE WHEN JSON_EXTRACT(options, '$.product_code') IS NOT NULL THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) as pct
|
||||
FROM order_nodes WHERE deleted_at IS NULL;
|
||||
|
||||
-- 0.2: work_order_items의 source_order_item_id NULL 비율
|
||||
SELECT COUNT(*) as total,
|
||||
SUM(CASE WHEN source_order_item_id IS NULL THEN 1 ELSE 0 END) as no_source,
|
||||
ROUND(SUM(CASE WHEN source_order_item_id IS NULL THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) as pct
|
||||
FROM work_order_items WHERE deleted_at IS NULL;
|
||||
|
||||
-- 0.3: soft deleted된 원본 데이터
|
||||
SELECT 'order_items' as tbl, COUNT(*) as deleted_count FROM order_items WHERE deleted_at IS NOT NULL
|
||||
UNION ALL
|
||||
SELECT 'order_nodes', COUNT(*) FROM order_nodes WHERE deleted_at IS NOT NULL;
|
||||
|
||||
-- 0.4: lot_no 중복 확인
|
||||
SELECT lot_no, COUNT(*) as cnt FROM stock_lots
|
||||
WHERE deleted_at IS NULL GROUP BY lot_no HAVING COUNT(*) > 1;
|
||||
```
|
||||
|
||||
### 검증 결과
|
||||
|
||||
| 조사 항목 | 결과 | 판단 |
|
||||
|----------|------|------|
|
||||
| order_nodes product_code 보유율 | | ⏳ |
|
||||
| work_order_items source NULL 비율 | | ⏳ |
|
||||
| soft deleted 원본 건수 | | ⏳ |
|
||||
| lot_no 중복 건수 | | ⏳ |
|
||||
|
||||
> Phase 0 결과에 따라 Phase 1 보정 전략 조정
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: product_code 전파 버그 수정
|
||||
|
||||
**목표**: 모든 `work_order_items` 생성/수정 경로에서 `product_code`, `product_name` 전달
|
||||
|
||||
### 작업 항목
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 1.1 | `OrderService::createProductionOrder` options 복사 수정 | ⏳ | L1410-1419 |
|
||||
| 1.2 | `WorkOrderService::store` 수주복사 로직 수정 | ⏳ | L287-296 |
|
||||
| 1.3 | `WorkOrderService::store` 직접 입력 경로 확인 | ⏳ | L311-317 (프론트 전달 의존) |
|
||||
| 1.4 | `WorkOrderService::update` 품목 수정 시 options 보존 확인 | ⏳ | L416-438 |
|
||||
| 1.5 | 기존 데이터 보정 마이그레이션 | ⏳ | 스냅샷 백업 후 실행 |
|
||||
| 1.6 | 프론트 WorkerScreen에 제품코드 표시 | ⏳ | actions.ts + index.tsx |
|
||||
| 1.7 | 프론트 ProductionDashboard에 제품코드 표시 | ⏳ | actions.ts |
|
||||
|
||||
---
|
||||
|
||||
### 1.1 백엔드 수정 — 5개 경로
|
||||
|
||||
#### 경로 1: `OrderService::createProductionOrder` (L1410-1419)
|
||||
|
||||
현재 코드:
|
||||
```php
|
||||
$woItemOptions = array_filter([
|
||||
'floor' => $orderItem->floor_code,
|
||||
'code' => $orderItem->symbol_code,
|
||||
'width' => $nodeOptions['width'] ?? $nodeOptions['open_width'] ?? null,
|
||||
'height' => $nodeOptions['height'] ?? $nodeOptions['open_height'] ?? null,
|
||||
'cutting_info' => $nodeOptions['cutting_info'] ?? null,
|
||||
'slat_info' => $slatInfo,
|
||||
'bending_info' => $nodeOptions['bending_info'] ?? null,
|
||||
'wip_info' => $nodeOptions['wip_info'] ?? null,
|
||||
], fn ($v) => $v !== null);
|
||||
```
|
||||
|
||||
수정 후:
|
||||
```php
|
||||
$woItemOptions = array_filter([
|
||||
'floor' => $orderItem->floor_code,
|
||||
'code' => $orderItem->symbol_code,
|
||||
'product_code' => !empty($nodeOptions['product_code']) ? $nodeOptions['product_code'] : null,
|
||||
'product_name' => !empty($nodeOptions['product_name']) ? $nodeOptions['product_name'] : null,
|
||||
'width' => $nodeOptions['width'] ?? $nodeOptions['open_width'] ?? null,
|
||||
'height' => $nodeOptions['height'] ?? $nodeOptions['open_height'] ?? null,
|
||||
'cutting_info' => $nodeOptions['cutting_info'] ?? null,
|
||||
'slat_info' => $slatInfo,
|
||||
'bending_info' => $nodeOptions['bending_info'] ?? null,
|
||||
'wip_info' => $nodeOptions['wip_info'] ?? null,
|
||||
], fn ($v) => $v !== null);
|
||||
```
|
||||
|
||||
> `!empty()` 사용으로 빈 문자열("")도 필터링
|
||||
|
||||
#### 경로 2: `WorkOrderService::store` 수주복사 (L287-296)
|
||||
|
||||
경로 1과 동일하게 `product_code`, `product_name` 추가.
|
||||
|
||||
> **⚠️ 주의**: 이 경로는 OrderService와 달리 `slat_info` 자동계산 로직이 없음 (별도 이슈 추적)
|
||||
|
||||
#### 경로 3: `WorkOrderService::store` 직접 입력 (L311-317)
|
||||
|
||||
프론트에서 `items[].options`에 product_code 포함 전달. 수동 생성이므로 product_code **nullable 허용**.
|
||||
|
||||
#### 경로 4: `WorkOrderService::update` 품목 수정 (L416-438)
|
||||
|
||||
기존 options 보존 여부 점검:
|
||||
- `update(['item_name' => ...])` 식 → options 보존됨 (OK)
|
||||
- `items()->updateOrCreate(...)` 패턴 → options 소실 위험 → **점검 필요**
|
||||
|
||||
#### 경로 5: `WorkOrderService::update` 품목 신규 추가 (L435)
|
||||
|
||||
경로 3과 동일 — 프론트 전달 의존. nullable 허용.
|
||||
|
||||
---
|
||||
|
||||
### 1.2 기존 데이터 보정 마이그레이션
|
||||
|
||||
```php
|
||||
// ⚠️ 보정 전 스냅샷 백업
|
||||
DB::statement('CREATE TABLE IF NOT EXISTS work_order_items_backup_product_code
|
||||
AS SELECT id, options FROM work_order_items');
|
||||
|
||||
// ⚠️ BelongsToTenant 글로벌 스코프 우회 + SoftDeletes 포함
|
||||
WorkOrderItem::withoutGlobalScopes()
|
||||
->whereNull(DB::raw("JSON_EXTRACT(options, '$.product_code')"))
|
||||
->whereNotNull('source_order_item_id')
|
||||
->chunk(100, function ($items) {
|
||||
// bulk 조회로 N+1 방지
|
||||
$orderItemIds = $items->pluck('source_order_item_id')->filter()->unique();
|
||||
$orderItems = OrderItem::withTrashed()
|
||||
->with(['orderNode' => fn($q) => $q->withTrashed()])
|
||||
->whereIn('id', $orderItemIds)
|
||||
->get()
|
||||
->keyBy('id');
|
||||
|
||||
foreach ($items as $item) {
|
||||
$orderItem = $orderItems->get($item->source_order_item_id);
|
||||
if ($orderItem?->orderNode) {
|
||||
$nodeOptions = $orderItem->orderNode->options ?? [];
|
||||
$productCode = !empty($nodeOptions['product_code']) ? $nodeOptions['product_code'] : null;
|
||||
$productName = !empty($nodeOptions['product_name']) ? $nodeOptions['product_name'] : null;
|
||||
if ($productCode) {
|
||||
$options = $item->options ?? [];
|
||||
$options['product_code'] = $productCode;
|
||||
if ($productName) $options['product_name'] = $productName;
|
||||
$item->updateQuietly(['options' => $options]); // 이벤트 미발생
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 보정 결과 로그
|
||||
$total = WorkOrderItem::withoutGlobalScopes()->whereNull('deleted_at')->count();
|
||||
$withCode = WorkOrderItem::withoutGlobalScopes()
|
||||
->whereNull('deleted_at')
|
||||
->whereNotNull(DB::raw("JSON_EXTRACT(options, '$.product_code')"))
|
||||
->count();
|
||||
Log::info("product_code 보정 완료: {$withCode}/{$total}");
|
||||
```
|
||||
|
||||
> `source_order_item_id`가 NULL인 건: 수동 생성 작업지시로 보정 불가. Phase 0 조사에서 건수 파악 후 감수 범위로 문서화.
|
||||
|
||||
---
|
||||
|
||||
### 1.3 프론트엔드 수정
|
||||
|
||||
**WorkerScreen/actions.ts** — API 응답에서 productCode 매핑:
|
||||
```typescript
|
||||
const productCode = api.items?.[0]?.options?.product_code || '-';
|
||||
const productName = api.items?.[0]?.options?.product_name || api.items?.[0]?.item_name || '-';
|
||||
```
|
||||
|
||||
**WorkerScreen/index.tsx** — 작업 카드에 제품코드 표시:
|
||||
```typescript
|
||||
itemName: productCode !== '-' ? `${productCode} - ${productName}` : productName,
|
||||
```
|
||||
|
||||
**ProductionDashboard/actions.ts** — 동일 적용.
|
||||
|
||||
> **다중 개소**: items[0]만 가져오므로 다중 개소 시 첫 번째만 표시. 향후 UI 개선 시 items 전체 순회 필요.
|
||||
|
||||
---
|
||||
|
||||
### 1.4 배포 순서
|
||||
|
||||
```
|
||||
백엔드 배포 (5개 경로 수정)
|
||||
↓
|
||||
마이그레이션 실행 (스냅샷 백업 → 보정)
|
||||
↓
|
||||
프론트엔드 배포 (WorkerScreen + Dashboard)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 검증 결과
|
||||
|
||||
### Phase 1 테스트 케이스
|
||||
|
||||
| 테스트 | 예상 결과 | 실제 결과 | 상태 |
|
||||
|--------|----------|----------|------|
|
||||
| 신규 작업지시 (OrderService 경로) | options에 product_code 포함 | | ⏳ |
|
||||
| 신규 작업지시 (WorkOrderService 수주복사) | options에 product_code 포함 | | ⏳ |
|
||||
| product_code NULL인 order_nodes | 오류 없이 NULL 저장 | | ⏳ |
|
||||
| product_code 빈 문자열 | empty 체크로 필터링 | | ⏳ |
|
||||
| 데이터 보정 (source 있는 건) | product_code 채워짐 | | ⏳ |
|
||||
| 데이터 보정 (source NULL) | skip, 오류 없음 | | ⏳ |
|
||||
| 데이터 보정 (soft deleted 원본) | withTrashed로 정상 조회 | | ⏳ |
|
||||
| WorkerScreen 표시 | "FG-KQTS01-측면형-SUS - 슬랫 방화" | | ⏳ |
|
||||
| WorkerScreen — product_code 없는 건 | productName만 표시 | | ⏳ |
|
||||
| 기존 API 회귀 테스트 | 작업지시 목록/상세 정상 응답 | | ⏳ |
|
||||
|
||||
### 데이터 검증 쿼리
|
||||
|
||||
```sql
|
||||
-- 보정 후 성공률
|
||||
SELECT COUNT(*) as total,
|
||||
COUNT(CASE WHEN JSON_EXTRACT(options, '$.product_code') IS NOT NULL THEN 1 END) as with_code,
|
||||
ROUND(COUNT(CASE WHEN JSON_EXTRACT(options, '$.product_code') IS NOT NULL THEN 1 END) * 100.0 / COUNT(*), 1) as pct
|
||||
FROM work_order_items WHERE deleted_at IS NULL;
|
||||
|
||||
-- 보정 데이터 정확도 (원본 대조)
|
||||
SELECT woi.id,
|
||||
JSON_EXTRACT(woi.options, '$.product_code') as wo_code,
|
||||
JSON_EXTRACT(onode.options, '$.product_code') as node_code,
|
||||
CASE WHEN JSON_EXTRACT(woi.options, '$.product_code') = JSON_EXTRACT(onode.options, '$.product_code')
|
||||
THEN 'MATCH' ELSE 'MISMATCH' END as status
|
||||
FROM work_order_items woi
|
||||
JOIN order_items oi ON woi.source_order_item_id = oi.id
|
||||
JOIN order_nodes onode ON oi.order_node_id = onode.id
|
||||
WHERE woi.deleted_at IS NULL
|
||||
AND JSON_EXTRACT(woi.options, '$.product_code') IS NOT NULL;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 참고 파일
|
||||
|
||||
### 백엔드
|
||||
|
||||
| 파일 | 역할 | 주요 위치 |
|
||||
|------|------|----------|
|
||||
| `api/app/Services/OrderService.php` | 수주→작업지시 변환 | `createProductionOrder` L1177, options L1410-1419 |
|
||||
| `api/app/Services/WorkOrderService.php` | 작업지시 서비스 | `store` L287-296, L311-317, `update` L416-438 |
|
||||
| `api/app/Models/Production/WorkOrderItem.php` | 작업지시 품목 모델 | options 캐스트 |
|
||||
| `api/app/Models/OrderNode.php` | 수주 노드 모델 | options 캐스트 |
|
||||
|
||||
### 프론트엔드
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `react/src/components/production/WorkerScreen/actions.ts` | 작업자 화면 서버 액션 |
|
||||
| `react/src/components/production/WorkerScreen/index.tsx` | 작업자 화면 메인 |
|
||||
| `react/src/components/production/ProductionDashboard/actions.ts` | 대시보드 서버 액션 |
|
||||
|
||||
### DB 테이블
|
||||
|
||||
| 테이블 | 핵심 컬럼/필드 |
|
||||
|--------|---------------|
|
||||
| `order_nodes` | options JSON: product_code, product_name |
|
||||
| `order_items` | order_node_id, item_id, floor_code |
|
||||
| `work_order_items` | source_order_item_id, options JSON (**수정 대상**) |
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 날짜 | 항목 | 변경 내용 |
|
||||
|------|------|----------|
|
||||
| 2026-02-27 | 문서 작성 | 통합 계획 Phase 0-1 상세 문서 작성 |
|
||||
|
||||
---
|
||||
|
||||
*이 문서는 [`integrated-master-plan.md`](./integrated-master-plan.md)의 Phase 0-1 상세입니다.*
|
||||
300
plans/integrated-phase-2.md
Normal file
300
plans/integrated-phase-2.md
Normal file
@@ -0,0 +1,300 @@
|
||||
# Phase 2: 절곡 검사 분석/설계 + 견적/품질 개선
|
||||
|
||||
> **통합 계획**: [`integrated-master-plan.md`](./integrated-master-plan.md)
|
||||
> **원본**:
|
||||
> - [`document-system-improvement-plan.md`](./document-system-improvement-plan.md) Phase 1
|
||||
> - [`product-code-traceability-plan.md`](./product-code-traceability-plan.md) Phase 2, 3
|
||||
> **상태**: ⏳ 실행 대기
|
||||
> **의존성**: Phase 2A는 독립 (Phase 1과 병렬 가능), Phase 2B는 Phase 1 완료 필수
|
||||
|
||||
---
|
||||
|
||||
## 1. Phase 2A: 절곡 검사 분석/설계
|
||||
|
||||
**목표**: 절곡 구성품(검사 항목) 정보를 API에서 제공하는 구조 설계
|
||||
**Phase 1과 병렬 가능** (분석 전용, 코드 변경 없음)
|
||||
|
||||
### 1.1 작업 항목
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 2A.1 | 절곡 제품코드별 구성품(BOM) 데이터 구조 분석 | ⏳ | `items`/BOM 테이블에서 KWE01/KSS01/KSS02 확인 |
|
||||
| 2A.2 | 마감유형(S1/S2/S3)별 차이 분석 | ⏳ | 5130 레거시 참조 |
|
||||
| 2A.3 | `inspection-config` 범용 API 설계 | ⏳ | `GET /api/v1/work-orders/{id}/inspection-config` (I5 정책) |
|
||||
| 2A.4 | `DEFAULT_GAP_PROFILES` 기준치 5130 대조 | ⏳ | I1: Single Source of Truth 보정 |
|
||||
|
||||
### 1.2 구성품 데이터 소스 분석 대상
|
||||
|
||||
```
|
||||
분석 대상:
|
||||
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 — 현재 기준치
|
||||
```
|
||||
|
||||
### 1.3 구성품 결정 로직 (설계안)
|
||||
|
||||
```
|
||||
입력: work_order_id
|
||||
↓
|
||||
1차: 작업지시 → 공정 자동 판별 (inspection-config API)
|
||||
↓
|
||||
2차: product_code → BOM 테이블에서 하위 구성품 조회
|
||||
↓ (BOM 미등록 시)
|
||||
3차: DEFAULT_GAP_PROFILES 기본값 사용
|
||||
↓ (템플릿 미설정 시 = 레거시)
|
||||
4차: INITIAL_PRODUCTS fallback (BendingInspectionContent, KWE01 하위호환)
|
||||
```
|
||||
|
||||
각 단계의 역할은 다음과 같다.
|
||||
|
||||
- **1차 (공정 판별)**: `work_order_id`로부터 작업지시의 공정 타입(`bending`, `screen`, `slat`)을 자동 판별한다. 비절곡 공정이면 빈 `items` 배열을 반환하고 종료한다.
|
||||
- **2차 (BOM 조회)**: 해당 제품코드의 BOM에 등록된 구성품 목록을 조회한다. BOM 데이터가 있으면 이를 기준으로 검사 항목을 구성한다.
|
||||
- **3차 (기본 프로파일)**: BOM에 구성품이 등록되지 않은 경우, `DEFAULT_GAP_PROFILES`에 정의된 기본 갭 기준치를 사용한다.
|
||||
- **4차 (레거시 fallback)**: 템플릿 설정도 없는 경우, 기존 `BendingInspectionContent`의 `INITIAL_PRODUCTS` 7개 항목을 KWE01 전용 하위호환으로 사용한다.
|
||||
|
||||
### 1.4 inspection-config API 설계안 (I5 정책 결정)
|
||||
|
||||
```
|
||||
GET /api/v1/work-orders/{id}/inspection-config
|
||||
|
||||
※ BelongsToTenant 스코프 필수 (M1)
|
||||
※ 공정 타입 자동 판별
|
||||
```
|
||||
|
||||
**절곡 Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"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": "1", "design_value": "30" },
|
||||
{ "point": "2", "design_value": "78" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**비절곡 Response (스크린/슬랫)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"work_order_id": 456,
|
||||
"process_type": "screen",
|
||||
"product_code": "FG-KQTS01",
|
||||
"template_id": 12,
|
||||
"items": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**응답 필드 설명**:
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `work_order_id` | `integer` | 작업지시 ID |
|
||||
| `process_type` | `string` | 공정 타입 (`bending`, `screen`, `slat`) |
|
||||
| `product_code` | `string` | 제품코드 |
|
||||
| `finish_type` | `string\|null` | 마감유형 (절곡 전용: `S1`, `S2`, `S3`) |
|
||||
| `template_id` | `integer\|null` | 검사 양식 ID |
|
||||
| `items` | `array` | 검사 대상 구성품 목록 (비절곡 시 빈 배열) |
|
||||
| `items[].id` | `string` | 구성품 식별자 (kebab-case) |
|
||||
| `items[].category` | `string` | 제품 카테고리 코드 |
|
||||
| `items[].product_name` | `string` | 구성품 명칭 |
|
||||
| `items[].product_type` | `string` | 구성품 유형/규격 |
|
||||
| `items[].length_design` | `string` | 설계 길이 |
|
||||
| `items[].width_design` | `string` | 설계 폭 (`N/A` 가능) |
|
||||
| `items[].gap_points` | `array` | 갭 측정 포인트 목록 |
|
||||
|
||||
### 1.5 현재 하드코딩 현황 (레거시 동결 -- C3)
|
||||
|
||||
`BendingInspectionContent.tsx`의 `INITIAL_PRODUCTS` (7개, KWE01 전용):
|
||||
|
||||
| # | 항목 ID | productName | productType | gapPoints 수 |
|
||||
|---|---------|-------------|-------------|:----------:|
|
||||
| 1 | `guide-rail-wall` | 가이드레일 | 벽면형 | 5 |
|
||||
| 2 | `guide-rail-side` | 가이드레일 | 측면형 | 5 |
|
||||
| 3 | `case` | 케이스 | 500X380 | 4 |
|
||||
| 4 | `bottom-finish` | 하단마감재 | 60X40 | 2 |
|
||||
| 5 | `bottom-l-bar` | 하단L-BAR | 17X60 | 1 |
|
||||
| 6 | `smoke-w50` | 연기차단재 | W50 가이드레일용 | 2 |
|
||||
| 7 | `smoke-w80` | 연기차단재 | W80 케이스용 | 2 |
|
||||
|
||||
Phase 2A 분석 완료 후, 이 하드코딩 항목들은 `inspection-config` API 응답으로 대체될 예정이다. 현재는 C3(레거시 동결) 정책에 따라 수정하지 않는다.
|
||||
|
||||
---
|
||||
|
||||
## 2. Phase 2B: 견적/수주 정합성 + 품질검사 FK
|
||||
|
||||
**목표**: `quotes.product_code` 활용 + `inspections` ↔ `work_orders` FK 연결
|
||||
**선행 조건**: Phase 1 완료
|
||||
**내부 병렬성**: 2B-견적과 2B-품질은 독립 경로
|
||||
|
||||
```
|
||||
Phase 2B 내부 구조:
|
||||
|
||||
Phase 1 완료
|
||||
|
|
||||
+----+----+
|
||||
| |
|
||||
2B-견적 2B-품질
|
||||
(2B.1~3) (2B.4~7)
|
||||
| |
|
||||
+----+----+
|
||||
|
|
||||
Phase 2B 완료
|
||||
```
|
||||
|
||||
### 2.1 견적 데이터 정합성 (원본 Phase 2)
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 2B.1 | 견적 저장 시 `quotes.product_code` 저장 | ⏳ | 다중 개소: 첫 번째 개소 코드 대표 저장 |
|
||||
| 2B.2 | 견적→수주 변환 시 `camelCase`→`snake_case` 변환 확인 | ⏳ | `OrderService::createFromQuote` |
|
||||
| 2B.3 | 기존 데이터 보정 스크립트 | ⏳ | `calculation_inputs`에서 추출 |
|
||||
|
||||
**다중 개소 정책**: `quotes.product_code`에는 첫 번째 개소 코드를 대표값으로 저장한다. 전체 목록은 `calculation_inputs.items[].productCode`를 참조한다.
|
||||
|
||||
**의존성 주의**: `orders.item_id` 설정은 `items` 테이블에 FG 품목 등록이 필요하므로 Phase 5에서 처리한다.
|
||||
|
||||
**데이터 보정 스크립트 상세**:
|
||||
|
||||
```php
|
||||
// 2B.3 보정 로직 개요
|
||||
// quotes 테이블에서 product_code가 null인 레코드 대상
|
||||
// calculation_inputs JSON에서 items[0].productCode 추출하여 저장
|
||||
|
||||
$quotes = Quote::whereNull('product_code')
|
||||
->whereNotNull('calculation_inputs')
|
||||
->get();
|
||||
|
||||
foreach ($quotes as $quote) {
|
||||
$inputs = json_decode($quote->calculation_inputs, true);
|
||||
$productCode = $inputs['items'][0]['productCode'] ?? null;
|
||||
if ($productCode) {
|
||||
$quote->update(['product_code' => $productCode]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 품질검사 연결 강화 (원본 Phase 3)
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 2B.4 | `inspections` 테이블에 `work_order_id` FK 마이그레이션 | ⏳ | `nullable` |
|
||||
| 2B.5 | `Inspection` 모델에 `workOrder()` 관계 메서드 추가 | ⏳ | N+1 방지 |
|
||||
| 2B.6 | 품질검사 생성 시 `work_order_id` 설정 로직 | ⏳ | `InspectionService` |
|
||||
| 2B.7 | 기존 `inspections` 데이터에 `work_order_id` 보정 | ⏳ | `lot_no` 기반 역추적 (중복 사전 확인) |
|
||||
|
||||
**마이그레이션 설계 (2B.4)**:
|
||||
|
||||
```php
|
||||
Schema::table('inspections', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('work_order_id')->nullable()->after('id');
|
||||
$table->foreign('work_order_id')
|
||||
->references('id')
|
||||
->on('work_orders')
|
||||
->nullOnDelete();
|
||||
$table->index('work_order_id');
|
||||
});
|
||||
```
|
||||
|
||||
**모델 관계 (2B.5)**:
|
||||
|
||||
```php
|
||||
// Inspection.php
|
||||
public function workOrder(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(WorkOrder::class);
|
||||
}
|
||||
|
||||
// WorkOrder.php
|
||||
public function inspections(): HasMany
|
||||
{
|
||||
return $this->hasMany(Inspection::class);
|
||||
}
|
||||
```
|
||||
|
||||
**역추적 보정 로직 (2B.7)**:
|
||||
|
||||
```
|
||||
inspections.lot_no → work_order_items.lot_no → work_orders.id
|
||||
|
|
||||
중복 검사: 동일 lot_no에 다수 work_order 매칭 시 경고 로그
|
||||
|
|
||||
MATCH: work_order_id 설정
|
||||
NO_MATCH: null 유지 (수동 보정 대상)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 검증 결과
|
||||
|
||||
### 3.1 Phase 2A 검증
|
||||
|
||||
| 조사 항목 | 결과 | 판단 |
|
||||
|----------|------|------|
|
||||
| KWE01 BOM 구성품 수 | | ⏳ |
|
||||
| KSS01 BOM 구성품 수 | | ⏳ |
|
||||
| KSS02 BOM 구성품 수 | | ⏳ |
|
||||
| 마감유형별 차이점 | | ⏳ |
|
||||
| `DEFAULT_GAP_PROFILES` 5130 대조 | | ⏳ |
|
||||
|
||||
### 3.2 Phase 2B 검증
|
||||
|
||||
| 테스트 | 예상 결과 | 실제 결과 | 상태 |
|
||||
|--------|----------|----------|------|
|
||||
| 견적 저장 시 `quotes.product_code` | 첫 번째 개소 코드 | | ⏳ |
|
||||
| 다중 개소 대표 코드 | 첫 번째 개소 | | ⏳ |
|
||||
| 견적→수주 변환 `camelCase`→`snake_case` | 정상 변환 | | ⏳ |
|
||||
| `inspections.work_order_id` FK 마이그레이션 | 성공, `nullable` | | ⏳ |
|
||||
| 기존 inspection 조회 회귀 | 정상 | | ⏳ |
|
||||
| `lot_no` 기반 역추적 보정 정확도 | MATCH 95% 이상 | | ⏳ |
|
||||
|
||||
---
|
||||
|
||||
## 4. 참고 파일
|
||||
|
||||
### 4.1 Phase 2A 관련
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `react/.../documents/TemplateInspectionContent.tsx` | `DEFAULT_GAP_PROFILES` (L176-206), `buildBendingProducts` (L209-274) |
|
||||
| `react/.../documents/BendingInspectionContent.tsx` | `INITIAL_PRODUCTS` (L71-135, 레거시 동결) |
|
||||
| `5130/estimate/common/common_addrowJS.php` | 레거시 구성품 정의 |
|
||||
| `5130/output/view_inspection_bending.php` | 절곡 중간검사 성적서 |
|
||||
|
||||
### 4.2 Phase 2B 관련
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `api/app/Services/Quote/QuoteService.php` | 견적 서비스 (`product_code` L324) |
|
||||
| `api/app/Services/InspectionService.php` | 품질검사 서비스 |
|
||||
| `api/app/Models/Quality/Inspection.php` | 검사 모델 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 변경 이력
|
||||
|
||||
| 날짜 | 항목 | 변경 내용 |
|
||||
|------|------|----------|
|
||||
| 2026-02-27 | 문서 작성 | 통합 계획 Phase 2 상세 문서 작성 |
|
||||
359
plans/integrated-phase-3.md
Normal file
359
plans/integrated-phase-3.md
Normal file
@@ -0,0 +1,359 @@
|
||||
# Phase 3: 절곡 검사 동적 구현
|
||||
|
||||
> **통합 계획**: [`integrated-master-plan.md`](./integrated-master-plan.md)
|
||||
> **원본**: [`document-system-improvement-plan.md`](./document-system-improvement-plan.md) Phase 2
|
||||
> **상태**: ⏳ 실행 대기
|
||||
> **의존성**: Phase 1 (product_code 전파) + Phase 2A (API 설계) 완료 필수
|
||||
> **리뷰 문서**: [`document-system-improvement-review.md`](./document-system-improvement-review.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 목표
|
||||
|
||||
API 기반 동적 구성품 로딩으로 `buildBendingProducts()` 고정 로직을 대체한다.
|
||||
|
||||
Phase 1에서 `product_code` 전파 버그를 수정하고, Phase 2A에서 API 설계를 완료한 뒤, 이 Phase에서 실제 구현을 진행한다.
|
||||
|
||||
### 1.2 핵심 구현 항목
|
||||
|
||||
- `inspection-config` API 구현 (공정 자동 판별)
|
||||
- `TemplateInspectionContent` API 연동 (`buildBendingProducts` 대체)
|
||||
- `document_data` EAV 저장/복원 검증
|
||||
- 트랜잭션 보강 (`lockForUpdate` + `DB::transaction`)
|
||||
|
||||
### 1.3 선행 완료 커밋 (react/)
|
||||
|
||||
| 커밋 | 내용 |
|
||||
|------|------|
|
||||
| `7b8b5cf5` | feat: TemplateInspectionContent 절곡 bending save/restore 지원 |
|
||||
| `54716e63` | feat: InspectionReportModal에서 documentRecords prop 전달 |
|
||||
| `36052f3e` | fix: bending 개소별 저장 fallback 조건 수정 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 작업 항목
|
||||
|
||||
| # | 작업 항목 | 상태 | 비고 |
|
||||
|---|----------|:----:|------|
|
||||
| 3.1 | `inspection-config` API 구현 (공정 자동 판별) | ⏳ | `BelongsToTenant` 필수 (M1) |
|
||||
| 3.2 | `TemplateInspectionContent` API 연동 (`buildBendingProducts` 대체) | ⏳ | `DEFAULT_GAP_PROFILES` → API 기준치 |
|
||||
| 3.3 | `document_data` EAV 저장/복원 검증 | ⏳ | C1 `field_key` 인코딩 패턴 |
|
||||
| 3.4 | 기존 절곡 검사 데이터 하위 호환 확인 | ⏳ | 레거시(Path A) + 신규(Path B) 독립 동작 |
|
||||
| 3.5 | `createInspectionDocument` 트랜잭션 보강 | ⏳ | I2: `lockForUpdate` + `DB::transaction` |
|
||||
|
||||
---
|
||||
|
||||
## 3. 상세 구현 내용
|
||||
|
||||
### 3.1 inspection-config API 구현
|
||||
|
||||
Phase 2A 설계 기반. 엔드포인트: `GET /api/v1/work-orders/{id}/inspection-config`
|
||||
|
||||
#### 3.1.1 구현 방향
|
||||
|
||||
```php
|
||||
// WorkOrderController 또는 신규 InspectionConfigController
|
||||
public function inspectionConfig(WorkOrder $workOrder)
|
||||
{
|
||||
// 1. 공정 타입 자동 판별
|
||||
$processType = $workOrder->process->type; // screen, slat, bending, etc.
|
||||
|
||||
// 2. product_code 추출 (Phase 1에서 수정됨)
|
||||
$productCode = $workOrder->items->first()?->options['product_code'] ?? null;
|
||||
|
||||
// 3. BOM 기반 구성품 조회 (절곡만)
|
||||
$items = [];
|
||||
if ($processType === 'bending') {
|
||||
$items = $this->getBendingComponents($productCode, $workOrder);
|
||||
}
|
||||
|
||||
// 4. 템플릿 ID 조회
|
||||
$templateId = $workOrder->process->steps()
|
||||
->where('needs_inspection', true)
|
||||
->first()?->document_template_id;
|
||||
|
||||
return ApiResponse::handle(fn() => [
|
||||
'work_order_id' => $workOrder->id,
|
||||
'process_type' => $processType,
|
||||
'product_code' => $productCode,
|
||||
'template_id' => $templateId,
|
||||
'items' => $items,
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.1.2 핵심 요구사항
|
||||
|
||||
| 항목 | 요구사항 | 정책 근거 |
|
||||
|------|----------|----------|
|
||||
| 멀티테넌시 | `BelongsToTenant` 스코프 필수 적용 | M1 |
|
||||
| 응답 시간 | < 200ms | M2 |
|
||||
| Fallback | BOM 미등록 시 빈 `items` 배열 반환 | C5 |
|
||||
| 공정 판별 | 프론트가 공정 타입을 하드코딩하지 않음 | I5 |
|
||||
|
||||
#### 3.1.3 응답 구조 (예시)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"work_order_id": 123,
|
||||
"process_type": "bending",
|
||||
"product_code": "KWE01",
|
||||
"template_id": 45,
|
||||
"items": [
|
||||
{
|
||||
"id": "guide_rail_wall",
|
||||
"name": "가이드레일 벽면",
|
||||
"gap_points": [30, 78, 25, 45],
|
||||
"labels": ["상", "중상", "중하", "하"]
|
||||
},
|
||||
{
|
||||
"id": "guide_rail_front",
|
||||
"name": "가이드레일 정면",
|
||||
"gap_points": [30, 78, 25, 45],
|
||||
"labels": ["상", "중상", "중하", "하"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> BOM 미등록이거나 `product_code`가 없는 경우 `items: []`를 반환하고, 프론트에서 `DEFAULT_GAP_PROFILES`를 사용한다.
|
||||
|
||||
---
|
||||
|
||||
### 3.2 TemplateInspectionContent API 연동
|
||||
|
||||
#### 3.2.1 현재 코드 구조 (AS-IS)
|
||||
|
||||
```typescript
|
||||
// TemplateInspectionContent.tsx
|
||||
const DEFAULT_GAP_PROFILES = { /* L176-206 */ };
|
||||
|
||||
function buildBendingProducts(order): BendingProduct[] { /* L209-274 */ }
|
||||
|
||||
const isBending =
|
||||
order.processType === 'bending' || columns에 point sub_labels 존재;
|
||||
```
|
||||
|
||||
`buildBendingProducts()`가 `order.bendingInfo`에서 동적 구성품을 생성하지만, 프론트 데이터에 의존하며 BOM 기반이 아니다.
|
||||
|
||||
#### 3.2.2 변경 내용 (TO-BE)
|
||||
|
||||
```typescript
|
||||
// TemplateInspectionContent.tsx (Phase 3 변경)
|
||||
|
||||
interface InspectionConfig {
|
||||
process_type: string;
|
||||
product_code: string;
|
||||
items: BendingInspectionItem[];
|
||||
}
|
||||
|
||||
// API 호출 (React Query 또는 Server Action)
|
||||
const { data: config, isLoading } = useInspectionConfig(workOrderId);
|
||||
|
||||
// fallback: API 실패/미응답 → buildBendingProducts 기본값
|
||||
const bendingProducts = config?.items?.length
|
||||
? mapConfigToProducts(config.items)
|
||||
: buildBendingProducts(order);
|
||||
```
|
||||
|
||||
#### 3.2.3 변경 범위
|
||||
|
||||
| 변경 대상 | 내용 | 비고 |
|
||||
|----------|------|------|
|
||||
| API 호출 추가 | `useInspectionConfig(workOrderId)` 훅 또는 Server Action | 신규 |
|
||||
| `buildBendingProducts` | 유지 (fallback 용도) | 기존 코드 수정 없음 |
|
||||
| `DEFAULT_GAP_PROFILES` | API 응답의 `gap_points`로 대체, 미응답 시 기존값 사용 | I1 기준 통일 |
|
||||
| `bendingExpandedRows` | API 기반 구성품으로 행 확장 | 기존 로직 활용 |
|
||||
|
||||
---
|
||||
|
||||
### 3.3 document_data EAV 저장 구조 (C1 정책)
|
||||
|
||||
#### 3.3.1 저장 구조
|
||||
|
||||
```
|
||||
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} → 추가 측정값
|
||||
```
|
||||
|
||||
> 이미 save/restore 구현 완료 (커밋 `7b8b5cf5`)
|
||||
> `productIdx`는 `buildBendingProducts()` 반환 배열의 인덱스
|
||||
|
||||
#### 3.3.2 BOM 동적화 시 향후 전환 (C4)
|
||||
|
||||
| 구분 | 현행 (Phase 3) | 향후 (BOM 동적화) |
|
||||
|------|---------------|------------------|
|
||||
| `field_key` 형식 | `b{productIdx}_...` | `b{productId}_...` |
|
||||
| 매핑 기준 | 배열 인덱스 | 구성품 식별자 |
|
||||
| BOM 스냅샷 | 없음 | `document.options.bom_snapshot` 저장 |
|
||||
|
||||
---
|
||||
|
||||
### 3.4 하위호환 (C2)
|
||||
|
||||
두 개의 독립적인 데이터 경로가 존재한다.
|
||||
|
||||
```
|
||||
Path A: InspectionInputModal
|
||||
→ work_order_items.options.inspection_data
|
||||
→ 개소별 빠른 입력 (기존 유지)
|
||||
|
||||
Path B: TemplateInspectionContent
|
||||
→ document_data EAV
|
||||
→ 검사 성적서 (신규 방식)
|
||||
|
||||
→ 두 경로 독립 동작, 마이그레이션 불필요
|
||||
→ 레거시 데이터(Path A)는 그대로 유지
|
||||
→ 신규 데이터(Path B)는 EAV에 저장
|
||||
```
|
||||
|
||||
#### 3.4.1 하위호환 보장 조건
|
||||
|
||||
| 조건 | 설명 | 검증 방법 |
|
||||
|------|------|----------|
|
||||
| Path A 무변경 | `InspectionInputModal`의 절곡 입력/저장 로직 건드리지 않음 | 기존 데이터 정상 표시 확인 |
|
||||
| Path B 독립 | `TemplateInspectionContent`는 `document_data` EAV만 사용 | 신규 저장→조회 사이클 검증 |
|
||||
| 롤백 가능 | `document_template_id` NULL 설정 시 레거시 컴포넌트 자동 복귀 | I4 정책 결정 |
|
||||
|
||||
---
|
||||
|
||||
### 3.5 createInspectionDocument 트랜잭션 보강 (I2)
|
||||
|
||||
#### 3.5.1 현재 문제
|
||||
|
||||
`WorkOrderService::createInspectionDocument`에 `DB::transaction()` 없이 조회→분기→create/update를 실행한다. 절곡 동적화로 API 호출이 추가되면 race window가 확대된다.
|
||||
|
||||
#### 3.5.2 수정 내용
|
||||
|
||||
```php
|
||||
// WorkOrderService::createInspectionDocument
|
||||
public function createInspectionDocument(WorkOrder $workOrder, ...)
|
||||
{
|
||||
return DB::transaction(function () use ($workOrder, ...) {
|
||||
// lockForUpdate로 동시 생성 방지
|
||||
$workOrder->lockForUpdate();
|
||||
|
||||
// 기존 document 중복 체크
|
||||
$existing = $workOrder->documents()
|
||||
->where('template_id', $templateId)
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
return $existing; // 이미 존재하면 반환
|
||||
}
|
||||
|
||||
// 신규 생성
|
||||
return $this->documentService->create(...);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.5.3 적용 범위
|
||||
|
||||
| 항목 | 설명 |
|
||||
|------|------|
|
||||
| `lockForUpdate()` | 동일 `WorkOrder`에 대한 동시 문서 생성 방지 |
|
||||
| `DB::transaction()` | 조회→분기→생성 전체를 원자적으로 처리 |
|
||||
| 중복 체크 | `template_id` 기준 기존 문서 존재 시 생성 대신 반환 |
|
||||
| 별도 작업 | 절곡 동적화와 무관하게 기존 코드 결함 수정 (I2) |
|
||||
|
||||
---
|
||||
|
||||
## 4. 데이터 경로 다이어그램
|
||||
|
||||
```
|
||||
작업지시(WorkOrder)
|
||||
│
|
||||
├─ inspection-config API ← Phase 3 구현
|
||||
│ ├─ process_type 자동 판별
|
||||
│ ├─ product_code 추출 (Phase 1에서 수정됨)
|
||||
│ └─ BOM 기반 구성품 목록 반환
|
||||
│
|
||||
├─ TemplateInspectionContent (React)
|
||||
│ ├─ AS-IS: buildBendingProducts() 고정 로직
|
||||
│ └─ TO-BE: inspection-config API → 동적 구성품
|
||||
│ └─ fallback: buildBendingProducts() 유지
|
||||
│
|
||||
├─ Path A: InspectionInputModal → options.inspection_data
|
||||
│ └─ 개소별 빠른 입력 (기존 유지)
|
||||
│
|
||||
└─ Path B: TemplateInspectionContent → document_data EAV
|
||||
├─ row_index = 개소(WorkOrderItem)
|
||||
├─ field_key = b{idx}_ok, b{idx}_p{pt}_n1 등
|
||||
└─ save/restore 구현 완료 (7b8b5cf5)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 검증 계획
|
||||
|
||||
| # | 테스트 | 예상 결과 | 실제 결과 | 상태 |
|
||||
|---|--------|----------|----------|:----:|
|
||||
| 1 | KWE01 → 구성품 표시 | `buildBendingProducts` 결과와 동일 | | ⏳ |
|
||||
| 2 | KSS01 → 다른 구성품 | KSS01 전용 구성품 | | ⏳ |
|
||||
| 3 | KSS02 → 다른 구성품 | KSS02 전용 구성품 | | ⏳ |
|
||||
| 4 | 마감유형 S1/S2/S3 | 유형별 차이 반영 | | ⏳ |
|
||||
| 5 | 구성품 수 7개 미만/초과 | 정상 렌더링 | | ⏳ |
|
||||
| 6 | API 미응답 시 fallback | `buildBendingProducts` 기본값 | | ⏳ |
|
||||
| 7 | BOM 미등록 시 | `DEFAULT_GAP_PROFILES` 사용 | | ⏳ |
|
||||
| 8 | 저장→조회→재저장 사이클 | 데이터 무손실 | | ⏳ |
|
||||
| 9 | 기존 절곡 데이터 (Path A) | 정상 표시 | | ⏳ |
|
||||
| 10 | 신규 절곡 데이터 (Path B) | EAV 정상 동작 | | ⏳ |
|
||||
| 11 | mng `show.blade.php` 렌더링 | 성적서 정상 표시 | | ⏳ |
|
||||
| 12 | `inspection-config` API 응답 | < 200ms | | ⏳ |
|
||||
| 13 | 스크린/슬랫 회귀 | 변화 없음 | | ⏳ |
|
||||
| 14 | 트랜잭션 동시 접근 (I2) | race condition 없음 | | ⏳ |
|
||||
|
||||
---
|
||||
|
||||
## 6. 참고 파일
|
||||
|
||||
### 6.1 React
|
||||
|
||||
| 파일 | 역할 | 비고 |
|
||||
|------|------|------|
|
||||
| `react/.../documents/TemplateInspectionContent.tsx` | 통합 방향 (C3) | L176-274 |
|
||||
| `react/.../documents/BendingInspectionContent.tsx` | 레거시 동결 (C3) | L71-135 |
|
||||
| `react/.../documents/InspectionReportModal.tsx` | 모달 래퍼 | `documentRecords` 전달 완료 |
|
||||
| `react/.../documents/inspection-shared.tsx` | 공유 유틸 | |
|
||||
| `react/.../WorkerScreen/InspectionInputModal.tsx` | Path A 유지 | ~950행 |
|
||||
|
||||
### 6.2 API
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `api/app/Services/WorkOrderService.php` | `createInspectionDocument` (I2 보강) |
|
||||
| `api/app/Services/DocumentService.php` | 문서 CRUD |
|
||||
| `api/app/Http/Controllers/V1/DocumentController.php` | 문서 API |
|
||||
|
||||
### 6.3 5130 레거시
|
||||
|
||||
| 파일 | 역할 |
|
||||
|------|------|
|
||||
| `5130/output/view_inspection_bending.php` | 절곡 중간검사 |
|
||||
| `5130/estimate/common/common_addrowJS.php` | 구성품 정의 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 변경 이력
|
||||
|
||||
| 날짜 | 항목 | 변경 내용 |
|
||||
|------|------|----------|
|
||||
| 2026-02-27 | 문서 작성 | 통합 계획 Phase 3 상세 문서 작성 |
|
||||
|
||||
---
|
||||
|
||||
*이 문서는 [`integrated-master-plan.md`](./integrated-master-plan.md)의 Phase 3 상세입니다.*
|
||||
@@ -1,8 +1,10 @@
|
||||
# 품목(제품코드) 연결 구조 개선 계획
|
||||
|
||||
> **⚠️ 이 문서는 아카이브 참조용입니다. 통합 계획은 [`integrated-master-plan.md`](./integrated-master-plan.md)를 참조하세요.**
|
||||
|
||||
> **작성일**: 2026-02-25
|
||||
> **목적**: 견적 → 수주 → 생산 → 출하 → 품질 전 단계에서 제품코드(모델코드) 추적성 확보
|
||||
> **상태**: 🔄 계획 수립 완료, 실행 대기
|
||||
> **상태**: 📦 통합 계획으로 이관 (2026-02-27)
|
||||
> **리뷰**: v2 - SuperClaude 3개 페르소나 리뷰 반영 (Backend Architect, System Architect, Quality Engineer)
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user