# アーキテクチャ設計書

## 概要

本ドキュメントは、InvenTree モバイルアプリケーションのアーキテクチャ設計を記載したものです。InvenTree アプリは、InvenTree 在庫管理システムのコンパニオンアプリとして、Flutter フレームワークを用いて開発されたクロスプラットフォームモバイルアプリケーションです。Android および iOS デバイスをネイティブサポートし、バーコードスキャン機能を中心とした在庫管理操作を提供します。

## システム全体構成

### アーキテクチャ概要図

[アーキテクチャ構成図](./アーキテクチャ構成図.md) を参照してください。

### システム境界と外部連携

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| InvenTree Server | REST API (HTTP/HTTPS) | 在庫データの取得・更新・作成・削除 |
| Sentry | HTTPS | エラー監視・クラッシュレポート |
| デバイスカメラ | ネイティブAPI | バーコードスキャン |
| ローカルファイルシステム | ファイルI/O | 設定データ・キャッシュ・添付ファイルの保存 |
| Google Play Store / Apple App Store | 配布チャネル | アプリ配布 |

## レイヤー構成

### アーキテクチャスタイル

本アプリケーションは **レイヤードアーキテクチャ** をベースに、以下の特徴を持つ構成となっています：

- **Presentation Layer**: Flutter Widget を用いた UI 構築
- **Application Layer**: API 通信・バーコード処理などのビジネスロジック
- **Domain Layer**: InvenTree のドメインモデル（Part、Stock、Order 等）
- **Infrastructure Layer**: ローカルストレージ、HTTP クライアント、ファイル管理

Flutter 固有のパターンとして、StatefulWidget と RefreshableState mixin を組み合わせた状態管理を採用しています。

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| Presentation | UI表示、ユーザー操作の受付、画面遷移 | `lib/widget/`配下の各Widget、`lib/settings/`配下の設定画面 |
| Application | API通信、バーコード処理、フォーム処理 | `InvenTreeAPI`、`BarcodeHandler`、`APIFormField` |
| Domain | ビジネスエンティティの定義、ドメインロジック | `InvenTreeModel`およびその派生クラス群 |
| Infrastructure | データ永続化、外部サービス連携 | `InvenTreePreferencesDB`、`UserProfileDBManager`、Sentry連携 |

### レイヤー間の依存関係ルール

- **Presentation → Application**: Widget から API クラスやハンドラを呼び出し
- **Presentation → Domain**: Widget 内でドメインモデルを参照・表示
- **Application → Domain**: API レスポンスをドメインモデルに変換
- **Application → Infrastructure**: HTTP通信、ローカルストレージアクセス
- **禁止事項**: Infrastructure層からPresentation層への直接参照は禁止

## モジュール構成

### ドメイン分割

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| Part（部品） | 部品情報、カテゴリ、テストテンプレートの管理 | `inventree/part.dart`、`widget/part/` |
| Stock（在庫） | 在庫アイテム、ロケーション、テスト結果の管理 | `inventree/stock.dart`、`widget/stock/` |
| Order（注文） | 購買注文、販売注文、出荷管理 | `inventree/purchase_order.dart`、`inventree/sales_order.dart`、`widget/order/` |
| Company（会社） | サプライヤー、顧客、メーカーの管理 | `inventree/company.dart`、`widget/company/` |
| Barcode（バーコード） | バーコードスキャン、処理ハンドラ | `barcode/` |
| Settings（設定） | アプリ設定、サーバー接続設定、ユーザープロファイル | `settings/`、`preferences.dart`、`user_profile.dart` |

### パッケージ構造

```
lib/
├── main.dart                    # アプリケーションエントリーポイント
├── api.dart                     # InvenTree API クライアント (シングルトン)
├── api_form.dart                # 動的フォーム生成・処理
├── app_colors.dart              # 色定義
├── dsn.dart                     # Sentry DSN 設定
├── helpers.dart                 # ユーティリティ関数
├── l10.dart                     # ローカリゼーションヘルパー
├── labels.dart                  # ラベル印刷機能
├── preferences.dart             # 設定管理 (Sembast NoSQL)
├── user_profile.dart            # ユーザープロファイル管理
├── barcode/                     # バーコード機能
│   ├── barcode.dart             # バーコードスキャンエントリ・ハンドラ実装
│   ├── camera_controller.dart   # カメラベースのスキャナ
│   ├── wedge_controller.dart    # ウェッジスキャナ対応
│   ├── controller.dart          # スキャナコントローラ基底クラス
│   ├── handler.dart             # バーコード処理ハンドラ基底クラス
│   ├── tones.dart               # スキャン音
│   ├── stock.dart               # 在庫関連バーコード処理
│   ├── purchase_order.dart      # 購買注文バーコード処理
│   └── sales_order.dart         # 販売注文バーコード処理
├── inventree/                   # ドメインモデル
│   ├── model.dart               # 基底モデルクラス (InvenTreeModel)
│   ├── part.dart                # 部品モデル
│   ├── stock.dart               # 在庫モデル
│   ├── company.dart             # 会社モデル
│   ├── purchase_order.dart      # 購買注文モデル
│   ├── sales_order.dart         # 販売注文モデル
│   ├── orders.dart              # 注文共通処理
│   ├── attachment.dart          # 添付ファイルモデル
│   ├── bom.dart                 # 部品表モデル
│   ├── notification.dart        # 通知モデル
│   ├── parameter.dart           # パラメータモデル
│   ├── project_code.dart        # プロジェクトコードモデル
│   ├── sentry.dart              # Sentry エラー報告
│   └── status_codes.dart        # ステータスコード管理
├── settings/                    # 設定画面
│   ├── settings.dart            # メイン設定画面
│   ├── app_settings.dart        # アプリ設定
│   ├── select_server.dart       # サーバー選択
│   ├── login.dart               # ログイン画面
│   ├── about.dart               # アプリ情報
│   ├── release.dart             # リリースノート
│   ├── barcode_settings.dart    # バーコード設定
│   ├── home_settings.dart       # ホーム画面設定
│   ├── part_settings.dart       # 部品表示設定
│   ├── stock_settings.dart      # 在庫表示設定
│   ├── purchase_order_settings.dart  # 購買注文設定
│   └── sales_order_settings.dart     # 販売注文設定
├── widget/                      # UIウィジェット
│   ├── home.dart                # ホーム画面
│   ├── drawer.dart              # ナビゲーションドロワー
│   ├── search.dart              # 検索画面
│   ├── refreshable_state.dart   # リフレッシュ可能な状態基底クラス
│   ├── paginator.dart           # ページネーション
│   ├── dialogs.dart             # ダイアログ
│   ├── snacks.dart              # スナックバー通知
│   ├── fields.dart              # フォームフィールド
│   ├── spinner.dart             # ローディングスピナー
│   ├── progress.dart            # プログレス表示
│   ├── back.dart                # 戻るボタン
│   ├── link_icon.dart           # リンクアイコン
│   ├── notes_widget.dart        # ノート表示
│   ├── notifications.dart       # 通知表示
│   ├── attachment_widget.dart   # 添付ファイルウィジェット
│   ├── parameter_widget.dart    # パラメータウィジェット
│   ├── part/                    # 部品関連ウィジェット
│   ├── stock/                   # 在庫関連ウィジェット
│   ├── order/                   # 注文関連ウィジェット
│   └── company/                 # 会社関連ウィジェット
└── l10n/                        # 多言語対応 (40言語以上)
    ├── app_en.arb               # 英語（基準）
    └── [locale]/                # 各言語ディレクトリ
```

### コンポーネント依存関係

```
┌─────────────────────────────────────────────────────────────┐
│                    main.dart (EntryPoint)                   │
└─────────────────────┬───────────────────────────────────────┘
                      │
        ┌─────────────▼─────────────┐
        │     InvenTreeApp          │
        │  (MaterialApp + Theme)    │
        └─────────────┬─────────────┘
                      │
        ┌─────────────▼─────────────┐
        │   InvenTreeHomePage       │
        │   (widget/home.dart)      │
        └─────────────┬─────────────┘
                      │
    ┌─────────────────┼─────────────────┐
    │                 │                 │
    ▼                 ▼                 ▼
┌───────────┐   ┌───────────┐   ┌───────────┐
│  Widget   │   │ Barcode   │   │ Settings  │
│  (各画面) │   │ Scanner   │   │  (設定)   │
└─────┬─────┘   └─────┬─────┘   └─────┬─────┘
      │               │               │
      └───────────────┼───────────────┘
                      │
        ┌─────────────▼─────────────┐
        │      InvenTreeAPI         │
        │    (api.dart - Singleton) │
        └─────────────┬─────────────┘
                      │
        ┌─────────────▼─────────────┐
        │    InvenTreeModel         │
        │   (Domain Models)         │
        └─────────────┬─────────────┘
                      │
    ┌─────────────────┼─────────────────┐
    │                 │                 │
    ▼                 ▼                 ▼
┌───────────┐   ┌───────────┐   ┌───────────┐
│ HTTP      │   │  Sembast  │   │  Sentry   │
│ Client    │   │  (NoSQL)  │   │ (Error)   │
└───────────┘   └───────────┘   └───────────┘
```

## ミドルウェア構成

### データベース

| 種類 | ミドルウェア | バージョン | 用途 |
| --- | --- | --- | --- |
| NoSQL (ローカル) | Sembast | ^3.6.0 | アプリ設定、ユーザープロファイルの永続化 |

### キャッシュ

| ミドルウェア | バージョン | 用途 | TTL |
| --- | --- | --- | --- |
| flutter_cache_manager | ^3.3.0 | ネットワーク画像キャッシュ | 設定可能 |
| cached_network_image | ^3.3.1 | 画像の表示とキャッシュ | 自動管理 |

### メッセージキュー

該当なし（本アプリケーションでは使用していません）

### 検索エンジン

該当なし（サーバー側で検索処理を実行）

### その他ミドルウェア

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| mobile_scanner | ^7.0.1 | バーコードスキャン（カメラ） |
| sentry_flutter | 8.14.2 | エラー監視・クラッシュレポート |
| http | ^1.4.0 | HTTP通信 |
| audioplayers | ^6.1.0 | スキャン音の再生 |
| adaptive_theme | ^3.3.0 | ダーク/ライトテーマ管理 |

## データフロー

### リクエスト処理の流れ

1. **ユーザー操作**: Widget 上でユーザーがアクション（タップ、入力等）を実行
2. **Widget 処理**: RefreshableState またはその派生クラスがイベントをハンドリング
3. **API呼び出し**: InvenTreeAPI シングルトンを通じて REST API を呼び出し
4. **HTTP通信**: HttpClient でサーバーに HTTPS リクエストを送信
5. **レスポンス受信**: APIResponse オブジェクトとしてレスポンスを受信
6. **モデル変換**: JSON データを InvenTreeModel 派生クラスに変換
7. **UI更新**: setState() を通じて Widget を再描画
8. **エラーハンドリング**: エラー時は Snackbar 表示および Sentry へのレポート

### 非同期処理の流れ

1. **バーコードスキャン開始**: scanBarcode() 関数でスキャナ画面を起動
2. **バーコード検出**: カメラまたはウェッジスキャナがバーコードを検出
3. **サーバー問い合わせ**: BarcodeHandler.processBarcode() で API に問い合わせ
4. **結果処理**: onBarcodeMatched / onBarcodeUnknown でハンドリング
5. **画面遷移**: 該当するドメインの詳細画面へ遷移
6. **フィードバック**: 音声・Snackbar でユーザーに結果を通知

### データ永続化の流れ

1. **設定変更**: ユーザーが設定画面で値を変更
2. **保存処理**: InvenTreeSettingsManager.setValue() を呼び出し
3. **Sembast 書き込み**: StoreRef を通じて NoSQL データベースに書き込み
4. **読み込み処理**: アプリ起動時に InvenTreeSettingsManager.getValue() で読み込み
5. **プロファイル管理**: UserProfileDBManager でサーバー接続情報を管理

## 横断的関心事

### 認証・認可

| 方式 | 実装箇所 | 対象 |
| --- | --- | --- |
| Token認証 | InvenTreeAPI._authorizationHeader() | 全API通信 |
| ロールベースアクセス制御 | InvenTreeAPI.checkRole() | 機能制限 |
| パーミッションチェック | InvenTreeAPI.checkPermission() | モデル操作制限 |

### ロギング・監査

| 種類 | 実装方式 | 保存先 |
| --- | --- | --- |
| デバッグログ | debug() ヘルパー関数 | コンソール出力 |
| エラーレポート | sentryReportError() | Sentry |
| メッセージレポート | sentryReportMessage() | Sentry |

### エラーハンドリング

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| ネットワークエラー | SocketException キャッチ | Snackbar通知 |
| タイムアウト | TimeoutException キャッチ | タイムアウトダイアログ |
| サーバーエラー (5xx) | ステータスコードチェック | エラーダイアログ + Sentry |
| クライアントエラー (4xx) | ステータスコードチェック | Snackbar通知 |
| SSL証明書エラー | badCertificateCallback | 設定に応じて許可/拒否 |
| JSON パースエラー | FormatException キャッチ | エラーダイアログ |

### トランザクション管理

| 範囲 | 管理方式 | 分離レベル |
| --- | --- | --- |
| ローカル設定 | Sembast 単一操作 | 自動 |
| APIリクエスト | 個別HTTPリクエスト | サーバー側で管理 |

## 設計原則・コーディング規約

### 適用している設計原則

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| シングルトンパターン | API クライアント、設定マネージャ | `InvenTreeAPI._internal()`, `InvenTreeSettingsManager._internal()` |
| ファクトリパターン | モデル生成 | `InvenTreeModel.createFromJson()` |
| テンプレートメソッドパターン | リフレッシュ可能ウィジェット | `RefreshableState.refresh()`, `request()` |
| ストラテジーパターン | バーコードハンドラ | `BarcodeHandler` と各種派生クラス |
| Mixin | ウィジェット共通機能 | `BaseWidgetProperties` mixin |
| 継承による拡張 | ドメインモデル | `InvenTreeModel` → `InvenTreePart`, `InvenTreeStockItem` 等 |

### コーディング規約

- **言語**: Dart 3.8.1 以上
- **フォーマッター**: dart format（analysis_options.yaml で設定）
- **Lint**: lint パッケージによる静的解析
- **命名規則**:
  - クラス名: UpperCamelCase
  - 変数・関数名: lowerCamelCase
  - 定数: SCREAMING_SNAKE_CASE または lowerCamelCase
  - ファイル名: snake_case.dart
- **null安全**: Dart null safety 完全対応
- **非同期処理**: async/await パターンを推奨
- **エラーハンドリング**: try-catch による例外処理、Sentry へのレポート

## 備考

- 本アプリケーションは InvenTree サーバー API バージョン 100 以上をサポート
- API バージョンに応じた機能の有効化/無効化を `InvenTreeAPI` クラス内で管理
- 多言語対応（40言語以上）は Flutter の国際化機能（flutter_localizations）を使用
- プラットフォーム固有の機能（カメラ、ファイルアクセス等）は各種 Flutter プラグインで対応
