調達から支払いまでの請求書処理向けデータテンプレート
調達から支払いまでの請求書処理向けデータテンプレート
- 収集を推奨する属性
- 追跡すべき主要なアクティビティ
- SAP S/4HANAからのデータ抽出手順
調達から支払いまでの請求書処理の属性
| 名前 | 説明 | ||
|---|---|---|---|
| 請求書番号 InvoiceNumber | 仕入先請求書伝票を一意に識別する番号で、プロセスの主要なケース識別子として使用されます。 | ||
| 説明 請求書番号は、SAP S/4HANAで各仕入先請求書に割り当てられる一意の識別子です。作成、仮登録、承認、支払など、関連するすべてのアクティビティを結び付け、1つのプロセスインスタンスとしてまとめます。 プロセスマイニングでは、各請求書の処理全体を追跡するための基本となる属性です。受領から最終的な支払までのプロセスフローを再構成し、請求書ごとのサイクルタイム、ボトルネック、プロセスのばらつきを分析できます。 重要な理由 関連するすべてのイベントを結び付け、システム内で請求書が処理される全過程を追跡するための重要なキーです。 入手先 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 | |||
| ユーザー名 UserName | アクティビティを実行した担当者またはシステムのSAPユーザーIDです。 | ||
| 説明 この属性は、特定のトランザクションを実行したユーザー、または伝票を作成したユーザーを識別します。個人のユーザーIDの場合も、自動バッチ処理に使われるシステムIDの場合もあります。 ユーザー別に分析すると、業務負荷の分布やトレーニングの必要性を把握し、通常とは異なるユーザーの行動を見つけられます。たとえば、例外処理を頻繁に担当するユーザーや、自動処理された請求書(「BATCHUSER」など)を特定できます。これは「請求書自動化率」の重要業績評価指標(KPI)の算出に役立ちます。 重要な理由 プロセスのアクティビティを特定のユーザーやシステムアカウントに関連付け、業務負荷の分析、パフォーマンスの比較、自動化の検出を可能にします。 入手先 BKPF-USNAM(入力者)やCDHDR-USERNAME(変更者)などのフィールドから取得します。 例 SMITHJMUELLERTWF-BATCH | |||
| 仕入先番号 VendorNumber | 請求書を提出した仕入先を一意に識別する番号です。 | ||
| 説明 仕入先番号は、請求書に関連する仕入先または債権者を識別します。請求書の取引と仕入先マスターデータを結び付けます。 この属性は、「仕入先の支払パフォーマンス」の評価や、例外処理や支払ブロックにつながる問題のある請求書を頻繁に提出する仕入先の特定など、仕入先を軸とした分析に欠かせません。仕入先との関係管理や、仕入先の信頼性評価にも役立ちます。 重要な理由 仕入先ごとのプロセスパフォーマンスを分析し、傾向の把握、関係管理、仕入先に関する問題の評価に役立ちます。 入手先 通常、会計伝票明細テーブルBSEGのLIFNRフィールドにあります。 例 100345700012V9832 | |||
| 会社コード CompanyCode | 財務諸表を作成する、法的に独立した会社を表す組織単位です。 | ||
| 説明 会社コードは、SAP Financeにおける基本的な組織単位です。各請求書には特定の会社コードが割り当てられ、取引を担う法人が決まります。 プロセスマイニングでは、会社コードで絞り込んだり比較したりすることで、事業部門、法人、国ごとのプロセスパフォーマンスを分析できます。地域ごとの効率、コンプライアンス、自動化の状況の違いを特定し、対象を絞った改善施策につなげられます。 重要な理由 組織内の異なる法人や地域ごとに、請求書処理のパフォーマンスを分類して比較できます。 入手先 BKPFテーブルのBUKRSフィールドにある標準フィールドです。 例 1000US01DE01 | |||
| 伝票タイプ DocumentType | 仕入先請求書やクレジットメモなど、会計伝票の種類を分類するコードです。 | ||
| 説明 伝票タイプは、SAPで異なる業務取引を区別するために使用します。たとえば、「KR」は通常の仕入先請求書、「KG」は仕入先クレジットメモを表す場合があります。 伝票タイプ別に分析すると、取引の種類ごとにプロセスを分類し、処理方法を把握できます。たとえば、クレジットメモの処理は通常の請求書とは大きく異なる場合があります。この分類により、より正確で関連性の高いプロセスインサイトが得られます。 重要な理由 通常の請求書とクレジットメモなど、異なるプロセス経路をたどることが多い各種の財務取引を区別できます。 入手先 BKPFテーブルの伝票ヘッダーにあるBLARTフィールドで確認できます。 例 KRREKG | |||
| 支払ブロック理由 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)に結び付けます。この関連付けは、請求書を購買発注書および入庫と照合する三点照合プロセスの基礎となります。 この属性で分析すると、購買発注書に基づく請求書と、そうでない請求書の問題を把握できます。照合の不一致を調査し、プロセスの調達部分の効率を理解するうえで重要です。 重要な理由 請求書を調達プロセスに結び付け、照合の不一致や購買発注書への適合性を分析するために役立ちます。 入手先 通常、伝票明細テーブル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)を簡単に算出できます。手戻りが発生したケースを絞り込んで調査し、非効率や繰り返しの手作業につながる根本原因を把握できます。 重要な理由 作業のやり直しが必要な非効率なプロセスフローを特定し、無駄の定量化やプロセス上の例外の根本原因の特定に役立ちます。 入手先 イベントログ内のアクティビティの順序に基づいて算出します。たとえば、請求書のトレースに「請求書却下」が含まれる場合、このフラグはtrueになります。 例 truefalse | |||
| 承認サイクル回数 ApprovalCycleCount | 請求書が承認に回された回数です。 | ||
| 説明 この指標は、1件の請求書について「請求書を承認に回付」アクティビティが発生した回数を数えます。回数が1回を超える場合、請求書が少なくとも1回却下または差し戻され、新たな承認サイクルが必要になったことを示します。 この属性は、「初回承認率」の重要業績評価指標(KPI)を直接支えます。承認サイクルの回数が多い請求書を分析すると、情報不足や誤ったコードなど、承認に至らなかった理由を特定し、プロセスの改善につなげられます。 重要な理由 承認サブプロセス内の手戻りを定量化し、初回で正しく処理できた割合の測定や、承認却下の理由の特定に役立ちます。 入手先 一意のInvoiceNumberごとに「請求書を承認に回付」アクティビティの発生回数を数えて算出します。 例 123 | |||
| 抽出タイムスタンプ ExtractionTimestamp | ソースシステムからデータを抽出した日時です。 | ||
| 説明 この属性は、データを抽出したイベントのタイムスタンプを記録します。プロセスマイニングツールで分析するデータがどの程度新しいかを示します。 分析では、インサイトがどの時点のデータに基づいているかを確認するために使用します。最新の情報に基づく意思決定を支え、データ更新サイクルを適切に管理するため、業務監視用ダッシュボードで重要な属性です。 重要な理由 データの新しさを示し、利用可能な最新情報に基づいて分析やレポートを行えるようにします。 入手先 SAPのフィールドではありません。データ抽出ツールまたはETLプロセスが、データの取得時に生成して追加します。 例 2023-10-27T02:00:00Z2023-10-28T02:00:00Z2023-10-29T02:00:00Z | |||
| 支払期日遵守 IsPaidOnTime | 請求書が支払期日当日またはそれ以前に支払われた場合にtrueとなるフラグです。 | ||
| 説明 この真偽値属性は、実際の支払日(「支払実行」アクティビティのタイムスタンプ)と「支払期日」を比較した結果です。各請求書の支払状況を明確に示します。 「支払期日遵守率」の重要業績評価指標(KPI)を算出するための中心的な計算です。遅延が発生した請求書を絞り込み、遅延に関連する仕入先、会社コード、請求書金額などの特徴を分析できます。 重要な理由 支払条件を守れているかを直接測定します。仕入先との関係管理や財務業務における重要な指標です。 入手先 「支払実行」アクティビティのEventTimeとPaymentDueDate属性を比較して算出します。(支払日 <= PaymentDueDate) 例 truefalse | |||
| 支払条件 PaymentTerms | 支払期日や割引期間など、仕入先と合意した支払条件を定めるコードです。 | ||
| 説明 支払条件は、早期支払割引の有無を含め、請求書の支払ルールを定めます。たとえば、「Z030」は「30日以内に正味額を支払う」という意味の場合があります。 この属性は、財務計画や運転資金の最適化に欠かせません。プロセスマイニングでは、「支払期日」の算出や早期支払割引の適用可否の判定に使われ、「早期支払割引適用率」の重要業績評価指標(KPI)を直接支えます。 重要な理由 支払期日と割引のルールを定め、支払期日遵守に関する重要業績評価指標(KPI)や運転資金の管理に直接影響します。 入手先 BSEGテーブルの仕入先明細にあるZTERMフィールド(支払条件キー)で確認できます。 例 0001Z030NT60 | |||
| 消込伝票番号 ClearingDocumentNumber | 請求書を消し込む伝票の番号で、通常は支払伝票を表します。 | ||
| 説明 消込伝票番号は、未消込の請求書明細を消込処理に結び付けます。消込処理はほとんどの場合、支払伝票です。これにより、請求書が支払済みであることを確認できます。 この属性は、請求書と支払を結び付ける確実な手がかりです。「支払実行」アクティビティとそのタイムスタンプの特定に使います。全体のサイクルタイムや支払期日遵守率の算出に欠かせません。 重要な理由 請求書が支払済みであることを確認し、特定の支払取引に結び付けます。サイクルタイムや支払パフォーマンスの分析に欠かせません。 入手先 伝票明細テーブルBSEGのAUGBLフィールド(消込伝票番号)で確認できます。 例 150000000115000000231500000088 | |||
| 自動処理かどうか IsAutomated | アクティビティが自動システムユーザーによって実行されたかどうかを示すフラグです。 | ||
| 説明 アクティビティに関連付けられたユーザーが、「WF-BATCH」や「SAP_SYSTEM」など、既知のシステムアカウントまたはバッチアカウントの場合、この真偽値属性はtrueになります。手作業のステップと自動処理のステップを区別できます。 この属性は、「請求書自動化率」の重要業績評価指標(KPI)の算出に欠かせません。プロセスのどの部分が自動化されているかを分析することで、自動化施策の成果を測定し、手作業の削減と効率向上に向けた次の機会を特定できます。 重要な理由 手作業のアクティビティとシステムによるアクティビティを区別します。自動化率の測定や、さらなる自動化の機会の特定に欠かせません。 入手先 ユーザー名属性から導出します。特定のユーザーIDを「自動処理」として分類する対応表またはルールを作成します。 例 truefalse | |||
| 請求書日付 InvoiceDate | 仕入先が請求書を発行した日付です。 | ||
| 説明 請求書日付は伝票日付とも呼ばれ、仕入先が請求書に記載した日付です。合意済みの支払条件に基づいて支払期日を算出する際の起点となります。 分析では、請求書の経過期間や早期支払割引の適用可否など、財務計算の基礎となります。「早期支払割引適用率」の重要業績評価指標(KPI)を算出する際にも使われます。 重要な理由 支払条件と支払期日の算出基準となり、運転資金の管理や割引の適用に欠かせません。 入手先 BKPFテーブルの伝票ヘッダーにあるBLDATフィールド(伝票日付)で確認できます。 例 2023-04-122023-05-152023-06-20 | |||
調達から支払いまでの請求書処理のアクティビティ
| アクティビティ | 説明 | ||
|---|---|---|---|
| 支払実行 | 標準プロセスの最後のアクティビティで、支払が行われ、請求書の消込が完了します。これにより、仕入先への資金の支払いが完了したことが示されます。 | ||
| 重要な理由 これをもって、調達から支払いまでの請求書処理が完了します。全体のサイクルタイムの算出や、支払期日どおりに支払われた割合の測定に欠かせません。 入手先 このイベントは、仕入先明細の消込伝票情報から取得します。消込日付(BSEG-AUGDT)と消込伝票(BSEG-AUGBL)によって、支払済みであることを確認できます。 記録 消込済み仕入先明細の消込日付(BSEG-AUGDT)を使用します。 イベントタイプ explicit | |||
| 請求書の承認 | 指定された権限者が請求書を承認したことを示します。承認ワークフローが正常に完了したとき、またはリリースインジケーターが設定されたときに記録します。 | ||
| 重要な理由 請求書の支払いブロックが解除される重要な節目です。承認の遅れはよくあるボトルネックであり、このアクティビティを追跡すると、対応の遅い承認者やプロセスのステップを特定できます。 入手先 SAPワークフローの最終リリースステップ、または請求書や関連する購買文書のテーブルにあるリリースステータス項目の変更から推定できます。 記録 ワークフローの完了イベント、または文書のリリースステータス項目の変更から推定します。 イベントタイプ inferred | |||
| 請求書の転記 | 仮登録または承認済みの請求書が総勘定元帳に正式に転記される、重要な財務イベントです。この処理により、仕入先に対する債務が認識されます。 | ||
| 重要な理由 転記は、データ入力と承認の段階から決済段階へ移る重要な節目です。請求書の作成から転記までの時間は、社内処理の効率を測る重要な指標です。 入手先 このイベントは、伝票ヘッダーの転記日付(BKPF-BUDAT)で識別します。先に仮登録された伝票の場合は、転記済みステータスに変わった時点がイベントのタイムスタンプになります。 記録 イベントのタイムスタンプには、転記日付(BKPF-BUDAT)を使用します。 イベントタイプ explicit | |||
| 請求書取消 | 転記済みの請求書伝票を取り消すアクティビティです。誤った請求書に対する最終イベントであり、その後、正しい内容で再入力されることがよくあります。 | ||
| 重要な理由 取消は、プロセスの早い段階で検出できなかった重大なエラーを示します。発生頻度と根本原因を追跡することは、プロセスの改善と会計上の誤りの削減に欠かせません。 入手先 取消伝票が作成されると、取消として識別されます。元の伝票ヘッダー(BKPF)には取消伝票番号(BKPF-STBLG)が記録され、その逆も同様です。イベント時刻には、取消伝票の転記日付を使用します。 記録 BKPF-STBLGフィールドに値がある伝票を特定し、取消伝票の転記日付を使用します。 イベントタイプ explicit | |||
| 請求書文書の作成 | 最初に発生するイベントで、SAPで請求書文書が作成されたことを示します。ユーザーが新しい請求書文書を保存した時点で記録できます。文書は仮登録または転記前の状態の場合があります。 | ||
| 重要な理由 このアクティビティは、請求書処理の開始を示します。このイベントから他のイベントまでの時間を分析することは、処理全体のリードタイムを測定するうえで重要です。 入手先 このイベントは、通常BKPFまたは物流請求書の場合はRBKPの文書ヘッダーテーブルにある作成日時(CPUDT、CPUTM)から記録します。FB60、MIRO、MIR7などのトランザクションコード(BKPF-TCODE)から、作成方法を確認できます。 記録 請求書文書の作成日時には、BKPF-CPUDTとBKPF-CPUTMを使用します。 イベントタイプ explicit | |||
| 支払いブロックの解除 | 以前に設定された支払いブロックが解除され、問題が解消したことを示します。これにより、請求書は再び支払い可能になります。 | ||
| 重要な理由 ブロックの設定から解除までの時間は、プロセス上の例外を解消するまでの時間を示します。この時間を短縮することは、業務効率と仕入先との関係を改善するうえで重要です。 入手先 支払いブロックキー項目(BSEG-ZLSPR)がクリアされた時点で、このイベントを記録します。この変更はCDHDRとCDPOSのテーブルに記録され、解除日時を確認できます。 記録 変更文書(CDHDR/CDPOS)を使って、BSEG-ZLSPR項目がクリアされた時点を特定します。 イベントタイプ explicit | |||
| 支払いブロックの設定 | 請求書の支払いを防ぐため、意図的にブロックを設定するアクティビティです。価格や数量の不一致、またはクレジットメモの処理待ちなどが原因となることがあります。 | ||
| 重要な理由 支払いブロックは、支払い遅延や仕入先との紛争の主な原因です。期日どおりの支払いを増やすには、ブロックの発生頻度、継続時間、理由を分析することが重要です。 入手先 請求書の明細項目にある支払いブロックキー項目(BSEG-ZLSPR)の変更を追跡して、このイベントを記録します。CDHDRとCDPOSの変更ログから、ブロックが設定された日時とユーザーを確認できます。 記録 変更文書(CDHDR/CDPOS)を使って、BSEG-ZLSPR項目に値が設定された時点を特定します。 イベントタイプ explicit | |||
| 支払提案に追加 | 支払処理の一環として、請求書が選択され、支払提案に含まれます。これは、自動支払プロセスの最初のステップです。 | ||
| 重要な理由 このアクティビティは、支払の意思が示されたことを表します。このステップから最終的な支払実行までに遅れがある場合、支払処理、承認、銀行との通信に問題がある可能性があります。 入手先 支払処理のテーブル、特に支払提案に含まれる明細を記録するREGUPで確認できます。対応するREGUHテーブルの実行日付がタイムスタンプになります。 記録 支払提案の実行時に、請求書がREGUPテーブルに登録された時点を特定します。 イベントタイプ explicit | |||
| 支払遅延 | 請求書の支払が算出された支払期日を過ぎて実行された場合に発生する、計算上のイベントです。2つの日付フィールドを比較して判定します。 | ||
| 重要な理由 このアクティビティは、支払期日遵守に関する重要業績評価指標(KPI)の把握に役立ちます。また、支払遅延が頻発する仕入先や事業部門を特定できます。支払遅延は仕入先との関係悪化や違約金につながる可能性があります。 入手先 消込日付(BSEG-AUGDT)と正味支払期日を比較して算出します。支払期日は、基準日(BSEG-ZFBDT)と支払条件(BSEG-ZTERM)から算出されます。 記録 BSEG-AUGDT >(BSEG-ZFBDT + 支払条件の日数)を比較して判定します。 イベントタイプ calculated | |||
| 請求書データの更新 | 請求書文書の作成後に変更が加えられたことを示すアクティビティです。却下後の手戻りやエラー修正の際によく発生します。 | ||
| 重要な理由 頻繁な更新は、手戻りや入力時のデータ品質の問題を示している可能性があります。変更を追跡すると、修正にかかる作業量を把握し、よくあるエラーを特定できます。 入手先 主要項目の変更は、SAPの変更文書テーブルであるCDHDR(ヘッダー)とCDPOS(明細)に記録されます。対象の請求書オブジェクトに対する変更を抽出して、イベントを作成できます。 記録 CDHDRとCDPOSから、請求書オブジェクトの変更イベントを抽出します。 イベントタイプ explicit | |||
| 請求書の仮登録 | システムに入力済みで、総勘定元帳にはまだ転記されていない請求書を指します。未完成の請求書を保存したり、転記前に後から確認したりするために仮登録を使います。 | ||
| 重要な理由 仮登録は、プロセスが意図的に一時停止されていることを示します。仮登録された請求書の件数や処理時間を追跡すると、正式な転記と承認のサイクルが始まる前に遅延が起きる理由を特定できます。 入手先 MIR7やFV60などの仮登録用トランザクションで作成された文書を特定するか、BKPFテーブルの特定のステータス項目、またはVBKPFなどの仮登録文書専用テーブルを確認します。 記録 仮登録用トランザクションで作成された文書を特定するか、仮登録のステータスを確認します。 イベントタイプ explicit | |||
| 請求書の却下 | 承認プロセス中に請求書が却下されたことを示します。このイベントが発生すると、修正して再提出するための手戻りが生じます。 | ||
| 重要な理由 請求書の却下は、プロセスの非効率やデータ品質の問題を示す重要な指標です。却下の頻度や理由を分析すると、改善やトレーニングの機会を特定できます。 入手先 SAPワークフローの「却下」などの特定のステータス更新、または現在の承認ワークフローを取り消して処理担当者に差し戻すイベントから推定します。 記録 却下を示すワークフローのステータス変更から推定します。 イベントタイプ inferred | |||
| 請求書を承認に回す | 請求書の正式な承認ワークフローが開始されたことを示すアクティビティです。請求書のステータスが「承認待ち」に変わったときや、ワークフロー項目が作成されたときに推定できます。 | ||
| 重要な理由 承認サイクルタイムの測定開始点です。承認がいつ始まるかを把握することは、承認ワークフロー自体のボトルネックを特定するうえで欠かせません。 入手先 通常、請求書オブジェクト(例:BUS2081)に関連付けられたSAP Business Workflowの開始(SWW_WI2OBJテーブル)、または文書ヘッダーのカスタムステータス項目の変更から推定します。 記録 請求書文書に関連するワークフロー項目の作成から推定します。 イベントタイプ inferred | |||
データ抽出ガイド
ステップ
- 前提条件と権限:抽出を実行するユーザーに、必要なCore Data Services(CDS)ビューへアクセスするためのSAP S/4HANA権限があることを確認します。主なビューは、
I_InvoiceDocument、I_OperationalAcctgDocItem、I_ChangeDocument、I_ChangeDocumentItem、I_PaymentProposalItemです。また、ODataサービスや直接SQL接続など、選択したインターフェースでクエリを実行する権限も必要です。 - 接続方法の確認:SQLクエリを実行するため、SAP S/4HANAシステムへの接続方法を決めます。一般的な方法には、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列に「Invoice Document Created」だけでなく、複数のアクティビティが含まれていることも確認します。 - データ変換の確認:クエリは整ったイベントログ形式で出力するように構成されています。ただし、
EventTime列がYYYY-MM-DDTHH:MM:SSなど、一貫したタイムスタンプ形式になっていることを確認してください。必要に応じて、提示されたクエリが日付と時刻のフィールドを1つのタイムスタンプにまとめます。 - データのエクスポート:ツールから最終結果を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)で厳密に絞り込んでください。
クエリの例 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 HANAテナントまたはデータベーススキーマへの直接読み取りアクセスが承認されていることを確認し、必要なSAPテーブルと、承認済みの変更履歴テーブルまたはワークフローテーブルにアクセスできる読み取り専用データベースユーザーを用意します。SAP HANA Database Explorer、SAP HANA Studio、または承認済みのSQLクライアントを使用してください。本番環境への書き込みアクセスは使用しないでください。
- 対象のS/4HANAシステムで、物理テーブル名と列名を確認します。ACDOCA、BKPF、RBKPは標準的な出発点ですが、ワークフロー、保留、支払提案、支払実行、変更履歴、支払ブロック履歴には、リリースや顧客ごとに異なるオブジェクトが使われる場合があります。クエリ内の角括弧付きプレースホルダーを、システムカタログで確認したオブジェクトと、該当する業務上の意味に合わせて置き換えてください。
- [Start timestamp]と[End timestamp]を使って抽出期間を指定します。通常は3~6か月分を目安に、伝票とイベントを十分に含む期間を設定してください。支払期日や支払遅延が請求書の作成期間外になる場合は、期間を広げます。
- 設定済みの請求書キーを使ってケースを識別します。クエリではケース識別子にInvoiceNumberを使用し、番号の重複を避けるため、必要に応じて会社コードと会計年度を内部で組み合わせます。ProcessMindのケース識別子に会計年度や会社コードを追加する必要があるか、業務上の定義を確認してください。
- RBKP、BKPF、ACDOCAから転記済み請求書のデータを対応付けます。請求書ヘッダー情報にはRBKP、会計伝票のタイムスタンプとユーザーにはBKPF、仕入先、金額、購買伝票、消込、支払関連の会計情報には、利用可能な場合にACDOCAを使用します。すべての転記パターンで各フィールドに値が入るとは限りません。
- 保留、承認、却下、更新、支払ブロック、取消、支払提案、支払実行の各イベントを、システムで確認したデータソースから対応付けます。イベントのタイムスタンプ、請求書参照、ユーザー、ステータス、変更前後の値を取得できる、承認済みのビューまたはテーブルにプレースホルダーのデータソースを置き換えてください。ProcessMindはイベントを推測しないため、各アクティビティを明示的なイベント行として出力する必要があります。
- 本番環境以外、または読み取り専用のセッションでSQLクエリ全体を実行します。実行計画を確認し、必要に応じて会社コード、伝票タイプ、会計年度、イベントタイムスタンプでクエリを絞り込みます。大規模な仕訳テーブルと履歴テーブルを無条件に結合しないでください。
- 以下の確認項目に沿って結果を検証します。必須列がすべて存在すること、すべてのイベントにEventTimeが設定されていること、すべてのケースにInvoiceNumberが設定されていること、対応するデータがある場合に13種類すべてのアクティビティ名が含まれていることを確認してください。
- ProcessMindが対応する区切り形式のファイルとして結果をエクスポートします。UTF-8のCSVを推奨します。1行につき1イベントとし、InvoiceNumber、ActivityName、EventTime、UserName、CompanyCode、VendorNumber、AmountInCompanyCodeCurrency、PaymentDueDate、DocumentType、PaymentBlockReason、PurchasingDocumentの各列を含めます。タイムスタンプのタイムゾーンを統一し、識別子の先頭のゼロを保持してください。
- イベントログをProcessMindにアップロードし、InvoiceNumberをケース識別子、ActivityNameをアクティビティ列、EventTimeをタイムスタンプ列に設定します。ProcessMindの設定で追加のケースキーに対応している場合は、抽出時と同じ複合キーの方針を使用してください。
設定
- 期間:初回の抽出には、直近3~6か月の期間を設定します。承認、支払、消込、取消、支払遅延のイベントが請求書の作成期間後に発生する場合は、履歴を追加してください。
- 会社の範囲:[Company code filter]で絞り込み、選択した会社コードが抽出対象として承認されていることを確認します。
- 伝票の範囲:[Document type filter]で絞り込み、対象プロセスに該当する仕入先請求書、クレジットメモ、保留中の請求書、取消の伝票タイプを含めます。
- ケース識別子:プロセス定義に従い、InvoiceNumberを使用します。請求書番号が一意でない場合は、会社コードと会計年度を抽出結果に保持するか、ProcessMindのモデルに合わせて複合ケースキーを設定します。
- イベントソース:ワークフローのステータス変更、承認判断、保留、変更履歴、支払ブロック、支払提案、支払実行の物理データソースを確認します。これらのデータソースは、S/4HANAのリリース、有効化された機能、ワークフロー設計、顧客拡張によって異なります。
- タイムスタンプの方針:抽出時刻ではなく、業務イベントの発生時刻を選択します。タイムゾーンを明記し、アップロード前にすべてのイベントのタイムスタンプを同じ基準で変換してください。
- 金額の方針:会社コード通貨での金額を使用し、選択したデータソースで借方と貸方の符号が一貫していることを確認します。請求書ケースに対する集計ルールを検証せずに、仕訳明細を合計しないでください。
- 支払の方針:「支払実行」が消込、支払伝票の転記、銀行での実行、または別の業務上の節目のどれを指すかを定義します。合意したプロセス定義に合うデータソースを使用してください。
- 支払遅延:Payment ExecutedがPaymentDueDateより後に発生した場合に限り、Late Payment Executedを出力します。クエリではこのイベントを明示的に計算し、ProcessMindによる推測には頼りません。
- 処理性能:日付、会社コード、伝票タイプ、該当する会計年度でデータソースへの読み取りを絞り込みます。必要な列だけを選択し、クエリの実行計画を確認してください。履歴データが大きい場合は、承認済みの中間ビューを実体化します。
- 前提条件:SAP HANAへの直接接続、選択したすべてのオブジェクトに対する読み取り権限、メタデータの確認権限、買掛金、総勘定元帳、購買、ワークフロー、支払に関するデータへのアクセスが必要です。必要なSAPライセンス、データベースアクセス方針、データ保護の承認が整っていることを確認してください。
- セキュリティ:読み取り専用の技術ユーザーを使用し、仕入先と支払のデータを保護してください。組織の移送、監査、マスキング、認証情報管理に関する方針に従ってください。
クエリの例 sql
WITH
invoice_base AS (
SELECT
r.INV_DOC_NO AS InvoiceNumber,
r.COMPANY_CODE AS CompanyCode,
r.FISCAL_YEAR AS FiscalYear,
r.DOCUMENT_TYPE AS DocumentType,
r.VENDOR_NO AS VendorNumber,
r.GROSS_AMOUNT_CC AS AmountInCompanyCodeCurrency,
r.PAYMENT_DUE_DATE AS PaymentDueDate,
r.PURCHASING_DOCUMENT AS PurchasingDocument,
r.CREATED_AT AS InvoiceCreatedAt,
r.CREATED_BY AS InvoiceCreatedBy
FROM [Your RBKP invoice header source] r
WHERE r.CREATED_AT >= '[Start timestamp]'
AND r.CREATED_AT < '[End timestamp]'
AND r.COMPANY_CODE IN ([Company code filter])
AND r.DOCUMENT_TYPE IN ([Document type filter])
),
posted_accounting AS (
SELECT
b.INV_DOC_NO AS InvoiceNumber,
b.COMPANY_CODE AS CompanyCode,
b.FISCAL_YEAR AS FiscalYear,
b.ACCOUNTING_DOCUMENT AS AccountingDocument,
b.POSTING_DATE AS PostingDate,
b.CREATED_AT AS PostedAt,
b.CREATED_BY AS PostedBy,
b.REVERSAL_DOCUMENT AS ReversalDocument,
b.REVERSED_DOCUMENT AS ReversedDocument
FROM [Your BKPF accounting document source] b
WHERE b.CREATED_AT >= '[Start timestamp]'
AND b.CREATED_AT < '[End timestamp]'
AND b.COMPANY_CODE IN ([Company code filter])
),
journal_attributes AS (
SELECT
a.COMPANY_CODE AS CompanyCode,
a.FISCAL_YEAR AS FiscalYear,
a.ACCOUNTING_DOCUMENT AS AccountingDocument,
MAX(a.VENDOR_NO) AS VendorNumber,
SUM(a.AMOUNT_IN_COMPANY_CODE_CURRENCY) AS AmountInCompanyCodeCurrency,
MAX(a.PURCHASING_DOCUMENT) AS PurchasingDocument,
MAX(a.CLEARING_DATE) AS ClearingDate,
MAX(a.CLEARING_DOCUMENT) AS ClearingDocument
FROM [Your ACDOCA universal journal source] a
WHERE a.COMPANY_CODE IN ([Company code filter])
AND a.POSTING_DATE >= '[Start date]'
AND a.POSTING_DATE < '[End date]'
GROUP BY
a.COMPANY_CODE,
a.FISCAL_YEAR,
a.ACCOUNTING_DOCUMENT
),
source_events AS (
SELECT
e.INV_DOC_NO AS InvoiceNumber,
e.COMPANY_CODE AS CompanyCode,
e.FISCAL_YEAR AS FiscalYear,
e.EVENT_TIMESTAMP AS EventTime,
e.EVENT_USER AS UserName,
e.PAYMENT_BLOCK_REASON AS PaymentBlockReason,
e.PURCHASING_DOCUMENT AS PurchasingDocument,
e.VENDOR_NO AS VendorNumber,
e.AMOUNT_IN_COMPANY_CODE_CURRENCY AS AmountInCompanyCodeCurrency,
e.PAYMENT_DUE_DATE AS PaymentDueDate,
e.DOCUMENT_TYPE AS DocumentType,
e.EVENT_TYPE AS SourceEventType
FROM [Your verified invoice event and workflow source] e
WHERE e.EVENT_TIMESTAMP >= '[Start timestamp]'
AND e.EVENT_TIMESTAMP < '[End timestamp]'
AND e.COMPANY_CODE IN ([Company code filter])
),
base_events AS (
SELECT
i.InvoiceNumber,
'Invoice Document Created' AS ActivityName,
i.InvoiceCreatedAt AS EventTime,
i.InvoiceCreatedBy AS UserName,
i.CompanyCode,
COALESCE(i.VendorNumber, j.VendorNumber) AS VendorNumber,
COALESCE(i.AmountInCompanyCodeCurrency, j.AmountInCompanyCodeCurrency) AS AmountInCompanyCodeCurrency,
i.PaymentDueDate,
i.DocumentType,
CAST(NULL AS NVARCHAR(20)) AS PaymentBlockReason,
COALESCE(i.PurchasingDocument, j.PurchasingDocument) AS PurchasingDocument
FROM invoice_base i
LEFT JOIN posted_accounting p
ON p.InvoiceNumber = i.InvoiceNumber
AND p.CompanyCode = i.CompanyCode
AND p.FiscalYear = i.FiscalYear
LEFT JOIN journal_attributes j
ON j.CompanyCode = p.CompanyCode
AND j.FiscalYear = p.FiscalYear
AND j.AccountingDocument = p.AccountingDocument
WHERE i.InvoiceCreatedAt IS NOT NULL
UNION ALL
SELECT
s.InvoiceNumber,
'Invoice Parked' AS ActivityName,
s.EventTime,
s.UserName,
s.CompanyCode,
COALESCE(s.VendorNumber, i.VendorNumber) AS VendorNumber,
COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency) AS AmountInCompanyCodeCurrency,
COALESCE(s.PaymentDueDate, i.PaymentDueDate) AS PaymentDueDate,
COALESCE(s.DocumentType, i.DocumentType) AS DocumentType,
s.PaymentBlockReason,
COALESCE(s.PurchasingDocument, i.PurchasingDocument) AS PurchasingDocument
FROM source_events s
LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PARKED'
UNION ALL
SELECT s.InvoiceNumber, 'Invoice Sent For Approval', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'SENT_FOR_APPROVAL'
UNION ALL
SELECT s.InvoiceNumber, 'Invoice Approved', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'APPROVED'
UNION ALL
SELECT s.InvoiceNumber, 'Invoice Rejected', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'REJECTED'
UNION ALL
SELECT s.InvoiceNumber, 'Invoice Data Updated', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'DATA_UPDATED'
UNION ALL
SELECT s.InvoiceNumber, 'Payment Block Set', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_BLOCK_SET'
UNION ALL
SELECT s.InvoiceNumber, 'Payment Block Removed', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_BLOCK_REMOVED'
UNION ALL
SELECT
i.InvoiceNumber,
'Invoice Posted',
p.PostedAt,
p.PostedBy,
i.CompanyCode,
COALESCE(i.VendorNumber, j.VendorNumber),
COALESCE(i.AmountInCompanyCodeCurrency, j.AmountInCompanyCodeCurrency),
i.PaymentDueDate,
i.DocumentType,
CAST(NULL AS NVARCHAR(20)),
COALESCE(i.PurchasingDocument, j.PurchasingDocument)
FROM invoice_base i
INNER JOIN posted_accounting p ON p.InvoiceNumber = i.InvoiceNumber AND p.CompanyCode = i.CompanyCode AND p.FiscalYear = i.FiscalYear
LEFT JOIN journal_attributes j ON j.CompanyCode = p.CompanyCode AND j.FiscalYear = p.FiscalYear AND j.AccountingDocument = p.AccountingDocument
WHERE p.PostedAt IS NOT NULL
UNION ALL
SELECT s.InvoiceNumber, 'Payment Proposal Created', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_PROPOSAL_CREATED'
UNION ALL
SELECT s.InvoiceNumber, 'Payment Executed', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_EXECUTED'
UNION ALL
SELECT s.InvoiceNumber, 'Late Payment Executed', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_EXECUTED'
AND s.EventTime > CAST(COALESCE(s.PaymentDueDate, i.PaymentDueDate) AS TIMESTAMP)
UNION ALL
SELECT
i.InvoiceNumber,
'Invoice Reversed',
p.ReversalEventAt,
p.ReversalUser,
i.CompanyCode,
COALESCE(i.VendorNumber, j.VendorNumber),
COALESCE(i.AmountInCompanyCodeCurrency, j.AmountInCompanyCodeCurrency),
i.PaymentDueDate,
i.DocumentType,
CAST(NULL AS NVARCHAR(20)),
COALESCE(i.PurchasingDocument, j.PurchasingDocument)
FROM invoice_base i
INNER JOIN [Your verified reversal event source] p ON p.INV_DOC_NO = i.InvoiceNumber AND p.COMPANY_CODE = i.CompanyCode AND p.FISCAL_YEAR = i.FiscalYear
LEFT JOIN journal_attributes j ON j.CompanyCode = p.COMPANY_CODE AND j.FiscalYear = p.FISCAL_YEAR AND j.AccountingDocument = p.ACCOUNTING_DOCUMENT
WHERE p.ReversalEventAt IS NOT NULL
)
SELECT
InvoiceNumber,
ActivityName,
EventTime,
UserName,
CompanyCode,
VendorNumber,
AmountInCompanyCodeCurrency,
PaymentDueDate,
DocumentType,
PaymentBlockReason,
PurchasingDocument
FROM base_events
WHERE InvoiceNumber IS NOT NULL
AND EventTime IS NOT NULL
ORDER BY InvoiceNumber, EventTime, ActivityName; ステップ
- ABAPエディターを開く:SAP S/4HANAシステムにログインし、トランザクション
SE38(ABAPエディター)を開きます。 - プログラムを作成する:プログラム欄に新しいプログラム名(例:
Z_PM_INVOICE_EXTRACT)を入力し、「作成」をクリックします。タイトルを入力し、タイプを「実行可能プログラム」に設定して、適切なパッケージに保存します。 - プログラム構成と選択画面を定義する:エディターで、最終的なイベントログ出力用のデータ構造を定義します。次に、請求書の入力日、会社コード、伝票タイプなどの期間や条件をユーザーが指定できる選択画面を作成します。これにより、プログラムを繰り返し柔軟に利用できます。
- データ選択ロジックを実装する:複数のSAPテーブルからデータを選択するABAP SQL文を記述します。プログラムでは、必要な13種類のアクティビティごとに順次クエリを実行します。
- ヘッダーと明細データを抽出する:「Invoice Document Created」や「Invoice Posted」などの基本イベントについては、
RBKP(ロジスティクス請求書ヘッダー)やBKPF(会計伝票ヘッダー)などの主要テーブルからデータを選択します。 - 変更伝票データを抽出する:「Payment Block Set」や「Payment Block Removed」などのアクティビティについては、変更伝票テーブル
CDHDR(変更伝票ヘッダー)とCDPOS(変更伝票明細)を検索します。たとえば、テーブルBSEGのZLSPRなど、特定のフィールドに対する変更を特定する必要があります。 - 支払データを抽出する:支払関連のアクティビティを取得するには、支払提案用の
REGUP(支払プログラムの処理済み明細)や、実行済み支払用のBSAK(消込済み仕入先明細)などのテーブルを検索します。消込日(AUGDT)と正味支払期日(ZFBDT)を比較して、「Late Payment Executed」を区別します。 - ワークフローデータを抽出する:承認アクティビティについては、
SWW_WI2OBJなどのSAP Business Workflowテーブルを検索し、ワークフロー項目と請求書オブジェクトを関連付けます。この処理はワークフローの設定に大きく依存するため、相応の調整が必要になる場合があります。 - データをイベントログ形式に統合する:選択した各アクティビティのデータを、共通の内部テーブル構造に整形します。テーブルの各行は1つのイベントを表し、ケース識別子(
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の各テーブルに対する広範な読み取り権限が必要です。
クエリの例 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. 準備はできましたか?
今日から請求書処理の改善を始めましょう。このテンプレートを使って、業務の大幅な改善と効率向上に向けた第一歩を踏み出せます。
SAP S/4HANAの請求書処理を今すぐ改善
ボトルネックを特定し、請求書処理のサイクルタイムを30%以上短縮しましょう。
クレジットカード不要。数分で設定できます。