# 출하계획 동시 등록 컴포넌트 (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) 필터링 확인