From 8d30539ad8f3ea1b200234536522cbcc91daba8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Fri, 20 Mar 2026 16:09:31 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20[=EC=9E=85=EA=B3=A0=C3=97=EC=88=98?= =?UTF-8?q?=EC=9E=85=EA=B2=80=EC=82=AC]=20=EA=B2=80=EC=82=AC=EC=99=84?= =?UTF-8?q?=EB=A3=8C=E2=86=92=EC=9E=AC=EA=B3=A0=20=EC=9E=90=EB=8F=99=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=84=A4=EA=B3=84=20=EB=B0=98=EC=98=81=20?= =?UTF-8?q?(2026-03-20=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../receiving-inspection-integration-plan.md | 125 ++++++++++++------ 1 file changed, 82 insertions(+), 43 deletions(-) diff --git a/dev/dev_plans/receiving-inspection-integration-plan.md b/dev/dev_plans/receiving-inspection-integration-plan.md index 1eb6e2b..23dcbd8 100644 --- a/dev/dev_plans/receiving-inspection-integration-plan.md +++ b/dev/dev_plans/receiving-inspection-integration-plan.md @@ -1,7 +1,7 @@ # 입고등록 × 수입검사 연동 계획 > **작성일**: 2026-03-17 -> **상태**: 설계 중 +> **상태**: 구현 완료 (Phase 1 데이터 매핑 제외) > **담당**: R&D실 (API) + 프론트엔드 개발자 (React) --- @@ -19,12 +19,13 @@ | `DocumentService::resolve()` | ✅ | 품목 ID → 수입검사 템플릿 자동 매칭 | | `ReceivingService::getItemsWithInspectionTemplate()` | ✅ | 입고 목록에서 `has_inspection_template` 플래그 반환 | | React `checkInspectionTemplate()` | ✅ | 입고 상세 로드 시 API 호출 → `hasInspectionTemplate` 상태 설정 | -| React 수입검사 버튼 렌더링 | ✅ | `hasInspectionTemplate === true` → "수입검사하기" + "수입검사성적서 보기" 버튼 표시 | +| React 수입검사 버튼 렌더링 | ✅ | 템플릿 존재 또는 검사결과 있으면 버튼 표시 | | `ImportInspectionInputModal` | ✅ | 수입검사 입력 모달 (검사항목 동적 로드) | | `InspectionModal` | ✅ | 수입검사 성적서 보기 모달 | | MNG 중복 검증 | ✅ | 동일 category 내 같은 품목 중복 연결 방지 | +| 검사완료 → `inspection_completed` 상태 전이 | ✅ | 검사완료 시 자동 상태 변경 | +| 검사완료 → 재고 자동 생성 | ✅ | `inspection_completed` 상태에서 Stock/StockLot 자동 생성 | | **품목 ↔ 템플릿 매핑 데이터** | ❌ | `linked_item_ids`에 품목 미연결 (27종 전부) | -| 검사결과 → 입고 반영 API | ⚠️ | options에 저장은 되나 상태 전이 보강 필요 | ### 1.3 핵심 포인트 @@ -49,25 +50,61 @@ API DocumentService::resolve() └─ 출력: { template: {...}, is_new: true/false } ``` -### 2.2 입고 → 수입검사 흐름 (구현됨) +### 2.2 입고 → 수입검사 → 재고 흐름 (구현 완료) ``` -입고 상세 로드 (ReceivingDetail.tsx) - ↓ loadData() → getReceivingById(id) - ↓ result.data.itemId 확인 - ↓ checkInspectionTemplate(itemId) 호출 - ↓ API: GET /api/v1/documents/resolve?category=incoming_inspection&item_id={itemId} +입고 등록 (receiving_pending) ↓ - ├─ hasTemplate: true - │ → hasInspectionTemplate = true - │ → customHeaderActions 렌더링: - │ [수입검사하기] → ImportInspectionInputModal 오픈 - │ [수입검사성적서 보기] → InspectionModal 오픈 +입고 상세 로드 (ReceivingDetail.tsx) + ↓ checkInspectionTemplate(itemId) + ↓ + ├─ 템플릿 존재 또는 검사결과 있음 + │ → [수입검사하기] + [수입검사성적서 보기] 버튼 표시 │ - └─ hasTemplate: false - → 버튼 미표시 (수입검사 불필요) + └─ 템플릿 없고 검사결과 없음 + → 버튼 미표시 + ↓ +[수입검사하기] → ImportInspectionInputModal + ↓ 검사항목 입력 → 검사완료 버튼 + ↓ +saveInspectionData() + ↓ Step 1: POST /v1/documents/upsert (검사 데이터 저장) + ↓ Step 2: PUT /v1/receivings/{id} (status → inspection_completed) + ↓ +ReceivingService::update() + ↓ inspection_completed 감지 → 재고 반영 대상 + ↓ StockService::increaseFromReceiving() + ↓ +Stock + StockLot 자동 생성 → 재고현황에 표시 ``` +### 2.3 상태 흐름 (확정) + +``` +receiving_pending ──수입검사완료──→ inspection_completed ──(재고 자동 생성) +(입고대기) (검사완료) + +receiving_pending ──입고처리──→ completed ──(재고 자동 생성) +(입고대기) (입고완료) +``` + +> **핵심**: `inspection_completed`와 `completed` 두 상태 모두 재고 생성을 트리거한다. + +### 2.4 재고 연동 조건 (`ReceivingService::update()`) + +```php +$stockStatuses = ['completed', 'inspection_completed']; +$wasCompleted = in_array($oldStatus, $stockStatuses); +$isCompletingReceiving = in_array($newStatus, $stockStatuses) && !$wasCompleted; +``` + +| 상태 변경 | 재고 동작 | +|----------|----------| +| `receiving_pending` → `inspection_completed` | Stock/StockLot **생성** | +| `receiving_pending` → `completed` | Stock/StockLot **생성** | +| `inspection_completed` → `receiving_pending` | 재고 **차감** (전량) | +| `inspection_completed` → `inspection_completed` (수량 변경) | 재고 **조정** (차이분) | + > **view/edit 모드에서만 버튼 표시.** new 모드에서는 아직 품목이 저장되지 않았으므로 미표시. --- @@ -134,55 +171,52 @@ MNG 문서양식관리에서 27종 수입검사 템플릿의 `linked_item_ids` | MNG에서 linked_item_ids 설정 | R&D실 | 각 템플릿 수정 | | 매핑 검증 (누락/중복 체크) | R&D실 | API로 검증 | -### Phase 2: API 보강 (백엔드, 필요 시) - -> Phase 1 완료 후 실제 검사 플로우를 테스트하며 부족한 부분을 보강한다. +### Phase 2: API 보강 (백엔드) — ✅ 완료 | 작업 | 상태 | 설명 | |------|:----:|------| | `DocumentService::resolve()` | ✅ 완료 | 품목 → 템플릿 매칭 | +| `DocumentService::formatTemplateForReact()` | ✅ 완료 | 클로저 스코프 수정 (`$methodCodes`) | | `ReceivingService::getItemsWithInspectionTemplate()` | ✅ 완료 | 입고 목록 `has_inspection_template` 플래그 | -| `checkInspectionTemplate()` React 호출 | ✅ 완료 | 입고 상세에서 버튼 표시 제어 | -| 수입검사 결과 → Receiving options 반영 | ⚠️ 보강 필요 | 검사완료 시 inspectionDate/Result 자동 설정 | -| 입고 상태 전이 (inspection_pending) | ⚠️ 보강 필요 | 검사 시작 → 검사대기, 검사완료 → 입고대기 | +| `Receiving::STATUSES` | ✅ 완료 | `inspection_completed` 상태 추가 | +| `ReceivingService::update()` | ✅ 완료 | `inspection_completed` 상태에서 재고 자동 생성 | +| `StoreReceivingRequest` | ✅ 완료 | `order_qty` required 검증, `inspection_completed` 허용 | +| 수입검사 결과 → Receiving options 반영 | ✅ 완료 | `saveInspectionData()`에서 자동 설정 | -### Phase 3: React UI 보강 (프론트엔드, 필요 시) - -> 버튼 표시 및 모달 연동은 이미 구현됨. 검사 결과 저장 후 입고 데이터 자동 반영 부분만 보강. +### Phase 3: React UI 보강 (프론트엔드) — ✅ 완료 | 작업 | 상태 | 설명 | |------|:----:|------| -| 수입검사하기 버튼 | ✅ 완료 | `hasInspectionTemplate` 기반 조건부 렌더링 | +| 수입검사하기 버튼 | ✅ 완료 | 템플릿 존재 또는 검사결과 있으면 표시 | | ImportInspectionInputModal | ✅ 완료 | 검사항목 동적 로드 + 입력 | | InspectionModal (성적서 보기) | ✅ 완료 | 저장된 검사 성적서 조회 | -| 검사 결과 저장 후 입고 자동 갱신 | ⚠️ 보강 필요 | `handleImportInspectionSave()` → `loadData()` 이미 호출, API 보강 후 자동 반영 | +| 검사완료 → `inspection_completed` 상태 전이 | ✅ 완료 | `saveInspectionData()` → status 자동 변경 | +| 입고 목록 삭제 기능 | ✅ 완료 | 체크박스 선택 → 삭제 버튼 표시 | +| 단위(unit) → API 전달 | ✅ 완료 | `transformFrontendToApi()`에서 `unit` 매핑 | --- ## 5. 관련 API 엔드포인트 -### 5.1 기존 (구현 완료) +### 5.1 구현 완료 ``` GET /api/v1/documents/resolve params: { category: 'incoming_inspection', item_id: 101 } → 해당 품목의 수입검사 템플릿 + 기존 문서 반환 -POST /api/v1/documents - → 검사 결과 문서 저장 +POST /api/v1/documents/upsert + → 검사 데이터 저장 (sections/items/field_values) + +PUT /api/v1/receivings/{id} + body: { status: 'inspection_completed', inspection_status, inspection_date, inspection_result } + → 상태 변경 + 재고 자동 생성 (inspection_completed 시) GET /api/v1/items/{id} → 응답에 has_inspection_template 포함 ``` -### 5.2 보강 필요 - -``` -PATCH /api/v1/receivings/{id}/inspection-result (신규) - body: { inspection_date, inspection_result, document_id? } - → Receiving.options의 검사일/검사결과 업데이트 - → 상태 전이 (inspection_pending → receiving_pending) -``` +> 별도 `PATCH /inspection-result` 엔드포인트는 불필요. `saveInspectionData()`가 `documents/upsert` + `receivings/{id}` PUT 2단계로 처리한다. --- @@ -205,11 +239,15 @@ PATCH /api/v1/receivings/{id}/inspection-result (신규) └──────────────────────────────────────────────────────────────────┘ ``` -### 버튼 렌더링 조건 (ReceivingDetail.tsx:882) +### 버튼 렌더링 조건 (ReceivingDetail.tsx) ```typescript +const showInspectionActions = hasInspectionTemplate + || !!detail?.inspectionResult + || !!detail?.inspectionDate; + const customHeaderActions = - (isViewMode || isEditMode) && detail && hasInspectionTemplate ? ( + (isViewMode || isEditMode) && detail && showInspectionActions ? (
@@ -220,10 +258,11 @@ const customHeaderActions = | 조건 | 결과 | |------|------| | new 모드 | 버튼 미표시 (품목 미저장) | -| view/edit + `hasInspectionTemplate=false` | 버튼 미표시 | +| view/edit + 템플릿 없고 검사결과 없음 | 버튼 미표시 | | view/edit + `hasInspectionTemplate=true` | **두 버튼 모두 표시** | +| view/edit + 검사결과 또는 검사일 있음 | **두 버튼 모두 표시** (합격 후에도 유지) | -> **핵심**: MNG에서 해당 품목의 수입검사 템플릿에 `linked_item_ids`를 설정하면 버튼이 자동 표시된다. +> **핵심**: 템플릿이 있거나, 이미 검사가 수행된 경우 버튼이 표시된다. --- @@ -236,4 +275,4 @@ const customHeaderActions = --- -**최종 업데이트**: 2026-03-17 +**최종 업데이트**: 2026-03-20