# 画面設計書 32-キャッシュフローレポート画面

## 概要

本ドキュメントは、Actual Budget アプリケーションのキャッシュフローレポート画面の設計仕様を記述したものである。

### 本画面の処理概要

キャッシュフローレポート画面は、ユーザーの収入・支出・振替の推移を時系列で可視化する画面である。予算対象口座のキャッシュフロー（現金の流れ）を日別または月別で集計し、棒グラフと折れ線グラフを組み合わせて表示する。

**業務上の目的・背景**：家計管理において、収入と支出のバランスを把握することは予算計画の基盤となる。この画面では、指定期間内の収入・支出の推移を可視化することで、キャッシュフローのパターンや季節変動を分析できる。収入が支出を上回っているか、どの時期に支出が増加するかといった傾向を把握することで、より効果的な予算配分と貯蓄計画の立案が可能となる。「手元資金」の変動を追跡することで、資金繰りの安定性を評価できる。

**画面へのアクセス方法**：サイドバーの「レポート」メニューをクリック後、レポートダッシュボードから「キャッシュフロー」カードを選択、または直接 `/reports/cash-flow` URLにアクセスする。ダッシュボードウィジェットとして追加されている場合は、ウィジェットIDを含むURL `/reports/cash-flow/:id` でアクセスする。

**主要な操作・処理内容**：
1. 期間選択：開始月と終了月をドロップダウンから選択、またはプリセットボタンで期間を指定
2. 残高表示の切替：残高の推移ラインの表示/非表示を切り替え
3. フィルタ適用：口座やカテゴリなどの条件でデータをフィルタリング
4. ウィジェット保存：ダッシュボードウィジェットとして現在の設定を保存

**画面遷移**：レポートダッシュボード画面（`/reports`）から遷移する。モバイル画面幅では戻るボタンでレポートダッシュボードへ戻る。

**権限による表示制御**：特に権限による制御はない。予算ファイルがロードされていることが前提条件となる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | 収支レポート | 主機能 | 収入・支出のキャッシュフロー表示 |
| 34 | カテゴリ別支出 | 補助機能 | カテゴリごとの収支内訳表示 |

## 画面種別

詳細・分析画面

## URL/ルーティング

- `/reports/cash-flow` - 基本URL
- `/reports/cash-flow/:id` - ダッシュボードウィジェットID指定時

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| 開始日 | 入力 | string | Yes | 表示期間の開始日（YYYY-MM-DD形式） |
| 終了日 | 入力 | string | Yes | 表示期間の終了日（YYYY-MM-DD形式） |
| 表示モード | 入力 | string | Yes | 'static' または 'sliding-window' |
| 残高表示 | 入力 | boolean | Yes | 残高推移ラインの表示有無 |
| フィルタ条件 | 入力 | array | No | RuleConditionEntity配列 |
| フィルタ演算子 | 入力 | string | No | 'and' または 'or' |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 総収入 | number | 期間内の収入合計額 |
| 総支出 | number | 期間内の支出合計額 |
| 総振替 | number | 期間内の振替合計額 |
| 変動額 | number | 収入+支出+振替の合計変動額 |
| キャッシュフローグラフ | chart | 日別/月別の収入・支出を示す棒グラフと残高推移の折れ線グラフ |

## イベント仕様

### 1-期間変更

ユーザーが開始月または終了月のドロップダウンを変更した際、`onChangeDates`関数が呼び出される。期間が31日*3ヶ月を超える場合は自動的に月別集計（concise）モードに切り替わる。

### 2-残高表示切替

「Show balance」/「Hide balance」ボタン押下で、`setShowBalance`により状態が切り替わり、グラフ上の残高推移ラインの表示/非表示が変更される。

### 3-フィルタ適用

フィルタボタンからフィルタ条件を追加すると、`onApplyFilter`が呼び出され、条件配列が更新される。スプレッドシートが再計算され、フィルタ条件に合致するデータのみが表示される。

### 4-ウィジェット保存

「Save widget」ボタン押下時、`onSaveWidget`関数が実行され、`send('dashboard-update-widget', {...})`によりサーバーへウィジェット設定が保存される。保存内容にはshowBalance設定も含まれる。

### 5-ウィジェット名変更

タイトルをクリックして編集モードに入り、新しい名前を入力して確定すると、`onSaveWidgetName`関数が実行され、ウィジェットのメタデータが更新される。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ウィジェット保存 | dashboard_widgets | UPDATE | ウィジェットのmeta情報を更新 |
| ウィジェット名変更 | dashboard_widgets | UPDATE | ウィジェットのmeta.nameを更新 |
| データ取得 | transactions | SELECT | 取引データを取得してキャッシュフローを計算 |

### テーブル別更新項目詳細

#### dashboard_widgets

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | meta | JSON（conditions, conditionsOp, timeFrame, showBalance） | ウィジェット保存時 |
| UPDATE | meta.name | string | ウィジェット名変更時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| MSG_WIDGET_SAVED | 成功 | Dashboard widget successfully saved. | ウィジェット保存成功時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| ウィジェットが存在しない | 「Save widget」ボタンが表示されない |
| データがない | グラフが空の状態で表示される |
| 取引データ取得失敗 | ローディング状態が継続 |

## 備考

- キャッシュフローは予算対象口座（budgeted accounts）のみを対象として計算される
- 3ヶ月を超える期間を選択すると自動的に月別集計モードに切り替わる
- 収入は正の値、支出は負の値として表示される
- グラフはRechartsライブラリを使用してレンダリングされる
- プライバシーフィルタが有効な場合、金額表示がマスクされる

---

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

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

### 推奨読解順序

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

まず、キャッシュフローレポートで使用されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models.ts | `loot-core/types/models` | `CashFlowWidget`, `TimeFrame`型の定義を確認 |
| 1-2 | cash-flow-spreadsheet.ts | `packages/desktop-client/src/components/reports/spreadsheets/cash-flow-spreadsheet.ts` | キャッシュフローデータの集計ロジックと戻り値の構造を理解 |

**読解のコツ**: `cashFlowByDate`関数の戻り値構造（graphData, totalExpenses, totalIncome, totalTransfers）を確認する。

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

処理の起点となるメインコンポーネントを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CashFlow.tsx | `packages/desktop-client/src/components/reports/reports/CashFlow.tsx` | `CashFlow`関数コンポーネントがエントリーポイント。URLパラメータからウィジェットIDを取得 |

**主要処理フロー**:
1. **54-66行**: `CashFlow`関数 - ウィジェットデータの取得
2. **72-403行**: `CashFlowInner`関数 - メインのレンダリングロジック
3. **98-99行**: showBalance状態の初期化（ウィジェットメタデータまたはデフォルトtrue）
4. **111-123行**: params（スプレッドシートパラメータ）の生成
5. **124行**: `useReport`フック呼び出し

#### Step 3: データ取得層を理解する

スプレッドシート計算とデータ取得の流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cash-flow-spreadsheet.ts | `packages/desktop-client/src/components/reports/spreadsheets/cash-flow-spreadsheet.ts` | `cashFlowByDate`関数の実装。日別・月別の収支集計ロジック |
| 3-2 | useReport.ts | `packages/desktop-client/src/components/reports/useReport.ts` | レポートデータ取得のカスタムフック |

**主要処理フロー**:
- isConcise（月別表示）の判定は期間が31*3日を超えるかどうかで決定
- 取引データをクエリし、日付ごとに収入・支出・振替を集計

#### Step 4: UIコンポーネントを理解する

グラフ表示とサマリー表示の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Header.tsx | `packages/desktop-client/src/components/reports/Header.tsx` | 期間選択、フィルタボタン等の共通ヘッダーコンポーネント |
| 4-2 | CashFlowGraph.tsx | `packages/desktop-client/src/components/reports/graphs/CashFlowGraph.tsx` | Rechartsを使用したキャッシュフローグラフのレンダリング |

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

```
CashFlow (エントリーポイント)
    │
    ├─ useWidget (ウィジェットデータ取得)
    │      └─ send('dashboard-get-widget')
    │
    └─ CashFlowInner (メインコンポーネント)
           │
           ├─ useRuleConditionFilters (フィルタ管理)
           │
           ├─ cashFlowByDate (データ計算)
           │      └─ useReport (データ取得フック)
           │
           ├─ Header (期間・フィルタUI)
           │      ├─ Select (期間選択)
           │      └─ FilterButton (フィルタUI)
           │
           ├─ AlignedText (サマリー表示)
           │      └─ FinancialText (金額フォーマット)
           │
           └─ CashFlowGraph (グラフ描画)
                  └─ Recharts (グラフライブラリ)
```

### データフロー図

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

URLパラメータ ─────────▶ useWidget ─────────────────▶ ウィジェットメタデータ
                              │
期間選択 ──────────────▶ state (start, end, mode)
                              │
                              ├──▶ isConcise判定
                              │    (31*3日超で月別表示)
                              │
残高表示切替 ─────────▶ state (showBalance)
                              │
フィルタ ──────────────▶ useRuleConditionFilters
                              │
                              ▼
                      cashFlowByDate
                              │
                              ▼
                        useReport
                              │
                              ▼
取引データ(DB) ──────▶ データ集計処理 ─────────────▶ graphData
                              │                        totalIncome
                              │                        totalExpenses
                              │                        totalTransfers
                              ▼
                      CashFlowGraph
                              │
                              ▼
                        画面表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CashFlow.tsx | `packages/desktop-client/src/components/reports/reports/CashFlow.tsx` | ソース | メインコンポーネント |
| cash-flow-spreadsheet.ts | `packages/desktop-client/src/components/reports/spreadsheets/cash-flow-spreadsheet.ts` | ソース | データ集計ロジック |
| CashFlowGraph.tsx | `packages/desktop-client/src/components/reports/graphs/CashFlowGraph.tsx` | ソース | グラフ描画コンポーネント |
| Header.tsx | `packages/desktop-client/src/components/reports/Header.tsx` | ソース | 共通ヘッダーコンポーネント |
| useReport.ts | `packages/desktop-client/src/components/reports/useReport.ts` | ソース | レポートデータ取得フック |
| useWidget.ts | `packages/desktop-client/src/hooks/useWidget.ts` | ソース | ウィジェットデータ取得フック |
| reportRanges.ts | `packages/desktop-client/src/components/reports/reportRanges.ts` | ソース | 期間計算ユーティリティ |
| Change.tsx | `packages/desktop-client/src/components/reports/Change.tsx` | ソース | 変動額表示コンポーネント |
| AlignedText.tsx | `@actual-app/components/aligned-text` | ソース | 整列テキスト表示コンポーネント |
