Files
sam-docs/front/[API-2025-12-04] quote-api-request.md
hskwon 02a27f2bba docs: 규칙 및 원칙 문서 체계 추가
- standards/ 폴더 추가 (코딩 규칙: 네이밍, 스타일)
- rules/ 폴더 추가 (비즈니스 규칙: 검증, 도메인 로직)
- principles/ 폴더 추가 (설계 원칙: 아키텍처, API 설계)
- INDEX.md에 규칙 및 원칙 섹션 추가
- 각 폴더에 README.md 생성
2025-12-05 17:57:47 +09:00

19 KiB
Raw Blame History

견적관리 API 요청서

작성일: 2025-12-04 목적: 견적관리 기능을 위한 백엔드 API 요청 참조: sam-design/QuoteManagement3Write.tsx, QuoteManagement3Detail.tsx


1. 개요

1.1 기능 요약

견적관리 시스템은 다음 기능을 지원해야 합니다:

  • 견적 CRUD (등록, 조회, 수정, 삭제)
  • 견적 상태 관리 (임시저장 → 확정 → 수주전환)
  • 견적 수정 이력 관리 (버전 관리)
  • 견적 품목(BOM) 관리
  • 자동 견적 산출 (수식 기반 계산) ← 백엔드 구현

1.2 특이사항

  • 자동 견적 산출 로직은 백엔드에서 구현 예정 (수식 계산 엔진)
  • 프론트엔드는 입력값을 전달하고 계산 결과를 받아서 표시

2. 데이터 모델

2.1 Quote (견적) - 메인 엔티티

interface Quote {
  // === 기본 정보 ===
  id: number;
  tenant_id: number;
  quote_number: string;           // 견적번호 (예: KD-SC-251204-01)
  registration_date: string;      // 등록일 (YYYY-MM-DD)
  receipt_date: string;           // 접수일
  author: string;                 // 작성자

  // === 발주처 정보 ===
  client_id: number | null;       // 거래처 ID (FK)
  client_name: string;            // 거래처명 (직접입력 대응)
  manager: string | null;         // 담당자
  contact: string | null;         // 연락처

  // === 현장 정보 ===
  site_id: number | null;         // 현장 ID (FK, 별도 테이블 필요시)
  site_name: string | null;       // 현장명
  site_code: string | null;       // 현장코드

  // === 제품 정보 ===
  product_category: 'SCREEN' | 'STEEL';  // 제품 카테고리
  product_id: number | null;      // 선택된 제품 ID (품목마스터 FK)
  product_code: string | null;    // 제품코드
  product_name: string | null;    // 제품명

  // === 규격 정보 ===
  open_size_width: number | null;   // 오픈사이즈 폭 (mm)
  open_size_height: number | null;  // 오픈사이즈 높이 (mm)
  quantity: number;                  // 수량 (기본값: 1)
  unit_symbol: string | null;       // 부호
  floors: string | null;            // 층수

  // === 금액 정보 ===
  material_cost: number;          // 재료비 합계
  labor_cost: number;             // 노무비
  install_cost: number;           // 설치비
  subtotal: number;               // 소계
  discount_rate: number;          // 할인율 (%)
  discount_amount: number;        // 할인금액
  total_amount: number;           // 최종 금액

  // === 상태 관리 ===
  status: 'draft' | 'sent' | 'approved' | 'rejected' | 'finalized' | 'converted';
  current_revision: number;       // 현재 수정 차수 (0부터 시작)
  is_final: boolean;              // 최종확정 여부
  finalized_at: string | null;    // 확정일시
  finalized_by: number | null;    // 확정자 ID

  // === 기타 정보 ===
  completion_date: string | null; // 납기일
  remarks: string | null;         // 비고
  memo: string | null;            // 메모
  notes: string | null;           // 특이사항

  // === 시스템 필드 ===
  created_at: string;
  updated_at: string;
  created_by: number | null;
  updated_by: number | null;
  deleted_at: string | null;      // Soft Delete
}

2.2 QuoteItem (견적 품목) - BOM 계산 결과

interface QuoteItem {
  id: number;
  quote_id: number;               // 견적 ID (FK)
  tenant_id: number;

  // === 품목 정보 ===
  item_id: number | null;         // 품목마스터 ID (FK)
  item_code: string;              // 품목코드
  item_name: string;              // 품명
  specification: string | null;   // 규격
  unit: string;                   // 단위

  // === 수량/금액 ===
  base_quantity: number;          // 기본수량
  calculated_quantity: number;    // 계산된 수량
  unit_price: number;             // 단가
  total_price: number;            // 금액 (수량 × 단가)

  // === 수식 정보 ===
  formula: string | null;         // 수식 (예: "W/1000 + 0.1")
  formula_source: string | null;  // 수식 출처 (BOM템플릿, 제품BOM 등)
  formula_category: string | null; // 수식 카테고리
  data_source: string | null;     // 데이터 출처

  // === 기타 ===
  delivery_date: string | null;   // 품목별 납기일
  note: string | null;            // 비고
  sort_order: number;             // 정렬순서

  created_at: string;
  updated_at: string;
}

2.3 QuoteRevision (견적 수정 이력)

interface QuoteRevision {
  id: number;
  quote_id: number;               // 견적 ID (FK)
  tenant_id: number;

  revision_number: number;        // 수정 차수 (1, 2, 3...)
  revision_date: string;          // 수정일
  revision_by: number;            // 수정자 ID
  revision_by_name: string;       // 수정자 이름
  revision_reason: string | null; // 수정 사유

  // 이전 버전 데이터 (JSON)
  previous_data: object;          // 수정 전 견적 전체 데이터 (스냅샷)

  created_at: string;
}

3. API 엔드포인트

3.1 견적 CRUD

Method Endpoint 설명 비고
GET /api/v1/quotes 목록 조회 페이지네이션, 필터, 검색
GET /api/v1/quotes/{id} 단건 조회 품목(items), 이력(revisions) 포함
POST /api/v1/quotes 생성 품목 배열 포함
PUT /api/v1/quotes/{id} 수정 수정이력 자동 생성
DELETE /api/v1/quotes/{id} 삭제 Soft Delete
DELETE /api/v1/quotes 일괄 삭제 ids[] 파라미터

3.2 견적 상태 관리

Method Endpoint 설명 비고
PATCH /api/v1/quotes/{id}/finalize 최종확정 status → 'finalized', is_final → true
PATCH /api/v1/quotes/{id}/convert-to-order 수주전환 status → 'converted', 수주 데이터 생성
PATCH /api/v1/quotes/{id}/cancel-finalize 확정취소 is_final → false (조건부)

3.3 자동 견적 산출 (핵심 기능)

Method Endpoint 설명 비고
POST /api/v1/quotes/calculate 자동 산출 수식 계산 엔진
POST /api/v1/quotes/{id}/recalculate 재계산 기존 견적 재산출

3.4 견적 문서 출력

Method Endpoint 설명 비고
GET /api/v1/quotes/{id}/document/quote 견적서 PDF
GET /api/v1/quotes/{id}/document/calculation 산출내역서 PDF
GET /api/v1/quotes/{id}/document/purchase-order 발주서 PDF

3.5 문서 발송 API 신규 요청

Method Endpoint 설명 비고
POST /api/v1/quotes/{id}/send/email 이메일 발송 첨부파일 포함
POST /api/v1/quotes/{id}/send/fax 팩스 발송 팩스 서비스 연동
POST /api/v1/quotes/{id}/send/kakao 카카오톡 발송 알림톡/친구톡

3.6 견적번호 생성

Method Endpoint 설명 비고
GET /api/v1/quotes/generate-number 견적번호 생성 ?category=SCREEN

4. 상세 API 명세

4.1 목록 조회 GET /api/v1/quotes

Query Parameters:

page: number (default: 1)
size: number (default: 20)
q: string (검색어 - 견적번호, 발주처, 담당자, 현장명)
status: string (상태 필터)
product_category: string (제품 카테고리)
client_id: number (발주처 ID)
date_from: string (등록일 시작)
date_to: string (등록일 종료)
sort_by: string (정렬 컬럼)
sort_order: 'asc' | 'desc'

Response:

{
  "success": true,
  "data": {
    "current_page": 1,
    "data": [
      {
        "id": 1,
        "quote_number": "KD-SC-251204-01",
        "registration_date": "2025-12-04",
        "client_name": "ABC건설",
        "site_name": "강남 오피스텔 현장",
        "product_category": "SCREEN",
        "product_name": "전동스크린 A형",
        "quantity": 10,
        "total_amount": 15000000,
        "status": "draft",
        "current_revision": 0,
        "is_final": false,
        "created_at": "2025-12-04T10:00:00Z"
      }
    ],
    "last_page": 5,
    "per_page": 20,
    "total": 100
  }
}

4.2 단건 조회 GET /api/v1/quotes/{id}

Response:

{
  "success": true,
  "data": {
    "id": 1,
    "quote_number": "KD-SC-251204-01",
    "registration_date": "2025-12-04",
    "receipt_date": "2025-12-04",
    "author": "김철수",

    "client_id": 10,
    "client_name": "ABC건설",
    "manager": "이영희",
    "contact": "010-1234-5678",

    "site_id": 5,
    "site_name": "강남 오피스텔 현장",
    "site_code": "PJ-20251204-01",

    "product_category": "SCREEN",
    "product_id": 100,
    "product_code": "SCR-001",
    "product_name": "전동스크린 A형",

    "open_size_width": 2000,
    "open_size_height": 3000,
    "quantity": 10,
    "unit_symbol": "A",
    "floors": "3층",

    "material_cost": 12000000,
    "labor_cost": 1500000,
    "install_cost": 1500000,
    "subtotal": 15000000,
    "discount_rate": 0,
    "discount_amount": 0,
    "total_amount": 15000000,

    "status": "draft",
    "current_revision": 2,
    "is_final": false,

    "completion_date": "2025-12-31",
    "remarks": "급하게 진행 필요",
    "memo": "",
    "notes": "",

    "items": [
      {
        "id": 1,
        "item_code": "SCR-MOTOR-001",
        "item_name": "스크린 모터",
        "specification": "220V, 1/4HP",
        "unit": "EA",
        "base_quantity": 1,
        "calculated_quantity": 10,
        "unit_price": 150000,
        "total_price": 1500000,
        "formula": "Q",
        "formula_source": "제품BOM",
        "sort_order": 1
      }
    ],

    "revisions": [
      {
        "revision_number": 2,
        "revision_date": "2025-12-04",
        "revision_by_name": "김철수",
        "revision_reason": "고객 요청으로 수량 변경"
      },
      {
        "revision_number": 1,
        "revision_date": "2025-12-03",
        "revision_by_name": "김철수",
        "revision_reason": "단가 조정"
      }
    ],

    "created_at": "2025-12-04T10:00:00Z",
    "updated_at": "2025-12-04T15:30:00Z"
  }
}

4.3 생성 POST /api/v1/quotes

Request Body:

{
  "registration_date": "2025-12-04",
  "receipt_date": "2025-12-04",

  "client_id": 10,
  "client_name": "ABC건설",
  "manager": "이영희",
  "contact": "010-1234-5678",

  "site_id": 5,
  "site_name": "강남 오피스텔 현장",
  "site_code": "PJ-20251204-01",

  "product_category": "SCREEN",
  "product_id": 100,

  "open_size_width": 2000,
  "open_size_height": 3000,
  "quantity": 10,
  "unit_symbol": "A",
  "floors": "3층",

  "completion_date": "2025-12-31",
  "remarks": "급하게 진행 필요",

  "items": [
    {
      "item_id": 50,
      "item_code": "SCR-MOTOR-001",
      "item_name": "스크린 모터",
      "unit": "EA",
      "base_quantity": 1,
      "calculated_quantity": 10,
      "unit_price": 150000,
      "total_price": 1500000,
      "formula": "Q",
      "sort_order": 1
    }
  ]
}

4.4 자동 산출 POST /api/v1/quotes/calculate 핵심

Request Body:

{
  "product_id": 100,
  "product_category": "SCREEN",
  "open_size_width": 2000,
  "open_size_height": 3000,
  "quantity": 10,
  "floors": "3층",
  "unit_symbol": "A",

  "options": {
    "guide_rail_install_type": "벽부형",
    "motor_power": "1/4HP",
    "controller": "표준형",
    "edge_wing_size": 50,
    "inspection_fee": 0
  }
}

Response:

{
  "success": true,
  "data": {
    "product_id": 100,
    "product_name": "전동스크린 A형",
    "product_category": "SCREEN",

    "open_size": {
      "width": 2000,
      "height": 3000
    },
    "quantity": 10,

    "items": [
      {
        "item_id": 50,
        "item_code": "SCR-MOTOR-001",
        "item_name": "스크린 모터",
        "specification": "220V, 1/4HP",
        "unit": "EA",
        "base_quantity": 1,
        "calculated_quantity": 10,
        "unit_price": 150000,
        "total_price": 1500000,
        "formula": "Q",
        "formula_result": "10 × 1 = 10",
        "formula_source": "제품BOM: 전동스크린 A형",
        "data_source": "품목마스터 [SCR-MOTOR-001]"
      },
      {
        "item_id": 51,
        "item_code": "SCR-RAIL-001",
        "item_name": "가이드레일",
        "specification": "알루미늄",
        "unit": "M",
        "base_quantity": 1,
        "calculated_quantity": 60,
        "unit_price": 15000,
        "total_price": 900000,
        "formula": "H/1000 × 2 × Q",
        "formula_result": "(3000/1000) × 2 × 10 = 60",
        "formula_source": "BOM템플릿: 스크린_표준",
        "data_source": "품목마스터 [SCR-RAIL-001]"
      }
    ],

    "summary": {
      "material_cost": 12000000,
      "labor_cost": 1500000,
      "install_cost": 1500000,
      "subtotal": 15000000,
      "total_amount": 15000000
    },

    "calculation_info": {
      "bom_template_used": "스크린_표준",
      "formula_variables": {
        "W": 2000,
        "H": 3000,
        "Q": 10
      },
      "calculated_at": "2025-12-04T10:00:00Z"
    }
  }
}

5. 수식 계산 엔진 (백엔드 구현 요청)

5.1 수식 변수

변수 설명 예시
W 오픈사이즈 폭 (mm) 2000
H 오픈사이즈 높이 (mm) 3000
Q 수량 10

5.2 수식 예시

수량 그대로: Q
높이 기반: H/1000
폭+높이: (W + H) / 1000
가이드레일: H/1000 × 2 × Q
스크린원단: (W/1000 + 0.1) × (H/1000 + 0.3) × Q

5.3 반올림 규칙

규칙 설명
ceil 올림
floor 내림
round 반올림

5.4 BOM 템플릿 연동

  • 제품별 BOM 템플릿에서 수식 조회
  • 템플릿이 없으면 품목마스터 BOM 사용
  • 수식 + 단가로 자동 금액 계산

6. 상태 흐름도

[신규등록]
    ↓
[draft] 임시저장
    ↓ (최종확정)
[finalized] 확정
    ↓ (수주전환)
[converted] 수주전환

6.1 상태별 제약

상태 수정 가능 삭제 가능 비고
draft O O 자유롭게 수정
sent O O 발송 후 수정 가능 (이력 기록)
finalized X X 확정 후 수정 불가
converted X X 수주전환 후 불변

7. 프론트엔드 구현 현황 (2025-12-04 업데이트)

7.1 구현 완료된 파일

파일 설명 상태
quote-management/page.tsx 견적 목록 페이지 완료 (샘플 데이터)
quote-management/new/page.tsx 견적 등록 페이지 완료
quote-management/[id]/page.tsx 견적 상세 페이지 완료
quote-management/[id]/edit/page.tsx 견적 수정 페이지 완료
components/quotes/QuoteRegistration.tsx 견적 등록/수정 컴포넌트 완료
components/quotes/QuoteDocument.tsx 견적서 문서 컴포넌트 완료
components/quotes/QuoteCalculationReport.tsx 산출내역서 문서 컴포넌트 완료
components/quotes/PurchaseOrderDocument.tsx 발주서 문서 컴포넌트 완료

7.2 UI 기능 구현 현황

기능 상태 비고
견적 목록 조회 UI 완료 샘플 데이터, API 연동 필요
견적 검색/필터 UI 완료 로컬 필터링, API 연동 필요
견적 등록 폼 UI 완료 API 연동 필요
견적 상세 페이지 UI 완료 API 연동 필요
견적 수정 폼 UI 완료 API 연동 필요
견적 삭제 UI 완료 로컬 상태, API 연동 필요
견적 일괄 삭제 UI 완료 로컬 상태, API 연동 필요
자동 견적 산출 버튼만 백엔드 수식 엔진 필요
발주처 선택 샘플 데이터 /api/v1/clients 연동 필요
현장 선택 샘플 데이터 발주처 연동 후 현장 API 필요
제품 선택 샘플 데이터 /api/v1/item-masters 연동 필요
견적서 모달 UI 완료 PDF/이메일/팩스/카톡 버튼, 발송 API 필요
산출내역서 모달 UI 완료 PDF/이메일/팩스/카톡 버튼, 발송 API 필요
발주서 모달 UI 완료 PDF/이메일/팩스/카톡 버튼, 발송 API 필요
최종확정 버튼 UI 완료 API 연동 필요

7.3 견적 등록/수정 폼 필드 (구현 완료)

기본 정보 섹션:

  • 등록일 (readonly, 오늘 날짜)
  • 작성자 (readonly, 로그인 사용자)
  • 발주처 선택 * (필수)
  • 현장명 (발주처 선택 시 연동)
  • 발주 담당자
  • 연락처
  • 납기일
  • 비고

자동 견적 산출 섹션 (동적 항목):

  • 층수
  • 부호
  • 제품 카테고리 (PC) *
  • 제품명 *
  • 오픈사이즈 (W0) *
  • 오픈사이즈 (H0) *
  • 가이드레일 설치 유형 (GT) *
  • 모터 전원 (MP) *
  • 연동제어기 (CT) *
  • 수량 (QTY) *
  • 마구리 날개치수 (WS)
  • 검사비 (INSP)

기능:

  • 견적 항목 추가/복사/삭제
  • 자동 견적 산출 버튼
  • 샘플 데이터 생성 버튼

7.4 다음 단계 (API 연동)

// useQuoteList 훅 (목록)
const {
  quotes,
  pagination,
  isLoading,
  fetchQuotes,
  deleteQuote,
  bulkDelete
} = useQuoteList();

// useQuote 훅 (단건 CRUD)
const {
  quote,
  isLoading,
  fetchQuote,
  createQuote,
  updateQuote,
  finalizeQuote,
  convertToOrder
} = useQuote();

// useQuoteCalculation 훅 (자동 산출)
const {
  calculationResult,
  isCalculating,
  calculate,
  recalculate
} = useQuoteCalculation();

8. 관련 참조

8.1 거래처 API 연동

  • 발주처 선택 시 /api/v1/clients 연동
  • 직접입력 시 자동 등록 가능

8.2 현장 API (추후)

  • 현장 선택 시 /api/v1/sites 연동 (별도 API 필요시)

8.3 품목마스터 연동

  • 제품 선택 시 /api/v1/item-masters 연동
  • BOM 조회 시 품목마스터 BOM 활용

9. 요청 우선순위

순위 API 설명
P1 견적 CRUD 기본 목록/등록/수정/삭제
P1 자동 산출 수식 계산 엔진 (핵심)
P1 견적번호 생성 자동 채번
P2 상태 관리 확정/수주전환
P2 수정 이력 버전 관리
P3 문서 출력 PDF 생성

10. 질문사항

  1. 현장(Site) 테이블: 별도 테이블로 관리할지? (거래처 하위 개념)
  2. 수식 계산: BOM 템플릿 테이블 구조는?
  3. 문서 출력: PDF 라이브러리 선정 (TCPDF, Dompdf 등)
  4. 알림: 견적 발송 시 이메일/카카오톡 연동 계획?