Files
sam-docs/projects/mes/v2-analysis/order-analysis/03-quote-ui.md

245 lines
8.3 KiB
Markdown
Raw Normal View History

# 견적/수주 UI 분석
> 분석 일시: 2024-12-18
> 소스:
> - design/mes기획서_리액트/src/components/QuoteDetailNew.jsx
> - design/mes기획서_리액트/src/components/QuoteDocumentDialogs.jsx
## QuoteDetailNew.jsx - 견적 상세
### Props
| Prop | 타입 | 설명 |
|------|------|------|
| quote | Object | 견적 데이터 |
| orders | Array | 수주 목록 (관련 수주 찾기용) |
| onNavigate | Function | 화면 이동 |
| onBack | Function | 목록으로 돌아가기 |
| onConvertToOrder | Function | 수주 전환 콜백 |
| onUpdateQuote | Function | 견적 업데이트 콜백 |
| onCreateOrder | Function | 수주 생성 콜백 |
### 견적 상태 (StatusBadge)
| 상태 | 스타일 | 설명 |
|------|--------|------|
| 최초작성 | gray | 초기 상태 |
| 최종확정 | blue | 견적 확정 |
| 수주전환 | green | 수주로 전환됨 |
| 수정중 | yellow | 수정 진행 중 |
### 화면 구성
```
┌─────────────────────────────────────────────────────────────┐
│ [헤더] │
│ 좌: 견적 상세 + [견적서] [산출내역서] [발주서] 버튼 │
│ 우: [목록] [수정] [최종확정] [수주전환] 버튼 │
├─────────────────────────────────────────────────────────────┤
│ [기본 정보] Card │
│ - 견적번호, 작성자, 발주처, 담당자, 연락처 │
│ - 현장명, 현장코드, 상태, 접수일, 납기일, 비고 │
├─────────────────────────────────────────────────────────────┤
│ [자동 견적 산출 정보] Card │
│ - 품목, 수량, 단가, 공급가액, 부가세, 총 견적금액 │
├─────────────────────────────────────────────────────────────┤
│ [특이사항] Card │
│ - 특이사항 텍스트 │
└─────────────────────────────────────────────────────────────┘
```
### 수주전환 모달 (convertForm)
| 필드 | 타입 | 필수 | 설명 |
|------|------|------|------|
| shipDate | date | - | 출하예정일 |
| shipDateUndecided | boolean | - | 출하일 미정 여부 |
| dueDate | date | - | 납기일 |
| dueDateUndecided | boolean | - | 납기일 미정 여부 |
| deliveryMethod | select | - | 배송방법 (상차/택배/직접배송) |
| freightCost | select | - | 운임비 (선불/착불/무료) |
| receiverName | text | - | 수령자명 |
| receiverPhone | text | - | 수령자연락처 |
| deliveryAddress | text | - | 납품주소 |
| deliveryAddressDetail | text | - | 상세주소 |
| note | textarea | - | 비고 |
### 수주전환 비즈니스 로직
```javascript
// 수주번호 생성 규칙
const dateCode = new Date().toISOString().slice(2,10).replace(/-/g, '');
const newOrderNo = `KD-SO-${dateCode}-${순번2자리}`;
// 예: KD-SO-241218-01
// 생성되는 수주 데이터
const newOrder = {
id: Date.now(),
orderNo: newOrderNo, // 자동생성 수주번호
quoteNo: quote.quoteNo, // 원본 견적번호
quoteId: quote.id, // 원본 견적 ID
orderDate: '오늘 날짜',
customerName: quote.customerName,
siteName: quote.siteName,
siteAddress: quote.deliveryAddress,
manager: quote.manager,
contact: quote.contact,
productName: quote.productName,
qty: quote.qty,
totalAmount: quote.finalAmount || quote.totalAmount,
status: '수주확정', // 초기 상태
dueDate: convertForm.dueDate,
shipDate: convertForm.shipDate,
deliveryMethod: convertForm.deliveryMethod,
freightCost: convertForm.freightCost,
receiverName: convertForm.receiverName,
receiverPhone: convertForm.receiverPhone,
deliveryAddress: convertForm.deliveryAddress,
deliveryAddressDetail: convertForm.deliveryAddressDetail,
note: convertForm.note,
creditGrade: quote.creditGrade,
items: quote.items || [],
history: [{
id: Date.now(),
changedAt: '현재시간',
changeType: '수주등록',
description: `견적(${quote.quoteNo})에서 수주전환`,
changedBy: '현재 사용자',
}],
};
```
---
## QuoteDocumentDialogs.jsx - 문서 출력
### 1. QuoteSheetDialog (견적서)
**구성:**
- 수신자 정보: 상호, 담당자, 연락처, 현장명
- 발신자 정보: 상호, 대표자, 사업자번호, 연락처
- 견적 요약: 견적번호, 견적일, 유효기간(30일), 견적금액
- 품목 테이블: No, 품목명, 규격, 수량, 단가, 금액
- 합계: 공급가액, 부가세(10%), 총 견적금액
- 비고
**액션 버튼:**
- 인쇄 (Printer)
- 다운로드 (Download)
- 이메일 (Mail)
### 2. CalculationSheetDialog (산출내역서)
**구성:**
- 견적번호, 현장명, 작성일
- 산출 테이블: No, 품목, 층/부호, 가로, 세로, 면적(m²), 수량, 단가, 금액
- 합계
- 산출 기준 안내
**면적 계산:**
```javascript
const area = ((item.width || 0) * (item.height || 0) / 1000000).toFixed(2);
```
### 3. PurchaseOrderDialog (발주서)
**구성:**
- 발주처 정보 (귀하): 상호, 담당자, 연락처, 현장
- 수주처 정보: 상호, 대표자, 사업자번호, 연락처
- 발주 요약: 발주번호, 발주일, 납기일, 발주금액
- 품목 테이블: No, 품목명, 규격, 수량, 단가, 금액
- 발주 합계
- 특기사항
- 서명란: 발주자(인), 수주자(인)
**발주번호 생성:**
```javascript
// 견적번호에서 변환
const purchaseOrderNo = `PO-${quote.quoteNo?.replace('QT', '')}`;
// 예: QT-2024-001 → PO-2024-001
```
---
## Quote 데이터 구조
### quote 객체
| 필드 | 타입 | 설명 |
|------|------|------|
| id | number | 견적 ID |
| quoteNo | string | 견적번호 (QT-YYMMDD-##) |
| quoteDate | string | 견적일 |
| customerName | string | 발주처명 |
| manager | string | 담당자 |
| contact | string | 연락처 |
| siteName | string | 현장명 |
| siteCode | string | 현장코드 |
| deliveryAddress | string | 납품주소 |
| productName | string | 대표 품목명 |
| qty | number | 수량 |
| unitPrice | number | 단가 |
| totalAmount | number | 총금액 (공급가액) |
| finalAmount | number | 최종금액 |
| status | string | 상태 |
| dueDate | string | 납기일 |
| createdBy | string | 작성자 |
| note | string | 비고 |
| specialNote | string | 특이사항 |
| creditGrade | string | 신용등급 |
| items | Array | 품목 목록 |
### items[] 객체
| 필드 | 타입 | 설명 |
|------|------|------|
| id | number | 품목 ID |
| productName | string | 품목명 |
| category | string | 카테고리 |
| floor | string | 층 |
| location | string | 위치 |
| width | number | 가로(mm) |
| height | number | 세로(mm) |
| qty | number | 수량 |
| unitPrice | number | 단가 |
| amount | number | 금액 |
| orderStatus | string | 수주 상태 (pending/ordered) |
| orderId | number | 연결된 수주 ID |
---
## API 추정
### 견적 → 수주 전환 API
```
POST /api/orders/from-quote/{quoteId}
Body: {
shipDate: string | null,
dueDate: string | null,
deliveryMethod: string,
freightCost: string,
receiverName: string,
receiverPhone: string,
deliveryAddress: string,
deliveryAddressDetail: string,
note: string
}
Response: {
order: { ... }, // 생성된 수주
quote: { ... } // 업데이트된 견적 (status: '수주전환')
}
```
### 문서 출력 API
```
GET /api/quotes/{id}/documents/quote-sheet - 견적서 PDF
GET /api/quotes/{id}/documents/calculation - 산출내역서 PDF
GET /api/quotes/{id}/documents/purchase-order - 발주서 PDF
POST /api/quotes/{id}/documents/email - 이메일 발송
```
---
## 다음 분석 단계
1. App.jsx 수주 섹션 추출 - 수주 목록/등록/상세 UI
2. 비즈니스 로직 통합 분석