# 画面設計書 35-サマリーレポート画面

## 概要

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

### 本画面の処理概要

サマリーレポート画面は、フィルタ条件に合致する取引の集計結果を、合計、平均、パーセンテージなど様々な形式で表示する画面である。数学的な表現を視覚化し、計算の過程と結果を同時に表示する。

**業務上の目的・背景**：特定のカテゴリや条件に合致する取引の総額を把握したり、月平均・年平均を計算したり、全体に占める割合を算出するニーズに対応する。例えば「食費の月平均はいくらか」「貯蓄が収入の何%か」といった分析を、直感的なビジュアル表現で確認できる。数式の形で計算過程を可視化することで、結果の根拠が明確になる。

**画面へのアクセス方法**：サイドバーの「レポート」メニューをクリック後、レポートダッシュボードから「サマリー」ウィジェットを選択、または直接 `/reports/summary/:id` URLにアクセスする。

**主要な操作・処理内容**：
1. 期間選択：開始日と終了日をドロップダウンから選択
2. 表示タイプ選択：合計、月平均、年平均、取引平均、パーセンテージから選択
3. 被除数フィルタ設定：分子となるデータのフィルタ条件を設定
4. 除数フィルタ設定（パーセンテージ時）：分母となるデータのフィルタ条件を設定
5. 全期間除数オプション（パーセンテージ時）：除数を全期間で計算するかのチェック
6. ウィジェット保存：ダッシュボードウィジェットとして現在の設定を保存

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

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | 収支レポート | 主機能 | 収支サマリーの表示 |

## 画面種別

詳細・分析画面

## URL/ルーティング

- `/reports/summary/:id` - ダッシュボードウィジェットID指定

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| 開始日 | 入力 | string | Yes | 表示期間の開始日 |
| 終了日 | 入力 | string | Yes | 表示期間の終了日 |
| 表示タイプ | 入力 | string | Yes | 'sum', 'avgPerMonth', 'avgPerYear', 'avgPerTransact', 'percentage' |
| 被除数フィルタ条件 | 入力 | array | No | RuleConditionEntity配列（分子用） |
| 除数フィルタ条件 | 入力 | array | No | RuleConditionEntity配列（分母用、パーセンテージ時） |
| 全期間除数 | 入力 | boolean | No | 除数を全期間で計算するか（パーセンテージ時） |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 被除数（分子）値 | number | フィルタ条件に合致する取引の合計 |
| 除数（分母）値 | number | 月数/年数/取引数またはフィルタ条件に合致する取引の合計 |
| 計算結果 | number | 被除数を除数で割った結果（合計時は被除数そのまま） |
| 数式表現 | component | シグマ記号と条件を用いた数学的表現 |

## イベント仕様

### 1-期間変更

ヘッダーの期間選択を変更すると、`onChangeDates`関数が呼び出され、`start`, `end`, `mode`の状態が更新される。スプレッドシートが再計算される。

### 2-表示タイプ変更

「Show as」ドロップダウンで表示タイプを変更すると、`setContent`により内部状態が更新される。パーセンテージ以外のタイプでは除数が固定（月数、年数、取引数）される。

### 3-被除数フィルタ設定

被除数（分子）側のフィルタボタンからフィルタ条件を追加・編集すると、`dividendFilters`の状態が更新され、スプレッドシートが再計算される。

### 4-除数フィルタ設定

パーセンテージモード時、除数（分母）側のフィルタボタンからフィルタ条件を追加・編集すると、`divisorFilters`の状態が更新される。

### 5-全期間除数チェック

「All time divisor」チェックボックスの切り替えにより、除数の計算対象期間が変更される。チェック時は全取引期間、未チェック時は選択期間のみ。

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

「Save widget」ボタン押下時、`onSaveWidget`関数が実行され、フィルタ条件、期間、コンテンツ設定がウィジェットのメタデータとして保存される。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ウィジェット保存 | dashboard_widgets | UPDATE | ウィジェットのmeta情報を更新 |
| データ取得 | transactions | SELECT | 取引データを取得して集計 |

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

#### dashboard_widgets

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

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| MSG_WIDGET_SAVED | 成功 | Dashboard widget successfully saved. | ウィジェット保存成功時 |
| MSG_SAVE_ERROR | エラー | Cannot save: No widget available. | ウィジェットが存在しない状態で保存試行時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| ウィジェットが存在しない | 保存時にエラー通知を表示 |
| contentのJSONパースエラー | デフォルト値にフォールバック |
| データがない | フィルタなし時は「all transactions」と表示 |

## 備考

- 数式表現はシグマ記号（Σ）と括弧を用いて視覚的に表現
- フィルタ条件なしの場合は「all transactions」と緑色で表示
- プライバシーフィルタが有効な場合、金額表示がマスクされる
- パーセンテージ結果には「%」サフィックスが付加される
- 結果の色は正/負/ゼロで分けて表示される

---

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

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

### 推奨読解順序

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

まず、サマリーレポートで使用されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models.ts | `loot-core/types/models` | `SummaryWidget`, `SummaryContent`型の定義を確認 |
| 1-2 | summary-spreadsheet.ts | `packages/desktop-client/src/components/reports/spreadsheets/summary-spreadsheet.ts` | サマリーデータの集計ロジック |

**読解のコツ**: `SummaryContent`のtypeプロパティ（sum, avgPerMonth等）と、divisor関連プロパティの関係を理解する。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Summary.tsx | `packages/desktop-client/src/components/reports/reports/Summary.tsx` | `Summary`関数コンポーネントがエントリーポイント |

**主要処理フロー**:
1. **54-66行**: `Summary`関数 - ウィジェットデータの取得
2. **74-520行**: `SummaryInner`関数 - メインのレンダリングロジック
3. **90-111行**: content状態の初期化（JSONパース含む）
4. **120-138行**: summarySpreadsheetパラメータの生成
5. **140行**: useReportフック呼び出し

#### Step 3: 数式表現コンポーネントを理解する

数学的な視覚表現の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Summary.tsx 内Operator | 同上 行522-589 | 演算子表現コンポーネント |
| 3-2 | Summary.tsx 内SumWithRange | 同上 行591-650 | シグマ記号と範囲表現 |

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

```
Summary (エントリーポイント)
    │
    ├─ useWidget (ウィジェットデータ取得)
    │
    └─ SummaryInner (メインコンポーネント)
           │
           ├─ useRuleConditionFilters (被除数フィルタ)
           │      └─ dividendFilters
           │
           ├─ useRuleConditionFilters (除数フィルタ)
           │      └─ divisorFilters
           │
           ├─ summarySpreadsheet (データ計算)
           │      └─ useReport (データ取得フック)
           │
           ├─ Header (期間選択)
           │
           ├─ FieldSelect (表示タイプ選択)
           │
           ├─ Checkbox (全期間除数)
           │
           └─ Operator (数式表現)
                  │
                  ├─ SumWithRange (被除数)
                  │      ├─ SvgSum (シグマ記号)
                  │      ├─ 期間表示
                  │      └─ AppliedFilters / FilterButton
                  │
                  └─ SumWithRange (除数、パーセンテージ時)
```

### データフロー図

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

URLパラメータ ─────────▶ useWidget ─────────────────▶ ウィジェットメタデータ
                              │
                              ├──▶ meta.content (JSON) ──▶ content状態
                              │
期間選択 ──────────────▶ state (start, end, mode)
                              │
表示タイプ ────────────▶ content.type
    │                         │
    │   sum ──────────────────┼──▶ 合計のみ
    │   avgPerMonth ──────────┼──▶ 合計 / 月数
    │   avgPerYear ───────────┼──▶ 合計 / 年数
    │   avgPerTransact ───────┼──▶ 合計 / 取引数
    │   percentage ───────────┼──▶ 被除数合計 / 除数合計
                              │
被除数フィルタ ────────▶ dividendFilters
                              │
除数フィルタ ─────────▶ divisorFilters (percentage時)
                              │
全期間除数 ────────────▶ content.divisorAllTimeDateRange
                              │
                              ▼
                    summarySpreadsheet
                              │
                              ▼
                        useReport
                              │
                              ▼
取引データ(DB) ──────▶ データ集計処理 ─────────────▶ dividend
                                                        divisor
                                                        total
                                                        fromRange
                                                        toRange
                              │
                              ▼
                      Operator / 結果表示
                              │
                              ▼
                        画面表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Summary.tsx | `packages/desktop-client/src/components/reports/reports/Summary.tsx` | ソース | メインコンポーネント |
| summary-spreadsheet.ts | `packages/desktop-client/src/components/reports/spreadsheets/summary-spreadsheet.ts` | ソース | データ集計ロジック |
| Header.tsx | `packages/desktop-client/src/components/reports/Header.tsx` | ソース | 期間選択ヘッダー |
| AppliedFilters.tsx | `packages/desktop-client/src/components/filters/AppliedFilters.tsx` | ソース | 適用済みフィルタ表示 |
| FilterButton.tsx | `packages/desktop-client/src/components/filters/FiltersMenu.tsx` | ソース | フィルタボタン |
| FieldSelect.tsx | `packages/desktop-client/src/components/rules/RuleEditor.tsx` | ソース | フィールド選択コンポーネント |
| icons/v2.tsx | `@actual-app/components/icons/v2` | ソース | Σ、括弧等のアイコン |
