# 帳票設計書 2-ピッキング作業書 (Picking Operations)

## 概要

本ドキュメントは、在庫管理システムにおけるピッキング作業書（Picking Operations）のPDF帳票出力機能について、帳票レイアウト、データ取得仕様、出力条件等を定義する設計書である。

### 本帳票の処理概要

ピッキング作業書は、倉庫でのピッキング作業を効率的に行うためのPDF帳票であり、ピッキング対象の製品リスト、保管場所、数量、バーコード情報等を一覧形式で出力する機能を提供する。

**業務上の目的・背景**：ピッキング作業書は、倉庫内での商品取り出し作業（ピッキング）を効率化するための重要な帳票である。作業者が商品を正確かつ迅速に収集できるよう、製品の保管場所、必要数量、バーコード情報を明確に提示する。また、バーコードスキャンによる作業確認にも対応し、ピッキングミスの防止と作業効率の向上に貢献する。

**帳票の利用シーン**：入荷作業や内部移動作業の際に使用する。作業開始前に印刷し、作業者が倉庫内を移動しながら指定された場所から商品を収集する際の作業指示書として活用する。

**主要な出力内容**：
1. 出荷元会社情報（会社名、住所、連絡先）
2. 倉庫住所と仕入先住所
3. 伝票番号とバーコード、ステータス、予定日時
4. 製品明細（製品名、数量、保管場所、ロット/シリアル番号、製品バーコード）
5. 作業完了確認メッセージ

**帳票の出力タイミング**：在庫オペレーション画面から「Picking Operations」ボタンをクリックした際にPDFとしてダウンロードされる。

**帳票の利用者**：倉庫作業者、ピッキング担当者、出荷検品担当者

## 帳票種別

作業指示書

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| INV-002 | 在庫オペレーション詳細画面 | /inventories/operations/{type}/{id} | 「Picking Operations」ボタンクリック |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | PDF |
| 用紙サイズ | A4 |
| 向き | 縦（Portrait） |
| ファイル名 | Picking Operations-{オペレーション名}.pdf（スラッシュはアンダースコアに変換） |
| 出力方法 | ダウンロード（streamDownload） |
| 文字コード | UTF-8 |

### PDF固有設定

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

## 帳票レイアウト

### レイアウト概要

帳票は会社情報ヘッダー、倉庫/仕入先住所、伝票タイトルとバーコード、詳細情報、製品明細テーブル、作業確認フッターの構成となる。複数オペレーションを一括出力する場合は、各オペレーションごとにページ分割される。

```
+-----------------------------------------------+
|              出荷元会社情報                    |
|   (会社名、住所、Email、電話番号)              |
+-----------------------------------------------+
|    倉庫住所              |    仕入先住所       |
|  (Warehouse Address)    | (Vendor Address)   |
+-----------------------------------------------+
| Packing Slip #{伝票番号}     [バーコード]      |
+-----------------------------------------------+
| Status: {ステータス}   | Scheduled At: {日時} |
+-----------------------------------------------+
| Product | Qty | To | Lot/Serial | Barcode    |
|---------|-----|----|-----------  |-----------|
| 製品1   | 10  | A1 | LOT001     | [barcode] |
+-----------------------------------------------+
|   作業確認メッセージ                           |
+-----------------------------------------------+
```

### ヘッダー部（出荷元会社情報）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 会社名 | 出荷元会社の名称 | Operation.company.name | テキスト（28px、青色） |
| 2 | 住所1 | 会社の住所（番地） | Operation.company.partner.street1 | テキスト |
| 3 | 住所2 | 会社の住所（建物等） | Operation.company.partner.street2 | テキスト（存在する場合のみ） |
| 4 | 市区町村 | 市区町村名 | Operation.company.partner.city | テキスト |
| 5 | 都道府県 | 都道府県名 | Operation.company.partner.state.name | テキスト（存在する場合のみ） |
| 6 | 郵便番号 | 郵便番号 | Operation.company.partner.zip | テキスト |
| 7 | 国名 | 国名 | Operation.company.partner.country.name | テキスト（存在する場合のみ） |
| 8 | Email | 会社のメールアドレス | Operation.company.email | テキスト（存在する場合のみ） |
| 9 | 電話番号 | 会社の電話番号 | Operation.company.phone | テキスト（存在する場合のみ） |

### 倉庫住所部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | セクションタイトル | 「Warehouse Address」固定文字列 | - | 太字 |
| 2 | 住所1 | 倉庫住所（番地） | Operation.destinationLocation.warehouse.partnerAddress.street1 | テキスト |
| 3 | 住所2 | 倉庫住所（建物等） | Operation.destinationLocation.warehouse.partnerAddress.street2 | テキスト（存在する場合のみ） |
| 4 | 市区町村 | 市区町村名 | Operation.destinationLocation.warehouse.partnerAddress.city | テキスト |
| 5 | 都道府県 | 都道府県名 | Operation.destinationLocation.warehouse.partnerAddress.state.name | テキスト（存在する場合のみ） |
| 6 | 郵便番号 | 郵便番号 | Operation.destinationLocation.warehouse.partnerAddress.zip | テキスト |
| 7 | 国名 | 国名 | Operation.destinationLocation.warehouse.partnerAddress.country.name | テキスト（存在する場合のみ） |
| 8 | Email | 倉庫のメールアドレス | Operation.destinationLocation.warehouse.partnerAddress.email | テキスト（存在する場合のみ） |
| 9 | 電話番号 | 倉庫の電話番号 | Operation.destinationLocation.warehouse.partnerAddress.phone | テキスト（存在する場合のみ） |

### 仕入先住所部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | セクションタイトル | 「Vendor Address」固定文字列 | - | 太字 |
| 2 | 仕入先名 | 仕入先の名前 | Operation.partner.name | テキスト |
| 3 | 住所1 | 仕入先住所（番地） | Operation.partner.street1 | テキスト |
| 4 | 住所2 | 仕入先住所（建物等） | Operation.partner.street2 | テキスト（存在する場合のみ） |
| 5 | 市区町村 | 市区町村名 | Operation.partner.city | テキスト |
| 6 | 都道府県 | 都道府県名 | Operation.partner.state.name | テキスト（存在する場合のみ） |
| 7 | 郵便番号 | 郵便番号 | Operation.partner.zip | テキスト |
| 8 | 国名 | 国名 | Operation.partner.country.name | テキスト（存在する場合のみ） |
| 9 | Email | 仕入先のメールアドレス | Operation.partner.email | テキスト（存在する場合のみ） |
| 10 | 電話番号 | 仕入先の電話番号 | Operation.partner.phone | テキスト（存在する場合のみ） |

### 伝票タイトル部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 伝票タイトル | 「Packing Slip #」+オペレーション名 | Operation.name | 24px、青色、下線付き |
| 2 | オペレーションバーコード | オペレーション名のバーコード | Operation.name | Code128形式、高さ44px |

### 詳細情報部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | ステータス | オペレーションの状態 | Operation.state.name | テキスト |
| 2 | 予定日時 | 作業予定日時 | Operation.scheduled_at | 日時形式 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Product | 製品名 | MoveLine.product.name | テキスト | 自動 |
| 2 | Quantity | 数量と単位 | MoveLine.qty + MoveLine.uom.name | 数値（カンマ区切り） + 単位名 | 自動 |
| 3 | To | 保管先ロケーション（パッケージ名付き） | MoveLine.destinationLocation.full_name + MoveLine.resultPackage.name | テキスト | 自動 |
| 4 | Lot/Serial Number | ロット/シリアル番号とバーコード | MoveLine.lot.name | バーコード + テキスト（条件付き） | 自動 |
| 5 | Product Barcode | 製品バーコード | MoveLine.product.barcode | バーコード + テキスト（存在する場合） | 自動 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 確認メッセージ | 作業完了確認メッセージ | 固定文字列 | 中央揃え、グレー文字、0.9em |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| オペレーションID | 出力対象のOperation.id | Yes |
| moveLines | オペレーションに紐づくMoveLine一覧 | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | MoveLine.id | 昇順（デフォルト） |

### 改ページ条件

複数オペレーションを出力する場合、各オペレーションごとにページブレークが発生する（page-break-after: always）。最終オペレーションでは改ページしない。

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| inventories_operations | オペレーション基本情報 | 主テーブル |
| inventories_move_lines | 製品明細情報 | operation_id = inventories_operations.id |
| inventories_locations | ロケーション情報 | destination_location_id = id |
| inventories_warehouses | 倉庫情報 | locations.warehouse_id = id |
| products_products | 製品マスタ | inventories_move_lines.product_id = id |
| inventories_lots | ロット情報 | inventories_move_lines.lot_id = id |
| inventories_packages | パッケージ情報 | inventories_move_lines.result_package_id = id |
| support_uoms | 単位マスタ | inventories_move_lines.uom_id = id |
| support_companies | 会社情報 | inventories_operations.company_id = id |
| partners_partners | パートナー | 複数テーブルから参照 |

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

#### inventories_operations

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| name | 伝票番号、バーコード | id指定 | WH/OUT/XXX形式 |
| state | ステータス | - | Enum型 |
| scheduled_at | 予定日時 | - | datetime型 |
| company_id | 会社情報取得用 | - | FK |
| partner_id | 仕入先情報取得用 | - | FK |
| destination_location_id | 倉庫情報取得用 | - | FK |

#### inventories_move_lines

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| product_id | 製品情報取得用 | operation_id一致 | FK |
| qty | 数量 | - | decimal型 |
| uom_id | 単位情報取得用 | - | FK |
| lot_id | ロット情報取得用 | - | FK（nullable） |
| destination_location_id | 保管先ロケーション | - | FK |
| result_package_id | 結果パッケージ | - | FK（nullable） |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 数量表示 | number_format(qty) | 整数表示 | カンマ区切り |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[Picking Operationsボタンクリック] --> B[PickingOperationAction実行]
    B --> C[Operation recordsをViewに渡す]
    C --> D[Blade templateでHTML生成]
    D --> E[バーコード生成: DNS1D::getBarcodeHTML]
    E --> F[DomPDFでPDF変換]
    F --> G[用紙サイズA4縦設定]
    G --> H[streamDownloadでファイル返却]
    H --> I[ブラウザでダウンロード]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| データなし | moveLinesが空 | テーブル非表示 | テーブル部分をスキップして出力 |
| 会社情報なし | company.partnerがnull | 会社住所部分非表示 | 会社名のみ表示 |
| 仕入先なし | partnerがnull | 仕入先セクション非表示 | 仕入先セクションをスキップ |
| 倉庫住所なし | warehouse.partnerAddressがnull | 倉庫住所非表示 | 倉庫住所セクションをスキップ |
| バーコードなし | product.barcodeがnull | バーコード非表示 | バーコード列を空白で表示 |
| ロットなし | lotがnull | ロットバーコード非表示 | ロット列を空白で表示 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1オペレーションあたり明細100件程度 |
| 目標出力時間 | 5秒以内（バーコード生成含む） |
| 同時出力数上限 | 制限なし（ただしサーバーリソースに依存） |

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

- 仕入先・倉庫の情報（住所、電話番号、メールアドレス）を含むため、アクセス権限を持つユーザーのみが出力可能
- バーコードには製品情報・ロット情報が含まれるため、社外への持ち出し管理に注意
- PDF出力時のログ記録は実装されていない（必要に応じて監査ログの追加を検討）

## 備考

- ロット/シリアル番号列の表示は、TraceabilitySettings.enable_lots_serial_numbers設定が有効な場合のみ表示される
- バーコードはCode128形式で生成される（DNS1D::getBarcodeHTML使用）
- オペレーション名のバーコードは高さ44px、ロット/製品バーコードは高さ33pxで生成
- 保管先ロケーション表示時に、result_package_idが存在する場合はパッケージ名も併記される
- 複数オペレーションの一括出力に対応しているが、現在のUIでは単一オペレーションのみを対象としている
