勘定科目マスターDB化の実装記録
概要
tax-assistantプロジェクトで、勘定科目をDBで管理する機能を実装した。これまでフロントエンドにハードコードしていた勘定科目一覧を、マネーフォワード会計のCSVエクスポートからインポートできるようにした。
実装の背景
以前の実装では勘定科目の選択肢がフロントエンドに固定で埋め込まれていた。クライアントごとに使う勘定科目は異なるし、同じ勘定科目でも税区分が違うケースもある。運用を続けていく上でDB管理は必須だった。
Phase 1: DBスキーマ作成
account_categoriesテーブル
CREATE TABLE IF NOT EXISTS account_categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
sub_account TEXT,
tax_type TEXT NOT NULL,
category_type TEXT NOT NULL,
mf_category TEXT,
display_order INTEGER DEFAULT 0,
is_active INTEGER DEFAULT 1,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
UNIQUE(name, sub_account, tax_type)
);
設計のポイント
UNIQUE制約を (name, sub_account, tax_type) の3カラムに設定した理由
当初は (name, sub_account) で一意にしようとした。しかし実務では「会議費・課税10%」と「会議費・非課税」を両方使うケースがある。同じ勘定科目名・補助科目でも税区分違いで複数登録できないと困る。
Codexレビューで「税区分の違いで同名科目を分ける運用は想定していますか?」と聞かれて気づいた。
category_typeの分類
pl_expense ... 損益計算書・費用
pl_revenue ... 損益計算書・収益
bs_asset ... 貸借対照表・資産
bs_liability ... 貸借対照表・負債
bs_equity ... 貸借対照表・純資産(その他)
個人事業主の場合、「純資産」より「その他」と呼んだほうが実態に近い。事業主貸・事業主借などが入る。
mf_categoryカラム
マネーフォワードの「分類」(現金及び預金、売上債権、有価証券...)をそのまま保持する。UIのミラーカラムで中項目として使うため。
CSVインポート元
C:\Users\numbe\Git_repo\tax-assistant\apps\ledger-viewer\data\indiv_items_download_ex01.csv
マネーフォワード会計からエクスポートしたサンプル美容室の勘定科目マスター。カラム構造は以下の通り。
| カラム | 内容 |
|---|---|
| 決算書科目 | 貸借対照表 or 損益計算書 |
| 分類 | 現金及び預金、売上債権など |
| 勘定科目 | 勘定科目名 |
| 補助科目 | 補助科目名(空の場合あり) |
| 税区分 | 課税10%、非課税など |
| 並び順 | 表示順(1か空が多い) |
display_orderの扱い
元CSVの「並び順」は1か空ばかりで連番になっていなかった。CSVの行順(読み込み順)をそのままdisplay_orderとして使用。これで「現金」から始まる自然な並び順になる。
Phase 2: API実装
エンドポイント
| メソッド | パス | 用途 |
|---|---|---|
| GET | /api/account-categories/dropdown | ドロップダウン選択用一覧 |
| GET | /api/account-categories/{id} | 詳細取得 |
| DELETE | /api/account-categories/{id} | 物理削除 |
ドロップダウン用APIはフィルタ・ソートに対応。?category_type=pl_expense のようにカテゴリで絞り込める。
削除の方針
当初は論理削除(is_active=0)で設計していた。しかし実装中に「無効科目も表示」のチェックボックスが必要になり、UIが複雑になる。
結局、無効科目は取り込まない方針に変更。削除は物理削除とした。マスターデータは再インポートすれば復元できるので問題ない。
Phase 3: MatrixView.vueの改修
月次推移表でPL科目とBS科目を表示している。これまではハードコードで分類していたが、APIから取得した勘定科目マスターのcategory_typeで動的に分類するよう変更。
// 勘定科目マスターを取得
const { data: accountCategories } = await useFetch('/api/account-categories/dropdown')
// category_typeでPL/BS分類
const plCategories = computed(() =>
accountCategories.value?.filter(c =>
c.category_type === 'pl_expense' || c.category_type === 'pl_revenue'
) ?? []
)
Phase 4: WebUI実装
ミラーカラムスタイルのレイアウト
4カラム構成を採用。
| カラム | 内容 |
|---|---|
| 1列目 | 大分類(BS / PL) |
| 2列目 | 中分類(資産/負債/その他 or 収益/費用) |
| 3列目 | 小分類(MFの分類をそのまま使用) |
| 4列目 | 勘定科目一覧 |
勘定科目一覧の表示形式
マネーフォワードのUIを参考に、同じ勘定科目名をグループ化して縦に連結表示。補助科目がある場合はL字型の連結線で接続。
┌──────────────────────────────────────────┐
│ 勘定科目 税区分 補助科目 削除 │
├──────────────────────────────────────────┤
│ 普通預金 対象外 - 🗑 │
│ └──────────────── みずほ銀行 🗑 │
│ └──────────────── 住信SBI 🗑 │
│ 売掛金 課税10% - 🗑 │
└──────────────────────────────────────────┘
キーボードナビゲーション
←→キーで小分類を順番に巡回できる。「1/23」のような位置表示付きのナビゲーションバーも実装。
/import-accounting-master スラッシュコマンド
Claude Codeから直接インポートを実行できるスラッシュコマンドを作成。
# 使用例
/import-accounting-master
実行すると、指定のCSVファイルを読み込んでaccount_categoriesテーブルにUPSERT。既存データは上書きされる。
Codexレビュー12回の経緯
計画段階でCodex(GPT-5.2)にレビューを依頼した。12回のレビューを経て計画品質を向上させた。
主な指摘と対応
| 回 | Critical | High | 主な指摘 |
|---|---|---|---|
| 1 | 0 | 2 | 入出金の管理方法、WebUIでの設定変更可否 |
| 3 | 1 | 2 | テナントスコープがない(個人用アプリなので不要と回答) |
| 9 | 3 | - | tax_typeをNOT NULLに、初期投入をPhase 1に |
| 12 | 0 | 0 | Critical/High解消 |
印象的だった指摘
「税区分の違いで同名科目を分ける運用は想定していますか?」
これはCodexの確認質問だったが、実務では普通にある。会議費で課税10%と非課税を使い分けるケースなど。UNIQUE制約を (name, sub_account, tax_type) に変更するきっかけになった。
「direction(入金/出金)と必須勘定科目の整合性をAPIバリデーションで担保すべき」
帳票タイプマスター(別計画)との連携で、入金時と出金時でデフォルト勘定科目が異なる。Pydanticのバリデーションでこれを担保する設計を追加。
実装で修正したファイル
| ファイル | 内容 |
|---|---|
sql/account_categories.sql | テーブル定義 |
src/migrations.py | マイグレーション追加 |
src/db/account_categories.py | DB操作関数 |
src/server/routers/account_categories.py | APIルーター |
scripts/import_account_master.py | CSVインポートスクリプト |
.claude/commands/import-accounting-master.md | スラッシュコマンド |
frontend/app/api.ts | API型定義追加 |
frontend/app/components/MatrixView.vue | 動的分類対応 |
frontend/app/components/AccountMasterView.vue | マスター管理UI |
tests/test_account_categories.py | ユニットテスト |
テスト
CSVインポートのユニットテストとAPIフィルタ/ソートのテスト、キーボードナビゲーションのテストを作成。全59テストがパス。
今後の課題
- 帳票タイプマスター(
document_typesテーブル)との連携 - 勘定科目マスターを使った仕訳ルールの自動提案
勘定科目マスターDB化が完了したことで、帳票タイプマスター管理機能の実装に着手できる状態になった。