データテンプレート:買掛金請求書処理
買掛金の請求書処理データテンプレート
- 包括的な分析のための推奨属性
- 効果的に追跡すべき主要アクティビティ
- データ抽出の手順ガイド
買掛金請求書処理の属性
| 名前 | 説明 | ||
|---|---|---|---|
アクティビティ ActivityName | 請求書処理ライフサイクルで発生した特定の業務イベント/ステップの名称。 | ||
説明 アクティビティは、AP プロセスの中の明確な段階や操作を表します(例:'Invoice Received'、'Invoice Posted'、'Payment Executed' など)。これらがプロセスマップを構成する基本要素です。 アクティビティ分析は Process Mining の肝です。プロセスの流れを可視化し、典型的な経路を把握し、標準手順からの逸脱を検知し、各ステップの頻度や所要時間を測定できます。特定の請求書におけるアクティビティの並びが、その請求書のプロセス経路を形作ります。 その重要性 プロセスの各ステップを定義し、フローの可視化・分析、ボトルネックの特定、手戻りループの検知を可能にします。 取得元 伝票ステータスの変更(例: BKPF-BSTAT)、変更履歴(CDHDR/CDPOS テーブル)、Workflow ログなど複数の情報源から導出します。多くの場合、カスタム抽出ロジックが必要です。 例 請求書 受領請求書 承認済み支払実行請求書 支払ブロック | |||
イベント時刻 EventTime | アクティビティが発生した正確な日時。 | ||
説明 Event Time は各アクティビティに紐づくタイムスタンプで、請求書に起きたイベントの時系列を提供します。プロセスの流れを理解し、時間分析を行ううえで不可欠です。 分析では Event Time を基準にアクティビティの順序を正しく並べ、各ステップ間のサイクルタイムや待ち時間を算出し、月次などの期間比較でパフォーマンスを評価します。あらゆる時間系KPIの土台となります。 その重要性 このタイムスタンプは、イベントを時系列に並べ、サイクルタイムや所要時間など時間ベースの指標を算出するうえで不可欠です。プロセスマイニングの根幹となる項目です。 取得元 SAP の各テーブルにある複数の日時フィールドから取得します(例:作成日(BKPF-CPUDT)、転記日(BKPF-BUDAT)、消込日(BSAK-AUGDT)、変更ログのタイムスタンプ(CDHDR-UDATE/UTIME)など)。 例 2023-10-01T09:00:00Z2023-10-05T14:30:15Z2023-10-15T11:21:05Z | |||
請求書 Invoice | 請求書ドキュメントの一意の識別子。AP プロセスにおける主要なケース ID として扱われます。 | ||
説明 請求書(Invoice)は、受領から支払いまでの全アクティビティを結び付ける中核オブジェクトです。SAP S/4HANA では、Company Code(BUKRS)、一意の Document Number(BELNR)、Fiscal Year(GJAHR)からなる複合キーで表すのが一般的です。 Invoice 単位で分析すると、ライフサイクルをエンドツーエンドで俯瞰できます。総サイクルタイムなどの主要指標の算出、個別請求書のボトルネック特定、プロセス上の多様な経路の理解に不可欠です。 その重要性 各請求書の軌跡を一意に識別でき、ライフサイクル全体の追跡とケース単位のパフォーマンス分析が可能になります。 取得元 これは、BKPF(会計伝票ヘッダ)またはRBKP(請求書受領ヘッダ)のBUKRS・BELNR・GJAHRから導出される複合キーです。 例 1000-1900000001-20231710-1900000002-20232000-5100000003-2024 | |||
ソースシステム SourceSystem | データを抽出したシステム。 | ||
説明 この属性はプロセスデータの出所を示します。このビューでは通常「SAP S/4HANA」となります。 複数ERPや連携システムがある環境では、このフィールドはデータリネージとデータの区分の観点で重要です。正しいデータセットで分析できるようにし、発生源まで遡ってデータ品質の問題を診断する助けになります。 その重要性 データの出所を示します。データガバナンス、トラブルシューティング、マルチシステム環境で特に重要です。 取得元 データ抽出時にデータセットの出所を示すために付与する、通常は固定の値です。 例 SAP S/4HANASAP ECC 6.0S4H_PROD_100 | |||
最終データ更新 LastDataUpdate | このレコードのデータがソースシステムから最後に更新されたタイムスタンプ。 | ||
説明 この属性は、SAP S/4HANAからの直近のデータ抽出・更新日時を示します。分析中のデータの鮮度を把握するうえで重要なメタデータです。 プロセス分析がどれだけ最新かを利用者が理解するために不可欠で、データの遅延に関する期待値の調整、定期的な更新スケジュールの策定、データ整合性の維持に役立ちます。 その重要性 データの鮮度を示し、プロセス分析がどれだけ最新かをユーザーに明確にします。 取得元 この値はソースシステムからデータを抽出した時点で生成され、各レコードに付与されます。 例 2024-05-20T04:00:00Z2024-05-21T04:00:00Z | |||
ユーザー名 UserName | そのアクティビティを実行したユーザーID。 | ||
説明 この属性は、記帳、承認、消込など特定アクティビティを実行したSAPユーザーIDを記録し、各プロセスステップと個々のユーザーを結びつけます。 ユーザー名での分析は、業務負荷の分散状況の把握、トップパフォーマーの特定、追加トレーニングが必要なユーザーの見極めに有効です。また、承認ボトルネックを可視化するdashboardでは、どの承認者が遅延の原因になっているかを特定するのに役立ちます。 その重要性 各アクティビティを担当者にひも付け、ユーザーのパフォーマンスや業務負荷、職務分掌ポリシーの遵守状況を分析できます。 取得元 通常は BKPF-USNAM(入力者)のようなヘッダテーブル、または CDHDR-USERNAME(変更者)のような変更ドキュメントテーブルで取得します。 例 ABROWNJSMITHAP_AUTOMATION | |||
仕入先名 VendorName | 請求書を提出した仕入先の名称。 | ||
説明 この属性は仕入先(ベンダー)の正式名称を保持します。請求書伝票に格納された仕入先番号を介して紐づきます。 仕入先分析は、サプライヤー関係の管理や、特定の仕入先に固有のプロセス課題の把握に欠かせません。例えば「不一致のある請求書を最も多く提出している仕入先はどこか」「戦略上重要な仕入先に継続的に期日内で支払えているか」といった問いに答えられます。また、請求書番号や金額と並び、重複支払の検知に重要なキー項目です。 その重要性 仕入先別にプロセスパフォーマンスを分析でき、課題のある仕入先の特定や戦略的な関係の効果的なマネジメントに役立ちます。 取得元 仕入先マスタ LFA1(フィールド NAME1)から取得します。BKPF または RBKP の仕入先番号(LIFNR)で結合します。 例 Office Supplies Inc.Global Consulting GroupMachine Parts GmbH | |||
会社コード CompanyCode | 請求書の処理対象となる組織単位。 | ||
説明 会社コードは、外部報告に必要な完結した会計帳簿を作成できる最小の組織単位です。APの文脈では、仕入先に対して債務を負う法的主体を表します。 会社コード別に分析することで、組織内の異なる法的主体間でプロセスパフォーマンスを比較できます。標準プロセスの準拠状況や、効率の高い部門、サイクルタイムが長い領域、手戻り率の高い領域を特定できます。 その重要性 複数法人間でプロセスパフォーマンスを比較でき、地域・事業部ごとの課題やベストプラクティスを特定できます。 取得元 伝票ヘッダテーブルに格納されています。FI 請求書は主に BKPF-BUKRS、MM 請求書は RBKP-BUKRS です。 例 10001710US01DE01 | |||
発注番号 PurchaseOrderNumber | 請求書に関連する購買発注(PO)の一意の識別子(該当する場合)。 | ||
説明 この属性は請求書と事前承認済みの発注書(PO)を紐づけます。PO番号の有無は、発注書—請求書—入庫の3点照合の前提となります。 コンプライアンスと業務効率の分析に不可欠です。購買ポリシーの順守を測る「POなし請求書比率」KPIの計算に使われるほか、POベースの請求書に対する照合プロセスを可視化する「3点照合パフォーマンス」dashboardの基礎データになります。 その重要性 発注書なしで処理された請求書を特定し、3点照合の効率や購買ポリシーの遵守状況を測るうえで重要です。 取得元 請求書の明細テーブルに格納されています。MM は RSEG-EBELN、FI は BSEG-EBELN。 例 45000012344500005678 | |||
請求書 期日 InvoiceDueDate | 仕入先への支払い期限日。 | ||
説明 Invoice Due Date は、遅延による費用を避け、良好な仕入先関係を維持するための支払期限です。請求書の基準日と仕入先と合意した支払条件に基づき算出されます。 この日付は 'Payment Compliance & Aging' dashboard や「期限内支払率」KPI に不可欠です。期日と実支払日を比較することで、期日内・早期・遅延の実態が明らかになり、財務面・取引関係の双方に直結する示唆が得られます。 その重要性 期限内支払い分析の中核となる項目です。支払いパフォーマンスや、仕入先との関係・延滞料への影響を測定できます。 取得元 この日付はしばしば計算で求められます。正味支払期日はBSEG-NETDTに格納されます。支払基準日(BSEG-ZFBDT)と支払条件(BSEG-ZTERM)から算出することもできます。 例 2023-10-312023-11-152024-01-10 | |||
請求書金額 InvoiceAmount | 請求書の総額(元のドキュメント通貨建て)。 | ||
説明 仕入先が提出した請求書の総額です。商品・サービスの対価、税金、その他の諸費用を含み、控除や割引の適用前の金額です。 請求書金額は、幅広い分析で使う重要な財務属性です。高額請求の優先度付け、プロセス遅延の金銭的影響(例:大型請求の延滞料)の把握、プロセスのセグメント化(例:「高額請求は承認経路が異なるか」)に役立ちます。重複支払いの可能性を特定するうえでも欠かせません。 その重要性 プロセスに財務的な文脈を与え、金額基準の分析や高額請求書の優先度付け、財務インパクトの定量化を可能にします。 取得元 MM 請求書は RBKP-RMWWR(請求書総額)などに格納されています。FI 請求書は BSEG の明細(WRBTR)から算出します。 例 1500.00250.7512345.50 | |||
仕入先請求書番号 VendorInvoiceNumber | 仕入先の請求書に記載された請求書番号。 | ||
説明 仕入先の会計システムで管理される参照番号で、紙または電子の請求書に記載されています。請求書受領時に手入力するか、OCRで取り込みます。 この項目は業務運用・分析の両面で非常に重要で、とりわけ「請求書重複支払いの可能性」dashboardで活用します。重複検知の一般的な方法は、仕入先名・仕入先請求書番号・請求書金額が同一の社内の請求書ドキュメントを複数検索することです。請求書の主な外部参照です。 その重要性 重複支払の可能性を検出する重要なフィールドであり、ベンダーとのやり取りにおける主要な外部参照として機能します。 取得元 ドキュメントヘッダの「Reference」フィールド(通常は BKPF-XBLNR)に格納。 例 INV-2023-9876733401120231015-001 | |||
処理時間 ProcessingTime | 単一アクティビティの所要時間。 | ||
説明 処理時間(Activity Duration)は、各アクティビティの開始から終了までに要した時間です。イベントログのデータから算出します。 この指標は「Activity Duration & Rework Heatmap」ダッシュボードで特に重要です。どのステップが最も時間を消費しているかを特定できます。処理時間を分析することで、長引く承認や差異解消に時間を要する活動などの非効率を可視化し、的を絞った改善につなげられます。 その重要性 各アクティビティに要した時間を定量化し、時間を要している工程やボトルネックの特定に役立ちます。 取得元 同一請求書の現在アクティビティの EventTime と、後続アクティビティの EventTime の差分で算出します。 例 P2DT3H4MPT5HP7D | |||
割引取得 DiscountTaken | 早期支払割引が適用されたかどうかを示すブール型フラグ。 | ||
説明 この属性は、請求書の支払い時に現金割引(早期支払割引)を実際に取得できたかどうかを示します。APプロセスの財務効率を測る重要要素です。 このフラグは「早期支払割引の取得率」KPIの中核です。支払条件に基づき割引適用が可能だった請求書を抽出し、このフラグを分析することで、どれだけの金額を節約できたか、またどれだけの機会を逃したかを正確に算出できます。APパフォーマンスを定量的かつ明確に示す指標です。 その重要性 利用可能な早期支払割引の活用状況を直接測定でき、企業の利益に直結します。 取得元 支払伝票の割引額フィールド(BSEG-SKNTO)が 0 より大きいかで判定します。 例 truefalse | |||
支払ブロック理由 BlockingReason | 支払ブロックの理由(不一致や問題点の内容)。 | ||
説明 請求書が 3-way マッチやその他の検証でチェックに失敗した場合、支払いはブロックされます。Blocking Reason は、数量不一致、価格差異、入庫伝票の欠落など、問題の内容を示します。 この属性は「請求書不整合の手戻り分析」dashboard に不可欠です。ブロック理由の頻度を分析することで、プロセス非効率の根本原因を突き止められます。たとえば「価格差異」が多い場合は、購買システムのマスタデータに課題がある可能性を示します。 その重要性 請求書の不整合や手戻りの根本原因を直接把握でき、的確なプロセス改善を後押しします。 取得元 RSEG などの請求書明細テーブルの、SPGR*(例:SPGRP、SPGRQ、SPGRT)で始まるフィールドに格納。RBKP_BLOCKED に格納されている場合もあります。 例 価格不一致数量不一致検収未計上 | |||
支払条件 PaymentTerms | 請求書の支払いに関して仕入先と取り決めた条件。早期支払割引などが含まれることがあります。 | ||
説明 支払条件は、支払期日や早期支払割引の有無・内容を定めるルールです。例えば「Z001」は「30日以内に支払い、10日以内なら2%割引」といった条件に対応している場合があります。 この属性は「早期支払割引獲得率」ダッシュボードの土台となります。支払条件を分析することで、割引対象だった請求書を洗い出せます。実際に獲得できた割引と突き合わせれば、取り逃した節約機会が明らかになり、支払プロセスの効率も定量的に評価できます。 その重要性 早期支払割引の機会分析、支払プロセスの財務パフォーマンス測定、取り逃した削減額の把握に不可欠です。 取得元 仕入先明細(BSEG-ZTERM)、または請求書ヘッダ(RBKP-ZTERM)に格納されています。 例 Z0010001NT30 | |||
支払遅延 IsLatePayment | 請求書が期日超過で支払われたかどうかを示すブール型フラグ。 | ||
説明 この計算属性は、請求書の支払いが公式な期日を過ぎて行われたかを示す真偽フラグです。「消込日」と「請求書の支払期日」を比較して導出します。 このフラグにより、「支払コンプライアンスとエイジング」dashboardや「期日内支払率」KPIの分析が容易になります。遅延支払件数の集計、期日内支払の割合計算、遅延が多い仕入先や会社コードの特定が簡単に行えます。 その重要性 支払条件の遵守度を直接測定し、期日どおりの支払KPIの計算を簡素化。支払パフォーマンスが低い領域の特定に役立ちます。 取得元 計算属性。ロジックは IF ClearingDate > InvoiceDueDate THEN true ELSE false。 例 truefalse | |||
消込日 ClearingDate | 支払いが実行され、未消込から外れた日付。 | ||
説明 消込日は、請求書が会計上決済されたことを示す日付です。'Payment Cleared' アクティビティが発生した日であり、多くの請求書での最終ステップとなります。 この日付は実際の支払日として用いられ、支払期日(Invoice Due Date)との比較に使われます。したがって「期限内支払率」KPI の算出や、支払パフォーマンスに関する分析に不可欠です。また、請求書のエンドツーエンドのサイクルタイムを計算する際の終点にもなります。 その重要性 請求書の最終清算を示し、サイクルタイム計測の終点であると同時に、期日どおりの支払分析の基準となります。 取得元 消込済み明細のテーブルに格納されています。例:仕入先は BSAK-AUGDT。 例 2023-10-282023-11-142024-01-09 | |||
自動処理 IsAutomated | 人手ではなくシステムにより自動実行されたアクティビティかどうかを示すフラグ。 | ||
説明 このブール型の属性は、人手による実行か、システムジョブ・workflow・ボットによる自動実行かを区別します。例えば、自動のPayment Runやシステム起票の請求書は自動としてフラグ付けされます。 この属性を分析することで、Accounts Payableプロセスの自動化レベルを把握できます。自動化施策の成果測定、手作業との効率比較、さらなる自動化余地の特定に活用できます。 その重要性 プロセスの自動化率を測ることで、自動化の効果検証やさらなる改善余地の発見に役立ちます。 取得元 ユーザー名(例: 'SAP_SYSTEM' や 'BATCHUSER' などのシステムユーザーID)や、自動ジョブに紐づく特定のトランザクションコードから判定します。 例 truefalse | |||
請求書伝票タイプ InvoiceDocumentType | 請求書ドキュメントの区分。SAPでの処理方法を制御します。 | ||
説明 Document Type は、会計ドキュメントを分類する SAP の重要な設定要素です。例えば仕入先請求書は 'KR'、MM 請求書は 'RE'、仕入先の返金伝票は 'KG' が一般的です。番号範囲や必須項目などもこの区分により決まります。 プロセス分析では、Document Type で絞り込むことで、請求書の種類ごとの流れを比較できます。たとえば、返金伝票の承認プロセスは標準の請求書と異なる場合があります。これは 'Invoice Approval Routing Variants' dashboard でも有用です。 その重要性 請求書タイプの取り扱いに基づいてプロセスをセグメント化でき、処理経路やサイクルタイムのばらつきを可視化します。 取得元 伝票ヘッダテーブルの BKPF-BLART フィールドから直接取得します。 例 KRREKG | |||
請求書通貨 InvoiceCurrency | 請求書金額の通貨コード(例:USD、EUR)。 | ||
説明 この属性は請求金額の通貨を示します。金額解釈の前提となるコンテキスト情報です。 多国籍の組織では、通貨を考慮せずに請求書を分析すると誤解を招きます。本フィールドにより、単一のレポート通貨へ換算する、または通貨別にセグメントして地域ごとの活動を把握するなど、適切な金額処理が可能になります。 その重要性 請求金額の解釈に必要な文脈を提供し、正確な財務分析・レポートを支援します。多国籍環境でも有効です。 取得元 伝票ヘッダテーブルに格納されています。主に BKPF-WAERS または RBKP-WAERS です。 例 USDEURGBPJPY | |||
買掛金請求書処理のアクティビティ
| アクティビティ | 説明 | ||
|---|---|---|---|
支払実行 | 請求書に対する支払いが実行されました。支払実行(Payment Run)が完了し、支払伝票が作成・計上された時点で記録されます。 | ||
その重要性 このアクティビティはキャッシュフロー分析に不可欠で、請求書の支払期日とこの日付を比較することで「期日内支払率」KPIを測定します。 取得元 これは、請求書を消込した支払伝票の転記日付から取得します。支払伝票番号は請求書の明細(BSEG)の消込伝票番号フィールド(AUGBL)に紐づきます。 取得 請求書明細を消し込んだ支払伝票の転記日付(BUDAT)を特定します。 イベントタイプ explicit | |||
支払消込済み | このアクティビティは請求書の最終クローズを示します。補助元帳で支払と請求書が相互に消込され、プロセス完了となります。 | ||
その重要性 プロセスの最終完了点であり、エンドツーエンドのサイクルタイムを正しく算出するために不可欠です。債務の決済が完了したことを確定します。 取得元 これは明示的なイベントで、請求書伝票の仕入先明細行(BSEG)に消込日(AUGDT)が入った時点を指します。 取得 請求書明細の消込日(BSEG-AUGDT)を使用します。 イベントタイプ explicit | |||
請求書 取消 | 請求書ドキュメントが反転(取消)され、会計上の影響が実質的に無効になっています。誤登録や仕入先とのトラブルが理由となることが多く、プロセスの別の終端です。 | ||
その重要性 取消を追跡すると、二重申請や請求書データの誤りなど、プロセス失敗の要因を特定でき、上流工程の課題も明らかになります。 取得元 反転伝票が作成された時点で明示的に記録されます。元の伝票ヘッダ(BKPF)には、反転伝票番号(STBLG)と反転理由が格納されます。 取得 原伝票ヘッダ(BKPF-STBLG)にリンクされた取消伝票の転記日付を特定します。 イベントタイプ explicit | |||
請求書 受領 | このアクティビティは、SAPで請求書伝票が作成されたことを示します。手入力でも、OCR/VIMなどの自動インターフェースでも対象です。このイベントは通常、会計伝票ヘッダの作成日時から取得されます。 | ||
その重要性 プロセスの起点であり、請求書処理のエンドツーエンドのサイクルタイム算出や、AP(買掛金)全体のスループット測定に不可欠です。 取得元 このイベントは、会計伝票ヘッダ(BKPF)から取得します。伝票作成日(CPUDT)と作成時刻(CPUTM)を使用します。 取得 請求書ドキュメントには作成タイムスタンプ(BKPF-CPUDT, BKPF-CPUTM)を使用します。 イベントタイプ explicit | |||
請求書 承認済み | 請求書は workflow 上で必要な承認をすべて取得しました。多くの場合、転記や支払ブロック解除の直前のステップです。 | ||
その重要性 承認サイクルの完了を示す重要なマイルストーンです。回付から承認までの時間は、効率性を測る重要指標です。 取得元 SAP Business Workflow のログから完了または最終リリースのステップとして取得します。あるいは、ルーティング後の支払ブロック解除から推定できます。 取得 SAP のワークフローログから完了イベントを抽出するか、最終の「解放」イベントを特定します。 イベントタイプ explicit | |||
請求書 支払ブロック | システムが自動または手動で請求書に支払ブロックを設定し、支払いを停止しています。価格・数量の不一致や承認未了が主な原因です。 | ||
その重要性 これは、問題や手戻りを示す重要な指標です。保留理由や期間を分析することで、支払遅延やプロセスの非効率の根本原因を特定できます。 取得元 これは明示的なステータスで、会計伝票の仕入先明細行(BSEG)にある支払保留キー(ZLSPR)に記録されます。 取得 ブロック理由が BSEG-ZLSPR フィールドに設定された際、変更ドキュメントとして記録されます。 イベントタイプ explicit | |||
請求書 転記 | 請求書が総勘定元帳に正規登録され、負債が計上されます。Parked(保留)文書が転記済みに変わる、または直接転記されます。 | ||
その重要性 これは重要な財務マイルストーンです。支払義務の確定を意味し、多くの場合、支払スケジュール設定の前提となります。 取得元 このイベントは、伝票ヘッダ(BKPF)の転記日付(BUDAT)で判別します。転記済み伝票では伝票ステータス(BKPF-BSTAT)はブランクです。 取得 Parked でないドキュメント(BKPF-BSTAT が空白)の場合は、転記タイムスタンプ(BKPF-BUDAT)を使用します。 イベントタイプ explicit | |||
入荷照合済み | このアクティビティは、請求数量・金額が対応する入庫伝票(Goods Receipt)と一致したことを示します。3点照合シナリオにおける最終確認です。 | ||
その重要性 これを追跡することで、3-way マッチングの非効率や、受入実績と仕入先の請求内容との不一致を特定できます。 取得元 これは、請求書明細に物料伝票(入庫)の参照が存在することから推定します。多くは発注品目の履歴を介して紐づきます。 取得 請求書明細に入荷(GR)伝票の参照がある場合に推定します(例:MIRO 請求書の RSEG)。 イベントタイプ inferred | |||
差異を解消 | このアクティビティは、支払保留の原因とみられる事前特定の問題が調査され、解決したことを示します。請求書の支払保留が解除された時点で記録されます。 | ||
その重要性 この手戻りループの追跡は「請求書不整合の手戻り分析」dashboard にとって重要です。エラー修正に要した時間と工数を定量化できます。 取得元 これは、支払保留の解除を示す変更伝票から推定します。主な情報源はBSEG-ZLSPRフィールドの変更ログです。 取得 BSEG の変更履歴から、ZLSPR フィールドが値ありから空白に変更されたレコードを特定します。 イベントタイプ inferred | |||
支払提案を作成 | 支払実行(例:F110)の一環として支払提案に組み込まれました。本実行の完了待ちで、支払い予定の状態です。 | ||
その重要性 このアクティビティは、未払債務が支払い準備中の明細へ移行したことを示し、支払い業務の効率分析に役立ちます。 取得元 このイベントは支払プログラムのデータテーブルに明示的に記録されます。具体的にはREGUP(支払プログラムの処理明細)とREGUH(ヘッダ)です。 取得 REGUH で識別される支払実行において、請求書が REGUP に現れるタイミングを特定します。 イベントタイプ explicit | |||
発注と照合済み | このアクティビティは、請求書が対応する発注書(PO)と照合済みであることを示します。購買系の請求書における3点照合の重要なステップです。 | ||
その重要性 このアクティビティの分析は照合プロセスの効率測定に役立ち、KPIである『3-Way Matching Performance』や『PO-Less Invoice Percentage』の基礎となります。 取得元 これは、BSEGまたはACDOCAの請求書明細に有効な発注書番号(EBELN)と品目(EBELP)が入っている場合に推定されます。 取得 請求書作成時に発注書参照(BSEG-EBELN)が存在することから推定します。 イベントタイプ inferred | |||
請求書 却下 | 承認ワークフローの途中で承認者が請求書を却下しました。通常、この操作により請求書は処理担当者に差し戻され、修正や確認が求められます。 | ||
その重要性 却下の追跡は、承認プロセス内の手戻りループを浮き彫りにし、コンプライアンス上の問題や請求書のコード誤りを示す場合があります。 取得元 これは、請求書に紐づくSAP Business Workflowのログ内で、特定の結果イベントとして取得されます。 取得 SAP のワークフローログから、ステータスが「却下」のイベントを抽出します。 イベントタイプ explicit | |||
請求書 承認ルートへ送付 | ビジネスルールに基づき、請求書が workflow に回され、必要な承認に提出されました。ここから承認サブプロセスが始まります。 | ||
その重要性 このアクティビティは「請求書承認の平均所要時間」KPIの計測の起点となり、承認ボトルネックの分析に役立ちます。 取得元 SAP Business Workflow のログ(SWW* テーブル)から取得可能で、請求書オブジェクト(例: BUS2081)に紐づくワークフローインスタンスの開始が記録されています。 取得 請求書ドキュメントに紐づくワークフロー開始イベントを、SAP のワークフローログ(例:SWW_WIHEAD)から抽出します。 イベントタイプ explicit | |||
請求書 期日超過 | 請求書の正味支払期日を過ぎても消込が行われていないことを示す、計算で判定されるイベント。延滞・未払いの状態を意味します。 | ||
その重要性 「Payment Compliance & Aging」dashboard に不可欠なアクティビティで、延滞請求書の早期発見と管理、遅延の根本原因分析に役立ちます。 取得元 これはSAPにおける明示的なイベントではありません。システムの現在日付と正味支払期日(支払基準日BSEG-ZFBDTと支払条件から算出)を比較して計算されます。 取得 イベントのタイムスタンプが請求書の正味支払期日を超えたときに発生する計算イベントです。 イベントタイプ calculated | |||
請求書 駐車 | システムに入力済みだが、まだ総勘定元帳に転記していない請求書を表します。不完全な伝票をいったん保存し、後で処理や承認を行う目的で意図的に用いられるステップです。 | ||
その重要性 Parked 請求書を追跡すると、正式な転記プロセスが始まる前の遅延を把握でき、データの完全性や初期バリデーションの問題を可視化できます。 取得元 このステータスは会計ドキュメントヘッダのドキュメントステータス項目から判定します(Parked は BKPF-BSTAT = 'V')。ステータスが設定された時点でイベントが発生します。 取得 BKPF の変更履歴から、BSTAT フィールドが 'V'(Vor-erfasst/事前入力)に設定されたレコードを特定します。 イベントタイプ inferred | |||
抽出ガイド
ステップ
- 前提条件とアクセス権: CDSビューがあるSAP S/4HANAのデータベーススキーマ(一般的にはSAPABAP1など)に読み取り権限を持つユーザーをご用意ください。SAP HANAデータベースに接続できるSQLクライアント(SAP HANA Studio、DBeaverなどのクエリツール)が必要です。
- 主要なCDSビューの特定: 抽出で使用する主なCDSビューは I_JournalEntry、I_JournalEntryItem、I_SupplierInvoiceAPI01、I_ChangeDocument、I_WorkflowStatusDetails、I_PaymentProposalItem です。各ビューの主要フィールドを把握しておきましょう。
- クエリ範囲の定義: SQLクライアントでSAP HANAに接続し、実行前に抽出の範囲を決めます。対象のソースシステムID、請求書の作成日時(CreationDateTime)の期間、該当する会社コードを設定してください。
- メインクエリの準備: queryセクションの完全なSQLをSQLクライアントに貼り付けます。Common Table Expressions(CTE)を用いて、まずベースとなる請求書群を選定し、その後15種類のアクティビティのデータをUNIONしてイベントログを構築します。
- クエリパラメータの設定: コピーしたSQL内のプレースホルダー変数を探し、分析期間の開始日と終了日の '[YYYY-MM-DD]' を実際の日付に置き換えます。会社コードは '[Your Company Code 1]'、'[Your Company Code 2]' のように、分析対象の一覧へ置き換えてください。
- 抽出クエリの実行: 完全なSQLクエリを実行します。データ量や期間によって、完了まで数分〜数時間かかる場合があります。
- 結果の一次確認: クエリ完了後、出力の先頭数百行を確認します。データの整合性、各列が期待通りに埋まっているか、ActivityName に複数の値が含まれているかをチェックしてください。
- イベントログのエクスポート: SQLクライアントから結果全体をCSVにエクスポートします。文字化け防止のためUTF-8で保存してください。ファイル名は sap_s4hana_ap_event_log.csv のように内容が分かる名前にします。
- アップロードの準備: Process Miningツールにアップロードする前に、CSVの列ヘッダーが要求される属性名(Invoice、ActivityName、EventTime、SourceSystem、LastDataUpdate、UserName など)と完全一致していることを確認してください。
- Process Miningツールへアップロード: 生成したCSVをProcess Miningプラットフォームにアップロードし、列をCase ID・Activity・Timestamp各フィールドにマッピングします。
設定
- 主要なCDSビュー: 抽出は、標準の S/4HANA CDS ビューを組み合わせて行います。主なビューは次のとおりです。
- I_JournalEntry と I_JournalEntryItem: 財務伝票のヘッダー/明細、転記の詳細、消し込み情報を取得します。
- I_SupplierInvoiceAPI01: MM(ロジスティクス)領域の請求書固有情報。PO 参照や支払ブロックなどを含みます。
- I_ChangeDocument: 支払ブロックの設定/解除など、変更の正確なタイムスタンプを追跡します。
- I_WorkflowStatusDetails: 請求書承認のワークフローに関連するイベントを抽出します。
- I_PaymentProposalItem: 請求書が支払提案(Payment Run)に含まれたタイミングを特定します。
- I_Supplier: VendorName などの仕入先マスタ情報でデータを補完します。
- 期間フィルター: データ量を抑えるため、期間フィルターは不可欠です。提供クエリでは Invoices_Base CTE の CreationDateTime で絞り込みます。初期分析では 3〜6 か月の範囲を推奨します。パフォーマンスを現実的な水準に保てます。
- 必須フィルター: 常に CompanyCode で絞り込んでください。すべての会社コードを一括で分析すると非常に遅く、業務上の意味も薄れがちです。あわせて JournalEntryType で仕入先関連の伝票(例: 'KR', 'RE')のみに限定してください。
- 前提条件: クエリで使用するすべての CDS ビューおよび背後の HANA スキーマに対して、実行ユーザーに SELECT 権限が必要です。SAP GUI 上のアプリケーション権限だけでは不十分です。
- パフォーマンス上の注意: I_ChangeDocument への直接クエリはリソース負荷が高くなりうるため、本クエリではまず請求書を事前に絞り込んで負荷を軽減しています。非常に大きなデータセットでは、閑散時間帯に抽出を実行するか、期間を小分けにしてバッチ実行することを検討してください。
a クエリ例 sql
`sql
-- Common Table Expression (CTE) to select the base set of AP Invoices
WITH Invoices_Base AS (
SELECT
I_JournalEntry.CompanyCode,
I_JournalEntry.AccountingDocument,
I_JournalEntry.FiscalYear,
CONCAT(I_JournalEntry.CompanyCode, CONCAT(I_JournalEntry.AccountingDocument, I_JournalEntry.FiscalYear)) AS InvoiceId,
I_JournalEntry.CreationDateTime,
I_JournalEntry.CreatedByUser,
I_JournalEntry.DocumentStatus,
I_JournalEntry.JournalEntryType,
I_JournalEntry.ReversalReferenceJournalEntry,
I_JournalEntry.IsReversed,
I_JournalEntry.ReversalDate,
IJE_ITEM.NetDueDate,
IJE_ITEM.Supplier,
SUP.SupplierName AS VendorName,
IJE_ITEM.AmountInCompanyCodeCurrency AS InvoiceAmount,
MM.PurchaseOrder AS PurchaseOrderNumber,
MM.PaymentBlockingReason
FROM I_JournalEntry
-- Join to get item details like due date and supplier
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON I_JournalEntry.CompanyCode = IJE_ITEM.CompanyCode
AND I_JournalEntry.AccountingDocument = IJE_ITEM.AccountingDocument
AND I_JournalEntry.FiscalYear = IJE_ITEM.FiscalYear
AND IJE_ITEM.IsSupplier = 'X'
-- Join to get vendor name from master data
LEFT JOIN I_Supplier AS SUP
ON IJE_ITEM.Supplier = SUP.Supplier
-- Join to get MM Invoice specific data like PO Number and Payment Block
LEFT JOIN I_SupplierInvoiceAPI01 AS MM
ON I_JournalEntry.AccountingDocument = MM.AccountingDocument
AND I_JournalEntry.CompanyCode = MM.CompanyCode
AND I_JournalEntry.FiscalYear = MM.FiscalYear
WHERE
I_JournalEntry.JournalEntryType IN ('KR', 'RE') -- Standard Vendor Invoice Types
AND I_JournalEntry.CompanyCode IN ('[Your Company Code 1]', '[Your Company Code 2]')
AND I_JournalEntry.CreationDateTime BETWEEN '[YYYY-MM-DD]T00:00:00Z' AND '[YYYY-MM-DD]T23:59:59Z'
)
-- Event: 1. Invoice Received
SELECT
B.InvoiceId AS "Invoice",
'Invoice Received' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
UNION ALL
-- Event: 2. Invoice Parked
SELECT
B.InvoiceId AS "Invoice",
'Invoice Parked' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.DocumentStatus = 'V' -- 'V' stands for Parked
UNION ALL
-- Event: 3. Purchase Order Matched
SELECT
B.InvoiceId AS "Invoice",
'Purchase Order Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PurchaseOrderNumber IS NOT NULL AND B.PurchaseOrderNumber <> ''
UNION ALL
-- Event: 4. Goods Receipt Matched
SELECT
B.InvoiceId AS "Invoice",
'Goods Receipt Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_SupplierInvoiceItemAPI01 AS MM_ITEM
ON B.AccountingDocument = MM_ITEM.AccountingDocument
AND B.FiscalYear = MM_ITEM.FiscalYear
WHERE MM_ITEM.GoodsReceipt IS NOT NULL AND MM_ITEM.GoodsReceipt <> ''
UNION ALL
-- Event: 5. Invoice Blocked For Payment
SELECT
B.InvoiceId AS "Invoice",
'Invoice Blocked For Payment' AS "ActivityName",
B.CreationDateTime AS "EventTime", -- Approximates block time as creation time if blocked on entry
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PaymentBlockingReason IS NOT NULL AND B.PaymentBlockingReason <> ''
UNION ALL
-- Event: 6. Discrepancy Resolved (Payment Block Removed)
SELECT
B.InvoiceId AS "Invoice",
'Discrepancy Resolved' AS "ActivityName",
CD.ChangeTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CD.UserName AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_ChangeDocument AS CD
ON CONCAT(B.CompanyCode, B.AccountingDocument, B.FiscalYear) = CD.ObjectValue
WHERE CD.ChangeDocumentObject = 'INVOICE'
AND CD.TableName = 'RBKP'
AND CD.FieldName = 'ZLSPR' -- Field for Payment Block
AND CD.NewFieldValue = '' -- Block was removed
UNION ALL
-- Event: 7, 8, 9. Workflow Events (Routed, Approved, Rejected)
SELECT
B.InvoiceId AS "Invoice",
CASE WF.WorkflowStatus
WHEN 'READY' THEN 'Invoice Routed For Approval'
WHEN 'APPROVED' THEN 'Invoice Approved'
WHEN 'REJECTED' THEN 'Invoice Rejected'
END AS "ActivityName",
WF.WorkflowStatusChangedDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
WF.WorkflowStatusChangedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_WorkflowStatusDetails AS WF
ON B.InvoiceId = WF.WorkflowScenarioInstance
WHERE WF.WorkflowStatus IN ('READY', 'APPROVED', 'REJECTED')
UNION ALL
-- Event: 10. Invoice Posted
SELECT
B.InvoiceId AS "Invoice",
'Invoice Posted' AS "ActivityName",
JE.PostingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntry AS JE
ON B.AccountingDocument = JE.AccountingDocument
AND B.CompanyCode = JE.CompanyCode
AND B.FiscalYear = JE.FiscalYear
WHERE B.DocumentStatus <> 'V' -- Any status other than Parked is considered Posted for AP
UNION ALL
-- Event: 11. Payment Proposal Created
SELECT
B.InvoiceId AS "Invoice",
'Payment Proposal Created' AS "ActivityName",
PPI.PaymentProposalRunDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
PPI.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_PaymentProposalItem AS PPI
ON B.CompanyCode = PPI.CompanyCode
AND B.AccountingDocument = PPI.AccountingDocument
AND B.FiscalYear = PPI.FiscalYear
UNION ALL
-- Event: 12. Payment Executed
-- This links the invoice to its clearing document, which is the payment document
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Executed' AS "ActivityName",
CLEAR_JE.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CLEAR_JE.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
INNER JOIN I_JournalEntry AS CLEAR_JE
ON IJE_ITEM.ClearingJournalEntry = CLEAR_JE.AccountingDocument
AND IJE_ITEM.CompanyCode = CLEAR_JE.CompanyCode
WHERE IJE_ITEM.ClearingJournalEntry IS NOT NULL AND IJE_ITEM.ClearingJournalEntry <> ''
AND CLEAR_JE.JournalEntryType = 'KZ' -- Vendor Payment Document Type
UNION ALL
-- Event: 13. Invoice Due Date Passed
SELECT
B.InvoiceId AS "Invoice",
'Invoice Due Date Passed' AS "ActivityName",
ADD_DAYS(B.NetDueDate, 1) AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
'SYSTEM' AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE B.NetDueDate < CURRENT_DATE
AND IJE_ITEM.ClearingDate IS NULL -- Invoice is not yet cleared
UNION ALL
-- Event: 14. Payment Cleared
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Cleared' AS "ActivityName",
IJE_ITEM.ClearingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
IJE_ITEM.ChangedByUser AS "UserName", -- User who cleared it
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE IJE_ITEM.ClearingDate IS NOT NULL
UNION ALL
-- Event: 15. Invoice Cancelled
SELECT
B.InvoiceId AS "Invoice",
'Invoice Cancelled' AS "ActivityName",
B.ReversalDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName", -- User who created the original document
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.IsReversed = 'X';
`ステップ
- 前提条件とアクセス権: CDSビューがあるSAP S/4HANAのデータベーススキーマ(一般的にはSAPABAP1など)に読み取り権限を持つユーザーをご用意ください。SAP HANAデータベースに接続できるSQLクライアント(SAP HANA Studio、DBeaverなどのクエリツール)が必要です。
- 主要なCDSビューの特定: 抽出で使用する主なCDSビューは I_JournalEntry、I_JournalEntryItem、I_SupplierInvoiceAPI01、I_ChangeDocument、I_WorkflowStatusDetails、I_PaymentProposalItem です。各ビューの主要フィールドを把握しておきましょう。
- クエリ範囲の定義: SQLクライアントでSAP HANAに接続し、実行前に抽出の範囲を決めます。対象のソースシステムID、請求書の作成日時(CreationDateTime)の期間、該当する会社コードを設定してください。
- メインクエリの準備: queryセクションの完全なSQLをSQLクライアントに貼り付けます。Common Table Expressions(CTE)を用いて、まずベースとなる請求書群を選定し、その後15種類のアクティビティのデータをUNIONしてイベントログを構築します。
- クエリパラメータの設定: コピーしたSQL内のプレースホルダー変数を探し、分析期間の開始日と終了日の '[YYYY-MM-DD]' を実際の日付に置き換えます。会社コードは '[Your Company Code 1]'、'[Your Company Code 2]' のように、分析対象の一覧へ置き換えてください。
- 抽出クエリの実行: 完全なSQLクエリを実行します。データ量や期間によって、完了まで数分〜数時間かかる場合があります。
- 結果の一次確認: クエリ完了後、出力の先頭数百行を確認します。データの整合性、各列が期待通りに埋まっているか、ActivityName に複数の値が含まれているかをチェックしてください。
- イベントログのエクスポート: SQLクライアントから結果全体をCSVにエクスポートします。文字化け防止のためUTF-8で保存してください。ファイル名は sap_s4hana_ap_event_log.csv のように内容が分かる名前にします。
- アップロードの準備: Process Miningツールにアップロードする前に、CSVの列ヘッダーが要求される属性名(Invoice、ActivityName、EventTime、SourceSystem、LastDataUpdate、UserName など)と完全一致していることを確認してください。
- Process Miningツールへアップロード: 生成したCSVをProcess Miningプラットフォームにアップロードし、列をCase ID・Activity・Timestamp各フィールドにマッピングします。
設定
- 主要なCDSビュー: 抽出は、標準の S/4HANA CDS ビューを組み合わせて行います。主なビューは次のとおりです。
- I_JournalEntry と I_JournalEntryItem: 財務伝票のヘッダー/明細、転記の詳細、消し込み情報を取得します。
- I_SupplierInvoiceAPI01: MM(ロジスティクス)領域の請求書固有情報。PO 参照や支払ブロックなどを含みます。
- I_ChangeDocument: 支払ブロックの設定/解除など、変更の正確なタイムスタンプを追跡します。
- I_WorkflowStatusDetails: 請求書承認のワークフローに関連するイベントを抽出します。
- I_PaymentProposalItem: 請求書が支払提案(Payment Run)に含まれたタイミングを特定します。
- I_Supplier: VendorName などの仕入先マスタ情報でデータを補完します。
- 期間フィルター: データ量を抑えるため、期間フィルターは不可欠です。提供クエリでは Invoices_Base CTE の CreationDateTime で絞り込みます。初期分析では 3〜6 か月の範囲を推奨します。パフォーマンスを現実的な水準に保てます。
- 必須フィルター: 常に CompanyCode で絞り込んでください。すべての会社コードを一括で分析すると非常に遅く、業務上の意味も薄れがちです。あわせて JournalEntryType で仕入先関連の伝票(例: 'KR', 'RE')のみに限定してください。
- 前提条件: クエリで使用するすべての CDS ビューおよび背後の HANA スキーマに対して、実行ユーザーに SELECT 権限が必要です。SAP GUI 上のアプリケーション権限だけでは不十分です。
- パフォーマンス上の注意: I_ChangeDocument への直接クエリはリソース負荷が高くなりうるため、本クエリではまず請求書を事前に絞り込んで負荷を軽減しています。非常に大きなデータセットでは、閑散時間帯に抽出を実行するか、期間を小分けにしてバッチ実行することを検討してください。
a クエリ例 sql
`sql
-- Common Table Expression (CTE) to select the base set of AP Invoices
WITH Invoices_Base AS (
SELECT
I_JournalEntry.CompanyCode,
I_JournalEntry.AccountingDocument,
I_JournalEntry.FiscalYear,
CONCAT(I_JournalEntry.CompanyCode, CONCAT(I_JournalEntry.AccountingDocument, I_JournalEntry.FiscalYear)) AS InvoiceId,
I_JournalEntry.CreationDateTime,
I_JournalEntry.CreatedByUser,
I_JournalEntry.DocumentStatus,
I_JournalEntry.JournalEntryType,
I_JournalEntry.ReversalReferenceJournalEntry,
I_JournalEntry.IsReversed,
I_JournalEntry.ReversalDate,
IJE_ITEM.NetDueDate,
IJE_ITEM.Supplier,
SUP.SupplierName AS VendorName,
IJE_ITEM.AmountInCompanyCodeCurrency AS InvoiceAmount,
MM.PurchaseOrder AS PurchaseOrderNumber,
MM.PaymentBlockingReason
FROM I_JournalEntry
-- Join to get item details like due date and supplier
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON I_JournalEntry.CompanyCode = IJE_ITEM.CompanyCode
AND I_JournalEntry.AccountingDocument = IJE_ITEM.AccountingDocument
AND I_JournalEntry.FiscalYear = IJE_ITEM.FiscalYear
AND IJE_ITEM.IsSupplier = 'X'
-- Join to get vendor name from master data
LEFT JOIN I_Supplier AS SUP
ON IJE_ITEM.Supplier = SUP.Supplier
-- Join to get MM Invoice specific data like PO Number and Payment Block
LEFT JOIN I_SupplierInvoiceAPI01 AS MM
ON I_JournalEntry.AccountingDocument = MM.AccountingDocument
AND I_JournalEntry.CompanyCode = MM.CompanyCode
AND I_JournalEntry.FiscalYear = MM.FiscalYear
WHERE
I_JournalEntry.JournalEntryType IN ('KR', 'RE') -- Standard Vendor Invoice Types
AND I_JournalEntry.CompanyCode IN ('[Your Company Code 1]', '[Your Company Code 2]')
AND I_JournalEntry.CreationDateTime BETWEEN '[YYYY-MM-DD]T00:00:00Z' AND '[YYYY-MM-DD]T23:59:59Z'
)
-- Event: 1. Invoice Received
SELECT
B.InvoiceId AS "Invoice",
'Invoice Received' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
UNION ALL
-- Event: 2. Invoice Parked
SELECT
B.InvoiceId AS "Invoice",
'Invoice Parked' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.DocumentStatus = 'V' -- 'V' stands for Parked
UNION ALL
-- Event: 3. Purchase Order Matched
SELECT
B.InvoiceId AS "Invoice",
'Purchase Order Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PurchaseOrderNumber IS NOT NULL AND B.PurchaseOrderNumber <> ''
UNION ALL
-- Event: 4. Goods Receipt Matched
SELECT
B.InvoiceId AS "Invoice",
'Goods Receipt Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_SupplierInvoiceItemAPI01 AS MM_ITEM
ON B.AccountingDocument = MM_ITEM.AccountingDocument
AND B.FiscalYear = MM_ITEM.FiscalYear
WHERE MM_ITEM.GoodsReceipt IS NOT NULL AND MM_ITEM.GoodsReceipt <> ''
UNION ALL
-- Event: 5. Invoice Blocked For Payment
SELECT
B.InvoiceId AS "Invoice",
'Invoice Blocked For Payment' AS "ActivityName",
B.CreationDateTime AS "EventTime", -- Approximates block time as creation time if blocked on entry
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PaymentBlockingReason IS NOT NULL AND B.PaymentBlockingReason <> ''
UNION ALL
-- Event: 6. Discrepancy Resolved (Payment Block Removed)
SELECT
B.InvoiceId AS "Invoice",
'Discrepancy Resolved' AS "ActivityName",
CD.ChangeTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CD.UserName AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_ChangeDocument AS CD
ON CONCAT(B.CompanyCode, B.AccountingDocument, B.FiscalYear) = CD.ObjectValue
WHERE CD.ChangeDocumentObject = 'INVOICE'
AND CD.TableName = 'RBKP'
AND CD.FieldName = 'ZLSPR' -- Field for Payment Block
AND CD.NewFieldValue = '' -- Block was removed
UNION ALL
-- Event: 7, 8, 9. Workflow Events (Routed, Approved, Rejected)
SELECT
B.InvoiceId AS "Invoice",
CASE WF.WorkflowStatus
WHEN 'READY' THEN 'Invoice Routed For Approval'
WHEN 'APPROVED' THEN 'Invoice Approved'
WHEN 'REJECTED' THEN 'Invoice Rejected'
END AS "ActivityName",
WF.WorkflowStatusChangedDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
WF.WorkflowStatusChangedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_WorkflowStatusDetails AS WF
ON B.InvoiceId = WF.WorkflowScenarioInstance
WHERE WF.WorkflowStatus IN ('READY', 'APPROVED', 'REJECTED')
UNION ALL
-- Event: 10. Invoice Posted
SELECT
B.InvoiceId AS "Invoice",
'Invoice Posted' AS "ActivityName",
JE.PostingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntry AS JE
ON B.AccountingDocument = JE.AccountingDocument
AND B.CompanyCode = JE.CompanyCode
AND B.FiscalYear = JE.FiscalYear
WHERE B.DocumentStatus <> 'V' -- Any status other than Parked is considered Posted for AP
UNION ALL
-- Event: 11. Payment Proposal Created
SELECT
B.InvoiceId AS "Invoice",
'Payment Proposal Created' AS "ActivityName",
PPI.PaymentProposalRunDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
PPI.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_PaymentProposalItem AS PPI
ON B.CompanyCode = PPI.CompanyCode
AND B.AccountingDocument = PPI.AccountingDocument
AND B.FiscalYear = PPI.FiscalYear
UNION ALL
-- Event: 12. Payment Executed
-- This links the invoice to its clearing document, which is the payment document
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Executed' AS "ActivityName",
CLEAR_JE.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CLEAR_JE.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
INNER JOIN I_JournalEntry AS CLEAR_JE
ON IJE_ITEM.ClearingJournalEntry = CLEAR_JE.AccountingDocument
AND IJE_ITEM.CompanyCode = CLEAR_JE.CompanyCode
WHERE IJE_ITEM.ClearingJournalEntry IS NOT NULL AND IJE_ITEM.ClearingJournalEntry <> ''
AND CLEAR_JE.JournalEntryType = 'KZ' -- Vendor Payment Document Type
UNION ALL
-- Event: 13. Invoice Due Date Passed
SELECT
B.InvoiceId AS "Invoice",
'Invoice Due Date Passed' AS "ActivityName",
ADD_DAYS(B.NetDueDate, 1) AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
'SYSTEM' AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE B.NetDueDate < CURRENT_DATE
AND IJE_ITEM.ClearingDate IS NULL -- Invoice is not yet cleared
UNION ALL
-- Event: 14. Payment Cleared
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Cleared' AS "ActivityName",
IJE_ITEM.ClearingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
IJE_ITEM.ChangedByUser AS "UserName", -- User who cleared it
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE IJE_ITEM.ClearingDate IS NOT NULL
UNION ALL
-- Event: 15. Invoice Cancelled
SELECT
B.InvoiceId AS "Invoice",
'Invoice Cancelled' AS "ActivityName",
B.ReversalDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName", -- User who created the original document
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.IsReversed = 'X';
`ステップ
- 仕様と設計: コーディングを開始する前に、ビジネスアナリストと協力し、15の必須アクティビティそれぞれについて、正確なトリガー条件とデータ項目を確認します。対象となるSAPテーブル、伝票タイプ(例:KR、RE)、および会社コードを特定します。
- ABAPプログラムの作成: トランザクションコード SE38 を使用して ABAP Editor を起動します。新しい実行可能プログラム(例: Z_PM_AP_INVOICE_EXTRACT)を作成し、わかりやすいタイトルを設定して、アプリケーションを「財務会計」に設定します。
- 選択画面の定義: プログラム内で、ユーザーが抽出期間(請求書作成日)、対象となる会社コード(BUKRS)、および関連する請求書伝票タイプ(BLART)を指定できるよう、PARAMETERS および SELECT-OPTIONS キーワードを用いて選択画面を定義します。アプリケーションサーバー上の出力ファイルパス用のパラメータも定義します。
- データ宣言: 最終的なイベントログ形式(例: TY_EVENT_LOG)に一致する内部テーブル構造を定義し、必須および推奨されるすべての属性を含めます。BKPF、BSEG、RBKP、RSEG、CDHDR、CDPOS、REGUHなどのさまざまなSAPソーステーブルから選択されたデータを保持するための内部テーブルを宣言します。
- メインデータの選択: ユーザーの選択画面の条件に基づいて、RBKP(ロジスティクス請求書)と BKPF(財務会計請求書)から主要な請求書セットを選択し、抽出ロジックを開始します。これらの主要な請求書キーを内部テーブルに保存し、その後のデータ検索に使用します。
- アクティビティの順次抽出: メインセットの各請求書について、一連の選択を実行して、各ビジネスアクティビティのタイムスタンプと詳細を取得します。たとえば、CDHDR と CDPOS で支払ブロックの変更を照会し、REGUH と REGUP で支払実行データを照会し、BKPF で取消伝票の詳細を照会します。見つかった各アクティビティについて、最終イベントログテーブルに新しいレコードを追加します。
- 算出イベントのロジック: テーブル項目に直接保存されていないアクティビティの ABAP ロジックを実装します。「請求書期日経過」イベントの場合、請求書期日(BSEG-ZFBDT + 支払条件)と消込日(BSEG-AUGDT)を使用します。消込日が期日よりも後の場合、タイムスタンプを期日に設定した新しいイベントレコードを作成します。
- データ変換とエンリッチメント: 各アクティビティのデータを収集する際に、すべての必須属性を設定します。これには、LFA1 からの仕入先名の検索、日付と時刻を単一のタイムスタンプ文字列に変換(CONCATENATE...INTO...)、および SourceSystem 値の設定が含まれます。
- 出力ファイルの生成: すべての請求書とそれに対応するアクティビティが処理され、最終的な内部テーブルに収集されたら、OPEN DATASET、LOOP AT ... TRANSFER、CLOSE DATASET ステートメントを使用して、選択画面で指定されたアプリケーションサーバーパスのファイルにデータを書き込みます。
- ダウンロードとアップロード準備: トランザクションコード CG3Y を使用して、生成されたファイルをアプリケーションサーバーからローカルマシンにダウンロードします。ファイルが UTF-8エンコードのCSV形式 で保存されていることを確認します。プロセスマイニングツールにアップロードする前に、列ヘッダーが必須属性(Invoice、ActivityName、EventTimeなど)と一致することを確認します。
設定
- 期間設定: 請求書作成日(BKPF-CPUDTまたはRBKP-CPUDT)について、P_CPUDT selection-optionを設定します。初回分析には、6~12ヶ月間のデータ範囲を推奨します。
- 会社コード(P_BUKRS): 特定の会社コードで絞り込むための必須SELECT-OPTIONSパラメーターです。絶対に必要な場合を除き、全ての会社コードを一度に処理することは推奨されません。
- 請求書伝票タイプ(P_BLART): 関連する請求書伝票タイプで絞り込むためのSELECT-OPTIONSパラメーターです。一般的なタイプには、「KR」(仕入先請求書)、「KG」(仕入先クレジットメモ)、「RE」(ロジスティクス請求書照合)などがあります。
- 実行モード: 大量のデータ処理の場合、フォアグラウンドの対話型プロセスでのタイムアウトを避けるため、プログラムはバックグラウンドジョブ(SM36/SM37)として実行する必要があります。ピーク時間外に実行するようスケジュールしてください。
- 出力ファイルパス: SAPアプリケーションサーバー上のファイルパスとファイル名を指定するPARAMETERです(例:/tmp/ディレクトリ内)。ファイルはダウンロードされる前にここに書き込まれます。
- 前提条件: レポートを実行するユーザーには、FI、CO、MMテーブル(BKPF、BSEG、RBKP、RSEG、LFA1)、変更伝票テーブル(CDHDR、CDPOS)、およびワークフローテーブルからの読み取り権限が必要です。さらに、アプリケーションサーバーにファイルを書き込むためには、権限オブジェクトS_DATASETが必要です。
a クエリ例 abap
`abap
*&---------------------------------------------------------------------*
*& Report Z_PM_AP_INVOICE_EXTRACT
*&---------------------------------------------------------------------*
*& This report extracts Accounts Payable invoice lifecycle events for
*& process mining analysis.
*&---------------------------------------------------------------------*
REPORT z_pm_ap_invoice_extract.
*&---------------------------------------------------------------------*
*& Data Structures
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
invoice TYPE belnr_d,
activityname TYPE string,
eventtime TYPE string,
sourcesystem TYPE logsys,
lastdataupdate TYPE string,
username TYPE uname,
companycode TYPE bukrs,
vendorname TYPE name1_gp,
invoiceamount TYPE wrbtr,
purchaseordernumber TYPE ebeln,
invoiceduedate TYPE d,
END OF ty_event_log.
DATA: gt_event_log TYPE TABLE OF ty_event_log.
DATA: gv_system_id TYPE logsys.
DATA: gv_last_update TYPE string.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_bukrs FOR bkpf-bukrs OBLIGATORY,
s_cpudt FOR bkpf-cpudt OBLIGATORY DEFAULT sy-datum,
s_blart FOR bkpf-blart.
PARAMETERS: p_fpath TYPE string OBLIGATORY DEFAULT '/tmp/ap_extract.csv'.
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
" Get System ID and Update Timestamp
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = gv_system_id
EXCEPTIONS
own_logical_system_not_defined = 1
OTHERS = 2.
CONCATENATE sy-datum sy-uzeit INTO gv_last_update.
" Internal tables for SAP data
DATA: lt_bkpf TYPE TABLE OF bkpf,
lt_rbkp TYPE TABLE OF rbkp.
" Select base documents
SELECT * FROM bkpf INTO TABLE lt_bkpf
WHERE bukrs IN s_bukrs
AND cpudt IN s_cpudt
AND blart IN s_blart
AND ( blart = 'KR' OR blart = 'KG' ). " Example FI Invoice Types
SELECT * FROM rbkp INTO TABLE lt_rbkp
WHERE bukrs IN s_bukrs
AND cpudt IN s_cpudt
AND blart IN s_blart
AND blart = 'RE'. " Example MM Invoice Type
" --- Process each invoice document ---
LOOP AT lt_bkpf ASSIGNING FIELD-SYMBOL(<fs_bkpf>).
PERFORM process_invoice USING <fs_bkpf>.
ENDLOOP.
LOOP AT lt_rbkp ASSIGNING FIELD-SYMBOL(<fs_rbkp>).
PERFORM process_mm_invoice USING <fs_rbkp>.
ENDLOOP.
" Write output to file
PERFORM write_output_file.
*&---------------------------------------------------------------------*
*& Form PROCESS_INVOICE (Handles FI Invoices)
*&---------------------------------------------------------------------*
FORM process_invoice USING iv_bkpf TYPE bkpf.
DATA: ls_bseg TYPE bseg,
ls_lfa1 TYPE lfa1,
ld_due_date TYPE d.
DATA: ls_event TYPE ty_event_log.
" Get Vendor and other details from first line item
SELECT SINGLE * FROM bseg INTO ls_bseg
WHERE bukrs = iv_bkpf-bukrs
AND belnr = iv_bkpf-belnr
AND gjahr = iv_bkpf-gjahr
AND koart = 'K'.
IF sy-subrc = 0.
SELECT SINGLE name1 FROM lfa1 INTO ls_lfa1-name1 WHERE lifnr = ls_bseg-lifnr.
CALL FUNCTION 'DETERMINE_DUE_DATE'
EXPORTING
i_zfbdt = ls_bseg-zfbdt
i_zbd1t = ls_bseg-zbd1t
i_zbd2t = ls_bseg-zbd2t
i_zbd3t = ls_bseg-zbd3t
i_zbd1p = ls_bseg-zbd1p
i_zbd2p = ls_bseg-zbd2p
i_zterm = ls_bseg-zterm
IMPORTING
e_faedt = ld_due_date.
ENDIF.
" Helper function to populate common fields
MACRO set_common_fields.
ls_event-invoice = iv_bkpf-belnr.
ls_event-sourcesystem = gv_system_id.
ls_event-lastdataupdate = gv_last_update.
ls_event-companycode = iv_bkpf-bukrs.
ls_event-vendorname = ls_lfa1-name1.
ls_event-invoiceduedate = ld_due_date.
SELECT SINGLE wrbtr FROM bseg INTO ls_event-invoiceamount WHERE belnr = iv_bkpf-belnr AND gjahr = iv_bkpf-gjahr AND koart = 'K'.
ENDMACRO.
" 1. Invoice Received
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Received'.
CONCATENATE iv_bkpf-cpudt iv_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
" 2. Invoice Parked (if document was created as parked)
IF iv_bkpf-bstat = 'V'.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Parked'.
CONCATENATE iv_bkpf-cpudt iv_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
" 10. Invoice Posted (For non-parked, same as received. For parked, this needs CDHDR/CDPOS logic not shown for brevity)
IF iv_bkpf-bstat <> 'V'.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Posted'.
CONCATENATE iv_bkpf-budat iv_bkpf-cputm INTO ls_event-eventtime. " Using posting date
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
" 5. & 7. Invoice Blocked / Discrepancy Resolved from Change Docs
DATA: lt_cdhdr TYPE TABLE OF cdhdr, lt_cdpos TYPE TABLE OF cdpos.
DATA(ld_objectkey) = |{ iv_bkpf-bukrs }{ iv_bkpf-belnr }{ iv_bkpf-gjahr }|.
SELECT * FROM cdhdr INTO TABLE lt_cdhdr WHERE objectclas = 'BELEG' AND objectid = ld_objectkey.
IF sy-subrc = 0.
SELECT * FROM cdpos INTO TABLE lt_cdpos FOR ALL ENTRIES IN lt_cdhdr
WHERE changenr = lt_cdhdr-changenr AND tabname = 'BSEG' AND fname = 'ZLSPR'.
LOOP AT lt_cdpos ASSIGNING FIELD-SYMBOL(<fs_cdpos>).
READ TABLE lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>) WITH KEY changenr = <fs_cdpos>-changenr.
IF sy-subrc = 0.
CLEAR ls_event.
set_common_fields.
IF <fs_cdpos>-value_new IS NOT INITIAL AND <fs_cdpos>-value_old IS INITIAL.
ls_event-activityname = 'Invoice Blocked For Payment'.
ELSEIF <fs_cdpos>-value_new IS INITIAL AND <fs_cdpos>-value_old IS NOT INITIAL.
ls_event-activityname = 'Discrepancy Resolved'.
ELSE.
CONTINUE.
ENDIF.
CONCATENATE <fs_cdhdr>-udate <fs_cdhdr>-utime INTO ls_event-eventtime.
ls_event-username = <fs_cdhdr>-username.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDIF.
" 6. 8. 9. Workflow Events (Routed, Approved, Rejected) - Simplified Example
" This requires knowledge of specific workflow templates. Placeholder logic:
" SELECT ... FROM SWW_WI2OBJ ... WHERE INSTID = [Invoice Object]
" SELECT ... FROM SWWWIHEAD ... to get status and times
" 11. & 12. & 14. Payment Proposal, Executed, Cleared
IF ls_bseg-augbl IS NOT INITIAL.
DATA: ls_regup TYPE regup.
SELECT SINGLE * FROM regup INTO ls_regup WHERE vblnr = ls_bseg-belnr.
IF sy-subrc = 0.
DATA(ld_rundate) = ls_regup-laufd.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Proposal Created'.
CONCATENATE ld_rundate '000000' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Executed'.
CONCATENATE ls_bseg-augdt '120000' INTO ls_event-eventtime. " Using clearing date as proxy
APPEND ls_event TO gt_event_log.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Cleared'.
CONCATENATE ls_bseg-augdt '120001' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
" 13. Invoice Due Date Passed (Calculated)
IF ls_bseg-augdt IS NOT INITIAL AND ld_due_date IS NOT INITIAL.
IF ls_bseg-augdt > ld_due_date.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Due Date Passed'.
CONCATENATE ld_due_date '235959' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDIF.
" 15. Invoice Cancelled
IF iv_bkpf-stblg IS NOT INITIAL.
DATA: ls_rev_bkpf TYPE bkpf.
SELECT SINGLE * FROM bkpf INTO ls_rev_bkpf WHERE belnr = iv_bkpf-stblg.
IF sy-subrc = 0.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Cancelled'.
CONCATENATE ls_rev_bkpf-cpudt ls_rev_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = ls_rev_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form PROCESS_MM_INVOICE (Handles MM/Logistics Invoices)
*&---------------------------------------------------------------------*
FORM process_mm_invoice USING iv_rbkp TYPE rbkp.
" This form would be similar to PROCESS_INVOICE, but starts with RBKP.
" It needs to find the corresponding FI document in BKPF via AWKEY.
" The logic for PO/GR Matched would be included here.
" For demonstration, creating placeholder events for MM-specific activities.
DATA: ls_event TYPE ty_event_log.
ls_event-invoice = iv_rbkp-belnr.
ls_event-sourcesystem = gv_system_id.
ls_event-lastdataupdate = gv_last_update.
ls_event-companycode = iv_rbkp-bukrs.
" 1. Invoice Received (MM)
ls_event-activityname = 'Invoice Received'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" 3. Purchase Order Matched (Implicit)
ls_event-activityname = 'Purchase Order Matched'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" 4. Goods Receipt Matched (Implicit)
ls_event-activityname = 'Goods Receipt Matched'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" NOTE: The rest of the events (Block, Pay, etc.) would be found by linking
" RBKP to BKPF and then reusing the logic from PROCESS_INVOICE.
" Link: BKPF-AWKEY = CONCATENATE( RBKP-BELNR, RBKP-GJAHR ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form WRITE_OUTPUT_FILE
*&---------------------------------------------------------------------*
FORM write_output_file.
DATA: lv_string TYPE string.
OPEN DATASET p_fpath FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc <> 0.
MESSAGE 'Error opening file.' TYPE 'E'.
RETURN.
ENDIF.
" Write Header
lv_string = 'Invoice,ActivityName,EventTime,SourceSystem,LastDataUpdate,UserName,CompanyCode,VendorName,InvoiceAmount,PurchaseOrderNumber,InvoiceDueDate'.
TRANSFER lv_string TO p_fpath.
" Write Data
LOOP AT gt_event_log ASSIGNING FIELD-SYMBOL(<fs_event>).
" Create a comma-separated string, handling potential commas in data
CONCATENATE <fs_event>-invoice
<fs_event>-activityname
<fs_event>-eventtime
<fs_event>-sourcesystem
<fs_event>-lastdataupdate
<fs_event>-username
<fs_event>-companycode
<fs_event>-vendorname
<fs_event>-invoiceamount
<fs_event>-purchaseordernumber
<fs_event>-invoiceduedate
INTO lv_string SEPARATED BY ','.
TRANSFER lv_string TO p_fpath.
ENDLOOP.
CLOSE DATASET p_fpath.
WRITE: / 'Extraction complete. File written to:', p_fpath.
ENDFORM.
`