• #Vue
  • #連結会計
  • #テスト駆動
  • #Codexレビュー
  • #リファクタリング
開発eurekapu-nuxt4メモ

連結会計レッスンを Vue + データ駆動でフルスクラッチ実装

朝の机にHTMLプロトタイプの連結精算表を広げると、セルの数値もハイライトの色も全部直書きで、設例を1本足すたびに数百行をコピペする構造になっていた。今日はこれを Vue コンポーネント + 型付きデータに置き換え、午前中に I-2-1〜I-2-3 の3本、午後に I-3-1〜I-3-3 の3本まで一気に実装した。途中で Codex GPT-5.5 が二重計上の致命点を指摘してきて、計画書を v1 → v2 → v3 まで書き直す羽目になった。

HTMLハードコードからデータ駆動へ

プロトタイプの consolidated-accounting.html は仕訳プールも精算表も、セルのハイライトクラスまで HTML に直書きされていた。設例3本を Vue で動かすには、構造を分解して再構築する必要がある。

最初に決めたのは、データ層を types.ts でスキーマ化することだ。1本のレッスンに必要な情報を以下に分けた。

// types.ts のスキーマ概要
type Example = {
  id: string                    // 'I-2-1'
  title: string
  premise: PremiseRow[]         // 前提条件(P社・S社の数値)
  journalEntries: JournalEntry[] // *A *B *C のラベル付き仕訳
  worksheet: {
    columns: Column[]           // 個別 / 修正列 / 連結
    rows: Row[]                 // 科目行(derived 行は依存式を持つ)
    modifyColumns: ModifyColumn[] // 列ごとの修正仕訳マッピング
  }
}

仕訳には *A *B *C のラベルを持たせ、精算表のセルから「どの仕訳がこの数値に効いたか」を逆引きできるようにした。これで「セルクリック → 仕訳モーダル」の動線が型レベルで保証される。

compute.ts は精算表の合計値を導出する純粋関数を集めたモジュール。derived 行(小計や利益)は他の行に依存するので、依存解決を複数パスのループで処理した。1パスでは「先に合計が出ていない行を参照して NaN になる」問題が起きたためだ。

// compute.ts の方針(疑似コード)
const computeRows = (rows, columns) => {
  let resolved = rows.filter(r => r.kind === 'data')
  while (resolved.length < rows.length) {
    const next = rows.filter(r => canResolve(r, resolved))
    if (next.length === 0) throw new Error('循環依存')
    resolved = [...resolved, ...next.map(compute)]
  }
  return resolved
}

types / format / compute / example-i-2-1 / test を並列で書いてから pnpm vitest を叩くと、12テストが全パスした。データ層が動けばあとは UI を被せるだけ、という確信が得られた瞬間で、ここから実装速度が一気に上がった。

Phase 3 のコンポーネント分解

UI は5つのコンポーネントに切った。

コンポーネント役割
PatternNavI-2-1 / I-2-2 / I-2-3 のタブ切替
RelationDiagramP社・S社の支配関係図
PremiseSection前提条件テーブル
WorksheetTable連結精算表(マーカー+クリック可能セル)
JournalEntryModalセルクリック時の仕訳ポップアップ

書き終えてChromeで開くと、I-2-1 の営業利益が 2,549 と出た。連結会計入門書の数値と一致している。I-2-2 は 2,375、I-2-3 の売上総利益は 2,930。3本とも書籍の数値と完全一致した。テストも31本全パス。

ここで /simplify をかけて3エージェントを並列レビューさせた。JournalEntryModalgroupOf labelOf を computed の外に出す指摘など3件を採用、回帰テストを再実行して31本全パス。feature-slides スキルで実装内容を65スライドのHTMLに起こし、午前のセッションをクローズした。

Codex 再帰レビューで致命点を潰す

午後、別セッションで I-3-1〜I-3-3(連結後の修正仕訳)の計画書を作成した。最初の v1 計画書を Codex GPT-5.5 に投げた段階では「致命点なし」だったのだが、書籍画像を読み直すと計画書と画像で数値が食い違っていた

画像の対応関係を確定させる作業を Phase 0 として差し込んだ。

設例内容
I-3-1機械装置のダウンストリーム未実現利益消去
I-3-2商品のアップストリーム+NCI按分
I-3-3ソフトウェアのアップストリーム+仕掛品振替

ここから計画書を v2 に書き直し、再度 codex exec resume --last -m gpt-5.5 でレビューを走らせると、Codex が一発で致命点を撃ち抜いてきた。

v2 の modifyColumnsindividual-modify(個別修正)を含めると、列の合計に個別修正分が二重計上される

確かにその通りだった。modifyColumns は「修正仕訳の列だけ」を持ち、個別修正は別のフィールドとして分離するのが正しい。v3 でこの構造を直し、再度 Codex に投げて「致命点なし」を取得してから着手に移った。プランレビューを2周回したことで、実装中に発覚すれば数時間ロスする構造ミスを30分で潰せた

I-3-1〜I-3-3 の実装と HMR キャッシュ問題

compute.ts を v3 仕様(modifyColumns 形式 + 複数パス依存解決)に書き換えて、I-3-1〜I-3-3 の example ファイルを並列で作成。テストを走らせると 70 本全パス(既存31 + 新規39)。

pnpm dev で立ち上げて Chrome で開くと、画面が古いままだった。データを書き換えても反映されない。HMR が compute.ts の構造変更を取りこぼしていた。dev サーバを一度落として再起動すると I-3-1 の「未実現損益調整」列が現れ、機械装置 △400 / 減価償却累計額 +40 / 連結後 22,000 / △7,200 / 14,800 / 1,200 / 0 の数値が書籍画像と一致した。

I-3-2 はNCI按分が絡むので疑っていたが、商品 △500 / 利益剰余金 / 非支配株主持分まで全数値完全一致。I-3-3 は同一セル(ソフトウェア × 未実現損益調整)に *B *C の両方が乗るパターンで、マーカーが *B *C の2つ並ぶようになっていた。クリックすると「複数の仕訳がこの数値を構成しています(2本の仕訳の合算)」と表示し、未実現損益消去の *B と減価償却費調整の *C を縦並びでモーダルに出した。

補助科目あり版を3設例分追加してテストを再実行すると、99本全パス(既存31 + I-3-X 39 + 補助 I-3-X 29)。

列単位集約モーダルの設計判断

ユーザーから「機械装置 △400(*A)と減価償却累計額 +40(*B)は同じ機械装置取引の連動した処理なのに、別々のモーダルに分かれているのはおかしい」と指摘が入った。

最初の実装は「セル単位のモーダル」だった。*A セルをクリックすると *A の仕訳だけ、*B セルをクリックすると *B の仕訳だけが出る。一見すると素直だが、連結ロジックの本質である「列内の仕訳が連動している」という構造が見えなくなる

設計判断を以下に切り替えた。

  • マーカーはセル単位: 各セルに乗る仕訳ラベル(*A, *B...)はそのまま表示
  • モーダルは列単位の集約: クリックされたセルの所属する列にぶら下がる仕訳を全部縦並びで表示
  • ハイライトはクリックしたセルの科目だけ: モーダル内のハイライトは、クリックした科目に絞る

I-3-2 の B/S 商品 △500 をクリックすると、モーダルには *A *B *C が縦並びで出て、ハイライトは「商品」の行だけが点灯する。書籍が「列=概念分類」を採用している構造と一致した。

WorksheetTable のセルクリックハンドラを「セルID渡し」から「列ID渡し」に変更、JournalEntryModal 側で列に紐づく仕訳を全部受け取るように修正。align-itemsflex-start から safe center に変えてモーダルを画面中央に表示するCSSも入れた。99テスト全パスを確認してこの日の実装をクローズ。

今日の収穫

  • データ層を先に固めると、UI 実装が一気に走る。Phase 2 のテスト12本が全部通った瞬間に、午後の30倍の速度が出た
  • Codex の再帰レビューは計画書段階で2回回す。v2 で individual-modify の二重計上を撃ち抜かれた経験は、今日いちばんの節約だった
  • HMR を信じないcompute.ts の構造変更は dev サーバ再起動で確認する習慣を固める
  • 「列単位集約モーダル」の設計判断は、書籍の構造から逆算した。セル単位の素直な実装が、必ずしもドメインの本質と一致するわけではない

明日やること

  • feature-slides で生成した65スライドを noteの下書きに変換する
  • I-3-1〜I-3-3 の補助科目あり版のスクショを計画書に貼る
  • 連結精算表のモバイル表示で、横スクロールが発生しないかブラウザ実機で確認する