

【設計】電子帳簿保存法の検索要件を「ファイル名規約」だけで満たす — DB を作らないという選択(確定申告自動化 第2回)
YYYYMMDD_金額_取引先.pdf というファイル名規約だけで十分です。なぜそれで成立するのか、どこが限界なのかを整理します。はじめに
第 1 回で「証憑の正本は receipts/ に置く」と書きました。ではその中身をどう管理するか。
電子帳簿保存法は、2024 年から電子取引データの電子保存を義務化しました。その際の要件のひとつが検索要件です。
これをエンジニアが読むと、反射的にこう考えます。
-
メタデータを持つ SQLite を置こうか
-
いや、索引用の CSV を並べておけばいいか
-
いっそのこと検索画面を作るか
しかし、このプロジェクトでは ファイル名規約だけで満たす設計にしました。この判断の根拠を書いておきます。
この記事でわかること
-
電帳法の検索要件をファイル名だけで満たす具体的な規約
-
なぜ DB を作らないと判断できるのか(規模の見積もり方)
-
規約を決めるときに悩む、日付・金額・取引先の定義問題
-
ファイル名規約の限界と、超えたときの移行先
対象読者
-
電帳法対応を自分で組もうとしている個人事業主・小規模事業者
-
「要件を見たらとりあえず DB」となりがちなエンジニア
-
ファイル名規約でメタデータを背負わせる設計の実例を見たい人
前提条件
-
本記事は免税事業者(インボイス未登録)の個人事業主を想定
-
税務の最終判断は税理士・税務署に確認してください(筆者は税務の専門家ではありません)
-
規模感は「月 60 件前後、年 700 件程度の証憑」
1. 決めた規約
結論から。これだけです。
receipts/YYYY/MM/YYYYMMDD_金額_取引先.pdf
実例はこのようになります。
receipts/
2026/
01/
20260105_3254_エディタサービス.pdf
20260128_16048_AIサブスク.pdf
20260130_878_API利用料.pdf
02/
20260203_1050_コミュニケーションツール.pdf
規約の意図を要件と対応付けると、そのまま 1 対 1 です。
| 電帳法の検索要件 | 規約上の場所 | 検索方法 |
|---|---|---|
| 取引年月日 | 先頭 8 桁(YYYYMMDD)とディレクトリ階層 | ls / find / ファイラの検索窓 |
| 取引金額 | 2 つ目のブロック(税込整数円) | 同上 |
| 取引先 | 3 つ目のブロック | 同上 |
「日付範囲で絞り込む」も find receipts/2026 -name "202603*" で完了します。金額で絞るなら find . -name "*_3254_*"。
2. なぜ DB を作らないと判断できるのか
決め手は「このデータはどれだけ大きくなるか」です。
個人事業主の経費証憑は、多くても月 100 件・年 1,200 件程度です。青色申告の保存義務期間は原則 7 年なので、最大でも 1 万件オーダーに収まります。
1 万件のファイル名を全走査するコストは、現代のマシンでは実質ゼロです。
# 1 万件あっても体感瞬時
time find receipts -name "*_3254_*"
つまり、検索性能のために索引を持つ必要がない。ここを確認した時点で DB の動機は半分消えます。
残り半分の動機は「構造化データとして扱いたい」ですが、これも不要でした。集計や分析が必要になったときは、会計 SaaS 側にすでに構造化データがあるからです。取引・勘定科目・金額は会計側が正で、こちらは証憑ファイルの保管庫に徒します。
同じデータを 2 ヶ所で持つと、必ずずれます。役割を分けるのが正解でした。
3. 規約を決めるときに悩んだこと
ファイル名規約は単純に見えて、実は 3 つの定義問題を含んでいます。ここを曖昧にすると、数ヶ月後に自分で自分のファイルを探せなくなります。
日付はどれか
候補が 3 つあります。
-
領収書の発行日
-
カードの利用日
-
カードの引き落とし日
採用したのは「領収書の発行日(取引日)」です。法令の言う「取引年月日」に直接対応するからです。
ただしここに落とし穴があって、定期便系の購入は注文日とカード請求日が最大 2 週間ズレます。ファイル名の日付とカード明細の日付が一致しないので、突合は日付ではなく金額で行うと手順に明記しています。
金額はどれか
外貨建てのサブスクだと、領収書の額面は USD、カード明細は円換算後の金額です。しかも円換算額はカード会社のレートで決まるので、領収書だけ見ても確定しません。
規約は「税込円。カード明細の円換算額が確定していればそれを採用し、未確定なら明細突合時にリネーム」としました。帳簿に乗るのは円換算後の額なので、そちらに合わせるのが自然です。
取引先名はどこまで正確に書くか
正式な法人名を入れると、ファイル名が長くなりすぎて一覧性が落ちます。逆に略しすぎると同一性が失われます。
採用したのは「台帳(docs/vendors.md)に登録した短い識別名を使う」ルールです。ファイル名は検索キーとして機能すればよく、正式名称は領収書 PDF の中に書いてあります。
この割り切りは重要です。ファイル名は索引であって、台帳そのものではない。
4. ファイル名規約の限界
この設計が壊れるケースも書いておきます。
1 枚の証憑に複数の取引が乗る場合。 月次の利用明細のように、1 つの PDF に複数項目の内訳が入っていることがあります。このとき「金額」をファイル名に 1 つしか書けません。
対処としては「引落合計額をファイル名にし、内訳は会計側の取引で分ける」としています。証憑ファイルは 1 枚で、それを複数の取引に添付する形です。
同日・同額・同一取引先が複数ある場合。 ファイル名が衝突します。これは実際にはほとんど起きませんでしたが、起きたら末尾に識別子を足すルールにしています。
件数が桁違いに増えた場合。 月数千件になるなら、素直にメタデータ DB を持つべきです。ただしその規模になる頃には帳簿ソフトのファイルボックス機能を使う方が早いはずです。
5. 規約を「守らせる」仕組み
規約は決めただけでは守られません。このプロジェクトでは 2 つの仕掛けを入れています。
規約を CLAUDE.md に書く。 セッションのたびに読まれる場所に置くことで、保存先を間違えにくくなります。
保存後に中身を検証する。 ファイル名と PDF の中身が一致しているかを、テキスト抽出で機械的に確かめます。
from pypdf import PdfReader
text = PdfReader("20260726_918_サブスク.pdf").pages[0].extract_text()
assert "918" in text # 金額が一致するか
assert "July 26, 2026" in text # 日付が一致するか
この検証を入れておくと、違う月の領収書を拾ってきたミスがその場で止まります。実際、ポータルの一覧から PDF を落とすときに隔月のものを拾うミスは起こります。目視確認に頼ると見逃します。
Tips
-
要件を見たらまず「データはどれだけ大きくなるか」を見積もる。万件オーダーなら、検索のための索引はほぼ不要
-
同じデータを 2 ヶ所で持たない。会計ソフト側に構造化データがあるなら、こちらはファイル保管に徒する
-
日付の定義を最初に 1 つに決める。発行日 / 利用日 / 引落日は全部違う。法令の語句に寄せるのが無難
-
定期便は注文日と請求日がズレる。明細との突合は日付ではなく金額で行う
-
ファイル名は索引、台帳は別に持つ。取引先の正式名称をファイル名に詰め込まない
-
規約は「検証コード」とセットで初めて守られる。PDF のテキスト抽出で金額・日付を突合する
まとめ
-
電帳法の検索要件(取引年月日・金額・取引先)は
YYYYMMDD_金額_取引先.pdfでそのまま満せる -
個人事業主規模なら保存義務 7 年分でも 1 万件オーダー。検索索引のための DB は不要
-
集計・分析は会計 SaaS 側に任せる。同じデータを 2 ヶ所で持つと必ずずれる
-
規約の難しさはフォーマットではなく、日付・金額・取引先の定義を 1 つに決めるところにある
-
1 枚の証憑に複数取引が乗るケースが唯一の苦しいところ。合計額をファイル名にし、内訳は会計側で分ける
-
規約は決めるだけでは守られない。
CLAUDE.mdへの明記と、PDF テキスト抽出による検証をセットで入れる


