金額計算の設計に挑む

cassetteの延澤です。 今回はみんなが大好きなお金、、の設計について書いていきます。

きっかけ

皆さんは金額を扱うアプリケーションを構築したことがありますか?
私は何だかんだ最近までお金を扱うアプリケーションを構築したことがあまりありませんでした。理由とすると金額を扱うシステムは専門の部署・人が行うことが多かったので既に構築されていることが多かったです。しかし、最近になって開発することになって少し知見が貯まったので折角なのでを書いておきます。

お金を扱う難しさ

一番難しいと感じたのは後方互換を残すことです。例えば、過去にユーザーに領収書・請求書を発行した場合、将来のシステム改修で過去の金額がズレることは避けなければいけません。また、決算においても売上・消費税の計算がズレるのはよろしくありません。
しかし、ユーザーの要望を満たすために決済手段は増えるし、様々な割引きプラン設定が金額計算をどんどん難しくさせます。そして気づいた時にに決済・会計ロジックはかなり複雑となり工数の増加を引き起こします。そして、最終的にズレる金額と対する早急な調査作業。。書いてて疲れてしまいました。

お金を不変として扱う

例えば、売上を1000円計上する場合はDBのカラムに格納します。そして、税率も同時に保存しておくと良いです。

売上 税率
1000 8

単純に定数として税率を設定していた場合、いつからその税率が適用されたのかが分かりにくくなるからです。それを回避するために同時に適用した税率も保存しておくことで後の計算をしやすくなります。また、全ての計算した金額も入れておきます。

税抜き 税率 税込み 割引金額 最終価格 手数料率 作成日時
1000 8 1080 500 580 20 2018-09-01 15:00:00

以上のように割引金額の計算ロジックや手数料率の計算は変更の入りやすい箇所でもあるので、その時の適用された金額や料率も格納しておきます。そして金額を表示する際はプログラムでごちゃごちゃ計算せずに素直にDBのカラムに保存してある金額を表示するほうがシンプルで楽です。 なので金額計算においてはdryで書くのではなく、毎回計算した値をDBに持っておくことで後で計算ロジックが変わっても過去のデータの考慮が少ないです。 *1

あと、金額計算を確認できる機能を管理画面に設置していると運用も楽になります。 また細かいことを言うと売上をいつ計上するのかという日付も会計上重要ですがここでは割愛します。

まとめ

販売管理システムは経験の差が出やすい箇所だなと感じました。
最新技術のキャッチアップは若手が有利ですが、こういう複雑で重要なビジネスロジックを構築できることはシニアエンジニアの強みでもあります。

*1:因みに割引金額が適用されるのが税抜き前に適用するのか税込みに適用するのか絶対に確認しておきましょう。