結論:発注書・納品書・請求書の三点照合は、明細の粒度を発注書側に揃え、分割納品・分割請求を数量ベースで累積加算してから比較すれば、Claude Codeで正規化から突合、差異レポート作成まで仕組み化できる。
- 要点1:突合の基準は「発注書の明細行」に統一し、複数回の納品・請求は累積数量で比較する
- 要点2:差異は「機械的に自動承認してよいもの」と「人が必ず確認するもの」に線引きし、税区分・単価・送料の最終判断はAIに渡さない
- 要点3:適格請求書の登録番号は形式チェック(T+13桁)だけで済ませず、国税庁の公表サイトで実在を確認する
対象読者:経理・購買部門とAI活用を進める開発者・PM・経営企画
今日やること:直近1ヶ月分の請求書・発注書・納品書を1つのフォルダに集め、明細の粒度がどれだけ揃っているかをまず目視で確認する
「先月の請求、また数字が合わないんです」。製造業のクライアント(従業員数百名規模、月間の取引先は100社超)を支援していたとき、経理担当者からそう相談されたことがあります。
原因を辿ると、発注書の明細粒度と請求書の明細粒度がそもそも違う、納品が2回に分かれているのに請求は1回にまとまっている、送料だけが請求書に計上されている——といった「よくある食い違い」が積み重なっていました。Excelとにらめっこしながら関数で突合していた作業を、Claude Codeでどこまで仕組み化できるか。この記事では、その実装パターンを解説します。
事例区分:実装パターン解説
本記事は複数の現場でよく見られる請求書突合の課題を一般化した実装パターン解説です。登場する企業・数値は特定の実在案件を示すものではなく、実装を検討する際の試算・想定値として記載しています。
何を突合するのか——三点照合と四点照合
経理・購買の現場で「突合」と呼ばれる作業は、主に次の3種類の書類の数量・金額を照らし合わせる作業を指します。
- 発注書(PO) — 何を、いくつ、いくらで発注したかの記録
- 納品書 — 実際に何が、いくつ納品されたかの記録
- 請求書 — 取引先が請求してきた金額・明細
この3つを突き合わせるのが「三点照合」です。さらに、社内で検品・受入処理をした「検収データ」を加えて4つを突き合わせる場合は「四点照合」と呼ばれます。検収データがあると、納品書上の数量ではなく「実際に受け入れて問題なしと確認した数量」を基準にできるため精度は上がりますが、検収データを持たない現場も多いので、まずは納品書ベースの三点照合から始めるのが現実的です。
現場で実際に詰まる5つの壁
三点照合が「実装したのに毎回差異だらけになる」原因は、たいてい業務ロジックの解像度不足にあります。よく詰まるポイントを5つに整理しました。
- 明細の粒度が合わない — 発注書は「品目A 100個」の1行でも、納品が2回に分かれて納品書は2行、請求書はさらにロット単位で3行、ということがある。品目コードや単位を正規化しないと、1対1で突合できない。
- 単位・端数の丸め違い — 単価×数量の端数処理(切り捨て/切り上げ/四捨五入)が発注側と請求側で異なると、1円単位の差異が大量に発生する。
- 値引き・送料の扱い — 値引きや送料が請求書にだけ明細行として計上され、発注書には存在しない。これを「差異」として毎回検出してしまうと、本当に見るべき差異が埋もれる。
- 複数納品の分割請求 — 1つの発注に対して複数回に分けて納品・請求されるケース。1回の請求書単体で発注書と突合しようとすると、必ず数量差異として引っかかる。
- 適格請求書の登録番号確認 — インボイス制度対応で、請求書に記載された登録番号が正しい形式か、実在する事業者のものかを確認する必要がある。
Claude Codeでどう組むか——全体のアーキテクチャ
この手の突合作業は「非構造化データ(PDF・スキャン画像)を構造化する部分」と「構造化されたデータ同士を照合する部分」に分けて考えると設計しやすくなります。前者はClaude Codeが得意な領域、後者は決定的なロジック(Pythonの通常のコード)に任せるのが安全です。
- 抽出 — 発注書CSV・納品書CSV・請求書PDFを読み取り、共通スキーマ(取引先/品目/数量/単価/金額/税率/日付)に正規化する
- 突合 — 発注明細をキーに、納品の累積数量と請求金額を照合し、差異を計算する(ここはコードで固定ロジックにする)
- 要約 — 差異が出た明細について、想定される原因(分割請求・値引き未反映・端数など)を自然文で要約する
- レポート — 差異一覧をCSV/HTMLで出力し、経理担当が確認しやすい形に整形する
- 記録 — 誰が・いつ・どの差異を確認して承認したかのログを残す
抽出・要約はClaude Codeに任せますが、「一致しているかどうか」の最終判定は必ずコード側の決定的なロジックに固定します。これは後述する「AIに任せてはいけないこと」とも関係する、この実装の一番の設計判断です。
実装コード例1:請求書PDFの正規化
まず、請求書PDF一式をClaude Codeに読み取らせて、共通スキーマのCSVに正規化します。権限は必要最小限に絞り、読み取り・書き込み・Pythonの実行だけを許可します。
invoices/2026-07/ # 請求書PDF一式(取引先ごとにフォーマットが異なる)
purchase_orders/2026-07.csv # 発注データ(基幹システムからのエクスポート)
delivery_notes/2026-07.csv # 納品データ(WMS/在庫管理からのエクスポート)
data/normalized/ # 正規化後のCSV出力先
claude -p "invoices/2026-07/ 配下の請求書PDFを1件ずつ読み取り、
取引先名・登録番号・請求書番号・請求日・明細行(品目名/数量/単位/単価/金額/税率)・
小計/消費税額/合計金額を抽出してください。
金額はカンマと円記号を除いた半角数値、日付はYYYY-MM-DD形式に正規化してください。
読み取れない・判読が曖昧な項目は空欄で埋めず、notes列に理由を書いてください。
出力は data/normalized/invoices.csv に1明細1行で書き出してください。
不足している情報があれば、最初に質問してから作業を開始してください。" \
--allowedTools "Read" "Write" "Bash(python3:*)" \
--model claude-sonnet-5 \
--output-format json
大量の請求書を毎月バッチ処理するだけなら、抽出タスク自体はそこまで複雑な推論を要求しないため、コスト重視で軽量モデルに切り替える選択肢もあります(フォーマットが安定している取引先だけを対象にする、など条件付きで)。
claude -p "同じ指示で invoices/2026-07/vendor-a/ のみ処理してください" \
--allowedTools "Read" "Write" \
--model claude-haiku-4-5-20251001
実装コード例2:突合ロジックと差異レポート
正規化が終わったら、突合そのものは通常のPythonコードで決定的に行います。ここをAIの自然言語判断に任せると、実行のたびに閾値や丸めルールがぶれるリスクがあるためです。
# scripts/match_three_way.py
import csv
from decimal import Decimal, ROUND_HALF_UP
from collections import defaultdict
from pathlib import Path
TOLERANCE_YEN = Decimal("1") # 端数丸めとして許容する差額(1円まで)
def normalize_amount(raw: str) -> Decimal:
cleaned = raw.replace(",", "").replace("¥", "").strip()
return Decimal(cleaned).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
def load_rows(path: Path) -> list[dict]:
with path.open(encoding="utf-8") as f:
return list(csv.DictReader(f))
def aggregate_by_po_line(rows: list[dict], qty_key: str, amount_key: str) -> dict:
"""分割納品・分割請求を発注明細キーごとに累積加算する"""
agg = defaultdict(lambda: {"qty": Decimal("0"), "amount": Decimal("0")})
for row in rows:
key = (row["po_no"], row["item_code"])
agg[key]["qty"] += Decimal(row[qty_key])
agg[key]["amount"] += normalize_amount(row[amount_key])
return agg
def match(po_rows, delivery_rows, invoice_rows) -> list[dict]:
delivered = aggregate_by_po_line(delivery_rows, "delivered_qty", "delivered_qty")
billed = aggregate_by_po_line(invoice_rows, "billed_qty", "amount")
results = []
for po in po_rows:
key = (po["po_no"], po["item_code"])
po_qty = Decimal(po["order_qty"])
po_amount = normalize_amount(po["amount"])
dv_qty = delivered.get(key, {"qty": Decimal("0")})["qty"]
bl_amount = billed.get(key, {"amount": Decimal("0")})["amount"]
qty_diff = dv_qty - po_qty
amount_diff = bl_amount - po_amount
status = "match"
if abs(qty_diff) > 0 or abs(amount_diff) > TOLERANCE_YEN:
status = "review_required"
results.append({
"po_no": po["po_no"],
"item_code": po["item_code"],
"item_name": po["item_name"],
"po_qty": po_qty,
"delivered_qty": dv_qty,
"qty_diff": qty_diff,
"po_amount": po_amount,
"billed_amount": bl_amount,
"amount_diff": amount_diff,
"status": status,
})
return results
def write_report(results: list[dict], out_path: Path) -> None:
review_rows = [r for r in results if r["status"] == "review_required"]
with out_path.open("w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=list(results[0].keys()))
writer.writeheader()
writer.writerows(review_rows)
print(f"要確認: {len(review_rows)}件 / 全{len(results)}件 → {out_path}")
if __name__ == "__main__":
po_rows = load_rows(Path("data/normalized/purchase_orders.csv"))
delivery_rows = load_rows(Path("data/normalized/delivery_notes.csv"))
invoice_rows = load_rows(Path("data/normalized/invoices.csv"))
results = match(po_rows, delivery_rows, invoice_rows)
write_report(results, Path("data/output/diff_report.csv"))
差異が出た明細だけを対象に、Claude Codeで「想定される原因」を自然文で要約させると、経理担当者がレポートを読む負担が下がります。ただしこの要約はあくまで「確認すべき候補」であり、判定そのものではありません。
claude -p "data/output/diff_report.csv を読み、amount_diff が0でない行について、
想定される原因(分割請求の合算漏れ/値引き未反映/送料計上/端数丸め/その他)を
1行ずつ推測してnotes列に追記してください。断定はせず『〜の可能性があります』という
表現にとどめてください。判定や承認はしないでください。" \
--allowedTools "Read" "Edit" \
--model claude-sonnet-5
人が見るべき差異、自動で流してよい差異
すべての差異を人が確認していては仕組み化した意味がありません。逆に、すべてを自動承認すると事故のもとになります。線引きの例を示します。
| 差異の種類 | 目安 | 扱い |
|---|---|---|
| 端数丸め | ±1円以内で、かつ原因が丸め処理と機械的に説明できる場合 | 自動承認可 |
| 数量差(分割納品) | 累積納品数量が発注数量と一致 | 自動突合可(累積加算ロジックで吸収) |
| 消費税区分の不一致 | 適用税率(8%/10%)が発注・請求で異なる | 必ず人が確認(税区分の最終判断はAIに渡さない) |
| 単価差 | 契約単価と請求単価が不一致 | 必ず人が確認(値上げ・値引き交渉の反映有無を確認) |
| 送料・値引きの計上 | 請求書にのみ明細行が存在 | 必ず人が確認(契約上の合意有無を確認) |
| 登録番号の形式不備 | 「T+13桁の数字」のパターン外 | 自動検知してアラート、支払は保留 |
適格請求書の登録番号確認(インボイス制度対応)
国税庁によると、適格請求書等保存方式(インボイス制度)は令和5年10月1日から始まっており、適格請求書は税務署長の登録を受けた適格請求書発行事業者でなければ交付できません(国税庁 No.6498)。
適格請求書に記載しなければならない事項は、国税庁の案内(令和7年4月1日現在の法令等)によると次の6点です(国税庁 No.6625)。
- 書類作成者の氏名または名称および登録番号
- 取引年月日
- 取引内容(軽減税率の対象品目である旨)
- 税率ごとに区分して合計した税込対価(または税抜対価)の額および適用税率
- 税率ごとに区分した消費税額等
- 書類の交付を受ける事業者の氏名または名称
登録番号の構成は、法人番号を持つ課税事業者は「T+法人番号」、それ以外の課税事業者は「T+13桁の数字」です(国税庁インボイス制度適格請求書発行事業者公表サイト)。これはコードで機械的にチェックできます。
import re
INVOICE_NO_PATTERN = re.compile(r"^T\d{13}$")
def is_valid_format(registration_no: str) -> bool:
"""登録番号の「形式」だけをチェックする(実在確認ではない)"""
return bool(INVOICE_NO_PATTERN.match(registration_no.strip()))
ここで注意したいのは、これはあくまで「形式チェック」だという点です。形式が正しくても、失効している番号や誤記載の番号は存在します。国税庁の適格請求書発行事業者公表サイトは、登録番号の検索画面に加えて全件データのダウンロードやWeb-API経由の照会も提供しているため(同サイトの案内による)、新規取引先の登録時や定期的なバッチ処理で実在確認まで組み込むのが安全です。形式チェックはあくまで足切りであり、実在確認の代わりにはなりません。
似た構造の課題として、仕訳異常検知をClaude Codeで実装した記事でも「差異をどう仕分けるか」の設計を扱っています。突合と仕訳チェックは、どちらも「機械的に流してよい差異」と「人が見るべき差異」の線引きが実装の核になる点で共通しています。
AIに任せてはいけないこと
この実装で一番大事なのは、Claude Codeに何をさせないかを決めることです。
- 最終承認 — 差異レポートを人が確認したうえで承認する運用にし、承認ボタンの代わりにAIの出力をそのまま使わない
- 支払実行 — 振込・会計システムへの反映など、金銭が動く操作はAIに直接実行させない。人が承認した後に、承認済みのデータだけを次工程に渡す
- 税区分の最終判断 — 消費税の適用税率や仕入税額控除の可否といった税務判断は、AIの推測ではなく税理士・経理責任者が最終判断する
Claude Codeが担えるのは、あくまで抽出・正規化・突合・要約までです。税務や会計処理の正確性に責任を持てるのは人(と専門家)であり、判断に迷う場合は税理士に相談してください。
段階的導入のロードマップ
Phase 1(2〜4週間):取引先1社・書式1パターンに絞って正規化と突合ロジックを検証する。差異の許容閾値(端数の許容範囲など)をチームで合意する。
Phase 2(1〜3ヶ月):取引件数の多い主要取引先の書式に対応を広げ、差異レポートを経理の日次・週次業務のフローに組み込む。
Phase 3(3ヶ月以降):手書き納品書や特殊な書式などロングテールの例外に対応し、承認ログの記録や会計システムの仕訳データとの連携まで拡張する。
想定される効果(試算)
以下は特定の実測データではなく、実装を検討する際の試算・想定です。
| 項目 | 想定される変化 | 備考 |
|---|---|---|
| 突合作業の内容 | 全件を目視・Excel関数で確認 → 正規化済みデータの「要確認」分だけを人が見る | 試算。書式のばらつきが大きい現場ほど短縮余地は大きい |
| 見落としリスク | 担当者の手作業による見落とし → 機械的な全件突合 | 全件を対象にできる点が定性的な効果 |
| 差異の一次仕分け | すべての差異を人が確認 → 自動承認可/要確認に一次仕分け | 人が見るのは「要確認」に絞られる |
【要注意】よくある失敗パターンと回避策
失敗1:差異の閾値を決めずにAIへ「合っているか判断して」と丸投げする
❌「この請求書とこの発注書、金額が合っているか教えて」
⭕「発注金額と請求金額の差が1円を超える明細だけを抽出し、差額と対象の明細行を一覧にしてください。判断はしないでください」
なぜ重要か:「合っている/合っていない」の最終判断を自然言語の出力に依存すると、閾値や丸めルールが実行のたびにぶれます。判定ロジックはコードに固定し、AIには抽出・要約だけを任せます。
失敗2:PDFの読み取り結果を検証せずにそのまま突合に使う
❌ 抽出結果をそのまま data/normalized/ に流し、突合スクリプトを実行する
⭕ 抽出後に取引先ごとに数件をサンプル抽出し、明細行数・合計金額が原本と一致するかを人が目視確認してから突合に進む
なぜ重要か:表組みが崩れたPDFや手書き注記があると、明細行の抽出漏れ・重複が起きます。突合ロジックがどれだけ正確でも、入力データが崩れていれば結果は信用できません。
失敗3:登録番号の形式チェックだけで「確認済み」にしてしまう
❌ 正規表現がマッチしたら「登録番号OK」として次の工程に進める
⭕ 形式チェック(コード)→ 国税庁公表サイトでの実在確認(人、または定期バッチでのAPI連携)の2段階にする
なぜ重要か:形式が正しくても、失効・誤記載の番号は存在します。形式チェックは足切りであって、実在確認の代わりにはなりません。
失敗4:AIが書いた差異理由をそのまま処理の根拠にする
❌ AIが出力した「送料の計上漏れの可能性があります」という一文をそのまま経理システムのメモに転記して処理を進める
⭕ AIの要約は「確認すべき候補」として扱い、実際の原因(契約内容・値引き合意など)は一次資料に当たって担当者が確認してから記録する
なぜ重要か:要約はあくまで推測です。契約書や発注担当者への確認を経ずに数字を動かすと、後から監査で説明できなくなります。
よくある質問
Q. 三点照合と四点照合の違いは何ですか?
三点照合は発注書・納品書・請求書の3種類の数量・金額を突合する方法です。四点照合はこれに検収データ(実際に検品・受入処理をした記録)を加え、納品書上の数量ではなく検収済み数量を基準にする点が異なります。検収データがない現場では、まず納品書ベースの三点照合から始めるのが現実的です。
Q. Claude Codeに請求書の最終承認をさせてもいいですか?
させるべきではありません。Claude Codeは抽出・正規化・突合・差異の要約までを担い、最終的な支払承認と税区分の判断は必ず経理担当者(必要に応じて税理士)が行う設計にしてください。
Q. 適格請求書の登録番号が本物かどうかはどう確認しますか?
まず形式(T+13桁の数字)をコードで機械チェックし、次に国税庁の適格請求書発行事業者公表サイトで実在を確認します。形式が正しくても実在しない、あるいは失効した番号である可能性があるため、形式チェックだけで済ませないでください。
Q. 分割納品・分割請求にはどう対応すればいいですか?
1つの発注に対して複数回の納品・請求が発生するケースでは、発注書の明細行をキーにして納品数量・請求金額を累積加算してから、発注数量・金額と突合するロジックにします。1回分の請求書単体で発注書と突合しようとすると、必ず差異として検出されてしまいます。
Q. 導入にはどれくらいの期間がかかりますか?
現場や書式のばらつきにもよりますが、最初のフォーマット(1取引先・1書式)で正規化と突合ロジックを検証するまでは数週間、複数取引先・複数書式へ横展開するにはさらに数ヶ月かかるのが一般的な目安です(試算であり実測値ではありません)。
まとめ:今日から始める3つのアクション
- 今日やること:直近1ヶ月分の請求書・発注書・納品書を1つのフォルダに集め、明細の粒度がどれだけ揃っているかを目視で確認する
- 今週中:取引先1社分だけ正規化スクリプトを書いて、実際にどのパターンで差異が出るかを洗い出す
- 今月中:差異を「自動承認してよいもの」と「人が確認するもの」に分類する社内ルールを、経理担当者と一緒に言語化する
関連記事として、会計事務所の記帳・仕訳をClaude Codeで効率化した実装5手順もあわせて参考にしてください。
著者:佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。X(@SuguruKun_ai)フォロワー約10万人。100社以上の企業向けAI研修・導入支援。著書『AIエージェント仕事術』(SBクリエイティブ)。
参考・出典
- 国税庁 No.6498 適格請求書等保存方式(インボイス制度)(参照日: 2026-07-27)
- 国税庁 No.6625 適格請求書等の記載事項(参照日: 2026-07-27)
- 国税庁インボイス制度適格請求書発行事業者公表サイト「登録番号とは」(参照日: 2026-07-27)
- Claude Code CLI reference(code.claude.com)(参照日: 2026-07-27)
ご質問・ご相談は お問い合わせフォーム からお気軽にどうぞ。