# 帳票設計書 1-Bill of Materials Report

## 概要

本ドキュメントは、InvenTreeシステムにおける部品表（BOM: Bill of Materials）レポートの設計仕様を記載する。このレポートは部品とその構成部品の一覧をPDF形式で出力する帳票である。

### 本帳票の処理概要

本帳票は、製造業における部品管理の中核機能として、特定の部品（アセンブリ）を構成するサブ部品の一覧を視覚的に表示するレポートを生成する。

**業務上の目的・背景**：製造業において、製品を組み立てるために必要な部品を正確に把握することは生産計画の基盤である。本帳票は、設計部門が作成したBOM情報を生産現場や調達部門に伝達するための標準ドキュメントとして機能する。部品の調達漏れや組立ミスを防止し、製造プロセスの効率化を実現する。

**帳票の利用シーン**：新製品の製造開始時の部品調達リスト作成、既存製品の定期メンテナンス時の部品確認、製造現場での組立作業時の部品チェックリストとして利用される。また、サプライヤーへの発注時の参考資料としても活用される。

**主要な出力内容**：
1. 親部品の基本情報（部品名、説明、画像）
2. 構成部品（サブパーツ）の一覧
3. 各構成部品の必要数量
4. 参照番号（Reference）
5. 備考（Notes）

**帳票の出力タイミング**：部品詳細画面のBOMタブから、または製造オーダー作成時に関連する部品のBOMレポートとして出力される。

**帳票の利用者**：生産管理者、製造現場担当者、調達担当者、品質管理担当者

## 帳票種別

一覧表（部品構成表）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | 部品詳細画面 | /part/{part_id}/ | BOMタブからレポート出力ボタン |
| - | レポート印刷API | /api/report/print/ | POSTリクエスト |

## 出力形式

### 基本仕様

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

### PDF固有設定

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

## 帳票レイアウト

### レイアウト概要

ヘッダー部にロゴとタイトル、本文に親部品情報と構成部品一覧、フッターに日付とバージョン情報を配置する。

```
┌─────────────────────────────────────┐
│  [ロゴ]        Bill of Materials    │
├─────────────────────────────────────┤
│  Part                               │
│  ┌─────────────────────────────┐   │
│  │ 部品名        │ 部品画像   │   │
│  │ 説明          │            │   │
│  └─────────────────────────────┘   │
│                                     │
│  Materials needed                   │
│  ┌─────────────────────────────┐   │
│  │ Part | Qty | Ref | Note     │   │
│  │------|-----|-----|----------|   │
│  │ ...  | ... | ... | ...      │   │
│  └─────────────────────────────┘   │
├─────────────────────────────────────┤
│  v{revision} - {date}  {version}   │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ロゴ | システムロゴ画像 | logo_image テンプレートタグ | 画像（高さ20mm） |
| 2 | タイトル | 帳票タイトル | 固定値 "Bill of Materials" | テキスト（h3） |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Part | 構成部品名 | bom_items.sub_part.full_name | テキスト+サムネイル画像 | 自動 |
| 2 | Quantity | 必要数量 | bom_items.quantity | 数値 | 自動 |
| 3 | Reference | 参照番号 | bom_items.reference | テキスト | 自動 |
| 4 | Note | 備考 | bom_items.notes | テキスト | 自動 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | リビジョン | テンプレートリビジョン | report_revision | v{number} |
| 2 | 日付 | 出力日 | date | 日付形式 |
| 3 | バージョン | InvenTreeバージョン | inventree_version | テキスト |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| part_id | 対象部品のID | Yes |
| BomItem関連 | part.get_bom_items()で取得 | - |

### ソート順

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

### 改ページ条件

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

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| part_part | 親部品情報 | 直接参照 |
| part_bomitem | BOM構成情報 | part_id = part.id |
| part_part (sub_part) | サブ部品情報 | bomitem.sub_part_id |

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

#### part_part（親部品）

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| full_name | 部品名 | - | name + variant の組み合わせ |
| description | 説明 | - | - |
| image | 部品画像 | - | part_image テンプレートタグ経由 |

#### part_bomitem

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

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| - | - | - | 本帳票に計算項目なし |

## 処理フロー

### 出力フロー

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | 指定された部品が存在しない | No valid items provided to template | 有効な部品IDを指定 |
| テンプレートエラー | テンプレートファイルが存在しない | Template file does not exist | テンプレートファイルを確認 |
| 構文エラー | テンプレート構文エラー | Template syntax error | テンプレートの記述を修正 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1部品あたり最大100BOM項目 |
| 目標出力時間 | 5秒以内 |
| 同時出力数上限 | システム設定による |

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

- 認証済みユーザーのみがレポートを出力可能
- 部品データへのアクセス権限は既存の権限モデルに従う
- 出力ログはDataOutputモデルに記録

## 備考

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

---

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

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

### 推奨読解順序

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

まず、帳票で使用されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models.py | `src/backend/InvenTree/part/models.py` | PartReportContext（431-461行目）でレポートコンテキストの構造を確認。bom_itemsが帳票のメインデータ |
| 1-2 | models.py | `src/backend/InvenTree/part/models.py` | BomItemクラス（ファイル後半）でsub_part, quantity, reference, notesの定義を確認 |

**読解のコツ**: TypedDictを使ったPartReportContextクラスがコンテキストの型定義を提供しており、帳票で利用可能な全データ項目を把握できる。

#### Step 2: エントリーポイントを理解する

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | api.py | `src/backend/InvenTree/report/api.py` | ReportPrint.post()（253-269行目）がAPIエントリーポイント |
| 2-2 | api.py | `src/backend/InvenTree/report/api.py` | print()メソッド（271-300行目）でバックグラウンドタスクへのオフロード処理 |

**主要処理フロー**:
1. **253行目**: POSTリクエスト受付、シリアライザでバリデーション
2. **261-264行目**: テンプレートからモデルインスタンス取得
3. **282-291行目**: DataOutputオブジェクト作成
4. **296行目**: report.tasks.print_reportsタスクをオフロード

#### Step 3: レポート生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | models.py | `src/backend/InvenTree/report/models.py` | ReportTemplate.print()（465-653行目）がメインの印刷処理 |
| 3-2 | models.py | `src/backend/InvenTree/report/models.py` | render()（263-277行目）でHTMLからPDFへの変換処理 |
| 3-3 | models.py | `src/backend/InvenTree/report/models.py` | get_context()（423-432行目）でテンプレートコンテキスト生成 |

**主要処理フロー**:
- **487行目**: ログ出力開始
- **514-565行目**: merge=Trueの場合の処理（複数アイテムを1レポートに統合）
- **566-605行目**: merge=Falseの場合の処理（アイテムごとに個別レポート生成）
- **629-640行目**: 複数PDFをPdfWriterで結合

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | inventree_bill_of_materials_report.html | `src/backend/InvenTree/report/templates/report/inventree_bill_of_materials_report.html` | 帳票のHTMLテンプレート全体 |

**主要処理フロー**:
- **1行目**: 基底テンプレート継承
- **95-103行目**: ヘッダー部（ロゴ、タイトル）
- **105-131行目**: 親部品情報表示
- **133-160行目**: BOM項目一覧のテーブル出力（{% for line in bom_items.all %}ループ）

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

```
ReportPrint.post() [api.py:253]
    │
    ├─ get_serializer() [api.py:255]
    │      └─ ReportPrintSerializer
    │
    ├─ template.get_model() [models.py:307]
    │
    └─ print() [api.py:271]
           │
           ├─ DataOutput.objects.create() [api.py:282]
           │
           └─ offload_task(report.tasks.print_reports) [api.py:296]
                  │
                  └─ ReportTemplate.print() [models.py:465]
                         │
                         ├─ get_context() [models.py:423]
                         │      │
                         │      ├─ base_context() [models.py:323]
                         │      │
                         │      └─ instance.report_context() [part/models.py]
                         │             └─ PartReportContext
                         │
                         ├─ render() [models.py:263]
                         │      │
                         │      ├─ render_as_string() [models.py:247]
                         │      │
                         │      └─ HTML().write_pdf() [WeasyPrint]
                         │
                         └─ PdfWriter.append() [models.py:635]
```

### データフロー図

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

Part ID ──────────▶ Part.objects.get() ──────────▶ Part インスタンス
                           │
                           ▼
                    part.report_context()
                           │
                           ├─▶ bom_items (BomItem QuerySet)
                           ├─▶ part (Part)
                           ├─▶ description
                           └─▶ その他コンテキスト
                           │
                           ▼
                    render_to_string()
                           │
                           ▼
                    HTML → PDF (WeasyPrint)
                           │
                           ▼
                    DataOutput ──────────────────▶ PDF ファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inventree_bill_of_materials_report.html | `src/backend/InvenTree/report/templates/report/` | テンプレート | BOMレポートのHTMLテンプレート |
| inventree_report_base.html | `src/backend/InvenTree/report/templates/report/` | テンプレート | レポート共通基底テンプレート |
| models.py | `src/backend/InvenTree/report/` | ソース | ReportTemplate, LabelTemplateモデル定義 |
| api.py | `src/backend/InvenTree/report/` | ソース | レポートAPI定義 |
| models.py | `src/backend/InvenTree/part/` | ソース | Part, BomItemモデル定義 |
| mixins.py | `src/backend/InvenTree/report/` | ソース | InvenTreeReportMixin定義 |
| serializers.py | `src/backend/InvenTree/report/` | ソース | ReportPrintSerializer定義 |
