MAS-025: 予算vs実績差異分析(41_trn_budget ベース)
概要
| 項目 | 内容 |
|---|---|
| 案件ID | MAS-025 |
| カテゴリ | FP&A・レポーティング |
| Phase | P1 |
| 優先度 | ★★★ |
| 所要時間 | 3-4時間 |
| 実装ステータス | 📝 仕様書段階・実装未着手 (2026-04-28 監査時点) |
| 対象ファイル | 200_data/202_repository.js(BudgetRepository 追加)100_config/101_sys_config.js(DDL登録: PL_BUD_VAR)templates/operations_sidebar.html(操作パネルにボタン追加)600_report/610_datamart_budget_variance.js(新規作成) |
目的
41_trn_budget の予算データと 42_trn_journal の実績データを科目・月次で突合し、差異額・差異率を新規タブ 66_pl_budget_variance に出力するレポートビルダーを新規実装する。
MAS-001(65_pl_variance)は「直近の確定実績 vs 当初計画(dmIngestPlanData_ で生成される計画値)」を比較する着地見込み・承認漏れ検出ベースの差異分析であり、予算策定→PDCAサイクルの主要ツールである「正規予算(41_trn_budget の入力データ)vs 実績」の比較は未実装であった。本案件はこのギャップを埋めるもので、独立した出力タブ 66_pl_budget_variance に予算/実績/差異額/差異率の 4 行 × 全科目を出力する。
BudgetRepository が未実装であるため、200_data/202_repository.js への追加も本案件のスコープに含める。
現在のコード
| ファイル/シート | 現状 |
|---|---|
200_data/202_repository.js | BudgetRepository が未定義(末尾は L351、AccountRepository.resetCache() 直後)。OrderRepository / InvoiceRepository / BankTxRepository / JournalRepository / AccountRepository のみ実装済み |
100_config/101_sys_config.js | 41_trn_budget のシステムキーは TRN_BUDG(L604, L657)として登録済。ただし 66_pl_budget_variance の DDL 登録(L613 PL_VAR 隣接位置)は未登録 |
templates/operations_sidebar.html | 「📊 マート更新」セクション(L62-68)に予実差異分析ボタン未配置。本プロジェクトはサイドバー HTML を UI 起点とし、SpreadsheetApp.getUi().createMenu() ベースの GAS 標準メニューは使用していない |
66_pl_budget_variance シート | 未作成 |
600_report/ 配下 | 既存最大番号は 609_datamart_kpi.js(次の新規ファイルは 610 を採番) |
修正方針
3 Step 構成で実装する。
Step 1 — BudgetRepository 追加(200_data/202_repository.js 末尾、L351 の直後)
OrderRepository(L107-146)と同一パターンで実装する。
_getSheet():Utils.getSheetByKey('TRN_BUDG', '41_trn_budget')(システムキー登録済を活用)findAll():readSheetAsDtos_(BudgetRepository._getSheet())を呼び、{ headers: string[], dtos: BudgetDTO[] }を返すsave()/append()は本案件では実装不要(読み取り専用)
有効フラグ のフィルタは Repository 層では行わず、呼び出し側でスキップする方針(既存 AccountRepository.findAsMap() L323-341 と同パターン)。
Step 2 — レポートビルダー新規作成(600_report/610_datamart_budget_variance.js)
- 関数名:
buildBudgetVarianceReport()(公開関数) - 既存
600_report/配下のレポートビルダーはLockServiceを使用していない(609_datamart_kpi.js等で確認済)。本案件でもLockServiceは導入せず、既存パターンに合わせてtry { ... } catch (e) { Utils.logError(FUNC, e); throw e; }のみで実装する - 出力シートのクリア手段は
sheet.clear()(書式・条件付き書式を含めて全消去、609_datamart_kpi.jsL28 と同パターン) - 処理フロー:
- 予算データ取得 —
BudgetRepository.findAll().dtos→ 有効フラグフィルタ(flag === false || String(flag).toUpperCase() === 'FALSE'で除外)→予算バージョン === '最新予算(V1)'でフィルタ - 予算データ 0 件ガード —
getWebSpreadsheet_().toast('予算データが未登録です(バージョン=最新予算(V1)、有効フラグ=TRUE 該当なし)', 'F-25', 5)を表示してreturn - 対象期間の確定 — フィルタ後予算 DTO から
Utils.parseDateToYm(dto['対象年月'])の最小・最大値を求め、{ minYm, maxYm, count }の集計サマリを作成 - 実行前確認ダイアログ —
SpreadsheetApp.getUi().alert('F-25 予算vs実績差異分析', '予算 ' + count + ' 件(' + minYm + ' 〜 ' + maxYm + ')を集計します。よろしいですか?', SpreadsheetApp.getUi().ButtonSet.OK_CANCEL)を表示し、OK以外が返ったらreturn(Webアプリ経由でgetUi()が取れない場合はtry/catchでスキップして続行) - 実績データ取得 —
JournalRepository.findAll().dtosをそのまま使用(JournalEntryDTOには有効フラグが定義されていないことを Phase 1 1-3 で確認済。TRN_JOURの DDL ヘッダー定義 L656 にも有効フラグは含まれない。フィルタ不要) - 科目マスタ取得 —
AccountRepository.findAsMap()(既存キャッシュをそのまま使用、resetCache()は呼ばない) - 集計 —
Utils.parseDateToYm()でキー生成し、科目名×YYYY-MM の 2 段階 Map 構造でbudgetとactualを加算するピボット集計。予算側は予算金額、実績側は税抜金額_実績を使用。Utils.parseDateToYmが空文字列を返した行(パース不能)は集計対象外 - 出力シート取得・クリア —
getWebSpreadsheet_().getSheetByName('66_pl_budget_variance')→nullならss.insertSheet('66_pl_budget_variance')→sheet.clear()(書式含めて全消去) - ヘッダー行書き込み — A=大分類、B=科目名、C=指標、D〜O=4月〜3月(会計年度 12 ヶ月、列ヘッダー値は
YYYY-MM文字列)、P=年度合計 - データ行書き込み — 科目ごとに「予算」「実績」「差異額」「差異率」の 4 行を書き込み
- 予算データ取得 —
- 差異計算:
- 差異額 = 実績金額 − 予算金額
- 差異率: 予算金額 ≠ 0 → 差異額 / 予算金額 / 予算金額 = 0 かつ 実績金額 = 0 → 0(数値)/ それ以外 →
'-'(文字列)
- 対象年度の決定:
buildKpiDashboard(609_datamart_kpi.js)が「P/L 売上高行の末尾非空セル」から境界月を逆算するのに対し、本案件は 予算データそのものから対象年月の最小〜最大を取り、該当年度を全カバーする 12 ヶ月 を対象とする。明示的な会計年度設定は行わず、予算の登録範囲=集計範囲とする(年度跨ぎがある場合は人間検討事項参照)
Step 3 — DDL 登録 + サイドバー UI 追加
3-1. DDL 登録(100_config/101_sys_config.js)
setupAllSchemas 内、PL_VAR(L613)の直後に以下を追加:
if (!existKeys.includes('PL_BUD_VAR')) confSheet.appendRow(['PL_BUD_VAR', '', '66_pl_budget_variance', 'P/L予実差異分析(予算ベース)']);
schemas 辞書には登録しない(書式は buildBudgetVarianceReport 側で sheet.clear() 後に都度設定するため、DDL 管理外として扱う)。
3-2. サイドバー UI 追加(templates/operations_sidebar.html)
「📊 マート更新」セクション(L62-68)の buildKpiDashboard ボタン直下に以下を追加:
<button class="btn" onclick="run('buildBudgetVarianceReport', this)">📊 予実差異分析(予算ベース)を更新</button>
SpreadsheetApp.getUi().createMenu() ベースの GAS 標準メニューは本プロジェクトでは使用していないため、addItem 追加ではなくサイドバー HTML への button 要素追加とする。
影響範囲
| ファイル/シート | 変更種別 | 影響 |
|---|---|---|
200_data/202_repository.js | 追加(末尾、新規 BudgetRepository 名前空間) | 既存 Repository には変更なし。新規モジュールの追加のみ |
100_config/101_sys_config.js | 1 行追加(PL_BUD_VAR の appendRow のみ。schemas 辞書は変更しない) | setupAllSchemas 実行時に 01_sys_config に 1 行追加。既存タブの DDL 適用には影響なし |
templates/operations_sidebar.html | 1 行追加(button 要素) | 既存ボタンへの影響なし |
600_report/610_datamart_budget_variance.js | 新規作成 | 他レポートビルダーへの影響なし |
66_pl_budget_variance シート | 初回実行時に自動作成 | setupAllSchemas で物理シートは作成されない。buildBudgetVarianceReport 内の ss.insertSheet で初回作成 |
注意事項
- 有効フラグの判定パターン統一 —
flag === false || String(flag).toUpperCase() === 'FALSE'で除外する(AccountRepository.findAsMap()L329-330、Utils.normalizePartnerName()L357 と同じパターン)。BudgetDTO は有効フラグを先頭フィールド(003_contracts.jsL134)として持つので、DTO 経由で安全に取得可能。 - JournalEntryDTO に
有効フラグは存在しない —003_contracts.jsのJournalEntryDTO定義(L97-129)およびTRN_JOURの DDL ヘッダー(101_sys_config.jsL656)の両方に有効フラグが含まれないことを Phase 1 で確認済。実績データのフィルタは行わない。将来有効フラグ列が追加された場合は本仕様の更新が必要。 - 予算バージョンの複数共存リスク —
Constants.SHEET_DEFAULTSの41_trn_budgetエントリ(002_constants.jsL74)でデフォルト値'最新予算(V1)'が定義されているが、ユーザーが手動で別バージョン(例:'当初予算'、'修正予算')を入力する可能性がある。本仕様ではフィルタ対象を'最新予算(V1)'の完全一致のみとし、複数バージョン対応は将来案件(MAS-002 予算スナップショット/バージョン管理)に委ねる。 - 収支区分の符号扱いの統一 —
BudgetDTO.収支区分('収入'/'支出')とJournalEntryDTO.収支区分(同上)はいずれも文字列ラベルであり、金額は両者とも 正値で格納される(既存の P/L マートも金額の絶対値で比較)。差異額計算(実績 − 予算)は単純な数値減算でよい。「収益科目で実績 > 予算 = 良好」「費用科目で実績 < 予算 = 良好」の業務的な解釈は、エッジケースセクションの差異評価方向性の表で示す。 Utils.parseDateToYm()の入力形式 —BudgetDTO.対象年月は'YYYY-MM'文字列、JournalEntryDTO.発生日(P/L計上日)はDate型または文字列。Utils.parseDateToYm()(004_utils.jsL92-99)は両方に対応済(Date /'YYYY-MM'/'YYYY/MM'/'YYYY年MM月')。空値が来た場合は''を返す → 空キーは集計対象外として扱う必要あり。- 科目マスタ未登録時の扱い — 予算 / 実績の
科目名が11_mst_accountに未登録の場合、本仕様では「未分類」グループに集約せず、集計対象から除外し warning ログを出力(Utils.logInfo('buildBudgetVarianceReport', '科目マスタ未登録: ' + acc))。既存dmProcessAllEvents_(602_datamart_main.jsL49)は throw する設計だが、レポート系では実行継続を優先する。 - DDL 管理外シートの追記 —
66_pl_budget_varianceは DDL のschemas辞書には登録しないため、CLAUDE.mdの「DDL (setupAllSchemas) で管理されないタブ」一覧への追記が必要。本案件のスコープに含める。 SpreadsheetApp.getUi()がない実行コンテキスト — トリガーや Web アプリ経由で実行された場合、getUi()は例外を投げる。確認ダイアログ表示はtry { ui = SpreadsheetApp.getUi(); ... } catch(e) { /* スキップして続行 */ }で囲む(setupAllSchemasL580 と同パターン)。
エッジケース
| 条件 | 表示値 | 理由 |
|---|---|---|
| 予算金額=0、実績金額>0 | "-"(文字列) | 差異率が無限大(ゼロ除算)のため計算不能 |
| 予算金額=0、実績金額=0 | 0(数値、フォーマット適用後 0.0%) | 計画通り=差異なし、計算可能 |
| 予算金額=0、実績金額<0 | "-"(文字列) | 予算外の費用発生 / マイナス計上、ゼロ除算で計算不可 |
| 予算金額>0、実績金額=0 | -1(数値、フォーマット適用後 △ 100.0%) | 予算に対して実績ゼロ、通常計算で差異率 -100% |
| 予算金額<0、実績金額>0 | 通常計算(差異額 = 実績 − 予算 / 差異率 = 差異額 / 予算金額) | 戻入予算など特殊パターン。符号反転に注意 |
| 予算データが 0 件(バージョンフィルタ後) | 処理中断・トースト表示 | 未登録データでの実行防止(誤操作ガード) |
| 予算 + 実績ともに 0 件の科目 | 該当科目を出力スキップ | 全科目羅列を避け、出力レポートをコンパクトに保つ |
| 科目が予算にのみ存在 | 実績=0 として差異計算(差異率=-100.0%) | 和集合アプローチ:予算未消化の可視化 |
| 科目が実績にのみ存在 | 予算=0 として差異計算(差異率="-") | 和集合アプローチ:予算外支出の可視化 |
| 科目マスタに未登録の科目名 | 集計対象から除外 + ログ警告 | レポート系は実行継続を優先(注意事項 6 参照) |
対象年月 が空または不正な値 | 該当 DTO を集計対象外 | Utils.parseDateToYm() が "" を返した場合のガード |
| 集計対象月が会計年度範囲を超える | 範囲外月は出力しない(最小〜最大の枠内のみ表示) | 動的算出方式で予算データに合わせる(人間検討事項参照) |
差異評価の方向性(業務解釈ガイド)
| 科目区分 | 良好な状態 | 警戒すべき状態 | レポート上の推奨表示 |
|---|---|---|---|
| 収益(売上高、その他収益等) | 差異額 > 0(実績 > 予算) | 差異額 < 0(実績 < 予算 = 未達) | 差異額 ≥ 0 を 緑系、< 0 を 赤系で色分け(将来案件) |
| 費用・原価(売上原価、販管費等) | 差異額 ≤ 0(実績 ≤ 予算 = 節約) | 差異額 > 0(実績 > 予算 = 超過) | 差異額 ≤ 0 を 緑系、> 0 を 赤系で色分け(将来案件) |
| B/S 系 | 本案件のスコープ外 | — | — |
本仕様では数値・差異額・差異率の出力までを範囲とし、色分け(条件付き書式)は将来案件として「人間が検討すべき事項」に記載する。
実データ検証
実装前および実装後に以下を MCP(または手動シート確認)で検証する:
41_trn_budgetの状態確認有効フラグ=TRUE のレコード件数(バージョン別カウント)。フィルタ後 0 件にならないことを事前確認予算バージョンの実際の格納値一覧。'最新予算(V1)'との完全一致確認(前後スペースなし、全角半角混在なし)対象年月の最小・最大値、および年度跨ぎがある場合の月分布予算金額の絶対値合計(予算規模の把握)
11_mst_accountと41_trn_budgetの科目名突合41_trn_budget.科目名が11_mst_account.科目名と完全一致するか(全角半角・前後スペースの違いも確認)- 不一致がある場合、注意事項 6 に従い該当行は集計対象外として除外(ログ警告で可視化)
42_trn_journalの確認JournalEntryDTO定義に有効フラグ列が含まれていないことを再確認(003_contracts.jsL97-129、およびTRN_JOURヘッダー定義101_sys_config.jsL656)- 集計対象期間内の
税抜金額_実績の科目別合計(実績規模の把握) 仕訳ステータス=仕訳振替のレコードを除外する必要があるかの判断(CLAUDE.md「仕訳振替の判定は=== "仕訳振替"の完全一致」ルール参照)。本仕様では当面除外せず、将来要件に応じて対応
出力後の検算
- 全科目の差異額の合算が、 全科目の実績合計 − 全科目の予算合計 と一致すること(集計ロジックのサンクチェック)
- 単一科目の月別差異額の合計が、その科目の年度合計差異額(P 列)と一致すること
関連ドキュメント
| ドキュメント | 関連箇所 |
|---|---|
docs/dev/dev_mas-001_variance_analysis.md | 既存の予実差異分析(着地見込みベース)。レポートビルダーの基本構成・実装パターン参考 |
docs/dev/dev_mas-003_kpi_dashboard.md | KPIダッシュボードのレポートビルダー実装パターン(609_datamart_kpi.js の sheet.clear() + try/catch パターン参考) |
000_infra/003_contracts.js | BudgetDTO / JournalEntryDTO の型定義 |
200_data/202_repository.js | BudgetRepository 追加先・既存 Repository パターン(OrderRepository がテンプレート) |
100_config/101_sys_config.js | setupAllSchemas の 01_sys_config システムキー登録セクション(PL_VAR 隣接) |
templates/operations_sidebar.html | 「📊 マート更新」セクションへのボタン追加 |
CLAUDE.md | DDL で管理されないタブ一覧への追記、コーディング規約(有効フラグ判定パターン) |
人間が検討すべき事項
docs/_internal/TODO_future.md の MAS-025 行に記載された「人間が検討すべき事項」:
41_trn_budgetのデータ整備状況 — 本案件の前提として、ユーザー(経営層・経理担当)が41_trn_budgetシートに予算を入力済みであることが必要。実装後に「データ未登録のため使えない」とならないよう、運用開始前に予算入力フェーズの完了を確認すること。
追加で検討すべき事項(実装過程で判明したもの):
- 集計対象年度の指定方法 — 本仕様は「予算データの
対象年月最小〜最大」で動的に決定する設計。代替案として a)03_sys_paramsにBUDGET_VARIANCE_FISCAL_YEARを追加して固定 / b) 実行時ダイアログで「対象年度」をプルダウン選択 / c) 暦年度・会計年度の選択を可能にする、なども検討余地あり。 予算バージョンフィルタ仕様の拡張 — 複数バージョン共存(当初予算 / 修正予算 / 最終予算 など)が必要になった場合、 a) 全バージョン横並び比較レポート / b) 実行時にバージョン選択ダイアログ / c)03_sys_paramsで参照バージョンを明示指定、のいずれを採用するか。MAS-002(予算スナップショット/バージョン管理)と統合検討すべき。66_pl_budget_varianceシートの DDL 管理化 — 現在は DDL 管理外(schemas辞書未登録)。書式パターンが安定したら DDLschemas辞書に登録してsetupAllSchemasで初期化される運用に移行することを推奨。本仕様完了後、運用 1〜2 ヶ月の安定確認をもって判断。- 差異セルの条件付き書式(色分け) — 「差異評価の方向性」テーブルに記載した収益/費用ごとの良/悪の色分けを将来案件として実装する余地あり(MAS-001 と同様に
03_sys_paramsのCFG_VARIANCE_*閾値を流用可能)。 - 科目マスタ未登録の警告通知 — 本仕様ではログ出力のみだが、件数が多い場合は実行後トースト通知での集約サマリ表示を追加検討。
- PJ別 / 組織別の予実差異 —
BudgetDTOにはPJ名/組織名フィールドがあるが、本仕様では集計次元に含めない(科目×月のみ)。需要があれば66b_pl_budget_variance_by_pj等の派生レポートを後続案件として検討。
実装プロンプト(Claude Code 用)
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 MAS-025「予算vs実績差異分析(41_trn_budget ベース)」を実装してください。
## 実行前タスク
- `200_data/202_repository.js` を Read し、`OrderRepository` の `_getSheet` / `findAll` の実装(L107-146)を確認する(BudgetRepository 作成のテンプレートとして使用)。`readSheetAsDtos_`(L19)の引数・戻り値も確認
- `100_config/101_sys_config.js` を Read し、`41_trn_budget` のシステムキー `TRN_BUDG`(L604)と、`PL_VAR` 登録行(L613)の正確な位置を確認する
- `templates/operations_sidebar.html` を Read し、「📊 マート更新」セクション(L62-68)の `buildKpiDashboard` ボタンの位置を確認する
- `000_infra/003_contracts.js` を Read し、`BudgetDTO`(L131-149)の全フィールドと、`JournalEntryDTO`(L97-129)に `有効フラグ` 列が含まれないことを確認する
- `600_report/609_datamart_kpi.js` を Read し、`sheet.clear()` パターン(L28)と `try/catch` での `Utils.logError` 呼び出しパターン(L49-52)を確認する
- `000_infra/004_utils.js` を Read し、`Utils.parseDateToYm()`(L92-99)の入力形式と戻り値仕様、`getWebSpreadsheet_()`(L9-15)の挙動を確認する
## 修正対象ファイル
1. `200_data/202_repository.js` — `BudgetRepository` を末尾(L351 の直後)に追加
2. `600_report/610_datamart_budget_variance.js` — 新規作成(番号は既存最大 609 +1 で `610` 確定)
3. `100_config/101_sys_config.js` — `setupAllSchemas` の `PL_VAR` 直後(L613 の次)に `PL_BUD_VAR` の `appendRow` 1 行を追加
4. `templates/operations_sidebar.html` — 「📊 マート更新」セクションの `buildKpiDashboard` ボタン直下に新規ボタン 1 行を追加
5. `CLAUDE.md` — 「DDL (setupAllSchemas) で管理されないタブ」一覧に `66_pl_budget_variance` を追記
## 実装内容
### 1. BudgetRepository 追加(`202_repository.js` 末尾)
`OrderRepository`(L107-146)と同一構造で実装すること:
- `_getSheet()`: `Utils.getSheetByKey('TRN_BUDG', '41_trn_budget')`(システムキー登録済を活用)
- `findAll()` のみ実装(戻り値: `{ headers: string[], dtos: BudgetDTO[] }`)
- `save()` / `append()` は実装しない(読み取り専用 Repository)
- 有効フラグフィルタは Repository 層では行わない(呼び出し側で実施)
### 2. レポートビルダー新規作成(`600_report/610_datamart_budget_variance.js`)
関数名: `buildBudgetVarianceReport()`
処理フロー(既存 `609_datamart_kpi.js` のパターンに倣うこと):
1. `var FUNC = 'buildBudgetVarianceReport'; try { ... } catch (e) { Utils.logError(FUNC, e); throw e; }` でラップ。`LockService` は使用しない(既存レポートビルダーとの整合)
2. 予算データ取得: `BudgetRepository.findAll().dtos` → 有効フラグフィルタ(`flag === false || String(flag).toUpperCase() === 'FALSE'` で除外)→ `予算バージョン === '最新予算(V1)'` でフィルタ
3. 件数 0 ガード: `getWebSpreadsheet_().toast('予算データが未登録です(バージョン=最新予算(V1)、有効フラグ=TRUE 該当なし)', 'F-25', 5)` → return
4. 対象期間決定: フィルタ後 DTO の `Utils.parseDateToYm(dto['対象年月'])` から最小・最大を計算(空文字列は除外)
5. 実行前確認ダイアログ: `try { var ui = SpreadsheetApp.getUi(); var resp = ui.alert('F-25 予算vs実績差異分析', msg, ui.ButtonSet.OK_CANCEL); if (resp !== ui.Button.OK) return; } catch(e) {}`(Webアプリ経由は try/catch でスキップ)
6. 実績データ取得: `JournalRepository.findAll().dtos` をそのまま使用(`有効フラグ` 列なしのためフィルタ不要)
7. 科目マスタ取得: `AccountRepository.findAsMap()`(既存キャッシュ流用、`resetCache()` 呼ばない)
8. 集計: 科目名 × `Utils.parseDateToYm(...)` の 2 段階 Map で `budget` / `actual` を加算。予算側は `予算金額`、実績側は `税抜金額_実績`。`acctMap[acc]` が undefined の科目はスキップ + `Utils.logInfo(FUNC, '科目マスタ未登録: ' + acc)` でログ警告
9. 出力シート取得: `ss.getSheetByName('66_pl_budget_variance')` → null なら `ss.insertSheet('66_pl_budget_variance')` → `sheet.clear()`
10. ヘッダー行書き込み: A=大分類、B=科目名、C=指標、D〜O=4月〜3月(YYYY-MM 文字列、対象期間に基づき動的算出)、P=年度合計
11. データ行書き込み: 科目ごとに「予算」「実績」「差異額」「差異率」の 4 行(科目名は B 列に予算行のみ表示、他は空欄でグルーピング表現)
12. 数値フォーマット: 予算/実績/差異額は `Constants.NUMBER_FORMATS.CURRENCY`、差異率は `Constants.NUMBER_FORMATS.PERCENT`、文字列 `"-"` のセルはフォーマット適用後も `"-"` 表示
13. 列幅調整: A=120, B=240, C=80, D-O=90, P=100
14. 完了通知: `Utils.toastResult(FUNC, sheetName + ' 再描画完了 (科目=' + accCount + ', 期間=' + minYm + '〜' + maxYm + ')')`
差異計算式:
- 差異額 = 実績金額 − 予算金額
- 差異率: 予算金額 ≠ 0 → 差異額 / 予算金額(数値)/ 予算=0 かつ 実績=0 → 0 / それ以外 → 文字列 `'-'`
### 3. DDL 登録(`101_sys_config.js`)
`setupAllSchemas` 内、`PL_VAR` の `appendRow`(L613)の直後の行に追加:
```js
if (!existKeys.includes('PL_BUD_VAR')) confSheet.appendRow(['PL_BUD_VAR', '', '66_pl_budget_variance', 'P/L予実差異分析(予算ベース)']);
```
`schemas` 辞書には登録しない(DDL 管理外シートとして扱う)。
### 4. サイドバー UI 追加(`templates/operations_sidebar.html`)
「📊 マート更新」セクション(L62-68)の `buildKpiDashboard` ボタン直下に追加:
```html
<button class="btn" onclick="run('buildBudgetVarianceReport', this)">📊 予実差異分析(予算ベース)を更新</button>
```
### 5. CLAUDE.md 追記
「DDL (setupAllSchemas) で管理されないタブ」一覧に `66_pl_budget_variance` を追記する(既存リスト末尾、`78_pj_pl` の後ろ等の適切な位置)。
## 制約
- `202_repository.js` の既存 Repository(OrderRepository / InvoiceRepository / BankTxRepository / JournalRepository / AccountRepository)は変更しない
- 有効フラグ判定は必ず `flag === false || String(flag).toUpperCase() === 'FALSE'` パターンを使用すること(`AccountRepository.findAsMap()` L329-330 と同パターン)
- 列参照はヘッダー名ベース(列番号ハードコード禁止)
- `AccountRepository.resetCache()` は呼ばない(既存動作への影響回避)
- `LockService` は使用しない(既存 600_report/ 配下レポートビルダーとの整合)
- `SpreadsheetApp.getUi()` の例外(Webアプリ経由)は `try/catch` で握りつぶしてダイアログをスキップする
- 出力シートが既存の場合は `sheet.clear()` で書式・条件付き書式まで全消去してから再描画(冪等性)
## エッジケース
| 条件 | 表示値 | 理由 |
|------|--------|------|
| 予算金額=0、実績金額>0 | `"-"` | 差異率が無限大のため表示不可 |
| 予算金額=0、実績金額=0 | `0`(フォーマット適用後 `0.0%`) | 計画通り |
| 予算金額=0、実績金額<0 | `"-"` | 予算外費用、計算不可 |
| 予算データが 0 件(バージョンフィルタ後) | 処理中断・トースト | 未登録ガード |
| 科目が一方のみに存在 | 不在側=0 として計算 | 和集合アプローチ |
| 科目マスタ未登録 | 集計対象外 + ログ警告 | レポート系は実行継続優先 |
| `対象年月` パース失敗 | 該当 DTO を集計対象外 | `Utils.parseDateToYm()` `""` ガード |
## 動作確認
1. `npm run push:dev` で開発用 GAS にデプロイ
2. GAS エディタで `setupAllSchemas` を実行し、`01_sys_config` に `PL_BUD_VAR` 行が追加されたことを確認
3. 操作パネルを開き、「📊 マート更新」セクションに「📊 予実差異分析(予算ベース)を更新」ボタンが表示されることを確認
4. ボタンクリック → 確認ダイアログが「件数」「期間」付きで表示されること
5. OK 押下 → `66_pl_budget_variance` シートが生成され、科目ごとに予算/実績/差異額/差異率 の 4 行が出力されること
6. `予算バージョン` を一時的に変更して 0 件状態を作り、トースト通知で中断されることを確認
7. 2 回連続実行してシートが重複せず上書きされること(冪等性確認)
8. Webアプリ経由(`getUi()` が取れない経路)で実行しても例外で止まらず、ダイアログをスキップして処理が完走することを確認(任意)
### 拡張思考の使用状況
| フェーズ | 拡張思考 | 備考 |
|---------|---------|------|
| BudgetRepository 追加 | なし | OrderRepository パターン踏襲のみ |
| レポートビルダー実装 | あり | ピボット集計ロジック・差異率エッジケース処理の設計 |
| DDL 登録 + サイドバー追加 | なし | 挿入位置特定後は定型作業 |
| CLAUDE.md 追記 | なし | リスト末尾追加のみ |
推奨実行モデル
| 工程 | 推奨モデル | 理由 |
|---|---|---|
| 仕様書作成(本ドキュメント) | Claude Opus 4.7 | レポート設計・既存パターン突合・人間検討事項抽出に高い推論力が必要 |
| Step 1 BudgetRepository 追加 | Claude Haiku 4.5 | 既存 OrderRepository パターンの横展開、判断不要 |
| Step 2 レポートビルダー新規作成 | Claude Sonnet 4.6 | ピボット集計・ダイアログ制御・差異率エッジケース処理の設計判断が必要 |
| Step 3-1 DDL 登録 | Claude Haiku 4.5 | 1 行追加、挿入位置特定後は定型 |
| Step 3-2 サイドバー UI 追加 | Claude Haiku 4.5 | button 1 行追加、定型作業 |
| Step 4 CLAUDE.md 追記 | Claude Haiku 4.5 | リスト末尾追加のみ |
変更履歴
| 日付 | 変更内容 |
|---|---|
| 2026-04-19 | 初版作成 |
仕様書作成プロンプト
展開して表示
【タイムアウト回避・実行原則(v1.7・必ず遵守すること)】
- 拡張思考の使い分け: Phase 1(設計)ではフル活用し、ファイル名形式・エッジケース一覧・Step 分割粒度・固有名詞(関数名/シート名/列名/行番号)を完全に確定させる。Phase 2(清書)では各 Step 内で最小限に抑え、Phase 1 確定済みの内容の書き下しに徹する。出力途中で再考しない。
- テキスト報告の禁止: 「〜を作成します」等の text のみで tool_use なしに turn を終了しない。説明は 1 文以内。直ちに tool を呼ぶ。
- 4-5 分割の Write/Edit 実行: 2-1(骨格 ~20行) / 2-2(概要〜注意事項 ~300行) / 2-3a(エッジケース〜人間検討事項 ~200行) / 2-3b(実装プロンプト〜変更履歴 ~250行) / 2-4(
<details>プロンプト全文記録) に分割。1 回の Write/Edit は約 300 行以内。 - 各 Step で何を書くかを具体指示: Phase 1 で確定済みの内容の書き下しに徹し、Phase 2 実行時に設計判断を持ち込まない。
======================================================================
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者兼仕様書ライターです。
案件 MAS-025「予算vs実績差異分析(41_trn_budget ベース)」の開発仕様書を作成してください。
開発仕様書を新規作成した場合は、docs/_config.json の nav 配列の適切なセクションにも必ず追記してください。
Phase 1: 実行前タスク(テキスト報告禁止。各項目を即座にツール実行)
「どう書くか」の判断は必ず Read で裏取りすること(Grep は発見まで)。 以下をすべて調査完了させてから Phase 2 に進む。
1-1: 案件定義の取得
docs/_internal/TODO_future.md で MAS-025 の行を検索し、案件名・概要・期待される効果・人間が検討すべき事項を取得する。
1-2: 類似仕様書の読み込み
docs/dev/dev_mas-001_variance_analysis.md を読み込み、レポートビルダー仕様書のセクション構成・実装プロンプト形式・推奨実行モデルテーブルの書き方を把握する。
1-3: DTO の全フィールド確認
000_infra/003_contracts.js を Read し、以下の型定義を確認する:
BudgetDTO(41_trn_budget):有効フラグ/予算バージョン/対象年月/収支区分/科目名/予算金額の型と値パターン。有効フラグが先頭フィールドであることを確認。JournalEntryDTO(42_trn_journal):有効フラグが定義に含まれるかどうかを確認する(含まれない場合、実績データのフィルタ方針を変更する必要があるため必ず確認)。発生日(P/L計上日)/収支区分/科目名/税抜金額_実績の型も確認。
1-4: 定数の確認
000_infra/002_constants.js を Read し、SHEET_DEFAULTS の pattern: '41_trn_budget' エントリで 予算バージョン のデフォルト値('最新予算(V1)')を確認する。
1-5: Repository 層の確認
200_data/202_repository.js を Read し、以下を確認する:
OrderRepositoryの全構造(_getSheet/findAllの実装)をBudgetRepository新規作成のテンプレートとして把握する。Utils.getSheetByKeyに渡す第 1 引数(システムキー)の形式(例:'WRK_ORDR')を確認し、41_trn_budgetに対応するキーの命名規則を推定する。JournalRepository.findAll()とAccountRepository.findAsMap()の戻り値型を確認する。BudgetRepositoryが存在しないことを確認する。readSheetAsDtos_/appendDtosToSheet_等の内部ヘルパー関数の所在を確認する。
1-6: システム設定・メニュー構造の確認
100_config/101_sys_config.js を Read し、以下を確認する:
01_sys_configシートに41_trn_budgetのシステムキーが登録されているか(またはUtils.getSheetByKeyのフォールバック名のみで対応するかを判断する)。- 既存の「📊 レポート」メニュー項目の一覧と、新メニュー項目を追加する正確な行番号を特定する。
66_pl_budget_varianceシートが DDL(setupAllSchemas)で管理されているかどうかを確認する。
1-7: 既存レポートビルダーのパターン確認
600_report/ 配下のファイル一覧を確認し、既存の最大ファイル番号を特定する(新規ファイルの番号決定のため)。その上で、最も実装が近いと思われるレポートビルダーを 1 件 Read し、以下のパターンを把握する:
LockService.getScriptLock()+try...finallyによる多重実行防止の実装箇所(行番号まで)。- 出力シートのクリア手段(
clearContents()/clear()/clearContent()のどれを使っているか)。 - データ取得 → 集計 → シート書き込みの全体フロー。
1-8: ユーティリティ確認
000_infra/004_utils.js を Read し、Utils.parseDateToYm() の引数型(Date / 文字列 "YYYY-MM" 等)と戻り値形式("YYYY-MM")を確認する。BudgetDTO.対象年月 が文字列 "YYYY-MM" 形式で格納されている場合の挙動も確認する。
Phase 2: 仕様書の分割作成
出力先: docs/dev/dev_mas-025_budget_variance.md
【重要】1 回のツール呼び出しで全内容を出力しない。以下の Step に必ず分割して実行すること。
Step 2-1: 骨格の作成 (Write、目安 ~20行)
以下の見出しのみを持つ骨格ファイルを Write で作成する(本文は空で可):
# F-25: 予算vs実績差異分析(41_trn_budget ベース)
## 概要
## 目的
## 現在のコード
## 修正方針
## 影響範囲
## 注意事項
## エッジケース
## 実データ検証
## 関連ドキュメント
## 人間が検討すべき事項
## 実装プロンプト(Claude Code 用)
## 推奨実行モデル
## 変更履歴
## 仕様書作成プロンプト
Step 2-2: 前半セクションの追記 (Edit または Bash heredoc、目安 ~300行)
以下を「概要」〜「注意事項」に書き込む:
概要テーブル: 案件ID=MAS-025、カテゴリ=FP&A・レポーティング、Phase/優先度/所要時間は 1-1 で取得した値を転記、対象ファイル=
200_data/202_repository.js(BudgetRepository 追加)・100_config/101_sys_config.js(メニュー追加)・600_report/60X_datamart_budget_variance.js(新規作成・番号は 1-7 で確認した最大番号+1)目的:
41_trn_budgetの予算データと42_trn_journalの実績データを科目・月次で突合し、差異額・差異率を66_pl_budget_varianceシートに出力するレポートビルダーを新規実装する。BudgetRepositoryが未実装であるため、202_repository.jsへの追加も本案件のスコープに含める。現在のコード:
200_data/202_repository.js:BudgetRepositoryが未実装(1-5 で確認した末尾行番号を明記)100_config/101_sys_config.js: 「📊 レポート」メニューに予実差異分析のメニュー項目が存在しない(1-6 で確認した行番号を明記)66_pl_budget_varianceシートが未作成
修正方針(3 Step 構成):
Step 1 — BudgetRepository 追加(
200_data/202_repository.js末尾に追加)OrderRepositoryと同一パターンで実装する_getSheet():Utils.getSheetByKey('{1-6で確認したシステムキー}', '41_trn_budget')(システムキー未登録の場合は第 1 引数にnull相当の代替を使い、フォールバック名のみで対応)findAll()のみ実装(書き込みは不要)。戻り値:{ headers: string[], dtos: BudgetDTO[] }有効フラグのフィルタは呼び出し側で行う(Repository 層では素通し)
Step 2 — レポートビルダー新規作成(
600_report/60X_datamart_budget_variance.js)- 関数名:
buildBudgetVarianceReport() LockService.getScriptLock()+try...finallyでラップ(1-7 で確認したパターンに倣う)- 処理フロー:
- 予算データ取得:
BudgetRepository.findAll().dtos→有効フラグフィルタ(flag === false || String(flag).toUpperCase() === 'FALSE'で除外)→予算バージョン === '最新予算(V1)'でフィルタ - 予算データ 0 件ガード:
SpreadsheetApp.getActiveSpreadsheet().toast('予算データが未登録です', 'F-25', 5)を表示してreturn - 実行前確認ダイアログ: 集計対象件数・
対象年月の最小〜最大値をSpreadsheetApp.getUi().alert()で表示し、ユーザーが OK を選択した場合のみ処理継続(ButtonSet.OK_CANCELを使用) - 実績データ取得:
JournalRepository.findAll().dtos→ 1-3 で確認した有効フラグ列の有無に応じてフィルタ - 科目マスタ取得:
AccountRepository.findAsMap() - 集計:
Utils.parseDateToYm(dto['対象年月'])/Utils.parseDateToYm(dto['発生日(P/L計上日)'])でキー生成し、{ 科目名: { YYYY-MM: { budget: 0, actual: 0 } } }形式でピボット集計 - 出力シート取得・クリア:
ss.getSheetByName('66_pl_budget_variance')→nullならss.insertSheet('66_pl_budget_variance')→sheet.clearContents()(フォーマットは保持) - ヘッダー行書き込み: A=大分類、B=科目名、C=指標、D〜O=4月〜3月(会計年度 12 ヶ月)、P=年度合計
- 科目ごとに「予算」「実績」「差異額」「差異率」の 4 行を書き込み
- 予算データ取得:
- 差異計算:
- 差異額 = 実績金額 − 予算金額
- 差異率 = 差異額 / 予算金額(ゼロ除算はエッジケーステーブル参照)
- 対象年度の決定: 1-6 で確認した既存パターンに合わせること。既存パターンが不明な場合は「要確認事項」として仕様書に明記し、暫定として実行時ダイアログ入力とする
Step 3 — メニュー追加(
100_config/101_sys_config.js)- 1-6 で確認した「📊 レポート」メニューの適切な位置(行番号を明記)に
.addItem('予実差異分析(予算ベース)を更新', 'buildBudgetVarianceReport')を追加
影響範囲:
200_data/202_repository.js:BudgetRepository追加(既存 Repository への変更なし)100_config/101_sys_config.js: メニュー項目 1 件追加600_report/60X_datamart_budget_variance.js: 新規作成66_pl_budget_varianceシート: 初回実行時に自動作成
注意事項:
有効フラグの判定はflag === false || String(flag).toUpperCase() === 'FALSE'パターンを徹底すること(202_repository.jsのAccountRepository.findAsMap()に同パターンあり)予算バージョンが複数存在する場合の重複計上に注意。Constants.SHEET_DEFAULTSの'最新予算(V1)'でフィルタするが、将来的に複数バージョン対応が必要になる可能性を「人間が検討すべき事項」に記載BudgetDTO.収支区分('収入' | '支出')とJournalEntryDTO.収支区分を突合する際、符号の扱いを統一すること(両者とも正値で格納されているか確認)Utils.parseDateToYm()に文字列"YYYY-MM"を渡した場合の正常動作は 1-8 で確認済みであること66_pl_budget_varianceシートが DDL 管理外の場合、CLAUDE.mdの「DDLで管理されないタブ」一覧に追記する必要がある
Step 2-3a: エッジケース〜人間検討事項の追記 (Edit または Bash、目安 ~200行)
## エッジケースセクション:
| 条件 | 表示値 | 理由 |
|---|---|---|
| 予算金額=0、実績金額>0 | "-" | 差異率が無限大のため表示不可 |
| 予算金額=0、実績金額=0 | "0.0%" | 計画通り(計算可能) |
| 予算金額=0、実績金額<0 | "-" | 予算外の費用発生(計算不可) |
| 予算金額>0、実績金額=0 | -100.0% | 予算に対して実績ゼロ(通常計算) |
| 予算データが 0 件(バージョンフィルタ後) | 処理中断・トースト表示 | 未登録データでの実行防止 |
| 科目が予算にのみ存在 | 実績=0 として差異計算 | 和集合アプローチ |
| 科目が実績にのみ存在 | 予算=0 として差異計算(差異率は "-") | 和集合アプローチ、予算外支出 |
差異評価の方向性: 収益科目(売上高等)は 差異額 > 0 が良好だが、費用・原価科目は 差異額 < 0(実績 < 予算)が良好となる。レポート上での色分けや記号(△)による区別を推奨事項として記載すること。
## 実データ検証セクション:41_trn_budgetシートで MCP またはシート直接確認: 有効フラグ=TRUE のレコード件数、予算バージョンの実際の格納値('最新予算(V1)'との一致確認)、対象年月の最小・最大値11_mst_accountの科目名と41_trn_budgetの科目名が完全一致するか(全角半角・スペースの違いも確認)42_trn_journalに有効フラグ列が実際に存在するかどうか(1-3 のJournalEntryDTO定義に含まれていない場合は特に要確認)
## 関連ドキュメントセクション:
| ドキュメント | 関連箇所 |
|---|---|
docs/dev/dev_mas-001_variance_analysis.md | レポートビルダーの基本構成・実装パターン参考 |
000_infra/003_contracts.js | BudgetDTO / JournalEntryDTO の型定義 |
200_data/202_repository.js | BudgetRepository 追加先・既存 Repository パターン |
## 人間が検討すべき事項セクション:- 1-1 で取得した TODO_future.md の「人間が検討すべき事項」を転記
- 追加事項: 集計対象年度の指定方法(
03_sys_paramsパラメータ参照 / ダイアログ入力 / 固定値のいずれか) - 追加事項:
予算バージョンフィルタ仕様(複数バージョン共存時、どのバージョンを使うかのルール) - 追加事項:
66_pl_budget_varianceシートをsetupAllSchemas(DDL)管理に含めるかどうか。含めない場合はCLAUDE.mdの「DDLで管理されないタブ」一覧に追記が必要
Step 2-3b: 実装プロンプト〜変更履歴の追記 (Edit または Bash、目安 ~250行)
実装プロンプトは コードブロック(バッククォート3つ以上)で囲まず、行頭4スペースインデント で以下の内容を出力すること:
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 MAS-025「予算vs実績差異分析(41_trn_budget ベース)」を実装してください。
## 実行前タスク
- `200_data/202_repository.js` を Read し、`OrderRepository` の `_getSheet` / `findAll` の実装を確認する(BudgetRepository 作成のテンプレートとして使用)
- `100_config/101_sys_config.js` を Read し、`41_trn_budget` のシステムキーと「📊 レポート」メニューへの追加位置(行番号)を確認する
- `000_infra/003_contracts.js` を Read し、`BudgetDTO` の全フィールドと `JournalEntryDTO` の `有効フラグ` 列の有無を確認する
- `600_report/` 配下の既存レポートビルダーを 1 件 Read し、`LockService.getScriptLock()` の使用パターンと出力シートのクリア手段を確認する
## 修正対象ファイル
1. `200_data/202_repository.js` — `BudgetRepository` を末尾に追加
2. `600_report/60X_datamart_budget_variance.js` — 新規作成(番号は `600_report/` 配下の既存最大番号+1 で確定)
3. `100_config/101_sys_config.js` — 「📊 レポート」メニューへのメニュー項目追加
## 実装内容
### 1. BudgetRepository 追加(`202_repository.js` 末尾)
`OrderRepository` と同一構造で実装すること:
- `_getSheet()`: `Utils.getSheetByKey('{101_sys_config.jsで確認したシステムキー}', '41_trn_budget')`(キー未登録の場合はフォールバック名のみで対応)
- `findAll()` のみ実装。戻り値: `{ headers: string[], dtos: BudgetDTO[] }`
- `有効フラグ` フィルタは Repository 層では行わない(呼び出し側で実施)
### 2. レポートビルダー新規作成(`600_report/60X_datamart_budget_variance.js`)
関数名: `buildBudgetVarianceReport()`
処理フロー(既存レポートビルダーのパターンに倣うこと):
1. `LockService.getScriptLock().tryLock(3000)` でロック取得。失敗時は toast 表示して return。`try...finally` で `lock.releaseLock()` を確実に実行
2. 予算データ取得: `BudgetRepository.findAll().dtos` → 有効フラグフィルタ(`flag === false || String(flag).toUpperCase() === 'FALSE'` で除外)→ `予算バージョン === '最新予算(V1)'` でフィルタ
3. 件数 0 ガード: `SpreadsheetApp.getActiveSpreadsheet().toast('予算データが未登録です', 'F-25', 5)` → return
4. 実行前確認ダイアログ: 件数と `対象年月` の範囲を整形して `SpreadsheetApp.getUi().alert('確認', msg, SpreadsheetApp.getUi().ButtonSet.OK_CANCEL)` で表示。CANCEL なら return
5. 実績データ取得: `JournalRepository.findAll().dtos` → 有効フラグ列が存在する場合のみフィルタ
6. 科目マスタ取得: `AccountRepository.findAsMap()`
7. 集計: `Utils.parseDateToYm()` でキー生成し、`{ 科目名: { 'YYYY-MM': { budget: 0, actual: 0 } } }` 形式でピボット集計
8. 出力シート取得: `ss.getSheetByName('66_pl_budget_variance')` → null なら `ss.insertSheet('66_pl_budget_variance')` → `sheet.clearContents()`
9. ヘッダー行書き込み: A=大分類、B=科目名、C=指標、D〜O=4月〜3月(会計年度 12 ヶ月)、P=年度合計
10. 科目ごとに「予算」「実績」「差異額」「差異率」の 4 行を書き込み
差異計算式:
- 差異額 = 実績金額 − 予算金額
- 差異率: 予算金額 ≠ 0 → 差異額 / 予算金額 / 予算=0 かつ 実績=0 → 0 / それ以外 → null(セルに "-" を表示)
### 3. メニュー追加(`101_sys_config.js`)
「📊 レポート」メニューの確認済み行番号に `.addItem('予実差異分析(予算ベース)を更新', 'buildBudgetVarianceReport')` を追加
## 制約
- `202_repository.js` の既存 Repository(OrderRepository / InvoiceRepository 等)は変更しない
- 有効フラグ判定は必ず `flag === false || String(flag).toUpperCase() === 'FALSE'` パターンを使用すること
- 列参照はヘッダー名ベース(列番号ハードコード禁止)
- `AccountRepository` のキャッシュをリセットしない(既存動作に影響しないよう、`AccountRepository.resetCache()` を呼ばない)
## エッジケース
| 条件 | 表示値 | 理由 |
|------|--------|------|
| 予算金額=0、実績金額>0 | "-" | 差異率が無限大のため表示不可 |
| 予算金額=0、実績金額=0 | "0.0%" | 計画通り |
| 予算金額=0、実績金額<0 | "-" | 予算外費用、計算不可 |
| 予算データが 0 件 | 処理中断・トースト | 未登録ガード |
| 科目が一方のみに存在 | 不在側=0 として計算 | 和集合アプローチ |
## 動作確認
1. `npm run push:dev` で開発用 GAS にデプロイ
2. 「📊 レポート」>「予実差異分析(予算ベース)を更新」を実行
3. 確認ダイアログが件数・期間付きで表示されること
4. `66_pl_budget_variance` シートが生成され、科目ごとに予算/実績/差異額/差異率 の 4 行が出力されること
5. `予算バージョン` フィルタで 0 件になる場合にトースト通知で中断されること
6. 2 回実行してシートが重複せず上書きされること(べき等性確認)
### 拡張思考の使用状況
| フェーズ | 拡張思考 | 備考 |
|---------|---------|------|
| BudgetRepository 追加 | なし | OrderRepository パターン踏襲のみ |
| レポートビルダー実装 | あり | ピボット集計ロジックの設計 |
| メニュー追加 | なし | 挿入位置特定後は定型作業 |
- 推奨実行モデル:
| 工程 | 推奨モデル | 理由 |
|---|---|---|
| BudgetRepository 追加 | Claude Haiku | 既存 OrderRepository パターンの横展開、判断不要 |
| レポートビルダー新規作成 | Claude Sonnet | ピボット集計・ダイアログ制御の設計判断が必要 |
| メニュー追加 | Claude Haiku | 挿入位置特定後は定型作業 |
- 変更履歴:
| 日付 | 変更内容 |
|---|---|
| 2026-04-19 | 初版作成 |
Step 2-4: 仕様書作成プロンプトの記録 (Edit または Bash)
## 仕様書作成プロンプト セクションに以下の形式で、この <instruction> タグ内の全文をそのまま貼り付けて記録する:
<details><summary>展開して表示</summary>
(この instruction 全文)
</details>
Phase 3: 後処理(テキスト報告禁止。即座にツール実行)
docs/_config.json追記:nav配列の「§E.5 FP&A・レポーティング」セクションに追加:{ "file": "dev/dev_mas-025_budget_variance.md", "title": "E.5.X F-25 予算vs実績差異分析" }※E.5.Xの番号は既存エントリの最大番号+1 に修正すること。docs/_internal/changelog.md先頭行に追記:| 2026-04-19 | [dev_mas-025_budget_variance.md](dev_mas-025_budget_variance.md) | 初版作成。F-25 予算vs実績差異分析の開発仕様書 |Git コミット&プッシュ:
git add docs/dev/dev_mas-025_budget_variance.md docs/_internal/changelog.md docs/_config.json git commit -m "docs: F-25 予算vs実績差異分析の開発仕様書を作成 BudgetRepository新規追加・66_pl_budget_varianceレポートビルダー・メニュー追加の仕様書。 BudgetDTO/JournalEntryDTOのフィールド確認・エッジケーステーブル・実データ検証を含む。 https://claude.ai/code/session_XXXXX" git push -u origin docs/dev-F-25