# 画面設計書 9-予算画面（デスクトップ）

## 概要

本ドキュメントは、Actual Budget アプリケーションのデスクトップ向け予算画面の設計仕様を記述したものである。

### 本画面の処理概要

予算画面は、Actual Budgetのメイン画面であり、月別の予算を表示・編集する画面である。封筒予算（Envelope Budget）と追跡予算（Tracking Budget）の2種類の予算タイプをサポートし、カテゴリごとの予算額設定、実績の確認、予算繰越の管理を行う。デスクトップ版では複数月の予算を横並びで表示可能。

**業務上の目的・背景**：予算管理はActual Budgetの中核機能であり、ユーザーはこの画面で「収入をどのカテゴリにいくら割り当てるか」を計画し、実際の支出と比較してお金の流れを把握する。封筒予算システムでは「使う前に予算を割り当てる」という考え方に基づき、支出をカテゴリごとに管理する。予算の過不足を視覚的に把握し、必要に応じて調整を行う。

**画面へのアクセス方法**：以下の方法でこの画面にアクセスする：
- 予算ファイルを開いた直後（口座が1件以上存在する場合のデフォルト）
- サイドバーの「Budget」メニューをクリック
- `/budget` URLへの直接アクセス

**主要な操作・処理内容**：
1. 月別予算の表示・ナビゲーション（前月/次月）
2. カテゴリ別予算額の設定・編集
3. カテゴリ/カテゴリグループの作成・編集・削除
4. 予算繰越（Carryover）の設定
5. カテゴリの非表示設定
6. ゴール設定・ノート追加
7. 予算テンプレートの適用

**画面遷移**：
- 遷移元：予算ファイル選択後、サイドバーメニュー、他の画面からの戻り
- 遷移先：カテゴリ詳細画面（カテゴリクリック時）、設定画面、他のメニュー画面

**権限による表示制御**：予算タイプ（封筒/追跡）によって表示コンポーネントと操作可能な項目が変わる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | 予算作成・編集 | 主機能 | 月次予算の作成・編集・削除、カテゴリ予算額設定 |
| 2 | 予算繰越（Carryover） | 補助機能 | 未使用予算の翌月繰越設定 |
| 15 | カテゴリ作成・編集・削除 | 補助機能 | 予算カテゴリの追加・編集・削除処理 |
| 16 | カテゴリグループ管理 | 補助機能 | カテゴリグループの作成・編集・削除処理 |
| 17 | カテゴリ非表示 | 補助機能 | 使用しないカテゴリの非表示設定 |
| 61 | ゴール設定 | 補助機能 | カテゴリごとの貯蓄目標設定 |
| 62 | ノート機能 | 補助機能 | カテゴリへのメモ追加機能 |

## 画面種別

一覧・編集画面（メイン画面）

## URL/ルーティング

`/budget`

## 入出力項目

| 項目名 | 項目ID | 入出力 | 必須 | データ型 | 最大長 | 備考 |
|--------|--------|--------|------|----------|--------|------|
| 月選択 | startMonth | 入力 | 必須 | string | - | "YYYY-MM"形式 |
| 予算額 | budgeted | 入力 | 任意 | number | - | カテゴリごとの予算額 |
| カテゴリ名 | categoryName | 入力 | 任意 | string | - | 新規/編集時 |
| グループ名 | groupName | 入力 | 任意 | string | - | 新規/編集時 |

## 表示項目

| 項目名 | 表示内容 | 備考 |
|--------|----------|------|
| 月ナビゲーション | 現在表示月と前月/次月ボタン | 複数月表示対応 |
| サマリー | To Budget / Total Budgeted / Total Spent 等 | 予算タイプにより異なる |
| カテゴリグループ | グループ名と集計値 | 折りたたみ可能 |
| カテゴリ行 | カテゴリ名、予算額、使用額、残高 | 編集可能 |
| 収入セクション | 収入カテゴリの一覧 | 下部に表示 |

## イベント仕様

### 1-月ナビゲーション（前月/次月ボタン押下）

1. `onMonthSelect` 関数を実行
2. 新しい月のデータをprewarm（キャッシュ準備）
3. `setStartMonthPref` で表示月を更新
4. スプレッドシートから新しい月のデータをロード

### 2-予算額編集（セルクリック→入力）

1. カテゴリ行の予算セルをクリックして編集モードに
2. 金額を入力
3. `onBudgetAction` で 'budget-amount' アクションを実行
4. スプレッドシートが更新され、サマリーに反映

### 3-カテゴリ作成

1. カテゴリグループメニューから「Add category」を選択
2. `pushModal` で新規カテゴリモーダルを表示
3. カテゴリ名を入力して確定
4. `createCategory` アクションを実行

### 4-カテゴリグループ作成

1. 予算画面メニューから「Add category group」を選択
2. `pushModal` で新規グループモーダルを表示
3. グループ名を入力して確定
4. `createCategoryGroup` アクションを実行

### 5-カテゴリ編集・削除

1. カテゴリ行を右クリックまたはメニューアイコンをクリック
2. コンテキストメニューから操作を選択
3. 編集: 名前変更モーダル表示
4. 削除: 確認モーダル表示（取引がある場合は移行先カテゴリ選択）

### 6-予算アクション（一括操作）

1. 月ヘッダーをクリックしてメニュー表示
2. 各種予算アクションを選択:
   - Copy last month's budget
   - Set budgets to zero
   - Set budgets to 3 month average
   - Apply budget templates

### 7-カテゴリ並べ替え

1. カテゴリ行をドラッグ
2. `onReorderCategory` でカテゴリ順序を更新
3. グループ間の移動も可能

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 予算額編集 | budget_data | INSERT/UPDATE | カテゴリ・月ごとの予算額を更新 |
| カテゴリ作成 | categories | INSERT | 新規カテゴリを追加 |
| カテゴリ編集 | categories | UPDATE | カテゴリ名・設定を更新 |
| カテゴリ削除 | categories, transactions | DELETE/UPDATE | カテゴリ削除、取引の移行 |
| グループ作成 | category_groups | INSERT | 新規グループを追加 |
| グループ削除 | category_groups, categories | DELETE/UPDATE | グループ削除、カテゴリの移行 |
| 並べ替え | categories, category_groups | UPDATE | sort_order を更新 |

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

#### budget_data

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | category_id | 対象カテゴリID | 予算対象カテゴリ |
| INSERT/UPDATE | month | 対象月（YYYY-MM） | 予算対象月 |
| INSERT/UPDATE | amount | 入力された予算額 | 予算額（整数、セント単位） |
| INSERT/UPDATE | carryover | 繰越フラグ | 封筒予算時 |

#### categories

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | 自動生成UUID | カテゴリID |
| INSERT | name | 入力されたカテゴリ名 | カテゴリ名 |
| INSERT | group_id | 所属グループID | カテゴリグループ |
| INSERT | is_income | true/false | 収入カテゴリか |
| UPDATE | hidden | true/false | 非表示フラグ |

## メッセージ仕様

| メッセージID | メッセージ内容 | 種別 | 表示条件 |
|-------------|---------------|------|----------|
| category-name-required | "Name is required." | エラー | カテゴリ名が空の場合 |
| delete-confirm | 削除確認ダイアログ | 確認 | カテゴリ/グループ削除時 |
| transfer-required | 移行先選択ダイアログ | 確認 | 取引があるカテゴリ削除時 |

## 例外処理

| 例外ケース | 処理内容 |
|------------|----------|
| データロード失敗 | ローディング表示を継続、エラー通知 |
| カテゴリ名重複 | エラーメッセージを表示 |
| 削除対象に取引あり | 移行先カテゴリの選択を要求 |

## 備考

- 予算タイプ（封筒/追跡）は設定画面で切り替え可能
- スプレッドシートベースでリアクティブにデータが更新される
- 複数月表示数は `maxMonths` グローバル設定で制御
- カテゴリの並び順はドラッグ&ドロップで変更可能

---

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

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

### 推奨読解順序

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

カテゴリと予算データの型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models/category.d.ts | `loot-core/types/models/category.d.ts` | CategoryEntity, CategoryGroupEntityの型定義 |
| 1-2 | bindings.ts | `packages/desktop-client/src/spreadsheet/bindings.ts` | スプレッドシートバインディング |

**読解のコツ**: CategoryEntity の `hidden`, `is_income` 等のフラグの意味を理解する

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

メインコンポーネントの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.tsx | `packages/desktop-client/src/components/budget/index.tsx` | Budget関数コンポーネントの実装 |

**主要処理フロー**:
1. **40-57行目**: Budget関数の初期化、状態管理（月、予算タイプ、表示設定）
2. **59-78行目**: init useEffect でカテゴリ取得と予算境界の取得
3. **89-119行目**: onMonthSelect で月変更時のprewarm処理
4. **133-135行目**: onBudgetAction で予算操作を実行
5. **156-208行目**: 予算タイプに応じたProvider とテーブルのレンダリング

#### Step 3: 予算テーブルを理解する

テーブルコンポーネントの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DynamicBudgetTable.tsx | `packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx` | AutoSizingBudgetTable |
| 3-2 | BudgetTable.tsx | `packages/desktop-client/src/components/budget/BudgetTable.tsx` | BudgetTable 本体 |

#### Step 4: 予算タイプ別コンポーネントを理解する

封筒予算と追跡予算の実装差分を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | EnvelopeBudgetComponents.tsx | `packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx` | 封筒予算コンポーネント |
| 4-2 | TrackingBudgetComponents.tsx | `packages/desktop-client/src/components/budget/tracking/TrackingBudgetComponents.tsx` | 追跡予算コンポーネント |

#### Step 5: カテゴリ操作を理解する

カテゴリ関連のReduxアクションを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | budgetSlice.ts | `packages/desktop-client/src/budget/budgetSlice.ts` | カテゴリCRUD、applyBudgetAction |

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

```
Budget (index.tsx)
    │
    ├─ useCategories() ─────────────────────▶ categoryGroups取得
    │
    ├─ useBudgetComponents() ───────────────▶ 予算タイプ別コンポーネント選択
    │
    ├─ [budgetType === 'envelope']
    │      └─ EnvelopeBudgetProvider
    │             └─ AutoSizingBudgetTable
    │                    ├─ BudgetSummary
    │                    ├─ BudgetHeader（月ナビゲーション）
    │                    └─ BudgetTable
    │                           ├─ ExpenseGroupComponent
    │                           │      └─ ExpenseCategoryComponent
    │                           └─ IncomeGroupComponent
    │                                  └─ IncomeCategoryComponent
    │
    └─ [budgetType === 'tracking']
           └─ TrackingBudgetProvider
                  └─ AutoSizingBudgetTable
                         └─ (同様の構造)

    │
    ├─ onMonthSelect(month)
    │      ├─ prewarmMonth()
    │      └─ setStartMonthPref()
    │
    └─ onBudgetAction(month, type, args)
           └─ dispatch(applyBudgetAction())
```

### データフロー図

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

予算額入力 ──────────────▶ BudgetTable ──────────────────▶ onBudgetAction
                              │
                              ▼
                    dispatch(applyBudgetAction)
                              │
                              ▼
                    send('budget/budget-action')
                              │
                              ▼
                     [サーバー: budget_data更新]
                              │
                              ▼
                    スプレッドシート再計算
                              │
                              ▼
                    useSheetValue() で自動更新
                              │
                              ▼
                    UI再レンダリング ─────────────────────▶ 画面表示更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.tsx | `packages/desktop-client/src/components/budget/index.tsx` | ソース | メインコンポーネント |
| DynamicBudgetTable.tsx | `packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx` | ソース | 自動サイズ調整テーブル |
| BudgetTable.tsx | `packages/desktop-client/src/components/budget/BudgetTable.tsx` | ソース | 予算テーブル本体 |
| EnvelopeBudgetComponents.tsx | `packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx` | ソース | 封筒予算コンポーネント |
| EnvelopeBudgetContext.tsx | `packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetContext.tsx` | ソース | 封筒予算コンテキスト |
| TrackingBudgetComponents.tsx | `packages/desktop-client/src/components/budget/tracking/TrackingBudgetComponents.tsx` | ソース | 追跡予算コンポーネント |
| TrackingBudgetContext.tsx | `packages/desktop-client/src/components/budget/tracking/TrackingBudgetContext.tsx` | ソース | 追跡予算コンテキスト |
| budgetSlice.ts | `packages/desktop-client/src/budget/budgetSlice.ts` | ソース | 予算Redux スライス |
| bindings.ts | `packages/desktop-client/src/spreadsheet/bindings.ts` | ソース | スプレッドシートバインディング |
| util.ts | `packages/desktop-client/src/components/budget/util.ts` | ソース | prewarmMonth等ユーティリティ |
