# 재고생산관리 API 명세

> **작성일**: 2026-03-16
> **상태**: 설계 확정
> **대상**: React 프론트엔드 개발자

---

## 1. 개요

### 1.1 목적

재고생산관리는 **수주 없이 재고 목적으로 생산**하는 경우를 위한 기능이다.
기존 수주관리(Order) API를 **그대로 사용**하되, `order_type_code: 'STOCK'`으로 구분한다.

### 1.2 핵심 원칙

- 별도 API 엔드포인트 없음 — 기존 `/api/v1/orders` 사용
- `order_type_code` 필터로 수주(`ORDER`)와 재고생산(`STOCK`)을 분리
- 화면은 수주관리를 **단순화**한 형태 (거래처, 견적, 배송, 할인 등 불필요)
- 하류 시스템(작업지시, 생산, 출하)은 **동일하게 동작**

---

## 2. API 엔드포인트

> **기본 URL**: `/api/v1/orders`
> **인증**: `Bearer Token` (Sanctum) + `API Key`

### 2.1 목록 조회

```
GET /api/v1/orders?order_type=STOCK
```

| 파라미터 | 타입 | 필수 | 설명 |
|----------|------|:----:|------|
| `order_type` | string | ✅ | `STOCK` 고정 |
| `page` | int | - | 페이지 (기본: 1) |
| `size` | int | - | 페이지 크기 (기본: 20) |
| `q` | string | - | 검색어 (생산번호, 메모) |
| `status` | string | - | 상태 필터 (`DRAFT`, `CONFIRMED` 등) |
| `date_from` | date | - | 등록일 시작 |
| `date_to` | date | - | 등록일 종료 |

**응답 예시**:

```json
{
  "success": true,
  "message": "message.order.fetched",
  "data": {
    "data": [
      {
        "id": 42,
        "order_no": "STK202603160001",
        "order_type_code": "STOCK",
        "status_code": "DRAFT",
        "quantity": "100.0000",
        "memo": "봄 시즌 대비 재고 확보",
        "options": {
          "production_reason": "시즌 대비",
          "target_stock_qty": 500
        },
        "items": [
          {
            "id": 1,
            "item_name": "25mm 알루미늄 블라인드",
            "specification": "W1000 x H2000",
            "quantity": "100.0000",
            "unit_price": "15000.00"
          }
        ],
        "created_at": "2026-03-16T10:30:00Z"
      }
    ],
    "current_page": 1,
    "last_page": 1,
    "total": 1
  }
}
```

---

### 2.2 통계 조회

```
GET /api/v1/orders/stats?order_type=STOCK
```

| 파라미터 | 타입 | 필수 | 설명 |
|----------|------|:----:|------|
| `order_type` | string | ✅ | `STOCK` 고정 |

**응답 예시**:

```json
{
  "success": true,
  "data": {
    "total": 15,
    "draft": 3,
    "confirmed": 5,
    "in_progress": 4,
    "completed": 2,
    "cancelled": 1,
    "total_amount": 0,
    "confirmed_amount": 0
  }
}
```

---

### 2.3 생성

```
POST /api/v1/orders
```

**요청 본문**:

```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"
    }
  ]
}
```

**필수 필드**:

| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `order_type_code` | string | ✅ | `STOCK` 고정 |
| `items` | array | ✅ | 생산할 품목 목록 |
| `items[].item_name` | string | ✅ | 품목명 |
| `items[].quantity` | number | ✅ | 수량 |
| `items[].unit_price` | number | ✅ | 단가 (재고생산은 `0` 가능) |

**선택 필드**:

| 필드 | 타입 | 설명 |
|------|------|------|
| `memo` | string | 비고 |
| `options.production_reason` | string | 생산 사유 |
| `options.target_stock_qty` | number | 목표 재고 수량 |
| `items[].item_id` | int | 품목 마스터 ID |
| `items[].specification` | string | 규격 |
| `items[].unit` | string | 단위 |

**사용하지 않는 필드** (수주 전용):

```
❌ client_id, client_name, client_contact  → 거래처 없음
❌ site_name                               → API가 '재고생산'으로 자동 설정
❌ quote_id                                → 견적 없음
❌ delivery_date, delivery_method_code     → 납기/배송 불필요
❌ discount_rate, discount_amount          → 할인 없음
❌ sales_recognition                       → 매출 인식 불필요
❌ options.shipping_cost_code              → 운임비용 불필요
❌ options.receiver, receiver_contact      → 수신자 불필요
❌ options.shipping_address                → 배송지 불필요
```

> **자동 생성**: `order_no`는 `STK{YYYYMMDD}{NNNN}` 형식으로 서버에서 자동 생성

---

### 2.4 단건 조회

```
GET /api/v1/orders/{id}
```

기존 수주 조회와 동일. `order_type_code`가 `STOCK`인지 프론트에서 확인.

---

### 2.5 수정

```
PUT /api/v1/orders/{id}
```

생성과 동일한 필드 사용. `order_type_code`는 변경하지 않는다.

---

### 2.6 삭제

```
DELETE /api/v1/orders/{id}
```

기존 수주 삭제와 동일.

---

### 2.7 상태 변경

```
PATCH /api/v1/orders/{id}/status
```

```json
{
  "status": "CONFIRMED"
}
```

**상태 흐름** (수주와 동일):

```
DRAFT → CONFIRMED → IN_PROGRESS → COMPLETED
  └─────→ CANCELLED ──→ DRAFT (복구)
```

> **재고생산 특수**: `CONFIRMED` 상태 진입 시 매출 자동 생성이 **발생하지 않음**

---

### 2.8 생산지시 생성

```
POST /api/v1/orders/{id}/production-order
```

재고생산은 **절곡 공정이 자동 선택**된다 (API에서 처리). `process_ids` 전달 불필요.

```json
{
  "priority": "normal",
  "memo": "재고생산 작업"
}
```

---

**API 자동 처리 항목** (STOCK 타입):

| 항목 | 일반 수주 | 재고생산 (자동) |
|------|----------|---------------|
| 현장명 (`project_name`) | `site_name` 또는 `client_name` | `'재고생산'` 고정 |
| 공정 | BOM item_id → process_items 매칭 | **절곡 공정 자동 선택** |
| 작업예정일 (`scheduled_date`) | `delivery_date` | **생성일 (now())** |
| 매출 생성 | `sales_recognition` 정책 적용 | **생성 안 함** |

> 프론트에서 `process_ids`, `scheduled_date`를 전달하지 않아도 API가 자동 처리

---

## 3. 채번 규칙

| 주문 유형 | 접두사 | 예시 |
|----------|--------|------|
| 수주 (ORDER) | `ORD` | `ORD202603160001` |
| 재고생산 (STOCK) | `STK` | `STK202603160001` |

---

## 4. 화면 설계 가이드

### 4.1 수주관리 화면 vs 재고생산관리 화면

```
┌─ 수주관리 ──────────────────┐    ┌─ 재고생산관리 ───────────────┐
│                              │    │                              │
│ [거래처 정보]                │    │ [생산 정보]                  │
│  - 거래처 선택               │    │  - 생산 사유 (텍스트)        │
│  - 현장명                    │    │  - 목표 재고 수량            │
│  - 배송/납기일               │    │  - 비고                      │
│  - 운임비용                  │    │                              │
│  - 견적 연결                 │    ├──────────────────────────────┤
│  - 할인                      │    │ [품목 목록]                  │
│  - 매출 인식 방식            │    │  - 품목 선택                 │
│                              │    │  - 수량                      │
│ [개소/구역 (OrderNode)]      │    │  - 규격                      │
│  - N-depth 트리 구조         │    │                              │
│                              │    │ (단가/금액/할인 불필요)      │
│ [품목 목록]                  │    │ (개소/구역 불필요)           │
│  - 품목, 수량, 단가, 할인    │    │                              │
│  - floor_code, symbol_code   │    └──────────────────────────────┘
│  - 금액 계산                 │
│                              │
└──────────────────────────────┘
```

### 4.2 목록 페이지 표시 컬럼

| 컬럼 | 설명 |
|------|------|
| 생산번호 | `order_no` (STK...) |
| 상태 | `status_code` (상태 배지) |
| 품목 | 대표 품목명 + (외 N건) |
| 수량 | 총 수량 |
| 생산 사유 | `options.production_reason` |
| 등록일 | `created_at` |

### 4.3 상태 배지 색상 (수주와 동일)

| 상태 | 라벨 | 색상 |
|------|------|------|
| `DRAFT` | 등록 | gray |
| `CONFIRMED` | 확정 | blue |
| `IN_PROGRESS` | 진행중 | yellow |
| `IN_PRODUCTION` | 생산중 | orange |
| `PRODUCED` | 생산완료 | green |
| `COMPLETED` | 완료 | green |
| `CANCELLED` | 취소 | red |

---

## 5. 구현 체크리스트

### 프론트엔드 (React)

- [ ] 재고생산관리 메뉴/라우트 추가
- [ ] 목록 페이지: `GET /api/v1/orders?order_type=STOCK`
- [ ] 통계 카드: `GET /api/v1/orders/stats?order_type=STOCK`
- [ ] 생성 폼: `order_type_code: 'STOCK'` 필수 전송
- [ ] 상세/수정 페이지: 수주 화면 단순화 (거래처/견적/배송/할인 제거)
- [ ] 생산지시 생성 버튼: `POST /api/v1/orders/{id}/production-order`
- [ ] 상태 변경: `PATCH /api/v1/orders/{id}/status`

### 프론트엔드 — 생산지시 목록 수정

- [ ] 생산지시 목록에서 `order_type_code`가 `STOCK`인 건: 납기 컬럼 `-` 표시
- [ ] 생산지시 생성 UI: STOCK 수주는 공정 선택 불필요 (API가 절곡 자동 선택)

### 백엔드 (API) — 완료

- [x] `Order::TYPE_STOCK = 'STOCK'` 상수 추가
- [x] StoreOrderRequest에 `STOCK` validation 추가
- [x] UpdateOrderRequest에 `STOCK` validation 추가
- [x] 재고생산 채번: `STK{YYYYMMDD}{NNNN}`
- [x] stats()에 `order_type` 필터 추가
- [x] STOCK 타입 확정 시 매출 자동 생성 스킵
- [x] options에 `production_reason`, `target_stock_qty` 필드 추가
- [x] store()에서 STOCK 타입 `site_name = '재고생산'` 자동 설정
- [x] createProductionOrder()에서 STOCK: `project_name = '재고생산'` 고정
- [x] createProductionOrder()에서 STOCK: 절곡 공정 자동 선택
- [x] createProductionOrder()에서 STOCK: `scheduled_date = now()` 자동 설정

---

## 관련 문서

- 수주관리: 기존 수주 API는 동일 엔드포인트 (`/api/v1/orders`)
- 작업지시: `POST /api/v1/orders/{id}/production-order`
- 품목관리: `rules/item-policy.md`

---

**최종 업데이트**: 2026-03-16
