会計システムの帳票カテゴリ拡張と仕訳ビューア改善
朝イチで仕訳ビューアを開いたら、サンプルクライアントのクレカ明細409件がずらっと並んでいた。これを全部消して仮払金明細105件に差し替えるところから一日が始まった。帳票カテゴリの新設、確定サマリーの追加、バグ修正、UIリファクタリングと、仕訳ビューアを横断的に触った一日の記録。
帳票カテゴリに「仮払金明細」を新規追加
バックエンド・DB・フロントエンドの三点セット
新しい帳票種別 temporary_payment(仮払金明細)を追加した。変更箇所は3レイヤーにまたがる。
- DB: 帳票種別テーブルに
temporary_paymentレコードを追加 - バックエンド: CSVインポート処理で仮払金明細を受け付けるよう拡張
- フロントエンド: ドロップダウンやフィルタに仮払金明細の選択肢を追加
データ入れ替え
サンプルクライアントのクレカ明細409件を全削除し、仮払金明細105件をインポートした。既存の仕訳ルールとの紐付けも確認し、インポート後にビューア上で正しく表示されることを目視チェックした。
仕訳ビューアの確定状況サマリー
ヘッダーに確定/未確定の件数を表示
仕訳ビューアのヘッダー部分に、確定状況のサマリーを追加した。ビューアを開いた瞬間に「あと何件残っているか」が目に飛び込んでくる。
表示内容:
- 確定○件 / 未確定○件: 全体の進捗が一目でわかる
- クレカ・レシートの内訳: 帳票種別ごとの確定/未確定件数を表示
これまではスクロールしながら未確定の行を探していたが、サマリーがあることで作業の全体像を把握してから着手できるようになった。
帳票種別表示ロジックの修正
getSourceLabel関数のハードコード問題
帳票種別を表示する getSourceLabel 関数が、種別名をハードコードしていた。新しい帳票種別を追加するたびに関数を書き換える必要があり、追加漏れでラベルが「不明」と表示される問題が起きていた。
修正内容:
getSourceLabelをマスタデータ(docTypeMap)から動的に取得する方式に変更docTypeMapのフィルタロジックも見直し、全種別が正しくフィルタリングされるよう修正
// Before: ハードコード
const getSourceLabel = (type: string) => {
if (type === 'credit_card') return 'クレカ明細'
if (type === 'receipt') return 'レシート'
return '不明'
}
// After: マスタデータから取得
const getSourceLabel = (type: string) =>
docTypeMap.get(type)?.label ?? type
確定ボタンの不具合修正
MatchedRule型にidがない問題
確定ボタンを押すとエラーになるバグが発生していた。原因を追ったところ、DBベースの仕訳ルールでは id をキーにして行を特定するが、フロントエンドの MatchedRule 型に id フィールドが存在しなかった。
その結果、確定処理で row_number が undefined になり、バックエンドが「どの行を確定するのか」を特定できなかった。
修正:
MatchedRule型にidフィールドを追加- 仕訳ルールマッチング時に
idを伝播するよう修正 - 確定APIへのリクエストで
idを正しく送信
型定義のずれがランタイムエラーとして表面化する典型的なパターンだった。TypeScriptの型を信じきっていると、DB由来のデータとフロントの型定義の隙間に落ちることがある。
SearchableSelectコンポーネントの共有化
components/ui/ への移動
勘定科目の選択UIで使っていた SearchableSelect コンポーネントを、components/ui/ に移動して共有コンポーネント化した。
移動前は特定の画面に密結合していたが、帳票種別の選択や他の場面でも同じドロップダウン+検索UIが必要になり、共有化に踏み切った。
勘定科目選択UIの改善
勘定科目の選択ドロップダウンにテキスト入力でのフィルタリング機能を追加した。勘定科目は数が多い(100件超)ので、スクロールで探すのは現実的でない。先頭数文字を打つだけで候補が絞り込まれるようにした。
テスト
既存テスト18件が全パスすることを確認した。今回の変更は既存のテストケースに影響を与えなかった。
振り返り
一日を通して、仕訳ビューアの「使いにくさ」を一つずつ潰していった。確定サマリーを追加したことで、ビューアを開いた瞬間に残作業が見える。getSourceLabel のハードコードを消したことで、帳票種別を追加するたびにコードを探し回る手間がなくなった。MatchedRule のバグは、フロントの型定義とDBスキーマを突き合わせる作業を怠った結果だった。型を書いたら安心するのではなく、データの出どころまで追う癖をつける必要がある。
SearchableSelectの共有化は、2回目の利用シーンが出たタイミングで実行した。「3回使ったら共通化」とよく言われるが、UIコンポーネントは2回目で十分だと感じた。同じUIが別の場所に複製されると、片方だけ改善が入って挙動がずれる未来が見えたからだ。