FBDI 演習:AP 請求書を一括取込する
このページの列名と入力条件は、25D の Payables の公式ドキュメント(インタフェース表の説明)で確認したものです。テンプレート(PayablesStandardInvoiceImportTemplate.xlsm)の個々の列の順序・列数は確認していません。公式の説明(Payables のガイド、26C)には、テンプレートの列の順序を変えないこと、使わない列は非表示かスキップにして削除しないことが書かれています。実機では、必ず対象リリースのテンプレートを使ってください。
この演習で身につくこと
Section titled “この演習で身につくこと”- AP 請求書の FBDI の流れ(入力 → CSV 生成 → zip → アップロード → ロード → インポート → 結果確認 → 修正)を、画面とジョブの対応で説明できる
- ヘッダーと明細の関係(INVOICE_ID)と、主な列の入力条件を説明できる
- 取込前のチェック(合計・形式・重複・マスタ・期間)を Python で作り、不備を検出できる
- zip を Base64 にして
importBulkDataで投入し、ReqstIdと状態を確かめられる(モック) - リジェクトの原因を読み、直して再取込する手順を説明できる
仕組みは FBDI、API の詳細は ERP Integration Service を参照してください。
前提・準備(Fusion 環境あり/なし)
Section titled “前提・準備(Fusion 環境あり/なし)”シナリオ(架空)
Section titled “シナリオ(架空)”サンプル商事株式会社の JP01 営業単位で、旧システムに残る 10 月分の未払請求書 4 件(標準 3 件、クレジットメモ 1 件)を取り込みます。
| ID・請求書番号 | 仕入先(番号)・サイト | タイプ | 金額(円) | 明細(円) |
|---|---|---|---|---|
| 1001・INV-2026-0001 | サンプル商事株式会社(10001)・TOKYO | STANDARD | 110,000 | 100,000 + 10,000(運賃) |
| 1002・A-55120 | テスト物産株式会社(10002)・TOKYO | STANDARD | 52,800 | 48,000 + 4,800(運賃) |
| 1003・K-3003 | 架空工業株式会社(10003)・NAGOYA | STANDARD | 33,000 | 33,000 |
| 1004・CM-2026-0007 | サンプル商事株式会社(10001)・TOKYO | CREDIT | −11,000 | −11,000 |
合計はヘッダー 4 件・184,800 円、明細 6 行・184,800 円です。これが取込後に照合する期待値です。
Fusion 環境ありルート
Section titled “Fusion 環境ありルート”- テスト環境 を使います(本番では行いません)。取り込んだ請求書は、テスト環境で取消などにより整理します。
- 請求書取込とアップロードの職務ロール(Import Payable Invoice Batch、Upload data for Payables Import)を含むジョブロール。Accounts Payable Specialist に含まれます(セキュリティ演習 の表、26D 時点)。スケジュール済プロセスの作業領域には Manage Scheduled Processes(
FND_MANAGE_SCHEDULED_PROCESSES_PRIV)も必要です。UCM アカウントfin/payables/importへのアクセス権は、環境の管理者に確認します。 - Windows 版の Excel(FBDI のテンプレートは .xlsm で、Mac 版はありません)。
- 仕入先 3 社とそのサイトが、JP01 営業単位で請求書に使える状態で登録済みであること、勘定組合せと会計期間(2026 年 10 月)が使えること。自社のテスト環境の値(仕入先・サイト・BU・勘定)に読み替えます。
環境なしルート
Section titled “環境なしルート”- ターミナル(macOS、Linux、WSL)、Python 3.9 以上、
curl、base64コマンド。 - このサイトの練習用モック API。ベース URL と認証は ハンズオン演習の進め方 を参照してください。
export BASE="https://<このサイトのURL>/api/mock/fscmRestApi/resources/11.13.18.05"export FA_USER=learner FA_PASS=welcome1ステップ 1:取り込むデータの構造を理解する
Section titled “ステップ 1:取り込むデータの構造を理解する”CSV は、ヘッダー用と明細用の 2 つです。次が主な列と入力条件です(インタフェース表の公式の説明にもとづきます)。
| 列 | 入力条件 |
|---|---|
| INVOICE_ID | ヘッダーと明細をひも付けるキー。明細にも同じ値を入れる |
| OPERATING_UNIT | BU の名前。ORG_ID と両方入れて食い違うとリジェクト。ORG_ID を入れなければ、取込を実行するロールの BU が使われる |
| SOURCE | 請求書ソース。Import Payables Invoices の Source パラメータで取込対象を選ぶ。定義済みの値と一致させる |
| INVOICE_NUM | 請求書番号。同じ仕入先の中で重複するとリジェクト。空だと取込日が入る |
| INVOICE_AMOUNT、INVOICE_TYPE_LOOKUP_CODE | 金額は通貨の小数桁数以内。タイプは STANDARD か CREDIT で、金額の符号と合わせる(STANDARD は 0 以上) |
| VENDOR_NUM、VENDOR_NAME、VENDOR_SITE_CODE | 仕入先とサイトを特定する。サイトは、未指定や無効なとき既定の支払サイトなどから探し、特定できないとリジェクト |
| GL_DATE | 会計日。会計期間がオープンか将来の期間であること |
| LINE_NUMBER、LINE_TYPE_LOOKUP_CODE | 明細番号は 1 以上の整数で請求書内で一意。タイプは ITEM、FREIGHT など(ルックアップ INVOICE LINE TYPE の値) |
| AMOUNT、ACCOUNTING_DATE | 明細金額(標準請求書は正)。日付は YYYY/MM/DD |
| DIST_CODE_CONCATENATED | 配分の勘定組合せ。区切り文字は COA の定義に従う(例:100-4000-000) |
ステップ 2:CSV を用意する
Section titled “ステップ 2:CSV を用意する”Fusion 環境あり
- FBDI ガイド(File-Based Data Import (FBDI) for Financials)の Payables Standard Invoice Import から、
PayablesStandardInvoiceImportTemplate.xlsmをダウンロードします。 - ヘッダーのシートと明細のシート(インタフェース表に対応)に、シナリオの表のデータを入力します。列の順序を変えず、列も削除しません。使わない列は非表示にします。入力方法は列見出しのツールチップに書かれています。
- ステップ 7 の練習のために、1003 だけ日付を古くします。ヘッダーの GL_DATE と明細の ACCOUNTING_DATE を、オープンでない期間の日付(例:2020/01/05)にします。この不備は、ステップ 3 のチェックで検出できる種類のものですが、リジェクトを体験するため、あえて取り込みます。
- Instructions and CSV Generation シートの Generate CSV File をクリックし、zip を保存します。zip の中の CSV の名前は、テンプレートが付けたまま使います。
環境なし
作業フォルダを作り、2 つの CSV を保存します。
mkdir fbdi-lab && cd fbdi-lab
cat > ApInvoicesInterface.csv <<'EOF'INVOICE_ID,OPERATING_UNIT,SOURCE,INVOICE_NUM,INVOICE_AMOUNT,INVOICE_DATE,VENDOR_NAME,VENDOR_NUM,VENDOR_SITE_CODE,INVOICE_CURRENCY_CODE,INVOICE_TYPE_LOOKUP_CODE,DESCRIPTION,GL_DATE1001,JP01 Business Unit,External,INV-2026-0001,110000,2026/10/01,サンプル商事株式会社,10001,TOKYO,JPY,STANDARD,10月分 配送料,2026/10/011002,JP01 Business Unit,External,A-55120,52800,2026/10/03,テスト物産株式会社,10002,TOKYO,JPY,STANDARD,保守部品,2026/10/031003,JP01 Business Unit,External,K-3003,33000,2026/10/05,架空工業株式会社,10003,NAGOYA,JPY,STANDARD,加工費(9月分),2026/10/051004,JP01 Business Unit,External,CM-2026-0007,-11000,2026/10/07,サンプル商事株式会社,10001,TOKYO,JPY,CREDIT,9月分 配送料の減額,2026/10/07EOF
cat > ApInvoiceLinesInterface.csv <<'EOF'INVOICE_ID,LINE_NUMBER,LINE_TYPE_LOOKUP_CODE,AMOUNT,ACCOUNTING_DATE,DESCRIPTION,DIST_CODE_CONCATENATED1001,1,ITEM,100000,2026/10/01,配送料(10月分),101-1000-5120-0001001,2,FREIGHT,10000,2026/10/01,燃料サーチャージ,101-1000-5120-0001002,1,ITEM,48000,2026/10/03,保守部品 A-200,101-2000-5310-0001002,2,FREIGHT,4800,2026/10/03,送料,101-2000-5310-0001003,1,ITEM,33000,2026/10/05,加工費(9月分),101-3000-5410-0001004,1,ITEM,-11000,2026/10/07,配送料の減額(9月分),101-1000-5120-000EOFモックの仕入先とサイトは REST で確認できます。仕入先番号 10001 の仕入先 ID は 100000001 です。取込前に、仕入先とサイトがあることを確かめる作業の練習です(実機でも suppliers リソースで同じように確認できます)。
curl -s -u "$FA_USER:$FA_PASS" "$BASE/suppliers?limit=4&fields=SupplierId,Supplier,SupplierNumber&onlyData=true"curl -s -u "$FA_USER:$FA_PASS" "$BASE/suppliers/100000001/child/sites?fields=SupplierSite,ProcurementBU&onlyData=true"ステップ 3:取り込む前に自分でチェックする
Section titled “ステップ 3:取り込む前に自分でチェックする”FBDI は、ロードに成功してもインポートで行ごとにリジェクトされます。リジェクトされた行は、インタフェース表に残り、修正の手間が増えます。取り込む前に、典型的な不備を検出するスクリプトを用意します。次の check_ap_csv.py を保存してください。
#!/usr/bin/env python3"""AP 請求書 FBDI 用の簡略 CSV(ヘッダー行付き)を、取込の前にチェックする。
使い方: python3 check_ap_csv.py ApInvoicesInterface.csv ApInvoiceLinesInterface.csv注意: 実際の FBDI の CSV(テンプレートが生成)はヘッダー行がなく、列も 100 を超えます。 ここでは学習用に、主要列だけをヘッダー付きで並べたファイルを対象にしています。"""import csvimport reimport sysfrom collections import defaultdictfrom decimal import Decimal, InvalidOperation
# ---- 実機では、ここをマスタから作る(REST の suppliers、BI Publisher のレポートなど) ----SUPPLIER_SITES = {("10001", "TOKYO"), ("10001", "OSAKA"), ("10002", "TOKYO"), ("10003", "NAGOYA")}OPEN_PERIOD = ("2026/10/01", "2026/10/31") # GL 日付が入るべき、オープンな会計期間(例)DECIMALS = {"JPY": 0} # 通貨ごとの小数桁数(未登録の通貨は 2 桁)ACCOUNT = re.compile(r"^\d{3}-\d{4}-\d{4}-\d{3}$") # 勘定組合せの形式(自社の COA に合わせる)DATE = re.compile(r"^\d{4}/\d{2}/\d{2}$") # FBDI の日付は YYYY/MM/DD
problems = []
def ng(where, message): problems.append(f"{where}: {message}")
def read(path, columns): with open(path, encoding="utf-8-sig", newline="") as f: reader = csv.DictReader(f) missing = [c for c in columns if c not in (reader.fieldnames or [])] if missing: ng(path, f"必要な列がありません: {', '.join(missing)}") return [] return list(enumerate(reader, start=2)) # 1 行目はヘッダーなので、2 行目から数える
def money(where, text, currency): try: value = Decimal(text) except InvalidOperation: ng(where, f"金額が数値ではありません: {text!r}") return None if -value.as_tuple().exponent > DECIMALS.get(currency, 2): ng(where, f"{currency} の小数桁数を超えています: {text}") return value
def date_ok(where, name, text): if not DATE.match(text): ng(where, f"{name} は YYYY/MM/DD 形式にします: {text!r}") return False return True
def main(header_path, line_path): headers = read(header_path, ["INVOICE_ID", "OPERATING_UNIT", "SOURCE", "INVOICE_NUM", "INVOICE_AMOUNT", "INVOICE_DATE", "VENDOR_NUM", "VENDOR_SITE_CODE", "INVOICE_CURRENCY_CODE", "INVOICE_TYPE_LOOKUP_CODE", "GL_DATE"]) lines = read(line_path, ["INVOICE_ID", "LINE_NUMBER", "LINE_TYPE_LOOKUP_CODE", "AMOUNT", "ACCOUNTING_DATE", "DIST_CODE_CONCATENATED"]) by_id, seen = {}, {}
for n, h in headers: where = f"{header_path} {n} 行目(INVOICE_ID={h['INVOICE_ID']})" by_id[h["INVOICE_ID"]] = h if not h["INVOICE_NUM"]: ng(where, "INVOICE_NUM が空です(空だと取込日が請求書番号になります)") if not h["SOURCE"] or not h["OPERATING_UNIT"]: ng(where, "SOURCE と OPERATING_UNIT は入れます") key = (h["VENDOR_NUM"], h["INVOICE_NUM"]) if key in seen: ng(where, f"仕入先 {key[0]} の請求書番号 {key[1]} が {seen[key]} 行目と重複しています") seen[key] = n if (h["VENDOR_NUM"], h["VENDOR_SITE_CODE"]) not in SUPPLIER_SITES: ng(where, f"仕入先 {h['VENDOR_NUM']} にサイト {h['VENDOR_SITE_CODE']} がありません") date_ok(where, "INVOICE_DATE", h["INVOICE_DATE"]) if date_ok(where, "GL_DATE", h["GL_DATE"]) and not OPEN_PERIOD[0] <= h["GL_DATE"] <= OPEN_PERIOD[1]: ng(where, f"GL_DATE {h['GL_DATE']} がオープンな期間 {OPEN_PERIOD[0]}〜{OPEN_PERIOD[1]} の外です") kind = h["INVOICE_TYPE_LOOKUP_CODE"] if kind not in ("STANDARD", "CREDIT"): ng(where, f"INVOICE_TYPE_LOOKUP_CODE は STANDARD か CREDIT にします: {kind!r}") value = money(where, h["INVOICE_AMOUNT"], h["INVOICE_CURRENCY_CODE"]) if value is not None and kind == "STANDARD" and value < 0: ng(where, "STANDARD の金額は 0 以上にします(マイナスは CREDIT)") if value is not None and kind == "CREDIT" and value >= 0: ng(where, "CREDIT の金額はマイナスにします")
line_sum, line_nos = defaultdict(Decimal), defaultdict(set) for n, ln in lines: where = f"{line_path} {n} 行目(INVOICE_ID={ln['INVOICE_ID']})" h = by_id.get(ln["INVOICE_ID"]) if h is None: ng(where, "対応するヘッダー(INVOICE_ID)がありません") continue if not ln["LINE_NUMBER"].isdigit() or int(ln["LINE_NUMBER"]) < 1: ng(where, f"LINE_NUMBER は 1 以上の整数にします: {ln['LINE_NUMBER']!r}") elif ln["LINE_NUMBER"] in line_nos[ln["INVOICE_ID"]]: ng(where, f"LINE_NUMBER {ln['LINE_NUMBER']} が請求書内で重複しています") line_nos[ln["INVOICE_ID"]].add(ln["LINE_NUMBER"]) if ln["LINE_TYPE_LOOKUP_CODE"] not in ("ITEM", "FREIGHT", "MISCELLANEOUS"): ng(where, f"LINE_TYPE_LOOKUP_CODE が不明です: {ln['LINE_TYPE_LOOKUP_CODE']!r}") date_ok(where, "ACCOUNTING_DATE", ln["ACCOUNTING_DATE"]) if not ACCOUNT.match(ln["DIST_CODE_CONCATENATED"]): ng(where, f"DIST_CODE_CONCATENATED の形式が COA と合いません: {ln['DIST_CODE_CONCATENATED']!r}") value = money(where, ln["AMOUNT"], h["INVOICE_CURRENCY_CODE"]) if value is not None: line_sum[ln["INVOICE_ID"]] += value
total = Decimal(0) for invoice_id, h in by_id.items(): try: amount = Decimal(h["INVOICE_AMOUNT"]) except InvalidOperation: continue total += amount if invoice_id not in line_nos: ng(f"{header_path} INVOICE_ID={invoice_id}", "明細がありません") elif line_sum[invoice_id] != amount: ng(f"{header_path} INVOICE_ID={invoice_id}", f"明細の合計 {line_sum[invoice_id]} がヘッダーの金額 {amount} と一致しません")
print(f"ヘッダー {len(headers)} 件・金額合計 {total}/明細 {len(lines)} 行・金額合計 {sum(line_sum.values())}") if problems: print(f"NG:{len(problems)} 件の問題があります") for p in problems: print(" -", p) return 1 print("OK:問題は見つかりませんでした(取込の成功を保証するものではありません)") return 0
if __name__ == "__main__": if len(sys.argv) != 3: sys.exit(__doc__) sys.exit(main(sys.argv[1], sys.argv[2]))実行して、OK と、ヘッダー 4 件・明細 6 行・どちらも金額合計 184800 が出ることを確認します。
python3 check_ap_csv.py ApInvoicesInterface.csv ApInvoiceLinesInterface.csv実機のルートでも、テンプレートに入力した内容を同じ観点で確認します(合計、形式、重複、マスタ、期間)。テンプレートの入力シートは、確認用にヘッダー付きの CSV として書き出すと、このスクリプトを流用できます。
ステップ 4:不備を仕込んで、検出できるか確かめる
Section titled “ステップ 4:不備を仕込んで、検出できるか確かめる”チェックは、不備を見つけられて初めて意味があります。次の 6 か所を書き換えた CSV を bad/ に作り、チェックに通らないことを確かめます。
| 書き換える場所 | 内容 | ねらい |
|---|---|---|
| 明細 1002 の LINE_NUMBER 2 の AMOUNT | 4800 → 4500 | 明細の合計がヘッダーと合わない |
| ヘッダー 1003 の INVOICE_DATE | 2026/10/05 → 2026-10-05 | 日付の形式 |
| ヘッダー 1004 の INVOICE_NUM | CM-2026-0007 → INV-2026-0001 | 同じ仕入先内の番号の重複 |
| ヘッダー 1003 の VENDOR_SITE_CODE | NAGOYA → KYOTO | 仕入先にないサイト |
| ヘッダー 1002 の GL_DATE | 2026/10/03 → 2026/11/03 | オープンな期間の外 |
| ヘッダー 1004 の INVOICE_TYPE_LOOKUP_CODE | CREDIT → STANDARD | タイプと金額の符号の不一致 |
エディタで書き換えてもかまいません。次のスクリプトでも作れます。
不備入りの CSV を作るスクリプト(make_bad.py)
"""カレントの 2 つの CSV をコピーし、6 か所に不備を仕込んで bad/ に保存する。"""import csvimport os
# (ファイル, INVOICE_ID, 行を絞る(列, 値), 書き換える列, 新しい値)DEFECTS = [ ("ApInvoiceLinesInterface.csv", "1002", ("LINE_NUMBER", "2"), "AMOUNT", "4500"), # 合計の不一致 ("ApInvoicesInterface.csv", "1003", None, "INVOICE_DATE", "2026-10-05"), # 日付の形式 ("ApInvoicesInterface.csv", "1004", None, "INVOICE_NUM", "INV-2026-0001"), # 番号の重複 ("ApInvoicesInterface.csv", "1003", None, "VENDOR_SITE_CODE", "KYOTO"), # 未登録のサイト ("ApInvoicesInterface.csv", "1002", None, "GL_DATE", "2026/11/03"), # オープン期間の外 ("ApInvoicesInterface.csv", "1004", None, "INVOICE_TYPE_LOOKUP_CODE", "STANDARD"), # タイプと符号の不一致]
os.makedirs("bad", exist_ok=True)for name in ("ApInvoicesInterface.csv", "ApInvoiceLinesInterface.csv"): with open(name, encoding="utf-8", newline="") as f: reader = csv.DictReader(f) fields, rows = reader.fieldnames, list(reader) for file, invoice_id, narrow, column, value in DEFECTS: for row in rows: if file == name and row["INVOICE_ID"] == invoice_id and (narrow is None or row[narrow[0]] == narrow[1]): row[column] = value with open(f"bad/{name}", "w", encoding="utf-8", newline="") as f: writer = csv.DictWriter(f, fieldnames=fields, lineterminator="\n") writer.writeheader() writer.writerows(rows)print("bad/ に不備入りの CSV を作成しました")python3 make_bad.pypython3 check_ap_csv.py bad/ApInvoicesInterface.csv bad/ApInvoiceLinesInterface.csv6 件の問題が報告されれば成功です。報告された内容を見て、元のデータ(作業フォルダの CSV)が正しいことを再確認します。
ステップ 5:zip にして取り込む
Section titled “ステップ 5:zip にして取り込む”Fusion 環境あり
- ナビゲータ > ツール > File Import and Export で、zip をアップロードします。アカウントは
fin/payables/importです。 - ナビゲータ > ツール > スケジュール済プロセス(Scheduled Processes)で Load Interface File for Import を実行します。Import Process に Import Payables Invoices、Data File にアップロードした zip を指定します。状態が Succeeded になることを確認します(子ジョブの Transfer File、Load File to Interface も成功していること)。
- Import Payables Invoices を実行します。主なパラメータは次のとおりです。
- Business Unit:JP01 営業単位(自社のテスト用 BU に読み替え)
- Source:CSV の SOURCE 列と同じ値(この演習では External)
- Import Set:任意。指定すると、その Import Set の請求書だけを取り込めます。同じ Source のデータでも、要求ごとに一意の値にすると処理時間が短くなります(公式の説明、26C)
- Purge:今回は無効のままにします(結果を確認するため、インタフェース表にデータを残す)
画面の 3 つの手順は、importBulkData の 1 回の呼び出しに置き換えられます。自動化は erpintegrations を参照してください。
環境なし
zip を作り、中身を確かめます。ファイル名の ApInvoices_20261015_01.zip は、日付と連番を入れる命名の例です。
python3 -m zipfile -c ApInvoices_20261015_01.zip ApInvoicesInterface.csv ApInvoiceLinesInterface.csvpython3 -m zipfile -l ApInvoices_20261015_01.zipzip の中身が 2 つの CSV であることを確かめたら、Base64 にして importBulkData で投入します。DocumentContent は改行を含めない 1 行にします。ParameterList は、公式の例と同じ 13 個の値の並びです(2 番目が BU 名、8 番目が Source)。実機では、自環境のジョブ定義でパラメータの並びを確認します。
submit() { # 使い方: submit <zip ファイル> [FileName(省略時は zip のファイル名)] curl -s -u "$FA_USER:$FA_PASS" -H "Content-Type: application/json" -X POST "$BASE/erpintegrations" -d @- <<EOF | python3 -c "import sys, json; print(json.load(sys.stdin)['ReqstId'])"{ "OperationName": "importBulkData", "DocumentContent": "$(base64 < "$1" | tr -d '\n')", "ContentType": "zip", "FileName": "${2:-$1}", "DocumentAccount": "fin\$/payables\$/import\$", "JobName": "oracle/apps/ess/financials/payables/invoices/transactions,APXIIMPT", "ParameterList": "#NULL,JP01 Business Unit,#NULL,#NULL,#NULL,#NULL,#NULL,External,#NULL,#NULL,#NULL,1,#NULL", "CallbackURL": "#NULL", "NotificationCode": "#NULL"}EOF}REQ=$(submit ApInvoices_20261015_01.zip)echo "ReqstId = $REQ"ステップ 6:結果を確認する
Section titled “ステップ 6:結果を確認する”Fusion 環境あり
- スケジュール済プロセスで、Import Payables Invoices が終了したことを確認し、出力のレポート(Import Payables Invoices Report)を開きます。作成された件数と、リジェクトされた請求書と理由を読みます。インポートが正常終了でも、一部の行がリジェクトされていることがあります。出力の件数は毎回確認します。
- 今回の期待値は、作成 3 件・リジェクト 1 件(1003)です。ナビゲータ > Payables > Invoices で 3 件の請求書を検索し、件数と金額(1001、1002、1004)を確認します。取込直後の請求書は、検証(Validate)をまだ実行していないため、未検証の状態です。
環境なし
状態を確認する関数を定義し、すぐに 1 回、15 秒ほど待ってからもう 1 回呼びます。
status() { curl -s -u "$FA_USER:$FA_PASS" "$BASE/erpintegrations?finder=ESSJobStatusRF;requestId=$1&onlyData=true" | python3 -c "import sys, json; print(json.load(sys.stdin)['items'][0]['RequestStatus'])"}status "$REQ" # 投入の直後:WAIT(その後 RUNNING)sleep 16status "$REQ" # SUCCEEDEDモックの状態は、投入からの経過時間で決まります(5 秒まで WAIT、15 秒まで RUNNING、その後に最終の状態)。SUCCEEDED は「ジョブが終わった」ことを示すだけです。モックは zip の中身を読んでいない ので、データが正しいことの証拠にはなりません。データの正しさは、ステップ 3 の取込前チェックと、実機ではインポートの出力・インタフェース表・画面で確かめます。
ステップ 7:エラーを直して再取込する
Section titled “ステップ 7:エラーを直して再取込する”Fusion 環境あり
- ステップ 6 の出力で、1003 のリジェクトの理由が期間(会計日)に関するものであることを読み取ります。
- ナビゲータ > Payables > Invoices の Correct Import Errors(タスクまたはスプレッドシート)で、リジェクトされた行を検索します。検索条件には Business Unit、Invoice Source、Import Set、Show Only Error Lines などがあります。
- 1003 のヘッダーの GL 日付と、明細の会計日を、2026/10/05 に直します。
- 修正をアップロードして再インポートし、4 件・184,800 円になることを確認します。スプレッドシートに出ないエラー(税の設定に起因するものなど)は、プロセスのログで確認します。詳しくは ADFdi を参照してください。
- 取込済みのインタフェース表のデータは、必要に応じて Purge で整理します(FBDI のパージ)。
環境なし
- ステップ 4 の
bad/で報告された 6 件を、1 件ずつ原因を読み、bad/の CSV を直します。 check_ap_csv.pyがOKになるまで、直してはチェックを繰り返します(元の CSV と同じ内容になります)。FileNameにerrorを含めて投入すると、モックは最終的にERRORを返します。ステップ 5 のsubmitとステップ 6 のstatusを定義した同じシェルで、次を実行します。次の演習で、ログの取得とエラー処理を扱います。
REQ_ERR=$(submit ApInvoices_20261015_01.zip ApInvoices_error_01.zip)sleep 16status "$REQ_ERR" # ERROR確認ポイント
Section titled “確認ポイント”- ヘッダーと明細が INVOICE_ID でひも付くこと、明細の合計がヘッダー金額と一致する必要があることを説明できる
- ロードとインポートの 2 段階があり、ロードが成功してもリジェクトが起こることを説明できる
- 取込前のチェックで、6 種類の不備(合計、日付形式、番号の重複、サイト、期間、タイプと符号)を検出できた
- 環境なし:zip の中身が 2 つの CSV であること、
ReqstIdが返り、状態が WAIT → RUNNING → SUCCEEDED と変わることを確認できた - 環境なし:モックの
SUCCEEDEDがデータの正しさを示さない理由を説明できる - 環境あり:最初の取込で 3 件が作成され、1003 がリジェクトされた。理由を読み、Correct Import Errors で直して再取込し、4 件・184,800 円になった
ステップ 3・4:チェックの出力を表示
正しいデータの出力です。
ヘッダー 4 件・金額合計 184800/明細 6 行・金額合計 184800OK:問題は見つかりませんでした(取込の成功を保証するものではありません)不備入りのデータ(bad/)の出力です。6 件の不備が、それぞれ 1 件ずつ報告されます。
ヘッダー 4 件・金額合計 184800/明細 6 行・金額合計 184500NG:6 件の問題があります - bad/ApInvoicesInterface.csv 3 行目(INVOICE_ID=1002): GL_DATE 2026/11/03 がオープンな期間 2026/10/01〜2026/10/31 の外です - bad/ApInvoicesInterface.csv 4 行目(INVOICE_ID=1003): 仕入先 10003 にサイト KYOTO がありません - bad/ApInvoicesInterface.csv 4 行目(INVOICE_ID=1003): INVOICE_DATE は YYYY/MM/DD 形式にします: '2026-10-05' - bad/ApInvoicesInterface.csv 5 行目(INVOICE_ID=1004): 仕入先 10001 の請求書番号 INV-2026-0001 が 2 行目と重複しています - bad/ApInvoicesInterface.csv 5 行目(INVOICE_ID=1004): STANDARD の金額は 0 以上にします(マイナスは CREDIT) - bad/ApInvoicesInterface.csv INVOICE_ID=1002: 明細の合計 52500 がヘッダーの金額 52800 と一致しません実機では、これらの不備はインポートのリジェクトか、意図しない値での取込になります。取込前に防ぐほうが、修正の手間が小さくなります。
ステップ 5・6(環境なし):期待される結果を表示
zip の一覧です。
File Name Modified SizeApInvoicesInterface.csv 2026-10-15 15:03:14 764ApInvoiceLinesInterface.csv 2026-10-15 15:03:14 522ReqstId は数字だけの文字列です(例:2481859510。値は投入の時刻で変わります)。状態の遷移は、投入の直後が WAIT、数秒後が RUNNING、15 秒を過ぎると SUCCEEDED です。
モックのログ(ESSJobExecutionDetailsRF で取得できる出力)には、処理件数が 3 件と書かれます。これは固定の値で、CSV の件数(4 件)とは関係がありません。モックが zip の中身を見ていないことの表れです。ログの取得は 自動化演習 で行います。
ステップ 5・6・7(Fusion 環境あり):期待される結果を表示
- Load Interface File for Import:Succeeded。子ジョブも成功する(形式が正しければロードは通り、期間などの業務ルールは次のインポートで検証される)
- Import Payables Invoices(1 回目):作成 3 件(1001、1002、1004)、リジェクト 1 件(1003。会計日の期間に関する理由)
- 請求書(1 回目の後):3 件。1004 は −11,000 円のクレジットメモ。検証状態は未検証
- ステップ 7 の後:1003 の GL 日付と会計日を 2026/10/05 に直して再インポートすると、4 件・金額の合計 184,800 円になる
出力に表示されるリジェクトの理由の文言は、リリースにより異なります。
よくあるエラーと対処
Section titled “よくあるエラーと対処”| 症状 | 原因 | 対処 |
|---|---|---|
| ロードが失敗する(実機) | テンプレートの列の削除・並べ替え、zip 内の CSV の名前変更 | テンプレートから Generate CSV File で作り直す |
| 仕入先・サイトを特定できずリジェクト | VENDOR_NUM と VENDOR_SITE_CODE の組がない。サイト割当の漏れ | 仕入先マスタとサイト割当を確認する |
| 期間でリジェクト | GL_DATE の期間がオープンでも将来でもない | 期間をオープンするか、日付を直す |
| 請求書番号の重複でリジェクト | 同じ仕入先に同じ番号がある | 旧番号の付け替えルールを決めて直す |
| 請求書番号が取込日になっている | INVOICE_NUM が空 | 旧伝票番号を CSV に入れる |
| 取込対象が 0 件になる | Import Payables Invoices の Source が CSV の SOURCE と違う | 同じ値にそろえる |
| 400:JobName(モック) | 「パッケージ名,ジョブ定義名」のカンマが 1 つではない | oracle/apps/ess/financials/payables/invoices/transactions,APXIIMPT の形にする |
| 400:DocumentContent(モック) | Base64 に改行が入っている | base64 < file | tr -d '\n' で 1 行にする |
| 401(モック) | 認証情報がない | -u "$FA_USER:$FA_PASS" を付ける |
- 同じ 4 件を REST の
POST $BASE/invoicesで作成し(モックは保存されません)、1 件ごとに成否が返る点が FBDI とどう違うかを整理する(REST 演習 2)。 - データを 2 つのファイルに分け、Import Set を変えて 2 回投入する設計にする。並列化する場合の考え方は 移行設計 の「性能」を参照する。
- 旧システムの CSV から、この演習の簡略 CSV へ変換する Python を書く。変換ルールは、移行設計のマッピング定義書の形で先に決める。
- 請求書日付と支払条件を変え、期日が過去のものと将来のものが混ざるデータにする。OTBI 演習 のテストデータとして使える。
- 投入と状態確認、ログ取得を 1 つのスクリプトにする(自動化演習)。
公式ドキュメント
Section titled “公式ドキュメント”本サイトは学習目的で個人が作成した非公式の教材であり、Oracle Corporation およびその関連会社とは関係ありません。内容の正確性は保証しません。最新の仕様・試験範囲は必ず公式ドキュメントと Oracle University の情報で確認してください。
模擬テストの問題は公開されている出題範囲(Exam Topics)と公式ドキュメントをもとに独自に作成したもので、実際の試験問題ではありません。
Oracle、Java、MySQL は Oracle Corporation およびその子会社、関連会社の米国およびその他の国における登録商標です。その他の製品名・会社名は各社の商標です。
© 2026 Fusion ERP 実装ラボ