# 帳票設計書 12-Stock Location QR and Text Label

## 概要

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

### 本帳票の処理概要

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

**業務上の目的・背景**：倉庫や保管場所の管理において、各ロケーションを視覚的にも機械的にも識別できることが求められる。本ラベルは、作業者がスキャナなしでも目視でロケーション名を確認できる一方、QRコードをスキャンして詳細情報にアクセスすることも可能にする。No.11のQRコードのみのラベルと比較して、人間が読める情報を追加することで、ピッキング作業やロケーション確認作業の効率性を向上させる。

**帳票の利用シーン**：新規ロケーションの作成時、棚卸作業の準備時、倉庫レイアウト変更時、既存ラベルの劣化・破損による再印刷時などに利用される。特に、QRスキャナを持たない作業者がロケーション名を目視で確認する必要がある場面で有用。

**主要な出力内容**：
1. 在庫ロケーションを一意に識別するQRコード画像
2. ロケーション名（location.name）のテキスト表示

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

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

## 帳票種別

ラベル

## 利用画面

| 画面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コードの右側に配置される。

```
┌─────────────────────────────────────┐
│  ┌─────────┐                        │
│  │         │  Warehouse A - Shelf 1 │
│  │   QR    │                        │
│  │  Code   │                        │
│  │         │                        │
│  └─────────┘                        │
└─────────────────────────────────────┘
```

### QRコード部

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

### テキスト部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ロケーション名 | 在庫ロケーションの名前 | StockLocation.name（location.nameコンテキスト変数） | テキスト |

## 出力条件

### 抽出条件

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

### ソート順

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

### 改ページ条件

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

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

### 参照テーブル一覧

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

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

#### stock_stocklocation

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

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| QRコードサイズ | height（mm） x height（mm） | - | ラベル高さに基づく正方形 |
| テキスト配置位置 | left: height（mm） | - | QRコードの右側に配置 |

## 処理フロー

### 出力フロー

```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_and_text.html`
- No.11との違いはロケーション名のテキスト表示の有無

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models.py | `src/backend/InvenTree/stock/models.py` | StockLocationReportContext（103-118行目）でコンテキストの型定義を確認。`location`オブジェクトが提供され、`location.name`でロケーション名にアクセス可能 |
| 1-2 | models.py | `src/backend/InvenTree/stock/models.py` | report_context()メソッド（170-178行目）で実際に渡されるデータを理解。`qr_data`と`location`が主要なコンテキスト変数 |

**読解のコツ**: テンプレートで`{{ location.name }}`として使用されるため、StockLocationモデルのnameフィールドを確認。

#### Step 2: テンプレートファイルの差異を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stocklocation_qr.html | `src/backend/InvenTree/report/templates/label/stocklocation_qr.html` | QRのみのベースラベルの構造を確認（比較用） |
| 2-2 | stocklocation_qr_and_text.html | `src/backend/InvenTree/report/templates/label/stocklocation_qr_and_text.html` | QR+テキストラベルの構造。`.loc`クラスでテキスト配置を確認（17-25行目）、`{{ location.name }}`でロケーション名表示（34行目） |

**主要処理フロー**:
- **17-25行目**: `.loc`クラスのスタイル定義
  - `left: {{ height }}mm` でQRコードの右側に配置
  - `top: 2mm` で上部余白
- **31行目**: QRコード画像の生成（qrcodeタグ使用）
- **33-35行目**: ロケーション名のテキスト表示

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

処理フローはNo.11と同一のため、詳細は省略。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | api.py | `src/backend/InvenTree/report/api.py` | LabelPrintクラス（95-224行目）がラベル印刷のエントリーポイント |

#### Step 4: レイアウト仕様を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | label_base.html | `src/backend/InvenTree/report/templates/label/label_base.html` | 基底テンプレートの構造。`{{ width }}`と`{{ height }}`がラベルサイズを決定 |

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

```
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()
                         │
                         ├─ plugin.print_labels()
                         │      │
                         │      └─ get_context() [models.py:704]
                         │             │
                         │             ├─ base_context()
                         │             │
                         │             └─ StockLocation.report_context()
                         │                    │
                         │                    └─ returns: location, qr_data, parent, stock_items
                         │
                         └─ plugin.after_printing()
```

### データフロー図

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

StockLocation.id ──────▶ LabelPrint API ──────────────────▶ DataOutput
                               │
                               ▼
                         LabelTemplate
                               │
                               ▼
                    ┌─────────────────────┐
                    │   report_context()  │
                    │  - location         │◀─── location.name を取得
                    │  - qr_data          │
                    │  - parent           │
                    └─────────────────────┘
                               │
                               ▼
                    ┌──────────────────────────────┐
                    │ stocklocation_qr_and_text.html│
                    │  + label_base.html           │
                    └──────────────────────────────┘
                               │
                    ┌──────────┴──────────┐
                    ▼                     ▼
            ┌─────────────┐       ┌─────────────┐
            │ qrcode tag  │       │ location.name│
            └─────────────┘       └─────────────┘
                    │                     │
                    ▼                     ▼
             QRコード画像            テキスト
                    │                     │
                    └─────────┬───────────┘
                              ▼
                         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_and_text.html | `src/backend/InvenTree/report/templates/label/stocklocation_qr_and_text.html` | テンプレート | 本ラベルのテンプレート |
| stocklocation_qr.html | `src/backend/InvenTree/report/templates/label/stocklocation_qr.html` | テンプレート | 比較対象（QRのみ）のテンプレート |
