カスケード再計算の設計
控除の判定は独立ではなく、同じ事実(属性)が複数の控除の入力になっている。特に「本人の合計所得金額」は多くの控除判定の入力パラメータであり、この値が変わると連鎖的に複数の控除の判定結果が変わる。
→ 設計思想の詳細: 属性ベース思考
依存グラフ
NOTE
R8(令和8年分)の子育て世帯・生命保険料控除拡充(→ 令和8年施行予定)により、物的控除(生命保険料控除)が人的控除の判定結果(23歳未満の扶養親族の有無)に依存する 関係が初めて生じる。点線は年度限定の依存を示す。
設計方針: 全再計算
部分再計算ではなく全再計算 を採用する。
| 観点 | 部分再計算 | 全再計算(採用) |
|---|---|---|
| 実装の複雑さ | 高(依存グラフの管理が必要) | 低(全ステップを再実行するだけ) |
| 正確性 | 依存関係の漏れによるバグリスク | 常に正確 |
| パフォーマンス | 変更箇所のみ再計算 | 全体再計算だが、純粋関数のため高速(<1ms) |
| 将来の税制改正 | 新しい依存関係が追加されるたびに修正が必要 | 計算エンジンの更新のみで対応 |
純粋関数で構成されたパイプラインは副作用がなく、全体を再実行しても計算コストは極めて低い。依存グラフの管理という本質的でない複雑さを排除し、正確性を保証する。
人的控除→物的控除の横断依存(R8 子育て世帯・生命保険料控除拡充)
R8(令和8年分)の税制改正(→ 令和8年施行予定)により、物的控除の計算パラメータが人的控除の判定結果に依存する前例のないケースが発生する。
| 項目 | 内容 |
|---|---|
| 改正内容 | 23歳未満の扶養親族を有する居住者について、一般生命保険料控除の適用限度額を4万円→6万円に拡充 |
| 影響 | 扶養親族の所得見積額の変更 → 23歳未満扶養親族の該当有無が変わる → 一般生命保険料控除の上限額が変わる |
| 期間 | R8年分限りの時限措置 |
設計方針:
全再計算が横断依存を自然に吸収する: 全ステップ再実行の方針により、人的控除側の判定結果が変わった場合に物的控除も自動的に正しく再計算される。部分再計算を採用していた場合、この横断依存の追跡が必要になっていた
計算順序の明示的制約: パイプラインのステップ⑤(所得控除の合計額)の内部で、物的控除の計算は
CategoryJudgmentResultを入力として必要とする。カテゴリ判定 → 人的控除計算 → 物的控除計算 の順序が暗黙の前提から明示的な制約となるLifeInsuranceCalculator のインターフェース: 全年度の
LifeInsuranceCalculatorがCategoryJudgmentResultを引数に受け取る統一インターフェースとする。R8 以外の年度はこの引数を単に無視する。年度ごとにインターフェースを変える設計は避け、統一性を保つcsharp// 全年度で統一のインターフェース public static DeductionDetail Calculate( InsuranceDeduction insuranceData, CategoryJudgmentResult categories, // R8のみ参照、他年度は無視 LifeInsuranceParameters parameters);時限措置の扱い: R8 固有のロジック(23歳未満扶養親族の有無による上限切替)は
LifeInsuranceParameters内の年度パラメータとして表現する。R9 以降のパラメータにはこの拡充が含まれないため、計算エンジンの年度バージョニングにより自然に無効化される
再計算のタイミング
| 状態 | 再計算タイミング | 実行範囲 |
|---|---|---|
| Draft | 所得見積額の変更時(リアルタイムプレビュー) | Stage 3 + パイプライン全体 |
| Draft → Submitted | ライフサイクル遷移時 | 全 Stage を改めて実行して確定 |
| Submitted → Approved | 管理者の承認操作時 | 検証用に全体再計算(結果が一致することを確認) |
| 再年調 | 事実データの訂正時 | 当該年度の計算エンジンで全体再計算 |