Media > AI活用ユースケース > 経理 > SaaS 企業が海外のクラウドのマーケットプレイス経由の売上について毎月届く英文の支払の明細を読み取り、顧客ごとの売上の台帳と自社の請求の記録との差の一覧を作る

SaaS 企業が海外のクラウドのマーケットプレイス経由の売上について毎月届く英文の支払の明細を読み取り、顧客ごとの売上の台帳と自社の請求の記録との差の一覧を作る

実装ステータス:構成例 技術的に実現可能な構成として設計したもの。自社未検証

海外の販売パートナーから毎月届く英文の支払の明細を AWS Textract で読み取り、契約の番号で自社の請求の記録と1行ずつ突き合わせます。顧客ごとの売上の台帳に入れる案と、差のある行だけの一覧を作ります。

サマリー
AIサービス
AWS Textract/Azure AI/Google Document AI
連携・自動化
Python
対象業界
IT・SaaS/その他
対象部門
経理/財務
対象業務
内容確認・チェック/比較検討
主な課題
入力作業が多い/属人化している/確認ミスが多い
AIで行う処理
抽出
主な効果
入力漏れ削減/工数削減/機会損失防止
導入難易度
★★★☆☆
実装レベル
半自動化
費用感
API連携(中)
人間の確認
条件付き
現在工数
45h/月
AI導入後
12h/月
想定削減
73%
年間削減
396h
モデル条件による試算値です。実在企業の実績ではありません。

01導入前 / 導入後の業務フロー

導入前(Before)
  1. パートナーからのメールで届いた PDF の明細を、担当者が共有フォルダに保存する
  2. 明細を1通ずつ開き、表の行をスプレッドシートに書き写す。ページをまたぐ表は、ページの区切りで行がずれないように手で直す
  3. 請求の記録から、そのパートナーの今月の契約の一覧を書き出す
  4. 書き写した行を、契約の番号で請求の記録と1行ずつ照らし、卸値・数量・期間を見る
  5. 差し引かれた手数料を、パートナーとの契約の率で検算する
  6. 返金の行があれば、自社が返金を承認した記録と照らす
  7. 請求の記録にあって明細に無い契約に印を付ける
  8. 差の一覧を作ってパートナーへの問い合わせの案を書き、顧客ごとの売上の台帳に入れる
導入後(After)
  1. 人届いた PDF の明細を、パートナーごとの受付の場所に保存する
  2. 自動保存をきっかけに読み取りが始まり、形式・サイズ・パスワードの有無を確かめる
  3. 自動AWS Textract が明細の表と、明細の番号・期間・通貨・支払額の値を、信頼度とともに返す
  4. 自動パートナーごとの列の対応表で、共通の項目(契約の番号・期間・総額・手数料・返金・税・支払額)にそろえる
  5. 自動契約の番号で請求の記録と照らし、卸値・数量・期間・手数料の率を検算する
  6. 自動請求の記録の側から、今月の明細に載るはずの契約を並べ、載っていない契約を拾う
  7. 自動行ごとに `matched` / `price_diff` / `fee_rate_diff` / `period_diff` / `refund` / `not_in_statement` / `not_in_records` / `needs_review` を付ける
  8. 自動顧客ごとの売上の台帳に入れる案と、差のある行だけの一覧を作る
  9. 人担当者が `matched` 以外の行だけを、明細の該当箇所と見比べて確かめる
  10. 人パートナーへの問い合わせを決め、台帳への反映を承認する
各工程の詳しい説明を読む
  1. パートナーからのメールで届いた PDF の明細を、担当者が共有フォルダに保存する
  2. 明細を1通ずつ開き、表の行をスプレッドシートに書き写す。ページをまたぐ表は、ページの区切りで行がずれないように手で直す
  3. 請求の記録から、そのパートナーの今月の契約の一覧を書き出す
  4. 書き写した行を、契約の番号で請求の記録と1行ずつ照らし、卸値・数量・期間を見る
  5. 差し引かれた手数料を、パートナーとの契約の率で検算する
  6. 返金の行があれば、自社が返金を承認した記録と照らす
  7. 請求の記録にあって明細に無い契約に印を付ける
  8. 差の一覧を作ってパートナーへの問い合わせの案を書き、顧客ごとの売上の台帳に入れる

(a)書き写しで時間の半分が消える。 30通で月に数千行を書き写し、差の原因を探しに行くと自分の写し間違いだった、ということが毎月あります。

(b)明細に載っていない契約は、探さないと見つからない。 明細を上から照らす作業では、明細にある行しか目に入りません。7番目は逆向きの作業で、忙しい月には飛ばされます。

(c)卸値の改定が明細に反映されていない。 価格を改定した月の後、パートナーが古い卸値のまま支払ってくる契約が数件混ざります。 1件の差は小さく、合計で見ると為替の違いに紛れます。

(d)パートナーごとの読み方が、担当者の頭の中にある。 どの列が手数料差引後か、返金はマイナスの行か別の表か。その担当者が休むと、照合が止まります。

  1. 【人】 届いた PDF の明細を、パートナーごとの受付の場所に保存する
  2. 【自動】 保存をきっかけに読み取りが始まり、形式・サイズ・パスワードの有無を確かめる
  3. 【自動】 AWS Textract が明細の表と、明細の番号・期間・通貨・支払額の値を、信頼度とともに返す
  4. 【自動】 パートナーごとの列の対応表で、共通の項目(契約の番号・期間・総額・手数料・返金・税・支払額)にそろえる
  5. 【自動】 契約の番号で請求の記録と照らし、卸値・数量・期間・手数料の率を検算する
  6. 【自動】 請求の記録の側から、今月の明細に載るはずの契約を並べ、載っていない契約を拾う
  7. 【自動】 行ごとに matched / price_diff / fee_rate_diff / period_diff / refund / not_in_statement / not_in_records / needs_review を付ける
  8. 【自動】 顧客ごとの売上の台帳に入れる案と、差のある行だけの一覧を作る
  9. 【人】 担当者が matched 以外の行だけを、明細の該当箇所と見比べて確かめる
  10. 【人】 パートナーへの問い合わせを決め、台帳への反映を承認する

9番目が、この設計の分かれ目です。 人が見るのは差のある行だけです。全行を人が確かめると、書き写しが「見比べ」に変わるだけで、時間はあまり減りません。

6番目を、明細を読む処理と別に置いているのは意図してのことです。 明細を読む処理は、明細に無いものを知りようがありません。明細が1通届かなかった月は、その1通分の契約が黙って抜けます。

02今回想定するシステム構成

構成図
支払の明細(PDF。パートナーからのメール)
   │  担当者がパートナーごとの受付の場所へ保存
   ▼【トリガー】Amazon S3 への保存
AWS Lambda
   ├──▶ 形式・サイズ・パスワードの確認、パートナーと通貨の見分け
   ▼
AWS Textract(StartDocumentAnalysis。TABLES と QUERIES)
   │   表のセルと列見出し、明細の番号・期間・通貨・支払額、それぞれの信頼度
   ▼
AWS Lambda(Python)
   │   ① パートナーごとの列の対応表で、共通の項目にそろえる
   │   ② 契約の番号で請求の記録と照らす(卸値・数量・期間)
   │   ③ パートナーとの契約の率で、手数料を検算する
   │   ④ 請求の記録の側から、明細に載っていない契約を拾う
   ▼
行ごとの判定(matched / price_diff / fee_rate_diff / period_diff / refund / not_in_statement / not_in_records / needs_review)
   ▼
【人が matched 以外の行だけ確認】
   ├──▶ 顧客ごとの売上の台帳に入れる案
   └──▶ パートナーへの問い合わせの案(差の一覧)
役割想定する製品代替候補
OCRAWS Textract(StartDocumentAnalysis の TABLES と QUERIES)Azure AI Document Intelligence、Google Document AI
差異計算請求の記録との照合、手数料の検算、明細に無い契約の洗い出し(Python。AWS Lambda で動かす)─
連携AWS Lambda(S3 への保存を起点に読み取りを始め、結果を一覧に書く)Amazon EventBridge
保管Amazon S3(明細と読み取りの結果)社内のファイルサーバー
通知Amazon SNS(読み取りの完了と、要確認の知らせ)社内のチャット

請求の記録と顧客ごとの売上の台帳は、新しく足すものではありません。 新しく作るのは、明細の列見出しを共通の項目に結び付ける列の対応表と、手数料の率と差し引く項目をパートナーごとに1行にまとめた契約の条件の表の2つです。

明細は、AWS Textract の表の解析で読みます。 表はセルごとに行と列の番号が付いて返り、列見出しのセルには COLUMN_HEADER、表の題名には TABLE_TITLE、表の下の注記には TABLE_FOOTER、区切りの見出しには TABLE_SECTION_TITLE、小計などの集計のセルには TABLE_SUMMARY が付きます。どの行が契約で、どの行が小計かを、セルの種類で見分けられます。

AWS Textract は日本語を読めません。 対応する言語は英語・フランス語・ドイツ語・イタリア語・ポルトガル語・スペイン語で、縦書きにも対応しません。顧客の名前に漢字が混ざる行では、その列は読めません。 照合の鍵を顧客の名前ではなく契約の番号に置くのは、このためです。

自社が直接出品している分は対象外です。 たとえば AWS Marketplace の売り手向けのダッシュボードは、請求書ごとの総額・返金・手数料・支払の状態(Disbursed、Not disbursed など)を表で示し、書き出しの方法も案内されています。表で取れるものを PDF で読み直す理由はありません。

03どうやって実装するのか

Step1

処理の起点を決める

パートナーごとの受付の場所(S3 の接頭辞)に明細が保存されたことを起点にします。 明細はパートナーごとに届く日が違い、月初の数日に集中しますが、全部がそろう日は決まっていません。全部そろってからまとめて読む形にすると、早く届いた明細の差に気づくのが遅れます。 1通ずつ動かします。

保存の場所はパートナーごとに分け、接頭辞からパートナーを決めます。 明細の中の社名は、表記の揺れやロゴの画像で迷うからです。

読み取りを始めるときは、ClientRequestToken にファイルの識別子を入れます。同じトークンで呼び直すと同じ JobId が返るので、同じ明細を二重に読みません。 JobTag にはパートナーのコードを入れます。

Step2

入力データを集める

データ中身取得元
支払の明細PDF。パートナーとマーケットプレイス、明細の期間、通貨パートナーからのメール(担当者が保存)
読み取り結果表のセル・列見出し・小計、明細の番号・期間・通貨・支払額、それぞれの信頼度AWS Textract
請求の記録契約の番号、顧客、プラン、卸値、数量、サービスの期間、今月の支払の対象か自社の請求管理の仕組み(毎月の書き出し)
列の対応表パートナーごとの列見出しと、共通の項目との対応新しく作る表
契約の条件の表パートナーごとの手数料の率、差し引かれる項目、支払の通貨新しく作る表
返金の承認の記録自社が返金を承認した契約と金額自社のサポートの記録

質を決めるのは、請求の記録の「今月の支払の対象か」の列です。 これが無いと、明細に載っていない契約を拾う④の処理が、そもそも何と比べればよいか分かりません。サービスの期間と、パートナーとの支払の取り決め(翌月払いなど)から、この列を請求の記録の側で出しておきます。

返金の承認の記録は、承認した覚えのない返金の行を拾うために持ちます。

Step3

データの取得方法を決める

取るものどこから何に使うか
表とセルGetDocumentAnalysis の TABLE・CELL のブロック契約ごとの行
セルの種類CELL の EntityTypes列見出し・小計・区切りの見出しの見分け
明細の見出しの値QUERY_RESULT のブロック明細の番号・期間・通貨・支払額
信頼度各ブロックの Confidenceneeds_review の判定

問い(Queries)は、明細の見出しにある値だけに使います。 "What is the statement period?"、"What is the payout currency?"、"What is the total net payout amount?" のような問いです。問いは、ページを指定しないと既定で1ページ目だけに当たります。 支払額の合計は最後のページにあることが多いので、Pages に ["*"] を指定して全ページに当てます。問いは非同期の処理で1ページあたり30個までです。

結果は NextToken で続きを取ります。 1回で返るブロックは最大1,000個で、200行の明細は1回では返りきりません。取りきる前に照合を始めると、後半のページの契約がすべて「明細に無い」になります。 JobId は7日しか有効でないので、取りきった結果はその場で S3 に保存します。

Step4

AIへ渡す前に整形する

  1. 形式の確認 … PDF・JPEG・PNG・TIFF であることを確かめます。パスワード付きの PDF は読めないので、パートナーに外したものを送ってもらいます
  2. サイズとページ数の確認 … 非同期の処理で、PDF は500MBと3,000ページが上限です
  3. パートナーと通貨の確定 … 保存の場所からパートナーを決め、ファイル名の決まり(パートナーのコード・期間・通貨)と照らします
  4. 列見出しの正規化 … 大文字と小文字、前後の空白、改行の入った見出しをそろえてから、列の対応表に当てます
  5. 金額の正規化 … 桁区切りのカンマ、括弧で書かれたマイナス、通貨の記号を外し、数値にそろえます。桁区切りがピリオドの書式のパートナーは、対応表に印を付けておきます
  6. 契約の番号の正規化 … 前後の空白とハイフンの有無をそろえます。それ以上は直しません
  7. 重複の確認 … 同じパートナー・同じ期間・同じ通貨の明細が既にあれば、差し替えの版かを人に確かめます

5番目を軽く見ないでください。 欧州のパートナーには、1.234,56 のように桁区切りと小数点が逆の書式で明細を出してくるところがあります。そのまま数値にすると、金額が千倍か千分の一になります。 書式はパートナーごとに対応表に書いておき、推測で切り替えません。

6番目で「それ以上は直さない」のは、1文字違いの番号を寄せると、別の顧客の契約に支払が入ったことになるからです。

Step5

AIに処理させる

AIにさせるのは、明細の表と見出しの値を読み取って、セルごとの文字と信頼度を返すことだけです。 照合と検算は、Python の決まった処理で行います。

読み取るもの使う機能判断できないときの扱い
契約ごとの行(契約の番号・プラン・期間・総額・手数料・返金・税・支払額)表の解析(TABLES)信頼度が基準より低いセルは needs_review
列見出しセルの種類(COLUMN_HEADER)対応表に無い見出しは、その列を使わず人へ
小計・合計の行セルの種類(TABLE_SUMMARY)契約の行として扱わない
明細の番号・期間・通貨・支払額問い(QUERIES)答えが無いか信頼度が低ければ、明細ごと人へ

照合で付ける判定は次のとおりです。

判定決め方
matched契約の番号が当たり、卸値・数量・期間・手数料の率がすべて合う
price_diff総額が、請求の記録の卸値 × 数量と合わない
fee_rate_diff差し引かれた手数料が、契約の条件の表の率で計算した額と合わない
period_diffサービスの期間が、請求の記録の期間と合わない
refund返金の行。返金の承認の記録と照らした結果を添える
not_in_statement請求の記録で今月の支払の対象なのに、明細に無い
not_in_records明細にあるのに、請求の記録に無い
needs_review読み取りの信頼度が低い、列が足りない、見出しの値が取れない
させないこと理由
列の意味の推測対応表に無い見出しを似た名前の項目に寄せると、手数料差引前と後を取り違える
金額の計算での穴埋め読めなかった手数料を総額と支払額から逆算すると、検算の意味がなくなる
外貨の換算・計上の時期の判断経理の決まりで、会計システムの側で行う

2行目がいちばん起きやすい失敗です。 手数料の列だけ読めなかったとき、総額から支払額を引けば手数料が出ます。しかしその瞬間、「手数料が契約の率と合っているか」の検算ができなくなります。 読めなかったセルは読めなかったものとして人に回します。

Step6

指示内容を固定する

この構成の読み取りは AWS Textract で、生成AIへの文章の指示はありません。指示にあたるのは、問いの文と、照合の規則の設定です。 パートナーごとの設定の例を示します。

【パートナーの設定】partner_code: P07
statement_prefix: s3://<受付のバケット>/partners/P07/
number_format: "1.234,56"            # 桁区切りがピリオド、小数点がカンマ
negative_format: "parentheses"       # (120.00) はマイナス
currency_from: "query"               # 通貨は問いの答えから取る

【問い(QueriesConfig)】すべて Pages: ["*"]
- Alias: STATEMENT_NO    Text: "What is the statement number?"
- Alias: PERIOD          Text: "What is the statement period?"
- Alias: CURRENCY        Text: "What is the payout currency?"
- Alias: TOTAL_PAYOUT    Text: "What is the total net payout amount?"

【列の対応表】(明細の列見出し → 共通の項目)
"Agreement ID"          → contract_no
"Plan"                  → plan
"Service Period"        → service_period
"Gross Amount"          → gross
"Marketplace Fee"       → fee
"Refund"                → refund
"Withholding Tax"       → tax_withheld
"Net Payout"            → net
上記に無い見出しの列は使わない。必須の列(contract_no、gross、net)が
1つでも見つからない表は、照合せずに明細ごと needs_review にする。

【照合の規則】
- 鍵は contract_no だけ。顧客の名前では照合しない。
- contract_no は前後の空白とハイフンだけをそろえる。近い番号に寄せない。
- 信頼度が 90 未満のセルを含む行は needs_review。値を使って検算しない。
- 手数料の検算は、契約の条件の表の率 × gross。差が許容の幅を超えたら fee_rate_diff。
- fee・refund・tax_withheld のどれかが読めなかったら、gross と net から逆算しない。
- TABLE_SUMMARY の行は契約の行として扱わず、合計の検算にだけ使う。
- 明細の行の net の合計と、問い TOTAL_PAYOUT の答えが合わなければ、
  明細ごと needs_review にする(ページの読み落としを疑う)。
- 請求の記録で今月の支払の対象の契約のうち、どの明細にも無いものを
  not_in_statement として、パートナーごとに並べる。

信頼度の基準の「90」は例です。 最初の1か月は、どの信頼度のセルで誤りが出たかを数えてから決めます。

「明細の合計と行の合計が合わなければ、明細ごと人へ」の規則が、読み落としを止めます。 ページをまたぐ表で1ページ分の行が別の表として返り、対応表に当たらずに落ちても、合計が合わないことで気づけます。 行ごとの照合だけでは、落ちた行は「無かった」ことになります。

Step7

出力形式を固定する

次の形のJSONで、明細1通ごとに保存します。

{
  "statement_id": "",
  "partner_code": "P07",
  "marketplace": "",
  "period": { "from": "2026-09-01", "to": "2026-09-30" },
  "currency": "EUR",
  "total_payout": { "value": 0, "confidence": 0 },
  "sum_of_lines": 0,
  "total_check": "ok | mismatch",
  "lines": [
    { "contract_no": "", "plan": "", "service_period": "",
      "gross": 0, "fee": 0, "refund": 0, "tax_withheld": 0, "net": 0,
      "min_confidence": 0,
      "status": "matched | price_diff | fee_rate_diff | period_diff | refund | not_in_records | needs_review",
      "expected": { "gross": 0, "fee": 0, "service_period": "" },
      "source": { "page": 0, "row": 0 } }
  ],
  "not_in_statement": [
    { "contract_no": "", "customer_code": "", "expected_net": 0, "months_missing": 0 }
  ]
}

1つ目の理由は、読み取った値と、比べた先の値を並べて持てることです。 lines の各行に、明細から読んだ値と expected(請求の記録と契約の条件から出した値)を両方入れます。担当者は、差がいくらで、どちらの値が何に基づいているかを、明細を開く前に読めます。

2つ目は、source で明細の該当箇所に戻れることです。 数百行の明細で該当の行を探す時間が、確認の時間の大半を占めがちです。

3つ目は、not_in_statement を行とは別に持つことです。 明細に無い契約は行のどこにも置けないので、別の配列にして、何か月続けて載っていないか(months_missing)を持たせます。 2か月以上続くなら、パートナーの登録の漏れを疑います。

顧客ごとの売上の台帳には、matched の行と人が確かめた行だけを、明細の番号を添えて入れます。

Step8

システムへ連携する

つなぎ先方式内容
Amazon S3保存の通知明細の保存を検知し、読み取りを始める
AWS TextractStartDocumentAnalysis/GetDocumentAnalysis表と問いの解析。完了は SNS で受ける
請求の記録毎月の書き出しの読み取り契約の番号・卸値・数量・期間・今月の支払の対象か
顧客ごとの売上の台帳人が承認した行の書き込み承認された行だけを足す
会計システム既存の入力の経路この構成からは書き込まない

会計システムへは書き込みません。 外貨の換算と売上の計上の時期は経理の決まりで決まり、この構成が出すのは、明細と請求の記録の差までです。 書き込みを足すと、読み取りの誤りがそのまま帳簿に入ります。

請求の記録も読むだけです。 違いがどちらの誤りかは、人が確かめてから決めます。

Step9

人が確認する

人が開くのは matched 以外の行と、not_in_statement の一覧だけです。 matched の行は、パートナーごとの件数と合計を流し見ます。

  1. total_check が mismatch の明細を先に見る … 行の読み落としがある恐れがあります。この明細の行の判定は、合計が合うまで使いません
  2. needs_review の行を明細と見比べる … source のページと行を開き、読めなかったセルの値を確かめて入れ直します
  3. price_diff と fee_rate_diff の原因を決める … 卸値の改定の反映漏れか、契約の条件の表の誤りかを確かめます
  4. refund の行を、返金の承認の記録と照らす … 承認の記録に無い返金は、パートナーへの問い合わせに回します
  5. not_in_statement を、続いている月の数で並べて見る … 2か月以上続くものから確かめます
  6. 台帳への反映を承認する … 承認したものだけを台帳に入れます

目標は、30通をならして1通24分です。 差のある行は1通あたり数行という想定です。

Step10

例外に対処する

起きること対応
パスワード付きの PDF読めない。パートナーに外したものを送ってもらう
対応していない形式(Office の文書など)PDF にしてもらうか、PDF にしてから保存する
読み取りの失敗(FAILED)StatusMessage を残し、ファイルを受付の場所に残す。次の段階へ進めない
一部のページだけの成功(PARTIAL_SUCCESS)Warnings のページを確かめ、明細ごと needs_review
明細の行の合計と支払額が合わないページの読み落としを疑い、明細ごと needs_review
対応表に無い列見出しその列を使わない。新しい書式なら対応表を人が足す
必須の列が見つからない照合をせず、明細ごと人へ
問いへの答えが無い期間・通貨を人が入れる
同じ期間の明細が2通届く差し替えの版か別のマーケットプレイスの分かを人が確かめる

3行目から5行目は、どれも「読めなかった」ことが分かる形で止める規則です。 読めた分だけで照合に進めると、読めなかったページの契約がすべて not_in_statement になります。

Step11

記録を残す

  • 元の明細の PDF と、保存した日時・保存した人・パートナー
  • AWS Textract が返した結果の全文(全ページ分、NextToken で取りきったもの)
  • 照合に使った、その月の請求の記録の書き出しと、そのときの列の対応表・契約の条件の表
  • 行ごとの判定(status、expected、source)と not_in_statement の一覧
  • 人が判定を覆した記録 … どの行を、どちらに変え、理由は何か
  • パートナーへの問い合わせの日時と、回答・修正された明細との対応

3つ目で「そのときの表」を残すのは、表が後から変わるためです。 契約の条件の表の率を直すと、過去の月の fee_rate_diff の意味が変わります。当時の表が残っていないと、どの月まで遡って直すかが決まりません。

04実装レベルの3段階

最小構成:明細を1通ずつ読み取り、スプレッドシートで請求の記録と照らす / 読み取りと、契約の番号の当たり方の確かめ
半自動化:上記+S3 への保存を起点に読み取り、照合・手数料の検算・明細に無い契約の洗い出しを一覧に書き出す / 読み取り・照合・検算・未払いの候補の洗い出し
本格構成:上記+入金の記録と明細の支払額を照らし、承認された行を台帳へ書き込むまでを一続きにする / 明細から入金の確認、台帳への反映まで

最小構成は、確かめるための段階です。 照合が手作業のまま残ります。 半自動化で、1通90分が24分程度になります。 これが本記事の想定です。照合と検算と、明細に無い契約の洗い出しが自動になり、人の時間は差のある行の確認に絞られます。 本格構成で入金の記録との照合を足すと、さらに短くなりますが、入金は複数の明細がまとめて振り込まれることがあり、照合の規則が1段難しくなります。

05工数削減シミュレーション

前提値(モデル条件)
対象人数
2 名
月間件数
30 件
1件あたり現在時間
90 分
1件あたり導入後時間
24 分
現在  30件 × 90分 ÷ 60 = 45 時間/月
導入後 30件 × 24分 ÷ 60 = 12 時間/月
月間削減時間
33h
削減率
73%
年間削減時間
396h
年間金額換算(時間単価4,000円)
158万円
モデル条件による試算であり、実際の効果は業務内容・運用方法によって異なります。

自社条件で導入効果を整理したい方へ

このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。

AI活用について相談する

06向いている企業・向いていない企業

向いている
  1. 自社の SaaS を、海外の販売パートナーを通じて各国のクラウドのマーケットプレイスで売っていて、パートナーごとに書式の違う英文の支払の明細が PDF で毎月届く SaaS 企業。明細の数百行を自社の請求の記録と目で突き合わせていて、卸値の違い・返金・支払われていない契約に気づくのが翌月以降になっている場合。請求の記録から、パートナーの契約の番号(agreement ID や subscription ID)を含む一覧を書き出せる場合。
向いていない
  1. マーケットプレイスに自社が直接出品していて、運営者の管理画面やデータの書き出しで支払の明細を表として取り出せる場合(PDF を読む必要がありません)。海外の販売パートナーが1〜2社で、明細が月に数通しか届かない場合。明細が日本語で届く場合(AWS Textract は日本語を読めません)。なお、売上の計上の時期、外貨の換算、源泉の税の扱い、パートナーへの申し出の可否の判断は、この構成では行いません。

07最小構成で試す方法

  1. 先月の明細から4通を選ぶ(パートナーを4社に分け、そのうち1社は桁区切りがピリオドの書式のところを入れる)
  2. その4通について、当時どの行に差を見つけ、どう問い合わせたかを書き出す
  3. 4通を S3 に置き、StartDocumentAnalysis を TABLES と QUERIES で1通ずつ呼び、結果を取りきって保存する
  4. 返った表をスプレッドシートに写し、契約の番号の列を請求の記録の契約の番号と照らす
  5. 当たらなかった行を並べ、番号の書き方の違いか、請求の記録の側の空欄か、本当に記録に無い契約かを分ける

4通は必ずやってください。 照合の処理を組む前に、「表がページをまたいでどう返るか」と「契約の番号がどれだけそのまま当たるか」を確かめます。

出てきた内容判断
契約の番号がほぼそのまま請求の記録に当たる列の対応表を作り、S3 と Lambda の連携に進む
番号の空白やハイフンの違いで当たらない前処理の決まりをパートナーごとに作る。構成は有効
請求の記録にパートナーの契約の番号が無い請求の記録の整備が先。 読み取りの問題ではない

3行目は珍しくありません。 照合に時間がかかっていた理由の1つが、記録の側にあったと分かったということです。

08実装時につまずきやすいポイント

問題対策
後半のページの契約が「明細に無い」になるNextToken で結果を取りきってから照合する
支払額の合計が問いで取れない問いは既定で1ページ目だけ。**Pages に ["*"] を指定する**
金額が千倍・千分の一になる桁区切りと小数点の書式を、パートナーごとに対応表に書く
小計の行が契約の行として照合されるTABLE_SUMMARY のセルの行を除く
読めなかった手数料を逆算で埋める逆算しない。読めなかったら人へ
顧客の名前が読めない漢字は読めない。照合の鍵を契約の番号にする
契約の条件の表が古い全行が同じ差なら表を疑う。契約の更新の日を表に持たせる
明細が1通届かなかった月に気づかない請求の記録の側から数える④の処理で拾う
同じ明細を二重に読むClientRequestToken にファイルの識別子を入れる
読み取りの結果が後から取れないJobId は7日で無効。その場で S3 に保存する

上の2行が、この構成の失敗のほとんどです。 どちらも、読み取りが成功したように見えて、一部しか読めていない状態です。エラーは出ず、not_in_statement が増えるか、明細ごとの検算が合わないかでしか気づけません。合計の検算を省かないでください。

09セキュリティ・AIガバナンス上の注意点

この構成で扱うデータ: 顧客の会社名と契約の番号、プランと数量、卸値と手数料の率、パートナーとの契約の条件、そして明細に印刷されている振込先の口座情報です。

  1. AWS の AI サービスによる内容の利用を止める … AWS の AI サービスは、顧客の内容をモデルの学習などサービスの改善に使い、利用中のリージョンの外に保存することがあるとされています。AWS Organizations のオプトアウトの方針で止められるので、読み始める前に設定します
  2. パートナーとの契約の条件を外に出さない … 手数料の率と卸値は、パートナーとの契約で取り決めた機密の情報です。照合は自社の AWS の環境の中の処理で行い、契約の条件の表そのものを外のサービスへ渡しません
  3. 読み取りの結果を暗号化して保存する … StartDocumentAnalysis で KMS の鍵を指定すると、結果の保存に使われます。受付の場所と結果の保存の場所のアクセスを、経理の担当者と処理の役割だけに絞ります
  4. 問い合わせを自動で送らない … 差の一覧はパートナーへの問い合わせの案までです。差の原因が自社の記録の側にあることもあり、確かめずに送ると関係に響きます
  5. この構成は会計の判断を代替しません … 売上の計上の時期、外貨の換算の基準、源泉の税の扱いは、経理と顧問の税理士・会計士が決めることです。 この構成が出すのは、明細と請求の記録の差という事実だけです

誤りが起きた場合のリスクは、差を見落として少ない支払を受け入れることと、差の無いものを問い合わせることの2つです。 どちらも「読めなかった」を読めなかったものとして扱う規則で防ぎます。

10まず何から始めるか

1週目:請求の記録に、パートナーの契約の番号を持たせる

請求の記録に、パートナーの側が明細に載せる契約の番号の列を足します。10社すべてを一度に埋める必要はありません。明細の行の多い上位3社から埋めます。 あわせて「今月の支払の対象か」の列を、サービスの期間と支払の取り決めから出せるようにします。

2週目:4通で試す

先月の明細から4通を選び、AWS Textract で表と問いの解析をかけます。表がページをまたいでどう返るか、契約の番号がどれだけそのまま当たるかを確かめます。

3週目:列の対応表と契約の条件の表を作る

上位3社について、列見出しと共通の項目の対応、桁区切りの書式、手数料の率を、契約書を手元に置いて表にします。

4週目:保存から一覧までをつなぐ

S3 への保存を起点に読み取り、照合の結果を一覧に書き出すところまで作ります。この時点では not_in_statement を出さず、明細にある行の判定だけを見ます。

2か月目: not_in_statement の洗い出しと合計の検算を足し、残りのパートナーの対応表を作ります。3か月目以降: 1通90分が何分になったかを実測し、差の傾向をもとに明細の書式や卸値の登録の仕方をパートナーと相談した時点で、この構成は完成です。


11関連ユースケース

12この仕組みを理解するための記事

13技術仕様の確認日・参考情報

技術仕様確認日:2026-10-29/最終更新:2026-10-29
確認した内容情報源確認日
形式が JPEG・PNG・PDF・TIFF で、非同期の処理で PDF が500MB・3,000ページまでであること。パスワード付きの PDF を扱えないこと。対応言語が英・仏・独・伊・葡・西で縦書きに非対応なこと。問いは英語の文書だけで、非同期で1ページ30個までであることAWS: Set Quotas in Amazon Textract2026-10-29
FeatureTypes の TABLES・QUERIES、ClientRequestToken で同じ JobId が返ること、JobTag、SNS への完了の通知、KMSKeyId、JobId が7日だけ有効なことAWS: StartDocumentAnalysis2026-10-29
1回に最大1,000個のブロックを返し NextToken で続きを取ること。JobStatus の PARTIAL_SUCCESS、StatusMessage・WarningsAWS: GetDocumentAnalysis2026-10-29
セルの種類に COLUMN_HEADER・TABLE_SUMMARY などがあり、結合セルが MERGED_CELL で返ることAWS: Tables2026-10-29
問いの Pages を指定しないと既定で1ページ目だけになり、* で全ページを指定できることAWS: Query2026-10-29
ダッシュボードが請求書ごとの総額・返金・手数料・純収入と支払の状態を示し、表の書き出しが案内されていることAWS Marketplace: Collections and disbursement dashboard2026-10-29
内容をサービスの改善に使い、リージョンの外に保存しうること。オプトアウトの方針で止められることAWS Organizations: AI services opt-out policies2026-10-29

明細の書式、手数料の率、支払の取り決めは、パートナーとの契約によって違います。 本記事のパートナーの設定と列の名前は例示で、製品の公開仕様で確認できた範囲だけを扱っています。売上の計上と外貨の換算の扱いは、経理と顧問の専門家で決めてください。

実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。

自社の業務に使えるAI活用候補を整理します

このユースケース(UC-2234)についてのご相談はこちらから。

AI活用について相談する
目次