CF精算表: 法人税ライフサイクルモジュールの実装・統合・リファクタリング
朝、法人税の取引モジュール(CF_306)のPythonファイルを新規に開いた。ここまでのパイプラインは借入金・固定資産・運転資本と個別論点を積み上げてきたが、法人税だけはどの論点にも横串で刺さる。単独モジュールを作って統合する方針で進めた。ところが統合した瞬間、CFWSの数字が合わない。法人税仕訳が二重に計上されていた。原因を追い、修正し、さらにリファクタリングで重複コードを潰す --- 朝から夜まで法人税に向き合い続けた一日だった。
CF_306 法人税ライフサイクル取引モジュールの新規実装
gen_tax_lifecycle_xlsx.py
法人税の「発生→計上→支払→繰越」というライフサイクル全体を1ファイルで表現する取引モジュールを書いた。中間決算なしの年1回申告を前提に、以下の流れを仕訳として自動生成する。
- 12/31に税引前当期純利益を算出し、法人税等を計上(未払法人税等)
- 翌年2/28に未払法人税等を取り崩して現金で支払う
- 税引前当期純利益がマイナスなら欠損金として繰越
繰越欠損金マトリクス
元Excelモジュールの繰越欠損金マトリクスと照合しながら実装した。マトリクスは「発生年度 x 使用年度」の2次元テーブルで、各年度の欠損金が何年度にいくら使用されたかを追跡する。10年繰越のルールに従い、期限切れの欠損金が自動で落ちるようにした。
Excel上ではマトリクスの各セルに数式を入れ、行合計が繰越残高、列合計がその年度の控除額と一致することを検証できるようにした。
税金仕訳ビルダーの追加
mf_journal.pyにbuild_tax_journals関数を追加した。税引前当期純利益の算出、法人税額の計算、未払法人税等の計上仕訳と支払仕訳の生成をこの関数に集約した。会計ソフトAのインポート形式に合わせた仕訳データを返す。
CF_300 総合演習への法人税統合 --- 二重計上バグとの格闘
二重計上バグの発見
法人税モジュールを総合演習(CF_300)に統合してCFWSを再生成すると、法人税等の金額が想定の2倍になっていた。Check行が0にならない。仕訳シートを開いて法人税の行をカウントすると、同じ仕訳が2セットある。
原因の特定
仕訳の出所を追うと、1セットは今回追加したbuild_tax_journalsから、もう1セットはCF_304(運転資本)のExcelに既に埋め込まれていた。運転資本モジュールが独自に法人税仕訳を生成しており、そこに新モジュールの仕訳を重ねていた。
修正: filter_journalsにexclude_taxオプション追加
総合演習では法人税モジュール側の仕訳を正とし、運転資本側の法人税仕訳を除外する方針にした。filter_journals関数にexclude_taxパラメータを追加し、総合演習での結合時にのみ運転資本の法人税仕訳をフィルタアウトする。個別論点としてCF_304を単体で動かすときは従来通り法人税込みで生成される。
未払法人税等が計上されない問題
二重計上を潰した後、今度は未払法人税等のBS残高がゼロのままだった。計上日を確認すると期中日付になっていた。期末日(12/31)に計上し、翌年2/28に支払う日付に修正して解消した。決算日をまたぐ負債が正しくBSに載るようになった。
CFWS営業CF小計の調整列並び替え
法人税を統合したことで、CFWSの営業CF小計内に「法人税等調整額」の行が追加された。日本基準の様式2に合わせ、調整列の行順序を「減価償却費→貸倒引当金増減→受取利息→支払利息→...→法人税等調整額」の並びに修正した。
CF計算書セクションのBS由来/PL由来統合
CFWSの下半分(CF計算書セクション)では、BS由来の増減とPL由来の調整を分離して出力していた。法人税が加わると列順序と行順序が噛み合わなくなったため、BS由来とPL由来を統合し、列順序と行順序を一致させる修正を入れた。
CF_304 運転資本への法人税統合
税引前当期純利益の自動計算
gen_working_capital_xlsx.pyに税引前当期純利益を自動計算するロジックを追加した。PLの売上高から売上原価・販管費・営業外損益を差し引き、税引前当期純利益を算出する。この値をもとに法人税額を計算し、仕訳を生成する。
cf-labels.jsonとCFWS配分ロジック
未払法人税等をcf-labels.jsonに追加し、CFWS上での配分先を設定した。ここで手が止まった。未払法人税等の増減は営業CFの小計内に入るのか、小計外なのか。
日本基準の間接法CFWSでは、「法人税等の支払額」は営業CF小計の外に表示する。小計は営業活動から生まれたキャッシュを示し、税金の支払いはその後に控除する。cf-labels.jsonの配分設定を修正し、「法人税等の支払額」が小計外に正しく配置されるようにした。
繰越利益剰余金への法人税反映
繰越利益剰余金の配分ロジックに法人税等を追加した。当期純利益 = 税引前当期純利益 - 法人税等 という関係が、BS上の繰越利益剰余金の増減に正しく反映されるようになった。
税金モジュールのリファクタリング(4タスク)
法人税統合を終えた時点で、build_tax_journalsが3ファイルに散在していた。CF_306単体・CF_300総合・CF_304運転資本のそれぞれが微妙に異なるコピーを持っている。同じロジックの3つのコピーは、次の変更で必ず壊れる。リファクタリングを4タスクに分割して実行した。
Task 1: build_tax_journals を mf_journal.py に統合
3ファイルのbuild_tax_journalsを比較し、差分を洗い出した。パラメータの違いを引数で吸収し、mf_journal.pyの1箇所に統合した。3ファイルから重複コードを削除。
Task 2: write_tax_params 共通関数
税金パラメータ(税率・繰越期間・申告期限等)をExcelシートに書き出す処理が各ファイルにコピーされていた。write_tax_paramsとして共通関数に切り出した。
Task 3: write_nol_matrix 統合
繰越欠損金マトリクスの書き出し処理を共通化した。CF_306とCF_300で列の開始位置が異なるため、col_startパラメータを追加して吸収した。
Task 4: write_tax_schedule_sheet の整理
税金スケジュールシート(計上日・支払日・金額の一覧)の書き出し処理を整理した。
Codex(GPT-5.4)レビューで漏れを検出
リファクタリング完了後、Codexにレビューを依頼した。「CF_300総合演習版でwrite_tax_paramsの呼び出しが旧関数のまま残っている」という指摘が返ってきた。確認すると、Task 2で共通関数に切り出した際にCF_300側のimportを更新し忘れていた。指摘通り修正してリファクタリング完了。
CFWSの取引_税金シートを数式化
リファクタリング後、取引_税金シートの値がベタ打ちのまま残っていた。前日の方針に従い、年次推移表からINDEX/MATCHで参照する数式に置き換えた。年次推移表の値を変更すれば、取引_税金シートにも自動で反映される。
最後にIBフォーマット(投資銀行モデルの書式ルール)を適用し、ヘッダ色・数値書式・参照セルの色分けを統一した。
振り返り
二重計上バグは、仕訳シートの行数を数えた瞬間に「あ、倍ある」と気づいた。原因の特定自体は速かったが、「どちらを正とするか」の判断に時間を使った。単体モジュールでも総合演習でも同じコードパスを通したい。しかし総合演習では法人税の計算元となるPL数値が他モジュールの仕訳も含む。結局、exclude_taxフラグで結合時にフィルタする設計に落ち着いた。
リファクタリングの4タスクは、統合直後にやったからこそ差分が小さかった。これが数日寝かせると、各ファイルが独自に進化して統合コストが跳ね上がる。コピーが生まれた瞬間に潰す --- この判断は正しかった。
Codexのレビューでimport漏れを拾えたのも収穫だった。人間の目は「変更した箇所」に集中するが、「変更すべきだったのにしなかった箇所」は見落としやすい。外部レビューの価値はそこにある。