調達から支払いまで:購買発注データテンプレート
調達から支払いまで:購買発注データテンプレート
- 収集を推奨する属性
- 追跡すべき主要なアクティビティ
- SAP ECCからの抽出ガイド
調達から支払いまで:発注書の属性
| 名前 | 説明 | ||
|---|---|---|---|
| アクティビティ Activity | 購買発注のライフサイクル内で発生した、特定の業務イベントまたはステップの名称です。 | ||
| 説明 この属性は、「購買発注作成」、「購買発注承認」、「入庫計上」など、プロセス内の1つのステップを表します。これらのアクティビティの順序によって、各購買発注のプロセスフローが形成されます。 アクティビティの順序、頻度、間隔を分析することは、プロセスマイニングの中心的な機能です。ボトルネック、手戻りループ、標準プロセスからの逸脱を特定し、改善と標準化を重点的に進められます。 重要な理由 アクティビティはプロセスの各ステップを定義します。その順序とタイミングを分析することで、実際のプロセスフロー、ボトルネック、逸脱を把握できます。 入手先 CDHDR/CDPOS(変更)、EKBE(入庫/請求書照合)、EBAN(購買依頼)など、さまざまなSAPテーブルとトランザクションログから導出します。生成には、カスタムロジックまたは抽出プログラムが必要になることがあります。 例 購買発注作成購買発注承認入庫計上 | |||
| イベント時刻 EventTime | アクティビティが発生した正確な日時です。 | ||
| 説明 このタイムスタンプは、購買発注が承認された時刻や入庫が計上された時刻など、イベントが発生した正確な瞬間を示します。ケース内のすべてのアクティビティを時系列に並べるために使用します。 タイムスタンプは、プロセスマイニングの基盤です。アクティビティ間のサイクル時間の算出、遅延の特定、プロセスの処理量の分析、サービスレベル合意(SLA)に対するパフォーマンスの測定など、時間に基づく分析を可能にします。 重要な理由 サイクル時間やボトルネックなど、所要時間に基づくすべての指標を算出し、イベントを時系列に並べるために欠かせないタイムスタンプです。 入手先 EKKO-AEDAT(変更日)、CDHDR-UDATE/UTIME(変更ログのタイムスタンプ)、EKBE-BUDAT(転記日)など、SAPテーブルのさまざまな日付項目と時刻項目から導出します。 例 2023-04-15T10:05:31Z2023-04-16T14:22:00Z2023-05-01T09:00:15Z | |||
| 購買発注 PurchaseOrder | 調達プロセスを追跡する際の主要なケースとなる、購買発注(PO)伝票の一意の識別子です。 | ||
| 説明 購買発注番号は、作成から最終入庫、完了までのすべてのアクティビティを結び付ける中心的な識別子です。一意の購買発注番号ごとに、調達プロセスの1つのインスタンスを表します。 プロセスマイニングでは、各購買の開始から完了までの流れを再構築するために、この属性が欠かせません。個々の発注について、サイクル時間、プロセスのばらつき、コンプライアンスチェックを詳細に分析でき、プロセスモデル全体の基盤になります。 重要な理由 関連するすべてのイベントを結び付ける中核的な識別子であり、個々の購買発注のライフサイクル全体を分析できます。 入手先 テーブル:EKKO、項目:EBELN 例 450001762345000176244500017625 | |||
| ユーザー名 UserName | アクティビティを実行したユーザーのユーザーIDです。 | ||
| 説明 この属性は、伝票を作成、変更、承認した従業員のSAPユーザー名を記録します。自動化されたステップでは、システムユーザーまたはバッチユーザーのIDが表示される場合があります。 ユーザー別に分析することで、トレーニングの必要性、パフォーマンスの高い担当者、コンプライアンス上の潜在的な問題を特定できます。業務量の分布、承認マトリクスへの準拠、チームや個人ごとのパフォーマンスに関するダッシュボードの構築にも役立ちます。 重要な理由 ユーザーの操作を個人に結び付け、ユーザーのパフォーマンス、業務量、コンプライアンス手順の遵守状況を分析できます。 入手先 テーブル:EKKO、項目:ERNAM(作成者)、テーブル:CDHDR、項目:USERNAME(変更者)。 例 JSMITHMBROWNBATCH_USER | |||
| 仕入先番号 VendorNumber | 仕入先を一意に識別する番号です。 | ||
| 説明 商品またはサービスの調達先である仕入先を一意に識別するコードです。調達プロセスにおける重要なマスターデータです。 この属性は、仕入先を軸とした分析に欠かせません。仕入先の納入パフォーマンスの評価、仕入先間のリードタイム比較、支出パターンの分析が可能になります。「仕入先納入パフォーマンス」ダッシュボードの主要な分析軸です。 重要な理由 仕入先のパフォーマンスを分析し、信頼できる仕入先や、遅延・品質問題の原因となっている仕入先を特定できます。 入手先 テーブル:EKKO、項目:LIFNR 例 100345V-20598700112 | |||
| 会社コード CompanyCode | 購買を開始する法人または会社を識別するコードです。 | ||
| 説明 会社コードは、SAPにおける独立した法人を表します。すべての取引は会社コード単位で計上されるため、基本的な組織単位となります。 会社コード別にプロセスを分析することで、異なる事業部門や国の調達効率とコンプライアンスを比較できます。ある法人のベストプラクティスを他の法人へ展開したり、プロセスに課題を抱える特定の法人を特定したりできます。 重要な理由 法人を表し、組織内の異なる部門や地域にまたがるプロセスパフォーマンスの比較とコンプライアンスチェックを可能にします。 入手先 テーブル:EKKO、項目:BUKRS 例 10002100US01 | |||
| 伝票タイプ DocumentType | 購買発注の種類を分類するコードです。 | ||
| 説明 伝票タイプはSAPの設定項目であり、購買発注の番号範囲、項目選択、全体的なプロセスフローを制御します。標準購買発注、サービス購買発注、在庫転送発注など、種類ごとに異なる設定を定義できます。 この属性は分析に有効な軸です。伝票タイプが異なると、意図的に異なるプロセスに従うことが多いためです。伝票タイプで絞り込むことで、サイクル時間やプロセスフローをより正確に比較できます。 重要な理由 異なる購買プロセスの種類(標準、サービス、返品など)を区別します。種類ごとに経路や期待されるパフォーマンスが異なる場合があります。 入手先 テーブル:EKKO、項目:BSART 例 NBFOUB | |||
| 品目グループ MaterialGroup | 特性が類似する品目またはサービスをまとめるための分類です。 | ||
| 説明 品目グループ、つまり購買カテゴリは、調達する商品またはサービスの種類を分類するために使用します。例として、「ITハードウェア」、「事務用品」、「専門サービス」などがあります。 この属性は、支出分析と調達パターンの把握に欠かせません。カテゴリ別にプロセスを絞り込み、処理方法、承認者、供給する仕入先を分析できます。「購買発注金額分析」ダッシュボードの主要な分析軸です。 重要な理由 商品またはサービスのカテゴリ別にプロセスを分けて分析し、支出の種類ごとの行動、サイクル時間、仕入先の違いを明らかにします。 入手先 テーブル:EKPO、項目:MATKL 例 00101IT_HWCONSULT | |||
| 発注金額 OrderAmount | 購買発注明細の合計金額です。 | ||
| 説明 この属性は、購買発注の特定の明細の合計金額を表します。数量に正味価格を掛けて算出します。購買発注全体の金額を求める場合は、明細金額を集計する必要があります。 発注金額でプロセスを分析することは、より厳格な管理や異なる承認経路が必要な高額取引を特定するうえで重要です。「購買発注金額分析」ダッシュボードを支え、金額の大きい発注を優先してプロセス改善を進めるのに役立ちます。 重要な理由 各購買の財務的な影響を数値化し、金額に基づく分析によって高額発注の優先順位付けやコスト削減機会の特定を可能にします。 入手先 テーブル:EKPO、項目:NETWR(正味発注金額)。 例 1500.00250.7512345.50 | |||
| ソースシステム SourceSystem | データを抽出したシステムです。 | ||
| 説明 データの取得元を識別する属性です。通常は、SAP ECCのインスタンス識別子(例:「ECC_PROD_100」)を使用します。複数のシステムがある環境では、データソースを区別するのに役立ちます。 ガバナンスとデータリネージュの観点から、ソースシステムの把握は重要です。データの整合性を確保し、特に異なるERPシステムやモジュールからデータを統合する場合に、抽出や品質に関する問題のトラブルシューティングに役立ちます。 重要な理由 データの取得元を示します。データガバナンス、検証、複数システムにまたがる分析の管理に欠かせません。 入手先 通常は、データ抽出プロセスの実行時に、データセットの取得元システムを示す静的な値として追加します。 例 SAP_ECC_PRODECC_EU_100S4H_FIN | |||
| プラント Plant | 商品を納入する物理的な場所またはプラントです。 | ||
| 説明 プラントは、商品またはサービスを受け入れる生産施設、倉庫、その他の場所を表す組織単位です。 プラント別に分析することで、調達プロセスにおける地域差を把握できます。特定の場所への仕入先の納入時間の違いや、受入プロセスが非効率なプラントを明らかにし、入庫の適時性を分析できます。 重要な理由 納入場所を示し、地域ごとのプロセスの違いや物流パフォーマンスを分析するのに役立ちます。 入手先 テーブル:EKPO、項目:WERKS 例 100011002000 | |||
| 仕入先名 VendorName | 仕入先の正式名称です。 | ||
| 説明 仕入先番号よりも利用者にとって分かりやすい、仕入先の名称です。通常は仕入先マスターデータから取得します。 仕入先番号が結合や一意の識別に使われるのに対し、仕入先名は利用者向けのダッシュボードやレポートに欠かせません。仕入先コードに詳しくない業務担当者にも、分析内容を直感的に理解してもらえます。 重要な理由 仕入先を人が読みやすい名称で表示し、業務担当者にとってダッシュボードやレポートを理解しやすくします。 入手先 テーブル:LFA1、項目:NAME1。EKKO-LIFNRからLFA1-LIFNRへの結合が必要です。 例 Staples Inc.Global Tech SolutionsOffice Supply Co. | |||
| 最終データ更新 LastDataUpdate | ソースシステムからデータが最後に更新された日時を示すタイムスタンプです。 | ||
| 説明 この属性は、直近のデータ抽出または更新の日時を記録します。分析対象データの鮮度を把握するための情報になります。 ダッシュボードにこの情報を表示することは、分析がほぼリアルタイムのデータに基づくものか、過去のスナップショットに基づくものかを理解するうえで重要です。利用者の期待値を適切に管理し、データの経過時間が明確な状態で意思決定できるようにします。 重要な理由 データの適時性を利用者に伝え、分析が業務の最新状況を反映しているかを理解できるようにします。 入手先 データ抽出またはETLプロセスの実行時に、そのプロセスによって生成・追加されるタイムスタンプです。 例 2023-10-27T02:00:00Z2023-10-28T02:00:00Z | |||
| 却下理由 RejectionReason | 購買依頼または購買発注が却下された理由を説明する理由コードまたはテキストです。 | ||
| 説明 この属性には、承認ワークフロー中に購買発注が却下された際に示された具体的な理由が記録されます。手戻りや遅延の根本原因を把握するうえで重要な情報です。 却下理由を分析すると、価格の誤り、予算超過、コンプライアンスに適合しない仕入先選定など、共通する問題を特定できます。この情報をもとに根本原因へ対処し、PO作成時の品質を高め、承認プロセスを効率化できます。 重要な理由 承認が失敗する理由を直接把握できるため、手戻りの削減や承認サイクルの短縮に向けた改善を進められます。 入手先 この情報は見つけにくい場合があります。長いテキストフィールドに保存されていたり、カスタムワークフローの設定に依存していたりするためです。多くの場合、特定の実装知識が必要です。 例 価格が不正確予算超過重複した申請 | |||
| 希望納入日 RequestedDeliveryDate | 業務部門が仕入先に商品またはサービスの納入を求める日付です。 | ||
| 説明 購買発注で指定する納入目標日です。実際の納入パフォーマンスを測定する際の基準になります。 この日付は、「納期遵守入庫率」KPIの算出に欠かせません。実際の入庫日と希望納入日を比較することで、仕入先の信頼性と社内の受入業務の効率を定量的に測定でき、「仕入先納入パフォーマンス」ダッシュボードを支えます。 重要な理由 納入の目標日であり、納期遵守パフォーマンスKPIの算出と仕入先の信頼性評価に欠かせません。 入手先 テーブル:EKPO、項目:EINDT 例 2023-06-102023-07-222023-08-01 | |||
| 承認後変更か IsPostApprovalChange | 初回承認後にPOの変更が発生したかどうかを示すフラグです。 | ||
| 説明 このブール型の属性は、同じPOについて「Purchase Order Approved」アクティビティの後に「Purchase Order Changed」アクティビティが検出された場合にtrueになります。プロセスの後半で発生する問題のある変更を切り分けるのに役立ちます。 この計算フィールドは、「Post-Approval PO Change Rate」KPIと「Purchase Order Rework and Changes」ダッシュボードに直接対応します。遅延や再承認の原因となる影響の大きい変更を定量化して明らかにし、初期仕様やスコープ設定の問題を特定できます。 重要な理由 承認後の手戻りを直接測定する指標であり、プロセスの安定性と効率を評価する重要なKPIです。割合が高い場合、上流の要件定義に問題がある可能性があります。 入手先 イベントログ内のアクティビティの順序から導出される計算属性です。 例 truefalse | |||
| 納期遵守 IsOnTimeDelivery | 商品が要求納期までに受領されたかどうかを示すフラグです。 | ||
| 説明 このブール型の属性は、「Goods Receipt Posted」アクティビティのタイムスタンプが「Requested Delivery Date」以前の場合にtrueになります。PO明細ごとの納期遵守状況を、明確な二値の結果として示します。 この属性は、「On-Time Goods Receipt Rate」KPIの基盤となります。納期どおりの納品と遅延納品を簡単に集計・フィルタリングできるため、仕入先のパフォーマンスと社内の受入業務の効率を分析しやすくなります。 重要な理由 納期遵守について、成功または失敗を明確に示す指標です。仕入先のパフォーマンスKPIやダッシュボードに直接対応します。 入手先 入庫計上日(EKBE-BUDAT)と要求納期(EKPO-EINDT)を比較して算出される計算属性です。 例 truefalse | |||
| 購買グループ PurchasingGroup | 調達業務を担当する個人または購買担当者のグループです。 | ||
| 説明 購買グループは、特定の購買業務を担当する個人または購買担当者のチームを表します。仕入先との主な窓口となります。 この属性は、購買組織よりも詳細な分析を可能にします。購買担当者間の業務量の分布を把握し、担当者単位のパフォーマンスの違いを特定できます。リソース配分やトレーニング施策の検討にも役立ちます。 重要な理由 購買を担当する個人またはチームを詳細に把握し、担当者やチーム単位で業務量とパフォーマンスを分析できます。 入手先 テーブル:EKKO、項目:EKGRP 例 001002N01 | |||
| 購買依頼 PurchaseRequisition | 購買発注に先行する購買依頼の識別子です。 | ||
| 説明 購買発注を起点となった購買依頼に結び付ける属性です。すべての購買発注に先行する購買依頼があるとは限りません。 この関連付けは、「購買依頼から発注への変換」ダッシュボードと「購買依頼から購買発注への変換率」KPIの分析に欠かせません。初回依頼から正式な発注の作成まで、上流プロセスの効率を測定し、購買依頼なしで作成されたコンプライアンス違反の購買発注を特定できます。 重要な理由 購買発注を元の依頼に結び付け、購買依頼から購買発注への変換プロセスを分析するとともに、先行する購買依頼なしで作成された購買発注を特定できます。 入手先 テーブル:EKPO、項目:BANFN 例 1001589010015891 | |||
| 購買組織 PurchasingOrganization | 価格交渉と商品またはサービスの調達を担う組織単位です。 | ||
| 説明 購買組織は、SAPで調達業務を担う主要な組織単位です。会社全体で集中管理することも、プラントや地域ごとに分散管理することもできます。 購買組織別にプロセスパフォーマンスを分析することで、効率の高い調達チームを特定できます。サイクル時間、手戻り率、コストなどの指標を組織単位で比較し、ベストプラクティスや支援が必要な領域を明らかにします。 重要な理由 担当する調達チームを識別し、異なる組織単位間でパフォーマンスを比較・分析できます。 入手先 テーブル:EKKO、項目:EKORG 例 1000US01DE01 | |||
| 通貨 Currency | 購買発注金額の通貨コードです。 | ||
| 説明 この属性は、購買発注金額の通貨を示します。USD、EUR、GBPなどが該当します。金額を解釈するために必要な情報です。 グローバルな組織では、正確な財務分析に通貨情報が欠かせません。発注金額を正しく集計・比較でき、すべての金額KPIを通貨の前提と合わせて解釈できます。 重要な理由 すべての金額に必要な前提を示し、特に多国籍組織における正確な財務分析を支えます。 入手先 テーブル:EKKO、項目:WAERS 例 USDEURJPY | |||
調達から支払いまで:発注書のアクティビティ
| アクティビティ | 説明 | ||
|---|---|---|---|
| 入庫計上 | 特定の購買発注に対して、仕入先から商品を物理的に受け取ったことを示します。入庫計上は、MIGOなどのトランザクションで実行される明示的な操作であり、品目伝票を作成して在庫を更新します。 | ||
| 重要な理由 仕入先の納入パフォーマンスを追跡し、請求書照合プロセスの開始点を把握するための重要な節目です。納期遵守率と入庫の適時性の算出に使用します。 入手先 品目伝票の作成時に記録されます。イベントのタイムスタンプには、品目伝票ヘッダーテーブル(MKPF)の転記日(MKPF-BUDAT)または作成日(MKPF-CPUDT)を使用します。品目テーブル(MSEG)を介して購買発注に関連付けられます。 取得 購買発注を参照する品目伝票について、MKPFテーブルの転記または作成タイムスタンプを使用します。 イベントタイプ explicit | |||
| 購買依頼作成 | このアクティビティは、商品またはサービスに対する正式な依頼が作成されたことを示します。ユーザーが新しい購買依頼伝票を保存した際に記録される明示的なイベントです。ME51Nなどのトランザクションによって、EBANテーブルに一意のレコードが作成されます。 | ||
| 重要な理由 調達プロセスの主な開始点です。このイベントから購買発注の作成までの時間を分析することで、社内の需要を実行可能な発注に変換する効率を測定できます。 入手先 購買依頼ヘッダーテーブル(EBAN)にエントリが作成された時点で記録されます。作成日(EBAN-BADAT)と時刻が、このイベントのタイムスタンプになります。 取得 作成日を基に、EBANテーブルの新しいエントリを特定します。 イベントタイプ explicit | |||
| 購買発注を仕入先へ送付 | 承認済みの購買発注が、EDI、メール、印刷などを通じて正式に仕入先へ送信された時点を示します。出力メッセージが正常に処理された際に、メッセージ管理テーブルへ記録される明示的なイベントです。 | ||
| 重要な理由 仕入先のリードタイムの計測が始まる重要な節目です。このイベントから入庫までの時間を分析することで、仕入先のパフォーマンスと納期遵守状況を評価できます。 入手先 メッセージステータステーブル(NAST)に記録されます。該当する購買発注の出力タイプについて、処理ステータス(NAST-VSTAT)が「1」(正常処理済み)の場合、NAST-DATVRとNAST-UHRVRからタイムスタンプを取得できます。 取得 購買発注の出力メッセージについて、NASTテーブルの処理タイムスタンプを使用します。 イベントタイプ explicit | |||
| 購買発注作成 | このアクティビティは、仕入先との拘束力のある契約となる正式な購買発注伝票が作成されたことを示します。ユーザーが購買発注を作成して保存した際に記録される明示的なイベントです。ME21Nなどのトランザクションにより、EKKOテーブルとEKPOテーブルにエントリが作成されます。 | ||
| 重要な理由 購買発注のライフサイクルが正式に始まったことを示します。購買依頼から購買発注への変換時間と、発注から納品完了までの所要時間を測定する重要な節目です。 入手先 該当する購買発注番号(EKKO-EBELN)について、購買発注ヘッダーテーブル(EKKO)の作成日(EKKO-AEDAT)から取得します。 取得 新しい購買発注ごとに、EKKOテーブルの作成タイムスタンプを使用します。 イベントタイプ explicit | |||
| 購買発注完了 | 購買発注明細が全量納入済みとみなされたことを示します。通常は、購買発注明細の「納入完了」インジケーターが自動または手動で設定されたことから推定されるイベントです。 | ||
| 重要な理由 発注履行プロセスの論理的な終点になります。作成から完了までの購買発注サイクル全体の所要時間を算出するために欠かせません。 入手先 購買発注明細の「納入完了」インジケーター(EKPO-ELIKZ)が「X」に設定された時点を記録する変更文書(CDHDR/CDPOS)から推定します。最後の明細が完了とマークされた時点を、購買発注全体の完了とみなせます。 取得 EKPO-ELIKZフラグが設定された時点のタイムスタンプを、変更文書から特定します。 イベントタイプ inferred | |||
| 購買発注承認 | 購買発注が最終承認され、仕入先に送付できる状態になったことを示します。通常は、購買発注のリリースステータスが「完全リリース済み」または「承認済み」に変更されたことから推定される重要な節目です。 | ||
| 重要な理由 このアクティビティは、購買発注承認サイクル時間KPIの算出と、承認ワークフローのボトルネック特定に欠かせません。仕入先への発注送付など、その後の多くのアクティビティの前提条件です。 入手先 購買発注ヘッダーテーブル(EKKO)の変更ログ(CDHDR/CDPOS)を追跡し、最終リリースコードが適用された時点、または全体リリースステータスインジケーター(EKKO-FRGKE)が「リリース済み」に設定された時点を特定します。 取得 購買発注の全体リリースステータス(EKKO-FRGKE)が最終承認状態に変更された時点のタイムスタンプを特定します。 イベントタイプ inferred | |||
| サービス確認入力 | サービスに基づく購買発注では、サービスが提供されたことの確認を示します。サービス入力シートの作成を通じて記録される明示的なイベントです。ML81Nなどのトランザクションを使用します。 | ||
| 重要な理由 サービスに対する入庫に相当し、サービス発注の履行状況を追跡するうえで欠かせません。サービス料金の支払いに向けた財務プロセスを開始します。 入手先 サービス入力シートヘッダーテーブル(ESSR)の作成日(ESSR-ERDAT)から取得します。購買発注との関連付けはESLLテーブルにあります。 取得 購買発注に関連付けられたサービス入力シートについて、ESSRテーブルの作成タイムスタンプを使用します。 イベントタイプ explicit | |||
| 品質検査実施 | 入庫した商品について品質検査が実施されたことを示します。通常は、入庫時に作成された検査ロットに対して、品質管理モジュールで使用決定が行われた時点から推定します。 | ||
| 重要な理由 品質が重視される業界では、検査プロセスの所要時間と結果を分析するのに役立ちます。この段階の遅延は、入庫から使用可能になるまでの間にボトルネックを生む可能性があります。 入手先 品質管理モジュールから推定します。入庫時に検査ロットが作成され(QALSテーブル)、タイムスタンプを含む使用決定が作成された時点でアクティビティを記録します(QAVEテーブル)。 取得 品目伝票に関連付けられた検査ロットについて、QAVEテーブルの使用決定のタイムスタンプを特定します。 イベントタイプ inferred | |||
| 購買依頼承認 | 購買依頼が購買発注に変換できるよう、正式に承認されたことを示します。このイベントは、SAPのリリース戦略ワークフローで追跡される購買依頼データのリリースステータス項目の変更から推定されます。 | ||
| 重要な理由 承認を追跡することは、発注前の段階にあるボトルネックを特定し、承認ポリシーへのコンプライアンスを確保するうえで重要です。この段階の遅延は、調達サイクル全体の所要時間に直接影響します。 入手先 購買依頼テーブル(EBAN)の変更ログから推定します。具体的には、リリースステータス項目(例:EBAN-FRGZU)の変更を監視するか、EBANオブジェクトについてCDHDR/CDPOSの変更文書を分析します。 取得 EBANのリリースステータス項目に関する変更文書を監視し、最終承認のタイムスタンプを特定します。 イベントタイプ inferred | |||
| 購買発注の承認依頼 | 作成または変更された購買発注が、設定済みのリリース戦略に従って承認に提出されたことを示します。リリース戦略が起動し、購買発注が承認待ちのステータスになった時点から推定されるイベントです。 | ||
| 重要な理由 購買発注の作成と承認プロセスの開始を区別することで、承認サイクル時間KPIを正確に測定できます。承認ワークフローが始まるまでの遅延も明らかになります。 入手先 リリースステータスの初期設定を示す購買発注(オブジェクトEINKBELEG)の変更文書(CDHDR/CDPOS)から推定します。または、全体リリースステータス(EKKO-FRGKE)が、承認プロセスの開始を示す値に初めて設定された時点から推定します。 取得 購買発注のリリース戦略を起動した最初の変更文書エントリを特定します。 イベントタイプ inferred | |||
| 購買発注削除 | 購買発注明細の取消しまたは論理削除を示し、入庫や請求などの後続処理を停止します。購買発注明細に削除インジケーターが設定された時点で記録される推定イベントです。 | ||
| 重要な理由 発注が取り消されたことを示す終端アクティビティです。発注が削除された理由と時期を分析することで、需要計画や仕入先選定の問題を明らかにできます。 入手先 購買発注明細の削除インジケーター(EKPO-LOEKZ)が「L」に設定されたことを示す変更文書(CDHDR/CDPOS)から推定します。 取得 EKPO-LOEKZフラグが設定された時点のタイムスタンプを、変更文書から特定します。 イベントタイプ inferred | |||
| 購買発注却下 | 承認者が承認ワークフロー中に購買発注を却下した際に発生します。購買発注のリリース戦略データにおけるステータス変更から、却下が発生したことを示す推定イベントです。 | ||
| 重要な理由 却下を追跡することで、購買発注のデータ品質、ポリシー違反、承認マトリクスの問題を特定できます。却下は手戻りにつながることが多く、サイクル全体の所要時間を増加させます。 入手先 購買発注のリリースステータスに関する変更文書(CDHDR/CDPOS)から推定します。通常は、リリースコードが取り消された時点、または特定の却下ステータスが設定された時点で記録されます。 取得 リリースコードの取消し、または却下を示すステータス変更について変更ログを監視します。 イベントタイプ inferred | |||
| 購買発注変更 | 初回作成後に購買発注へ加えられた変更を示します。数量、価格、納期などの変更が該当します。これらの変更は、SAPの変更文書システムに明示的に記録されます。 | ||
| 重要な理由 特に承認後の頻繁な変更は、プロセスの非効率、初期計画の不備、またはスコープの拡大を示します。このアクティビティは、購買発注の手戻りと変更に関するダッシュボードおよび関連KPIに欠かせません。 入手先 購買発注オブジェクト(EINKBELEG)について、変更文書ヘッダー(CDHDR)テーブルと明細(CDPOS)テーブルに明示的に記録されます。変更ごとにタイムスタンプ付きの新しいエントリが作成されます。 取得 購買発注番号に関連付けられたCDHDRテーブルとCDPOSテーブルから、変更イベントとタイムスタンプを抽出します。 イベントタイプ explicit | |||
| 返品 | 受け取った商品を、品質上の問題や誤納品などの理由で仕入先へ返却したことを示します。返品専用の移動タイプで品目伝票を転記することで記録される明示的なイベントです。 | ||
| 重要な理由 仕入先の品質や発注内容の正確性に関する問題を明らかにし、プロセスの手戻りを示す重要な指標になります。入庫差異率KPIの算出に欠かせません。 入手先 返品移動タイプ(例:「122」:仕入先への返品納入)が使用された際に、品目伝票テーブル(MKPF/MSEG)へ記録されます。転記日(MKPF-BUDAT)がタイムスタンプになります。 取得 元の購買発注を参照する返品移動タイプ(例:122)の品目伝票を特定します。 イベントタイプ explicit | |||
抽出ガイド
ステップ
- ABAPプログラムを作成:トランザクションコードSE38でABAPエディタを開きます。新しいプログラム名を入力します。例:Z_PM_PO_EXTRACT。「作成」をクリックします。タイトルには「Process Mining PO Data Extraction」などを入力し、タイプを「実行可能プログラム」に設定します。
- 選択画面を定義:プログラムで選択画面のパラメータを定義します。これにより、抽出対象のデータを絞り込めます。主なパラメータは、購買発注の作成日範囲、会社コード(BUKRS)、購買伝票タイプ(BSART)です。
- データ構造を定義:最終的なイベントログ形式に合わせた内部テーブル構造を宣言します。PurchaseOrder、Activity、EventTime、UserName、VendorNumber、OrderAmount、MaterialGroup、CompanyCode、DocumentTypeなど、必要な属性と推奨属性を含めます。
- データ選択ロジックを実装:必要な14種類のアクティビティごとにデータを選択するABAPの中核ロジックを記述します。EKKO、EKPO、EKBE、EBAN、CDHDR、CDPOS、NASTなど、複数のSAPテーブルを検索します。コードを整理しやすくするため、アクティビティごとに個別のサブルーチン(PERFORM)を使用します。
- 購買依頼データを選択:EBANテーブルを検索して「Purchase Requisition Created」イベントを取得し、EKPOテーブルを介して購買発注と関連付けます。変更ログテーブル(CDHDR、CDPOS)を使い、リリースステータスフィールドの変更を追跡して「Purchase Requisition Approved」イベントを特定します。
- 購買発注の主要イベントを選択:EKKOテーブルとEKPOテーブルを検索して「Purchase Order Created」イベントを取得します。オブジェクトEINKBELEGの変更ログテーブル(CDHDR、CDPOS)を使い、リリースインジケータや削除フラグなど特定フィールドの変更にもとづいて、「Purchase Order Changed」、「Purchase Order Approved」、「Purchase Order Rejected」、「Purchase Order Completed」、「Purchase Order Deleted」イベントを抽出します。
- POの通信イベントを選択:NASTテーブルを検索し、POが正常に送信されたレコードを特定して、「Purchase Order Sent to Vendor」アクティビティを取得します。
- 商品・サービスのイベントを選択:EKBEテーブルで品目伝票の計上を検索し、移動タイプのカテゴリにもとづいて「Goods Receipt Posted」と「Goods Returned」アクティビティを特定します。サービス入力シートについてはESSRとESLLを検索し、「Services Confirmation Entered」を取得します。
- 品質管理イベントを選択:品質管理モジュールを使用している場合は、QALSテーブルとQAVEテーブルを検索し、POに関連付けられた検査ロットについて使用決定が行われた時点を特定します。これが「Quality Inspection Performed」アクティビティに該当します。
- データを統合して整形:個別に選択したデータを1つの最終内部テーブルに統合します。EventTimeフィールドの形式を統一してください(例:YYYY-MM-DDTHH:MI:SS)。
- ファイルダウンロードを実装:最終内部テーブルをファイルとしてダウンロードする機能を追加します。推奨形式はタブ区切りまたはCSVで、GUI_DOWNLOAD関数モジュールを使って出力できます。
- 実行して保存:トランザクションSE38またはSA38でプログラムを実行します。選択条件を入力してレポートを実行します。表示されたら、出力ファイルを.csv拡張子でローカルマシンに保存します。これでアップロードの準備が整います。
設定
- 日付範囲:抽出対象の日付範囲を明確に定義することが重要です。通常は購買発注の作成日(EKKO-AEDAT)を基準にします。データ量とプロセスの把握しやすさのバランスを考えると、まずは3~6か月が適しています。
- 会社コード(BUKRS):1つ以上の会社コードでフィルタリングし、関連する法人に対象を限定します。パフォーマンスと分析対象の適切性を左右する重要なパラメータです。
- 購買伝票タイプ(BSART):特定の伝票タイプ(例:「NB」は標準PO)でフィルタリングし、標準プロセスに対象を絞ります。必要に応じて、特殊な調達タイプを除外します。
- データの粒度:抽出対象は購買発注明細レベルです。Case IDには購買発注番号(EBELN)を使用します。入庫など明細レベルのイベントを含むすべてのイベントを、この主要なCase IDに関連付けます。
- パフォーマンスに関する考慮事項:大規模なデータセットでは、タイムアウトを避けるため、プログラムをバックグラウンドジョブ(SM36)として実行するようスケジュールしてください。特にCDHDRやCDPOSなど、WHERE句で使用する主要フィールドにデータベースインデックスが設定されていることを確認してください。
- 前提条件:レポートを実行するユーザーには、ABAPワークベンチ(SE38)へのアクセス権、プログラムの開発・実行権限が必要です。また、EKKO、EKPO、EKBE、CDHDR、CDPOS、EBAN、NAST、ESSR、QMテーブルなど、基盤となるすべてのテーブルへの読み取り権限も必要です。
a サンプルクエリ abap
REPORT Z_PM_PO_EXTRACT.
TABLES: ekko, ekpo, eban.
*&---------------------------------------------------------------------*
*& Data Structures for Event Log
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
purchaseorder TYPE ebeln,
activity TYPE string,
eventtime TYPE timestamp,
username TYPE ernam,
vendornumber TYPE lifnr,
orderamount TYPE netwr_ak,
materialgroup TYPE matkl,
companycode TYPE bukrs,
documenttype TYPE bsart,
END OF ty_event_log.
DATA: gt_event_log TYPE TABLE OF ty_event_log.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_aedat FOR ekko-aedat OBLIGATORY, " PO Creation Date
s_bukrs FOR ekko-bukrs, " Company Code
s_bsart FOR ekko-bsart, " PO Document Type
s_ebeln FOR ekko-ebeln. " PO Number
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM get_po_headers.
IF gt_event_log IS NOT INITIAL.
PERFORM get_pr_created.
PERFORM get_pr_approved.
PERFORM get_po_created.
PERFORM get_po_release_events. " Approved, Rejected, Approval Requested
PERFORM get_po_sent_to_vendor.
PERFORM get_po_changed.
PERFORM get_goods_receipt_posted.
PERFORM get_services_confirmed.
PERFORM get_quality_inspection.
PERFORM get_goods_returned.
PERFORM get_po_completed.
PERFORM get_po_deleted.
PERFORM download_to_csv.
ELSE.
MESSAGE 'No Purchase Orders found for the given criteria.' TYPE 'I'.
ENDIF.
*&---------------------------------------------------------------------*
*& Form GET_PO_HEADERS (Base data)
*&---------------------------------------------------------------------*
FORM get_po_headers.
SELECT h~ebeln, h~lifnr, h~bukrs, h~bsart, p~netwr, p~matkl
FROM ekko AS h
INNER JOIN ekpo AS p ON h~ebeln = p~ebeln
INTO TABLE @DATA(lt_po_base)
WHERE h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND h~bsart IN @s_bsart
AND h~ebeln IN @s_ebeln.
SORT lt_po_base BY ebeln.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PR_CREATED
*&---------------------------------------------------------------------*
FORM get_pr_created.
DATA: lt_pr_events TYPE TABLE OF ty_event_log.
SELECT p~ebeln AS purchaseorder,
'Purchase Requisition Created' AS activity,
b~erdat AS event_date,
'000000' AS event_time,
b~ernam AS username,
h~lifnr AS vendornumber,
p~netwr AS orderamount,
p~matkl AS materialgroup,
h~bukrs AS companycode,
h~bsart AS documenttype
FROM ekpo AS p
JOIN eban AS b ON p~banfn = b~banfn AND p~bnfpo = b~bnfpo
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE p~ebeln IN @s_ebeln
AND p~banfn IS NOT NULL AND p~banfn <> ''
AND h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND h~bsart IN @s_bsart
INTO TABLE @DATA(lt_pr_created).
LOOP AT lt_pr_created ASSIGNING FIELD-SYMBOL(<fs_pr>).
DATA(ls_event) = CORRESPONDING ty_event_log(<fs_pr>).
CONCATENATE <fs_pr>-event_date <fs_pr>-event_time INTO DATA(lv_ts).
CONVERT DATE <fs_pr>-event_date TIME '000000' INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PR_APPROVED
*&---------------------------------------------------------------------*
FORM get_pr_approved.
DATA: lt_pr_list TYPE TABLE OF eban-banfn.
SELECT DISTINCT p~banfn FROM ekpo AS p
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND p~banfn IS NOT NULL AND p~banfn <> ''
INTO TABLE @lt_pr_list.
IF lt_pr_list IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime, p~fname, p~value_new
FROM cdhdr AS h
JOIN cdpos AS p ON h~objectid = p~objectid AND h~changenr = p~changenr
FOR ALL ENTRIES IN @lt_pr_list
WHERE h~objectclas = 'BANF'
AND h~objectid = @lt_pr_list-table_line
AND p~tabname = 'EBAN'
AND p~fname = 'FRGZU'
INTO TABLE @DATA(lt_cd_pr).
LOOP AT lt_cd_pr ASSIGNING FIELD-SYMBOL(<fs_cd>) WHERE <fs_cd>-value_new = 'X'.
SELECT SINGLE p~ebeln, p~netwr, p~matkl, h~lifnr, h~bukrs, h~bsart
FROM ekpo AS p
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE p~banfn = @<fs_cd>-objectid(10)
INTO @DATA(ls_po_info).
IF sy-subrc = 0.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = ls_po_info-ebeln
activity = 'Purchase Requisition Approved'
username = <fs_cd>-username
vendornumber = ls_po_info-lifnr
orderamount = ls_po_info-netwr
materialgroup = ls_po_info-matkl
companycode = ls_po_info-bukrs
documenttype = ls_po_info-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_CREATED
*&---------------------------------------------------------------------*
FORM get_po_created.
LOOP AT lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>).
SELECT SINGLE aedat, ernam FROM ekko INTO @DATA(ls_ekko)
WHERE ebeln = @<fs_po>-ebeln.
IF sy-subrc = 0.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Created'
username = ls_ekko-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE ls_ekko-aedat TIME '000000' INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_RELEASE_EVENTS
*&---------------------------------------------------------------------*
FORM get_po_release_events.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime, p~value_new
FROM cdhdr AS h
JOIN cdpos AS p ON h~objectid = p~objectid AND h~changenr = p~changenr
WHERE h~objectclas = 'EINKBELEG'
AND h~objectid IN lt_ebeln
AND p~tabname = 'EKKO'
AND p~fname = 'FRGKE'
INTO TABLE @DATA(lt_cd_po).
LOOP AT lt_cd_po ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
CASE <fs_cd>-value_new.
WHEN '2' OR 'R'. " Final Release
ls_event-activity = 'Purchase Order Approved'.
WHEN '1'. " Blocked
ls_event-activity = 'Purchase Order Rejected'.
WHEN OTHERS. " Any other change implies a pending state
ls_event-activity = 'Purchase Order Approval Requested'.
ENDCASE.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_SENT_TO_VENDOR
*&---------------------------------------------------------------------*
FORM get_po_sent_to_vendor.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT objky, erdat, eruhr, ernam
FROM nast
WHERE kapol = 'EF' AND objky IN lt_ebeln AND vstat = '1'
INTO TABLE @DATA(lt_nast).
LOOP AT lt_nast ASSIGNING FIELD-SYMBOL(<fs_nast>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_nast>-objky.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Sent to Vendor'
username = <fs_nast>-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_nast>-erdat TIME <fs_nast>-eruhr INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_CHANGED
*&---------------------------------------------------------------------*
FORM get_po_changed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT DISTINCT objectid, username, udate, utime
FROM cdhdr
WHERE objectclas = 'EINKBELEG' AND objectid IN lt_ebeln AND tcode <> 'ME21N' AND tcode <> 'ME22'
INTO TABLE @DATA(lt_cdhdr_chg).
LOOP AT lt_cdhdr_chg ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Changed'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_GOODS_RECEIPT_POSTED
*&---------------------------------------------------------------------*
FORM get_goods_receipt_posted.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT k~ebeln, m~cpudt, m~cputm, m~usnam, k~bewtp
FROM ekbe AS k JOIN mkpf AS m ON k~belnr = m~mblnr AND k~gjahr = m~mjahr
WHERE k~ebeln IN lt_ebeln AND k~bewtp = 'E' AND k~shkzg = 'S'
INTO TABLE @DATA(lt_gr).
LOOP AT lt_gr ASSIGNING FIELD-SYMBOL(<fs_gr>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_gr>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Goods Receipt Posted'
username = <fs_gr>-usnam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_gr>-cpudt TIME <fs_gr>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_SERVICES_CONFIRMED
*&---------------------------------------------------------------------*
FORM get_services_confirmed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT l~ebeln, h~erdat, h~eruhr, h~ernam
FROM essr AS h JOIN esll AS l ON h~lblni = l~lblni
WHERE l~ebeln IN lt_ebeln
INTO TABLE @DATA(lt_ses).
LOOP AT lt_ses ASSIGNING FIELD-SYMBOL(<fs_ses>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_ses>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Services Confirmation Entered'
username = <fs_ses>-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_ses>-erdat TIME <fs_ses>-eruhr INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_QUALITY_INSPECTION
*&---------------------------------------------------------------------*
FORM get_quality_inspection.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT q~ebeln, v~vdatum, v~vzeit, v~vname
FROM qals AS q JOIN qave AS v ON q~prueflos = v~prueflos
WHERE q~ebeln IN lt_ebeln
INTO TABLE @DATA(lt_qm).
LOOP AT lt_qm ASSIGNING FIELD-SYMBOL(<fs_qm>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_qm>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Quality Inspection Performed'
username = <fs_qm>-vname
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_qm>-vdatum TIME <fs_qm>-vzeit INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_GOODS_RETURNED
*&---------------------------------------------------------------------*
FORM get_goods_returned.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT k~ebeln, m~cpudt, m~cputm, m~usnam
FROM ekbe AS k JOIN mkpf AS m ON k~belnr = m~mblnr AND k~gjahr = m~mjahr
WHERE k~ebeln IN lt_ebeln AND k~bwart = '122'
INTO TABLE @DATA(lt_ret).
LOOP AT lt_ret ASSIGNING FIELD-SYMBOL(<fs_ret>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_ret>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Goods Returned'
username = <fs_ret>-usnam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_ret>-cpudt TIME <fs_ret>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_COMPLETED
*&---------------------------------------------------------------------*
FORM get_po_completed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime
FROM cdhdr AS h JOIN cdpos AS p ON h~changenr = p~changenr AND h~objectid = p~objectid
WHERE h~objectclas = 'EINKBELEG' AND h~objectid IN lt_ebeln AND p~tabname = 'EKPO' AND p~fname = 'ELIKZ' AND p~value_new = 'X'
INTO TABLE @DATA(lt_cd_comp).
LOOP AT lt_cd_comp ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Completed'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_DELETED
*&---------------------------------------------------------------------*
FORM get_po_deleted.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime
FROM cdhdr AS h JOIN cdpos AS p ON h~changenr = p~changenr AND h~objectid = p~objectid
WHERE h~objectclas = 'EINKBELEG' AND h~objectid IN lt_ebeln AND p~tabname = 'EKPO' AND p~fname = 'LOEKZ' AND p~value_new = 'L'
INTO TABLE @DATA(lt_cd_del).
LOOP AT lt_cd_del ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Deleted'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DOWNLOAD_TO_CSV
*&---------------------------------------------------------------------*
FORM download_to_csv.
DATA: lv_filename TYPE string.
DATA: lt_fieldnames TYPE TABLE OF string.
APPEND 'PurchaseOrder' TO lt_fieldnames.
APPEND 'Activity' TO lt_fieldnames.
APPEND 'EventTime' TO lt_fieldnames.
APPEND 'UserName' TO lt_fieldnames.
APPEND 'VendorNumber' TO lt_fieldnames.
APPEND 'OrderAmount' TO lt_fieldnames.
APPEND 'MaterialGroup' TO lt_fieldnames.
APPEND 'CompanyCode' TO lt_fieldnames.
APPEND 'DocumentType' TO lt_fieldnames.
DATA(lv_header) = REDUCE string( INIT h = '' FOR f IN lt_fieldnames NEXT h = h && f && cl_abap_char_utilities=>horizontal_tab ).
REPLACE LAST OCCURRENCE OF cl_abap_char_utilities=>horizontal_tab IN lv_header WITH cl_abap_char_utilities=>cr_lf.
DATA(lv_file_content) = lv_header.
LOOP AT gt_event_log ASSIGNING FIELD-SYMBOL(<fs_log>).
DATA lv_line TYPE string.
DATA lv_eventtime_str TYPE string.
lv_eventtime_str = |{ <fs_log>-eventtime TIMESTAMP = ISO }|.
lv_line = <fs_log>-purchaseorder && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-activity && cl_abap_char_utilities=>horizontal_tab &&
lv_eventtime_str && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-username && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-vendornumber && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-orderamount && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-materialgroup && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-companycode && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-documenttype && cl_abap_char_utilities=>cr_lf.
CONCATENATE lv_file_content lv_line INTO lv_file_content.
ENDLOOP.
CALL METHOD cl_gui_frontend_services=>gui_download
EXPORTING
filename = 'C:\temp\po_event_log.csv'
filetype = 'ASC'
CHANGING
data_tab = lv_file_content. ステップ
- データベース接続を確立:SAP ECCの基盤データベースに接続するため、読み取り専用の認証情報と接続情報(ホスト名、ポート、データベース名)を取得します。DBeaver、SQL Developer、SSMSなど、必要なクライアントツールがインストールされていることを確認してください。
- SAPスキーマを特定:データベースに接続し、テーブルが配置されている主要なSAPスキーマを特定します。多くの場合、SAPSR3、SAPHANADB、またはシステム固有の類似した名前です。ユーザーのデフォルトスキーマでない場合は、クエリ内のすべてのテーブル名にこのスキーマを付ける必要があります。
- SQLクエリを確認:提供されたSQLスクリプトをクライアントツールで開きます。このクエリは、複数のSAPテーブルを結合して、調達から支払いまでのプロセスから14種類のアクティビティを抽出するよう設計されています。
- クエリパラメータをカスタマイズ:スクリプトの先頭にあるPO_BASE共通テーブル式(CTE)を確認します。プレースホルダーの値を変更して、抽出範囲を定義します。
- [START_DATE]と[END_DATE]:分析対象の日付範囲を設定します(例:「20230101」と「20230630」)。AEDAT(変更日)フィールドでのフィルタリングを推奨します。
- [COMPANY_CODE_1]、[COMPANY_CODE_2]:対象に含めるSAP会社コードを指定します。
- [DOC_TYPE_1]、[DOC_TYPE_2]:対象に含めるPO伝票タイプを指定します。
- [Your SAP Schema]:スクリプト全体で、このプレースホルダーを実際のSAPスキーマ名に置き換えます。
- クエリを実行:カスタマイズしたSQLスクリプトをSAPデータベースに対して実行します。実行時間は、日付範囲、データ量、データベースのパフォーマンスによって異なります。
- 結果を確認:クエリの完了後、出力を簡単に確認します。行数が妥当であること、PurchaseOrder、Activity、EventTimeなどの主要な列に想定どおり値が入っていることを確認してください。
- データをCSVにエクスポート:SQLクライアントから結果セット全体をCSVファイルにエクスポートします。文字化けを防ぐため、UTF-8エンコードを使用してください。
- アップロードの準備:CSVファイルの列見出しが、必要な属性名と完全に一致していることを確認します:PurchaseOrder、Activity、EventTime、UserName、VendorNumber、OrderAmount、MaterialGroup、CompanyCode、DocumentType。
- プロセスマイニングツールにアップロード:完成したCSVファイルをプロセスマイニングアプリケーションにアップロードし、分析と可視化を行います。
設定
- 前提条件:SAP ECCの基盤データベースに対する直接の読み取り専用アクセスが必要です。EKKO、EKPO、EKBE、EBAN、CDHDR、CDPOS、NASTなどのテーブルを検索するための十分な権限が必要です。
- 日付範囲のフィルタリング:データ量を抑えるため、日付範囲フィルターを適用することが重要です。EKKO.AEDAT(PO変更日)を3~6か月の期間で絞り込む方法が一般的です。日付範囲が広すぎると、クエリの実行に非常に長い時間がかかる場合があります。
- 主要なデータフィルター:分析対象を適切に絞るため、必ずEKKO.BUKRS(会社コード)とEKKO.BSART(伝票タイプ)でフィルタリングしてください。関連する法人と業務プロセスに対象を限定できます。
- パフォーマンスに関する考慮事項:このクエリでは、変更履歴テーブル(CDHDR、CDPOS)を含む複数の大規模テーブルを結合します。データベースへの負荷が高くなる可能性があるため、システムのパフォーマンスへの影響を避けるために、利用の少ない時間帯、またはレプリケーションされた非本番データベースで抽出を実行することを強く推奨します。
- 変更文書のログ記録:「Approved」、「Rejected」、「Completed」、「Changed」などのアクティビティの正確性は、SAPで該当フィールドの変更文書ログが有効になっているかどうかに左右されます。SAP管理者に確認し、トランザクションSCDOでこのログが有効になっていることを確認してください。
a サンプルクエリ sql
WITH PO_BASE AS (
SELECT
H.EBELN, -- Purchase Order Number
I.EBELP, -- Purchase Order Item
H.LIFNR, -- Vendor Number
H.BUKRS, -- Company Code
H.BSART, -- Document Type
I.NETWR, -- Order Amount (Item Level)
I.MATKL, -- Material Group
I.BANFN, -- Purchase Requisition Number
I.BNFPO -- Purchase Requisition Item
FROM [Your SAP Schema].EKKO AS H
JOIN [Your SAP Schema].EKPO AS I ON H.EBELN = I.EBELN
WHERE H.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' -- Filter on PO Change Date, e.g., '20230101' and '20231231'
AND H.BUKRS IN ('[COMPANY_CODE_1]', '[COMPANY_CODE_2]') -- Specify Company Codes
AND H.BSART IN ('[DOC_TYPE_1]', '[DOC_TYPE_2]') -- Specify PO Document Types
)
-- 1. Purchase Requisition Created
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Requisition Created' AS "Activity",
TO_TIMESTAMP(CONCAT(pr.ERDAT, '000000'), 'YYYYMMDDHH24MISS') AS "EventTime", -- Time is not available in EBAN
pr.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EBAN pr ON po.BANFN = pr.BANFN AND po.BNFPO = pr.BNFPO
WHERE po.BANFN IS NOT NULL AND po.BANFN <> ''
UNION ALL
-- 2. Purchase Requisition Approved
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Requisition Approved' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'BANF' AND ch.OBJECTID = po.BANFN
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EBAN' AND cp.FNAME = 'FRGZU' AND cp.VALUE_NEW = 'X' -- Release indicator set to 'released'
UNION ALL
-- 3. Purchase Order Created
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Created' AS "Activity",
TO_TIMESTAMP(CONCAT(ekko.ERDAT, ' ', ekko.ERZET), 'YYYYMMDD HH24MISS') AS "EventTime",
ekko.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKKO ekko ON po.EBELN = ekko.EBELN
UNION ALL
-- 4. Purchase Order Approval Requested / 5. Approved / 6. Rejected (from Change Docs)
SELECT
po.EBELN AS "PurchaseOrder",
CASE
WHEN cp.VALUE_NEW > cp.VALUE_OLD THEN 'Purchase Order Approval Requested'
WHEN cp.VALUE_NEW = ekko.FRGKE AND ekko.FRGKE = 'R' THEN 'Purchase Order Approved'
ELSE 'Purchase Order Rejected' -- Simplified logic, may need adjustment
END AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKKO ekko ON po.EBELN = ekko.EBELN
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID = po.EBELN
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKKO' AND cp.FNAME = 'FRGZU' -- Release status
UNION ALL
-- 7. Purchase Order Sent to Vendor
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Sent to Vendor' AS "Activity",
TO_TIMESTAMP(CONCAT(na.ERDAT, ' ', na.ERUHR), 'YYYYMMDD HH24MISS') AS "EventTime",
na.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].NAST na ON na.OBJKY = po.EBELN AND na.KSCHL = '[Your PO Output Type]' -- e.g., 'NEU'
WHERE na.VSTAT = '1' -- Successfully processed
UNION ALL
-- 8. Purchase Order Changed
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Changed' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID = po.EBELN
WHERE ch.TCODE IN ('ME22', 'ME22N') -- Filter for change transactions
UNION ALL
-- 9. Goods Receipt Posted
SELECT
ekbe.EBELN AS "PurchaseOrder",
'Goods Receipt Posted' AS "Activity",
TO_TIMESTAMP(CONCAT(mkpf.CPUDT, ' ', mkpf.CPUTM), 'YYYYMMDD HH24MISS') AS "EventTime",
mkpf.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM [Your SAP Schema].EKBE AS ekbe
JOIN [Your SAP Schema].MKPF AS mkpf ON ekbe.BELNR = mkpf.MBLNR AND ekbe.GJAHR = mkpf.MJAHR
JOIN PO_BASE AS po ON ekbe.EBELN = po.EBELN AND ekbe.EBELP = po.EBELP
WHERE ekbe.BEWTP = 'E' -- Goods Receipt
AND ekbe.SHKZG = 'S' -- Debit/Credit Indicator: Goods Receipt
UNION ALL
-- 10. Services Confirmation Entered
SELECT
po.EBELN AS "PurchaseOrder",
'Services Confirmation Entered' AS "Activity",
TO_TIMESTAMP(CONCAT(essr.ERDAT, ' ', essr.ERZET), 'YYYYMMDD HH24MISS') AS "EventTime",
essr.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKBE ekbe ON po.EBELN = ekbe.EBELN AND po.EBELP = ekbe.EBELP
JOIN [Your SAP Schema].ESSR essr ON ekbe.LBLNI = essr.LBLNI
WHERE ekbe.BEWTP = 'L' -- Service Entry Sheet
UNION ALL
-- 11. Quality Inspection Performed
SELECT
po.EBELN AS "PurchaseOrder",
'Quality Inspection Performed' AS "Activity",
TO_TIMESTAMP(CONCAT(qave.VDATUM, ' ', qave.VZEIT), 'YYYYMMDD HH24MISS') AS "EventTime",
qave.VNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKBE ekbe ON po.EBELN = ekbe.EBELN AND po.EBELP = ekbe.EBELP
JOIN [Your SAP Schema].QALS qals ON qals.MBLNR = ekbe.BELNR AND qals.MJAHR = ekbe.GJAHR
JOIN [Your SAP Schema].QAVE qave ON qals.PRUEFLOS = qave.PRUEFLOS
WHERE ekbe.BEWTP = 'E' -- Linked to a Goods Receipt
UNION ALL
-- 12. Goods Returned
SELECT
ekbe.EBELN AS "PurchaseOrder",
'Goods Returned' AS "Activity",
TO_TIMESTAMP(CONCAT(mkpf.CPUDT, ' ', mkpf.CPUTM), 'YYYYMMDD HH24MISS') AS "EventTime",
mkpf.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM [Your SAP Schema].EKBE AS ekbe
JOIN [Your SAP Schema].MKPF AS mkpf ON ekbe.BELNR = mkpf.MBLNR AND ekbe.GJAHR = mkpf.MJAHR
JOIN PO_BASE AS po ON ekbe.EBELN = po.EBELN AND ekbe.EBELP = po.EBELP
WHERE ekbe.BEWTP = 'E' -- Goods Movement
AND ekbe.SHKZG = 'H' -- Debit/Credit Indicator: Return
AND ekbe.BWART = '122' -- Movement type for return to vendor
UNION ALL
-- 13. Purchase Order Completed
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Completed' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID LIKE CONCAT(po.EBELN, po.EBELP, '%')
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKPO' AND cp.FNAME = 'ELIKZ' AND cp.VALUE_NEW = 'X' -- Delivery completed indicator
UNION ALL
-- 14. Purchase Order Deleted
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Deleted' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID LIKE CONCAT(po.EBELN, po.EBELP, '%')
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKPO' AND cp.FNAME = 'LOEKZ' AND cp.VALUE_NEW = 'L'; -- Deletion indicator ステップ
- 前提条件と接続:サードパーティETLツールにSAP認定コネクタがインストールされ、ライセンスが付与されていることを確認します。ETLツールの管理コンソールで、SAP ECCシステムへの新しい接続を設定します。アプリケーションサーバーホスト、システム番号、クライアントID、適切なRFC権限とテーブル読み取り権限を持つ専用SAPユーザーが必要です。
- ソーステーブルを特定:ETLジョブまたはデータフローで、必要なSAPテーブルをデータソースとして定義します。主なテーブルは、EKKO(POヘッダー)、EKPO(PO明細)、EBAN(購買依頼)、CDHDR(変更文書ヘッダー)、CDPOS(変更文書明細)、MSEG(伝票セグメント:品目)、MKPF(品目伝票ヘッダー)、NAST(メッセージステータス)、ESSR(サービス入力シートヘッダー)、QALS(検査ロット)です。
- 「Purchase Order Created」を抽出:EKKOテーブルをソースとするデータフローを作成します。希望する日付範囲(例:AEDAT)と組織範囲(例:会社コードのBUKRS、伝票タイプのBSART)にもとづいてレコードをフィルタリングします。EKKO.EBELNをPurchaseOrderに、「Purchase Order Created」をActivityにマッピングし、AEDATとERZETを組み合わせてEventTimeを作成します。その他の必要な属性もマッピングします。
- 「Goods Receipt Posted」を抽出:MSEGをソースとし、MBLNRとMJAHRでMKPFに結合する別のデータフローを作成します。「101」などの関連する移動タイプでフィルタリングします。MSEG.EBELNをPurchaseOrderに、「Goods Receipt Posted」をActivityにマッピングし、MKPF.CPUDTとMKPF.CPUTMをEventTimeに使用します。
- 変更にもとづくイベントを抽出(承認、変更、削除):CDHDRとCDPOSをCHANGENRで結合するデータフローを作成します。この1つのソースから複数のアクティビティを導出できます。
- OBJECTCLAS = 'EINKBELEG'かつTABNAME = 'EKPO'でフィルタリングします。
- **「Purchase Order Approved」**では、リリースステータスフィールド(例:FNAME = 'FRGZU')の変更を対象にし、新しい値(VALUE_NEW)が最終承認を示すレコードに絞り込みます。
- **「Purchase Order Deleted」**では、削除インジケータ(FNAME = 'LOEKZ')の変更を対象にし、新しい値が「L」のレコードに絞り込みます。
- **「Purchase Order Changed」**では、他の関連フィールドの変更を対象にし、他のアクティビティで使用する特定のステータスフィールドは除外します。
- これらすべてのイベントでは、CDHDR.UDATEとCDHDR.UTIMEをEventTimeに使用します。
- 「Purchase Requisition」イベントを抽出:EBANから「Purchase Requisition Created」を取得するデータフローを作成します。これをPurchaseOrderケースに関連付けるには、購買依頼番号(BANFN)と明細(BNFPO)を使ってEBANとEKPOを結合します。「Purchase Requisition Approved」では、OBJECTCLAS = 'BANF'のCDHDR/CDPOSを使用します。イベントを最終的なPOに正しく関連付けるには、慎重なマッピングが必要です。
- 「PO Sent to Vendor」を抽出:NASTテーブルをソースとするデータフローを作成します。OBJECTKEY(PO番号を含む)、関連する出力タイプ(KSCHL)、正常な処理ステータス(VSTAT = '1')でフィルタリングします。EventTimeにはERDATとUHRを使用します。
- アクティビティストリームを統合:前の手順で作成した個別のデータフローの出力を、ETLツールの「Union」または「Merge」変換で統合します。すべてのストリームで列名とデータ型(PurchaseOrder、Activity、EventTimeなど)が一致していることを確認します。
- データ型と形式を変換:EventTime列を統一したタイムスタンプ形式(例:YYYY-MM-DD HH:MM:SS)に変換します。OrderAmountは標準的な10進数形式に変換します。
- 出力先を定義:統合したデータストリームの出力先または「sink」を設定します。通常はCSVやParquetなどのフラットファイルです。区切り文字、テキスト修飾子、ヘッダーのオプションを設定します。
- 実行して検証:ETLジョブ全体を実行します。出力ファイルを検証し、14種類のアクティビティがすべて含まれていること、行数が妥当であること、主要な属性に正しい値が入っていることを確認します。
- スケジュールしてエクスポート:検証が完了したら、データを最新の状態に保つため、ETLジョブを定期的(例:毎晩)に実行するようスケジュールします。生成されたファイルをプロセスマイニングツールにアップロードできる状態になります。
設定
- 前提条件:対応するSAP Certified Connector for ECCを備えた商用ETLツール(例:Informatica PowerCenter、Talend、SAP Data Services)が必要です。また、対象テーブルに対するS_RFCおよびS_TABU_DISの権限を持つSAPダイアログユーザーまたはシステムユーザーも必要です。
- SAP接続:コネクターにSAPアプリケーションサーバー、システム番号、クライアント、ユーザー、パスワードを設定する必要があります。Secure Network Communications(SNC)の使用を推奨します。
- 期間フィルター:データ量を制限するため、期間フィルターを必ず適用してください。一般的には、EKKO.AEDAT(購買発注作成日)を直近3~12か月に絞り込みます。SAPから過剰なデータを抽出しないよう、このフィルターはデータソース側で適用してください。
- 組織範囲のフィルター:必ずEKKO.BUKRS(会社コード)で絞り込み、特定の事業単位に分析範囲を限定する場合は、EKPO.WERKS(プラント)またはEKKO.EKORG(購買組織)によるフィルターも検討してください。
- 伝票タイプのフィルター:EKKO.BSARTを使用して、関連する購買発注タイプだけを含めます。標準的なP2Pプロセスに含まれない在庫移送やその他の社内伝票は除外してください。
- パフォーマンス調整:変更伝票テーブル(CDHDR、CDPOS)からの抽出には時間がかかる場合があります。OBJECTCLAS、OBJECTID、UDATEに対するフィルターが適用されていることを確認してください。データ転送速度を高めるため、SAPコネクターの「Packet Size」設定を調整してください。非常に大規模なシステムでは、初回に履歴データをロードし、その後はスケジュールされた差分ロードを行う方法を検討してください。
a サンプルクエリ sql
/*
This is a logical representation of the transformations performed within the ETL tool.
The tool's graphical interface will be used to configure these separate data flows, which are then combined with a UNION transformation.
Placeholders like [Your ETL Tool Functions] and [Filter Values] must be configured in the tool.
*/
-- 1. Purchase Requisition Created
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Requisition Created' AS Activity,
[Your ETL Tool Functions].DateTime(eban.ERDAT, eban.ERZET) AS EventTime,
eban.ERNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM EBAN AS eban
INNER JOIN EKPO AS ekpo ON eban.BANFN = ekpo.BANFN AND eban.BNFPO = ekpo.BNFPO
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 2. Purchase Requisition Approved (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Requisition Approved' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EBAN AS eban ON cdhdr.OBJECTID = eban.BANFN
INNER JOIN EKPO AS ekpo ON eban.BANFN = ekpo.BANFN AND eban.BNFPO = ekpo.BNFPO
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'BANF' AND cdpos.TABNAME = 'EBAN' AND cdpos.FNAME = 'FRGZU' AND cdpos.VALUE_NEW = '[Final Release Indicator for PR]'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 3. Purchase Order Created
SELECT
EBELN AS PurchaseOrder,
'Purchase Order Created' AS Activity,
[Your ETL Tool Functions].DateTime(AEDAT, ERZET) AS EventTime,
ERNAM AS UserName,
LIFNR AS VendorNumber,
NULL AS OrderAmount, -- Amount is at item level
NULL AS MaterialGroup, -- Attribute is at item level
BUKRS AS CompanyCode,
BSART AS DocumentType
FROM EKKO
WHERE AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 4. Purchase Order Approval Requested / 5. Approved / 6. Rejected (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
CASE
WHEN cdpos.VALUE_NEW = '[Final Release Code]' THEN 'Purchase Order Approved'
WHEN cdpos.VALUE_NEW = '[Rejection Release Code]' THEN 'Purchase Order Rejected'
ELSE 'Purchase Order Approval Requested'
END AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKKO AS ekko ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKKO' AND cdpos.FNAME = 'FRGKE'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 7. Purchase Order Sent to Vendor
SELECT
ekko.EBELN AS PurchaseOrder,
'Purchase Order Sent to Vendor' AS Activity,
[Your ETL Tool Functions].DateTime(nast.ERDAT, nast.UHR) AS EventTime,
nast.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM NAST AS nast
INNER JOIN EKKO AS ekko ON nast.OBJKY = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE nast.KAPPL = 'EF' AND nast.VSTAT = '1' AND nast.KSCHL IN ([Your PO Output Types])
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 8. Purchase Order Changed (inferred from change documents, simplified example)
SELECT DISTINCT
ekko.EBELN AS PurchaseOrder,
'Purchase Order Changed' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKKO AS ekko ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.FNAME NOT IN ('FRGKE', 'FRGZU', 'LOEKZ', 'ELIKZ')
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 9. Goods Receipt Posted
SELECT
mseg.EBELN AS PurchaseOrder,
'Goods Receipt Posted' AS Activity,
[Your ETL Tool Functions].DateTime(mkpf.CPUDT, mkpf.CPUTM) AS EventTime,
mkpf.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM MSEG AS mseg
INNER JOIN MKPF AS mkpf ON mseg.MBLNR = mkpf.MBLNR AND mseg.MJAHR = mkpf.MJAHR
INNER JOIN EKPO AS ekpo ON mseg.EBELN = ekpo.EBELN AND mseg.EBELP = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE mseg.BWART = '101' AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 10. Services Confirmation Entered
SELECT
essr.EBELN AS PurchaseOrder,
'Services Confirmation Entered' AS Activity,
[Your ETL Tool Functions].DateTime(essr.ERDAT, essr.ERZET) AS EventTime,
essr.ERNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM ESSR AS essr
INNER JOIN EKKO AS ekko ON essr.EBELN = ekko.EBELN
INNER JOIN EKPO AS ekpo ON essr.EBELN = ekpo.EBELN AND essr.EBELP = ekpo.EBELP
WHERE ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 11. Quality Inspection Performed
SELECT
qals.EBELN AS PurchaseOrder,
'Quality Inspection Performed' AS Activity,
[Your ETL Tool Functions].DateTime(qals.PASTRTERM, '000000') AS EventTime, -- Time is often not available
qals.PRUEFER AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM QALS AS qals
INNER JOIN EKKO AS ekko ON qals.EBELN = ekko.EBELN
INNER JOIN EKPO AS ekpo ON qals.EBELN = ekpo.EBELN AND qals.EBELP = ekpo.EBELP
WHERE qals.VCODE <> '' -- A usage decision code exists
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 12. Goods Returned
SELECT
mseg.EBELN AS PurchaseOrder,
'Goods Returned' AS Activity,
[Your ETL Tool Functions].DateTime(mkpf.CPUDT, mkpf.CPUTM) AS EventTime,
mkpf.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM MSEG AS mseg
INNER JOIN MKPF AS mkpf ON mseg.MBLNR = mkpf.MBLNR AND mseg.MJAHR = mkpf.MJAHR
INNER JOIN EKPO AS ekpo ON mseg.EBELN = ekpo.EBELN AND mseg.EBELP = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE mseg.BWART = '122' AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 13. Purchase Order Completed (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Order Completed' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKPO AS ekpo ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekpo.EBELN AND SUBSTRING(cdhdr.OBJECTID, 11, 5) = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKPO' AND cdpos.FNAME = 'ELIKZ' AND cdpos.VALUE_NEW = 'X'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 14. Purchase Order Deleted (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Order Deleted' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKPO AS ekpo ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekpo.EBELN AND SUBSTRING(cdhdr.OBJECTID, 11, 5) = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKPO' AND cdpos.FNAME = 'LOEKZ' AND cdpos.VALUE_NEW = 'L'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]); 準備はできましたか?
このテンプレートを使えば、SAP ECCで調達から支払いまでの購買発注プロセスを改善するための設計図を得られます。今すぐデータから情報を見つけ出し、業務効率の向上につなげてください。
P2P購買発注を最適化:今すぐ無料トライアルを開始
ボトルネックをなくし、サイクルタイムを30%以上短縮します。
クレジットカードは不要です。数分で始められます。