税務アシスタント外貨建てレシート対応 -- アルゼンチンペソの$問題から始まった一日
発端: ペソも「$」を使う
レシートOCRの結果を眺めていたら、金額欄に $ がついたレシートが混ざっていた。USドルだろうと思って流しかけたが、店名を見るとブエノスアイレスの飲食店。アルゼンチンペソだ。
ペソもドルも通貨記号は $。Gemini OCRが返してくる金額フィールドには $1,500 としか入っていない。これがUSD 1,500なのかARS 1,500なのか、記号だけでは判別できない。そのまま円換算すると桁が2つずれる。
手が止まった。
通貨記号から自動判別する仕組みを作り込むことも考えたが、今回は見送った。通貨コードのない $ を正確に判定するにはOCRの文脈解析が必要で、工数に見合わない。代わりに、「このレシートは外貨建てかもしれない」というフラグを人間が確認できる仕組みを作ることにした。
is_foreign_currency フラグのフルスタック実装
シンプルな真偽値フラグを、4つのレイヤーに通した。
1. Gemini OCRスキーマに外貨判定フィールドを追加
OCRのレスポンススキーマに is_foreign_currency: boolean を追加。Geminiが画像から読み取る際に、日本円以外の通貨記号や外国語表記を検出したら true を返すようにプロンプトを調整した。
# OCRスキーマに追加したフィールド(抜粋)
"is_foreign_currency": {
"type": "boolean",
"description": "日本円以外の通貨で記載されている場合true"
}
Geminiの判定精度に全幅の信頼は置けないが、明らかに外国語で書かれたレシートは拾える。拾い漏れは人間がUIで補正する想定。
2. DBマイグレーション
レシートテーブルにカラムを追加。デフォルトは 0(日本円)。
ALTER TABLE receipts ADD COLUMN is_foreign_currency INTEGER DEFAULT 0;
3. バックエンドAPI
4つの関数を修正した。
- insert: OCR結果の
is_foreign_currencyをDBに書き込み - get_all: レスポンスにフラグを含めて返却
- update: フロントエンドからの更新を受け付け
- convert: MF仕訳CSV変換時にフラグを参照(外貨レシートに注記を付与)
既存のCRUD関数にカラムを1つ足す作業なので、各関数の修正自体は数行で済んだ。
4. フロントエンドUI
ReceiptForm.vue にチェックボックスを追加した。
<input type="checkbox" v-model="form.isForeignCurrency"
:disabled="receipt.status === 'confirmed'" />
<span>外貨建て</span>
確定済みレシートではチェックボックスを disabled にして、誤操作を防いでいる。
外貨レシートの視覚的フィードバック
チェックをONにすると、レシートカードにオレンジのボーダーと「要チェック」バッジが表示される。一覧画面をスクロールしたとき、外貨レシートがオレンジの枠で囲まれて目に飛び込んでくる。
.receipt-card.foreign-currency {
border: 2px solid #f59e0b;
}
視覚的に目立たせることで、確認漏れを防ぐ狙い。月次の経理作業でレシート一覧を流し見するとき、オレンジが目に入ったら立ち止まって円建て金額を確認する、という運用フローを想定している。
運用フロー
今回の実装は「フラグを立てる」ところまで。通貨種別の自動識別や為替レート取得は含めていない。
想定している運用は以下の通り。
- レシートをOCRにかける。Geminiが外貨と判定したら自動で
is_foreign_currency = true - 一覧画面でオレンジ枠のレシートを目視確認
- クレジットカード明細の円建て金額と突合し、正しい金額を手入力
- 確認が済んだらレシートを確定
クレカの円建て決済額が「正」で、レシートの外貨金額は参考値。為替レートを自前で取得して自動換算する仕組みは、需要が出てきたら別途検討する。
振り返り
真偽値フラグ1つを4レイヤーに通す作業は、各レイヤーの修正量は小さいが、動線を端から端まで確認する必要がある。OCRスキーマ → DB → API → UIの順に積み上げて、最後にE2Eで「チェックを入れてリロードしても状態が保持されるか」を確認して完了。
アルゼンチンペソの $ 問題は、通貨記号がグローバルに一意でないという当たり前の事実を突きつけてきた。$ はアメリカドル、カナダドル、オーストラリアドル、メキシコペソ、アルゼンチンペソなど20以上の通貨で使われている。記号だけで通貨を特定しようとするのは設計として破綻する。
今回は「自動判別しない」という判断を選んだ。フラグだけ立てて人間に委ねる。精度の怪しい自動判別より、確実に目に留まるUIのほうが実務では信頼できる。