お客様の購買から支払いまで - 請求書処理データテンプレート
SAP S/4HANAお客様の購買から支払いまで - 請求書処理データテンプレート
- 収集を推奨する項目
- 追跡すべき主要アクティビティ
- `SAP S/4HANA`向け抽出`ガイド`
購買から支払いまで - 請求書処理の属性
| 名前 | 説明 | ||
|---|---|---|---|
| 請求書番号 InvoiceNumber | ベンダー請求書伝票の一意の識別子であり、プロセスの主要なケース識別子として機能します。 | ||
| 説明 「請求書番号」は、SAP S/4HANA内の各仕入先請求書に割り当てられる一意の識別子です。作成、仮保存、承認、支払いなどのすべての関連アクティビティを単一のまとまったプロセスインスタンスにリンクさせます。 プロセスマイニングにおいて、この属性は各請求書のエンドツーエンドのジャーニーを追跡するための基本です。これにより、受領から最終支払いまでのプロセスフロー全体を再構築でき、個々の請求書レベルでのサイクルタイム、ボトルネック、およびプロセスバリエーションの分析が可能になります。 その重要性 全ての関連イベントを接続するための不可欠なキーであり、システム全体における請求書のライフサイクルの完全な追跡を可能にします。 取得元 これは会計伝票番号であり、テーブルBKPFのフィールドBELNRで見つけることができます。 例 190000000119000000451900000132 | |||
| アクティビティ名 ActivityName | 特定の時点で請求書に対して発生したビジネスアクティビティまたはイベントの名前。 | ||
| 説明 「アクティビティ名」は、請求書処理ライフサイクルにおける特定のステップまたはステータス変更を記述します。例えば、「請求書伝票作成」、「請求書承認依頼」、「支払停止設定」、「支払い実行」などがあります。 この属性は、アクティビティの流れを視覚的に表現するプロセスマップを構築するために非常に重要です。これらのアクティビティ間の順序、頻度、および期間を分析することで、ボトルネック、手戻りループ、およびコンプライアンス違反のプロセスバリエーションを特定するのに役立ちます。これは、あらゆるプロセスマイニング分析の基盤となります。 その重要性 プロセスのステップを定義し、プロセスマップの可視化とプロセスフローおよびバリエーションの分析を可能にします。 取得元 SAPトランザクションコード(SY-TCODE)、変更伝票オブジェクトステータス(CDHDR/CDPOS)、およびステータス変更を示す特定のフィールド値の組み合わせから導出されます。 例 請求書仮登録請求書承認済み支払い実行 | |||
| イベント日時 EventTime | アクティビティが発生した正確な日時。 | ||
| 説明 イベントタイムとは、特定の活動がいつ正確に発生したかを記録するタイムスタンプです。このデータは、プロセスの異なるステップ間の期間、サイクルタイム、待機時間を計算するために不可欠です。 プロセスマイニング分析では、正確なタイムスタンプを使用して、「平均請求書サイクルタイム」や「請求書承認サイクルタイム」のようなパフォーマンスKPIを測定します。活動間の経過時間を分析することで、組織は請求書が遅延しているボトルネックを特定し、プロセスの加速の機会を特定できます。 その重要性 このタイムスタンプは、パフォーマンス監視、ボトルネック特定、SLA追跡を含むすべての時間ベース分析の基盤となります。 取得元 通常、変更伝票テーブルCDHDR(ヘッダー)およびCDPOS(明細)から、フィールドUDATEおよびUTIMEを使用して取得されます。一部のイベントについては、BKPF(CPUDT, CPUTM)などのテーブルの作成日または入力日からの場合もあります。 例 2023-04-15T10:30:00Z2023-04-18T14:05:21Z2023-05-02T09:00:00Z | |||
| ドキュメントタイプ DocumentType | 仕入先請求書やクレジットメモなど、さまざまな種類の会計伝票を分類するコードです。 | ||
| 説明 「伝票タイプ」は、SAPで異なるビジネス取引を区別するために使用されます。例えば、「KR」は通常標準的な仕入先請求書を表し、「KG」は仕入先貸方メモである場合があります。 伝票タイプ別に分析することで、異なる種類の取引がどのように処理されるかを理解するためにプロセスをセグメント化できます。例えば、貸方メモのプロセスは、標準請求書とは大きく異なる場合があります。このセグメンテーションにより、より正確で関連性の高いプロセス洞察が得られます。 その重要性 標準請求書やクレジットメモなど、異なるプロセスパスをたどることが多い様々な種類の財務取引を区別するのに役立ちます。 取得元 伝票ヘッダーテーブルBKPFのフィールドBLARTにあります。 例 KRREKG | |||
| ユーザー名 UserName | アクティビティを実行した人物またはシステムのSAPユーザーID。 | ||
| 説明 この属性は、特定のトランザクションを実行した、または伝票を作成したユーザーを識別します。個人のユーザーIDである場合もあれば、自動バッチジョブのシステムIDである場合もあります。 ユーザー別に分析することで、作業負荷の分散を理解し、トレーニングの必要性を特定し、異常なユーザー行動を発見するのに役立ちます。例えば、どのユーザーが頻繁に例外処理を行っているか、またはどの請求書が自動的に処理されているか(例:「BATCHUSER」)を浮き彫りにすることができ、これは「請求書自動化率」KPIの計算の鍵となります。 その重要性 プロセス活動を特定のユーザーまたはシステムアカウントに帰属させ、ワークロード分析、パフォーマンス比較、および自動化の検出を可能にします。 取得元 BKPF-USNAM(入力者)やCDHDR-USERNAME(変更者)などのフィールドから取得されます。 例 SMITHJMUELLERTWF-BATCH | |||
| 仕入先コード VendorNumber | 請求書を提出したベンダーの一意の識別子。 | ||
| 説明 「ベンダー番号」は、請求書に関連するサプライヤーまたは債権者を識別します。請求書取引をベンダーマスターデータにリンクさせます。 この属性は、「ベンダー支払いパフォーマンス」の評価や、例外や支払停止につながる問題のある請求書を頻繁に提出するベンダーの特定など、ベンダー中心の分析に不可欠です。ベンダー関係を管理し、サプライヤーの信頼性を評価するのに役立ちます。 その重要性 仕入先ごとのプロセスパフォーマンス分析を可能にし、パターンを特定し、関係を管理し、仕入先関連の問題を評価するのに役立ちます。 取得元 通常、会計伝票セグメントテーブルBSEGのフィールドLIFNRで見つけることができます。 例 100345700012V9832 | |||
| 会社コード CompanyCode | 財務諸表が作成される、法的に独立した会社を表す組織単位。 | ||
| 説明 「会社コード」は、SAP財務における基本的な組織単位です。各請求書は特定の会社コードに割り当てられ、取引に対する法的責任を負う法人を決定します。 プロセスマイニングにおいて、会社コードによるフィルタリングや比較は、異なる事業単位、法人、または国を横断したプロセスパフォーマンスの分析に不可欠です。これにより、効率性、コンプライアンス、自動化レベルにおける地域差を特定し、的を絞った改善イニシアチブをサポートします。 その重要性 組織内の異なる法人や地理的な拠点間で請求書処理のパフォーマンスをセグメント化し、比較することができます。 取得元 これは伝票ヘッダーテーブルBKPFの標準フィールドBUKRSです。 例 1000US01DE01 | |||
| 支払ブロック理由 PaymentBlockReason | 請求書が支払保留(ブロック)されている理由を示すコード。 | ||
| 説明 請求書の支払いが停止された場合、この属性は「数量不一致」や「価格不一致」など、停止の具体的な理由を提供します。これらの理由は、SAPで例外処理を標準化するために設定されています。 この属性は、「支払停止発生および期間」ダッシュボードにとって不可欠です。異なる停止理由の頻度を分析することで、特定のベンダー、品目、または内部プロセスに関する問題など、支払い遅延の根本原因を特定し、的を絞った是正措置を可能にします。 その重要性 支払停止の具体的な根本原因を提供し、遅延を減らし、初回正処理率を向上させるための的を絞った分析を可能にします。 取得元 テーブルBSEGの仕入先明細項目のフィールドZLSPR(支払い保留キー)にあります。 例 RIA | |||
| 支払期日 PaymentDueDate | 請求書が延滞になるのを避けるために支払う必要がある期日です。 | ||
| 説明 「支払期日」は、請求書日付と合意された支払条件に基づいて、ベンダーへの支払いが期日となる計算された日付です。これはプロセスにおける重要な期限として機能します。 この属性は、「期日内支払い率」KPIおよび「ベンダー支払いパフォーマンス」ダッシュボードにとって不可欠です。実際の支払い日付と期日を比較することで、企業は支払い義務を履行する能力を測定でき、これはベンダー関係と財務上の評判に影響を与えます。 その重要性 適時支払いパフォーマンスを測定するための主要なベンチマークであり、良好な仕入先関係を維持し、遅延手数料を回避するために重要です。 取得元 この日付は、テーブルBSEGのベンダー明細項目、フィールドZFBDT(期日計算の基準日)に直接利用できることがよくあります。正味期日は、この基準日と支払条件から計算されます。 例 2023-05-302023-06-152023-07-01 | |||
| 請求金額 AmountInCompanyCodeCurrency | 会社コードの現地通貨における請求書の合計総額。 | ||
| 説明 この属性は、請求書の合計金額を表します。請求書処理業務の財務的影響と規模を理解するための重要な指標です。 請求書金額を分析することで、高額請求書を優先的に処理し、支出の傾向を特定し、プロセス問題と財務的価値を関連付けるのに役立ちます。例えば、高額請求書が停止されやすいか、承認時間が長くなる傾向があるかを調査するために使用できます。 その重要性 プロセスに財務的なコンテキストを提供し、高額請求書が異なる方法で処理されているかどうかの特定など、金銭的価値に基づいた分析を可能にします。 取得元 この値は通常、テーブルBSEGの関連する明細項目、フィールドWRBTR(現地通貨での金額)の合計から導出されます。 例 1500.75125000.00850.20 | |||
| 購買発注 PurchasingDocument | 請求書が関連する購買発注番号。 | ||
| 説明 「購買伝票番号」は、仕入先請求書を元の購買発注(PO)にリンクさせます。このリンクは、請求書をPOおよび入庫と照合する三者照合プロセスにとって不可欠です。 この属性で分析することで、POに基づく請求書とPOに基づかない請求書に関連する問題を理解するのに役立ちます。照合の不一致を調査し、プロセスにおける調達部分の効率性を理解するための鍵となります。 その重要性 請求書を調達プロセスにリンクさせ、照合の不一致やPOのコンプライアンスを分析するために不可欠です。 取得元 この情報は通常、伝票セグメントテーブルBSEGのフィールドEBELN(購買伝票番号)で見つけることができます。 例 450000123445000056784500009012 | |||
| `ソースシステムID` SourceSystemId | データが抽出された元のSAP S/4HANAシステムの識別子。 | ||
| 説明 この属性は、例えば「S4H_PROD」や「ERP_EU」といった元となるシステムを指定します。複数のERPインスタンスや、レガシーシステムと最新システムが混在する環境では特に重要です。 分析においては、異なるシステムや地域間のプロセスパフォーマンスを比較できます。データの出所を保証し、複数のソースからのデータが中央のプロセスマイニングプラットフォームで結合される際のデータガバナンスとトラブルシューティングに不可欠です。 その重要性 データの出所に関するコンテキストを提供し、これはデータガバナンスや異なるシステムまたは会社拠点間のプロセス比較にとって不可欠です。 取得元 この値は通常、データ抽出中のSAPシステムID(sy-sysid)から導出されるか、ETLパイプラインで静的な値として構成されます。 例 S4PS4H_PROD_100ECC_EU | |||
| 取消理由 ReversalReason | 請求書伝票が取り消された理由を示すコードです。 | ||
| 説明 請求書が誤って転記された場合、多くは取り消されます。取り消し理由コードは、なぜこのアクションが取られたのかを説明します。例えば、「誤った転記日付」や「データ入力エラー」などです。 取り消し理由を分析することで、請求書転記プロセスにおけるエラーのパターンを特定できます。この洞察は、トレーニングの改善、システム制御の強化、または財務上の手戻りや管理上のオーバーヘッドにつながる繰り返しの問題に対処するために活用できます。 その重要性 請求書が取り消された理由を説明し、転記プロセスにおけるエラーや手戻りの原因を直接的に把握することができます。 取得元 テーブルBKPFの元の伝票ヘッダーのフィールドSTGRD(取り消し理由)にあります。 例 010205 | |||
| 手戻り IsRework | 承認却下や支払い保留解除など、請求書に手戻り活動があった場合に真となるフラグです。 | ||
| 説明 この属性は、1つ以上の手戻りループを経験した請求書にフラグを立てます。手戻りは、「請求書却下」に続く「請求書承認」、または「支払停止設定」後の「支払停止解除」など、特定のアクティビティシーケンスによって識別されます。 この属性は、「請求書手戻り率」KPIの計算を簡素化します。これにより、アナリストは手戻りのあるケースを簡単に分離して調査し、非効率性や繰り返しの手作業の根本原因を理解することができます。 その重要性 作業が繰り返される非効率なプロセスフローを特定し、無駄を定量化し、プロセス例外の根本原因を特定するのに役立ちます。 取得元 イベントログ内の活動のシーケンスに基づいて計算されます。例えば、請求書のトレースで「請求書却下済み」が発生した場合、このフラグは真になります。 例 truefalse | |||
| 承認サイクル回数 ApprovalCycleCount | 請求書が承認のために送信された回数です。 | ||
| 説明 このメトリックは、単一の請求書に対して「請求書承認依頼」アクティビティが発生した回数をカウントします。1より大きいカウントは、請求書が少なくとも一度却下または差し戻され、新たな承認サイクルが必要であることを示します。 この属性は、「初回承認率」KPIを直接サポートします。承認サイクルカウントが高い請求書を分析することで、組織は情報不足や誤ったコーディングなど、承認失敗の理由を特定し、プロセスを改善するための措置を講じることができます。 その重要性 承認サブプロセス内の手戻りを定量化し、初回承認率の測定と承認却下の理由特定に役立ちます。 取得元 一意のInvoiceNumberごとに「請求書承認依頼済み」活動の発生回数を数えることで計算されます。 例 123 | |||
| 抽出タイムスタンプ ExtractionTimestamp | データがソースシステムから抽出された日時。 | ||
| 説明 この属性は、データ抽出イベントのタイムスタンプを記録します。これは、プロセスマイニングツールで分析されるデータの鮮度を反映しています。 分析では、生成された洞察の鮮度を理解するために使用されます。運用監視ダッシュボードにとって、意思決定が最新の情報に基づいていることを確認し、データ更新サイクルを効果的に管理するために不可欠です。 その重要性 データの鮮度を示し、分析とレポートが利用可能な最新の情報に基づいていることを保証します。 取得元 これはSAPフィールドではありません。データ抽出ツールまたはETLプロセスによってデータ取得時に生成および追加されます。 例 2023-10-27T02:00:00Z2023-10-28T02:00:00Z2023-10-29T02:00:00Z | |||
| 支払条件 PaymentTerms | ベンダーと合意された支払条件(期日、割引期間など)を定義するコード。 | ||
| 説明 支払条件は、早期支払いの割引を含む、請求書の支払いに関するルールを定義します。例えば、「Z030」は「30日以内正味支払い」を意味する場合があります。 この属性は、財務計画と運転資金の最適化にとって不可欠です。プロセスマイニングでは、「支払期日」を計算し、早期支払い割引の適用資格を判断するために使用され、「早期支払い割引獲得率」KPIを直接サポートします。 その重要性 支払期日と割引のルールを定義し、適時支払いKPIと運転資金管理に直接影響を与えます。 取得元 テーブルBSEGの仕入先明細項目のフィールドZTERM(支払条件キー)にあります。 例 0001Z030NT60 | |||
| 期日内支払い済みか IsPaidOnTime | 請求書が支払期日以前に支払われた場合に真となるフラグです。 | ||
| 説明 このブール属性は、実際の支払い日付(「支払い実行」アクティビティのタイムスタンプ)を「支払期日」と比較した結果です。各請求書の支払いステータスについて、明確な二者択一の結果を提供します。 これは「期日内支払い率」KPIの主要な計算です。これにより、遅延に関連する一般的なベンダー、会社コード、請求書金額など、遅延支払いの特性を理解するための簡単なフィルタリングと分析が可能になります。 その重要性 支払条件への遵守を直接測定します。これは、仕入先関係管理と財務業務にとって重要なKPIです。 取得元 「支払い実行済み」活動のEventTimeをPaymentDueDate属性と比較して計算されます。(支払日 <= 支払期日)。 例 truefalse | |||
| 消込伝票番号 ClearingDocumentNumber | 請求書を消し込む伝票番号。通常は支払伝票を表します。 | ||
| 説明 「消込伝票番号」は、未処理の請求書明細を消込取引(ほとんどの場合、支払伝票)にリンクさせます。これにより、請求書が支払われたことが確認されます。 この属性は、請求書とその支払いを結びつける決定的なリンクです。「支払い実行」アクティビティとその対応するタイムスタンプを特定するために使用され、エンドツーエンドのサイクルタイムと期日内支払い率を計算するために不可欠です。 その重要性 請求書が支払われたことを確認し、それを特定の支払い取引にリンクします。これは、サイクルタイムと支払いパフォーマンス分析にとって重要です。 取得元 伝票明細テーブルBSEGのフィールドAUGBL(消込伝票番号)にあります。 例 150000000115000000231500000088 | |||
| 自動化 IsAutomated | 活動が自動化されたシステムユーザーによって実行されたかどうかを示すフラグです。 | ||
| 説明 このブール属性は、アクティビティに関連付けられたユーザーが「WF-BATCH」や「SAP_SYSTEM」などの既知のシステムアカウントまたはバッチアカウントである場合に「真」となります。手動プロセスステップと自動化されたプロセスステップを区別するのに役立ちます。 この属性は、「請求書自動化率」KPIの計算に不可欠です。プロセスのどの部分が自動化されているかを分析することで、組織は自動化イニシアチブの成功を測定し、手作業を削減し効率を向上させるさらなる機会を特定できます。 その重要性 手作業による活動とシステム主導の活動を区別し、自動化率を測定し、さらなる自動化の機会を特定するための基礎となります。 取得元 UserName属性から導出されます。特定のユーザーIDを「自動化された」として分類するためのマッピングまたはルールが作成されます。 例 truefalse | |||
| 請求日 InvoiceDate | ベンダーが請求書伝票を発行した日付。 | ||
| 説明 「請求書日付」は、伝票日付とも呼ばれ、ベンダーが請求書に記載する日付です。合意された支払条件に基づいて支払期日を計算するための開始点として使用されます。 分析において、この日付は、請求書の経過日数や早期支払い割引の資格を判断するなど、財務計算の基本となります。「早期支払い割引獲得率」KPIの主要な入力値です。 その重要性 支払条件と期日を計算するための基準となり、運転資金管理と割引獲得に不可欠です。 取得元 伝票ヘッダーテーブルBKPFのフィールドBLDAT(伝票日付)にあります。 例 2023-04-122023-05-152023-06-20 | |||
| 請求書の処理時間 InvoiceProcessingTime | 請求書における最初のアクティビティから最後のアクティビティまでの経過合計時間。 | ||
| 説明 このメトリックは、単一の請求書を処理するための合計期間を計算します。通常、請求書の作成または受領から最終支払いまでです。これは、エンドツーエンドのサイクルタイムのケースレベルの要約を提供します。 この計算された属性は、「平均請求書サイクルタイム」KPIおよび「エンドツーエンド請求書サイクルタイム」ダッシュボードの基礎となります。これにより、最も時間がかかっているケースを迅速に特定し、処理時間の延長に寄与する要因を分析することができます。 その重要性 各請求書のプロセスにおけるエンドツーエンドの効率性を測定し、特に長期間を要し調査が必要なケースを浮き彫りにします。 取得元 一意のInvoiceNumberごとに、最後のイベントのタイムスタンプと最初のイベントのタイムスタンプの差を取ることで計算されます。 例 10日4時間25日と1時間5日8時間 | |||
購買から支払いまで - 請求書処理のアクティビティ
| アクティビティ | 説明 | ||
|---|---|---|---|
| 支払い実行 | これは標準プロセスにおける最終アクティビティであり、支払いが行われ、請求書が消し込まれます。これは、資金がベンダーに支払われたことを意味します。 | ||
| その重要性 これはP2P請求書ライフサイクルの終了を示します。エンドツーエンドの総サイクルタイムを計算し、期日に対する期日内支払いパフォーマンスを測定するために不可欠です。 取得元 このイベントは、ベンダー明細項目の消込伝票情報から捕捉されます。消込日付(BSEG-AUGDT)と消込伝票(BSEG-AUGBL)は、支払いが完了したことを示します。 取得 消し込まれたベンダー明細項目から消込日付(BSEG-AUGDT)を使用します。 イベントタイプ explicit | |||
| 請求書の逆仕訳 | 以前に転記された請求書伝票の取り消しを表す活動です。これは誤った請求書の最終イベントであり、その後、多くの場合、正しく再入力されます。 | ||
| その重要性 取消は、プロセス早期に発見されなかった重大なエラーを示します。その頻度と根本原因を追跡することは、プロセス改善と財務上の不正確さの削減にとって不可欠です。 取得元 取り消し伝票が作成されたときに、取り消しが識別されます。元の伝票ヘッダー(BKPF)には取り消し伝票番号(BKPF-STBLG)が含まれ、その逆も同様です。取り消し伝票の転記日がイベント時刻となります。 取得 BKPF-STBLGフィールドに値がある伝票を識別し、取り消し伝票の転記日を使用します。 イベントタイプ explicit | |||
| 請求書仕訳計上済み | これは、仮保存または承認された請求書が正式に総勘定元帳に記帳される主要な財務イベントです。この行為は、ベンダーへの負債を認識します。 | ||
| その重要性 「記帳」は、データ入力と承認を財務決済フェーズから区別する主要な節目です。請求書作成から記帳までの時間は、内部処理効率の重要な指標となります。 取得元 このイベントは、伝票ヘッダーの記帳日付(BKPF-BUDAT)によって識別されます。最初に仮保存される伝票の場合、記帳済みステータスへの移行がイベントタイムスタンプを提供します。 取得 記帳日付(BKPF-BUDAT)をイベントタイムスタンプとして使用します。 イベントタイプ explicit | |||
| 請求書伝票を作成 | これは、SAPで請求書伝票が作成される最初のイベントです。ユーザーが新しい請求書伝票を保存したときに捕捉でき、これは仮保存または前記帳状態である可能性があります。 | ||
| その重要性 このアクティビティは、請求書処理ライフサイクルの開始を示します。このイベントから他のイベントまでの時間を分析することは、全体的な処理リードタイムを測定するために重要です。 取得元 このイベントは、伝票ヘッダーテーブル(通常はBKPFまたはロジスティクス請求書の場合はRBKP)の作成日付と時刻(CPUDT, CPUTM)から捕捉されます。FB60、MIRO、MIR7などのトランザクションコード(BKPF-TCODE)は作成方法を示します。 取得 請求書伝票には、BKPF-CPUDTとBKPF-CPUTMから作成タイムスタンプを使用します。 イベントタイプ explicit | |||
| 請求書承認済み | このアクティビティは、請求書が指定された権限者によって承認されたことを示します。これは、承認ワークフローが正常に完了したとき、またはリリースインジケーターが設定されたときに捕捉されます。 | ||
| その重要性 これは、支払いのための請求書の停止を解除する重要なマイルストーンです。承認の遅延は一般的なボトルネックであり、このアクティビティを追跡することで、遅い承認者やプロセスステップを特定するのに役立ちます。 取得元 これは、SAPワークフローの最終リリースステップから、または請求書やその購買伝票に関連するテーブルのリリースステータスフィールドへの変更を追跡することで推測できます。 取得 ワークフロー完了イベントまたは伝票のリリースステータスフィールドの変更から推測します。 イベントタイプ inferred | |||
| 支払ブロック解除 | 以前設定された支払停止が解除された問題解決を表します。これにより、請求書は再度支払いの対象となります。 | ||
| その重要性 停止が設定されてから解除されるまでの時間は、プロセス例外の解決時間を示します。この期間を短縮することは、効率とベンダー関係の改善の鍵となります。 取得元 このイベントは、支払停止キーフィールド(BSEG-ZLSPR)がクリアされたときに捕捉されます。この変更はCDHDRおよびCDPOSテーブルにログ記録され、解除のタイムスタンプを提供します。 取得 変更伝票(CDHDR/CDPOS)を介してBSEG-ZLSPRフィールドがクリアされる時期を特定します。 イベントタイプ explicit | |||
| 支払ブロック設定 | 請求書が支払われるのを防ぐために意図的に保留が設定される活動です。これは多くの場合、価格や数量の不一致、または未処理のクレジットメモが原因です。 | ||
| その重要性 支払停止は、遅延支払いおよびベンダーとの紛争の主要な原因です。停止の頻度、期間、および理由を分析することは、期日内支払い率を向上させる上で不可欠です。 取得元 このイベントは、請求書明細の支払停止キーフィールド(BSEG-ZLSPR)への変更を追跡することで捕捉されます。CDHDRおよびCDPOSの変更ログは、停止が設定されたときのタイムスタンプとユーザーを提供します。 取得 変更伝票(CDHDR/CDPOS)を介してBSEG-ZLSPRフィールドが入力される時期を特定します。 イベントタイプ explicit | |||
| 支払提案作成 | 請求書が選択され、支払い実行の一部として支払い提案に含まれます。これは自動支払いプロセスの最初のステップです。 | ||
| その重要性 このアクティビティは支払いの意図を示します。このステップから最終支払い実行までの遅延は、支払い実行プロセス、承認、または銀行通信に関する問題を明らかにする可能性があります。 取得元 これは支払い実行テーブル、特に支払い提案に含まれる明細を含むREGUPで見つけることができます。対応するREGUHテーブルの実行日がタイムスタンプを提供します。 取得 支払い提案実行から請求書がREGUPテーブルに表示される時期を特定します。 イベントタイプ explicit | |||
| 請求書データが更新されました | このアクティビティは、請求書伝票が最初に作成された後に加えられた変更を反映しています。これは、却下後の手戻りサイクル中やエラー訂正の際によく発生します。 | ||
| その重要性 頻繁な更新は、手戻りや入力時点での潜在的なデータ品質問題を示唆します。これらの変更を追跡することで、修正に費やされた労力を定量化し、一般的なエラーを特定するのに役立ちます。 取得元 キーフィールドへの変更は、SAPの変更伝票テーブルCDHDR(ヘッダー)とCDPOS(明細)にログとして記録されます。関連する請求書オブジェクトへの変更をフィルタリングすることでイベントを生成できます。 取得 請求書オブジェクトのCDHDRおよびCDPOSテーブルから変更イベントを抽出します。 イベントタイプ explicit | |||
| 請求書仮登録 | システムに入力されたものの、まだ総勘定元帳に記帳されていない請求書を表します。仮保存は、未完了の請求書を保存したり、記帳前のレビューのために使用されます。 | ||
| その重要性 「仮保存」は、プロセスの一時的な中断を示します。仮保存された請求書の期間と頻度を追跡することで、正式な記帳および承認サイクルが開始される前の遅延原因を特定するのに役立ちます。 取得元 これは、仮保存トランザクション(例:MIR7、FV60)を介して作成された伝票、またはBKPFテーブルの特定のステータスフィールドやVBKPFのような専用の仮保存伝票テーブルを確認することで識別できます。 取得 仮保存取引によって作成された伝票を識別するか、仮保存伝票ステータスを確認します。 イベントタイプ explicit | |||
| 請求書却下 | 承認プロセス中の請求書の却下を表します。このイベントは手戻りを引き起こし、修正と再提出が必要になります。 | ||
| その重要性 請求書の却下は、プロセスの非効率性やデータ品質問題の重要な指標です。却下の頻度と理由を分析することで、改善やトレーニングの機会を特定するのに役立ちます。 取得元 これは、SAPワークフロー内の特定のステータス更新(「却下」ステータスなど)から、または現在の承認ワークフローをキャンセルして処理者に戻すイベントから推測されます。 取得 却下を示すワークフローステータスの変更から推測します。 イベントタイプ inferred | |||
| 請求書承認依頼済 | このアクティビティは、請求書に対する正式な承認ワークフローの開始を示します。これは、請求書のステータスが「承認待ち」に変更されたり、ワークフローアイテムが生成されたりしたときに推測されることがよくあります。 | ||
| その重要性 これは承認サイクルタイムを測定するための開始点です。承認がいつ開始されるかを理解することは、承認ワークフロー自体のボトルネックを特定するために不可欠です。 取得元 これは通常、請求書オブジェクト(例:BUS2081)にリンクされたSAPビジネスワークフロー(SWW_WI2OBJテーブル)の開始から、または伝票ヘッダーのカスタムステータスフィールドの変更から推測されます。 取得 請求書伝票に関連するワークフローアイテムの作成から推測します。 イベントタイプ inferred | |||
| 遅延支払い実行済 | これは、請求書の支払いが計算された期日後に実行されたときに発生する計算イベントです。2つの日付フィールドを比較することによって導出されます。 | ||
| その重要性 このアクティビティは、期日内支払いKPIを直接サポートし、頻繁に遅延支払いが発生するベンダーや事業単位を特定するのに役立ちます。これは、ベンダー関係を損ない、ペナルティにつながる可能性があります。 取得元 これは、消込日付(BSEG-AUGDT)を正味期日と比較することによって計算されます。期日自体は、基準日(BSEG-ZFBDT)と支払条件(BSEG-ZTERM)から計算されます。 取得 BSEG-AUGDT > (BSEG-ZFBDT + 支払条件日数) を比較して導出します。 イベントタイプ calculated | |||
抽出ガイド
ステップ
- 前提条件と権限: 抽出を実行するユーザーが、SAP S/4HANAで必要なコアデータサービス(CDS)ビューにアクセスするための適切な権限を持っていることを確認してください。主要なビューには、
I_InvoiceDocument、I_OperationalAcctgDocItem、I_ChangeDocument、I_ChangeDocumentItem、I_PaymentProposalItemが含まれます。また、ユーザーは、ODataサービスや直接SQL接続など、選択したインターフェースを介してクエリを実行する権限も必要です。 - 接続方法の特定: SAP S/4HANAシステムに接続してSQLクエリを実行する方法を決定します。一般的な方法には、SAP Data Services、SAP Data Intelligence、SAPコネクタを持つサードパーティ製ETLツール、または組織のセキュリティポリシーで許可されている場合はSAP HANAデータベースへの直接SQL接続などがあります。
- 抽出パラメーターの定義: クエリを実行する前に、主要なパラメーターを定義します。抽出の日付範囲を、例えば
CreationDateが'YYYY-MM-DD'から'YYYY-MM-DD'の間にあるように指定します。また、データ抽出の範囲を制限するために含めたい特定のCompanyCode値を特定します。 - SQLクエリのカスタマイズ: 提供されたSQLクエリを選択したSQLクライアントまたはデータ抽出ツールにコピーします。
'{StartDate}'、'{EndDate}'、('{CompanyCode1}', '{CompanyCode2}')などのプレースホルダーを注意深く確認してください。これらのプレースホルダーを前のステップで定義した実際の値に置き換えます。また、特定のSAP構成に基づいてワークフローステータスのフィールド名を調整する必要がある場合があります。 - クエリの実行: SAP S/4HANAデータベースに対して、または適切なサービス層を介して、完全なSQLクエリを実行します。このクエリは包括的であるように設計されており、データ量と選択した日付範囲によっては実行にかなりの時間がかかる場合があります。潜在的なエラーやタイムアウトがないか実行状況を監視してください。
- 初期結果の確認: クエリが完了したら、出力の簡単なレビューを実行します。
InvoiceNumber、ActivityName、EventTimeの各列にデータが入力されていることを確認します。ActivityName列に、「請求書伝票作成済み」だけでなく、さまざまな活動が表示されていることを確認します。 - データ変換への対応: クエリはクリーンなイベントログ形式を生成するように構築されています。しかし、
EventTime列がYYYY-MM-DDTHH:MM:SSのような一貫したタイムスタンプ形式であることを確認してください。提供されたクエリは、必要に応じて日付と時刻のフィールドを単一のタイムスタンプに結合しています。 - データのエクスポート: ツールから最終的な結果セットをCSV(カンマ区切り値)ファイルにエクスポートします。この形式は、ProcessMindを含むプロセスマイニングツールと普遍的に互換性があります。
- アップロードの準備: アップロードする前に、文字化けを防ぐためにCSVファイルがUTF-8エンコーディングを使用していることを確認します。ファイル内の列ヘッダーが、
InvoiceNumber、ActivityName、EventTime、UserName、CompanyCodeなどの必要な属性と完全に一致していることを確認します。 - ProcessMindへのアップロード: 準備したCSVファイルをプロセスマイニングプロジェクトにアップロードします。ファイルからの列を、ツールのデータモデル構成内の対応するケースID、活動名、およびタイムスタンプフィールドにマッピングします。
設定
- 使用されるCDSビュー: 主要なデータソースは標準SAP CDSビューです。主なビューは、ヘッダーデータ用の
I_InvoiceDocument、財務転記と消込詳細用のI_OperationalAcctgDocItem、支払い保留やワークフローステータスなど請求書属性の履歴変更を追跡するためのI_ChangeDocumentとI_ChangeDocumentItemです。 - 日付範囲によるフィルタリング: パフォーマンスを管理するために、特定の期間でデータをフィルタリングすることが非常に重要です。提供されているクエリでは、
I_InvoiceDocumentビューのCreationDateにプレースホルダーが使用されています。推奨される開始点は3~6ヶ月分のデータです。 - 会社コードによるフィルタリング: 抽出が適切で管理しやすいことを確実にするため、常に1つ以上の
CompanyCodeでフィルタリングしてください。この目的のために、クエリにはWHERE inv.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')というプレースホルダーが含まれています。 - 伝票タイプによるフィルタリング:
InvoiceDocumentTypeでフィルタリングすることで、抽出をさらに絞り込むことができます。例えば、標準の仕入先請求書(RE)を含め、クレジットメモを除外したい場合があります。これは初期CTEのWHERE句に追加できます。 - 前提条件: クエリを実行するユーザーは、指定された会社コード内の財務および購買伝票に対する適切な表示権限が必要です。SQLクライアントを介した基盤となるHANAデータベースへのアクセスは標準ではなく、特別な権限が必要です。
- パフォーマンスに関する考慮事項: 変更伝票テーブル(
I_ChangeDocument、I_ChangeDocumentItem)からのデータ抽出は、パフォーマンスに負荷がかかる可能性があります。実行時間の長期化を防ぐためには、日付、会社コード、およびオブジェクトクラス(INCOMINGINVOICE)に厳密なフィルターを適用することが不可欠です。
a クエリ例 sql
WITH InvoiceBase AS (
SELECT
inv.InvoiceDocument,
inv.FiscalYear,
inv.CompanyCode,
inv.Supplier AS VendorNumber,
inv.DocumentType,
inv.GrossInvoiceAmountInCoCoCrcy AS AmountInCompanyCodeCurrency,
inv.NetDueDate AS PaymentDueDate,
inv.PurchasingDocument,
inv.CreationDateTime,
inv.CreatedByUser,
accdoc.AccountingDocument,
accdoc.ClearingDate,
accdoc.ClearingJournalEntry,
accdoc.PaymentBlockReason,
accdoc.IsReversed
FROM I_InvoiceDocument AS inv
LEFT JOIN I_OperationalAcctgDocItem AS accdoc
ON inv.AccountingDocument = accdoc.AccountingDocument
AND inv.FiscalYear = accdoc.FiscalYear
AND inv.CompanyCode = accdoc.CompanyCode
WHERE
inv.CreationDate BETWEEN '{StartDate}' AND '{EndDate}'
AND inv.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')
)
-- 1. Invoice Document Created
SELECT
InvoiceDocument AS "InvoiceNumber",
'Invoice Document Created' AS "ActivityName",
CreationDateTime AS "EventTime",
CreatedByUser AS "UserName",
CompanyCode AS "CompanyCode",
VendorNumber AS "VendorNumber",
AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
PaymentDueDate AS "PaymentDueDate",
DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase
UNION ALL
-- 2. Invoice Parked
SELECT
i.InvoiceDocument AS "InvoiceNumber",
'Invoice Parked' AS "ActivityName",
i.CreationDateTime AS "EventTime",
i.CreatedByUser AS "UserName",
i.CompanyCode AS "CompanyCode",
i.Supplier AS "VendorNumber",
i.GrossInvoiceAmountInCoCoCrcy AS "AmountInCompanyCodeCurrency",
i.NetDueDate AS "PaymentDueDate",
i.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
i.PurchasingDocument AS "PurchasingDocument"
FROM I_InvoiceDocument AS i
WHERE
i.InvoiceDocumentIsParked = 'X'
AND i.CreationDate BETWEEN '{StartDate}' AND '{EndDate}'
AND i.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')
UNION ALL
-- 3, 4, 5. Workflow activities (Sent for Approval, Approved, Rejected) from Change Docs
SELECT
cdpos.ObjectValue AS "InvoiceNumber",
CASE
WHEN cdpos.ValueNew = '[StatusSentForApproval]' THEN 'Invoice Sent For Approval'
WHEN cdpos.ValueNew = '[StatusApproved]' THEN 'Invoice Approved'
WHEN cdpos.ValueNew = '[StatusRejected]' THEN 'Invoice Rejected'
END AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.InvoiceDocument
WHERE
cdhdr.ObjectClassName = 'INCOMINGINVOICE'
AND cdpos.FieldName = '[WorkflowStatusFieldName]'
AND cdpos.ValueNew IN ('[StatusSentForApproval]', '[StatusApproved]', '[StatusRejected]')
UNION ALL
-- 6. Invoice Data Updated
SELECT
cdpos.ObjectValue AS "InvoiceNumber",
'Invoice Data Updated' AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.InvoiceDocument
WHERE
cdhdr.ObjectClassName = 'INCOMINGINVOICE'
AND cdpos.FieldName IN ('GrossInvoiceAmount', 'DocumentDate', 'PaymentTerms')
AND cdhdr.ChangeDate BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
-- 7 & 8. Payment Block Set/Removed
SELECT
inv.InvoiceDocument AS "InvoiceNumber",
CASE
WHEN cdpos.ValueNew <> '' AND cdpos.ValueOld = '' THEN 'Payment Block Set'
WHEN cdpos.ValueNew = '' AND cdpos.ValueOld <> '' THEN 'Payment Block Removed'
END AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
cdpos.ValueNew AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.AccountingDocument
WHERE
cdhdr.ObjectClassName = 'BELEG'
AND cdpos.TableName = 'BSEG'
AND cdpos.FieldName = 'ZLSPR'
AND ( (cdpos.ValueNew <> '' AND cdpos.ValueOld = '') OR (cdpos.ValueNew = '' AND cdpos.ValueOld <> '') )
UNION ALL
-- 9. Invoice Posted
SELECT
inv.InvoiceDocument AS "InvoiceNumber",
'Invoice Posted' AS "ActivityName",
CAST(accdoc.PostingDate AS TIMESTAMP) AS "EventTime",
accdoc.CreatedByUser AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
accdoc.PaymentBlockReason AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase AS inv
JOIN I_OperationalAcctgDocItem AS accdoc ON inv.AccountingDocument = accdoc.AccountingDocument
WHERE inv.AccountingDocument IS NOT NULL AND inv.IsReversed = FALSE
UNION ALL
-- 10. Payment Proposal Created
SELECT
item.InvoiceReference AS "InvoiceNumber",
'Payment Proposal Created' AS "ActivityName",
CAST(prun.PaymentRunDate AS TIMESTAMP) AS "EventTime",
prun.CreatedByUser AS "UserName",
item.CompanyCode AS "CompanyCode",
item.Supplier AS "VendorNumber",
item.AmountInTransactionCurrency AS "AmountInCompanyCodeCurrency",
item.NetDueDate AS "PaymentDueDate",
item.AccountingDocumentType AS "DocumentType",
item.PaymentBlockReason AS "PaymentBlockReason",
item.PurchasingDocument AS "PurchasingDocument"
FROM I_PaymentProposalItem as item
JOIN I_PaymentRun as prun ON item.PaymentRunName = prun.PaymentRunName
JOIN InvoiceBase AS inv ON item.InvoiceReference = inv.InvoiceDocument
UNION ALL
-- 11 & 12. Payment Executed / Late Payment Executed
SELECT
InvoiceDocument AS "InvoiceNumber",
CASE
WHEN ClearingDate > PaymentDueDate THEN 'Late Payment Executed'
ELSE 'Payment Executed'
END AS "ActivityName",
CAST(ClearingDate AS TIMESTAMP) AS "EventTime",
CAST(NULL AS VARCHAR(12)) AS "UserName", -- User for clearing is not always straightforward
CompanyCode AS "CompanyCode",
VendorNumber AS "VendorNumber",
AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
PaymentDueDate AS "PaymentDueDate",
DocumentType AS "DocumentType",
'' AS "PaymentBlockReason",
PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase
WHERE ClearingDate IS NOT NULL AND IsReversed = FALSE
UNION ALL
-- 13. Invoice Reversed
SELECT
rev.OriginalInvoiceDocument AS "InvoiceNumber",
'Invoice Reversed' AS "ActivityName",
rev.CreationDateTime AS "EventTime",
rev.CreatedByUser AS "UserName",
rev.CompanyCode AS "CompanyCode",
rev.Supplier AS "VendorNumber",
rev.GrossInvoiceAmountInCoCoCrcy AS "AmountInCompanyCodeCurrency",
CAST(NULL AS DATE) AS "PaymentDueDate",
rev.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
rev.PurchasingDocument AS "PurchasingDocument"
FROM I_InvoiceDocument AS rev
WHERE rev.OriginalInvoiceDocument IN (SELECT InvoiceDocument FROM InvoiceBase) AND rev.IsReversal = 'X' ステップ
- 前提条件と権限: 抽出を実行するユーザーが、SAP S/4HANAで必要なコアデータサービス(CDS)ビューにアクセスするための適切な権限を持っていることを確認してください。主要なビューには、
I_InvoiceDocument、I_OperationalAcctgDocItem、I_ChangeDocument、I_ChangeDocumentItem、I_PaymentProposalItemが含まれます。また、ユーザーは、ODataサービスや直接SQL接続など、選択したインターフェースを介してクエリを実行する権限も必要です。 - 接続方法の特定: SAP S/4HANAシステムに接続してSQLクエリを実行する方法を決定します。一般的な方法には、SAP Data Services、SAP Data Intelligence、SAPコネクタを持つサードパーティ製ETLツール、または組織のセキュリティポリシーで許可されている場合はSAP HANAデータベースへの直接SQL接続などがあります。
- 抽出パラメーターの定義: クエリを実行する前に、主要なパラメーターを定義します。抽出の日付範囲を、例えば
CreationDateが'YYYY-MM-DD'から'YYYY-MM-DD'の間にあるように指定します。また、データ抽出の範囲を制限するために含めたい特定のCompanyCode値を特定します。 - SQLクエリのカスタマイズ: 提供されたSQLクエリを選択したSQLクライアントまたはデータ抽出ツールにコピーします。
'{StartDate}'、'{EndDate}'、('{CompanyCode1}', '{CompanyCode2}')などのプレースホルダーを注意深く確認してください。これらのプレースホルダーを前のステップで定義した実際の値に置き換えます。また、特定のSAP構成に基づいてワークフローステータスのフィールド名を調整する必要がある場合があります。 - クエリの実行: SAP S/4HANAデータベースに対して、または適切なサービス層を介して、完全なSQLクエリを実行します。このクエリは包括的であるように設計されており、データ量と選択した日付範囲によっては実行にかなりの時間がかかる場合があります。潜在的なエラーやタイムアウトがないか実行状況を監視してください。
- 初期結果の確認: クエリが完了したら、出力の簡単なレビューを実行します。
InvoiceNumber、ActivityName、EventTimeの各列にデータが入力されていることを確認します。ActivityName列に、「請求書伝票作成済み」だけでなく、さまざまな活動が表示されていることを確認します。 - データ変換への対応: クエリはクリーンなイベントログ形式を生成するように構築されています。しかし、
EventTime列がYYYY-MM-DDTHH:MM:SSのような一貫したタイムスタンプ形式であることを確認してください。提供されたクエリは、必要に応じて日付と時刻のフィールドを単一のタイムスタンプに結合しています。 - データのエクスポート: ツールから最終的な結果セットをCSV(カンマ区切り値)ファイルにエクスポートします。この形式は、ProcessMindを含むプロセスマイニングツールと普遍的に互換性があります。
- アップロードの準備: アップロードする前に、文字化けを防ぐためにCSVファイルがUTF-8エンコーディングを使用していることを確認します。ファイル内の列ヘッダーが、
InvoiceNumber、ActivityName、EventTime、UserName、CompanyCodeなどの必要な属性と完全に一致していることを確認します。 - ProcessMindへのアップロード: 準備したCSVファイルをプロセスマイニングプロジェクトにアップロードします。ファイルからの列を、ツールのデータモデル構成内の対応するケースID、活動名、およびタイムスタンプフィールドにマッピングします。
設定
- 使用されるCDSビュー: 主要なデータソースは標準SAP CDSビューです。主なビューは、ヘッダーデータ用の
I_InvoiceDocument、財務転記と消込詳細用のI_OperationalAcctgDocItem、支払い保留やワークフローステータスなど請求書属性の履歴変更を追跡するためのI_ChangeDocumentとI_ChangeDocumentItemです。 - 日付範囲によるフィルタリング: パフォーマンスを管理するために、特定の期間でデータをフィルタリングすることが非常に重要です。提供されているクエリでは、
I_InvoiceDocumentビューのCreationDateにプレースホルダーが使用されています。推奨される開始点は3~6ヶ月分のデータです。 - 会社コードによるフィルタリング: 抽出が適切で管理しやすいことを確実にするため、常に1つ以上の
CompanyCodeでフィルタリングしてください。この目的のために、クエリにはWHERE inv.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')というプレースホルダーが含まれています。 - 伝票タイプによるフィルタリング:
InvoiceDocumentTypeでフィルタリングすることで、抽出をさらに絞り込むことができます。例えば、標準の仕入先請求書(RE)を含め、クレジットメモを除外したい場合があります。これは初期CTEのWHERE句に追加できます。 - 前提条件: クエリを実行するユーザーは、指定された会社コード内の財務および購買伝票に対する適切な表示権限が必要です。SQLクライアントを介した基盤となるHANAデータベースへのアクセスは標準ではなく、特別な権限が必要です。
- パフォーマンスに関する考慮事項: 変更伝票テーブル(
I_ChangeDocument、I_ChangeDocumentItem)からのデータ抽出は、パフォーマンスに負荷がかかる可能性があります。実行時間の長期化を防ぐためには、日付、会社コード、およびオブジェクトクラス(INCOMINGINVOICE)に厳密なフィルターを適用することが不可欠です。
a クエリ例 sql
WITH InvoiceBase AS (
SELECT
inv.InvoiceDocument,
inv.FiscalYear,
inv.CompanyCode,
inv.Supplier AS VendorNumber,
inv.DocumentType,
inv.GrossInvoiceAmountInCoCoCrcy AS AmountInCompanyCodeCurrency,
inv.NetDueDate AS PaymentDueDate,
inv.PurchasingDocument,
inv.CreationDateTime,
inv.CreatedByUser,
accdoc.AccountingDocument,
accdoc.ClearingDate,
accdoc.ClearingJournalEntry,
accdoc.PaymentBlockReason,
accdoc.IsReversed
FROM I_InvoiceDocument AS inv
LEFT JOIN I_OperationalAcctgDocItem AS accdoc
ON inv.AccountingDocument = accdoc.AccountingDocument
AND inv.FiscalYear = accdoc.FiscalYear
AND inv.CompanyCode = accdoc.CompanyCode
WHERE
inv.CreationDate BETWEEN '{StartDate}' AND '{EndDate}'
AND inv.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')
)
-- 1. Invoice Document Created
SELECT
InvoiceDocument AS "InvoiceNumber",
'Invoice Document Created' AS "ActivityName",
CreationDateTime AS "EventTime",
CreatedByUser AS "UserName",
CompanyCode AS "CompanyCode",
VendorNumber AS "VendorNumber",
AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
PaymentDueDate AS "PaymentDueDate",
DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase
UNION ALL
-- 2. Invoice Parked
SELECT
i.InvoiceDocument AS "InvoiceNumber",
'Invoice Parked' AS "ActivityName",
i.CreationDateTime AS "EventTime",
i.CreatedByUser AS "UserName",
i.CompanyCode AS "CompanyCode",
i.Supplier AS "VendorNumber",
i.GrossInvoiceAmountInCoCoCrcy AS "AmountInCompanyCodeCurrency",
i.NetDueDate AS "PaymentDueDate",
i.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
i.PurchasingDocument AS "PurchasingDocument"
FROM I_InvoiceDocument AS i
WHERE
i.InvoiceDocumentIsParked = 'X'
AND i.CreationDate BETWEEN '{StartDate}' AND '{EndDate}'
AND i.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')
UNION ALL
-- 3, 4, 5. Workflow activities (Sent for Approval, Approved, Rejected) from Change Docs
SELECT
cdpos.ObjectValue AS "InvoiceNumber",
CASE
WHEN cdpos.ValueNew = '[StatusSentForApproval]' THEN 'Invoice Sent For Approval'
WHEN cdpos.ValueNew = '[StatusApproved]' THEN 'Invoice Approved'
WHEN cdpos.ValueNew = '[StatusRejected]' THEN 'Invoice Rejected'
END AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.InvoiceDocument
WHERE
cdhdr.ObjectClassName = 'INCOMINGINVOICE'
AND cdpos.FieldName = '[WorkflowStatusFieldName]'
AND cdpos.ValueNew IN ('[StatusSentForApproval]', '[StatusApproved]', '[StatusRejected]')
UNION ALL
-- 6. Invoice Data Updated
SELECT
cdpos.ObjectValue AS "InvoiceNumber",
'Invoice Data Updated' AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.InvoiceDocument
WHERE
cdhdr.ObjectClassName = 'INCOMINGINVOICE'
AND cdpos.FieldName IN ('GrossInvoiceAmount', 'DocumentDate', 'PaymentTerms')
AND cdhdr.ChangeDate BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
-- 7 & 8. Payment Block Set/Removed
SELECT
inv.InvoiceDocument AS "InvoiceNumber",
CASE
WHEN cdpos.ValueNew <> '' AND cdpos.ValueOld = '' THEN 'Payment Block Set'
WHEN cdpos.ValueNew = '' AND cdpos.ValueOld <> '' THEN 'Payment Block Removed'
END AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
cdpos.ValueNew AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.AccountingDocument
WHERE
cdhdr.ObjectClassName = 'BELEG'
AND cdpos.TableName = 'BSEG'
AND cdpos.FieldName = 'ZLSPR'
AND ( (cdpos.ValueNew <> '' AND cdpos.ValueOld = '') OR (cdpos.ValueNew = '' AND cdpos.ValueOld <> '') )
UNION ALL
-- 9. Invoice Posted
SELECT
inv.InvoiceDocument AS "InvoiceNumber",
'Invoice Posted' AS "ActivityName",
CAST(accdoc.PostingDate AS TIMESTAMP) AS "EventTime",
accdoc.CreatedByUser AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
accdoc.PaymentBlockReason AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase AS inv
JOIN I_OperationalAcctgDocItem AS accdoc ON inv.AccountingDocument = accdoc.AccountingDocument
WHERE inv.AccountingDocument IS NOT NULL AND inv.IsReversed = FALSE
UNION ALL
-- 10. Payment Proposal Created
SELECT
item.InvoiceReference AS "InvoiceNumber",
'Payment Proposal Created' AS "ActivityName",
CAST(prun.PaymentRunDate AS TIMESTAMP) AS "EventTime",
prun.CreatedByUser AS "UserName",
item.CompanyCode AS "CompanyCode",
item.Supplier AS "VendorNumber",
item.AmountInTransactionCurrency AS "AmountInCompanyCodeCurrency",
item.NetDueDate AS "PaymentDueDate",
item.AccountingDocumentType AS "DocumentType",
item.PaymentBlockReason AS "PaymentBlockReason",
item.PurchasingDocument AS "PurchasingDocument"
FROM I_PaymentProposalItem as item
JOIN I_PaymentRun as prun ON item.PaymentRunName = prun.PaymentRunName
JOIN InvoiceBase AS inv ON item.InvoiceReference = inv.InvoiceDocument
UNION ALL
-- 11 & 12. Payment Executed / Late Payment Executed
SELECT
InvoiceDocument AS "InvoiceNumber",
CASE
WHEN ClearingDate > PaymentDueDate THEN 'Late Payment Executed'
ELSE 'Payment Executed'
END AS "ActivityName",
CAST(ClearingDate AS TIMESTAMP) AS "EventTime",
CAST(NULL AS VARCHAR(12)) AS "UserName", -- User for clearing is not always straightforward
CompanyCode AS "CompanyCode",
VendorNumber AS "VendorNumber",
AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
PaymentDueDate AS "PaymentDueDate",
DocumentType AS "DocumentType",
'' AS "PaymentBlockReason",
PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase
WHERE ClearingDate IS NOT NULL AND IsReversed = FALSE
UNION ALL
-- 13. Invoice Reversed
SELECT
rev.OriginalInvoiceDocument AS "InvoiceNumber",
'Invoice Reversed' AS "ActivityName",
rev.CreationDateTime AS "EventTime",
rev.CreatedByUser AS "UserName",
rev.CompanyCode AS "CompanyCode",
rev.Supplier AS "VendorNumber",
rev.GrossInvoiceAmountInCoCoCrcy AS "AmountInCompanyCodeCurrency",
CAST(NULL AS DATE) AS "PaymentDueDate",
rev.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
rev.PurchasingDocument AS "PurchasingDocument"
FROM I_InvoiceDocument AS rev
WHERE rev.OriginalInvoiceDocument IN (SELECT InvoiceDocument FROM InvoiceBase) AND rev.IsReversal = 'X' ステップ
- ABAPエディターへのアクセス: SAP S/4HANAシステムにログインします。トランザクション
SE38(ABAPエディター)を開きます。 - プログラムの作成: プログラムフィールドに新しいプログラム名(例:
Z_PM_INVOICE_EXTRACT)を入力し、「作成」ボタンをクリックします。タイトルを提供し、タイプを「実行可能プログラム」に設定し、適切なパッケージに保存します。 - プログラム構造と選択画面の定義: エディターで、最終的なイベントログ出力のデータ構造を定義します。次に、請求書入力日、会社コード、伝票タイプなどのパラメーターをユーザーが入力できるようにする選択画面を作成します。これにより、プログラムの再利用性と柔軟性が向上します。
- データ選択ロジックの実装: さまざまなSAPテーブルからデータを取得するための主要なABAP SQLステートメントを記述します。プログラムは、要求された13の活動それぞれについて順次クエリを実行します。
- ヘッダーおよび明細データの抽出: 「請求書伝票作成済み」や「請求書転記済み」などの基本的なイベントについては、
RBKP(ロジスティクス請求書ヘッダー)やBKPF(会計伝票ヘッダー)などの主要テーブルからデータを取得します。 - 変更伝票データの抽出: 「支払い保留設定」や「支払い保留解除」などの活動については、変更伝票テーブル
CDHDR(変更伝票ヘッダー)およびCDPOS(変更伝票明細)をクエリします。例えば、テーブルBSEGのZLSPRなど、特定のフィールドへの変更を識別する必要があります。 - 支払いデータの抽出: 支払い関連の活動を捕捉するには、支払い提案については
REGUP(支払いプログラムからの処理済み明細)のようなテーブルを、実行済み支払いについてはBSAK(消込済仕入先明細)のようなテーブルをクエリします。消込日(AUGDT)と純期日(ZFBDT)を比較することで、「遅延支払い実行済み」を区別します。 - ワークフローデータの抽出: 承認活動については、
SWW_WI2OBJのようなSAPビジネスワークフローテーブルをクエリして、ワークフローアイテムを請求書オブジェクトにリンクします。この部分は、特定のワークフロー設定に大きく依存するため、大幅な調整が必要となる場合があります。 - データをイベントログ形式に統合: 選択された各活動について、データを共通の内部テーブル構造にフォーマットします。このテーブルの各行は単一のイベントを表し、ケース識別子(
InvoiceNumber)、ActivityName、EventTime、およびその他の推奨属性を含める必要があります。 - 出力ファイルの生成: ABAPステートメント
OPEN DATASET、TRANSFER、CLOSE DATASETを使用して、最終的な内部テーブルの内容をSAPアプリケーションサーバー上のフラットファイルに書き込みます。カンマ区切り値(CSV)形式が推奨されます。 - スケジュールと実行: テストのためにフォアグラウンドでプログラムを実行します(
F8を使用)。本番稼働の場合、システムパフォーマンスへの影響を避けるため、トランザクションSM36を使用してオフピーク時にバックグラウンドジョブとしてスケジュールします。 - 取得とアップロード: トランザクション
AL11を使用して、ファイルが保存されたアプリケーションサーバーディレクトリに移動します。ファイルをローカルシステムにダウンロードします。プロセスマイニングツールにアップロードする前に、ファイルがUTF-8エンコードされ、正しくフォーマットされていることを確認してください。
設定
- 日付範囲: 請求書入力日(
RBKP-CPUDT)または転記日(BKPF-BUDAT)に基づいて、抽出する特定の日付範囲を定義します。初期分析では、管理可能なデータ量を確保するために3~6ヶ月の期間を推奨します。 - 会社コード(BUKRS): 1つ以上の会社コードでフィルタリングすることが重要です。大規模な組織で全ての会社コードのデータを抽出すると、実行時間が非常に長くなり、ファイルが大きくなる可能性があります。
- 伝票タイプ(BLART): 仕入先請求書を特定するために、関連する伝票タイプでフィルタリングします。一般的なタイプには、「RE」(請求書 - 総額)や「KR」(仕入先請求書)などがあります。これにより、分析に不要な伝票を除外できます。
- 仕入先勘定(LIFNR): プログラムには、特定の仕入先番号に対するオプションのフィルターを含めることができ、これはターゲットを絞った分析やテストに役立ちます。
- 出力ファイル設定: プログラムは、アプリケーションサーバー上の出力ファイルパスと、例えばカンマやセミコロンなどのフィールド区切り文字を定義するパラメーターを持つ必要があります。
- 前提条件: このプログラムを実行するユーザーまたはシステムアカウントは、ABAPプログラムの作成と実行(
SE38経由)のための開発者アクセス、およびBKPF、BSEG、RBKP、RSEG、CDHDR、CDPOS、ワークフローテーブルを含むFI、MM、Basisテーブルに対する広範な読み取り権限が必要です。
a クエリ例 abap
REPORT Z_PM_INVOICE_EXTRACT.
* --- Internal table structure for the final event log
TYPES: BEGIN OF ty_s_event_log,
invoicenumber TYPE char25,
activityname TYPE char50,
eventtime TYPE char19, "YYYY-MM-DD HH:MM:SS
username TYPE sy-uname,
companycode TYPE bukrs,
vendornumber TYPE lifnr,
amountincompanycodecurrency TYPE wrbtr,
paymentduedate TYPE char10, "YYYY-MM-DD
documenttype TYPE blart,
paymentblockreason TYPE char1,
purchasingdocument TYPE ebeln,
END OF ty_s_event_log.
DATA: lt_event_log TYPE STANDARD TABLE OF ty_s_event_log.
DATA: ls_event_log TYPE ty_s_event_log.
* --- Selection Screen for user inputs
PARAMETERS: p_path TYPE string DEFAULT '/usr/sap/tmp/invoice_events.csv'.
SELECT-OPTIONS: s_erdat FOR sy-datum OBLIGATORY, " Entry Date
s_bukrs FOR bkpf-bukrs OBLIGATORY, " Company Code
s_blart FOR bkpf-blart. " Document Type
START-OF-SELECTION.
* --- 1. Invoice Document Created (from Logistics Invoice Verification)
SELECT CONCAT( rbkp~belnr, rbkp~gjahr ) AS invoicenumber,
'Invoice Document Created' AS activityname,
CONCAT( rbkp~cpudt, rbkp~cputm ) AS eventtime,
rbkp~usnam AS username,
rbkp~bukrs AS companycode,
rbkp~lifnr AS vendornumber,
rbkp~rmwwr AS amountincompanycodecurrency,
'' AS paymentduedate,
rbkp~blart AS documenttype,
rbkp~zuonr AS paymentblockreason,
'' AS purchasingdocument
FROM rbkp
INTO TABLE @DATA(lt_created)
WHERE rbkp~cpudt IN @s_erdat
AND rbkp~bukrs IN @s_bukrs
AND rbkp~blart IN @s_blart.
LOOP AT lt_created INTO DATA(ls_created).
ls_event_log-invoicenumber = ls_created-invoicenumber.
ls_event_log-activityname = ls_created-activityname.
ls_event_log-eventtime = |{ ls_created-eventtime(8) } { ls_created-eventtime+8(2) }:{ ls_created-eventtime+10(2) }:{ ls_created-eventtime+12(2) }|.
ls_event_log-username = ls_created-username.
ls_event_log-companycode = ls_created-companycode.
ls_event_log-vendornumber = ls_created-vendornumber.
ls_event_log-amountincompanycodecurrency = ls_created-amountincompanycodecurrency.
ls_event_log-paymentduedate = ''.
ls_event_log-documenttype = ls_created-documenttype.
ls_event_log-paymentblockreason = ''.
ls_event_log-purchasingdocument = ls_created-purchasingdocument.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- 2. Invoice Parked (assuming status 'A' or 'B' in RBKP)
SELECT CONCAT( belnr, gjahr ) AS invoicenumber,
'Invoice Parked' AS activityname,
CONCAT( cpudt, cputm ) AS eventtime,
usnam AS username,
bukrs AS companycode,
lifnr AS vendornumber,
rmwwr AS amountincompanycodecurrency,
'' AS paymentduedate,
blart AS documenttype,
'' AS paymentblockreason,
'' AS purchasingdocument
FROM rbkp
INTO TABLE @DATA(lt_parked)
WHERE rbstat IN ('A', 'B')
AND cpudt IN @s_erdat
AND bukrs IN @s_bukrs
AND blart IN @s_blart.
LOOP AT lt_parked INTO DATA(ls_parked).
ls_event_log-invoicenumber = ls_parked-invoicenumber.
ls_event_log-activityname = ls_parked-activityname.
ls_event_log-eventtime = |{ ls_parked-eventtime(8) } { ls_parked-eventtime+8(2) }:{ ls_parked-eventtime+10(2) }:{ ls_parked-eventtime+12(2) }|.
ls_event_log-username = ls_parked-username.
ls_event_log-companycode = ls_parked-companycode.
ls_event_log-vendornumber = ls_parked-vendornumber.
ls_event_log-amountincompanycodecurrency = ls_parked-amountincompanycodecurrency.
ls_event_log-paymentduedate = ''.
ls_event_log-documenttype = ls_parked-documenttype.
ls_event_log-paymentblockreason = ''.
ls_event_log-purchasingdocument = ''.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- 3, 4, 5. Sent For Approval, Approved, Rejected (Placeholder logic, needs adaptation)
* --- This logic is a generic template for SAP Business Workflow.
* --- Your implementation will vary. You must identify the correct workflow tasks.
SELECT obj.instid, wi.wi_cd, wi.wi_ct, wi.wi_stat, wi.wi_aagent
FROM sww_wi2obj AS obj
JOIN swwlog AS wi ON obj~instid = wi~wi_id
INTO TABLE @DATA(lt_workflow)
WHERE obj~typeid = 'BUS2081' " Business Object for Incoming Invoice
AND obj~catid = 'BO'
AND wi~wi_cd IN s_erdat.
LOOP AT lt_workflow INTO DATA(ls_workflow).
* --- This is a placeholder, adapt task IDs and logic
CASE ls_workflow-wi_stat.
WHEN 'STARTED'.
ls_event_log-activityname = 'Invoice Sent For Approval'.
WHEN 'COMPLETED'.
ls_event_log-activityname = 'Invoice Approved'.
WHEN 'CANCELLED'.
ls_event_log-activityname = 'Invoice Rejected'.
WHEN OTHERS.
CONTINUE.
ENDCASE.
* --- Code to get invoice details based on ls_workflow-instid needed here
* --- ... appending to lt_event_log ...
ENDLOOP.
* --- 6, 7, 8. Payment Block Set/Removed, Data Updated (from Change Docs)
SELECT h~objectid, h~username, h~udate, h~utime, p~fname, p~value_new, p~value_old
FROM cdhdr AS h
JOIN cdpos AS p ON h~objectclas = p~objectclas AND h~objectid = p~objectid AND h~changenr = p~changenr
INTO TABLE @DATA(lt_changes)
WHERE h~objectclas = 'BELEGV'
AND h~udate IN s_erdat.
LOOP AT lt_changes INTO DATA(ls_change).
ls_event_log-invoicenumber = |{ ls_change-objectid+10(10) }{ ls_change-objectid(4) }|.
ls_event_log-username = ls_change-username.
ls_event_log-eventtime = |{ ls_change-udate } { ls_change-utime(2) }:{ ls_change-utime+2(2) }:{ ls_change-utime+4(2) }|.
IF ls_change-fname = 'ZLSPR'. " Payment Block
IF ls_change-value_old IS INITIAL AND ls_change-value_new IS NOT INITIAL.
ls_event_log-activityname = 'Payment Block Set'.
ls_event_log-paymentblockreason = ls_change-value_new.
ELSEIF ls_change-value_old IS NOT INITIAL AND ls_change-value_new IS INITIAL.
ls_event_log-activityname = 'Payment Block Removed'.
ls_event_log-paymentblockreason = ''.
ELSE.
CONTINUE.
ENDIF.
ELSE.
ls_event_log-activityname = 'Invoice Data Updated'.
ENDIF.
* --- Need to select other attributes based on invoice number
* --- ... appending to lt_event_log ...
ENDLOOP.
* --- 9. Invoice Posted
SELECT CONCAT( bkpf~belnr, bkpf~gjahr ) AS invoicenumber,
'Invoice Posted' AS activityname,
CONCAT( bkpf~cpudt, bkpf~cputm ) AS eventtime,
bkpf~usnam AS username,
bkpf~bukrs AS companycode,
bseg~lifnr AS vendornumber,
bseg~wrbtr AS amountincompanycodecurrency,
bseg~zfBDT AS paymentduedate,
bkpf~blart AS documenttype,
bseg~zlspr AS paymentblockreason,
bseg~ebeln AS purchasingdocument
FROM bkpf
JOIN bseg ON bkpf~bukrs = bseg~bukrs AND bkpf~belnr = bseg~belnr AND bkpf~gjahr = bseg~gjahr
INTO TABLE @DATA(lt_posted)
WHERE bkpf~cpudt IN @s_erdat
AND bkpf~bukrs IN @s_bukrs
AND bkpf~blart IN @s_blart
AND bseg~koart = 'K'. " Vendor line
LOOP AT lt_posted INTO DATA(ls_posted).
ls_event_log-invoicenumber = ls_posted-invoicenumber.
ls_event_log-activityname = ls_posted-activityname.
ls_event_log-eventtime = |{ ls_posted-eventtime(8) } { ls_posted-eventtime+8(2) }:{ ls_posted-eventtime+10(2) }:{ ls_posted-eventtime+12(2) }|.
ls_event_log-username = ls_posted-username.
ls_event_log-companycode = ls_posted-companycode.
ls_event_log-vendornumber = ls_posted-vendornumber.
ls_event_log-amountincompanycodecurrency = ls_posted-amountincompanycodecurrency.
ls_event_log-paymentduedate = ls_posted-paymentduedate.
ls_event_log-documenttype = ls_posted-documenttype.
ls_event_log-paymentblockreason = ls_posted-paymentblockreason.
ls_event_log-purchasingdocument = ls_posted-purchasingdocument.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- 10. Payment Proposal Created
SELECT CONCAT( regup~belnr, regup~gjahr ) AS invoicenumber,
'Payment Proposal Created' AS activityname,
CONCAT( reguh~erfdt, reguh~erfzt ) AS eventtime,
reguh~erfbu AS username,
regup~bukrs AS companycode,
regup~lifnr AS vendornumber,
regup~wrbtr AS amountincompanycodecurrency,
'' AS paymentduedate,
regup~blart AS documenttype,
'' AS paymentblockreason,
'' AS purchasingdocument
FROM regup
JOIN reguh ON regup~laufd = reguh~laufd AND regup~laufi = reguh~laufi
INTO TABLE @DATA(lt_proposal)
WHERE reguh~erfdt IN @s_erdat
AND regup~bukrs IN @s_bukrs.
LOOP AT lt_proposal INTO DATA(ls_proposal).
ls_event_log-invoicenumber = ls_proposal-invoicenumber.
ls_event_log-activityname = ls_proposal-activityname.
ls_event_log-eventtime = |{ ls_proposal-eventtime(8) } { ls_proposal-eventtime+8(2) }:{ ls_proposal-eventtime+10(2) }:{ ls_proposal-eventtime+12(2) }|.
ls_event_log-username = ls_proposal-username.
ls_event_log-companycode = ls_proposal-companycode.
ls_event_log-vendornumber = ls_proposal-vendornumber.
ls_event_log-amountincompanycodecurrency = ls_proposal-amountincompanycodecurrency.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- 11, 12. Payment Executed / Late Payment Executed
SELECT CONCAT( belnr, gjahr ) AS invoicenumber,
augdt,
zfBDT
FROM bsak
INTO TABLE @DATA(lt_cleared)
WHERE augdt IN @s_erdat
AND bukrs IN @s_bukrs.
LOOP AT lt_cleared INTO DATA(ls_cleared).
IF ls_cleared-augdt > ls_cleared-zfbdt.
ls_event_log-activityname = 'Late Payment Executed'.
ELSE.
ls_event_log-activityname = 'Payment Executed'.
ENDIF.
ls_event_log-invoicenumber = ls_cleared-invoicenumber.
ls_event_log-eventtime = |{ ls_cleared-augdt } 00:00:00|.
* --- Need to select other attributes based on invoice number
* --- ... appending to lt_event_log ...
ENDLOOP.
* --- 13. Invoice Reversed
SELECT CONCAT( stblg, stjah ) AS invoicenumber,
'Invoice Reversed' AS activityname,
CONCAT( cpudt, cputm ) AS eventtime,
usnam AS username,
bukrs AS companycode,
'' AS vendornumber,
'' AS amountincompanycodecurrency,
'' AS paymentduedate,
blart AS documenttype,
'' AS paymentblockreason,
'' AS purchasingdocument
FROM bkpf
INTO TABLE @DATA(lt_reversed)
WHERE stblg IS NOT NULL
AND cpudt IN @s_erdat
AND bukrs IN @s_bukrs.
LOOP AT lt_reversed INTO DATA(ls_reversed).
ls_event_log-invoicenumber = ls_reversed-invoicenumber.
ls_event_log-activityname = ls_reversed-activityname.
ls_event_log-eventtime = |{ ls_reversed-eventtime(8) } { ls_reversed-eventtime+8(2) }:{ ls_reversed-eventtime+10(2) }:{ ls_reversed-eventtime+12(2) }|.
ls_event_log-username = ls_reversed-username.
ls_event_log-companycode = ls_reversed-companycode.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- Write internal table to CSV file
OPEN DATASET p_path FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc <> 0.
MESSAGE 'Error opening file.' TYPE 'E'.
ENDIF.
DATA: lv_line TYPE string.
FIELD-SYMBOLS: <fs_any> TYPE any.
* --- Header row
lv_line = 'InvoiceNumber,ActivityName,EventTime,UserName,CompanyCode,VendorNumber,AmountInCompanyCodeCurrency,PaymentDueDate,DocumentType,PaymentBlockReason,PurchasingDocument'.
TRANSFER lv_line TO p_path.
LOOP AT lt_event_log INTO ls_event_log.
CLEAR lv_line.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE ls_event_log TO <fs_any>.
IF sy-subrc <> 0.
EXIT.
ENDIF.
IF sy-index = 1.
lv_line = <fs_any>.
ELSE.
CONCATENATE lv_line <fs_any> INTO lv_line SEPARATED BY ','.
ENDIF.
ENDDO.
TRANSFER lv_line TO p_path.
ENDLOOP.
CLOSE DATASET p_path.
WRITE: / 'Extraction complete. File saved to:', p_path.