セットアップ時に自動生成される勘定科目・補助科目だけでは、事業を続けるうちに足りなくなる。ユーザーが自分の事業に合わせて勘定科目や補助科目を後から追加できるようにした。
入口は2つのメソッド
BusinessUnit::addCustomAccount(type, accountName, subAccountName = null)Account::addCustomSubAccount(subAccountName)
前者は勘定科目そのものを追加し、あわせて初期の補助科目を1件作る。後者は既存の勘定科目に補助科目だけを追加する。
addCustomAccount()の第3引数(補助科目名)は省略可能で、省略すると勘定科目と同名の補助科目が自動で作られる。既存のcreateAccount()(セットアップ時のデフォルト科目作成)が「デフォルト科目名のリストにあればそのリスト分、なければ科目名と同名の補助科目を1件」作っていたのと同じルールを、個別追加のときにも踏襲した形になる。実際、この共通ロジックはAccount::addCustomSubAccount()という1つのメソッドに切り出して、createAccount()側もこれを呼ぶようにリファクタリングしている。
同名チェックはどこでやるか
addCustomAccount()では、追加しようとしている科目名が同一BusinessUnit内に既に存在する場合はInvalidArgumentExceptionを投げるようにした。事業体単位でのユニーク制約はDB側にはないので、アプリケーション層でチェックしている。
一方、補助科目名の重複はDBのユニーク制約(account_id + name)に任せている。ここは非対称だが、「同じ勘定科目に同名の補助科目を作る」というのは単純な一意制約違反として表現できるのに対して、「勘定科目名が事業体内で重複していないか」は事業体をまたいだクエリが必要になるため、素直にアプリケーション層でガードする方が扱いやすかった。
マニュアルを増やした
この機能はtinker経由での運用を想定しているので、manual/accounts.mdに使い方を書いた。既存のmanual/setup.md(初期セットアップ)からもリンクを張って、「セットアップ後に科目を足したくなったらこっち」という導線を作っている。