diff --git a/INDEX.md b/INDEX.md index 5b7f3b7..6fde46d 100644 --- a/INDEX.md +++ b/INDEX.md @@ -234,6 +234,7 @@ DB 도메인별: | [20260314_api_quality_improvement_deploy.md](dev/changes/20260314_api_quality_improvement_deploy.md) | API 품질 개선 배포 — 테스트 56개 + N+1 최적화 3건 (근거 문서 포함) | | [20260315_eval_removal_safe_math_evaluator.md](dev/changes/20260315_eval_removal_safe_math_evaluator.md) | API 보안 개선 — eval() 3건 제거, SafeMathEvaluator 도입 | | [20260316_sales_policy_changes.md](changes/20260316_sales_policy_changes.md) | 영업 정책 변경 — 수당 구조 개편 및 무료 체험 폐지 | +| [20260316_stock_production_order.md](dev/changes/20260316_stock_production_order.md) | 재고생산관리 기능 추가 (STOCK 타입, 절곡 공정 자동, 생산지시 연동) | --- @@ -266,6 +267,7 @@ DB 도메인별: | [vehicle-api.md](frontend/api-specs/vehicle-api.md) | 차량관리 API 명세 (20개 엔드포인트: 차량목록, 차량일지, 정비이력, 사진) | | [stock-production-api.md](frontend/api-specs/stock-production-api.md) | 재고생산관리 API 명세 (기존 수주 API + STOCK 타입) | | [vehicle-react-implementation.md](plans/vehicle-react-implementation.md) | 차량관리 React 구현 요청서 (3개 메뉴, 컴포넌트 구조, 타입 정의) | +| [stock-production-react-request.md](plans/stock-production-react-request.md) | 재고생산관리 React 구현 요청서 (수주 화면 단순화, API 스펙 포함) | ### frontend/integration/ — 프론트엔드 개발 가이드 diff --git a/dev/changes/20260316_stock_production_order.md b/dev/changes/20260316_stock_production_order.md new file mode 100644 index 0000000..7a72b1f --- /dev/null +++ b/dev/changes/20260316_stock_production_order.md @@ -0,0 +1,139 @@ +# 재고생산관리 기능 추가 + +**날짜:** 2026-03-16 +**작업자:** Claude Code + +--- + +## 변경 개요 + +수주 없이 재고 목적으로 생산하는 경우를 관리하는 **재고생산관리** 기능을 추가했다. +기존 `orders` 테이블을 공유하며, `order_type_code = 'STOCK'`으로 일반 수주와 구분한다. + +### 설계 원칙 + +- **내부 오더(Internal Order)** 패턴 — 재고생산도 수주로 취급 +- 기존 테이블/API 재사용 — 별도 테이블/엔드포인트 없음 +- 하류 시스템(작업지시, 생산, 출하, 품질검사) 변경 없이 동작 + +--- + +## 수정된 파일 + +### 커밋 1: `feat: [order] 재고생산관리(STOCK) 타입 추가` + +| 파일 | 변경 내용 | +|------|----------| +| `app/Models/Orders/Order.php` | `TYPE_STOCK = 'STOCK'` 상수 추가 | +| `app/Http/Requests/Order/StoreOrderRequest.php` | STOCK validation 허용, `production_reason`/`target_stock_qty` 옵션 추가 | +| `app/Http/Requests/Order/UpdateOrderRequest.php` | 동일 | +| `app/Services/OrderService.php` | STK 채번, stats `order_type` 필터, 매출 생성 스킵 | +| `app/Http/Controllers/Api/V1/OrderController.php` | stats에 `order_type` 파라미터 전달 | + +### 커밋 2: `feat: [order] 재고생산 생산지시 자동 처리` + +| 파일 | 변경 내용 | +|------|----------| +| `app/Services/OrderService.php` | `store()`: STOCK → `site_name='재고생산'` 자동 설정 | +| `app/Services/OrderService.php` | `createProductionOrder()`: STOCK 분기 추가 (절곡 자동, project_name, scheduled_date) | +| `lang/ko/error.php` | `bending_process_not_found` 에러 메시지 추가 | +| `lang/en/error.php` | 동일 (영문) | + +--- + +## 상세 변경 사항 + +### 1. Order 모델 — 타입 상수 + +```php +public const TYPE_ORDER = 'ORDER'; // 수주 +public const TYPE_PURCHASE = 'PURCHASE'; // 발주 +public const TYPE_STOCK = 'STOCK'; // 재고생산 (신규) +``` + +### 2. 채번 규칙 + +| 타입 | 접두사 | 형식 | 예시 | +|------|--------|------|------| +| ORDER | `ORD` | `ORD{YYYYMMDD}{NNNN}` | `ORD202603160001` | +| STOCK | `STK` | `STK{YYYYMMDD}{NNNN}` | `STK202603160001` | + +### 3. store() — STOCK 자동 처리 + +```php +if ($isStock) { + $data['site_name'] = '재고생산'; +} +``` + +### 4. createProductionOrder() — STOCK 분기 + +| 항목 | ORDER (기존) | STOCK (신규) | +|------|-------------|-------------| +| 공정 매칭 | BOM item_id → process_items 매핑 | **절곡 공정 직접 할당** (BOM 스킵) | +| project_name | `order.site_name ?? client_name` | `'재고생산'` 고정 | +| scheduled_date | `order.delivery_date` | `now()` | +| 매출 생성 | `sales_recognition` 정책 적용 | **생성 안 함** | + +절곡 공정 조회: +```php +$bendingProcess = Process::where('tenant_id', $tenantId) + ->where('process_name', '절곡') + ->where('is_active', true) + ->first(); +``` + +### 5. stats() — order_type 필터 + +```php +public function stats(?string $orderType = null): array +``` + +`GET /api/v1/orders/stats?order_type=STOCK` 으로 재고생산 전용 통계 조회 가능. + +### 6. 매출 생성 스킵 + +```php +if ($status === Order::STATUS_CONFIRMED + && $order->order_type_code !== Order::TYPE_STOCK // STOCK 제외 + && $order->shouldCreateSaleOnConfirm()) { +``` + +--- + +## 영향범위 분석 + +| 영역 | 영향 | 이유 | +|------|------|------| +| 기존 수주(ORDER) | ❌ 없음 | `$isStock` 조건 분기, else 블록에서 기존 코드 그대로 실행 | +| 기존 발주(PURCHASE) | ❌ 없음 | 동일 | +| 작업지시(WorkOrder) | ✅ 정상 동작 | `sales_order_id` FK로 연결, 절곡 공정 할당됨 | +| 생산/품질검사 | ❌ 없음 | WorkOrder 기반 하류 시스템, Order 타입 무관 | +| 출하(Shipment) | ❌ 없음 | WorkOrder 참조, Order.site_name 미사용 | +| 캘린더 | ✅ 표시됨 | `project_name='재고생산'`, `scheduled_date=now()` | +| 생산지시 목록 | ✅ 표시됨 | `site_name='재고생산'`으로 현장명 표시 | + +--- + +## 테스트 체크리스트 + +- [x] STOCK 수주 생성 → `order_no` STK 접두사 확인 +- [x] STOCK 수주 생성 → `site_name='재고생산'` 자동 설정 확인 +- [ ] STOCK 수주 확정 → 매출 자동 생성 안 됨 확인 +- [ ] STOCK 생산지시 생성 → 절곡 공정 자동 선택 확인 +- [ ] STOCK 생산지시 생성 → `project_name='재고생산'` 확인 +- [ ] STOCK 생산지시 생성 → `scheduled_date=today` 확인 +- [ ] 기존 ORDER 수주 생산지시 → 기존 BOM 매칭 정상 동작 확인 +- [ ] 생산지시 목록에서 STOCK 건 표시 확인 + +--- + +## 관련 문서 + +- [재고생산관리 기능 설명](../../features/sales/stock-production.md) +- [재고생산관리 API 명세](../../frontend/api-specs/stock-production-api.md) +- [프론트엔드 구현 요청서](../../frontend/requests/stock-production-react-request.md) + +--- + +**최종 업데이트**: 2026-03-16 diff --git a/plans/stock-production-react-request.md b/plans/stock-production-react-request.md new file mode 100644 index 0000000..d8eedbe --- /dev/null +++ b/plans/stock-production-react-request.md @@ -0,0 +1,341 @@ +# 재고생산관리 React 구현 요청서 + +> **작성일**: 2026-03-16 +> **요청자**: R&D 실장 +> **대상**: 프론트엔드 개발자 +> **우선순위**: 🟡 중요 +> **API 상태**: ✅ 구현 완료 (개발서버 배포됨) + +--- + +## 1. 개요 + +수주 없이 **재고 목적으로 생산**하는 경우를 관리하는 메뉴를 추가한다. +기존 수주관리 API를 그대로 사용하며, `order_type_code = 'STOCK'`으로 구분한다. + +### 1.1 구현 대상 + +| 메뉴 | 위치 | 설명 | 난이도 | +|------|------|------|:------:| +| **재고생산관리** | 판매관리 > 재고생산관리 | 재고생산 등록/목록/상세/수정/삭제 | **낮음** (수주 화면 복제 후 단순화) | + +### 1.2 참고 문서 + +| 문서 | 경로 | 용도 | +|------|------|------| +| **API 명세** (필독) | `docs/frontend/api-specs/stock-production-api.md` | 전체 엔드포인트, 요청/응답 형식 | +| 기능 설명 | `docs/features/sales/stock-production.md` | 비즈니스 개념, 수주와의 관계 | + +### 1.3 핵심 원칙 + +``` +✅ 수주관리 화면을 복제한 뒤 불필요한 필드 제거 +✅ API는 기존 /api/v1/orders 그대로 사용 (order_type=STOCK 필터) +✅ 생성 시 order_type_code: 'STOCK' 필수 전송 +❌ 별도 API 엔드포인트 없음 +❌ 거래처, 견적, 배송, 할인, 개소(Node) 관련 UI 불필요 +``` + +--- + +## 2. 파일 구조 (제안) + +기존 수주관리 구조를 따른다. + +``` +src/ +├── app/[locale]/(protected)/sales/order-management-sales/ +│ └── stocks/ # 재고생산관리 (신규) +│ ├── page.tsx # 목록 페이지 +│ └── [id]/ +│ ├── page.tsx # 상세 페이지 +│ └── production-order/ +│ └── page.tsx # 생산지시 생성 페이지 +│ +├── components/orders/ +│ └── StockProductionRegistration.tsx # 재고생산 등록/수정 폼 (신규) +│ └── (기존 actions.ts에 함수 추가 또는 별도 stockActions.ts) +``` + +> **대안**: `stocks/` 대신 기존 수주관리 페이지에서 `order_type` 탭으로 분리하는 방식도 가능. 실장 판단에 따름. + +--- + +## 3. 화면별 구현 가이드 + +### 3.1 재고생산 목록 페이지 + +**경로**: `/sales/order-management-sales/stocks` + +**수주관리 목록 페이지를 복제**한 뒤 다음을 변경: + +| 항목 | 수주관리 (현재) | 재고생산 (변경) | +|------|---------------|---------------| +| 페이지 제목 | 수주관리 | **재고생산관리** | +| API 호출 | `getOrders()` | `getOrders({ order_type: 'STOCK' })` | +| 통계 API | `getOrderStats()` | `getOrderStats({ order_type: 'STOCK' })` → `GET /api/v1/orders/stats?order_type=STOCK` | +| 표시 컬럼 | 수주번호, 거래처, 현장명, 수량, 납기, 금액... | **생산번호, 품목, 수량, 생산사유, 등록일, 상태** | +| 통계 카드 | 이번달 수주금액, 분할대기... | 전체, 등록, 확정, 진행중, 완료 (또는 간소화) | + +**목록 테이블 컬럼**: + +| 컬럼 | 데이터 | 비고 | +|------|--------|------| +| 번호 | 글로벌 인덱스 | | +| 생산번호 | `order_no` (STK...) | 배지 스타일 | +| 품목 | 대표 `items[0].item_name` + (외 N건) | | +| 수량 | 총 수량 | | +| 생산 사유 | `options.production_reason` | 없으면 `-` | +| 등록일 | `created_at` | YYYY-MM-DD | +| 상태 | `status_code` | 배지 (수주와 동일 색상) | +| 작업 | 상세보기, 삭제 | | + +**제거할 컬럼**: 거래처, 현장명, 납기, 금액 + +### 3.2 재고생산 등록/수정 폼 + +**수주 등록 폼(`OrderRegistration.tsx`)을 복제**한 뒤 다음을 변경: + +#### 제거할 섹션 + +``` +❌ 거래처 선택 (client_id, client_name, client_contact) +❌ 현장명 (site_name) — API가 '재고생산'으로 자동 설정 +❌ 견적 선택 (quote_id) / 견적에서 가져오기 +❌ 배송 정보 (delivery_date, delivery_method_code) +❌ 운임비용 (options.shipping_cost_code) +❌ 수신자 정보 (options.receiver, receiver_contact, shipping_address) +❌ 할인 (discount_rate, discount_amount) +❌ 금액 계산 (supply_amount, tax_amount, total_amount) +❌ 매출 인식 (sales_recognition) +❌ 개소/구역 (OrderNode) 트리 구조 +``` + +#### 유지할 섹션 + +``` +✅ 생산 사유 (options.production_reason) — 텍스트 입력 +✅ 목표 재고 수량 (options.target_stock_qty) — 숫자 입력 +✅ 비고 (memo) — 텍스트 입력 +✅ 품목 목록 (items[]) — 품목 선택 + 수량 입력 +``` + +#### 품목 입력 테이블 + +| 필드 | 타입 | 필수 | 비고 | +|------|------|:----:|------| +| 품목 | 품목 선택 (ItemAddDialog) | ✅ | item_id, item_name, item_code | +| 규격 | 텍스트 | - | specification | +| 수량 | 숫자 | ✅ | quantity | +| 단위 | 텍스트 | - | unit (기본: EA) | + +> **단가/금액은 불필요**하지만, API validation에서 `unit_price`가 required이므로 `0`을 전송 + +#### API 요청 예시 + +```json +{ + "order_type_code": "STOCK", + "memo": "봄 시즌 대비 재고 확보", + "options": { + "production_reason": "시즌 대비", + "target_stock_qty": 500 + }, + "items": [ + { + "item_id": 10, + "item_name": "25mm 알루미늄 블라인드", + "specification": "W1000 x H2000", + "quantity": 100, + "unit_price": 0, + "unit": "EA" + } + ] +} +``` + +### 3.3 재고생산 상세 페이지 + +**수주 상세(`OrderSalesDetailView.tsx`)를 복제**한 뒤 단순화: + +| 섹션 | 표시 | +|------|------| +| 생산번호 (order_no) | ✅ | +| 상태 (status_code) | ✅ 배지 | +| 생산 사유 | ✅ `options.production_reason` | +| 목표 재고 수량 | ✅ `options.target_stock_qty` | +| 비고 | ✅ `memo` | +| 품목 목록 | ✅ 테이블 (품목명, 규격, 수량) | +| 거래처/현장/납기/금액 | ❌ 제거 | +| 개소/구역 트리 | ❌ 제거 | + +**액션 버튼**: +- 수정 (DRAFT 상태만) +- 삭제 (DRAFT 상태만) +- 확정 (`PATCH /api/v1/orders/{id}/status` → `{ "status": "CONFIRMED" }`) +- 생산지시 생성 (CONFIRMED 상태만) → 기존 생산지시 생성 페이지 재사용 + +### 3.4 생산지시 생성 페이지 + +**기존 `[id]/production-order/page.tsx`를 재사용** 가능. + +STOCK 수주의 생산지시는 API가 자동 처리하므로 프론트에서 특별한 분기 불필요: + +| 항목 | API 자동 처리 | +|------|-------------| +| 공정 선택 | 절곡 공정 자동 선택 (process_ids 전달 불필요) | +| 현장명 | `'재고생산'` 고정 | +| 작업예정일 | `now()` 자동 (scheduled_date 전달 불필요) | + +> 단, 공정 매칭 미리보기 UI에서 STOCK 수주가 BOM 없이도 "절곡" 공정으로 표시되도록 조건 분기 필요할 수 있음. + +### 3.5 생산지시 목록 — STOCK 건 표시 (기존 페이지 수정) + +**경로**: `/sales/order-management-sales/production-orders/page.tsx` + +STOCK 타입 재고생산의 생산지시도 이 목록에 표시된다. 변경 필요 사항: + +| 컬럼 | 현재 | STOCK 건 표시 | +|------|------|-------------| +| 현장명 | `siteName` | `'재고생산'` (API가 자동 설정하므로 변경 불필요) | +| 거래처 | `clientName` | 빈 값 또는 `-` | +| 납기 | `deliveryDate` | `-` 표시 (STOCK은 delivery_date 없음) | +| 생산지시일 | `productionOrderedAt` | 정상 표시 | + +**구현 방법**: API 응답에 `order_type_code`가 이미 포함됨. 프론트 types에 추가: + +```typescript +// types.ts 수정 +interface ApiProductionOrder { + // ... 기존 필드 + order_type_code?: string; // 추가 +} + +// transform 함수에서 +orderTypeCode: data.order_type_code || 'ORDER', +``` + +테이블 렌더링에서: + +```typescript +// 납기 컬럼 +{item.orderTypeCode === 'STOCK' ? '-' : item.deliveryDate} + +// 거래처 컬럼 +{item.orderTypeCode === 'STOCK' ? '-' : item.clientName} +``` + +--- + +## 4. 메뉴 등록 + +메뉴 위치: + +``` +판매관리 +├── 거래처관리 +├── 견적관리 +├── 수주관리 +├── 재고생산관리 ← 신규 (수주관리 아래) +└── 단가관리 +``` + +> 메뉴 등록은 MNG 메뉴 동기화 기능으로 별도 처리. 프론트에서는 라우트만 구현. + +--- + +## 5. 수주관리와의 차이 요약 + +``` +┌─ 수주관리 ──────────────────┐ ┌─ 재고생산관리 ───────────────┐ +│ │ │ │ +│ 거래처 선택 │ │ 생산 사유 (텍스트) │ +│ 현장명 │ │ 목표 재고 수량 │ +│ 견적 연결 │ │ 비고 │ +│ 배송/납기/운임 │ │ │ +│ 할인/금액 계산 │ ├──────────────────────────────┤ +│ 매출 인식 방식 │ │ 품목 목록 │ +│ │ │ - 품목 선택 │ +│ 개소/구역 트리 (OrderNode) │ │ - 수량만 입력 │ +│ 품목 목록 (상세) │ │ (단가/금액/할인 불필요) │ +│ - 단가, 할인, 금액 계산 │ │ (개소/구역 불필요) │ +│ - floor_code, symbol_code │ │ │ +│ │ └──────────────────────────────┘ +└──────────────────────────────┘ +``` + +--- + +## 6. API 빠른 참조 + +### 6.1 목록 조회 + +``` +GET /api/v1/orders?order_type=STOCK&page=1&size=20 +``` + +### 6.2 통계 + +``` +GET /api/v1/orders/stats?order_type=STOCK +``` + +### 6.3 생성 + +``` +POST /api/v1/orders +Content-Type: application/json + +{ + "order_type_code": "STOCK", + "memo": "...", + "options": { "production_reason": "...", "target_stock_qty": 500 }, + "items": [{ "item_name": "...", "quantity": 100, "unit_price": 0 }] +} +``` + +### 6.4 상태 변경 + +``` +PATCH /api/v1/orders/{id}/status +{ "status": "CONFIRMED" } +``` + +### 6.5 생산지시 생성 + +``` +POST /api/v1/orders/{id}/production-order +{ "priority": "normal" } +``` + +> 공정/예정일은 API가 자동 처리 (절곡 공정, scheduled_date=now()) + +### 6.6 수정/삭제 + +``` +PUT /api/v1/orders/{id} — 수정 +DELETE /api/v1/orders/{id} — 삭제 +``` + +--- + +## 7. 구현 체크리스트 + +- [ ] `stocks/page.tsx` — 재고생산 목록 페이지 +- [ ] `stocks/[id]/page.tsx` — 재고생산 상세 페이지 +- [ ] `StockProductionRegistration.tsx` — 등록/수정 폼 (수주 폼 단순화) +- [ ] Server Actions — `getOrders({ order_type: 'STOCK' })` 등 (기존 actions.ts 활용) +- [ ] 생산지시 목록 — STOCK 건 납기 `-` 표시, `order_type_code` 타입 추가 +- [ ] 메뉴 라우트 등록 + +--- + +## 관련 문서 + +- [API 명세 (상세)](../frontend/api-specs/stock-production-api.md) +- [기능 설명](../features/sales/stock-production.md) +- [개발 변경이력](../dev/changes/20260316_stock_production_order.md) + +--- + +**최종 업데이트**: 2026-03-16