• #eurekapu
  • #キャッシュフロー計算書
  • #Python
  • #リファクタリング
  • #Codex
  • #会計基準
開発eurekapu-nuxt4

CFWS全37Q網羅修正 - 引当金と貸倒損失の調整ロジック再設計

朝、ユーザーから「引当金の取扱いのExcelを見てるんだけど、期首残高の仕訳が出力のMF仕訳シートに入ってないんですよ」と指摘が来た。Q3-3のCFWS(キャッシュフロー計算書ワークシート)を開いて比べてみると、元データには確かに 現金及び預金/資本金繰越利益剰余金_期首/製品保証引当金 といった期首残高の3行が並んでいる。生成後のシートからはそれが丸ごと消えていた。

ここから全37Qを網羅的に点検する一日が始まった。

期首残高がパーサーに拾われない

まずパーサーの entries_to_mf_rows を読み直した。設計としては include_opening=True が既定で、期首残高は MF仕訳シートに含めるはず。メインスクリプト側の呼び出しも正しい。となるとパースの入り口側で落ちている可能性が高い。

元Excelのセル値をUTF-8で読み直すと、原因が一発で見えた。

  • Q3-9のような標準形: N列 = x2_period、O列 = 開始残高
  • Q3-3だけ: N列 = 開始残高、O列 = 空

パーサーの _extract_opening_balancesentry.topic_key == '開始残高' でフィルタしていたため、Q3-3の期首行は全て素通りしていた。

修正はシンプルに。パース時点で N列が「開始残高」かつ O列が空なら、正しい位置に補正する。

if period_key == '開始残高' and not topic_key:
    topic_key = '開始残高'
    period_key = first_period_of_sheet

これでQ3-3を再生成すると、MF仕訳シートの Row 2-7 に期首残高の3仕訳がきれいに並んだ。

「未払金の増減」列が消えていた問題

次の指摘が来た。Q3-3の年次推移表には「未払金の増減」という調整列があるのに、生成したCFWSからは欠けている。代わりにその金額が「役員退職慰労引当金の増減額」列にまとめて配賦されていた。

該当仕訳は 役員退職慰労引当金 500 / 未払金 500 の1行。借方と貸方で別々のCF項目に割り付ける必要がある。

アロケータの _allocate_cfws を読むと、_entry_cf_label(entry, adjustments)1仕訳につき1つのCFラベル しか返していなかった。設計の前提がそもそも「1仕訳=1ラベル」だったのだ。

修正方針を設計し直した。

  • 1仕訳=1ラベルの前提を捨てる
  • entry.dr_cf_labelentry.cr_cf_label が両方あり、かつ異なる場合、DR側とCR側をそれぞれ独自のCFラベルで配賦する
  • ステップ6の列生成も同じロジックに寄せる

これで未払金500が「未払金の増減」列に独立して配賦されるようになり、役員退職慰労引当金の列の金額も整合した。

現金科目側のCSラベルが列として漏れ出す

再生成したシートを眺めていたら、今度は「その他の営業支出」という使っていないはずの列が勝手に追加されていた。

原因を追うと、アロケータが借方・貸方の両側からCS科目ラベルを無差別に収集していた。現金及び預金_その他の営業支出 のように現金科目に付いたサフィックスも、列生成のラベル候補として拾ってしまう。これは現金振替の方向を示すためのタグであって、調整項目の列になる筋合いはない。

_entry_cf_label 側でも同様に、現金科目に付いたCSラベルはスキップする方針に揃えた。

# E列/J列のCSラベルを読む時、科目が現金ならスキップ

Q5-15で再検証すると、支払保険料 / 現金及び預金_その他の営業支出 の仕訳が「支払保険料」側だけで評価され、誤生成されていた「その他の営業支出」列が消えた。

全37Qの網羅チェックに向けて計画立案

Q3-3の期首残高問題と未払金問題は直ったが、ユーザーから「他のQにも同じ漏れがあるはずだから全部見てほしい」と要望。単発の修正ではなく、全37Qの網羅チェック として計画を立てることにした。

プランモードに入り、サブエージェント3つを並列で走らせて全シートを洗う。計画書ができたら codex exec -m gpt-5.4 でレビューを投げた。

Codexから致命的な指摘が4点返ってきた。全て正当だったので計画を更新する。

  • 検証列の探索範囲が range(10, 22) で固定されていて、調整列が増えると「合計」列が22列目以降に移動してしまう
  • dual-label対象シートの識別条件が緩い
  • 期首残高補正がQ3-3以外の将来データで誤動作する可能性
  • 配賦の優先順位が明文化されていない

codex exec resume --last で再レビューを投げて、修正した計画が通ったことを確認してから実装に入った。

実装と全件再生成

Step 0〜6を順に進める。

  • Step 0: dry-run で37Qのシート一覧を確認(レイアウト用シートが混ざっていないか)
  • Step 1: verify列の動的探索に変更
  • Step 2: 旧ファイルを old/ に退避
  • Step 3: 全Q一括再生成
  • Step 5: dual-label対象シートのヘッダーと開始残高を確認

全37Q(多期間分含めて42シート)がエラーなく再生成された。pywin32が入っていないのでCOM経由のcheck=0検証はスキップだが、構造的には全件パスしている。

Q3-4 貸倒引当金の売上債権/貸付債権分離

午後、別セッションから「Q3-4の貸倒引当金を売上債権用と貸付債権用で分けてほしい」と依頼が来た。

mf-account-master.json を確認すると、会計ソフトAの公式マスタには 「貸倒引当金_売上債権」「貸倒引当金_貸付債権」「貸倒引当金_未収入金」が独立した勘定科目として既に登録済み だった。マスタに合わせるなら、スクリプト側で正規化して一つにまとめず、独立科目として残すのが正しい。

修正は3段構え。

  • _SPECIAL_ACCOUNTS の正規化で接尾辞(_売上債権 等)を残す
  • ACCOUNT_DB に3科目を追加。グループは other_current(既存の 貸倒引当金 と同じ)で、CF側では「貸倒引当金の増減額」に集計される
  • split_qa_to_cfws.py のPL→CFラベルマッピングに貸倒損失の売上債権/貸付債権版を追加

Q3-4を再生成すると、MF仕訳シートに「貸倒引当金_売上債権」「貸倒引当金_貸付債権」が別々に並んだ。CFWSのcheck値は分離前と同一だった(非破壊的な修正)。

貸倒損失の長期貸付金K列調整

もう一つ論点があった。貸倒損失のうち「貸付金の貸倒損失」は、会計基準上、売上債権の貸倒損失とは別に営業CFで個別に調整する必要がある。

長期貸付金のK列調整を追加し、PL由来の調整マッピングに 貸倒損失_貸付債権 を独立ラベルとして登録した。影響範囲はQ3-4, Q3-5, Q5-19〜Q5-23の計7Q。

振り返り

今日潰した致命的バグは3つ。

  • Q3-3の期首残高がパースで落ちる(元データの構造ゆれ)
  • _allocate_cfws が1仕訳=1ラベル前提で、DR/CR両側独立の配賦ができていなかった
  • 現金科目側のCSラベルが列として誤って生成される

どれも「1つのQを手で直してOK」ではなく、パーサーとアロケータの設計を見直して全37Qに効かせる形で直した。Codexレビューで計画段階の穴を4つ塞いでから実装に入ったおかげで、実装中の手戻りはほぼゼロだった。

スキル化で一度ミスをした。独自流でfrontmatterなしのスキルファイルを作ってしまい、ユーザーに「example-skills:skill-creator があるのになぜ参照しなかったのか」と指摘された。次に新しいスキルを作る時は /skill-creator を先に呼ぶ。

明日やること

  • pywin32を導入してCOM経由のcheck=0自動検証を復活させる
  • dual-labelの配賦ルールを cf-labels.json にデータ化して、スクリプト側のハードコードを減らす
  • Q3-4以外の6Q(Q3-5, Q5-19〜Q5-23)でも貸倒引当金分離がHTML上で正しく表示されているかブラウザで確認する