ERP-node/docs/shipping-plan-editor-plan.md

177 lines
6.0 KiB
Markdown
Raw Normal View History

# 출하계획 동시 등록 컴포넌트 (v2-shipping-plan-editor) 설계서
## 개요
수주 목록에서 다건 선택 후 "출하계획" 버튼 클릭 시 모달로 열리는 출하계획 일괄 등록 화면.
기존 ScreenModal + modalScreenId 매커니즘을 활용하여, DB 기반 화면(screen_definitions)으로 구현한다.
## 핵심 기능
1. 선택된 수주를 **품목(part_code) 기준으로 그룹핑**
2. 그룹별 **5칸 집계 카드**: 총수주잔량, 총 출하계획량, 현재고, 가용재고, 생산중수량
3. 그룹별 상세 테이블: 기존 계획(기존) + 신규 입력(신규) 구분 표시
4. 출하계획량만 입력 → 확인 시 shipment_plan에 일괄 INSERT
## 테이블 관계
```
sales_order_mng (수주)
├─ id (PK)
├─ part_code (품목코드) ← 그룹핑 기준
├─ part_name (품명)
├─ order_qty (수주수량)
├─ ship_qty (출하수량)
├─ balance_qty (잔량) = order_qty - ship_qty
├─ partner_id (거래처)
└─ due_date (납기일)
shipment_plan (출하계획)
├─ sales_order_id (FK → sales_order_mng.id)
├─ plan_qty (출하계획수량)
├─ plan_date (출하예정일)
├─ shipment_plan_no (자동 채번)
└─ status (READY)
inventory_stock (재고)
├─ item_code (품목코드)
└─ current_qty (현재고)
production_plan_mng (생산계획)
├─ item_code (품목코드)
├─ plan_qty (계획수량)
├─ completed_qty (완료수량)
└─ status (진행중 = in_progress / planned)
```
## 집계 카드 데이터 소스
| 카드 | 계산 방법 |
|------|----------|
| 총수주잔량 | SUM(sales_order_mng.balance_qty) WHERE part_code = ? |
| 총 출하계획량 | SUM(shipment_plan.plan_qty) WHERE sales_order_id IN (해당 품목 수주들) |
| 현재고 | SUM(inventory_stock.current_qty) WHERE item_code = part_code |
| 가용재고 | 현재고 - 총 출하계획량 (기존 계획분) |
| 생산중수량 | SUM(production_plan_mng.plan_qty - completed_qty) WHERE item_code = part_code AND status IN ('in_progress', 'planned') |
## 상세 테이블 컬럼
| 컬럼 | 소스 | 편집 |
|------|------|------|
| 구분 | "기존" or "신규" | 읽기 전용 (배지) |
| 수주번호 | sales_order_mng.order_no | 읽기 전용 |
| 거래처 | sales_order_mng.partner_id (엔티티 조인) | 읽기 전용 |
| 납기일 | sales_order_mng.due_date | 읽기 전용 |
| 미출하 | sales_order_mng.balance_qty | 읽기 전용 |
| 출하계획량 | 입력값 / shipment_plan.plan_qty | **입력 가능** |
## 데이터 흐름
```
1. 수주 목록에서 체크박스 선택 → "출하계획" 버튼 클릭
2. openScreenModal 이벤트 발생 (selectedData = 선택된 수주 배열)
3. ScreenModal이 모달 화면 로드 (v2-shipping-plan-editor 컴포넌트)
4. 컴포넌트가 groupedData (= selectedData) 수신
5. part_code 기준 그룹핑
6. 백엔드 API 호출: GET /api/shipping-plan/aggregate
→ 품목별 재고, 생산중수량, 기존 출하계획 조회
7. UI 렌더링 (집계 카드 + 상세 테이블)
8. 사용자가 출하계획량 입력
9. 확인 버튼 → POST /api/shipping-plan/batch
→ shipment_plan INSERT + sales_order_mng.plan_ship_qty UPDATE
```
## 파일 구조
```
frontend/lib/registry/components/v2-shipping-plan-editor/
├── index.ts # createComponentDefinition
├── ShippingPlanEditorRenderer.tsx # AutoRegisteringComponentRenderer
├── ShippingPlanEditorComponent.tsx # 메인 UI 컴포넌트
└── types.ts # 타입 정의
frontend/lib/api/
└── shipping.ts # API 클라이언트 함수
backend-node/src/
├── controllers/shippingPlanController.ts # API 핸들러
└── routes/shippingPlanRoutes.ts # 라우터
```
## 백엔드 API
### GET /api/shipping-plan/aggregate
품목별 집계 + 기존 출하계획 조회
Request: `?partCodes=ITEM001,SEAL-100&orderIds=172,175,178`
Response:
```json
{
"success": true,
"data": {
"ITEM001": {
"totalBalance": 1700,
"totalPlanQty": 500,
"currentStock": 1000,
"availableStock": 500,
"inProductionQty": 300,
"existingPlans": [
{ "id": 76, "salesOrderId": 172, "planQty": 500, "planDate": "2025-12-10", "shipmentPlanNo": "SPL-..." }
]
}
}
}
```
### POST /api/shipping-plan/batch
출하계획 일괄 저장
Request:
```json
{
"plans": [
{ "salesOrderId": 172, "planQty": 1000 },
{ "salesOrderId": 175, "planQty": 500 }
]
}
```
## 구현 상태
### 완료
- [x] types.ts (타입 정의)
- [x] index.ts (컴포넌트 정의)
- [x] ShippingPlanEditorRenderer.tsx (레지스트리 등록)
- [x] ShippingPlanEditorComponent.tsx (메인 UI)
- [x] frontend/lib/api/shipping.ts (API 클라이언트)
- [x] backend-node/src/controllers/shippingPlanController.ts (집계 + 일괄 저장)
- [x] backend-node/src/routes/shippingPlanRoutes.ts (라우터)
- [x] screen_definitions (screen_id: 4573, screen_code: *_SHIP_PLAN_EDITOR)
- [x] screen_layouts_v2 (layout_id: 11562)
### 연동 정보
| 항목 | 마스터(*) | 탑씰(COMPANY_7) |
|------|-----------|-----------------|
| screen_id | 4573 | 4574 |
| screen_code | *_SHIP_PLAN_EDITOR | TOPSEAL_SHIP_PLAN_EDITOR |
| layout_id | 11562 | 11563 |
탑씰 수주관리 화면(screen_id: 156)의 "출하계획" 버튼(comp_33659)이
targetScreenId: 4574로 연결되어, 체크박스 선택 → 버튼 클릭 → 모달 오픈.
선택된 수주 데이터는 `groupedData` prop으로 전달됨.
## 테스트 계획
### 1단계: 기본 기능
- [ ] 수주 선택 → 모달 열기 → groupedData 수신 확인
- [ ] part_code 기준 그룹핑 확인
- [ ] 집계 카드 데이터 표시 확인
### 2단계: CRUD
- [ ] 출하계획량 입력 → 집계 자동 재계산
- [ ] 확인 버튼 → shipment_plan INSERT 확인
- [ ] 기존 계획 "기존" 배지 표시 확인
### 3단계: 검증
- [ ] 출하계획량 > 미출하 시 에러 처리
- [ ] 멀티테넌시 (company_code) 필터링 확인