Files
sam-docs/dev/dev_plans/document-system-work-log.md
권혁성 db63fcff85 refactor: [docs] 팀별 폴더 구조 재편 (공유/개발/프론트/기획)
- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동)
- 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/)
- 기획팀 폴더 requests/ 생성
- plans/ → dev/dev_plans/ 이름 변경
- README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용)
- resources.md 신규 (노션 링크용, assets/brochure 이관 예정)
- CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동
- 전체 참조 경로 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:46:03 +09:00

326 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 5.3: 작업일지 폼 구현 계획
> **작성일**: 2026-02-10
> **마스터 문서**: [`document-system-master.md`](./document-system-master.md)
> **상태**: 🔄 진행 중 (3/4+α, mng 상세보기 ✅)
> **선행 조건**: Phase 5.0과 독립 (검사기준서 없음). 병렬 진행 가능
---
## 1. 개요
### 1.1 목적
mng에서 작업일지 양식 템플릿을 정의하고, React 작업자 화면(`/production/worker-screen`)의 작업일지 모달에서 해당 양식을 기반으로 작업 내역을 기록/조회할 수 있도록 한다.
### 1.2 하이브리드 방식
- **양식 정의**: mng 템플릿 시스템 (DocumentTemplate) 활용
- **전용 UI/로직**: React에서 작업일지 전용 컴포넌트로 구현 (검사 성적서와 다른 구조)
- **이유**: 작업일지는 검사 항목표가 아닌, 품목 목록 + 작업 통계 + 특이사항 구조
### 1.3 현재 상태
| 항목 | 상태 | 비고 |
|------|:----:|------|
| React WorkLogContent.tsx | ✅ | 정적 문서, DocumentHeader + 기본정보 + 품목테이블 + 작업내역 + 특이사항 |
| mng 양식 템플릿 | ✅ | WorkLogTemplateSeeder 3종 (스크린:62, 슬랫:63, 절곡:64) |
| WorkLogModal 양식 연동 | ✅ | 공정관리 workLogTemplateId 기반 콘텐츠 분기, processType 폴백 |
| ScreenWorkLogContent 자재 LOT | ✅ | materialLots item_name별 동적 그룹핑 (하드코딩 "내화실" 제거) |
| API 자재 투입 LOT 조회 | ✅ | materialInputLots 엔드포인트 (stock_transactions 기반) |
| API 작업일지 전용 | ✅ | getWorkLogTemplate, getWorkLog, createWorkLog (3개 라우트) |
| 작업 통계 계산 | ✅ | calculateWorkStats() 함수 존재 (완료/진행중/대기 수량) |
| **mng 문서 상세보기** | ✅ | **show.blade.php 작업일지 전용 섹션 (템플릿 컬럼 기반 동적 렌더링)** |
| **mng bf_ backfill 분기** | ✅ | **resolveAndBackfillBasicFields: 작업일지=label 기반, 검사=field_key 기반** |
| **mng 재단 알고리즘 (PHP)** | ✅ | **React calculateCutSize 동일 구현. 실리카/와이어/화이바 원단별 설정** |
| **mng 개소별 투입자재 LOT** | ✅ | **work_order_material_inputs → stock_lots JOIN, 개소별 lot_no 매핑** |
| **mng 취소 트랜잭션 상쇄** | ✅ | **work_order_input + work_order_input_cancel 합산 → 순수 투입량** |
### 1.4 성공 기준
1. mng에서 작업일지 양식 정의 가능 (기본필드, 결재라인)
2. React에서 WorkOrder 선택 시 작업일지 자동생성 또는 수동생성
3. 품목 목록(WorkOrderItem[])이 자동으로 테이블에 매핑
4. 작업 통계(지시수량/완료수량/진행률) 자동 계산
5. 특이사항 입력/저장 가능
---
## 2. 데이터 흐름
```
WorkOrder (작업지시)
├─ work_order_no: "KD-WO-260210-01"
├─ process_id → Process (공정: 스크린/슬랫/절곡)
├─ sales_order_id → Order (수주)
│ ├─ client_name: "발주처명"
│ └─ site_name: "현장명"
└─ items: WorkOrderItem[]
├─ [0] item_name="와이어 스크린", quantity=2, status="completed"
├─ [1] item_name="메쉬 스크린", quantity=4, status="in_progress"
└─ [N] ...
작업일지 생성:
Document (작업일지 1건 / 작업지시 1건)
├─ template_id → 작업일지 양식
├─ linkable_type = 'WorkOrder'
├─ linkable_id = work_order.id
├─ status: DRAFT → PENDING → APPROVED
└─ document_data (EAV)
├─ 기본필드: 발주처, 현장명, 작업일자, LOT NO, 납기일, 작업지시번호
├─ 품목데이터: 행(row) = WorkOrderItem별
│ ├─ r{행}_item_name = "와이어 스크린"
│ ├─ r{행}_floor_code = "1F-A"
│ ├─ r{행}_specification = "W7400×H2950"
│ ├─ r{행}_quantity = "2"
│ └─ r{행}_status = "completed"
├─ 작업통계: order_qty, completed_qty, in_progress_qty, waiting_qty, progress
└─ 특이사항: remarks
```
### 2.1 mng 상세보기 데이터 흐름 (구현 완료)
```
DocumentController::show($id)
├─ Document + relations 로드
├─ linkable_type === 'work_order' ?
│ ├─ workOrderItems (work_order_items, options JSON decode)
│ ├─ workOrder (work_orders)
│ ├─ salesOrder (orders, via work_order.sales_order_id)
│ ├─ materialInputLots (stock_transactions: work_order_input + cancel 상쇄)
│ │ └─ 순수 투입량 = SUM(qty) where qty < 0 → abs()
│ └─ itemLotMap (work_order_material_inputs → stock_lots JOIN)
│ └─ groupBy(work_order_item_id) → lot_no 문자열
├─ resolveAndBackfillBasicFields($document)
│ ├─ isWorkLog = sections 없음?
│ ├─ 작업일지 → buildWorkLogResolveMap (label 기반: 발주처, 현장명, 수주일 등)
│ └─ 검사 문서 → buildInspectionResolveMap (field_key 기반: product_name 등)
└─ view('documents.show', [...])
show.blade.php (작업일지 전용 섹션)
├─ 템플릿 컬럼 기반 동적 테이블
│ ├─ 헤더: simple 컬럼 = 1행, complex 컬럼 = colspan + sub_labels 2행
│ ├─ 데이터: $getCellValue (label 기반 매핑), $getSubCellValue (sub_label 매핑)
│ └─ PHP $calculateCutSize (재단 알고리즘: FABRIC_CONFIG 원단별)
├─ 작업 통계 (지시수량/완료/진행중/대기/진행률)
├─ 투입 자재 LOT 테이블 (materialInputLots)
└─ 비고 (remarks)
```
### 2.2 중간검사 문서와의 차이
| 항목 | 중간검사 | 작업일지 |
|------|---------|---------|
| 단위 | 작업지시 (내부 개소별 행) | 작업지시 (1:1) |
| 테이블 내용 | 검사항목 + 측정값 + 판정 | 품목 목록 + 상태 |
| 통계 | 적합/부적합 비율 | 완료/진행중/대기 수량 |
| Footer | 부적합 내용 + 종합판정 | 특이사항 |
| 결재 | 작성→검토→승인 (3단계) | 작성→확인 (2단계) |
---
## 3. 작업 항목
| # | 작업 | 상태 | 완료 기준 | 비고 |
|---|------|:----:|----------|------|
| 5.3.1 | mng 작업일지 양식 시더 생성 | ✅ | WorkLogTemplateSeeder 3종. 스크린(62)/슬랫(63)/절곡(64). 공정별 결재+기본필드+컬럼 | 검사 기준서 섹션 없음, 판정 없음 |
| 5.3.2 | mng 양식 편집 검증 | ✅ | 작업일지 양식 edit → 미리보기 정상 동작 확인 (코드 레벨 검증) | 빈 sections/judgement 안전 처리 |
| 5.3.3 | API 작업일지 생성/저장 | ✅ | getWorkLogTemplate, getWorkLog, createWorkLog 구현. 3개 라우트 추가 | EAV 저장, 기본필드 자동매핑, 작업통계 자동계산 |
| 5.3.4 | React WorkLogContent 양식 기반 전환 | ⏳ | 양식의 기본필드/결재라인을 API에서 받아 렌더링. 품목테이블/통계는 전용 로직 유지 | 하이브리드 |
### mng 작업일지 상세보기 (추가 작업, ✅ 완료)
| # | 작업 | 상태 | 설명 |
|---|------|:----:|------|
| α.1 | resolveAndBackfillBasicFields 작업일지/검사 분기 | ✅ | 섹션 유무로 판별. 작업일지=label 기반(발주처, 현장명 등), 검사=field_key 기반(product_name 등) |
| α.2 | show() 메서드 데이터 로딩 확장 | ✅ | workOrder, salesOrder, materialInputLots, itemLotMap 변수 추가 |
| α.3 | 템플릿 컬럼 기반 동적 테이블 렌더링 | ✅ | template.columns 구조대로 헤더/데이터 렌더링. complex 컬럼(제작사이즈, 규격매수) sub_labels 지원 |
| α.4 | PHP 재단 알고리즘 (calculateCutSize) | ✅ | React 동일 구현. FABRIC_CONFIG(실리카1220/와이어1100/화이바1100), 나머지높이+규격(매수) 자동계산 |
| α.5 | 개소별 투입자재 LOT 매핑 | ✅ | work_order_material_inputs → stock_lots JOIN. 입고 LOT NO 컬럼에 개소별 lot_no 표시 |
| α.6 | 투입자재 취소 트랜잭션 상쇄 | ✅ | stock_transactions에서 work_order_input(OUT,음수) + work_order_input_cancel(IN,양수) 합산 |
| α.7 | 작업통계/자재LOT/비고 섹션 | ✅ | 지시수량/완료/진행중/대기 통계, 투입 자재 LOT 테이블, 비고 표시 |
---
## 4. 작업일지 구조 (React 현재 기준)
### 4.1 WorkLogContent.tsx 구조
```
작업일지 문서
├─ DocumentHeader
│ ├─ 로고 (케이디산업)
│ ├─ 제목: "작업일지"
│ └─ 결재라인: 작성 / 확인
├─ 기본 정보 테이블
│ ├─ 발주처 / 현장명
│ ├─ 작업일자 / LOT NO
│ └─ 납기일 / 작업지시번호
├─ 품목 테이블
│ ├─ No | 품목명 | 층-부호 | 규격 | 수량 | 상태
│ ├─ [1] 와이어 스크린 | 1F-A | W7400×H2950 | 2 | 완료
│ ├─ [2] 메쉬 스크린 | 2F-B | W5200×H3100 | 4 | 작업중
│ └─ [N] ...
├─ 작업내역 (공정별)
│ ├─ 지시수량: 50
│ ├─ 완료수량: 30
│ ├─ 진행률: 60%
│ └─ 대기: 10 / 작업중: 10 / 완료: 30
└─ 특이사항
└─ (자유 텍스트 입력)
```
### 4.2 작업 통계 계산 (기존 로직)
```typescript
function calculateWorkStats(items: WorkOrderItem[]): WorkStats {
return {
orderQty: items.length, // 전체 개소 수
completedQty: items.filter(i => i.status === 'completed').length,
inProgressQty: items.filter(i => i.status === 'in_progress').length,
waitingQty: items.filter(i => i.status === 'waiting').length,
progress: (completedQty / orderQty) * 100
}
}
```
---
## 5. 양식 시더 구조 (구현 완료 - 3종)
```php
// WorkLogTemplateSeeder - 공정별 3종
// 스크린(ID:62): 결재 3단계(작성/검토/승인), 규격매수 컬럼(기준폭/900/800/600/400/300)
// 슬랫(ID:63): 결재 4단계(작성/승인×3), 방화유리/조인트바/코일 컬럼
// 절곡(ID:64): 결재 4단계(작성/승인×3), 유형명/세부품명/재질/길이규격 컬럼
//
// 공통: 기본필드 9개(신청업체4+신청내용5), 판정 없음, 비고만
[
'name' => '스크린 작업일지', // or 슬랫/절곡
'category' => '생산/작업일지',
'title' => '작업일지 (스크린)',
'company_name' => '케이디산업',
'footer_remark_label' => '비고',
'footer_judgement_label' => '', // NOT NULL 컬럼 → 빈문자열
'footer_judgement_options' => [], // 작업일지는 종합판정 없음
'approval_lines' => [
['name' => '작성', 'dept' => '생산', 'role' => '담당자', 'sort_order' => 1],
['name' => '확인', 'dept' => '생산', 'role' => '관리자', 'sort_order' => 2],
],
'basic_fields' => [
['label' => '발주처', 'field_type' => 'text'],
['label' => '현장명', 'field_type' => 'text'],
['label' => '작업일자', 'field_type' => 'date'],
['label' => 'LOT NO', 'field_type' => 'text'],
['label' => '납기일', 'field_type' => 'date'],
['label' => '작업지시번호', 'field_type' => 'text'],
],
// 섹션 없음 (작업일지는 검사 기준서가 필요 없음)
'sections' => [],
// 컬럼: 품목 테이블용 (React에서 직접 렌더링하므로 참조용)
'columns' => [
['label' => 'No', 'column_type' => 'text', 'width' => '40px'],
['label' => '품목명', 'column_type' => 'text', 'width' => '150px'],
['label' => '층-부호', 'column_type' => 'text', 'width' => '80px'],
['label' => '규격', 'column_type' => 'text', 'width' => '150px'],
['label' => '수량', 'column_type' => 'text', 'width' => '60px'],
['label' => '상태', 'column_type' => 'select', 'width' => '80px'],
],
]
```
---
## 6. 하이브리드 구현 전략
### mng 템플릿에서 관리하는 것
- 결재라인 (작성/확인 or 커스텀)
- 기본필드 (발주처, 현장명, 작업일자 등)
- 회사명, 문서 제목
### React 전용 로직으로 유지하는 것
- 품목 테이블 (WorkOrderItem[] 기반 동적 생성)
- 작업 통계 계산 (calculateWorkStats)
- 상태 배지 (완료/작업중/대기 → 색상 표시)
- 특이사항 입력 UI
### API 요청 흐름
```
1. 작업일지 생성 요청
POST /api/v1/work-orders/{id}/create-work-log
→ Document 생성 (template_id, linkable → WorkOrder)
→ 기본필드 자동매핑 (발주처, 현장명, LOT NO 등)
2. 작업일지 데이터 저장
PUT /api/v1/documents/{id}
Body: {
basic_data: { ... }, // 기본필드 (양식 기반)
table_data: [ ... ], // 품목 테이블 (전용 로직)
stats: { ... }, // 작업 통계 (자동 계산)
remarks: "특이사항" // 자유 텍스트
}
3. 작업일지 조회
GET /api/v1/documents/{id}
→ 양식 JSON + 저장된 데이터 반환
```
---
## 7. 핵심 파일 경로
### mng
| 파일 | 용도 |
|------|------|
| `mng/database/seeders/WorkLogTemplateSeeder.php` | ✅ 3종 생성 (62/63/64) |
| `mng/app/Http/Controllers/DocumentController.php` | ✅ show() 작업일지 데이터 로딩, resolveAndBackfillBasicFields 분기, buildWorkLogResolveMap |
| `mng/resources/views/documents/show.blade.php` | ✅ 작업일지 전용 섹션 (템플릿 컬럼 동적 렌더링, PHP 재단 알고리즘, 통계, 자재LOT, 비고) |
### react
| 파일 | 용도 |
|------|------|
| `react/src/components/production/WorkerScreen/WorkLogModal.tsx` | ✅ 작업일지 모달 (공정관리 양식 연동) |
| `react/src/components/production/WorkerScreen/WorkLogContent.tsx` | 작업일지 범용 (~280행) |
| `react/src/components/production/WorkOrders/documents/ScreenWorkLogContent.tsx` | ✅ 스크린 작업일지 (자재 LOT 동적화) |
| `react/src/components/production/WorkOrders/documents/SlatWorkLogContent.tsx` | 슬랫 작업일지 |
| `react/src/components/production/WorkOrders/documents/BendingWorkLogContent.tsx` | 절곡 작업일지 |
| `react/src/components/production/WorkerScreen/actions.ts` | API 호출 |
| `react/src/components/document-system/viewer/DocumentViewer.tsx` | 문서 뷰어 |
### api
| 파일 | 용도 |
|------|------|
| `api/app/Services/WorkOrderService.php` | ✅ getWorkLogTemplate, getWorkLog, createWorkLog |
| `api/app/Http/Controllers/Api/V1/WorkOrderController.php` | ✅ 작업일지 3개 엔드포인트 |
| `api/routes/api/v1/production.php` | ✅ work-log-template, work-log 라우트 |
| `api/app/Models/Production/WorkOrder.php` | ✅ documents() MorphMany 관계 |
---
## 8. 변경 이력
| 날짜 | 내용 |
|------|------|
| 2026-02-10 | Phase 5.3 계획 문서 신규 생성 |
| 2026-02-11 | 5.3.1 완료: WorkLogTemplateSeeder 3종 생성 (스크린62/슬랫63/절곡64). 범용(61) 삭제. React 공정별 코드 분석 기반 구조 반영. 판정 없음 확정 |
| 2026-02-11 | WorkLogModal 공정관리 양식 연동: workLogTemplateId/Name prop 추가, resolveProcessTypeFromTemplate() |
| 2026-02-11 | ScreenWorkLogContent 자재 LOT 동적화: "내화실 입고 LOT NO" → materialLots item_name별 그룹핑 |
| 2026-02-11 | 결정: 자재 LOT 역할 분리 — 개소별 품목=작업내역 테이블, 공용 자재=자재 투입 시스템 (예외 필드 없음) |
| 2026-02-12 | 5.3.2 완료: mng 양식 편집/미리보기 코드 레벨 검증 (빈 sections/judgement 안전 처리 확인) |
| 2026-02-12 | 5.3.3 완료: API 작업일지 3개 엔드포인트 구현 (getWorkLogTemplate, getWorkLog, createWorkLog). 기본필드 자동매핑, 작업통계 자동계산, EAV 저장 |
| 2026-02-12 | MNG α.1~7 완료: 작업일지 상세보기 전면 구현 |
| 2026-02-12 | DocumentController: resolveAndBackfillBasicFields 작업일지(label)/검사(field_key) 분기. buildWorkLogResolveMap, buildInspectionResolveMap 추가 |
| 2026-02-12 | show.blade.php: 템플릿 컬럼 기반 동적 테이블 (complex 컬럼 sub_labels 지원), PHP 재단 알고리즘 (React calculateCutSize 동일) |
| 2026-02-12 | show(): workOrder, salesOrder, materialInputLots(취소 상쇄), itemLotMap(개소별 LOT) 변수 추가 |
| 2026-02-12 | 자재 투입 방식 변경 요청 기록 (수량 입력 → LOT 선택 방식, 미착수) |
---
*이 문서는 /plan 스킬로 생성되었습니다.*