# App.jsx 수주 섹션 분석 > 분석 일시: 2024-12-18 > 소스: design/mes기획서_리액트/src/App.jsx (52768~56357줄) ## 컴포넌트 위치 | 컴포넌트 | 라인 | 설명 | |----------|------|------| | OrderList | 52768 | 수주 목록 | | OrderDetail | 53479 | 수주 상세 | | OrderCreate | 55280 | 수주 등록 | | OrderEdit | 56357 | 수주 수정 | --- ## 1. OrderList (수주 목록) ### Props ```javascript { orders, // 수주 배열 shipments, // 출하 배열 (연결용) workOrders, // 작업지시 배열 (연결용) onNavigate, // 화면 이동 onCreateWorkOrders, // 작업지시 생성 onDeleteOrders // 수주 삭제 } ``` ### 탭 필터 | 탭 ID | 라벨 | 필터 조건 | |-------|------|-----------| | all | 전체 | - | | registered | 수주등록 | status === '수주등록' | | confirmed | 수주확정 | status === '수주확정' | | production-complete | 생산지시완료 | status === '생산지시완료' | ### 리포트 카드 (4개) | 항목 | 계산 | |------|------| | 이번 달 수주 | `orders.reduce(sum + totalAmount)` | | 분할 대기 | 수주확정 && splits 없음 | | 생산지시 대기 | splits 있으나 productionStatus 미지시 | | 출하 대기 | 출하진행률 0% | ### 테이블 컬럼 ``` 체크박스 | 번호 | 로트번호 | 견적번호 | 발주처 | 현장명 | 상태 | 출고예정일 | 배송방식 | (작업) ``` ### 검색 필드 - 로트번호 (orderNo) - 견적번호 (quoteNo) - 발주처 (customerName) - 현장명 (siteName) ### 정렬 ```javascript .sort((a, b) => b.id - a.id) // ID 기준 내림차순 (최신 등록 최상단) ``` --- ## 2. OrderDetail (수주 상세) ### Props ```javascript { order, // 수주 데이터 productionOrders, // 생산지시 배열 customers, // 거래처 배열 (결제조건 확인) onNavigate, onBack, onUpdate, // 수주 업데이트 onCreateWorkOrder, // 작업지시 생성 onCreateProductionOrder } ``` ### 문서 탭 | 탭 ID | 라벨 | 용도 | |-------|------|------| | contract | 계약서 | 수주 계약 문서 | | statement | 거래명세서 | 납품 시 발행 | | purchaseOrder | 발주서 | 발주처 제출용 | ### 분할(Split) 관리 **분할 데이터 구조:** ```javascript { id: number, splitNo: string, // "{orderNo}-{순번2자리}" splitOrder: number, splitType: string, // '개소별' dueDate: string, itemIds: number[], // 분할 품목 ID 배열 productionStatus: string, // '작업대기', '작업지시' shipmentStatus: string, // '출고대기', ... productionOrderNo: string, totalQty: number, completedQty: number, remainingQty: number } ``` ### 생산지시 생성 로직 **공정별 작업지시 자동 분리:** 1. **스크린 공정**: 스크린 카테고리 품목 2. **슬랫 공정**: 슬랫/철재 카테고리 품목 3. **절곡 공정**: BOM 데이터 기반 절곡물 **작업지시 번호 생성:** ```javascript const woNo = `KD-PL-${dateCode}-${순번2자리}`; // 예: KD-PL-241218-01 ``` **공정별 작업 단계:** ```javascript { '스크린': ['원단절단', '미싱', '앤드락작업', '중간검사', '포장'], '슬랫': ['코일절단', '중간검사', '미미작업', '포장'], '절곡': ['절단', '절곡', '중간검사', '포장'], } ``` **팀 자동 배정:** ```javascript { '스크린': { assignee: '스크린팀', assignees: ['김스크린', '이스크린', '박스크린'] }, '슬랫': { assignee: '슬랫팀', assignees: ['김슬랫', '이슬랫', '박슬랫'] }, '절곡': { assignee: '절곡팀', assignees: ['김절곡', '이절곡'] }, } ``` --- ## 3. OrderCreate (수주 등록) ### Props ```javascript { quotes, // 견적 배열 (선택용) fromQuote, // 전환된 견적 additionalItems, // 추가분 품목 relatedOrders, // 관련 수주 (추가분용) isAdditional, // 추가분 여부 onNavigate, onBack, onSave } ``` ### 수주 유형 | 유형 | orderType | 설명 | |------|-----------|------| | 견적전환 | from-quote | 견적에서 수주 전환 | | 직접입력 | direct | 견적 없이 직접 등록 | | 추가분 | additional | 기존 수주에 추가 | ### 수주번호 생성 규칙 ```javascript // 신규: KD-SO-YYMMDD-순번 const orderNo = `KD-SO-${dateCode}-${seq}`; // 예: KD-SO-241218-01 // 추가분: 원수주번호-A, B, C... const additionalOrderNo = `${baseOrderNo}-${suffix}`; // 예: KD-SO-241218-01-A ``` ### 폼 필드 **기본 정보:** | 필드 | 타입 | 필수 | 설명 | |------|------|------|------| | orderDate | date | - | 수주일 (기본: 오늘) | | customerName | text | ✅ | 발주처 | | customerId | text | - | 거래처 ID | | siteName | text | ✅ | 현장명 | | manager | text | - | 담당자 | | contact | text | - | 연락처 | **납품 정보:** | 필드 | 타입 | 필수 | 옵션 | |------|------|------|------| | dueDate | date | ✅ | 납기일 | | deliveryMethod | select | - | 배송방법 (12종) | | deliveryAddress | text | - | 납품주소 | | receiverName | text | - | 수령자명 | | receiverPhone | text | - | 수령자연락처 | **배송방법 옵션 (12종):** ``` 상차(선불), 상차(착불), 직접배차, 직접수령, 경동화물(선불/착불), 경동택배(선불/착불), 대신화물(선불/착불), 대신택배(선불/착불) ``` ### 품목 추가/수정 폼 **품목 필드:** | 필드 | 타입 | 설명 | |------|------|------| | productCode | text | 품목코드 | | productName | select | 품목명 | | floor | text | 층 | | location | text | 위치 | | openWidth | number | 개구폭(mm) | | openHeight | number | 개구높이(mm) | | qty | number | 수량 | | unitPrice | number | 단가 | | guideRailType | select | 가이드레일형태 | | guideRailSpec | select | 가이드레일규격 | | finish | select | 마감 | ### 제작 스펙 자동 계산 ```javascript const prodWidth = openWidth + 140; const prodHeight = Math.max(openHeight + 400, 2950); const shaft = openWidth > 6000 ? 5 : 4; const capacity = openWidth > 6000 ? 300 : 160; ``` ### 저장 시 생성되는 데이터 ```javascript const newOrder = { id, orderNo, orderDate, quoteId, quoteNo, orderType, // 'from-quote' | 'direct' | 'additional' parentOrderNo, // 추가분일 경우 customerId, customerName, creditGrade, // 거래처 신용등급 siteName, siteCode, manager, contact, dueDate, status: '수주등록', paymentStatus: '미입금', accountingStatus: '미확인', deliveryMethod, totalAmount, deliveryAddress, receiverName, receiverPhone, items, // 품목 배열 motorSpec, // 모터/전장품 스펙 bomData, // 절곡물 BOM calculatedItems, // 견적 산출 품목 splits: [], documentHistory: [], changeHistory: [], createdAt, createdBy, note }; ``` --- ## 4. 수주 상태 흐름 ``` 수주등록 → 수주확정 → 생산중 → 생산완료 → 출하완료 ↓ 분할 관리 ↓ 생산지시 (공정별) ↓ 작업지시 생성 ``` --- ## 5. 관련 API 추정 ### 수주 CRUD ``` GET /api/orders - 수주 목록 GET /api/orders/{id} - 수주 상세 POST /api/orders - 수주 등록 PUT /api/orders/{id} - 수주 수정 DELETE /api/orders/{id} - 수주 삭제 DELETE /api/orders (bulk) - 수주 일괄 삭제 ``` ### 분할 관리 ``` POST /api/orders/{id}/splits - 분할 추가 PUT /api/orders/{id}/splits/{splitId} - 분할 수정 DELETE /api/orders/{id}/splits/{splitId} - 분할 삭제 ``` ### 생산지시 ``` POST /api/orders/{id}/production-order - 전체 생산지시 POST /api/orders/{id}/splits/{splitId}/production-order - 분할 생산지시 ``` ### 작업지시 ``` POST /api/work-orders - 작업지시 생성 GET /api/work-orders?orderNo={orderNo} - 수주별 작업지시 조회 ``` ### 문서 출력 ``` GET /api/orders/{id}/documents/contract - 계약서 GET /api/orders/{id}/documents/statement - 거래명세서 GET /api/orders/{id}/documents/purchase-order - 발주서 ```