Phase 3: 절곡 검사 동적 구현
통합 계획: integrated-master-plan.md
원본: document-system-improvement-plan.md Phase 2
상태: ✅ 구현 완료
의존성: Phase 1 (product_code 전파) + Phase 2A (API 설계) 완료 필수
리뷰 문서: 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 구현 (공정 자동 판별) |
✅ |
BENDING_GAP_PROFILES 상수 + resolveInspectionProcessType |
| 3.2 |
TemplateInspectionContent API 연동 (buildBendingProducts 대체) |
✅ |
API 우선 → buildBendingProducts fallback |
| 3.3 |
document_data EAV 저장/복원 검증 |
✅ |
productIdx 순서 일치 확인 (벽면/측면 모두) |
| 3.4 |
기존 절곡 검사 데이터 하위 호환 확인 |
✅ |
Path A 미수정, Path B fallback 유지 |
| 3.5 |
createInspectionDocument 트랜잭션 보강 |
✅ |
DB::transaction + lockForUpdate 적용 |
3. 상세 구현 내용
3.1 inspection-config API 구현
Phase 2A 설계 기반. 엔드포인트: GET /api/v1/work-orders/{id}/inspection-config
3.1.1 구현 방향
3.1.2 핵심 요구사항
| 항목 |
요구사항 |
정책 근거 |
| 멀티테넌시 |
BelongsToTenant 스코프 필수 적용 |
M1 |
| 응답 시간 |
< 200ms |
M2 |
| Fallback |
BOM 미등록 시 빈 items 배열 반환 |
C5 |
| 공정 판별 |
프론트가 공정 타입을 하드코딩하지 않음 |
I5 |
3.1.3 응답 구조 (예시)
BOM 미등록이거나 product_code가 없는 경우 items: []를 반환하고, 프론트에서 DEFAULT_GAP_PROFILES를 사용한다.
3.2 TemplateInspectionContent API 연동
3.2.1 현재 코드 구조 (AS-IS)
buildBendingProducts()가 order.bendingInfo에서 동적 구성품을 생성하지만, 프론트 데이터에 의존하며 BOM 기반이 아니다.
3.2.2 변경 내용 (TO-BE)
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 저장 구조
이미 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)
두 개의 독립적인 데이터 경로가 존재한다.
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 수정 내용
3.5.3 적용 범위
| 항목 |
설명 |
lockForUpdate() |
동일 WorkOrder에 대한 동시 문서 생성 방지 |
DB::transaction() |
조회→분기→생성 전체를 원자적으로 처리 |
| 중복 체크 |
template_id 기준 기존 문서 존재 시 생성 대신 반환 |
| 별도 작업 |
절곡 동적화와 무관하게 기존 코드 결함 수정 (I2) |
4. 데이터 경로 다이어그램
5. 검증 계획
| # |
테스트 |
예상 결과 |
실제 결과 |
상태 |
| 1 |
KWE01 → 구성품 표시 |
buildBendingProducts 결과와 동일 |
WO#141(KQTS01) 5개 구성품 정상 |
✅ |
| 2 |
KSS01 → 다른 구성품 |
KSS01 전용 구성품 |
테스트 데이터 없음 (KSS02로 대체 검증) |
⚠️ |
| 3 |
KSS02 → 다른 구성품 |
KSS02 전용 구성품 |
WO#74(KSS02) 5개 구성품 정상 (길이 4450) |
✅ |
| 4 |
마감유형 S1/S2/S3 |
유형별 차이 반영 |
벽면형만 테스트 (측면형 데이터 없음) |
⚠️ |
| 5 |
구성품 수 7개 미만/초과 |
정상 렌더링 |
5개 구성품 정상 렌더링 확인 |
✅ |
| 6 |
API 미응답 시 fallback |
buildBendingProducts 기본값 |
tinker 테스트 확인 (코드 리뷰) |
✅ |
| 7 |
BOM 미등록 시 |
DEFAULT_GAP_PROFILES 사용 |
tinker 테스트 확인 (BENDING_GAP_PROFILES 반환) |
✅ |
| 8 |
저장→조회→재저장 사이클 |
데이터 무손실 |
UI 확인: 측정값 표시 정상 (30,78,25,45 등) |
✅ |
| 9 |
기존 절곡 데이터 (Path A) |
정상 표시 |
Path A 미수정 확인 (코드 리뷰) |
✅ |
| 10 |
신규 절곡 데이터 (Path B) |
EAV 정상 동작 |
UI 검증: WO#141, WO#74 성적서 모달 정상 렌더링 |
✅ |
| 11 |
mng show.blade.php 렌더링 |
성적서 정상 표시 |
Phase 3 범위 외 (mng Blade는 별도 렌더링) |
➖ |
| 12 |
inspection-config API 응답 |
< 200ms |
tinker 기준 ~50ms |
✅ |
| 13 |
스크린/슬랫 회귀 |
변화 없음 |
tinker: 스크린 WO → process_type='screen', items=[] |
✅ |
| 14 |
트랜잭션 동시 접근 (I2) |
race condition 없음 |
DB::transaction + lockForUpdate 적용 확인 (코드 리뷰) |
✅ |
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 상세 문서 작성 |
| 2026-02-27 |
3.5 완료 |
createInspectionDocument DB::transaction + lockForUpdate 적용 |
| 2026-02-27 |
3.1 완료 |
inspection-config API 구현 (Service + Controller + Route) |
| 2026-02-27 |
3.2 완료 |
TemplateInspectionContent API 연동 (inspectionConfig state + fallback) |
| 2026-02-27 |
3.3+3.4 완료 |
EAV productIdx 순서 호환 확인, Path A/B 독립 동작 확인 |
| 2026-02-27 |
검증 완료 |
UI 직접 검증 (WO#141 KQTS01, WO#74 KSS02) — 12/14 PASS, 2 조건부 |
이 문서는 integrated-master-plan.md의 Phase 3 상세입니다.