# 機能設計書 3-予算レポート・ダッシュボード

## 概要

本ドキュメントは、Actual Budget における予算の使用状況をグラフやチャートで可視化するダッシュボード機能の設計を記述する。複数のウィジェットを組み合わせてカスタマイズ可能なレポート画面を提供する。

### 本機能の処理概要

**業務上の目的・背景**：予算管理において、数値データだけでなく視覚的なグラフやチャートによる分析は、財務状況の把握と意思決定を大きく支援する。本機能は、純資産推移、キャッシュフロー、支出分析などの多様なレポートをダッシュボード形式で提供し、ユーザーが自分のニーズに合わせてウィジェットを配置・カスタマイズできる。複数のダッシュボードを作成し、用途に応じて切り替えることも可能である。

**機能の利用シーン**：
- 月次の財務状況をグラフで確認する
- 年間の純資産推移を追跡する
- カテゴリ別の支出傾向を分析する
- カスタムレポートを作成して特定の分析を行う
- ダッシュボードをエクスポートして共有する

**主要な処理内容**：
1. ダッシュボードの表示とウィジェット管理
2. 各種レポートウィジェットの描画（純資産、キャッシュフロー、支出分析等）
3. ウィジェットのドラッグ&ドロップによる配置変更
4. ダッシュボードのインポート/エクスポート
5. カスタムレポートの作成と保存

**関連システム・外部連携**：react-grid-layout によるレイアウト管理、グラフライブラリ（Recharts等）による可視化

**権限による制御**：特別な権限制御なし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 30 | レポートダッシュボード画面 | 主画面 | レポートカードの一覧表示・ダッシュボード管理 |
| 31 | 純資産レポート画面 | 参照画面 | 純資産推移グラフの表示・分析 |
| 32 | キャッシュフローレポート画面 | 参照画面 | 収入・支出のキャッシュフロー表示 |
| 33 | 支出レポート画面 | 参照画面 | カテゴリ別支出の詳細分析 |
| 34 | カスタムレポート画面 | 参照画面 | カスタマイズ可能なレポートの作成・編集 |
| 39 | 予算分析レポート画面 | 参照画面 | 予算vs実績の分析・比較表示 |

## 機能種別

データ表示 / グラフ描画 / CRUD操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| dashboardId | string | No | 表示するダッシュボードのID | 存在するダッシュボードID |
| widgetType | string | Yes（追加時） | ウィジェットの種類 | 有効なウィジェットタイプ |
| widgetMeta | object | No | ウィジェットのメタ情報 | ウィジェットタイプに応じた形式 |

### 入力データソース

- URL パラメータ：ダッシュボードID
- ユーザー操作：ウィジェットの追加・削除・配置変更

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| widgets | Widget[] | ダッシュボード上のウィジェット一覧 |
| layout | Layout[] | ウィジェットの配置情報 |
| chartData | object | 各ウィジェットのグラフデータ |

### 出力先

- 画面表示：ダッシュボード画面にウィジェットを描画
- エクスポート：JSON形式でダッシュボード設定を出力

## 処理フロー

### 処理シーケンス

```
1. ダッシュボード画面にアクセス
   └─ useDashboard フックでウィジェット一覧を取得

2. ReactGridLayout でウィジェットを配置
   └─ 各ウィジェットコンポーネントを描画

3. 編集モード切替
   └─ ドラッグ&ドロップでウィジェット配置変更

4. ウィジェット追加
   └─ メニューからウィジェットタイプを選択
   └─ dashboard-add-widget メッセージを送信

5. 配置変更時
   └─ onLayoutChange で dashboard-update を送信

6. エクスポート
   └─ JSON形式でダッシュボード設定を保存
```

### フローチャート

```mermaid
flowchart TD
    A[ダッシュボード画面アクセス] --> B[useDashboard でウィジェット取得]
    B --> C[ReactGridLayout でレンダリング]
    C --> D{編集モード?}
    D -->|Yes| E[ドラッグ&ドロップ有効]
    D -->|No| F[閲覧のみ]
    E --> G{配置変更?}
    G -->|Yes| H[dashboard-update 送信]
    G -->|No| I{ウィジェット追加?}
    I -->|Yes| J[dashboard-add-widget 送信]
    I -->|No| K{ウィジェット削除?}
    K -->|Yes| L[dashboard-remove-widget 送信]
    H --> M[UI更新]
    J --> M
    L --> M
    F --> N[グラフ表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | ウィジェット最小サイズ | カスタムレポート・マークダウンは 2x1、その他は 3x2 | ウィジェット追加・リサイズ時 |
| BR-002 | モバイルレイアウト | モバイルでは1列レイアウトに自動変換 | 画面幅が狭い場合 |
| BR-003 | デフォルトダッシュボード | 少なくとも1つのダッシュボードが必要 | ダッシュボード削除時 |
| BR-004 | 実験的機能 | Crossover、Budget Analysis は Feature Flag で制御 | 常時 |

### 計算ロジック

各ウィジェットの計算ロジックは対応するスプレッドシート関数で実行：
- 純資産：口座残高の時系列集計
- キャッシュフロー：収入・支出の月別集計
- 支出分析：カテゴリ別支出の集計

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ダッシュボード取得 | dashboard_pages | SELECT | ダッシュボード一覧を取得 |
| ウィジェット取得 | dashboard | SELECT | 指定ダッシュボードのウィジェット一覧 |
| ウィジェット追加 | dashboard | INSERT | 新規ウィジェットを追加 |
| ウィジェット更新 | dashboard | UPDATE | ウィジェットの配置・メタ情報を更新 |
| ウィジェット削除 | dashboard | DELETE | ウィジェットを削除 |

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

#### dashboard

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | id | UUID | 主キー |
| INSERT/UPDATE | type | ウィジェットタイプ | 'net-worth-card', 'cash-flow-card' 等 |
| INSERT/UPDATE | x, y, width, height | 配置座標とサイズ | グリッド単位 |
| INSERT/UPDATE | meta | JSON | ウィジェット固有のメタ情報 |
| INSERT/UPDATE | dashboard_page_id | ダッシュボードID | 外部キー |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| json-parse-error | インポートエラー | JSONパースに失敗 | エラー通知を表示 |
| validation-error | インポートエラー | スキーマ検証に失敗 | 詳細メッセージを表示 |
| WIDGET_NOT_FOUND | データ不整合 | ウィジェットが見つからない | エラーログ出力 |

### リトライ仕様

- インポートエラー時はユーザーに通知、Undo可能

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

- ダッシュボードのインポート/リセットはアトミック操作

## パフォーマンス要件

- ダッシュボード表示：1秒以内
- グラフ描画：データ量に応じて最適化

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

- ダッシュボード設定はローカル保存
- エクスポートファイルには機密データを含まない

## 備考

- Feature Flag で一部機能（Crossover、Budget Analysis）を制御
- モバイル対応はレスポンシブレイアウトで実現

---

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

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

### 推奨読解順序

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

ウィジェットとダッシュボードのデータ型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models/index.ts | `packages/loot-core/src/types/models/index.ts` | Widget, DashboardEntity 型定義 |

**読解のコツ**: Widget は type プロパティで種類を識別し、meta プロパティでウィジェット固有の設定を持つ。

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

レポート画面のルーティングと初期化を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ReportRouter.tsx | `packages/desktop-client/src/components/reports/ReportRouter.tsx` | 各レポート画面へのルーティング |
| 2-2 | index.tsx | `packages/desktop-client/src/components/reports/index.tsx` | レポートページのエントリーポイント |

**主要処理フロー**:
- **17-53行目** (ReportRouter.tsx): 各レポートタイプへのルーティング定義
- Feature Flag による条件付きルート（crossoverReportEnabled, budgetAnalysisReportEnabled）

#### Step 3: ダッシュボード表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Overview.tsx | `packages/desktop-client/src/components/reports/Overview.tsx` | メインダッシュボードコンポーネント |

**主要処理フロー**:
- **94-96行目**: useDashboard でウィジェット一覧を取得
- **143-156行目**: desktopLayout の生成
- **216-231行目**: onLayoutChange でレイアウト変更を保存
- **233-244行目**: onAddWidget でウィジェット追加
- **665-809行目**: ReactGridLayout によるウィジェット描画

#### Step 4: 個別ウィジェットを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | NetWorthCard.tsx | `packages/desktop-client/src/components/reports/reports/NetWorthCard.tsx` | 純資産ウィジェット |
| 4-2 | CashFlowCard.tsx | `packages/desktop-client/src/components/reports/reports/CashFlowCard.tsx` | キャッシュフローウィジェット |
| 4-3 | SpendingCard.tsx | `packages/desktop-client/src/components/reports/reports/SpendingCard.tsx` | 支出分析ウィジェット |

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

```
Reports (index.tsx)
    │
    └─ ReportRouter
           │
           ├─ ReportsDashboardRouter
           │      │
           │      └─ Overview
           │             │
           │             ├─ useDashboard (ウィジェット取得)
           │             │
           │             ├─ ReactGridLayout
           │             │      │
           │             │      ├─ NetWorthCard
           │             │      ├─ CashFlowCard
           │             │      ├─ SpendingCard
           │             │      ├─ BudgetAnalysisCard
           │             │      ├─ CalendarCard
           │             │      ├─ SummaryCard
           │             │      ├─ CustomReportListCards
           │             │      └─ MarkdownCard
           │             │
           │             └─ DashboardHeader / DashboardSelector
           │
           ├─ NetWorth (詳細画面)
           ├─ CashFlow (詳細画面)
           ├─ Spending (詳細画面)
           └─ CustomReport (詳細画面)
```

### データフロー図

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

URL (dashboardId)  ───▶  useDashboard              ───▶  widgets 配列
                              │
                              ▼
                         ReactGridLayout
                         (layout 計算)            ───▶  レイアウト情報
                              │
                              ▼
ウィジェット操作      ───▶  onAddWidget /
(追加/削除/移動)           onRemoveWidget /
                         onLayoutChange           ───▶  DB更新
                              │
                              ▼
                         各ウィジェット
                         コンポーネント           ───▶  グラフ描画
                              │
                              ▼
                         spreadsheet計算          ───▶  chartData
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.tsx | `packages/desktop-client/src/components/reports/index.tsx` | ソース | レポートページエントリーポイント |
| ReportRouter.tsx | `packages/desktop-client/src/components/reports/ReportRouter.tsx` | ソース | レポートルーティング |
| Overview.tsx | `packages/desktop-client/src/components/reports/Overview.tsx` | ソース | ダッシュボードメインコンポーネント |
| NetWorthCard.tsx | `packages/desktop-client/src/components/reports/reports/NetWorthCard.tsx` | ソース | 純資産ウィジェット |
| CashFlowCard.tsx | `packages/desktop-client/src/components/reports/reports/CashFlowCard.tsx` | ソース | キャッシュフローウィジェット |
| SpendingCard.tsx | `packages/desktop-client/src/components/reports/reports/SpendingCard.tsx` | ソース | 支出分析ウィジェット |
| BudgetAnalysisCard.tsx | `packages/desktop-client/src/components/reports/reports/BudgetAnalysisCard.tsx` | ソース | 予算分析ウィジェット |
| CalendarCard.tsx | `packages/desktop-client/src/components/reports/reports/CalendarCard.tsx` | ソース | カレンダーウィジェット |
| SummaryCard.tsx | `packages/desktop-client/src/components/reports/reports/SummaryCard.tsx` | ソース | サマリーウィジェット |
| CustomReportListCards.tsx | `packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx` | ソース | カスタムレポートウィジェット |
| useDashboard.ts | `packages/desktop-client/src/hooks/useDashboard.ts` | ソース | ダッシュボードデータ取得フック |
| useReports.ts | `packages/desktop-client/src/hooks/useReports.ts` | ソース | カスタムレポート取得フック |
