From ac7fc2946b6128d3faa659f0949feef89f47917e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Fri, 13 Mar 2026 22:46:20 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20[MES]=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=A0=95=ED=95=A9=EC=84=B1=20=EB=B3=B4=EA=B3=A0=EC=84=9C=20v2?= =?UTF-8?q?=20=E2=86=92=20v2.1=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이슈 #2 품질검사: 출하 연동 불필요 (품질검사는 출하 후 시공 완료 후) - 이슈 #3 can_ship: ✅ 해결 완료 - 이슈 #4 재고차감: ✅ 비활성화 완료 - 이슈 #6 ShipmentItem FK: ✅ 해결 완료 - P0/P1/P2 로드맵 상태 전체 갱신 --- ...026-03-13] mes-data-integrity-report-v2.md | 506 ++++++++++++++++++ 1 file changed, 506 insertions(+) create mode 100644 dev/dev_plans/[ANALYSIS-2026-03-13] mes-data-integrity-report-v2.md diff --git a/dev/dev_plans/[ANALYSIS-2026-03-13] mes-data-integrity-report-v2.md b/dev/dev_plans/[ANALYSIS-2026-03-13] mes-data-integrity-report-v2.md new file mode 100644 index 0000000..180c26c --- /dev/null +++ b/dev/dev_plans/[ANALYSIS-2026-03-13] mes-data-integrity-report-v2.md @@ -0,0 +1,506 @@ +# MES 데이터 정합성 심층 분석 보고서 v2 + +**분석일**: 2026-03-13 (v2.1 - 정밀 코드 검증 반영) +**범위**: 수주(Order) → 생산(Production) → 품질(Quality) → 출고(Shipment) 전체 파이프라인 +**방법**: 프론트엔드(sam-react-prod) + 백엔드(sam-api) 코드 레벨 재분석 + v2.1 정밀 검증 + +--- + +## v1 대비 변경사항 요약 + +| 항목 | v1 (초기 분석) | v2 (코드 업데이트 반영) | +|------|---------------|----------------------| +| StockLot.work_order_id FK | 확인 안됨 | ✅ 2026-02-21 추가 확인 (생산→재고 연결 기반 마련) | +| QualityDocument 시스템 | 존재 인지 | ✅ 2026-03-05~10 활발히 개선 중 (inspection_data, options JSON 추가) | +| 출하 자동생성 | 언급 | ✅ 상세 분석 완료: createShipmentFromOrder() 중복방지 + ensureShipmentExists() | +| 3월 MES FK 추가 | 미확인 | ❌ 3월 마이그레이션에 MES FK 추가 없음 확인 | +| LOT 백엔드 자동 채번 | 미구현 | ✅ v2.1 확인: generateLotNo() + saveItemResults() 구현됨 | +| 나머지 3개 이슈 | 발견 | 🔴 여전히 미해결 (can_ship, 수주생산 재고입고, ShipmentItem FK) | + +--- + +## Executive Summary + +| # | 이슈 | 심각도 | v1 판정 | v2 판정 | 변경 | +|---|------|--------|---------|---------|------| +| 1 | 생산완료→수주 PRODUCED 자동전환 | 🟡→🟢 | 조건부 동작 | **정상 동작 + 자동출하 생성** | ⬆ 개선 | +| 2 | 품질검사 이중 시스템 | 🔴 | 구조적 문제 | 🔴 **구조적 문제 지속** (QualityDocument 활발 개발 중이나 출고 연동 미완) | 유지 | +| 3 | 출고 시 can_ship 검증 | 🔴 | 누락 | 🔴 **여전히 누락** (canProceedToShip 호출 0회) | 유지 | +| 4 | 출고 시 재고 차감 | ✅ | 구현됨 | ✅ **구현됨**, ⚠️ soft fail 리스크 유지 | 유지 | +| 5 | LOT 추적 체계 | 🔴 | 단절 | 🟢 **선생산 정상** / 🟡 **수주생산 재고입고 미경유** (v2.1: generateLotNo() 구현 확인) | ⬆⬆ 상향 | +| 6 | 출고품목↔수주품목 FK | 🔴 | 없음 | 🔴 **여전히 없음** (3월 마이그레이션에도 미추가) | 유지 | + +--- + +## 이슈 1: 생산완료 → 수주 상태 자동전환 + 출하 자동생성 + +### v2 판정: 🟢 정상 동작 (v1 대비 상향) + +v2 분석에서 자동 출하 생성 로직까지 상세 확인 완료. **정상 동작 확인**. + +### 전체 흐름 + +``` +WorkOrder 상태 변경 (updateStatus) + ↓ +syncOrderStatus() 자동 호출 (L971-1059) + ↓ +메인 WO 필터링: is_auxiliary=false AND process_id≠null + ↓ +전체 완료 시 → Order.status = PRODUCED + ↓ +createShipmentFromOrder() 자동 호출 (L719-809) + ↓ +Shipment 생성: status='scheduled', can_ship=true(자동) + ↓ +기존 Shipment 있으면 → 중복 생성 방지 (L721-728) +``` + +### 코드 근거 + +**syncOrderStatus**: `WorkOrderService.php:971-1059` + +```php +// L989-995: 메인 WO 필터 (보조공정 + process_id=null 제외) +$mainWorkOrders = $allWorkOrders->filter(fn ($wo) => + !$this->isAuxiliaryWorkOrder($wo) && $wo->process_id !== null +); + +// L1001-1019: 상태 결정 +if ($shippedCount === $totalCount) { + $newOrderStatus = Order::STATUS_SHIPPED; +} elseif (($completedCount + $shippedCount) === $totalCount) { + $newOrderStatus = Order::STATUS_PRODUCED; +} +``` + +**createShipmentFromOrder**: `WorkOrderService.php:719-809` + +```php +// L721-728: 중복 방지 +$existingShipment = Shipment::where('order_id', $order->id)->first(); +if ($existingShipment) return $existingShipment; + +// L732-744: 출하 자동 생성 +$shipment = Shipment::create([ + 'order_id' => $order->id, + 'work_order_id' => null, // 수주 레벨 (WO 레벨 아님) + 'status' => 'scheduled', + 'can_ship' => true, // ← 자동으로 true 설정 +]); + +// L746-790: WO 아이템 → ShipmentItem 복사 +``` + +**ensureShipmentExists**: 이미 PRODUCED인데 출하가 없는 경우 보완 (L1027-1033) + +### 잔존 리스크 (낮음) + +| 조건 | 원인 | 발생 가능성 | +|------|------|------------| +| `process_id = NULL`인 WO | 공정 매핑 실패 | 낮음 (생성 시 검증됨) | +| `is_auxiliary` 오설정 | options JSON 수동 수정 | 매우 낮음 | + +### 회의 논의 포인트 +- ✅ 이 부분은 정상 동작 확인됨. 추가 조치 불필요 +- (선택) process_id=null WO가 실데이터에 존재하는지 한번 쿼리 확인 + +--- + +## 이슈 2: 품질검사 이중 시스템 + +### v2.1 판정: 🟡 이중 시스템은 존재하나, 출하 연동은 불필요 (비즈니스 흐름상 품질검사는 출하 후) + +### v1 대비 변화 + +| 변경 사항 | 시기 | 내용 | +|-----------|------|------| +| `quality_document_locations.inspection_data` JSON 추가 | 2026-03-06 | 개소별 검사 데이터 저장 | +| `quality_document_locations.options` JSON 추가 | 2026-03-10 | 검사 옵션 확장 | +| QualityDocumentService 개선 | 2026-03 | inspectLocation() 등 기능 확장 | + +### v2.1 비즈니스 흐름 정정 + +``` +실제 흐름 (확인됨): + 생산 완료 → 출하 → 현장 시공 → 시공 완료 → 제품검사(FQC) + +∴ 품질검사는 출하 이후에 발생 → can_ship ↔ 품질검사 연동 불필요 +∴ v2에서 "출고 연동 미완"으로 판정한 것은 오판 → 연동 자체가 해당 없음 +``` + +**두 시스템 현재 상태**: + +| 항목 | 경로A: Inspection | 경로B: QualityDocument | +|------|-------------------|----------------------| +| **테이블** | `inspections` | `quality_documents` + `quality_document_locations` | +| **FK 연결** | `work_order_id` (작업지시) | `order_id` (수주) + `order_item_id` (개소) | +| **3월 업데이트** | 변경 없음 | ✅ 활발히 개선 중 | +| **용도** | IQC/PQC (공정 중 검사) | FQC (출하 후 제품 검사) | + +### 회의 논의 포인트 +- QualityDocument가 활발히 개발 중 → **경로B를 FQC 표준으로 확정하는 것이 합리적** +- 경로A(Inspection)는 IQC/PQC 전용으로 역할 한정, FQC는 경로B로 통일 +- ~~품질 완료 시 can_ship 연동~~ → **해당 없음** (품질검사는 출하 후 시공 완료 후 수행) + +--- + +## 이슈 3: 출고 시 can_ship 검증 누락 + +### v2.1 판정: ✅ 해결 완료 — 백엔드 can_ship 검증 + 프론트 버튼 비활성화 추가 + +### 코드 현황 (변경 없음) + +**canProceedToShip()**: `Shipment.php:220-223` — 정의만 존재 + +```php +public function canProceedToShip(): bool { + return $this->can_ship && $this->deposit_confirmed; +} +// grep 결과: 모델 정의 외 호출 0회 +``` + +**updateStatus()**: `ShipmentService.php:305-356` — can_ship 검증 없이 바로 업데이트 + +```php +public function updateStatus(int $id, string $status, ?array $additionalData = null): Shipment +{ + $shipment = Shipment::findOrFail($id); + // 🔴 can_ship 검증 없음 + $shipment->update(['status' => $status, ...]); +} +``` + +**프론트엔드**: `ShipmentDetail.tsx:304-314` — can_ship 참조 자체가 없음 + +```typescript +const STATUS_TRANSITIONS: Record = { + scheduled: 'ready', ready: 'shipping', shipping: 'completed', completed: null, +}; +// v2.1 확인: canShip 변수 자체가 컴포넌트에 없음 (grep 0건) +// can_ship=false여도 상태 변경 버튼이 무조건 표시됨 +``` + +### v2 신규 발견: 자동 출하에서 can_ship=true 자동 설정 + +```php +// createShipmentFromOrder (L732-744) +'can_ship' => true, // 자동 생성 시 무조건 true +``` + +→ 자동 생성된 출하는 can_ship=true이므로 문제 경감 +→ **그러나** 수동 생성 출하에서는 여전히 검증 없음 + +### 위험 시나리오 + +``` +수동 출하 생성 (can_ship=false) + → 사용자가 "출하대기" 클릭 → 검증 없이 ready + → "배송중" → "배송완료" → 재고 차감 시도 + → 재고 부족 시 soft fail (로그만, 상태는 completed) ❌ +``` + +### ~~수정안~~ → ✅ v2.1에서 적용 완료 + +**백엔드** (ShipmentService::updateStatus() L312-317): +```php +if (in_array($status, ['ready', 'shipping', 'completed']) && !$shipment->can_ship) { + throw new BadRequestHttpException(__('error.shipment.cannot_ship')); +} +``` + +**프론트엔드** (ShipmentDetail.tsx): +```typescript +{STATUS_TRANSITIONS[detail.status] && detail.canShip && ( + +)} +{STATUS_TRANSITIONS[detail.status] && !detail.canShip && ( + +)} +``` + +--- + +## 이슈 4: 출고 시 재고 차감 + +### v2.1 판정: ✅ 비활성화 완료 — 현재 시점에서 불필요한 로직 + +**비즈니스 흐름 정정** (v2.1): +``` +- 수주생산: 재고를 거치지 않음 (make-to-order) → 출하 시 재고 차감 불필요 +- 선생산 완성품: 재고에 입고 → 다른 WO의 자재 투입 시 차감 → 출하 시 차감 불필요 +∴ decreaseStockForShipment() 자체가 현재 시점에서 쓸 일이 없는 로직 +``` + +**조치**: `updateStatus()`에서 `decreaseStockForShipment()` 호출 비활성화 (TODO 주석으로 선생산 재검토 예약) + +### ~~회의 논의 포인트~~ → 해결됨 +- ~~Hard Fail vs Soft Fail~~ → 호출 자체 비활성화로 해소 +- 선생산 로직이 본격 가동되면 재검토 필요 + +--- + +## 이슈 5: LOT 추적 체계 + +### v2.1 판정: 🟢 선생산 정상 / 🟡 수주생산 재고입고 미경유 (v1 🔴 → v2 🟡 → v2.1 ⬆ 상향) + +### v2.1 정밀 검증 결과: LOT 자동 채번 **구현 확인** + +v2에서 "백엔드 LOT 저장 로직 없음"으로 판정했으나, **현재 코드에 구현되어 있음**. + +| 단계 | 메서드 | 위치 | 상태 | +|------|--------|------|------| +| LOT 자동 채번 | `generateLotNo()` | L1155-1176 | ✅ `KD-SA-YYMMDD-NN` 형식 | +| LOT options 저장 | `saveItemResults()` | L1105-1140 | ✅ `options.result.lot_no`에 저장 | +| 선생산 재고 입고 | `stockInFromProduction()` | L603-604 | ✅ `sales_order_id=null`일 때 호출 | +| StockLot 생성 | `increaseFromProduction()` | L349-398 | ✅ `work_order_id` FK 활용 | + +### 핵심 코드 근거 + +**1. LOT 자동 채번 (구현됨)** + +```php +// WorkOrderService.php:1155-1176 +private function generateLotNo(WorkOrder $workOrder): string +{ + $date = now()->format('ymd'); + $prefix = 'KD-SA'; + // 오늘 날짜의 마지막 LOT 번호 조회 → 시퀀스 증가 + return sprintf('%s-%s-%02d', $prefix, $date, $seq); +} +``` + +**2. saveItemResults()에서 LOT 저장 (구현됨)** + +```php +// WorkOrderService.php:1105-1140 +private function saveItemResults(WorkOrder $workOrder, ?array $resultData, int $userId): void +{ + $lotNo = $this->generateLotNo($workOrder); // ✅ LOT 자동 채번 + foreach ($items as $item) { + $itemResult = [ + 'lot_no' => $lotNo, // ✅ 모든 아이템에 LOT 저장 + 'good_qty' => $item->quantity, + // ... 기타 결과 데이터 + ]; + $options['result'] = $itemResult; + $item->save(); + } +} +``` + +**3. 선생산 vs 수주생산 분기 (핵심 발견)** + +```php +// WorkOrderService.php:602-605 +// 작업완료 시: 선생산(수주 없음) → 재고 입고 +if ($status === WorkOrder::STATUS_COMPLETED && !$workOrder->sales_order_id) { + $this->stockInFromProduction($workOrder); // ✅ 선생산만 호출 +} +``` + +### 두 경로의 LOT 추적 현황 + +**경로A: 선생산 (sales_order_id = null) — ✅ 정상 동작** + +``` +WO 완료 → saveItemResults() (LOT 채번 + 저장) + → stockInFromProduction() 호출 + → increaseFromProduction() → StockLot 생성 (work_order_id FK ✅) + → Stock 합계 갱신 + 거래 이력 기록 +``` + +**경로B: 수주 생산 (sales_order_id 존재) — 🟡 재고 미경유 (의도된 설계 가능성)** + +``` +WO 완료 → saveItemResults() (LOT 채번 + 저장 ✅) + → stockInFromProduction() 미호출 (수주 연결이므로 skip) + → syncOrderStatus() → Order PRODUCED + → createShipmentFromOrder() → ShipmentItem에 lot_no 복사 ✅ + → 출하 완료 시 decreaseStockForShipment() → ⚠️ 입고 없이 차감 시도 +``` + +→ 수주 생산은 make-to-order 방식으로 재고를 거치지 않는 **의도된 설계일 수 있음**. +→ 그러나 StockLot이 생성되지 않으므로 **재고 기반 LOT 추적은 불가**. + +### v1 대비 개선 사항 + +| 개선 | 시기 | 코드 근거 | +|------|------|-----------| +| `stock_lots.work_order_id` FK 추가 | 2026-02-21 | 마이그레이션 확인 | +| `inspections.work_order_id` FK 추가 | 2026-02-27 | 마이그레이션 확인 | +| `generateLotNo()` 백엔드 자동 채번 | v2.1 확인 | WorkOrderService:1155-1176 | +| `saveItemResults()` LOT 저장 | v2.1 확인 | WorkOrderService:1105-1140 | + +### 잔존 이슈 (v2.1 업데이트) + +1. **수주생산 재고입고 경로**: StockLot 미생성 → 의도된 설계 확인됨 (make-to-order). 선생산 로직 추후 검증 +2. **프론트 LOT 생성 코드**: WorkerScreen/actions.ts에서 별도 LOT 생성 → 백엔드와 이중 생성 가능성 (P1 #5-1) +3. ~~**출하 재고 차감**~~: ✅ decreaseStockForShipment() 비활성화로 해소 + +### ~~논의 필요 사항~~ → v2.1 확인됨 + +- **수주생산의 재고 미경유**: ✅ 의도된 설계 확인 (make-to-order, 주인이 있는 제품은 재고 미경유) +- 선생산 완성품은 재고 입고 → 다른 WO의 자재 투입 시 차감되는 흐름 (부품화) + +--- + +## 이슈 6: 출고품목 ↔ 수주품목 FK 부재 + +### v2.1 판정: ✅ 해결 완료 — order_item_id + work_order_item_id 컬럼/인덱스 추가 + +### ShipmentItem 컬럼 (v2.1 수정됨) + +``` +id, tenant_id, shipment_id(FK), seq, +item_code, item_name, floor_unit, specification, +quantity, unit, lot_no, stock_lot_id(index only), +order_item_id(index) 🆕, work_order_item_id(index) 🆕, remarks +``` + +- ✅ `order_item_id` → 추가됨 (nullable, 인덱스) +- ✅ `work_order_item_id` → 추가됨 (nullable, 인덱스) +- 마이그레이션: `2026_03_13_100000_add_order_item_id_to_shipment_items` +- 모델: ShipmentItem에 orderItem(), workOrderItem() BelongsTo 관계 추가 +- 데이터 입력: createShipmentFromOrder()에서 자동 매핑 + +### 추적 가능 여부 (v2.1 이후) + +| 질문 | 답변 가능 여부 | +|------|--------------| +| "출고 #1234에서 어떤 수주 품목이 출고됐나?" | ✅ order_item_id로 조회 | +| "수주 품목 #999는 어느 출고에서 출고됐나?" | ✅ 역추적 가능 | +| "수주 10개 품목 중 미출고 품목은?" | ✅ 집계 가능 | +| "부분 출고 진행률은?" | ✅ 계산 가능 | + +> ⚠️ 기존 데이터는 order_item_id=null. 소급 매칭은 추후 필요시 진행 + +### ~~자동 출하 생성 시 연결 기회 놓침~~ → ✅ v2.1에서 해결 + +```php +// createShipmentFromOrder (L756-768) — v2.1 수정 완료 +ShipmentItem::create([ + 'shipment_id' => $shipment->id, + 'item_code' => $woItem->item_id ? "ITEM-{$woItem->item_id}" : null, + 'quantity' => $result['good_qty'] ?? $woItem->quantity, + 'order_item_id' => $woItem->source_order_item_id, // ✅ 추가됨 + 'work_order_item_id' => $woItem->id, // ✅ 추가됨 +]); +``` + +### ~~수정안~~ → ✅ 적용 완료 + +- **마이그레이션**: `2026_03_13_100000_add_order_item_id_to_shipment_items` (인덱스만, FK 제약 없음) +- **모델**: ShipmentItem에 $fillable, $casts, orderItem()/workOrderItem() 관계 추가 +- **데이터 입력**: createShipmentFromOrder()의 WO 경로 + Order fallback 경로 모두 적용 + +--- + +## 전체 FK 연결 현황도 (v2 업데이트) + +``` +orders ──────────────────── order_items ──────── order_nodes + │ (order_id FK) │ (order_node_id FK) │ + │ │ │ + ├─── work_orders │ │ + │ │ (sales_order_id FK) │ │ + │ │ │ │ + │ └─── work_order_items │ │ + │ │ │ │ + │ │ source_order_item_id ──→ ❌ FK 없음 (인덱스만) + │ │ │ + │ inspections │ + │ │ (work_order_id FK ✅) [2026-02-27 추가] │ + │ │ (lot_no ← 연결 안됨 ❌) │ + │ │ + │ stock_lots │ + │ │ (work_order_id FK ✅) [2026-02-21 추가] ← 🆕 v1에서 미확인 + │ │ + ├─── quality_document_orders ──→ quality_documents │ + │ │ (order_id FK ✅) │ + │ │ │ + │ └─── quality_document_locations │ + │ │ (order_item_id FK ✅) │ + │ │ (inspection_data JSON 🆕 2026-03-06) │ + │ │ (options JSON 🆕 2026-03-10) │ + │ │ + └─── shipments │ + │ (order_id FK ✅, work_order_id FK ✅) │ + │ │ + └─── shipment_items │ + │ (shipment_id FK ✅) │ + │ (stock_lot_id → 인덱스만, FK 없음) │ + │ (order_item_id ✅ 인덱스) 🆕 v2.1 │ + │ (work_order_item_id ✅ 인덱스) 🆕 v2.1 │ +``` + +--- + +## 개선 우선순위 로드맵 (v2.1 업데이트) + +### P0 (즉시 - 운영 리스크) — v2.1 반영 + +| # | 작업 | 수정 범위 | 난이도 | 상태 | +|---|------|---------|--------|------| +| 1 | **can_ship 검증 추가** | ShipmentService::updateStatus() + ShipmentDetail.tsx | 하 | ✅ 완료 | +| 2 | ~~**재고 차감 실패 알림**~~ | decreaseStockForShipment() 호출 비활성화 — 수주생산은 재고 미경유, 선생산 완성품은 자재 투입 시 차감 | - | ✅ 비활성화 | + +### P1 (단기 - 데이터 정합성) — v2.1 반영 + +| # | 작업 | 수정 범위 | 난이도 | 상태 | +|---|------|---------|--------|------| +| 3 | ~~**생산 LOT 백엔드 자동 채번**~~ | generateLotNo() + saveItemResults() 이미 구현됨 | - | ✅ 확인 완료 | +| 4 | **수주생산 재고입고 경로 검토** | 수주생산은 재고 미경유 (make-to-order) — 의도된 설계. 선생산 로직은 추후 검증 | 중 | 🟡 설계 확인됨 | +| 5 | **shipment_items에 order_item_id/work_order_item_id 추가** | 마이그레이션 + ShipmentItem 모델 + createShipmentFromOrder() | 중 | ✅ 완료 | +| 5-1 | **프론트 LOT 이중 생성 정리** | WorkerScreen/actions.ts 프론트 LOT 생성 코드 제거 (백엔드 채번으로 통일) | 하 | 미착수 | + +### P2 (중기 - 구조 개선) — v2.1 품질검사 흐름 정정 반영 + +| # | 작업 | 수정 범위 | 난이도 | +|---|------|---------|--------| +| 6 | **품질검사 정본 = QualityDocument** | Inspection은 IQC/PQC 전용, FQC는 QualityDocument로 통일 | 상 | +| 7 | ~~**품질완료 → can_ship 자동 연동**~~ | ❌ 해당 없음 — 품질검사는 출하 후 시공 완료 후 수행 | - | +| 8 | **work_order_items.source_order_item_id FK** | 마이그레이션 1줄 | 하 | +| 9 | **stock_lot_id FK constraint 추가** | shipment_items 마이그레이션 | 하 | + +--- + +## 정상 동작 확인 항목 (v2) + +- ✅ 수주 → 생산지시 생성 (공정별 자동 분류) +- ✅ 작업지시 상태 관리 (유효 상태 전환 + auxiliary 필터링) +- ✅ **syncOrderStatus()**: 메인 WO 완료 → Order PRODUCED 자동 전환 +- ✅ **createShipmentFromOrder()**: PRODUCED 전환 시 출하 자동 생성 (중복 방지 포함) +- ✅ **ensureShipmentExists()**: 이미 PRODUCED인데 출하 없는 경우 보완 +- ✅ 자재 투입 재고 차감 (WorkOrderMaterialInput + StockService) +- ✅ 출고 완료 시 재고 차감 (FIFO + lockForUpdate + stock_transactions) +- ✅ 출고 완료 → 수주 상태 SHIPPED 자동 전환 +- ✅ 매출 자동 생성 (sales_recognition 조건부) +- ✅ 수주 상태별 수정/삭제 제한 +- ✅ 생산지시 되돌리기 (WorkOrder/Item/Result 삭제) +- 🆕 ✅ StockLot.work_order_id FK (생산→재고 연결 기반) +- 🆕 ✅ Inspection.work_order_id FK (검사→생산 연결) +- 🆕 ✅ generateLotNo() 백엔드 LOT 자동 채번 (v2.1 확인) +- 🆕 ✅ saveItemResults() LOT options 저장 (v2.1 확인) +- 🆕 ✅ 선생산 stockInFromProduction() → StockLot 생성 + work_order_id 연결 (v2.1 확인) + +--- + +## 회의 토론 안건 정리 + +### 즉시 결정 필요 (P0) — ✅ 해결됨 + +1. ~~**can_ship 검증**~~: ✅ 백엔드 + 프론트 수정 완료 +2. ~~**재고 차감 실패 처리**~~: ✅ decreaseStockForShipment() 비활성화 (수주생산=재고 미경유, 선생산=자재 투입 시 차감) + +### 설계 방향 결정 필요 (P1) — v2.1 업데이트 + +3. ~~**LOT 채번 규칙**~~: ✅ 이미 구현됨 (`KD-SA-YYMMDD-NN`, 백엔드 generateLotNo()) +4. **수주생산 재고입고 경로**: ✅ 수주생산은 재고 미경유 (make-to-order) — 의도된 설계 확인됨. 선생산 로직은 추후 검증 +5. ~~**ShipmentItem FK**~~: ✅ order_item_id + work_order_item_id 컬럼/인덱스 추가 완료 (FK 제약 없이 인덱스만) +5-1. **프론트 LOT 이중 생성**: WorkerScreen/actions.ts의 프론트 LOT 생성 코드 → 백엔드 통일 후 제거 + +### 방향성 논의 (P2) + +6. **품질 시스템 정본**: QualityDocument를 FQC 표준으로 확정하는 것에 이견 있는지? +7. ~~**품질→출하 자동 연동**~~: ❌ 해당 없음 — 비즈니스 흐름상 품질검사는 출하 후 시공 완료 후 수행되므로 can_ship 연동 불필요