• #tax-assistant
  • #OCR
  • #receipt-to-shiwake
  • #マネーフォワード
  • #CSV
  • #Googleシート
  • #日記
開発tax-assistantメモ

OCR・データ取込パイプライン改善 -- 領収書136件バッチ処理とreceipt-to-shiwakeスキル構築

朝、未処理の領収書PDFが溜まったフォルダを開いたら、ファイル数が3桁に達していた。手作業で1件ずつ仕訳を切る未来が一瞬よぎって、パイプラインを先に整備する方向へ舵を切った。


receipt-to-shiwake スキルの新規作成

領収書PDFを読み取り、マネーフォワード仕訳形式でGoogleシートへ書き込むワークフローをスキル化した。

パイプライン概要

領収書PDF → OCR読み取り → 仕訳データ構造化 → Googleシート書き込み

個人事業主の経理を前提にしているので、以下のルールを組み込んだ。

  • 貸方科目: 一律「事業主借」。個人のカード・現金で立て替えた経費は全てこれに落ちる
  • 税区分: 「課税仕入 10%」のような形式でOCR結果から自動設定
  • 摘要欄: 元のPDFファイル名を含める。後からファイル名で検索すれば、レシート画像と仕訳が紐づく

スキルとして切り出したことで、「PDF投げて、シートに書き込んで」の一言で仕訳が完成する。


OCRプロンプト・スキーマの改善

税区分の自動取得を追加

OCR読み取り時に debit_tax_type フィールドを追加した。従来は読み取り後に手動で税区分を設定していたが、レシートの記載内容から自動判定するようにした。

enumは3種類に絞った。

課税仕入 10%     ... 標準税率
課税仕入 8%(軽減) ... 食料品・新聞等
対象外          ... 税金の支払い等

税率の判定根拠はレシートの税率表記や品目から推定する。コンビニのレシートなら8%と10%が混在するケースがあるが、合計金額に対する税率で判定している。

勘定科目に「租税公課」を追加

固定資産税や自動車税の領収書が出てきたタイミングで、OCRのenum定義とフロントエンドの勘定科目リスト(2箇所)に「租税公課」を追加した。


大量データ取込

領収書OCR: 136件

2回のバッチに分けて処理した。

バッチ件数結果
1回目73件全件成功
2回目64件 + 1件エラー64件成功
合計137件投入136件成功、1件エラー

エラーの1件は領収書ではなく、お悔みの礼状だった。OCRパイプラインが「これは領収書ではない」と判定して弾いた形。内容を確認した上で、Claude自身のOCR(PDFの直接読み取り)で手動対応した。

136件が自動で仕訳データになるのを眺めていると、手作業で1件ずつ入力していた頃には戻れないと感じる。

クレカCSVインポート: 144件

三井住友カードのCSV明細を取り込んだ。144件の利用明細がインポートされ、既存の仕訳ルールに基づいて勘定科目が自動設定された。


MF仕訳CSVエクスポート

取り込んだデータをマネーフォワード仕訳CSV形式でエクスポートした。/export-mf-journal コマンドで、日付ソート・連番振り直し・適用欄へのファイル名記載まで一括で処理される。

前回の改善(2/25)で仕込んだ自動化が、今回の大量データで初めて本番稼働した格好になる。136件 + 144件 = 280件の仕訳が、コマンド一発でCSVに落ちた。


CSVファイルのGit管理整備

エクスポートしたCSVファイルがGitリポジトリに混入していたことに気づいた。

対応内容

  1. .gitignore にCSVファイルのパターンを追加
  2. 既にGit追跡されていた21件のCSVファイルをキャッシュから除外(git rm --cached

CSVは生成物であり、ソースコードではない。リポジトリに入っていると差分が膨らむし、クライアントの取引データが含まれるファイルをリモートに置くのはセキュリティ上も望ましくない。早めに気づいて整理できた。


振り返り

一日の作業を数字で振り返ると、領収書136件 + クレカ144件 = 合計280件のデータが仕訳として取り込まれた。receipt-to-shiwakeスキルを先に作ったことで、残りの領収書をまとめて流せた。

OCRスキーマに debit_tax_type を追加した判断は正解だった。後から手動で税区分を設定する作業が消えて、パイプラインの出口で仕訳がほぼ完成品として出てくる。「あと一手間」を減らすことが、大量データ処理では効いてくる。

エラーだった礼状の1件は、パイプラインの「領収書以外を弾く」挙動が正しく動いた証拠でもある。想定外の入力が混ざったときにサイレントに誤データを生成するよりも、エラーで止まるほうがはるかに安全だ。