# 画面設計書 37-数式レポート画面

## 概要

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

### 本画面の処理概要

数式レポート画面は、ユーザーがExcel風の数式を記述し、定義したクエリに基づいて取引データを集計・計算できる高度なカスタマイズ画面である。HyperFormulaライブラリを使用して数式を評価し、結果を動的に表示する。

**業務上の目的・背景**：標準的なレポートでは対応できない独自の計算ニーズに対応する。例えば「収入に対する固定費の割合」「複数カテゴリの合計」「月間平均支出」など、ユーザー固有の計算式を定義して結果を確認できる。QUERY関数により、フィルタ条件や期間を指定した取引データの集計値を数式内で参照可能。条件付きで結果の色を変更することもでき、目標達成状況を視覚的に把握できる。

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

**主要な操作・処理内容**：
1. 数式入力：Excel風の数式（=SUM, =AVERAGE等）をエディタに入力
2. クエリ定義：取引データを集計するクエリを名前付きで定義
3. クエリ設定：各クエリに対してフィルタ条件と期間を設定
4. フォントサイズ設定：結果表示のフォントサイズを動的または固定で設定
5. 条件付き色設定：結果値に応じた色表示の数式を設定
6. ウィジェット保存：設定をダッシュボードウィジェットとして保存

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

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | 収支レポート | 主機能 | 数式による収支計算・表示 |

## 画面種別

詳細・分析画面

## URL/ルーティング

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

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| 数式 | 入力 | string | Yes | Excel風の数式（=で始まる） |
| クエリ定義 | 入力 | Record<string, QueryConfig> | No | 名前付きクエリの定義 |
| フォントサイズモード | 入力 | string | Yes | 'dynamic' または 'static' |
| 静的フォントサイズ | 入力 | number | No | 固定フォントサイズ（px） |
| 条件付き色数式 | 入力 | string | No | 色を返す数式（オプション） |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 計算結果 | number/string | 数式の評価結果 |
| 数式エディタ | component | CodeMirrorベースの数式入力エディタ |
| クエリ定義パネル | component | クエリの追加・編集・削除UI |
| フォントサイズ設定 | component | 表示サイズの設定UI |
| 条件付き色設定 | component | 色数式の入力UI |

## イベント仕様

### 1-数式変更

数式エディタの内容が変更されると、`setFormula`により状態が更新され、`useFormulaExecution`フックが再実行されて結果が再計算される。

### 2-クエリ追加

「Add Query」ボタン押下後、クエリ名を入力して「Create」ボタンを押すと、`handleAddQuery`関数が実行され、新しいクエリ定義が追加される。同名のクエリが存在する場合はエラー通知が表示される。

### 3-クエリ削除

クエリアイテムの削除ボタン（ゴミ箱アイコン）を押すと、`handleRemoveQuery`関数が実行され、該当クエリが削除される。

### 4-クエリ設定変更

クエリアイテム内のフィルタや期間設定を変更すると、`handleUpdateQuery`関数が呼び出され、クエリ設定が更新される。数式が再評価される。

### 5-フォントサイズモード変更

フォントサイズのドロップダウンで「Dynamic」または「Static」を選択すると、`setFontSizeMode`により状態が更新される。

### 6-静的フォントサイズ変更

フォントサイズモードが「Static」の場合、サイズ入力フィールドの値を変更すると`setStaticFontSize`により状態が更新される。

### 7-条件付き色数式変更

条件付き色の数式を変更すると、`setColorFormula`により状態が更新され、色数式が評価されて結果の表示色が変更される。

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

ヘッダーのタイトルをクリックして編集すると、`onSaveWidgetName`関数が実行され、ウィジェット名が更新される。

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

「Save widget」ボタン押下時、`onSaveWidget`関数が実行され、数式、クエリ定義、フォントサイズ設定、色数式がウィジェットのメタデータとして保存される。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ウィジェット保存 | dashboard_widgets | UPDATE | ウィジェットのmeta情報を更新 |
| クエリ実行 | transactions | SELECT | フィルタ条件に合致する取引を集計 |

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

#### dashboard_widgets

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | meta | JSON（formula, queries, fontSizeMode, staticFontSize, colorFormula, name） | ウィジェット保存時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| MSG_WIDGET_SAVED | 成功 | Dashboard widget successfully saved. | ウィジェット保存成功時 |
| MSG_NO_WIDGET | エラー | Cannot save: No widget available. | ウィジェットなしで保存試行時 |
| MSG_QUERY_EXISTS | エラー | Query with this name already exists | 同名クエリ追加試行時 |
| MSG_FORMULA_ERROR | エラー | Formula must start with = | 数式が=で始まらない場合 |
| MSG_EXPORT_SUCCESS | 成功 | Query configuration copied to clipboard | クエリ設定エクスポート成功時 |
| MSG_EXPORT_FAILED | エラー | Failed to copy to clipboard | クリップボードコピー失敗時 |
| MSG_IMPORT_INVALID | エラー | Invalid JSON. Please check your input. | 無効なJSON入力時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| ウィジェットが存在しない | 「Save widget」ボタンを押してもエラー通知を表示、保存処理中断 |
| 数式が=で始まらない | エラーメッセージを表示、結果はnull |
| 未定義のクエリ参照 | コンソール警告を出力、該当クエリの値は0として扱う |
| 数式評価エラー | エラーメッセージを表示、結果はnull |
| HyperFormulaインスタンス破棄エラー | コンソールエラー出力、エラーメッセージを設定 |

## 備考

- HyperFormulaライブラリを使用してExcel互換の数式評価を実行
- CodeMirrorエディタで数式入力（シンタックスハイライト、オートコンプリート対応）
- QUERY('queryName')関数で名前付きクエリの集計値（金額合計）を参照
- QUERY_COUNT('queryName')関数で名前付きクエリの取引件数を参照
- 条件付き色では特殊変数RESULTで計算結果を参照可能
- テーマカラーもtheme_変数名で参照可能
- クエリ設定のJSON形式でのインポート・エクスポート機能あり
- ライブモード（sliding-window）と静的モード（static）のタイムフレーム切り替えに対応

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models.ts | `loot-core/types/models` | `FormulaWidget`型の定義を確認 |
| 1-2 | QueryManager.tsx | `packages/desktop-client/src/components/formula/QueryManager.tsx` | `QueryConfig`型（conditions, conditionsOp, timeFrame） |

**読解のコツ**: QueryConfigの構造がクエリ定義の核となる。conditionsがフィルタ条件、timeFrameが期間設定を担う。

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

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

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

**主要処理フロー**:
1. **47-59行**: `Formula`関数 - useWidgetでウィジェットデータ取得
2. **65-441行**: `FormulaInner`関数 - メインのレンダリングロジック
3. **72-87行**: 状態の初期化（formula, fontSizeMode, staticFontSize, colorFormula）
4. **91-95行**: useFormulaExecutionフック呼び出し（メイン数式評価）
5. **110-115行**: useFormulaExecutionフック呼び出し（色数式評価）
6. **117-123行**: handleQueriesChange - クエリ変更ハンドラ

#### Step 3: 数式評価ロジックを理解する

数式の評価処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | useFormulaExecution.ts | `packages/desktop-client/src/hooks/useFormulaExecution.ts` | 数式評価フック |

**主要処理フロー**:
1. **30-193行**: useFormulaExecution - メインフック
2. **57-63行**: QUERY()とQUERY_COUNT()のパターンマッチ
3. **75-99行**: クエリデータの取得
4. **118-123行**: HyperFormulaインスタンス生成
5. **143-153行**: 数式実行と結果取得
6. **329-339行**: fetchQuerySum - クエリ集計値取得
7. **341-351行**: fetchQueryCount - クエリ件数取得

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

数式エディタとクエリ管理UIを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FormulaEditor.tsx | `packages/desktop-client/src/components/formula/FormulaEditor.tsx` | CodeMirrorベース数式エディタ |
| 4-2 | QueryManager.tsx | `packages/desktop-client/src/components/formula/QueryManager.tsx` | クエリ定義管理UI |

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

```
Formula (エントリーポイント)
    │
    ├─ useWidget (ウィジェットデータ取得)
    │
    └─ FormulaInner (メインコンポーネント)
           │
           ├─ useFormulaExecution (メイン数式評価)
           │      │
           │      ├─ QUERY() パターンマッチ
           │      │      └─ fetchQuerySum
           │      │             └─ buildFilteredTransactionsQuery
           │      │                    └─ send('make-filters-from-conditions')
           │      │
           │      ├─ QUERY_COUNT() パターンマッチ
           │      │      └─ fetchQueryCount
           │      │
           │      └─ HyperFormula.buildEmpty
           │             ├─ addSheet
           │             ├─ addNamedExpression
           │             ├─ setCellContents
           │             └─ getCellValue
           │
           ├─ useFormulaExecution (色数式評価)
           │
           ├─ FormulaResult (結果表示)
           │
           ├─ FormulaEditor (数式入力)
           │      └─ CodeMirror
           │
           ├─ Select (フォントサイズモード)
           │
           ├─ Input (静的フォントサイズ)
           │
           ├─ FormulaEditor (色数式入力)
           │
           └─ QueryManager (クエリ管理)
                  │
                  ├─ QueryItem (各クエリ)
                  │      ├─ useRuleConditionFilters
                  │      ├─ AppliedFilters
                  │      ├─ FilterButton
                  │      └─ Select (期間選択)
                  │
                  └─ handleAddQuery / handleRemoveQuery / handleUpdateQuery
```

### データフロー図

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

URLパラメータ ─────────▶ useWidget ─────────────────▶ ウィジェットメタデータ
                              │
                              ├──▶ meta.formula ────────▶ formula状態
                              ├──▶ meta.queries ────────▶ queriesRef
                              ├──▶ meta.fontSizeMode ───▶ fontSizeMode状態
                              ├──▶ meta.staticFontSize ─▶ staticFontSize状態
                              └──▶ meta.colorFormula ───▶ colorFormula状態

数式入力 ─────────────────▶ formula状態
                              │
                              ▼
                    useFormulaExecution
                              │
                              ├──▶ QUERY('name')パターン検出
                              │         │
                              │         ▼
                              │    fetchQuerySum
                              │         │
                              │         ▼
                              │    取引データ(DB) ──▶ 集計値
                              │
                              ├──▶ QUERY_COUNT('name')パターン検出
                              │         │
                              │         ▼
                              │    fetchQueryCount
                              │         │
                              │         ▼
                              │    取引データ(DB) ──▶ 件数
                              │
                              ├──▶ 数式内のQUERY/QUERY_COUNTを値に置換
                              │
                              ▼
                    HyperFormula評価
                              │
                              ▼
                        result ─────────────────────▶ FormulaResult表示

色数式 ───────────────────▶ colorFormula状態
                              │
                              ├──▶ RESULT変数 = 計算結果
                              │
                              ▼
                    useFormulaExecution (色評価)
                              │
                              ▼
                        colorResult ────────────────▶ 表示色

クエリ定義変更 ───────────▶ handleQueriesChange
                              │
                              ▼
                    queriesVersion++
                              │
                              ▼
                    数式再評価トリガー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Formula.tsx | `packages/desktop-client/src/components/reports/reports/Formula.tsx` | ソース | メインコンポーネント |
| useFormulaExecution.ts | `packages/desktop-client/src/hooks/useFormulaExecution.ts` | ソース | 数式評価フック |
| FormulaEditor.tsx | `packages/desktop-client/src/components/formula/FormulaEditor.tsx` | ソース | 数式エディタ |
| QueryManager.tsx | `packages/desktop-client/src/components/formula/QueryManager.tsx` | ソース | クエリ管理UI |
| FormulaResult.tsx | `packages/desktop-client/src/components/reports/FormulaResult.tsx` | ソース | 結果表示 |
| codeMirror-excelLanguage.ts | `packages/desktop-client/src/components/formula/codeMirror-excelLanguage.ts` | ソース | Excel言語拡張 |
| AppliedFilters.tsx | `packages/desktop-client/src/components/filters/AppliedFilters.tsx` | ソース | 適用済みフィルタ表示 |
| FilterButton.tsx | `packages/desktop-client/src/components/filters/FiltersMenu.tsx` | ソース | フィルタボタン |
