控除計算の設計方針
ドメイン知識(税法・制度の事実)は
docs/domain/deductions/を参照。 本ドキュメントは控除計算に関する設計判断を集約する。
→ 設計ドキュメント一覧は 設計ドキュメント を参照
対象スコープ
年末調整(年始調整)で処理する控除:
- 所得控除 13種類 → 控除
- 所得金額調整控除(①子ども等のみ。②年金等は確定申告の領域だが、合計所得金額の見積額計算時には①②の両方を考慮する必要がある)
- 住宅借入金等特別控除(税額控除)
確定申告のみの控除(雑損控除・医療費控除・寄附金控除)はスコープ外。
共通設計方針
事実起点・明細レベル保持
紙の様式の制約をデータモデルに持ち込まない。明細(契約・掛金等)レベルでデータを保持し、合算は様式出力時に行う。
- 小規模企業共済等掛金: 紙の様式では4種類×1欄の固定構造だが、同一種別で複数レコードを許容し、合算は出力時に行う → 小規模企業共済等掛金控除
有利判定の自動化
申告者に選択を求めず、システムが最適な結果を自動判定する。
- 生命保険料控除: 新旧3パターン(新制度のみ / 旧制度のみ / 新旧合算)の計算を自動で行い、最も有利な結果を採用 → 生命保険料控除
- 地震保険料控除: 複数契約で地震/旧長期が混在する場合、各契約の区分選択の組み合わせで合計控除額(上限50,000円)が変わる。最適な組み合わせを自動判定し提示 → 地震保険料控除
年度バージョニング
税額計算コアは年度ごとの計算ルールをプラグイン的に持つ。共通のインターフェースで抽象化し、年度ごとの実装を切り替える。
- 基礎控除は本則(所得税法)と加算(租税特別措置法)が別の法律根拠であり、それぞれ独立に改正されうる。物価スライド制の導入により今後は毎年変わることが見込まれる
- 配偶者控除・配偶者特別控除の控除額テーブル、配偶者特別控除の段階逓減テーブルも税制改正で変わりうる
- 控除額の構造化パターン:
基礎控除額 = f(合計所得金額)
扶養控除額 = f(年齢区分, 同居老親等フラグ)
障害者控除額 = f(障害者区分, 同居フラグ, 対象者種別[本人/配偶者/扶養親族])
特定親族特別控除額 = f(特定親族の合計所得金額)閾値・控除額のデータ管理
閾値・控除額はコードにハードコードせず、年度マスタでデータとして管理する。閾値と控除額のペアをテーブル形式で管理する。ただし区分数や判定ロジック自体が変わる場合はコード変更が必要。
前年度の計算結果の再現性
- Finalized 後の TaxCalculationResult は不変(DM-501)
- 過去年度の計算ロジックは 最低7年間維持(再年調で当該年度のルールで再計算するため)
- 表示時は保存済みの結果をそのまま返す(再計算しない)
テスト方針
- Golden tests: 各年度の国税庁計算例との完全一致
- Property tests: 年度をまたいで「同一入力→同一結果」の純粋関数性を保証
- Boundary tests: 区分の境界値(閾値±1円)
電子的控除証明書・データ取込み
取込み方法の優先順位:
- 電子的控除証明書(XML: TEG800-850) — 最も正確、改ざん検証可能
- XML を読み込んで申告データに自動反映
- XML 内の署名・ハッシュ値による改ざん検証が必須 → e-Tax XML構造
- 団体保険データ(DAT/CSV) — 会社経由で一括取込み
- LINC形式DATファイル(団体扱い生命保険)
- 損保標準フォーマット形式DATファイル(団体扱い損害保険)
- DATファイルの仕様は設計フェーズで調査が必要
- AI OCR(紙の証明書) — XML非対応の保険会社向けフォールバック
- スマートフォン等で控除証明書を撮影し、項目(区分、新旧、支払保険料等の金額)を自動認識
- OCR結果は従業員による確認・修正を経て申告データに反映
- 手動入力 — 最終手段
参考(団体保険データ対応の他社実装例):
家族構成員との連携(保険料控除)
保険料控除で必要な家族の氏名(受取人・被保険者等)は、登録済みの家族一覧から選択する UI が望ましい。ただし保険料控除の氏名と家族構成員(人的控除用)は要件が異なるため、FK はオプショナルとする。
InsuranceDeduction テーブル(保険料控除用)
→ beneficiary_name NOT NULL -- 受取人等の氏名(常に保持)
→ family_member_id NULL -- FamilyMember への FK(紐づく場合のみ)障害者区分のウィザード形式 UI
障害者の区分判定(一般 / 特別 / 同居特別)は手帳の種類・等級・同居の有無など複雑な条件の組み合わせによる。ウィザード形式で正確な区分判定を支援する:
- 手帳の種類を選択 → 等級を選択 → 区分を自動判定
- 申告者に「一般の障害者ですか?特別障害者ですか?」とは聞かない
- → 障害者控除
早見表 vs 個別計算
国税庁の早見表(扶養控除額及び障害者等の控除額の合計額)は実務用の簡便計算ツールであり、税額計算エンジンでは各控除を 個別に計算 して合算する設計とする。理由:
- 早見表は加算方式のため、個別の控除額の内訳が見えない
- Declaration の Snapshot に各控除額を個別に記録する必要がある
- 年度ごとの控除額変更に対する保守性
控除種別ごとの設計ノート
基礎控除
→ 基礎控除
年度バージョニングの必要性が特に高い控除。本則(所得税法第86条)と加算額(租税特別措置法第41条の16の2)が別の法律根拠であり、それぞれ独立に改正される。R8以降の物価スライド制導入により、閾値が毎年変動する見込み。
配偶者控除・配偶者特別控除
控除額テーブルの年度パラメータ化:
- 配偶者控除の控除額(38万円/48万円/26万円/32万円/13万円/16万円)は年度パラメータとして管理
- 配偶者特別控除の段階逓減テーブル(所得区分の境界値と控除額)も年度パラメータとして管理。R7 では共通閾値の引上げ(48万円→58万円)に伴い開始点が変更された
- 配偶者の合計所得金額の閾値は扶養親族と同じ共通閾値を使用 → 共通閾値と変遷
本人の合計所得金額の3段階:
- 納税者本人の合計所得金額による控除額の3段階(900万円/950万円/1,000万円)は配偶者控除と配偶者特別控除に共通
- 配偶者特別控除では、これに加えて配偶者の合計所得金額による段階逓減が組み合わさり、2次元のテーブル参照 となる
排他制御:
- 配偶者の合計所得金額が共通閾値以下 → 配偶者控除、共通閾値超〜133万円 → 配偶者特別控除
- 同一年度で両方が適用されることはない(排他的)
- Tax Calculation Core が配偶者の合計所得金額から自動的に判定する
死亡時の判定ロジック:
配偶者の死亡日をデータとして保持し、以下のロジックを税額計算エンジンに実装:
- 死亡日時点で控除対象配偶者の要件を満たすか → 配偶者控除
- 12月31日時点で寡婦/ひとり親の要件を満たすか → 寡婦控除/ひとり親控除
- 両方満たせば両方適用(離婚の場合は1を不可とする)
所得税と住民税で判定結果が異なるケース:
配偶者が源泉徴収される退職所得を持つ場合、所得税と住民税で配偶者の合計所得金額が異なり、配偶者控除/配偶者特別控除の適用可否や控除額区分が変わるケースがある。 → 所得税と住民税
扶養控除
→ 扶養控除
- 「他の所得者が控除を受ける」選択時に、扶養手当への影響がありうる旨を案内する
「誰が控除を受けるか」の選択:
- 同一人物が複数の申告者の控除対象候補になりうる(ただし実際に控除を受けるのは1人のみ)
- 「誰が控除を受けるか」の選択をデータモデルで表現する必要がある
重複控除の禁止バリデーション:
- 同一人が複数の納税者の控除対象になることはできない
- 同一テナント内: システムで検出可能
- テナントをまたぐ場合(親子が別の会社に勤務): システム的な自動検証は困難。申告者の自己申告に依拠する
- 例外: 年の途中で死亡した納税者の控除対象者は、別の納税者の控除対象にもなれる
所得税と住民税で判定結果が異なるケース:
扶養親族・特定親族が源泉徴収される退職所得を持つ場合、所得税と住民税で合計所得金額が異なり、扶養控除・特定親族特別控除・障害者控除の適用可否が変わるケースがある。 → 所得税と住民税
障害者控除
→ 障害者控除
記載場所のビュー処理:
紙の様式上、障害者に関する情報の記載場所が条件によって動的に変わる(源泉控除対象配偶者に該当しない障害者配偶者、16歳未満の非居住者扶養親族が障害者の場合など)。データモデル上は家族構成員で親族の情報(居住区分・障害者区分・送金額等)を一元管理するため、出力時にどの欄に記載するかはビュー(View)の問題として処理する。 → 「紙の様式 ≠ データモデル」原則の具体例。declaration-forms.md 参照
同居データの設計:
同居特別障害者と同居老親等では「同居」の相手方の範囲が異なる。 → 「同居」の定義の違い — 同居特別障害者 vs 同居老親等
- 「同居しているか?」という単一のフラグでは不十分。「誰と同居しているか」 を事実として記録する
- 入院中か入所中か の区別も必要(入院は同居扱い、入所は非同居扱い)
- 家族構成員 / 親族関係に同居関係のデータを持ち、同居特別障害者と同居老親等の判定は 別々の判定関数 で行う
手帳申請中のステータス:
- 障害者区分の入力において「手帳申請中」のステータスを選択可能にする
- 申請中の場合は、申請している手帳の種類と想定される等級を入力させ、仮の障害者区分を適用する
- 手帳交付後に確定情報で更新するフローが必要
- 精神障害者保健福祉手帳・療育手帳の申請中は、この仮扱いの対象外であることをバリデーションで制御する
特定親族特別控除
→ 特定親族特別控除
他の所得者が控除を受けるケース:
特定親族特別控除は本人の合計所得金額に対する制限がないため、高所得の申告者では配偶者特別控除が受けられない場合でも、他の所得者が特定親族特別控除として控除を受けられるケースがある。 → 詳細は 控除を受ける所得者 参照
寡婦控除
→ 寡婦控除
- 事実起点の設計思想に基づき、離婚/死別の区分を入力項目に含める
- 離婚の場合に扶養親族の有無を自動バリデーション
- 死別の場合は扶養親族不要を正しく判定
- 紙の様式(チェックのみ)よりも正確な控除判定が可能
- 寡婦控除のデータモデルには離婚/死別区分を持つ(紙の様式ではチェックのみだが、要件が異なるため判定に必要)
- 事実婚の有無: 自己申告形式。住民票ベースの判定は本人の責任であり、詳細はシステムで保持しない
ひとり親控除
→ ひとり親控除
- 離婚/死別/未婚の区別は判定に不要(いずれも同一要件)
- 事実婚の有無: 寡婦控除と同じ方針(自己申告、詳細はシステムで保持しない)
勤労学生控除
→ 勤労学生控除
所得の種類別管理の設計検討:
- 現行 XML 様式は「給与所得」+「その他所得」の2区分に簡略化されている
- しかし勤労学生控除の判定には所得の種類(勤労/不労)の区分が必要
- 所得の種類別管理をデータモデルに持たせるかは要検討:
- 全従業員に10種類の内訳を求めるのは入力負荷が高い
- 種類別に持てば将来の税制改正対応がしやすい
- 事実起点の設計思想からは種類別に持つ方が整合的
社会保険料控除
→ 社会保険料控除
- 給与天引き分は給与データから自動取得(申告書への記載不要)
- 本人申告分は保険料控除申告書からの入力が必要
- 計算が最も単純(全額控除、上限なし)
- 新旧制度の区別や有利選択は存在しない
小規模企業共済等掛金控除
データモデル:
- 4種の掛金種別を区別する属性を持つ(申告書の4欄に対応)
- 同一種別で複数レコードを許容する(制度上複数契約が存在する可能性に対応)
- 合算は出力時(様式生成・控除額計算時)に行う
- 支払方法(給与天引き/個人払込)を区別する属性を持つ
- 給与天引き分は給与データからの自動取得を想定するが、記録として保持する
計算ロジック: 控除額 = 全掛金の年間額の合計(全額控除、上限なし)
バリデーション:
- 年間掛金額は0以上(マイナスは発生しない。社会保険料控除と同様、支払額そのもの)
- 各掛金種別の合計が制度上の拠出上限を超えていないかの警告(エラーではなく警告)
証明書の扱い:
- 個人払込の場合、掛金払込証明書の添付が必須(金額の多少にかかわらず)
- 電子的控除証明書(XML: TEG850)での自動取込みに対応
- 企業型DC・事業主払込iDeCo は給与天引きのため証明書不要
→ 全体のエンティティ構成は 控除 参照
生命保険料控除
→ 生命保険料控除
バリデーション方針: 控除証明書が発行されている時点で税制適格要件を満たしていることが保証されているため、バリデーションは補助的な位置づけ。電子的控除証明書からの自動取込み時は適格性チェック不要。
マイナス契約の選択的不申告リスクへの対応:
- 雇用主に確認義務がないことと同等のリスクレベルを許容する(申告内容の網羅性は検証しない)
- 同一区分・同一制度の契約が複数ある場合は「同じ区分の契約がすべて入力されているか確認してください」等の注意文言を表示し、合算義務を周知する
- 電子的控除証明書や団体保険データでの取込みを推奨し、構造的にリスクを軽減する
マイナス金額の入力 UI: モバイル端末の数字キーボード(inputmode="numeric" 等)ではマイナス記号が表示されない機種がある。チェックボックス等でマイナスを示す方式(金額は絶対値で入力し、符号をトグルで切り替える)が入力負荷が低い。
マイナス金額のデータモデル: 支払保険料等の金額(支払額から剰余金・割戻金を差し引いた金額)はマイナスになりうる。支払額と剰余金の内訳は申告に不要な情報であり、申告書に記載するのは差引後の金額のみ。
控除証明書の添付省略: 旧生命保険料(一般の生命保険料のうち旧制度)に限り、1契約の保険料が9,000円以下の場合は証明書不要。証明書不要のため架空契約の申告が理論上可能だが、性善説で申告者の申告を信じるスタンスとする(紙の年末調整と同等)。
続柄: 保険料控除の文脈では収集不要(現行様式で不要化済み。家族構成員には人的控除判定目的で続柄データが存在するが、保険料控除とは独立)。
エンティティ分割: 3区分を別エンティティとする。
生命保険料控除
├── GeneralLifeInsurance(一般の生命保険料、新旧あり)
├── NursingCareInsurance(介護医療保険料、新制度のみ)
└── PersonalPensionInsurance(個人年金保険料、新旧あり、支払開始日あり)地震保険料控除
→ 地震保険料控除
旧長期損害保険料の経過措置への対応:
- 現時点では旧長期損害保険料に対応する
- 将来、経過措置が終了し地震保険料のみになることを想定したデータ構造にする
- 旧長期損害保険の有無を示すフィールドは Optional として設計し、経過措置終了後はフィールドを非表示にするだけで対応可能にする
エンティティ設計:
EarthquakeInsuranceDeduction(1契約 = 1レコード)
→ 地震保険料額と旧長期損害保険料額の両方を保持
→ 同一契約にどちらか一方のみの場合は他方を 0 とする
→ どちらで控除を受けるかの選択(自動有利判定あり)所得金額調整控除
→ 所得金額調整控除
税額計算エンジン:
- 年税額計算パイプラインの 所得控除合計の前 に適用される独立したステップ
- 23歳未満の扶養親族の有無は家族構成員データから自動判定
- 特別障害者の判定は障害者控除のロジックと共有
- 控除額の計算自体は単純((収入−850万円)×10%、上限15万円)だが、適用要件の判定が複雑
データモデル:
- 所得金額調整控除申告書(NTAAPP007)のデータは独立して保持する必要がある
- 扶養控除等申告書(NTAAPP001)の扶養親族データと 重複する情報 が含まれるが、別の法的根拠に基づく別の申告書であるため独立管理
- 「他の所得者が控除を受ける扶養親族等」欄のデータも保持が必要(所得金額調整控除の重複適用の根拠)
重複適用の特殊性:
- 他の控除(扶養控除、配偶者控除等)は「同一生計内で一人の所得者のみ」が原則
- 所得金額調整控除はこの原則の 例外 であり、同じ扶養親族に対して複数の所得者が控除を受けられる
- バリデーションロジックで「扶養親族の重複」を排他チェックする際に除外する必要がある
- 同一テナント内の複数従業員の申告で、夫婦それぞれの申告で同一の子を所得金額調整控除の対象とするケースが発生しうる
住宅借入金等特別控除
- 調書方式・証明書方式のどちらにも対応する。データモデル上は「残高確認方式: 調書方式 | 証明書方式」のフラグで制御
- 調書方式の場合は年末残高等証明書の添付チェックをスキップするロジックが必要
- 3世代の様式差異を吸収するデータモデルが必要(居住開始年による区分数の違い、フィールドの有無)
- 連帯債務・借換え・居住用割合はそれぞれ年末残高を調整する計算ロジックが必要。特に居住用割合の端数処理(第4位切り上げ、90%以上→100%)は税計算コアに含める
- 調書方式と証明書方式で年末残高の取得経路が異なる → R8以降は調書方式でも返済計画表ベースとなり控除証明書の年末残高欄が空欄になる変更に対応が必要
- 控除しきれない残額の住民税への波及はスコープ要検討
- データモデル DM-404 住宅借入金等特別控除として既に定義