# 帳票設計書 11-Stock Location QR Label

## 概要

本ドキュメントは、InvenTreeシステムにおける在庫ロケーションQRラベル（Stock Location QR Label）の設計仕様を定義するものである。

### 本帳票の処理概要

本ラベルは、在庫ロケーション（倉庫、棚、引き出しなど）を識別するためのQRコードを含むラベルを出力する機能を提供する。

**業務上の目的・背景**：倉庫や保管場所の管理において、各ロケーションを迅速かつ正確に識別することは在庫管理業務の効率化に不可欠である。本ラベルにより、作業者はスマートフォンやハンディターミナルでQRコードをスキャンするだけで、該当ロケーションの詳細情報にアクセスできる。手作業による入力ミスを防ぎ、在庫の入出庫作業やピッキング作業の正確性と効率を向上させることを目的とする。

**帳票の利用シーン**：新規ロケーションの作成時、棚卸作業の準備時、倉庫レイアウト変更時、既存ラベルの劣化・破損による再印刷時などに利用される。また、日常的な入出庫作業においてロケーション確認のために参照される。

**主要な出力内容**：
1. 在庫ロケーションを一意に識別するQRコード画像
2. QRコードにはロケーションのバーコードデータ（内部識別子）がエンコードされる

**帳票の出力タイミング**：在庫ロケーション詳細画面から「ラベル印刷」操作を実行した際に出力される。複数のロケーションを選択して一括印刷することも可能。

**帳票の利用者**：倉庫管理者、在庫管理担当者、物流担当者、ピッキング作業者

## 帳票種別

ラベル

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | Stock Location Detail | /stock/location/{id} | 「Print Label」ボタン |
| - | Stock Location List | /stock/location/ | 複数選択後「Print Labels」ボタン |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | PDF |
| 用紙サイズ | カスタム（テンプレート設定による） |
| 向き | - |
| ファイル名 | output.pdf（デフォルト、テンプレート設定で変更可能） |
| 出力方法 | ダウンロード / プラグインによる直接印刷 |
| 文字コード | UTF-8 |

### PDF固有設定

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

## 帳票レイアウト

### レイアウト概要

ラベル全体にQRコード画像のみを配置するシンプルなレイアウト。QRコードはラベルの左上を起点として、ラベルの高さと同じサイズの正方形で表示される。

```
┌─────────────────────────────────────┐
│  ┌─────────┐                        │
│  │         │                        │
│  │   QR    │                        │
│  │  Code   │                        │
│  │         │                        │
│  └─────────┘                        │
└─────────────────────────────────────┘
```

### QRコード部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | QRコード | ロケーションのバーコードデータをエンコードしたQRコード | StockLocation.barcode（qr_dataコンテキスト変数） | 画像（PNG base64） |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| ロケーションID | 対象となる在庫ロケーションのID | Yes |
| テンプレートフィルタ | LabelTemplateのfiltersフィールドで定義されたフィルタ条件 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| - | 指定なし（選択順） | - |

### 改ページ条件

1ラベル1ページ。複数ロケーション選択時は各ラベルが個別のページとして出力される。

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| stock_stocklocation | ロケーション情報の取得 | PRIMARY KEY (id) |

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

#### stock_stocklocation

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| id | 内部識別用 | WHERE id = {指定ID} | - |
| name | ロケーション名（本ラベルでは未使用） | - | QR+テキストラベルで使用 |
| barcode_data | QRコードデータ | - | JSON形式のバーコードデータ |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| QRコードサイズ | height（mm） x height（mm） | - | ラベル高さに基づく正方形 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[ラベル印刷要求] --> B[LabelPrint API呼び出し]
    B --> C[テンプレート・アイテム検証]
    C --> D[DataOutput生成]
    D --> E[バックグラウンドタスク起動]
    E --> F[各ロケーションに対してループ]
    F --> G[report_context取得]
    G --> H[テンプレートレンダリング]
    H --> I[QRコード生成]
    I --> J[HTML→PDF変換]
    J --> K{全件処理完了?}
    K -->|No| F
    K -->|Yes| L[PDF結合]
    L --> M[DataOutput更新]
    M --> N[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | 指定されたロケーションが存在しない | No valid items provided to template | 有効なロケーションIDを指定 |
| テンプレートエラー | テンプレートファイルが存在しない | Template file {name} does not exist | テンプレートファイルを確認 |
| テンプレート構文エラー | テンプレートの構文が不正 | Template syntax error | テンプレートを修正 |
| プラグインエラー | 印刷プラグインが見つからない | Plugin not found | プラグイン設定を確認 |

## パフォーマンス要件

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

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

- ラベル印刷はログイン済みユーザーのみ実行可能（IsAuthenticatedOrReadScope）
- QRコードにはロケーションの内部識別子のみが含まれ、機密情報は含まれない
- テンプレートの作成・編集はスタッフ権限が必要（IsStaffOrReadOnlyScope）

## 備考

- QRコードの生成には`qrcode`ライブラリを使用
- デフォルトのエラー訂正レベルは「M」（15%）
- テンプレートはDjangoテンプレート言語で記述され、カスタマイズ可能
- テンプレートファイル: `stocklocation_qr.html`

---

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

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

### 推奨読解順序

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

まず、ラベル出力に使用されるコンテキストデータの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models.py | `src/backend/InvenTree/stock/models.py` | StockLocationReportContext（103-118行目）でコンテキストの型定義を確認。report_context()メソッド（170-178行目）で実際に渡されるデータを理解 |
| 1-2 | models.py | `src/backend/InvenTree/report/models.py` | LabelContextExtension（164-176行目）でラベル固有のコンテキスト（width, height, page_style）を確認 |

**読解のコツ**: TypedDictによる型定義を読むことで、テンプレートで利用可能な変数が明確になる。

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

処理の起点となるAPI エンドポイントを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | api.py | `src/backend/InvenTree/report/api.py` | LabelPrintクラス（95-224行目）がラベル印刷のエントリーポイント。postメソッド（157-185行目）でリクエスト処理の流れを確認 |

**主要処理フロー**:
1. **157-160行目**: リクエストデータのシリアライズと検証
2. **162-165行目**: テンプレートの取得と寸法検証
3. **167行目**: 印刷対象アイテムの取得
4. **177-180行目**: モデルインスタンスの取得とソート
5. **185行目**: printメソッド呼び出し

#### Step 3: テンプレートモデルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | models.py | `src/backend/InvenTree/report/models.py` | LabelTemplateクラス（656-794行目）でラベルテンプレートの構造を理解。get_context()メソッド（704-728行目）でコンテキスト生成を確認 |
| 3-2 | models.py | `src/backend/InvenTree/report/models.py` | print()メソッド（730-794行目）で実際の印刷処理フローを確認 |

**主要処理フロー**:
- **704-728行目**: コンテキスト生成（base_context + label固有 + プラグイン拡張）
- **688-702行目**: @pageスタイル生成（ラベルサイズ設定）

#### Step 4: テンプレートファイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | label_base.html | `src/backend/InvenTree/report/templates/label/label_base.html` | 基底テンプレートの構造。CSSスタイルとコンテンツブロックの定義を確認 |
| 4-2 | stocklocation_qr.html | `src/backend/InvenTree/report/templates/label/stocklocation_qr.html` | 実際のラベルテンプレート。QRコード表示の実装を確認 |

**主要処理フロー**:
- **label_base.html 36-44行目**: `.content`クラスでラベルサイズを設定
- **stocklocation_qr.html 7-15行目**: QRコードのスタイル定義（heightに基づく正方形）
- **stocklocation_qr.html 20行目**: qrcodeテンプレートタグでQRコード生成

#### Step 5: QRコード生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | barcode.py | `src/backend/InvenTree/report/templatetags/barcode.py` | qrcodeテンプレートタグ（49-95行目）の実装。QRCodeライブラリの使用方法を確認 |

**主要処理フロー**:
- **82-90行目**: QRCodeオブジェクトの生成とデータ追加
- **92行目**: 画像生成
- **95行目**: base64エンコードして返却

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

```
LabelPrint.post() [api.py:157]
    │
    ├─ serializer.is_valid() [api.py:160]
    │
    ├─ get_plugin_class() [api.py:102-125]
    │
    ├─ template.get_model().objects.filter() [api.py:177]
    │
    └─ print() [api.py:187-224]
           │
           ├─ DataOutput.objects.create() [api.py:200-209]
           │
           └─ offload_task(report.tasks.print_labels) [api.py:213-220]
                  │
                  └─ LabelTemplate.print() [models.py:730]
                         │
                         ├─ plugin.before_printing() [models.py:776-777]
                         │
                         ├─ plugin.print_labels() [models.py:779]
                         │      │
                         │      └─ get_context() [models.py:704]
                         │             │
                         │             ├─ base_context() [models.py:323-334]
                         │             │
                         │             └─ instance.report_context() [stock/models.py:170]
                         │
                         └─ plugin.after_printing() [models.py:781-782]
```

### データフロー図

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

StockLocation.id ──────▶ LabelPrint API ──────────────────▶ DataOutput
                               │
                               ▼
                         LabelTemplate
                               │
                               ▼
                    ┌─────────────────────┐
                    │   report_context()  │
                    │  - location         │
                    │  - qr_data          │
                    │  - parent           │
                    └─────────────────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │ stocklocation_qr.html│
                    │  + label_base.html  │
                    └─────────────────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │   qrcode tag        │──────────────▶ QRコード画像
                    │  (barcode.py)       │               (base64)
                    └─────────────────────┘
                               │
                               ▼
                         WeasyPrint ────────────────────▶ PDF
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| api.py | `src/backend/InvenTree/report/api.py` | ソース | ラベル印刷APIエンドポイント |
| models.py | `src/backend/InvenTree/report/models.py` | ソース | LabelTemplateモデル定義 |
| models.py | `src/backend/InvenTree/stock/models.py` | ソース | StockLocationモデルとreport_context |
| barcode.py | `src/backend/InvenTree/report/templatetags/barcode.py` | ソース | QRコード生成テンプレートタグ |
| label_base.html | `src/backend/InvenTree/report/templates/label/label_base.html` | テンプレート | ラベル基底テンプレート |
| stocklocation_qr.html | `src/backend/InvenTree/report/templates/label/stocklocation_qr.html` | テンプレート | 本ラベルのテンプレート |
| serializers.py | `src/backend/InvenTree/report/serializers.py` | ソース | APIシリアライザ |
| tasks.py | `src/backend/InvenTree/report/tasks.py` | ソース | バックグラウンドタスク |
