# 機能設計書 20-在庫アイテム削除

## 概要

本ドキュメントは、InvenTreeモバイルアプリにおける在庫アイテム削除機能の設計仕様を定義する。

### 本機能の処理概要

本機能は、在庫アイテムをデータベースから削除する機能である。削除操作は取り消し不可能であるため、確認ダイアログを表示してユーザーの意図を確認した上で実行する。

**業務上の目的・背景**：在庫管理業務において、誤って作成した在庫レコードや不要になった在庫レコードを削除する必要がある場合がある。在庫が0になった後のレコードのクリーンアップや、重複して作成された在庫の整理などに使用される。モバイルアプリから直接削除できることで、現場での迅速なデータ整理が可能となる。

**機能の利用シーン**：
- 誤って作成した在庫アイテムを削除する場合
- 在庫が0になり不要となったレコードを整理する場合
- 重複して作成された在庫を削除する場合
- 古い在庫履歴をクリーンアップする場合

**主要な処理内容**：
1. 削除確認ダイアログの表示
2. ユーザーによる削除確認
3. APIリクエストによる在庫アイテムの削除
4. 削除成功時は前の画面に戻る

**関連システム・外部連携**：InvenTree APIの `stock/{pk}/` エンドポイント（DELETE）を使用して在庫アイテムを削除する。

**権限による制御**：`stock` ロールの `delete` 権限が必要である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | 在庫アイテム詳細画面 | 主画面 | 削除ボタン押下時に確認ダイアログ表示 |

## 機能種別

データ削除（DELETE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pk | int | Yes | 削除対象の在庫アイテムID | 正の整数、存在確認 |

### 入力データソース

- 在庫詳細画面で表示中の在庫アイテム

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 削除結果 | bool | 削除成功時true、失敗時false |

### 出力先

- InvenTreeデータベース（StockItemテーブルからレコード削除）
- 削除成功時は前の画面（在庫一覧またはロケーション画面）に遷移

## 処理フロー

### 処理シーケンス

```
1. 削除ボタンの表示
   └─ canDelete権限がある場合に表示
2. ユーザーが削除を選択
3. 確認ダイアログの表示
   └─ confirmationDialog()で削除確認
4. ユーザーによる確認
   ├─ キャンセル：ダイアログを閉じて何もしない
   └─ 削除実行：処理を続行
5. APIリクエストの実行
   └─ DELETE stock/{pk}/ エンドポイントにリクエスト
6. レスポンスの処理
   ├─ 成功：前の画面に戻り、成功メッセージを表示
   └─ 失敗：エラーメッセージを表示
```

### フローチャート

```mermaid
flowchart TD
    A[在庫詳細画面] --> B{canDelete?}
    B -->|No| C[削除ボタン非表示]
    B -->|Yes| D[削除ボタン表示]
    D --> E[ユーザーが削除を選択]
    E --> F[_deleteItem]
    F --> G[confirmationDialog表示]
    G --> H{ユーザー確認}
    H -->|キャンセル| I[ダイアログ閉じる]
    H -->|削除| J[widget.item.delete]
    J --> K{削除成功?}
    K -->|No| L[エラーメッセージ表示]
    L --> M[画面に留まる]
    K -->|Yes| N[Navigator.pop]
    N --> O[成功メッセージ表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-20-01 | 削除確認必須 | 削除前に必ず確認ダイアログを表示する | 常時 |
| BR-20-02 | 削除権限チェック | delete権限がない場合は削除ボタンを表示しない | 常時 |
| BR-20-03 | 削除取消不可 | 削除操作は取り消しできない | 常時 |
| BR-20-04 | 削除後遷移 | 削除成功後は前の画面に自動的に戻る | 常時 |
| BR-20-05 | ステータスコード確認 | 削除成功はHTTPステータス204で判定 | 常時 |

### 計算ロジック

- 特になし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 削除 | StockItem | DELETE | 在庫アイテムレコードを削除 |

### テーブル別操作詳細

#### StockItem（InvenTree API経由）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | 全カラム | pk指定のレコードを削除 | 物理削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | トークン無効または期限切れ | 再ログインを促す |
| 403 | 権限エラー | delete権限がない | 権限確認メッセージを表示 |
| 404 | Not Found | 在庫アイテムが既に存在しない | エラーメッセージを表示 |
| 500 | サーバーエラー | サーバー内部エラー | リトライまたはエラー表示 |

### リトライ仕様

サーバーエラー時は手動で再度削除操作を実行可能。

## トランザクション仕様

単一レコードの削除のため、明示的なトランザクション管理は不要。

## パフォーマンス要件

- 確認ダイアログ表示は即座に行う
- API応答は通常数秒以内

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

- API認証トークンによるアクセス制御
- `stock` ロールの `delete` 権限チェック
- HTTPS通信によるデータ保護
- 確認ダイアログによる誤操作防止

## 備考

- 削除操作は取り消しできないため、慎重に使用すること
- 削除前に関連データ（テスト結果、履歴等）への影響を考慮すること
- サーバー側で論理削除が設定されている場合は、実際にはソフトデリートとなる可能性がある

---

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

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

### 推奨読解順序

#### Step 1: 削除ボタンの表示制御を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | stock_detail.dart | `lib/widget/stock/stock_detail.dart` | actionButtons()での削除ボタン表示制御 |

**読解のコツ**:
- **144-154行目**: canDeleteによる削除ボタンの表示制御
- **147行目**: 赤色のゴミ箱アイコンで削除ボタンを表示
- **150行目**: _deleteItem()を呼び出し

#### Step 2: 削除処理の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stock_detail.dart | `lib/widget/stock/stock_detail.dart` | _deleteItem()の実装 |

**主要処理フロー**:
- **319-338行目**: _deleteItem()の実装
- **321-323行目**: confirmationDialog()で削除確認ダイアログを表示
- **327行目**: onAcceptコールバックでwidget.item.delete()を呼び出し
- **328行目**: delete()の戻り値で成功判定
- **330-331行目**: 成功時はNavigator.pop()で前の画面に戻り、成功メッセージ表示
- **333行目**: 失敗時はエラーメッセージ表示

#### Step 3: delete()メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | model.dart | `lib/inventree/model.dart` | delete()の基底実装 |

**主要処理フロー**:
- **543-566行目**: delete()の実装
- **545-547行目**: pkが無効な場合はfalseを返す
- **549行目**: api.delete(url)でDELETEリクエストを送信
- **551-562行目**: レスポンスの検証とエラーハンドリング
- **565行目**: ステータスコード204で成功判定

#### Step 4: 権限チェックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | model.dart | `lib/inventree/model.dart` | canDelete権限チェック |

**主要処理フロー**:
- **244-254行目**: canDeleteゲッターの実装
- **246-248行目**: rolesRequiredの各ロールに対してdelete権限をチェック
- **145行目（stock.dart）**: rolesRequired = ["stock"]

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

```
StockDetailWidget.actionButtons()
    │
    └─ canDelete チェック
           │
           └─ _deleteItem()
                  │
                  ├─ confirmationDialog()
                  │      └─ 削除確認ダイアログ表示
                  │
                  └─ onAccept callback
                         │
                         └─ widget.item.delete()
                                │
                                └─ api.delete(url)
                                       │
                                       └─ DELETE stock/{pk}/
                                              │
                                              ├─ 成功 (204)
                                              │      └─ Navigator.pop()
                                              │              └─ showSnackIcon(success)
                                              │
                                              └─ 失敗
                                                     └─ showSnackIcon(failure)
```

### データフロー図

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

削除ボタン押下 ───▶ confirmationDialog() ───▶ 確認待ち
                         │
                         ▼
               ユーザー確認 ───▶ delete()呼び出し
                                    │
                                    ▼
                          DELETE stock/{pk}/
                                    │
                    ┌───────────────┴───────────────┐
                    ▼                               ▼
              成功 (204)                         失敗
                    │                               │
                    ▼                               ▼
            Navigator.pop()               エラーメッセージ表示
                    │
                    ▼
           前の画面に戻る
           + 成功メッセージ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| stock_detail.dart | `lib/widget/stock/stock_detail.dart` | ソース | 削除ボタン表示、_deleteItem()実装 |
| stock.dart | `lib/inventree/stock.dart` | ソース | InvenTreeStockItemモデル、rolesRequired定義 |
| model.dart | `lib/inventree/model.dart` | ソース | delete()基底実装、canDelete権限チェック |
| api.dart | `lib/api.dart` | ソース | InvenTree API通信クラス、delete()メソッド |
| dialogs.dart | `lib/widget/dialogs.dart` | ソース | confirmationDialog()関数 |
| snacks.dart | `lib/widget/snacks.dart` | ソース | 成功/失敗メッセージ表示 |
