消費税のサマリ画面と、申告用の集計ロジックを作った。インボイス制度の経過措置、少額特例、税率ごとの積み上げ計算まで含んでいて、正直かなり手強かった。
JournalEntryに消費税区分を持たせない
通常の会計ソフトは、仕訳(JournalEntry)1行ごとに「課税仕入・8%」「課税売上・10%」のような消費税区分をユーザーに設定させることが多い。Solerではそれをやりたくなかった。仕訳の入力段階で消費税の区分まで正しく選ばせるのは、簿記に慣れていないユーザーには負担が大きいし、区分の設定ミスがそのまま申告額のミスに直結する。
「課税仕入か課税売上か」は、その仕訳がどのAccountに紐づいているかを見れば自動的に決まる話で、ユーザーに選ばせる情報ではないと考えた。ユーザーが入力するのは8%か10%かという税率区分だけにして、課税仕入・課税売上の区別はソフト側がAccountの種類から判定する。
同じ理由で、仕訳を登録する時点で「控除」という概念そのものも出したくなかった。控除できるかどうか、何%控除できるかは、記帳のタイミングでユーザーが気にすることではなく、申告時の集計ロジックが後から解決すればいい話だと考えている。記帳時に大事なのは税率(8%か10%か)だけで、控除計算はその先の話として完全に切り離した。
「経過措置の判定はソフトの仕事」という思想
インボイス番号を持たない取引先からの経費・仕入れは、免税事業者からの仕入れとして経過措置(一定割合だけ控除可能)の対象になる。ここで決めたのは、経過措置の判定や控除割合の計算をユーザーに意識させないという方針。ユーザーがやることは、消費税の税率区分(0% / 8% / 10%)と仕入れ先を入力するだけにして、そこから先の「この取引先はインボイス登録済みか」「経過措置は何%の期間か」といった判定はすべてソフト側で計算する。
裏を返すと、この計算は取引先(Counterparty)のインボイス登録番号情報に依存する。つまり、仕入れ先情報を入れていない取引には経過措置が正しく反映されない。これは実務上ネックになる可能性があると思っていて、「仕入れ先の入力を省略したい」というニーズが出てきたら、また調整することになりそうだと今から予想している。
もう一つ助かったのが、「取引先のインボイス登録状態が後から変わったときの遡及修正」を考えずに済んだこと。ある取引先が「登録していたが、後で登録をやめた」というケースでは、同じ取引先でも支払日によってインボイスあり/なしの扱いが変わる。ここを「現在の登録状態」だけで判定すると、状態が変わるたびに過去の取引の経過措置判定がまとめてズレてしまう。
Counterpartyはもともと取引相手(Counterparty)機能を追加のときに、適格事業者かどうかをboolean一発ではなくCounterpartyQualificationEventという履歴で持つ設計に変えていた。今回の消費税サマリでは、その履歴をqualificationStatusAt(Carbon $date)で「その支払日時点でどちらだったか」を引く形でそのまま活用できた。同じ取引先であっても「この支払日はインボイス登録あり」「この支払日は登録なし」という判定が支払日ごとに変わり、取引先の登録状態が後から変化しても過去の仕訳を拾い直す必要がない。
2026/10/1の制度変更を見据えて、入力の悩みを減らす
経過措置の割合や少額特例の基準額は、2026年10月1日でまた変わる。制度がこれだけ動く以上、「今の制度でユーザーが何%控除できるか」を入力時に判断させるのは筋が悪いと考えた。ユーザー側の入力を「税率区分」と「取引先」だけに絞り、控除割合の計算・期間ごとのMatrix分割はすべてソフトに任せることで、制度が変わってもユーザーの入力体験は変えずに済む。
1万円以上の経費・仕入れだけをドリルダウンで見られるようにしたのもこの思想の延長。少額特例で1万円未満はそもそも判定不要になるので、確認すべき対象を絞り込める。ユーザーがやることは、一覧を眺めながら「支払先が間違っていないか」をチェックするだけでよくなる、というのを目指した。
少額特例(1万円未満の課税仕入れはインボイス保存なしで全額控除できる、という経過措置)は、今回実装するまで存在を知らなかった。制度を作った側の意図としては「少額の取引まで一律にインボイス管理を求めると事務負担が大きすぎる」という救済措置なんだろうと理解しているが、こういう細かい特例が消費税にはまだいくつも埋まっていそうで、実装しながら勉強になった。
Summaryの集計軸をどう区切るか
もう一つ悩んだのが、サマリ画面で経過措置や控除の状況をどの軸で区切って見せるかだった。最初に検討したのは、税率を主軸にする案。
- 8% – インボイスあり / なし
- 10% – インボイスあり / なし
税率で大きく分けてからインボイス有無で分ける、という発想だが、これだと少額特例(インボイス有無を問わず全額控除できる特例)がどちらの枝にも顔を出すことになり、区分がねじれる。結局、少額特例を独立した第一階層として切り出す形にした。
- 少額特例
- インボイスあり / 8%・10%
- インボイスなし / 8%・10%
少額特例だけ他と扱いが違うのは今も少し引っかかっていて、この分け方がベストかはまだ自信がない。ひとまずこれで動かしてみて、実際に使いながら軸の切り方を調整していくつもりでいる。
控除ありなしの比較
集計では、経過措置による控除を適用した場合と、適用しなかった場合の両方の税額を出せるようにした。控除の有無でどれだけ納税額が変わるかを見比べられないと、経過措置の計算が正しく効いているのかをユーザー自身が検証できない。ソフト側で自動計算する範囲を広げるほど、その計算結果を人間が検算できる手段を残しておく必要があると考えている。