はじめに
SAP標準機能だけでは、企業固有のビジネスルールや業務要件に対応しきれないケースが必ず発生します。そこで登場するのがBAdI(Business Add-In)です。BAdIはSAPが提供するオブジェクト指向型の拡張ポイントで、標準プログラムのソースコードを直接変更せずにカスタムロジックを組み込める仕組みです。
なぜBAdIを知る必要があるのか。SAPプロジェクトでは「発注時に特定条件でバリデーションを入れたい」「入庫時にカスタム項目を追加したい」といった要件が頻繁に出ます。こうした要件に対してアドオン開発で対応すると、アップグレード時の影響が大きくなります。BAdIを使えば、標準プログラムとカスタムロジックを分離できるため、保守性とアップグレード耐性が格段に向上します。
SAPの拡張技術にはUser Exit(PERFORM USEREXIT_XXXで呼び出されるサブルーチン)やCustomer Exit(SMOD/CMODで管理)もありますが、これらは手続き型で再利用性が低く、複数実装もできません。BAdIはオブジェクト指向で設計されており、フィルタ値による実装の切り替えや多重実装に対応しています。Clean Core戦略の観点からも、新規開発ではBAdIの活用が推奨されます。
この記事では、MMモジュールの業務フローに沿って、購買依頼から請求書照合までの各ステップで使われる主要BAdIを解説します。
BAdIの基本構造
BAdIの仕組みを理解するには、3つの登場人物を押さえれば十分です。
flowchart LR A["標準プログラム
(例:ME21N)"] --> B(("BAdI呼び出し
ポイント")) B --> C["カスタム実装
クラス"] C --> D(("処理結果を
標準に返却")) D --> E["標準プログラム
続行"]
BAdIの管理には2つのトランザクションコードを使います。
| Tコード | 用途 | 操作内容 |
|---|---|---|
| SE18 | BAdI定義の確認 | BAdIのインターフェース、メソッド、フィルタ値を確認する |
| SE19 | BAdI実装の作成 | BAdI定義に対するカスタム実装クラスを作成する |
多重実装とは、1つのBAdI定義に対して複数の実装クラスを作成できる機能です。ただし、すべてのBAdIが多重実装に対応しているわけではありません。SE18でBAdI定義を表示すると「Multiple Use」フラグで確認できます。多重実装が許可されていないBAdI(ME_PROCESS_PO_CUSTなど)では、1つの実装に複数の要件を集約する設計が必要です。
MM業務フローとBAdI呼び出しポイント
MM業務フローの各ステップで、どのBAdIが呼び出されるかを俯瞰します。
flowchart LR A["購買依頼
ME51N"] --> B(("ME_PROCESS
_REQ_CUST")) B --> C["発注
ME21N"] C --> D(("ME_PROCESS
_PO_CUST")) D --> E["入庫
MIGO"] E --> F(("MB_MIGO
_BADI")) F --> G["請求書照合
MIRO"] G --> H(("INVOICE
_UPDATE"))
この図はあくまで代表的なBAdIを1つずつ示したものです。実際には各ステップで複数のBAdIが用意されています。以降のセクションで、各ステップの主要BAdIを詳しく見ていきます。
購買依頼(ME51N / ME52N)のBAdI
購買依頼の作成・変更時に呼び出されるBAdIです。「なぜこの段階で拡張が必要か」というと、購買依頼は調達プロセスの起点であり、ここでデータの正確性を担保しないと、後続の発注・入庫で手戻りが発生するからです。
ME_PROCESS_REQ_CUST
Enhancement Spot: ME_PROCESS_REQ_CUST 対象Tコード: ME51N, ME52N, ME53N 多重実装: 不可
| メソッド | 処理タイミング | 用途 |
|---|---|---|
| INITIALIZE | トランザクション開始時 | 初期化処理、グローバル変数のセット |
| OPEN | 購買依頼のオープン時 | 伝票データの読み込み直後の処理 |
| PROCESS_HEADER | ヘッダデータ変更時 | ヘッダレベルの項目制御・値の自動設定 |
| PROCESS_ITEM | 明細データ変更時 | 明細レベルの項目値変更・デフォルト値設定 |
| PROCESS_ACCOUNT | 勘定設定データ変更時 | 原価センタや勘定コードの自動設定 |
| CHECK | 保存・チェック実行時 | バリデーションチェック・エラーメッセージ出力 |
| CLOSE | トランザクション終了時 | 後処理・リソース解放 |
活用シーン:
- 購買依頼の金額が50万円を超える場合に承認フラグを自動設定する
- 特定の品目グループに対して固定の購買グループを自動入力する
- 勘定設定カテゴリに応じて原価センタを自動補完する(CO業務フローと連携)
- 必須項目が未入力の場合にエラーメッセージを表示して保存を防止する
ME_REQ_POSTED
対象Tコード: ME51N, ME52N
購買依頼の転記(保存)完了後に呼び出されるBAdIです。伝票番号が確定した後の後処理に使います。外部システムへの連携通知や、カスタムテーブルへのログ書き込みなどが典型的な活用シーンです。
発注(ME21N / ME22N / ME23N)のBAdI
発注処理はMMモジュールで最もBAdI拡張の需要が高い領域です。取引先ごとの個別ルールや、社内の承認ポリシーなど、企業固有の要件が集中するためです。
ME_PROCESS_PO_CUST
Enhancement Spot: ME_PROCESS_PO_CUST 対象Tコード: ME21N, ME22N, ME23N, ME29N 対象BAPI: BAPI_PO_CREATE1, BAPI_PO_CHANGE 多重実装: 不可
| メソッド | 処理タイミング | 用途 |
|---|---|---|
| INITIALIZE | トランザクション開始時 | 初期化処理 |
| OPEN | 発注伝票のオープン時 | 伝票読み込み直後の処理 |
| PROCESS_HEADER | ヘッダデータ変更時 | ヘッダ項目の自動設定・制御 |
| PROCESS_ITEM | 明細データ変更時 | 明細項目の値変更・デフォルト値設定 |
| FIELDSELECTION_HEADER | ヘッダ画面表示時 | ヘッダ項目の表示/非表示/入力可否制御 |
| FIELDSELECTION_ITEM | 明細画面表示時 | 明細項目の表示/非表示/入力可否制御 |
| CHECK | 保存・チェック時 | バリデーションチェック |
| POST | 転記完了後 | 転記後の後処理(データ変更は不可) |
| CLOSE | トランザクション終了時 | 後処理 |
活用シーン:
- 発注金額が100万円を超える場合にカスタムの承認ワークフローを起動する
- 特定の仕入先に対して支払条件を自動設定する
- 発注明細のテキスト(ロングテキスト)が未入力の場合にエラーを出す
- 特定の購買組織では特定項目を入力不可にする
注意点として、PROCESS_ITEMメソッド内でSET_DATAを呼ぶと再度PROCESS_ITEMが呼ばれるため、無限ループに陥るリスクがあります。フラグ変数で制御するか、値が変わった場合のみSET_DATAを呼ぶ設計にしてください。ABAPデバッグの技法を活用して、処理の流れを確認することを推奨します。
ME_PO_PRICING_CUST
Enhancement Spot: ME_PO_PRICING_CUST 対象: 発注の価格決定処理
発注伝票の価格決定で使用される通信構造(KOMK / KOMP)の内容を拡張するBAdIです。標準の条件テクニックでは対応できないカスタム条件値の受け渡しに使います。たとえば、カスタムマスタの値を条件テクニックに渡して、取引先ごとの特殊な価格ロジックを実現するケースです。
入庫(MIGO)のBAdI
入庫処理では、品質検査の要否判定やカスタム項目の追加といった要件が多く発生します。MIGOトランザクションはサブスクリーン構造を持つため、BAdIを使って画面を拡張できる点が特徴です。
MB_MIGO_BADI
Enhancement Spot: MB_MIGO_BADI 対象Tコード: MIGO 多重実装: 可
| メソッド | 処理タイミング | 用途 |
|---|---|---|
| INIT | 初期化時 | BAdI実装の初期化 |
| MODE_SET | アクション選択時 | 入庫/出庫/転送などのモード判定 |
| PBO_HEADER | ヘッダ画面表示前 | ヘッダ用サブスクリーンの表示制御 |
| PBO_DETAIL | 明細画面表示前 | 明細用サブスクリーンの表示制御 |
| PAI_HEADER | ヘッダ画面入力後 | ヘッダ入力値の処理 |
| PAI_DETAIL | 明細画面入力後 | 明細入力値の処理 |
| LINE_MODIFY | 明細変更・追加時 | 明細データの動的変更 |
| LINE_DELETE | 明細削除時 | 削除時の整合性チェック |
| CHECK_ITEM | 明細チェック時 | 明細単位のバリデーション |
| CHECK_HEADER | ヘッダチェック時 | ヘッダ単位のバリデーション |
| POST_DOCUMENT | 転記完了後 | 転記後の後処理 |
| HOLD_DATA_LOAD | 保留データ読み込み時 | カスタムデータの復元 |
| HOLD_DATA_SAVE | 保留データ保存時 | カスタムデータの保存 |
| HOLD_DATA_DELETE | 保留データ削除時 | カスタムデータの削除 |
活用シーン:
- 入庫時にカスタムタブを追加して検査ロットの情報を表示する
- 特定のプラントへの入庫時に追加の品質チェック項目を必須にする
- 入庫数量が発注数量の110%を超える場合に警告メッセージを出す
- 転記完了後にカスタムテーブルへ在庫移動の履歴を記録する
LINE_MODIFYメソッドは表示モードでも呼び出される点に注意してください。更新処理を入れる場合は、MODE_SETで取得したモード情報を確認してから実行する設計が必要です。
MB_DOCUMENT_BADI
対象: 在庫移動伝票の転記処理全般
MIGOだけでなく、在庫移動伝票の転記全般に適用されるBAdIです。MB_MIGO_BADIが画面に特化しているのに対し、MB_DOCUMENT_BADIはバックグラウンド処理やBAPI経由の転記でも呼び出されます。カスタムデータの伝票転記時の書き込みなどに使います。
請求書照合(MIRO)のBAdI
請求書照合はFI(財務会計)との接点であり、会計伝票の生成に直結します。そのため、バリデーションの精度が特に重要です。
INVOICE_UPDATE
Enhancement Spot: INVOICE_UPDATE 対象Tコード: MIRO 多重実装: 可
| メソッド | 処理タイミング | 用途 |
|---|---|---|
| CHANGE_AT_SAVE | INSERT/UPDATE文の実行前 | 保存前のデータ変更・バリデーション |
| CHANGE_BEFORE_UPDATE | INSERT/UPDATE文の実行後、COMMIT前 | 転記後の追加処理 |
| CHANGE_IN_UPDATE | UPDATE TASK内 | 更新タスク内での処理 |
CHANGE_AT_SAVEメソッドには例外(ERROR_WITH_MESSAGE)があり、エラーを発生させて保存を中止できます。一方、CHANGE_BEFORE_UPDATEとCHANGE_IN_UPDATEには例外がないため、バリデーション目的ならCHANGE_AT_SAVEを使うのが正しい選択です。
注意点として、メソッド内でCOMMIT WORKやROLLBACKを記述してはいけません。データの不整合を引き起こすリスクがあります。
MRM_HEADER_CHECK
対象: 請求書のヘッダデータチェック
重複請求書の拡張チェックや、カスタマイジングで設定できない独自のヘッダチェックロジックを実装するBAdIです。INVOICE_UPDATEより後に呼び出されるため、INVOICE_UPDATEで変更したデータに対するチェックも可能です。
活用シーン:
- 同一仕入先・同一金額・同一日付の請求書が既に存在する場合に警告する
- 特定の勘定コードが使われている場合に追加の承認チェックを行う
- 請求書の通貨と発注の通貨が異なる場合にエラーを出す
在庫管理・その他のBAdI
MB_RESERVATION_BADI
対象Tコード: MB21, MB22(予約の登録・変更)
予約伝票の作成・変更時に呼び出されるBAdIです。PP(生産管理)との連携で、製造オーダに基づく予約の自動チェックなどに活用します。
ME_DEFINE_CALCTYPE
対象: 購買伝票の価格計算タイプ決定
購買伝票の価格計算タイプ(正味価格計算 / 総額計算など)を動的に切り替えるBAdIです。仕入先や品目グループに応じて計算方式を変えたい場合に使います。
ME_BAPI_PR_CUST
対象: 購買依頼のBAPI処理(BAPI_PR_CREATE, BAPI_PR_CHANGE)
ME_PROCESS_REQ_CUSTが画面トランザクション(ME51N等)向けなのに対し、ME_BAPI_PR_CUSTはBAPI経由での購買依頼作成・変更時に呼び出されます。外部システムからの連携で購買依頼を作成する場合は、こちらのBAdIを使います。
BAdI実装のベストプラクティス
パフォーマンスへの配慮
BAdIのメソッドは画面操作のたびに繰り返し呼び出されます。PROCESS_ITEMメソッドは明細行が変わるたびに実行されるため、メソッド内でSELECT文を毎回実行するとパフォーマンスが大幅に劣化します。初回呼び出し時にデータを内部テーブルにキャッシュし、以降はメモリから読み取る設計にしてください。ABAPパフォーマンスチューニングの手法が直接役立ちます。
フィルタ値の活用
BAdIによってはフィルタ値を設定でき、特定の購買組織やプラントに限定して実装を有効化できます。不必要な範囲で実装が動かないよう、フィルタ値は可能な限り絞り込みます。
テストとデバッグ
BAdIのデバッグには、実装クラスのメソッドに直接ブレークポイントを設定するのが効率的です。SE19で実装クラス名を確認し、SE24でクラスを開いてブレークポイントを設定します。また、SE16でテーブルSXC_ATTRを参照すると、BAdI実装の有効/無効状態を確認できます。
Clean Core対応
S/4HANAへの移行を見据えるなら、Clean Core戦略に沿った設計が重要です。Released APIとして公開されているBAdIのみを使い、非公開のBAdIへの依存は避けることで、将来のアップグレードリスクを最小化できます。
よくある疑問(FAQ)
Q1. BAdIとUser Exitはどちらを使うべきか?
新規開発であればBAdIを使ってください。User Exitは手続き型のサブルーチンで、アップグレード時に再実装が必要になるリスクがあります。BAdIはオブジェクト指向で、標準コードとの分離が明確です。既存のUser Exitが稼働中のシステムでは無理に置き換える必要はありませんが、新しい要件にはBAdIを選択するのが定石です。
Q2. 同じBAdIに複数の実装を作れるか?
SE18でBAdI定義を表示し「Multiple Use」フラグがオンになっていれば複数の実装を作成できます。ME_PROCESS_PO_CUSTのように多重実装不可のBAdIでは、1つの実装クラス内で条件分岐して複数要件に対応する設計が必要です。MB_MIGO_BADIは多重実装が可能です。
Q3. BAdI実装が動かない場合のデバッグ方法は?
まずSE19で実装が「有効」になっているか確認します。次に、フィルタ値が正しく設定されているか確認します。それでも動かない場合は、SE18でBAdI定義のインターフェース名を確認し、標準プログラム内でそのインターフェースがCALL METHOD GETで呼び出されている箇所にブレークポイントを設定します。ABAPデバッグの基本も参照してください。
Q4. S/4HANAでもBAdIは使えるか?
使えます。S/4HANAではむしろBAdIが拡張の中心的な仕組みです。ただし、ECC時代のBAdIがすべてS/4HANAで利用可能とは限りません。S/4HANA固有の新しいBAdI(Enhancement Spot)が追加されている場合もあるため、SE18で対象のBAdIが存在するかを必ず確認してください。
Q5. 使えるBAdIの一覧はどう調べるか?
3つの方法があります。(1) SE18でBAdI名をワイルドカード検索する。(2) 対象トランザクションの標準プログラム内で「CL_EXITHANDLER」を検索し、呼び出されているBAdIを特定する。(3) トランザクションSE24でインターフェース名「IF_EX_*」を検索する。最も確実なのは(2)の方法で、実際の呼び出し箇所からBAdI名とメソッド名を両方確認できます。
Q6. BAdIの中でデータベース更新は可能か?
メソッドによります。CHECK系メソッドはバリデーション用途のため、DB更新は避けるべきです。POST系メソッド(転記完了後に呼ばれるもの)であればカスタムテーブルへの書き込みは可能ですが、COMMIT WORKは標準プログラムが制御するため、メソッド内では記述しないでください。
BAdI実装の前にABAPの基礎を固めたい人へ
BAdIはオブジェクト指向ABAPの世界なので、クラス・メソッド・インタフェース・内部テーブル・SELECTといったABAPの基本文法がひと通り入っていないと、SE19で実装画面を開いた瞬間に手が止まりがちです。MMの業務知識とABAPの基礎、両方が揃って初めて「BAdIで何をどう書くか」が見えてきます。
ABAP側がまだ曖昧な状態であれば、アレグス株式会社・久米正通氏の『SAP ABAPプログラミング入門』のような体系的な入門書を1冊やっておくのがおすすめです。拡張ポイントのサンプルコードを写経するときに、各文の意味を立ち止まらずに読めるようになるだけでも、BAdI実装の進みが大きく変わります。
まとめ
- BAdIはSAPの標準コードを変更せずにカスタムロジックを組み込めるオブジェクト指向型の拡張ポイント
- MMモジュールでは購買依頼(ME_PROCESS_REQ_CUST)、発注(ME_PROCESS_PO_CUST)、入庫(MB_MIGO_BADI)、請求書照合(INVOICE_UPDATE)が4大BAdI
- ME_PROCESS_PO_CUSTは最も利用頻度が高く、PROCESS_ITEMメソッドでの無限ループに注意が必要
- MB_MIGO_BADIは画面拡張(サブスクリーン追加)にも対応しており、多重実装が可能
- INVOICE_UPDATEのバリデーションにはCHANGE_AT_SAVEメソッドを使う(例外を発生させて保存中止が可能)
- BAdI管理にはSE18(定義確認)とSE19(実装作成)を使う
- パフォーマンス劣化を防ぐため、メソッド内のDB読み取りはキャッシュ設計にする
- S/4HANA移行を見据えてReleased APIとして公開されたBAdIを優先的に使う
BAdIの実装力をさらに高めるには、ABAPの基礎からRAP・ODataまでカバーした実践講座で体系的に学ぶのが効率的です。BAdI実装クラスの読み書きはもちろん、Clean Core時代のRAPベースの拡張手法まで全335レクチャーで身につきます。