# 帳票設計書 4-Sales Order Report

## 概要

本ドキュメントは、InvenTreeシステムにおける販売オーダーレポートの設計仕様を記載する。このレポートは顧客への請求書/納品書として使用され、販売明細と合計金額をPDF形式で出力する帳票である。

### 本帳票の処理概要

本帳票は、顧客への請求書または納品書として使用される販売オーダー（Sales Order）の詳細レポートを生成する。販売品目、数量、単価、合計金額などの情報を一覧形式で出力する。

**業務上の目的・背景**：販売業務において、顧客への正式な請求書・納品書は取引の基本ドキュメントである。本帳票は、販売内容を明確に伝達し、顧客との取引記録として機能する。また、売上管理や会計処理の基礎資料としても使用される。

**帳票の利用シーン**：顧客への納品書・請求書送付、出荷前の内容確認、経理部門での売上計上、顧客からの問い合わせ対応時の参照資料として利用される。

**主要な出力内容**：
1. 販売オーダーの基本情報（参照番号、顧客名）
2. 販売明細（部品、数量、単価、小計）
3. 追加ライン項目（送料、手数料等）
4. 合計金額

**帳票の出力タイミング**：販売オーダー詳細画面から、受注確定後または出荷時に出力される。

**帳票の利用者**：営業担当者、出荷担当者、経理担当者、顧客

## 帳票種別

請求書/納品書

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | 販売オーダー詳細画面 | /sales/sales-order/{so_id}/ | レポート出力ボタン |
| - | レポート印刷API | /api/report/print/ | POSTリクエスト |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | PDF |
| 用紙サイズ | A4（設定により変更可能） |
| 向き | 縦 |
| ファイル名 | output.pdf（テンプレート設定により変更可能） |
| 出力方法 | ダウンロード |
| 文字コード | UTF-8 |

### PDF固有設定

| 項目 | 内容 |
|-----|------|
| パスワード保護 | 無 |
| 印刷制限 | 無 |
| 電子署名 | 無 |

## 帳票レイアウト

### レイアウト概要

ヘッダー部に顧客ロゴと販売オーダー情報、本文に明細一覧、フッターに合計金額を配置する。

```
┌─────────────────────────────────────┐
│  [Customer Logo]   Sales Order      │
│                    {prefix}{ref}    │
│                    {customer_name}  │
├─────────────────────────────────────┤
│  Line Items                         │
│  ┌─────────────────────────────┐   │
│  │Part|Ref|Qty|Unit|Total|Note │   │
│  │----|---|---|----|----|------|   │
│  │... |...|...|... |... |...   │   │
│  ├─────────────────────────────┤   │
│  │Extra Line Items             │   │
│  │... |...|...|... |... |...   │   │
│  ├─────────────────────────────┤   │
│  │         Total: {amount}     │   │
│  └─────────────────────────────┘   │
├─────────────────────────────────────┤
│  {date}                            │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 顧客ロゴ | 顧客企業ロゴ | company_image customer | 画像（幅150px） |
| 2 | タイトル | "Sales Order" | 固定値 | テキスト（h3） |
| 3 | 参照番号 | プレフィックス + 参照番号 | prefix, reference | テキスト |
| 4 | 顧客名 | 顧客企業名 | customer.name | テキスト |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Part | 部品名 + サムネイル | line.part.full_name | テキスト+画像 | 自動 |
| 2 | Reference | 参照番号 | line.reference | テキスト | 自動 |
| 3 | Quantity | 数量 | line.quantity | 数値（小数） | 自動 |
| 4 | Unit Price | 単価 | line.price | 通貨 | 自動 |
| 5 | Total Price | 小計 | line.total_line_price | 通貨 | 自動 |
| 6 | Note | 備考 | line.notes | テキスト | 自動 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Total | 合計金額 | order.total_price | 通貨 + 通貨コード |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| so_id | 対象販売オーダーのID | Yes |
| lines | 通常ライン項目 | - |
| extra_lines | 追加ライン項目 | - |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ライン項目のデフォルト順序 | - |

### 改ページ条件

明細項目が多い場合、ページ下端で自動改ページ

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| order_salesorder | 販売オーダー情報 | 直接参照 |
| company_company | 顧客情報 | salesorder.customer_id |
| order_salesorderlineitem | 販売明細 | salesorderlineitem.order_id |
| order_salesorderextraline | 追加明細 | salesorderextraline.order_id |
| part_part | 部品情報 | lineitem.part_id |

### テーブル別参照項目詳細

#### order_salesorder

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| reference | 参照番号 | - | - |
| total_price | 合計金額 | - | 自動計算 |
| order_currency | 通貨 | - | - |

#### order_salesorderlineitem

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| part | 部品 | - | ForeignKey |
| reference | 参照番号 | - | - |
| quantity | 数量 | - | - |
| price | 単価 | - | - |
| notes | 備考 | - | - |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Total Price (行) | quantity * price | - | total_line_priceプロパティ |
| Total (合計) | SUM(line.total_line_price) + SUM(extra_line.total_line_price) | 小数4桁 | TotalPriceMixin.calculate_total_price() |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[出力要求] --> B[パラメータ検証]
    B --> C[SalesOrder取得]
    C --> D[LineItems取得]
    D --> E[ExtraLines取得]
    E --> F[コンテキスト生成]
    F --> G[HTMLレンダリング]
    G --> H[WeasyPrintでPDF変換]
    H --> I[DataOutput保存]
    I --> J[ファイル返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | 指定された販売オーダーが存在しない | No valid items provided to template | 有効な販売オーダーIDを指定 |
| 通貨換算エラー | 為替レートが未設定 | - | 換算せずNULL返却 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1販売オーダーあたり最大50明細 |
| 目標出力時間 | 5秒以内 |
| 同時出力数上限 | システム設定による |

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

- 認証済みユーザーのみがレポートを出力可能
- 販売オーダーデータへのアクセス権限は既存の権限モデルに従う
- 顧客情報・金額情報は機密扱いの可能性があるため取扱注意
- 出力ログはDataOutputモデルに記録

## 備考

- テンプレートファイル: `src/backend/InvenTree/report/templates/report/inventree_sales_order_report.html`
- 基底テンプレート: `inventree_order_report_base.html`を継承
- i18n対応済み（多言語対応）

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models.py | `src/backend/InvenTree/order/models.py` | SalesOrderReportContext（224-244行目）でコンテキスト構造を確認 |
| 1-2 | models.py | `src/backend/InvenTree/order/models.py` | TotalPriceMixin（65-179行目）で合計計算ロジック確認 |

#### Step 2: テンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | inventree_sales_order_report.html | `src/backend/InvenTree/report/templates/report/` | 帳票全体構造 |

**主要処理フロー**:
- **9-18行目**: ヘッダー部（顧客ロゴ、タイトル、参照番号）
- **20-77行目**: 明細テーブル（通常ライン、追加ライン、合計）

### プログラム呼び出し階層図

```
ReportPrint.post() [api.py:253]
    │
    └─ ReportTemplate.print() [report/models.py:465]
           │
           ├─ get_context()
           │      │
           │      └─ salesorder.report_context()
           │             │
           │             ├─ lines (SalesOrderLineItem QuerySet)
           │             ├─ extra_lines (SalesOrderExtraLine QuerySet)
           │             └─ customer (Company)
           │
           └─ render() → HTML → PDF
```

### データフロー図

```
[入力]                    [処理]                         [出力]

SO ID ────────────▶ SalesOrder.objects.get() ───────▶ SO インスタンス
                           │
                           ▼
                    order.report_context()
                           │
                           ├─▶ lines (LineItem QuerySet)
                           ├─▶ extra_lines (ExtraLine QuerySet)
                           ├─▶ order (SalesOrder)
                           └─▶ customer (Company)
                           │
                           ▼
                    render_to_string() + render_currency
                           │
                           ▼
                    HTML → PDF (WeasyPrint) ─────────▶ PDF ファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inventree_sales_order_report.html | `src/backend/InvenTree/report/templates/report/` | テンプレート | 販売オーダーレポートのHTMLテンプレート |
| inventree_order_report_base.html | `src/backend/InvenTree/report/templates/report/` | テンプレート | オーダー系共通基底テンプレート |
| models.py | `src/backend/InvenTree/order/` | ソース | SalesOrder, SalesOrderLineItemモデル定義 |
| models.py | `src/backend/InvenTree/company/` | ソース | Companyモデル定義 |
