tax_typeにnon_taxableとtax_freeという2つの区分を用意していたが、これは自分が消費税の実務をちゃんと理解しないまま雑に作った区分だった。改めて消費税の仕組みを勉強し直したら、「非課税」「不課税」「免税」という3つの異なる概念があることがわかり、2つの区分では表現しきれていなかったので整理した。
このアプリが主に想定している一人親方のような個人事業主は、非課税の経費はあっても非課税の売上を持つことはほとんどないので、実務上は今まで通りnon_taxable(不課税)だけ押さえておけば大きく困ることはない。
それでも、区分としてきちんと分けておかないと今後の実装で困る、という理由で今回整理した。
何がわかったか
自分が最初にnon_taxableという名前を付けたときは、「消費税がかからない取引」を全部まとめて1つの区分で扱えばいいと思っていた。しかし消費税の実務では、「消費税がかからない」の中にも性質の異なる複数の概念がある。
- 非課税: 課税対象の取引ではあるが、性質上消費税を課さないとされているもの。土地の譲渡や保険料など。課税売上割合の計算には算入される。
- 不課税: そもそも消費税の課税対象になる「取引」ではない。現金の入出金や資産の内部振替など。課税売上割合の計算にも含めない。
- 免税: 課税対象の取引で、税率が0%になるもの。典型例は輸出売上。
non_taxableという1つの区分でこれを全部まとめてしまうと、将来的に課税売上割合の計算のような、非課税と不課税を区別しないといけない集計機能を作るときに詰む。実装を進める前にこの違いに気づけたのは収穫だった。
3つに分離
exempt(非課税)out_of_scope(不課税)zero_rated(免税)
これまでnon_taxableを使っていた箇所(DepreciationServiceの減価償却仕訳、InventoryClosingServiceの棚卸仕訳、TransactionRegistrarのデフォルト税区分など)は、内容を見直すと実質すべて「取引として消費税の対象外」のケースだったので、out_of_scopeに置き換えた。
名前を変えると影響範囲が広い
区分名を変えるだけの変更のはずが、実際の差分は14ファイルに及んだ。FreelancerBookTestやScenarioRulesTestのような、具体的な取引シナリオをテストしているファイルほど、文字列リテラルで'non_taxable'と書いていた箇所が多く、置き換えが手間だった。今後同じような名称変更をするときは、テスト側でも定数(JournalEntry::TAX_TYPE_OUT_OF_SCOPEのような)を使うようにした方が、次回の一斉置換が楽になりそう。