# 機能設計書 F012-見積書管理

## 概要

本ドキュメントは、AureusERPシステムにおける見積書管理機能（salesプラグイン）の機能設計書です。

### 本機能の処理概要

見積書管理機能は、顧客への見積提案から受注確定までのプロセスを管理します。見積書の作成、商品明細の追加、価格計算、有効期限管理、受注への変換など、営業活動における見積業務の一連の流れをサポートします。

**業務上の目的・背景**：企業の営業活動において、顧客への正確な見積提示は商談成約の重要な要素です。見積書管理機能は、商品情報・価格情報・税情報を一元管理し、迅速かつ正確な見積書作成を実現します。また、見積から受注への変換をシームレスに行うことで、営業プロセスの効率化を図ります。

**機能の利用シーン**：
- 営業担当者が顧客からの問い合わせに対して見積書を作成する場面
- 見積有効期限が近づいた際のフォローアップ
- 見積書を受注として確定する場面
- 見積書の修正・再発行が必要な場面

**主要な処理内容**：
1. 見積書の新規作成・編集・削除
2. 商品明細の追加・編集（数量、単価、税、割引）
3. 金額計算（小計、税額、合計）
4. 見積有効期限の管理
5. 見積状態の管理（下書き、送信済み、受注、キャンセル）
6. オプション商品の管理
7. 見積書から受注への変換

**関連システム・外部連携**：
- 顧客管理（Partner）との連携
- 商品管理（Product）との連携
- 税管理（Tax）との連携
- 請求書管理（Invoice）との連携
- 在庫管理（Inventory）との連携（配送処理）

**権限による制御**：
- 見積書の作成・編集は営業担当者権限が必要
- 見積書の削除はSALE状態では不可
- ロック状態の見積書は編集不可

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| SCR-SAL-001 | QuotationResource | 主画面 | 見積書の一覧表示・作成・編集・削除 |
| SCR-SAL-002 | ViewQuotation | 参照画面 | 見積書の詳細表示 |
| SCR-SAL-003 | EditQuotation | 編集画面 | 見積書の編集 |
| SCR-SAL-004 | ManageInvoices | 関連画面 | 請求書の管理 |
| SCR-SAL-005 | ManageDeliveries | 関連画面 | 配送の管理 |

## 機能種別

トランザクション管理 / CRUD操作 / 計算処理

## 入力仕様

### 入力パラメータ（見積書ヘッダ）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| partner_id | integer | Yes | 顧客ID | partners_partners.id存在チェック |
| validity_date | date | Yes | 有効期限日 | 日付形式 |
| date_order | date | Yes | 見積日 | 日付形式 |
| payment_term_id | integer | Yes | 支払条件ID | accounts_payment_terms.id存在チェック |
| user_id | integer | No | 営業担当者ID | users.id存在チェック |
| company_id | integer | No | 会社ID | companies.id存在チェック |
| currency_id | integer | Yes | 通貨ID | currencies.id存在チェック |
| client_order_ref | string | No | 顧客参照番号 | 最大255文字 |
| commitment_date | date | No | コミットメント日 | 日付形式 |
| origin | string | No | 元伝票 | 最大255文字 |
| campaign_id | integer | No | キャンペーンID | utm_campaigns.id存在チェック |
| medium_id | integer | No | メディアID | utm_mediums.id存在チェック |
| utm_source_id | integer | No | UTMソースID | utm_sources.id存在チェック |
| note | text | No | 備考・利用規約 | HTML許可 |

### 入力パラメータ（見積明細）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| product_id | integer | Yes | 商品ID | products.id存在チェック |
| product_qty | decimal | Yes | 数量 | 0以上、最大99999999999 |
| product_uom_id | integer | Yes | 単位ID | uoms.id存在チェック |
| price_unit | decimal | Yes | 単価 | 0以上、最大99999999999 |
| discount | decimal | No | 割引率(%) | 0-100 |
| taxes | array | No | 税ID配列 | accounts_taxes.id存在チェック |
| customer_lead | integer | No | リードタイム(日) | 0以上 |
| product_packaging_id | integer | No | パッケージングID | products_packagings.id存在チェック |
| product_packaging_qty | decimal | No | パッケージング数量 | 0以上 |

### 入力データソース

- 画面入力（Filament管理パネル）
- 見積テンプレートからの自動設定
- 顧客マスタからのデフォルト値取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | integer | 見積書ID |
| name | string | 見積番号（SO/{id}形式） |
| state | enum | 見積状態（draft/sent/sale/cancel） |
| invoice_status | enum | 請求状態 |
| amount_untaxed | decimal | 税抜金額 |
| amount_tax | decimal | 税額 |
| amount_total | decimal | 合計金額 |
| validity_date | date | 有効期限 |
| date_order | date | 見積日/受注日 |
| created_at | datetime | 作成日時 |
| updated_at | datetime | 更新日時 |

### 出力先

- 画面表示（Filament管理パネル）
- データベーステーブル（sales_orders, sales_order_lines）
- PDF出力（見積書帳票）

## 処理フロー

### 処理シーケンス

```
1. 見積書作成
   ├─ 顧客選択 → 関連情報自動設定
   ├─ 商品明細追加 → 単価・税自動取得
   ├─ 金額計算（小計、税額、合計）
   └─ 保存（state=draft）

2. 見積書確定
   ├─ バリデーションチェック
   ├─ state更新（draft→sale）
   ├─ 見積番号の確定
   └─ 配送オペレーション作成（在庫連携時）

3. 見積書キャンセル
   ├─ 状態チェック
   └─ state更新（→cancel）
```

### フローチャート

```mermaid
flowchart TD
    A[見積書作成開始] --> B[顧客選択]
    B --> C[商品明細追加]
    C --> D{商品追加完了?}
    D -->|No| C
    D -->|Yes| E[金額計算]
    E --> F[保存]
    F --> G{操作種別}
    G -->|確定| H[バリデーション]
    H --> I{検証OK?}
    I -->|Yes| J[受注確定]
    I -->|No| K[エラー表示]
    G -->|キャンセル| L[キャンセル処理]
    J --> M[配送オペレーション作成]
    M --> N[終了]
    L --> N
    K --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-012-001 | 見積番号自動採番 | 見積番号はSO/{id}形式で自動生成 | 保存時 |
| BR-012-002 | 有効期限デフォルト | 設定されたデフォルト日数を加算して設定 | 新規作成時 |
| BR-012-003 | 受注後削除不可 | state=saleの見積書は削除不可 | 削除操作時 |
| BR-012-004 | ロック時編集不可 | locked=trueの見積書は編集不可 | 編集操作時 |
| BR-012-005 | 商品重複不可 | 同一商品の複数明細行追加を防止 | 明細追加時 |
| BR-012-006 | 削除済み商品選択不可 | ソフトデリートされた商品は選択不可 | 商品選択時 |
| BR-012-007 | キャンセル時明細編集不可 | state=cancelの見積書は明細編集不可 | 明細操作時 |

### 計算ロジック

**小計計算**:
```
price_subtotal = price_unit * product_qty * (1 - discount / 100)
```

**税額計算**:
```
price_tax = Tax::collect(taxes, price_subtotal, quantity)
```

**合計計算**:
```
price_total = price_subtotal + price_tax
```

**マージン計算**:
```
margin = (price_unit - purchase_price) * product_qty * (1 - discount / 100)
margin_percent = margin / (price_unit * product_qty) * 100
```

**UOM数量換算**:
```
product_uom_qty = product_qty / uom.factor
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 見積書一覧 | sales_orders | SELECT | 一覧取得（currencyとJOIN） |
| 見積書作成 | sales_orders | INSERT | ヘッダ情報挿入 |
| 見積書作成 | sales_order_lines | INSERT | 明細情報挿入 |
| 見積書作成 | sales_order_line_taxes | INSERT | 明細税情報挿入 |
| 見積書編集 | sales_orders | UPDATE | ヘッダ情報更新 |
| 見積書編集 | sales_order_lines | UPDATE/INSERT/DELETE | 明細情報更新 |
| 見積書削除 | sales_orders | UPDATE | ソフトデリート |
| タグ設定 | sales_order_tags | INSERT/DELETE | 多対多関係管理 |

### テーブル別操作詳細

#### sales_orders

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | WHERE deleted_at IS NULL | ソフトデリート除外 |
| INSERT | partner_id, validity_date, date_order, payment_term_id, user_id, company_id, currency_id, state, name | フォーム入力値 | state=draftで挿入 |
| UPDATE | 全カラム | フォーム入力値 | locked=falseの場合のみ |
| UPDATE | deleted_at | 現在日時 | ソフトデリート |

#### sales_order_lines

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | order_id, product_id, product_qty, product_uom_qty, price_unit, discount, price_subtotal, price_tax, price_total | 計算値含む | 親オーダーと連動 |
| UPDATE | 全カラム | 計算値含む | 親オーダーの状態確認 |
| DELETE | - | WHERE order_id = ? | 明細削除時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E-012-001 | バリデーションエラー | 必須項目未入力 | エラーメッセージ表示 |
| E-012-002 | 削除制約違反 | SALE状態での削除試行 | 削除不可メッセージ表示 |
| E-012-003 | 編集制約違反 | ロック済みの編集試行 | 編集不可メッセージ表示 |
| E-012-004 | 商品重複エラー | 同一商品の複数選択 | 重複警告メッセージ表示 |
| E-012-005 | 外部キー制約違反 | 参照先が存在しない | エラーメッセージ表示 |

### リトライ仕様

データベース操作失敗時は自動リトライなし。ユーザーによる再操作を促す。

## トランザクション仕様

- 見積書ヘッダと明細は同一トランザクションで処理
- 明細の一括更新はEloquent Relationship経由で自動管理
- 状態変更と関連オペレーション作成は同一トランザクション

## パフォーマンス要件

- 見積書一覧表示: 2秒以内（100件まで）
- 見積書作成・更新: 3秒以内
- 金額再計算: リアルタイム（フロントエンド処理）
- currency情報はeager loadingで取得

## セキュリティ考慮事項

- OrderPolicyによるアクセス制御
- CSRF対策: Laravelの標準CSRF保護を適用
- 入力値サニタイズ: Laravelのバリデーション機能を使用
- noteフィールドのXSS対策（RichEditor使用時）
- 削除済み顧客・商品の選択を無効化

## 備考

- ProgressStepperコンポーネントで見積状態を視覚的に表示
- Summaryコンポーネント（Livewire）で金額サマリをリアルタイム表示
- オプション商品は見積明細へのワンクリック追加機能あり
- 設定（PriceSettings, ProductSettings）により割引・マージン・パッケージング表示を制御
