データ テンプレート: 購買から支払いまで - 購買オーダー
Purchase to Pay - 発注書データテンプレート
- 収集を推奨する項目
- 追跡すべき主要アクティビティ
- SAP ECCの抽出ガイダンス
購買から支払いまで - 発注書属性
| 名前 | 説明 | ||
|---|---|---|---|
アクティビティ Activity | 発注書ライフサイクル内で発生した特定のビジネスイベントまたはステップの名前。 | ||
説明 この属性は、「Purchase Order Created」、「Purchase Order Approved」、または「Goods Receipt Posted」といったプロセスにおける個々のステップを記述します。これらのアクティビティのシーケンスが、各Purchase Orderのプロセスフローを形成します。 アクティビティ間のシーケンス、頻度、および期間を分析することが、プロセスマイニングのコアとなります。これにより、ボトルネック、rework ループ、および標準プロセスからの逸脱を特定し、ターゲットを絞った改善と標準化の取り組みを可能にします。 その重要性 アクティビティはプロセスの各ステップを定義します。それらの順序とタイミングを分析することで、実際のプロセスフロー、ボトルネック、および逸脱が明らかになります。 取得元 変更に関するCDHDR/CDPOS、GR/IRに関する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)ドキュメントの一意の識別子であり、調達プロセスを追跡するための主要なケースとして機能します。 | ||
説明 Purchase Order番号は、作成から最終的なgoods receipt、そして完了までのすべてのアクティビティをリンクする中心的な識別子です。それぞれのPO番号は、調達プロセスの単一のインスタンスを表します。 プロセスマイニングにおいて、この属性は各購買のend-to-endの道のりを再構築するために不可欠です。これにより、個々のオーダーごとにcycle time、プロセスのバリエーション、コンプライアンスチェックを詳細に分析でき、プロセスモデル全体の基盤を形成します。 その重要性 これは、すべての関連イベントを接続するコア識別子であり、個々の発注書のライフサイクル全体を分析することを可能にします。 取得元 Table: EKKO, Field: EBELN 例 450001762345000176244500017625 | |||
オーダー金額 OrderAmount | 購買発注明細の合計金額です。 | ||
説明 この属性は、発注書の特定の明細行の合計金額を表し、数量に正味価格を掛けて算出されます。発注書全体の金額を知るには、明細金額を集計する必要があります。 発注金額別にプロセスを分析することは、より厳格な管理や異なる承認経路が必要となる可能性のある高額取引を特定するために非常に重要です。これは、「発注金額分析」ダッシュボードに利用され、財務的に重要な発注書にプロセス改善の取り組みを優先させる上で役立ちます。 その重要性 各購入がもたらす経済的な影響を数値化することで、価値基準に基づいた分析が可能になります。これにより、より価値の高い注文を優先したり、コスト削減の機会を見つけ出したりできます。 取得元 Table: EKPO, Field: NETWR (正味発注金額). 例 1500.00250.7512345.50 | |||
ドキュメントタイプ DocumentType | さまざまな種類の購買発注を分類するコードです。 | ||
説明 Document Typeは、SAPにおける購買発注の採番範囲、フィールド選択、および全体的なプロセスフローを制御する設定です。例えば、標準PO、サービスPO、在庫転送オーダーなどで異なるタイプが存在します。 この属性は分析において強力なディメンションとなります。なぜなら、異なるDocument Typeは意図的に異なるプロセスに従うことが多いためです。Document Typeでフィルタリングすることにより、cycle timeやプロセスフローをより正確に比較分析できます。 その重要性 様々な種類の購買プロセス (例:標準、サービス、返品) を区別します。これらは多くの場合、異なるパスとパフォーマンス期待値を持っています。 取得元 Table: EKKO, Field: BSART 例 NBFOUB | |||
ユーザー名 UserName | アクティビティを実行した担当者のユーザーIDです。 | ||
説明 この属性は、ドキュメントを作成、変更、または承認した従業員のSAPユーザー名をキャプチャします。自動化されたステップの場合、システムまたはバッチユーザーIDが表示されることがあります。 ユーザーごとに分析することで、研修の必要性、高いパフォーマンスを発揮する個人、または潜在的なコンプライアンスイシューを特定するのに役立ちます。これは、ワークロードの分散、承認マトリックスのコンプライアンス、および異なるチームや個人のパフォーマンスの理解に関するダッシュボードを構築するための鍵となります。 その重要性 ユーザーアクションを特定の個人に属性付けすることで、ユーザーパフォーマンス、ワークロード、およびコンプライアンスプロトコルへの準拠状況の分析を可能にします。 取得元 Table: EKKO, Field: ERNAM (登録者); Table: CDHDR, Field: USERNAME (変更者). 例 JSMITHMBROWNBATCH_USER | |||
仕入先コード VendorNumber | ベンダーまたはサプライヤーの一意の識別子です。 | ||
説明 これは、物品やサービスを調達するサプライヤーを一意に識別するコードです。調達プロセスにおいて、重要なマスタデータとして機能します。 この属性は、ベンダー中心の分析に不可欠です。これにより、ベンダーの納期遵守実績の評価、異なるサプライヤー間のリードタイム比較、支出パターンの分析を可能にします。これは、「ベンダー納期遵守実績」ダッシュボードの主要なディメンションです。 その重要性 仕入先のパフォーマンス分析を可能にし、信頼できる仕入先や遅延や品質問題を引き起こしている仕入先を特定するのに役立ちます。 取得元 Table: EKKO, Field: LIFNR 例 100345V-20598700112 | |||
会社コード CompanyCode | 購買を開始する法人または会社の識別子です。 | ||
説明 Company CodeはSAPにおける独立した法人組織を表します。すべての取引は会社コードレベルで転記され、これは基本的な組織単位です。 会社コード別にプロセスを分析することで、異なる事業単位や国間での調達効率とコンプライアンスの比較が可能になります。これにより、ある法人組織におけるベストプラクティスを他で展開したり、プロセスに課題を抱えている特定の単位を特定したりするのに役立ちます。 その重要性 法人組織を表し、組織内の異なる部門間でプロセスパフォーマンスの比較やコンプライアンスチェックを可能にします。 取得元 Table: EKKO, Field: BUKRS 例 10002100US01 | |||
品目グループ MaterialGroup | 類似の特性を持つ品目やサービスをグループ化するための分類です。 | ||
説明 Material Group(または購買カテゴリ)は、調達するデータ品目やサービスのタイプを分類するために使用されます。例としては、「IT Hardware」、「Office Supplies」、「Professional Services」などがあります。 この属性は、spend analysis(支出分析)や調達パターンを理解するために不可欠です。これにより、プロセスをフィルタリングして、異なるカテゴリがどのように処理され、誰が承認し、どのベンダーが供給しているかを分析できます。これは「Purchase Order Value Analysis」ダッシュボードにおける主要なディメンションです。 その重要性 プロセスを製品またはサービスカテゴリでセグメント化することで、異なる種類の支出における異なる挙動、サイクルタイム、または仕入先を明らかにできます。 取得元 Table: EKPO, Field: MATKL 例 00101IT_HWCONSULT | |||
エンドツーエンドサイクルタイム EndToEndCycleTime | 購買発注の最初のアクティビティから最後のアクティビティまでの総経過時間です。 | ||
説明 この指標は、購買依頼作成といった初期イベントから購買発注完了のような最終イベントまで、購買発注プロセス全体の期間を測定します。 これは、プロセス全体の効率を測る上で非常に重要なKPIです。パフォーマンスの全体像を把握し、最も長くかかっているケースや一般的なボトルネックの特定に役立ちます。また、「エンドツーエンドPOサイクルタイム分析」ダッシュボードおよび「平均エンドツーエンドPOサイクルタイム」KPIを直接サポートします。 その重要性 調達プロセス全体の速度と効率を測定し、その健全性を示す主要な指標となります。 取得元 これは、各ケースの最後のイベントのタイムスタンプから最初のイベントのタイムスタンプを差し引くことで算出される計算属性です。 例 10日4時間22 days 1 hour5日8時間 | |||
ソースシステム SourceSystem | データを抽出した元システム。 | ||
説明 この属性は、データの発生元を識別するものです。通常はSAP ECCインスタンス識別子(例:'ECC_PROD_100')が設定されます。複数のシステム環境では、データソースを区別するのに役立ちます。 ガバナンスとデータリネージにおいては、ソースシステムを把握することが非常に重要です。これにより、データの整合性を確保し、特に異なるERPシステムやモジュールからデータが統合される際には、データ抽出や品質に関する問題のトラブルシューティングに貢献します。 その重要性 データの発生源を特定します。これは、データガバナンス、検証、および複数のシステム間での分析管理にとって極めて重要です。 取得元 これは通常、データ抽出プロセス中に、データセットに発生元システムのラベルを付けるために追加される静的な値です。 例 SAP_ECC_PRODECC_EU_100S4H_FIN | |||
仕入先名 VendorName | ベンダーまたはサプライヤーの正式名称です。 | ||
説明 ベンダー番号よりも分かりやすい、ベンダーの名称です。通常、ベンダーマスターデータから取得されます。 Vendor Numberは結合や一意の識別に使用されますが、Vendor Nameはユーザー向けのダッシュボードやレポートに不可欠です。これにより、ベンダーコードに慣れていないビジネスユーザーでも分析がより直感的でアクセスしやすくなります。 その重要性 ベンダーの可読性の高い名称を提供することで、ビジネスユーザーにとってダッシュボードやレポートが格段に理解しやすくなります。 取得元 Table: LFA1, Field: NAME1。これはEKKO-LIFNRからLFA1-LIFNRへの結合が必要です。 例 Staples Inc.グローバルテックソリューションズオフィスサプライ社 | |||
最終データ更新 LastDataUpdate | ソースシステムからデータが最後に更新された日時を示すタイムスタンプです。 | ||
説明 この属性は、最新のデータ抽出または更新の日時を記録します。これにより、分析対象となるデータの鮮度に関する情報を提供します。 この情報をダッシュボードに表示することは、ユーザーがインサイトがほぼリアルタイムのデータに基づいているのか、過去のスナップショットに基づいているのかを理解するために不可欠です。これは、ユーザーの期待値を管理し、データの鮮度を把握した上で意思決定を行えるようにするために重要です。 その重要性 データの適時性についてユーザーに通知し、分析が最新の業務状況を反映しているかどうかを確実に理解できるようにします。 取得元 このタイムスタンプは、データ抽出またはETLプロセスの実行時に生成され、追加されます。 例 2023-10-27T02:00:00Z2023-10-28T02:00:00Z | |||
却下理由 RejectionReason | 購買依頼または発注が却下された理由を説明する理由コードまたはテキストです。 | ||
説明 この属性は、承認ワークフロー中にPurchase Orderが却下されたときに提供される具体的な理由をキャプチャします。この情報は、rework(手戻り)と遅延の根本原因を理解するために不可欠です。 却下理由を分析することで、不適切な価格設定、予算超過、またはコンプライアンス違反のベンダー選定などの一般的なイシューを特定するのに役立ちます。このインサイトにより、ビジネスは根本原因に対処し、最初のPO作成の品質を向上させ、承認プロセスを効率化できます。 その重要性 承認が失敗する理由について直接的な洞察を提供し、手戻りの削減や承認サイクルタイムの短縮に向けた的を絞った改善を可能にします。 取得元 この情報は、見つけるのが難しい場合があります。長文テキストフィールドに保存されているか、カスタムワークフロー設定に依存している可能性があります。多くの場合、特定の実装知識が必要となります。 例 価格誤り予算超過重複申請 | |||
工場 Plant | データ品目が配送される物理的な場所またはPlantです。 | ||
説明 Plantは、生産施設、倉庫、またはデータ品目やサービスが受領されるその他の場所を表す組織単位です。 Plantごとに分析することで、調達プロセスにおける地理的バリエーションを理解するのに役立ちます。特定の場所へのベンダー配送時間の違いを明らかにしたり、非効率な受領プロセスを持つ特定のPlantを特定したりすることができ、goods receiptの適時性分析をサポートします。 その重要性 納入場所を特定し、地域別のプロセス差異やロジスティクスパフォーマンスを分析するのに役立ちます。 取得元 Table: EKPO, Field: WERKS 例 100011002000 | |||
希望納期 RequestedDeliveryDate | 企業がベンダーに品目またはサービスの配送を要求した日付。 | ||
説明 これは、発注書に指定された目標納期です。実際の納期遵守実績が測定される際のベースラインとなります。 この日付は、「納期遵守入庫率」KPIを計算するために不可欠です。実際の入庫日をこの希望納期と比較することで、組織はベンダーの信頼性と社内受領効率を定量的に測定でき、これは「ベンダー納期遵守実績」ダッシュボードの分析を直接的にサポートします。 その重要性 これは、納期遵守実績KPIの計算とベンダーの信頼性評価に不可欠な、納期の目標日です。 取得元 Table: EKPO, Field: EINDT 例 2023-06-102023-07-222023-08-01 | |||
承認後の変更ですか IsPostApprovalChange | 最初の承認後に購買発注書の変更が発生したかどうかを示すフラグです。 | ||
説明 このブーリアン属性は、同じ発注書に対して「発注書承認済み」アクティビティの後に「発注書変更」アクティビティが検出された場合にtrueとなります。これにより、プロセス後期に発生する問題のある変更を特定するのに役立ちます。 この計算フィールドは、「承認後PO変更率」KPIと「発注書手戻りおよび変更」ダッシュボードを直接的にサポートするものです。この属性は、遅延を引き起こしたり、再承認が必要となる可能性のある、プロセスを阻害する変更を定量化・明確化するのに役立ちます。これにより、初期仕様やスコープ策定プロセスにおける潜在的な問題点を示唆することができます。 その重要性 承認後の手戻りを直接測定するものであり、プロセスの安定性と効率性における主要KPIです。手戻り発生率が高い場合、上流の要件定義に問題があることを示します。 取得元 これは、イベントログ内のアクティビティのシーケンスから導出される計算属性です。 例 truefalse | |||
納期内配送 IsOnTimeDelivery | 物品が要求納期通りまたはそれ以前に受領されたかどうかを示すフラグです。 | ||
説明 このブーリアン属性は、「入庫計上済み」アクティビティのタイムスタンプが「希望納期」以前である場合にtrueとなります。これにより、各発注書明細の納期遵守状況について明確な二値の結果(合否)を示します。 この属性は、「納期遵守入庫率」KPIの基盤となります。納期内と納期遅延の配送の集計とフィルタリングを容易にすることで、ベンダーパフォーマンスと社内受領効率の分析を簡素化します。 その重要性 納品の適時性に関する明確な成否メトリックを提供し、ベンダーパフォーマンスKPIやダッシュボードを直接的にサポートします。 取得元 これは、入庫計上日(EKBE-BUDAT)と希望納期(EKPO-EINDT)を比較して導出される計算属性です。 例 truefalse | |||
購買グループ PurchasingGroup | 調達アクティビティを担当する特定のバイヤーまたはバイヤーのグループです。 | ||
説明 Purchasing Groupは、特定の購買アクティビティを担当するバイヤー個人またはチームを表します。彼らはベンダーとの主要な連絡窓口です。 この属性は、Purchasing Organizationよりも詳細なレベルで分析を提供します。バイヤー間のワークロードの分散を理解し、バイヤーレベルでのパフォーマンスの違いを特定するのに役立ち、リソース配分や研修イニシアティブに役立つ情報を提供できます。 その重要性 購買の責任者が誰であるかを詳細に把握できるビューを提供し、購買担当者またはチームレベルでの詳細なワークロードとパフォーマンス分析を可能にします。 取得元 Table: EKKO, Field: EKGRP 例 001002N01 | |||
購買依頼書 PurchaseRequisition | 発注書に先行する購買依頼の識別子。 | ||
説明 この属性は、発注書を元の購買依頼に紐付けます。ただし、すべての発注書に先行する依頼があるわけではありません。 この関連付けは、「購買依頼から発注への変換」ダッシュボードや「PRからPOへの変換率」KPIの分析に不可欠です。これにより、初期依頼から正式な発注作成までの上流プロセスの効率を測定し、依頼なしで作成された非準拠の発注書を特定することができます。 その重要性 購買発注をその元の購買依頼と紐付けることで、購買依頼から購買発注への変換プロセスを分析し、事前の購買依頼なしで作成された購買発注を特定できるようになります。 取得元 Table: EKPO, Field: BANFN 例 1001589010015891 | |||
購買組織 PurchasingOrganization | 価格交渉およびデータ品目やサービスの調達を担当する組織単位です。 | ||
説明 Purchasing Organizationは、SAPにおける調達アクティビティを担当する主要な組織単位です。会社全体で集中管理することも、PlantやRegion(地域)ごとに分散管理することも可能です。 Purchasing Organizationごとにプロセスのパフォーマンスを分析することで、どの調達チームが最も効率的であるかを特定できます。これにより、異なる組織単位間でcycle time、rework rate(手戻り率)、コストなどのメトリクスを比較し、ベストプラクティスや改善が必要な領域を明確にすることができます。 その重要性 担当の調達チームを特定し、異なる組織ユニット間でのパフォーマンス比較と分析を可能にします。 取得元 Table: EKKO, Field: EKORG 例 1000US01DE01 | |||
通貨 Currency | 購買発注金額の通貨コードです。 | ||
説明 この属性は、発注書の金額がUSD、EUR、GBPなどのどの通貨で表示されているかを指定します。これにより、すべての金額値を正しく理解するための重要な情報となります。 グローバル企業にとって、通貨は正確な財務分析に不可欠です。これにより、発注金額の適切な集計と比較が可能になり、すべての金額KPIは、それぞれの通貨を考慮して解釈する必要があります。 その重要性 すべての金額に適切なコンテキストを提供し、特に多国籍組織において正確な財務分析を可能にします。 取得元 Table: EKKO, Field: WAERS 例 USDEURJPY | |||
購買から支払いまで - 発注書活動
| アクティビティ | 説明 | ||
|---|---|---|---|
ベンダーへ発注書送付済み | このアクティビティは、承認されたPurchase OrderがEDI、メール、または印刷などの方法で正式にベンダーに送信された時点を示します。これは、アウトプットメッセージが正常に処理されたときにメッセージ制御テーブルに記録される明示的なイベントです。 | ||
その重要性 これは、ベンダーのリードタイムの計測を開始する重要なマイルストーンです。このイベントから入庫までの時間を分析することは、ベンダーパフォーマンスと納期遵守を評価する上で重要です。 取得元 NASTメッセージステータステーブルに記録されます。関連するPO出力タイプにおいて、処理ステータス(NAST-VSTAT)が「1」(正常処理済み)の場合、NAST-DATVRとNAST-UHRVRからtimestampを取得できます。 取得 購買発注の出力メッセージには、NASTテーブルから処理タイムスタンプを使用します。 イベントタイプ explicit | |||
入荷記帳済み | このアクティビティは、特定のPurchase Orderに対するベンダーからのデータ品目の物理的な受領を意味します。goods receiptの記帳は、マテリアル ドキュメントを作成し、インベントリを更新する明示的なアクションです(例:トランザクション MIGO経由)。 | ||
その重要性 これは、ベンダーの納期遵守実績の追跡と、請求書照合プロセス開始の重要なマイルストーンです。納期遵守率や入庫の適時性を計算するために使用されます。 取得元 品目伝票の作成時に記録されます。このeventのtimestampは、品目伝票ヘッダーテーブル(MKPF)の転記日付(MKPF-BUDAT)または登録日付(MKPF-CPUDT)であり、明細テーブル(MSEG)を介してPOにリンクされます。 取得 購買発注を参照する品目伝票には、MKPFテーブルから転記/作成タイムスタンプを使用します。 イベントタイプ explicit | |||
発注書完了 | 購買発注品目が完全に納品されたと見なされることを示します。これは推測されるイベントであり、通常、購買発注品目に「納品完了」インジケーターが自動的または手動で設定されることから導き出されます。 | ||
その重要性 このアクティビティは、プロセスの注文履行部分の論理的な終点として機能します。これは、作成から完了までのend-to-endのPO cycle timeを計算するために不可欠です。 取得元 購買発注品目の「納品完了」インジケーター(EKPO-ELIKZ)が「X」に設定されたときに記録される変更ドキュメント(CDHDR/CDPOS)から推測されます。最後の品目が完了としてマークされることは、購買発注全体の完了を示す場合があります。 取得 EKPO-ELIKZ フラグが設定されたときのタイムスタンプを、変更ドキュメントから特定します。 イベントタイプ inferred | |||
購買オーダー作成済み | このアクティビティは、ベンダーとの拘束力のある契約である正式なPurchase Order ドキュメントの作成を意味します。これは、ユーザーがPOを作成および保存したとき(例:トランザクション ME21N経由)、EKKOおよびEKPOテーブルにエントリが生成されることで記録される明示的なイベントです。 | ||
その重要性 購買発注のライフサイクルが正式に開始されたことを示します。これは、購買依頼から購買発注への変換にかかる時間と、エンドツーエンドの調達完了までの時間の両方を測定する上で重要な節目となります。 取得元 対応する購買発注番号 (EKKO-EBELN) の購買発注ヘッダテーブル (EKKO) の登録日 (EKKO-AEDAT) から取得されます。 取得 各新規購買発注に対して、EKKOテーブルから作成タイムスタンプを使用します。 イベントタイプ explicit | |||
購買オーダー承認済み | Purchase Orderの最終承認を表し、仕入先への送付を承認します。この重要なマイルストーンは、POのリリースステータスが「完全にリリース済み」または「承認済み」状態に変化したことから推測されます。 | ||
その重要性 このアクティビティは、PO Approval Cycle Time KPIの計算と、承認ワークフローにおけるボトルネックの特定に不可欠です。これは、ベンダーへの発注送信など、後続のほとんどのアクティビティの前提条件となります。 取得元 購買発注ヘッダー テーブル(EKKO)の変更ログ(CDHDR/CDPOS)を追跡することで、最終リリースコードが適用されたとき、または全体リリースステータスインジケーター(EKKO-FRGKE)が「released」に設定されたときに推測されます。 取得 購買発注の全体リリースステータス(EKKO-FRGKE)が最終承認済みのステータスに変更されたときのタイムスタンプを特定します。 イベントタイプ inferred | |||
購買依頼書作成 | このアクティビティは、データ品目またはサービスの正式な要求の作成を示します。これは、ユーザーが新しい購買依頼ドキュメントを保存したとき(ME51Nのようなトランザクションを使用)、EBANテーブルに一意のレコードが生成されることで記録される明示的なイベントです。 | ||
その重要性 これは、調達プロセスの主要な開始点です。このイベントから発注書作成までの時間を分析することで、社内需要を実行可能な注文に変換する効率を測定するのに役立ちます。 取得元 Purchase Requisitionヘッダーテーブル(EBAN)にエントリが作成された際に記録されます。登録日付(EBAN-BADAT)と時刻がこのeventのtimestampとして機能します。 取得 作成日に基づいてEBAN テーブル内の新しいエントリを特定します。 イベントタイプ explicit | |||
サービス確認入力済 | サービスベースの購買発注の場合、このアクティビティは、サービスが提供されたことの確認を表します。これは、サービス入庫伝票の作成(例:トランザクションML81N経由)を通じて取得される明示的なイベントです。 | ||
その重要性 これは、サービスに対する入庫と同等のものであり、サービスオーダーの履行状況を追跡するために不可欠です。サービス支払いのための財務プロセスを開始させます。 取得元 サービス伝票ヘッダテーブル (ESSR) の登録日 (ESSR-ERDAT) から取得されます。購買発注書へのリンクはESLLテーブルにあります。 取得 購買発注にリンクされたサービス入力シートには、ESSRテーブルから作成タイムスタンプを使用します。 イベントタイプ explicit | |||
品質検査実行済み | 受領品が品質検査を受けたことを示します。このアクティビティは通常、入荷時に作成された検査ロットに対して、品質管理モジュールで使用決定がなされたときに推測されます。 | ||
その重要性 品質が重要視される業界において、このアクティビティは検査プロセスの期間と結果を分析するのに役立ちます。ここでの遅延は、入荷から使用可能になるまでの間にボトルネックを生み出す可能性があります。 取得元 品質管理モジュールから推測されます。入荷時に検査ロットが作成され(QALS テーブル)、このアクティビティは、タイムスタンプを含む使用決定(QAVE テーブル)の作成によってマークされます。 取得 品目ドキュメントにリンクされた検査ロットのQAVE テーブルにおける使用決定のタイムスタンプを特定します。 イベントタイプ inferred | |||
購買オーダー却下済み | このアクティビティは、承認者が承認ワークフロー中にPurchase Orderを却下したときに発生します。これは推測されるイベントであり、POのリリース戦略データにおけるステータス変更から導き出され、却下が発生したことを示します。 | ||
その重要性 却下を追跡することで、購買発注のデータ品質問題、ポリシー不遵守、または承認マトリックス内の問題点を特定できます。これはしばしば手戻りを引き起こし、全体のサイクルタイムを増加させます。 取得元 購買発注リリースステータスの変更ドキュメント(CDHDR/CDPOS)から推測されます。拒否は通常、リリースコードがキャンセルされたとき、または特定の拒否ステータスが設定されたときに記録されます。 取得 リリースコードのキャンセルや却下を示すステータス変更について、変更ログを監視します。 イベントタイプ inferred | |||
購買オーダー変更済み | 初期作成後にPurchase Orderに加えられた数量、価格、納期などのあらゆる変更を表します。これらの変更は、SAPの変更伝票システムに明示的に記録されます。 | ||
その重要性 特に承認後の頻繁な変更は、プロセスの非効率性、不十分な初期計画、またはスコープクリープを示します。このアクティビティは、購買発注のリワークと変更ダッシュボードおよび関連KPIにとって不可欠です。 取得元 購買発注オブジェクト (EINKBELEG) の変更伝票ヘッダ (CDHDR) とアイテム (CDPOS) テーブルに明示的にログ記録されます。各変更はタイムスタンプ付きの新しいエントリーを作成します。 取得 購買発注番号に紐づくCDHDRおよびCDPOS テーブルから変更イベントとタイムスタンプを抽出します。 イベントタイプ explicit | |||
購買依頼書承認済み | 購買依頼の正式な承認を表し、Purchase Orderへの変換を許可します。このeventは、SAPのリリース戦略workflowによって追跡される、購買依頼data内のリリースステータスfieldの変化から推測されます。 | ||
その重要性 承認を追跡することは、発注前フェーズでのボトルネックを特定し、承認ポリシーへの準拠を確保するために極めて重要です。ここでの遅延は、調達プロセス全体のサイクルタイムに直接影響を与えます。 取得元 購買依頼 テーブル(EBAN)の変更ログ、具体的にはリリースステータスフィールド(例:EBAN-FRGZU)への変更を監視するか、EBAN オブジェクトのCDHDR/CDPOSにおける変更ドキュメントを分析することで推測されます。 取得 EBANリリースステータスフィールドの変更ドキュメントを監視し、最終承認のタイムスタンプを特定します。 イベントタイプ inferred | |||
購買発注削除済み | Purchase Order明細のキャンセルまたは論理的削除を表し、入荷伝票作成や請求書処理などのさらなる処理を防止します。これは、PO明細に削除フラグが設定されたときに捕捉される推論されるeventです。 | ||
その重要性 これは、注文がキャンセルされたことを示す終端アクティビティです。注文がなぜ、いつ削除されたかを分析することで、需要計画やベンダー選定における問題を明らかにできます。 取得元 購買発注品目の削除インジケーター(EKPO-LOEKZ)が「L」に設定されていることを示す変更ドキュメント(CDHDR/CDPOS)から推測されます。 取得 EKPO-LOEKZ フラグが設定されたときのタイムスタンプを、変更ドキュメントから特定します。 イベントタイプ inferred | |||
購買発注承認依頼済み | 作成または変更された購買発注が、設定されたリリース戦略に従って承認のために提出されたことを示します。このイベントは、リリース戦略がトリガーされ、購買発注が承認保留ステータスになったときに推測されます。 | ||
その重要性 購買発注書作成と承認プロセス開始の区別は、承認サイクルタイム KPIを正確に測定するのに役立ちます。これにより、承認ワークフローが開始される前の遅延が浮き彫りになります。 取得元 購買発注(オブジェクト EINKBELEG)の変更ドキュメント(CDHDR/CDPOS)から推測されます。具体的には、リリースステータスの初期設定時、または全体リリースステータス(EKKO-FRGKE)が承認プロセスがアクティブであることを示す値に最初に設定された時です。 取得 購買発注のリリース戦略をトリガーする最初の変更ドキュメントエントリを特定します。 イベントタイプ inferred | |||
返品済み | 以前受領した商品を仕入先へ返品することを示します。これは、品質問題や誤った出荷が原因であることが多いです。返品固有の移動タイプで品目伝票を転記することによって捕捉される明示的なeventです。 | ||
その重要性 このアクティビティは、ベンダー品質または注文精度に関する問題を浮き彫りにし、プロセスのrework(手戻り)の主要なインジケータです。Goods Receipt Variance Rate KPIを計算するために不可欠です。 取得元 返品移動タイプ(例:「仕入先への返品」を示す122)が使用されると、品目伝票テーブル(MKPF/MSEG)に記録されます。転記日付(MKPF-BUDAT)がこのeventのtimestampとなります。 取得 元の購買発注を参照する返品移動タイプ(例:122)を持つ品目ドキュメントを特定します。 イベントタイプ explicit | |||
抽出ガイド
ステップ
- ABAPプログラムの作成: トランザクションコードSE38を使用してABAPエディタを開きます。新しいプログラムの名前(例: Z_PM_PO_EXTRACT)を入力し、「作成」をクリックします。「プロセスマイニング向けPOデータ抽出」のようなタイトルを付け、タイプを「実行可能プログラム」に設定します。
- 選択画面の定義: プログラム内で選択画面パラメーターを定義します。これにより、ユーザーは抽出したいデータを絞り込むことができます。主要なパラメーターには、購買発注の作成日期間、会社コード (BUKRS)、および購買伝票タイプ (BSART) が含まれます。
- データ構造の定義: 最終的なイベントログ形式に一致する内部テーブル構造を宣言します。この構造には、すべての必須および推奨される属性(PurchaseOrder、Activity、EventTime、UserName、VendorNumber、OrderAmount、MaterialGroup、CompanyCode、DocumentType)を含める必要があります。
- データ選択ロジックの実装: 14の必須アクティビティそれぞれに対してデータを選択するためのコアABAPロジックを作成します。これには、EKKO、EKPO、EKBE、EBAN、CDHDR、CDPOS、NASTなどの複数のSAPテーブルを照会することになります。コードを整理しやすくするため、各アクティビティごとに個別のサブルーチン (PERFORM) を使用してください。
- 購買依頼データの選択: EBANテーブルを照会して「購買依頼作成済み」イベントを検索し、EKPOテーブルを介して購買発注にリンクします。変更ログテーブル (CDHDR、CDPOS) を使用して、リリースステータス項目への変更を追跡することで「購買依頼承認済み」イベントを特定します。
- 購買発注のコアイベントの選択: EKKOおよびEKPOテーブルを照会して「購買発注作成済み」イベントを検索します。オブジェクトEINKBELEGに対する変更ログテーブル (CDHDR、CDPOS) を使用し、リリースインジケーターや削除フラグなどの特定の項目への変更に基づいて、「購買発注変更済み」、「購買発注承認済み」、「購買発注却下済み」、「購買発注完了済み」、「購買発注削除済み」のイベントを抽出します。
- 購買発注の通信イベントの選択: NASTテーブルを照会して、購買発注が正常に送信されたレコードを検索し、「ベンダーへの購買発注送信済み」アクティビティを捕捉します。
- 物品およびサービスイベントの選択: EKBEテーブルを照会して物資伝票の転記を検索し、移動タイプカテゴリに基づいて「入庫転記済み」および「返品済み」アクティビティを特定します。ESSRおよびESLLテーブルを照会してサービス伝票を検索し、「サービス確認入力済み」を捕捉します。
- 品質管理イベントの選択: 品質管理モジュールをご利用の場合、QALSおよびQAVEテーブルを照会して、購買発注にリンクされた検査ロットに対して使用決定がいつ行われたかを特定し、これが「品質検査実施済み」アクティビティとなります。
- データの結合とフォーマット: 個々の選択から得られたデータを単一の最終内部テーブルに統合します。EventTime項目が(例: YYYY-MM-DDTHH:MI:SSのように)一貫した形式でフォーマットされていることを確認します。
- ファイルダウンロードの実装: 最終内部テーブルをファイルとしてダウンロードする機能を追加します。推奨される形式はタブ区切りまたはCSVファイルです。これは、GUI_DOWNLOADファンクションモジュールを使用することで実現できます。
- 実行と保存: トランザクションSE38またはSA38を使用してプログラムを実行します。選択条件を入力し、レポートを実行します。プロンプトが表示されたら、.csv拡張子を付けて出力ファイルをローカルマシンに保存し、アップロードの準備を進めます。
設定
- 日付範囲:データ抽出においては、特定の日付範囲を定義することが極めて重要です。通常は購買発注の作成日 (EKKO-AEDAT) に基づいて設定します。データ量とプロセスに関する洞察のバランスを取る上で、3〜6ヶ月の範囲が適切な出発点となることがよくあります。
- 会社コード (BUKRS):関連する法主体に抽出を限定するため、1つまたは複数の会社コードでフィルターをかけます。これはパフォーマンスと関連性にとって重要なパラメータです。
- 購買伝票タイプ (BSART):標準プロセスに分析を集中させ、必要に応じて特殊な調達タイプを除外するために、特定の伝票タイプ(例:標準POの場合は 'NB')でフィルターをかけます。
- データ粒度:この抽出は購買発注明細レベルで設計されています。ケースIDは購買発注番号 (EBELN) です。明細レベルのイベント(入庫など)を含むすべてのイベントは、この主要なケースIDに紐付けられます。
- パフォーマンスに関する考慮事項:大規模なデータセットの場合、タイムアウトエラーを回避するためにプログラムをバックグラウンドジョブ (SM36) として実行するようにスケジュールしてください。WHERE 句で使用される主要なフィールド、特に CDHDR や CDPOS のようなテーブルにはデータベースインデックスが存在することを確認してください。
- 前提条件:レポートを実行するユーザーは、プログラムの開発および実行権限のために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]: 含める購買発注伝票タイプを指定してください。
- クエリの実行: カスタマイズされた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(購買発注変更日)を3〜6ヶ月の期間で絞り込むことが一般的な出発点です。広すぎる日付範囲は、クエリ実行時間が極端に長くなる原因となります。
- 主要データフィルター:焦点を絞った分析を確実にするため、常に EKKO.BUKRS(会社コード)および EKKO.BSART(伝票タイプ)でフィルターをかけます。これにより、関連する法主体とビジネスプロセスにスコープが絞られます。
- パフォーマンスに関する考慮事項:このクエリは、変更履歴テーブル (CDHDR、CDPOS) を含むいくつかの大規模なテーブルを結合します。これはリソースを大量に消費する可能性があります。システムパフォーマンスへの影響を避けるため、この抽出はオフピーク時間帯に実行するか、レプリケートされた非本番データベースに対して実行することを強くお勧めします。
- 変更伝票ロギング: '承認済み'、'却下済み'、'完了済み'、'変更済み' などのアクティビティの正確性は、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(購買発注ヘッダー)、EKPO(購買発注明細)、EBAN(購買依頼)、CDHDR(変更伝票ヘッダー)、CDPOS(変更伝票明細)、MSEG(伝票セグメント:品目)、MKPF(品目伝票ヘッダー)、NAST(メッセージステータス)、ESSR(サービスシートヘッダー)、QALS(検査ロット)が含まれます。
- 「購買発注作成済み」の抽出: EKKOテーブルからデータを取得するデータフローを作成します。希望する日付範囲(例: AEDATを使用)および組織範囲(例: 会社コードのBUKRS、伝票タイプのBSART)に基づいてレコードをフィルタリングします。EKKO.EBELNをPurchaseOrderに、'Purchase Order Created'をActivityにマッピングし、AEDATとERZETを組み合わせてEventTimeとします。その他の必要な属性もマッピングします。
- 「入庫伝票登録済み」の抽出: MSEGからデータを取得し、MBLNRとMJAHRでMKPFと結合する別のデータフローを作成します。関連する移動タイプ、例えば'101'でフィルタリングします。MSEG.EBELNをPurchaseOrderに、'Goods Receipt Posted'をActivityにマッピングし、MKPF.CPUDTとMKPF.CPUTMをEventTimeに使用します。
- 変更ベースのイベントの抽出(承認、変更、削除): CHANGENRで結合されたCDHDRおよびCDPOSからデータを取得するデータフローを作成します。この単一のソースを使用して、複数のアクティビティを導出できます。
- OBJECTCLAS = 'EINKBELEG' および TABNAME = 'EKPO' でフィルタリングします。
- 「購買発注承認済み」 の場合、リリースステータス項目(例: FNAME = 'FRGZU')への変更で、新しい値 (VALUE_NEW) が最終承認を示すレコードをフィルタリングします。
- 「購買発注削除済み」 の場合、削除フラグ(FNAME = 'LOEKZ')への変更で、新しい値が'L'であるレコードをフィルタリングします。
- 「購買発注変更済み」 の場合、他のアクティビティで使用される特定のステータス項目を除く、他の関連する項目変更をフィルタリングします。
- これらのすべてのイベントについて、CDHDR.UDATEおよびCDHDR.UTIMEをEventTimeに使用します。
- 「購買依頼」イベントの抽出: EBANから「購買依頼作成済み」のデータフローを作成します。これをPurchaseOrderケースにリンクするために、依頼番号 (BANFN) と明細 (BNFPO) を使用してEBANをEKPOに結合します。「購買依頼承認済み」の場合、OBJECTCLAS = 'BANF'でCDHDR/CDPOSを使用します。これにより、イベントが最終的なPOに関連付けられるよう、慎重なマッピングが必要です。
- 「仕入先にPO送信済み」の抽出: NASTテーブルからデータを取得するデータフローを作成します。OBJECTKEY(PO番号を含む)、関連する出力タイプ (KSCHL)、および処理ステータスが成功 (VSTAT = '1') でフィルタリングします。ERDATとUHRをEventTimeに使用します。
- アクティビティストリームの結合: ETLツールで「Union」または「Merge」変換を使用して、前のステップで作成したすべての個別のデータフローの出力を結合します。すべてのストリームで列名とデータ型 (PurchaseOrder、Activity、EventTimeなど) が一貫していることを確認します。
- データ型と形式の変換: EventTime列が一貫したタイムスタンプ形式(例: YYYY-MM-DD HH:MM:SS)に変換されていることを確認します。OrderAmountは標準の小数形式に変換します。
- ターゲット宛先の定義: 結合されたデータストリームのターゲットまたは「シンク」を設定します。これは通常、CSVやParquetファイルなどのフラットファイルです。区切り文字、テキスト修飾子、およびヘッダーオプションを設定します。
- 実行と検証: 完全なETLジョブを実行します。出力ファイルに対して検証チェックを実行し、14のアクティビティすべてが存在し、行数が妥当であり、主要な属性が正しく入力されていることを確認します。
- スケジュール設定とエクスポート: 検証後、データの鮮度を保つためにETLジョブを定期実行(例: 毎晩)するようにスケジュール設定します。生成されたファイルは、プロセスマイニングツールにアップロードする準備ができています。
設定
- 前提条件:対応するSAP認定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コネクタの「パケットサイズ」設定を調整します。非常に大規模なシステムの場合は、最初の履歴ロードに続いてスケジュールされた差分ロードを検討してください。
a クエリ例 config
/*
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]);