Data Template: Accounts Payable Invoice Processing
Your Accounts Payable Invoice Processing Data Template
- Recommended attributes for comprehensive analysis
- Key process activities to track effectively
- Step-by-step data extraction guidance
Accounts Payable Invoice Processing Attributes
| Name | Description | ||
|---|---|---|---|
Activity ActivityName | The name of a specific business event or step that occurred in the invoice processing lifecycle. | ||
Description The Activity represents a distinct stage or action within the Accounts Payable process, such as 'Invoice Received', 'Invoice Posted', or 'Payment Executed'. These are the building blocks of the process map. Analyzing activities is core to process mining. It helps visualize the process flow, identify common pathways, detect deviations from the standard process, and measure the frequency and duration of each step. The sequence of these activities for a given invoice forms its process journey. Why it matters It defines the steps of the process, allowing for the visualization and analysis of the process flow, identification of bottlenecks, and detection of rework loops. Where to get Derived from various sources including document status changes (e.g., BKPF-BSTAT), change documents (CDHDR/CDPOS tables), or workflow logs. This typically requires a custom extraction logic. Examples Invoice ReceivedInvoice ApprovedPayment ExecutedInvoice Blocked For Payment | |||
Event Time EventTime | The exact date and time when the activity occurred. | ||
Description Event Time is the timestamp associated with each activity, providing the chronological sequence of events for an invoice. This data is essential for understanding the process flow and performing any time-based analysis. In analysis, Event Time is used to order activities correctly, calculate cycle times between different steps, identify waiting times, and analyze process performance over different time periods (e.g., month-over-month). It is the foundation of all duration-based KPIs. Why it matters This timestamp is critical for ordering events chronologically and calculating all time-based metrics, such as cycle times and durations, which are fundamental to process mining. Where to get Sourced from various date/time fields across SAP tables, such as Creation Date (BKPF-CPUDT), Posting Date (BKPF-BUDAT), Clearing Date (BSAK-AUGDT), or change log timestamps (CDHDR-UDATE/UTIME). Examples 2023-10-01T09:00:00Z2023-10-05T14:30:15Z2023-10-15T11:21:05Z | |||
Invoice Invoice | The unique identifier for an invoice document, serving as the primary case ID for the Accounts Payable process. | ||
Description The Invoice is the central object that connects all related activities, from receipt to payment. In SAP S/4HANA, this is typically a composite key formed by the Company Code (BUKRS), a unique Document Number (BELNR), and the Fiscal Year (GJAHR). Analyzing by Invoice allows for a complete end-to-end view of the invoice lifecycle. This is fundamental for calculating key metrics like total cycle time, identifying bottlenecks for individual invoices, and understanding the different paths an invoice can take through the process. Why it matters It uniquely identifies each invoice's journey, making it possible to trace its full lifecycle and analyze process performance on a case-by-case basis. Where to get This is a composite key derived from tables BKPF (Accounting Document Header) or RBKP (Document Header: Invoice Receipt) using fields BUKRS, BELNR, and GJAHR. Examples 1000-1900000001-20231710-1900000002-20232000-5100000003-2024 | |||
Last Data Update LastDataUpdate | The timestamp indicating when the data for this record was last refreshed from the source system. | ||
Description This attribute provides the date and time of the most recent data extraction or update from SAP S/4HANA. It is a metadata field that is critical for understanding the freshness of the data being analyzed. This information is important for users to know how current the process analysis is. It helps in managing expectations about data latency and is vital for scheduling data refreshes and maintaining data integrity. Why it matters Indicates the freshness of the data, ensuring users are aware of how up-to-date their process analysis is. Where to get This value is generated and stamped on each record at the time of data extraction from the source system. Examples 2024-05-20T04:00:00Z2024-05-21T04:00:00Z | |||
Source System SourceSystem | The system from which the data was extracted. | ||
Description This attribute identifies the origin of the process data. For this view, the value will typically be 'SAP S/4HANA'. In environments with multiple ERPs or integrated systems, this field is crucial for data lineage and segregation. It ensures that analysis is performed on the correct dataset and helps in diagnosing data quality issues by tracing them back to the source. Why it matters Identifies the data's origin, which is crucial for data governance, troubleshooting, and in multi-system environments. Where to get This is typically a static value added during the data extraction process to label the dataset's origin. Examples SAP S/4HANASAP ECC 6.0S4H_PROD_100 | |||
Company Code CompanyCode | The organizational unit for which the invoice is processed. | ||
Description A Company Code is the smallest organizational unit for which a complete, self-contained set of accounts can be drawn up for external reporting. In the context of AP, it represents the legal entity that owes money to the vendor. Analyzing by Company Code allows for comparison of process performance across different legal entities within the organization. This helps identify which parts of the business are following standard processes and which have higher efficiency, longer cycle times, or higher rework rates. Why it matters Enables process performance comparison across different legal entities, helping to identify regional or business unit-specific issues and best practices. Where to get Found in document header tables, primarily BKPF-BUKRS for FI invoices and RBKP-BUKRS for MM invoices. Examples 10001710US01DE01 | |||
Invoice Amount InvoiceAmount | The total gross amount of the invoice in the original document currency. | ||
Description This is the total value of the invoice as submitted by the vendor. It includes the cost of goods or services, taxes, and any other charges, before any deductions or discounts. Invoice Amount is a critical financial attribute used for a wide range of analyses. It helps in prioritizing high-value invoices, understanding the financial impact of process delays (e.g., late fees on large invoices), and segmenting the process (e.g., 'Do high-value invoices follow a different approval path?'). It is also essential for identifying potential duplicate payments. Why it matters Provides financial context to the process, enabling value-based analysis, prioritization of high-value invoices, and quantification of financial impacts. Where to get Found in tables like RBKP-RMWWR (Gross invoice amount) for MM invoices or calculated from line items in BSEG (field WRBTR) for FI invoices. Examples 1500.00250.7512345.50 | |||
Invoice Due Date InvoiceDueDate | The date by which the invoice payment is due to the vendor. | ||
Description The Invoice Due Date is the deadline for paying the vendor to avoid late payment fees and maintain a good supplier relationship. This date is calculated based on the invoice's baseline date and the payment terms agreed upon with the vendor. This date is essential for the 'Payment Compliance & Aging' dashboard and the 'On-Time Payment Rate' KPI. By comparing the due date with the actual payment date, the analysis can reveal whether payments are being made on time, early, or late, which has direct financial and relational consequences. Why it matters This is the primary driver for on-time payment analysis, enabling the measurement of payment performance and its impact on vendor relationships and late fees. Where to get This date is often calculated. The net due date is in field BSEG-NETDT. It can also be derived from the baseline date for payment (BSEG-ZFBDT) and payment terms (BSEG-ZTERM). Examples 2023-10-312023-11-152024-01-10 | |||
Purchase Order Number PurchaseOrderNumber | The unique identifier of the purchase order associated with the invoice, if applicable. | ||
Description This attribute links an invoice to a pre-approved purchase order (PO). The presence of a PO number is the basis for the 3-way match process (PO-Invoice-Goods Receipt). This is a vital attribute for compliance and efficiency analysis. It is used to calculate the 'PO-Less Invoice Percentage' KPI, which measures adherence to procurement policies. It is also fundamental to the '3-Way Matching Performance' dashboard, allowing analysis of the matching process for PO-backed invoices. Why it matters Crucial for analyzing 3-way matching efficiency and measuring compliance with procurement policies by identifying invoices processed without a PO. Where to get Found in the invoice line item tables, such as RSEG-EBELN (for MM invoices) or BSEG-EBELN (for FI invoices). Examples 45000012344500005678 | |||
User Name UserName | The user ID of the person who performed the activity. | ||
Description This attribute records the SAP user ID responsible for executing a specific activity, such as posting, approving, or clearing an invoice. It links process steps to individual users. Analyzing by User Name is essential for understanding workload distribution, identifying top performers, and pinpointing users who may require additional training. It is also key for analyzing approval bottlenecks in dashboards, as it helps identify which specific approvers are causing delays in the process. Why it matters Attributes activities to specific individuals, enabling analysis of user performance, workload, and compliance with segregation of duties policies. Where to get Typically found in header tables like BKPF-USNAM (Entered by) or in change document tables CDHDR-USERNAME (Changed by). Examples ABROWNJSMITHAP_AUTOMATION | |||
Vendor Name VendorName | The name of the vendor who submitted the invoice. | ||
Description This attribute contains the official name of the supplier or vendor. It is linked via the Vendor Number stored on the invoice document. Vendor analysis is crucial for managing supplier relationships and identifying process issues specific to certain vendors. It can help answer questions like 'Which vendors submit the most invoices with discrepancies?' or 'Are we consistently paying certain strategic vendors on time?'. It is also a key field, along with invoice number and amount, for detecting potential duplicate payments. Why it matters Allows for analysis of process performance by supplier, helping to identify problematic vendors and manage strategic supplier relationships effectively. Where to get Retrieved from the vendor master data table LFA1 (field NAME1), by linking via the Vendor Number (LIFNR) found in BKPF or RBKP. Examples Office Supplies Inc.Global Consulting GroupMachine Parts GmbH | |||
Blocking Reason BlockingReason | The reason why an invoice is blocked for payment, indicating a discrepancy. | ||
Description When an invoice fails a validation check during the 3-way match or other verification steps, it is blocked for payment. The Blocking Reason specifies the nature of the issue, such as a quantity discrepancy, price variance, or missing goods receipt. This attribute is critical for the 'Invoice Discrepancy Rework Analysis' dashboard. Analyzing the frequency of different blocking reasons helps to identify the root causes of process inefficiencies. For example, if 'Price variance' is a common reason, it may point to issues with master data in the purchasing system. Why it matters Provides direct insight into the root causes of invoice discrepancies and rework, enabling targeted process improvement efforts. Where to get Stored in invoice line item tables like RSEG, in fields starting with SPGR* (e.g., SPGRP, SPGRQ, SPGRT). Can also be found in RBKP_BLOCKED. Examples Price DiscrepancyQuantity DiscrepancyMissing Goods Receipt | |||
Clearing Date ClearingDate | The date on which a payment was made and the invoice was cleared from open items. | ||
Description The Clearing Date signifies the financial settlement of the invoice. It is the date the 'Payment Cleared' activity occurs, marking the final step for most successful invoice journeys. This date is used to calculate the actual payment date for comparison against the Invoice Due Date. It is therefore essential for calculating the 'On-Time Payment Rate' KPI and for any analysis related to payment performance. It also marks the end point for calculating the end-to-end invoice cycle time. Why it matters Marks the final settlement of an invoice, serving as the end point for cycle time calculations and the basis for on-time payment analysis. Where to get Found in the tables for cleared items, such as BSAK-AUGDT for vendors. Examples 2023-10-282023-11-142024-01-09 | |||
Discount Taken DiscountTaken | A boolean flag indicating if an early payment discount was successfully applied. | ||
Description This attribute indicates whether a cash discount was actually taken when the invoice was paid. It is a critical component for measuring financial efficiency in the AP process. This flag is the core of the 'Early Payment Discount Capture Rate' KPI. By filtering for invoices where a discount was possible (based on Payment Terms) and then analyzing this flag, a business can precisely calculate how much money was saved and how many saving opportunities were missed. This provides a clear, quantifiable measure of AP performance. Why it matters Directly measures the success in capturing available early payment discounts, which has a direct impact on the company's bottom line. Where to get Derived by checking if the discount amount field (BSEG-SKNTO) is greater than zero on the payment document. Examples truefalse | |||
Invoice Currency InvoiceCurrency | The currency code for the invoice amount (e.g., USD, EUR). | ||
Description This attribute specifies the currency in which the Invoice Amount is denominated. It provides essential context for any financial values. In a multi-national organization, analyzing invoices without considering their currency can be misleading. This field allows for proper handling of financial data, either by converting all amounts to a single reporting currency or by segmenting the analysis by currency to understand regional financial activities. Why it matters Provides necessary context for the Invoice Amount, enabling accurate financial analysis and reporting, especially in multi-national contexts. Where to get Found in document header tables, primarily BKPF-WAERS or RBKP-WAERS. Examples USDEURGBPJPY | |||
Invoice Document Type InvoiceDocumentType | A classification of the invoice document, which controls how it is processed in SAP. | ||
Description The Document Type is a key configuration element in SAP that categorizes accounting documents. For example, 'KR' is typically used for vendor invoices, 'RE' for MM invoices, and 'KG' for vendor credit memos. This type determines things like the number range and which fields are required. In process analysis, filtering by Document Type allows for comparing the process flows for different kinds of invoices. For instance, the approval process for a credit memo might be different from that of a standard invoice. This is useful for the 'Invoice Approval Routing Variants' dashboard. Why it matters Allows for the segmentation of the process based on how different invoice types are handled, revealing variations in processing paths and cycle times. Where to get Directly from the document header table, field BKPF-BLART. Examples KRREKG | |||
Is Automated IsAutomated | A flag indicating if the activity was performed automatically by the system rather than by a human user. | ||
Description This boolean attribute distinguishes between human-initiated activities and those executed by system jobs, workflows, or bots. For example, an automated payment run or a system-generated invoice posting would be flagged as automated. Analyzing this attribute helps in understanding the level of automation in the Accounts Payable process. It can be used to measure the success of automation initiatives, compare the efficiency of automated vs. manual steps, and identify further opportunities for automation. Why it matters Helps measure the degree of automation in the process, enabling analysis of automation effectiveness and identifying opportunities for further improvement. Where to get Derived based on the User Name (e.g., system user IDs like 'SAP_SYSTEM' or 'BATCHUSER') or specific transaction codes associated with automated jobs. Examples truefalse | |||
Is Late Payment IsLatePayment | A boolean flag indicating if the invoice was paid after its due date. | ||
Description This calculated attribute is a simple true/false flag that indicates whether an invoice's payment was made after its official due date. It is derived by comparing the 'Clearing Date' to the 'Invoice Due Date'. This flag simplifies analysis for the 'Payment Compliance & Aging' dashboard and the 'On-Time Payment Rate' KPI. It allows for easy filtering and aggregation to count the number of late payments, calculate the percentage of on-time payments, and identify vendors or company codes with high rates of late payments. Why it matters Directly measures compliance with payment terms, simplifies on-time payment KPI calculation, and helps identify areas with poor payment performance. Where to get Calculated attribute. The logic is: IF ClearingDate > InvoiceDueDate THEN true ELSE false. Examples truefalse | |||
Payment Terms PaymentTerms | The conditions agreed upon with the vendor for paying an invoice, often including discount opportunities. | ||
Description Payment Terms define the rules for payment due dates and potential early payment discounts. For example, a term like 'Z001' might correspond to 'Payable within 30 days, 2% discount if paid in 10 days'. This attribute is the foundation for the 'Early Payment Discount Capture Rate' dashboard. By analyzing the payment terms, it's possible to identify all invoices that were eligible for a discount. Comparing this with the actual discounts taken reveals missed savings opportunities and measures the efficiency of the payment process. Why it matters It is essential for analyzing early payment discount opportunities, measuring the financial performance of the payment process, and identifying missed savings. Where to get Found in vendor line items, table BSEG-ZTERM, or on the invoice header in RBKP-ZTERM. Examples Z0010001NT30 | |||
Processing Time ProcessingTime | The duration of a single activity. | ||
Description Processing Time, or activity duration, is the time elapsed between the start and end of an activity. This metric is calculated from the event log data. This calculated measure is crucial for the 'Activity Duration & Rework Heatmap' dashboard. It helps pinpoint which specific steps in the process consume the most time. Analyzing processing times can highlight inefficiencies, such as long approval steps or lengthy discrepancy resolution activities, guiding targeted improvement efforts. Why it matters Quantifies the time spent on individual activities, helping to identify the most time-consuming steps and bottlenecks in the process. Where to get Calculated by finding the difference between the EventTime of the current activity and the EventTime of the subsequent activity for the same invoice. Examples P2DT3H4MPT5HP7D | |||
Vendor Invoice Number VendorInvoiceNumber | The invoice number provided by the vendor on their document. | ||
Description This is the reference number from the vendor's own accounting system, as printed on the physical or electronic invoice document. It is manually entered or captured via OCR during invoice receipt. This field is extremely important for operational purposes and for analysis, particularly for the 'Potential Duplicate Invoice Payments' dashboard. A common method for detecting duplicates is to search for multiple internal invoice documents that share the same Vendor Name, Vendor Invoice Number, and Invoice Amount. It is the primary external reference for an invoice. Why it matters It's a key field for detecting potential duplicate payments and serves as the primary external reference for communicating with vendors. Where to get Stored in the 'Reference' field on the document header, typically BKPF-XBLNR. Examples INV-2023-9876733401120231015-001 | |||
Accounts Payable Invoice Processing Activities
| Activity | Description | ||
|---|---|---|---|
Invoice Approved | The invoice has received all necessary approvals within the workflow system. This is often the final step before an invoice can be posted or unblocked for payment. | ||
Why it matters This key milestone marks the end of the approval cycle. The time between routing and approval is a critical metric for efficiency. Where to get Captured from SAP Business Workflow logs as a completion or final release step. Alternatively, it can be inferred from the removal of a payment block post-routing. Capture Extract workflow completion events from SAP workflow logs or identify the final 'release' event. Event type explicit | |||
Invoice Blocked For Payment | The system has automatically or manually placed a block on the invoice, preventing it from being paid. This is typically due to discrepancies in price, quantity, or missing approvals. | ||
Why it matters This is a key indicator of problems and rework. Analyzing block reasons and durations helps identify the root causes of payment delays and process inefficiencies. Where to get This is an explicit status recorded in the Payment Block Key field (ZLSPR) on the vendor line item of the accounting document (table BSEG). Capture Logged via change documents when the BSEG-ZLSPR field is populated with a block reason. Event type explicit | |||
Invoice Cancelled | The invoice document has been reversed, effectively nullifying its financial impact. This is an alternative end-state for the process, often due to incorrect entries or supplier disputes. | ||
Why it matters Tracking cancellations helps identify reasons for process failures, such as duplicate submissions or incorrect invoice data, which can point to upstream issues. Where to get This is explicitly recorded when a reversal document is created. The original document header (BKPF) will have the reversal document number (STBLG) and reversal reason populated. Capture Identify the posting date of the reversal document, which is linked in the original document's header (BKPF-STBLG). Event type explicit | |||
Invoice Posted | The invoice is formally recorded in the General Ledger, creating a financial liability. A parked document becomes a posted document, or a direct posting is made. | ||
Why it matters This is a critical financial milestone. It confirms the company's obligation to pay and is often a prerequisite for scheduling payment. Where to get This event is identified by the Posting Date (BUDAT) in the document header (BKPF). A posted document has a document status (BKPF-BSTAT) that is blank. Capture Use the posting timestamp (BKPF-BUDAT) for documents that are not parked (BKPF-BSTAT is blank). Event type explicit | |||
Invoice Received | This activity marks the creation of an invoice document in SAP, either manually or through an automated interface like OCR/VIM. This event is typically captured from the creation date and time of the accounting document header. | ||
Why it matters As the starting point of the process, this activity is essential for calculating the end-to-end invoice cycle time and measuring the throughput of the entire AP process. Where to get This event is captured from the accounting document header table (BKPF), using the document creation date (CPUDT) and time (CPUTM). Capture Use creation timestamp (BKPF-CPUDT, BKPF-CPUTM) for the invoice document. Event type explicit | |||
Payment Cleared | This activity marks the final closure of the invoice, where the payment and the invoice are reconciled against each other in the sub-ledger. This signifies the process is complete. | ||
Why it matters As the definitive end of the process, this activity is essential for accurate end-to-end cycle time calculation. It confirms the liability is settled. Where to get This is an explicit event marked by the Clearing Date (AUGDT) field being populated on the vendor line item of the invoice document (table BSEG). Capture Use the clearing date (BSEG-AUGDT) from the invoice line item. Event type explicit | |||
Payment Executed | A payment has been made against the invoice. This is captured when the payment run is completed and a payment document is created and posted. | ||
Why it matters This activity is crucial for cash flow analysis and for measuring the 'On-Time Payment Rate' KPI by comparing this date to the invoice due date. Where to get This is captured from the posting date of the payment document which clears the invoice. The payment document number is linked in the clearing document field (AUGBL) of the invoice line item (BSEG). Capture Identify the posting date (BUDAT) of the payment document that clears the invoice line item. Event type explicit | |||
Discrepancy Resolved | This activity indicates that a previously identified issue, which likely caused a payment block, has been investigated and resolved. This is captured when a payment block is removed from an invoice. | ||
Why it matters Tracking this rework loop is crucial for the 'Invoice Discrepancy Rework Analysis' dashboard. It helps quantify the time and effort spent on fixing errors. Where to get This is inferred from change documents showing the removal of a payment block. The change log for the BSEG-ZLSPR field is the primary source. Capture Identify change documents for table BSEG where the ZLSPR field is changed from a value to blank. Event type inferred | |||
Goods Receipt Matched | This activity signifies that the invoice quantities and values have been successfully matched to a corresponding goods receipt document. This is the final validation in a 3-way matching scenario. | ||
Why it matters Tracking this helps pinpoint inefficiencies in the 3-way matching process and identify discrepancies between goods received and what is being invoiced by the supplier. Where to get This is inferred from the presence of a material document reference (goods receipt) on the invoice line item, often linked through the purchase order item history. Capture Inferred from the presence of a Goods Receipt document reference on the invoice line item (e.g., in RSEG for MIRO invoices). Event type inferred | |||
Invoice Due Date Passed | A calculated event indicating that the invoice's net due date has passed without a payment being cleared against it. This signifies a late or overdue payment situation. | ||
Why it matters Essential for the 'Payment Compliance & Aging' dashboard, this activity helps to proactively identify and manage overdue invoices and analyze root causes for late payments. Where to get This is not an explicit event in SAP. It is calculated by comparing the system's current date against the Net Due Date (calculated from BSEG-ZFBDT or baseline date and payment terms). Capture Calculated event triggered when the event timestamp is greater than the invoice net due date. Event type calculated | |||
Invoice Parked | Represents an invoice that has been entered into the system but not yet posted to the general ledger. This is often an intentional step to save an incomplete document for later processing or approval. | ||
Why it matters Tracking parked invoices helps identify delays before the formal posting process begins and can highlight issues with data completeness or initial validation. Where to get This status is inferred from the document status field in the accounting document header (BKPF-BSTAT = 'V' for Parked). The event occurs when the status is set. Capture Identify change documents for table BKPF where the BSTAT field is set to 'V' (Vor-erfasst/Pre-entered). Event type inferred | |||
Invoice Rejected | An approver has rejected the invoice during the approval workflow. This action typically sends the invoice back to the processor for correction or clarification. | ||
Why it matters Tracking rejections highlights rework loops within the approval process and can indicate issues with policy compliance or incorrect invoice coding. Where to get This is captured as a specific outcome event within the SAP Business Workflow logs associated with the invoice. Capture Extract workflow 'rejected' status events from SAP workflow logs. Event type explicit | |||
Invoice Routed For Approval | The invoice has been submitted into a workflow for required approvals based on business rules. This marks the beginning of the approval sub-process. | ||
Why it matters This activity is the starting point for measuring the 'Average Invoice Approval Time' KPI and analyzing approval bottlenecks. Where to get Can be captured from SAP Business Workflow logs (SWW* tables) which record the start of a workflow instance linked to the invoice object (e.g., BUS2081). Capture Extract workflow start events from SAP workflow logs (e.g., table SWW_WIHEAD) linked to the invoice document. Event type explicit | |||
Payment Proposal Created | The invoice has been included in a payment proposal as part of a payment run (e.g., F110). It is now slated for payment pending final execution of the run. | ||
Why it matters This activity shows the transition from an open liability to an item actively being prepared for payment, helping to analyze the efficiency of payment operations. Where to get This event is explicitly logged in the payment run data tables, specifically REGUP (Processed Items from Payment Program) and REGUH (Header). Capture Identify when an invoice appears in table REGUP for a payment run identified in REGUH. Event type explicit | |||
Purchase Order Matched | This activity signifies that the invoice has been successfully matched to a corresponding purchase order. This is a critical step in the 3-way matching process for procurement-based invoices. | ||
Why it matters Analyzing this activity helps measure the efficiency of the matching process and is fundamental for the '3-Way Matching Performance' and 'PO-Less Invoice Percentage' KPIs. Where to get This is inferred when an invoice line item in table BSEG or ACDOCA contains a valid Purchase Order number (EBELN) and item (EBELP). Capture Inferred from the presence of a Purchase Order reference (BSEG-EBELN) on the invoice document upon creation. Event type inferred | |||
Extraction Guides
Steps
- Prerequisites and Access: Ensure you have a user with read access to the SAP S/4HANA database schema (typically
SAPABAP1or similar) where the CDS views reside. You will need an SQL client tool that can connect to the SAP HANA database, such as SAP HANA Studio, DBeaver, or similar database query tools. - Identify Core CDS Views: The primary CDS views for this extraction are
I_JournalEntry,I_JournalEntryItem,I_SupplierInvoiceAPI01,I_ChangeDocument,I_WorkflowStatusDetails, andI_PaymentProposalItem. Familiarize yourself with their key fields. - Define Query Scope: Open your SQL client and connect to the SAP HANA database. Before running the full query, define the scope of your extraction. This involves setting the correct source system identifier, the date range for invoices (
CreationDateTime), and the relevant Company Codes. - Prepare the Main Query: Copy the complete SQL query provided in the
querysection into your SQL client. The query uses Common Table Expressions (CTEs) to first select a base population of invoices and then constructs an event log by uniting data for 15 different activities. - Set Query Parameters: In the copied SQL query, locate the placeholder variables. Replace
'[YYYY-MM-DD]'with the start and end dates for your analysis period. Replace'[Your Company Code 1]', '[Your Company Code 2]'with the list of SAP Company Codes you wish to analyze. - Execute the Extraction Query: Run the complete SQL query. Depending on the data volume and the selected date range, this may take several minutes to several hours to complete.
- Review Preliminary Results: Once the query finishes, review the first few hundred rows of the output. Check for data consistency, ensure all columns are populated as expected, and verify that different
ActivityNamevalues are present. - Export the Event Log: Export the entire result set from your SQL client to a CSV file. Ensure the file is UTF-8 encoded to prevent character issues. Name the file descriptively, for example,
sap_s4hana_ap_event_log.csv. - Prepare for Upload: Before uploading to a process mining tool, confirm that the column headers in the CSV file exactly match the required attribute names:
Invoice,ActivityName,EventTime,SourceSystem,LastDataUpdate,UserName, etc. - Upload to Process Mining Tool: Upload the generated CSV file to your process mining platform, mapping the columns to the corresponding case ID, activity, and timestamp fields.
Configuration
- Key CDS Views: The extraction relies on a combination of standard S/4HANA CDS Views. The primary views are:
I_JournalEntry&I_JournalEntryItem: For core financial document headers, items, posting details, and clearing information.I_SupplierInvoiceAPI01: For MM (Logistics) invoice-specific details, including PO references and payment blocks.I_ChangeDocument: To track the exact timestamp of changes, such as setting or removing a payment block.I_WorkflowStatusDetails: To extract events related to the invoice approval workflow.I_PaymentProposalItem: To identify when an invoice is included in a payment run proposal.I_Supplier: To enrich the data with vendor master information likeVendorName.
- Date Range Filtering: It is critical to apply a date range filter to limit the data volume. The provided query filters on
CreationDateTimein theInvoices_BaseCTE. A range of 3-6 months is recommended for an initial analysis to ensure manageable performance. - Mandatory Filters: Always filter by
CompanyCode. Analyzing data across all company codes at once can be extremely slow and may not be business-relevant. Also, filter onJournalEntryTypeto select only vendor-related documents (e.g., 'KR', 'RE'). - Prerequisites: The executing database user must have
SELECTauthorization on all CDS views used in the query and on the underlying HANA schema. Application-level access in the SAP GUI is not sufficient. - Performance Considerations: Direct queries on
I_ChangeDocumentcan be resource-intensive. The provided query attempts to mitigate this by pre-filtering invoices first. For very large datasets, consider running the extraction during off-peak hours or in smaller date range batches.
a Sample Query sql
-- Common Table Expression (CTE) to select the base set of AP Invoices
WITH Invoices_Base AS (
SELECT
I_JournalEntry.CompanyCode,
I_JournalEntry.AccountingDocument,
I_JournalEntry.FiscalYear,
CONCAT(I_JournalEntry.CompanyCode, CONCAT(I_JournalEntry.AccountingDocument, I_JournalEntry.FiscalYear)) AS InvoiceId,
I_JournalEntry.CreationDateTime,
I_JournalEntry.CreatedByUser,
I_JournalEntry.DocumentStatus,
I_JournalEntry.JournalEntryType,
I_JournalEntry.ReversalReferenceJournalEntry,
I_JournalEntry.IsReversed,
I_JournalEntry.ReversalDate,
IJE_ITEM.NetDueDate,
IJE_ITEM.Supplier,
SUP.SupplierName AS VendorName,
IJE_ITEM.AmountInCompanyCodeCurrency AS InvoiceAmount,
MM.PurchaseOrder AS PurchaseOrderNumber,
MM.PaymentBlockingReason
FROM I_JournalEntry
-- Join to get item details like due date and supplier
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON I_JournalEntry.CompanyCode = IJE_ITEM.CompanyCode
AND I_JournalEntry.AccountingDocument = IJE_ITEM.AccountingDocument
AND I_JournalEntry.FiscalYear = IJE_ITEM.FiscalYear
AND IJE_ITEM.IsSupplier = 'X'
-- Join to get vendor name from master data
LEFT JOIN I_Supplier AS SUP
ON IJE_ITEM.Supplier = SUP.Supplier
-- Join to get MM Invoice specific data like PO Number and Payment Block
LEFT JOIN I_SupplierInvoiceAPI01 AS MM
ON I_JournalEntry.AccountingDocument = MM.AccountingDocument
AND I_JournalEntry.CompanyCode = MM.CompanyCode
AND I_JournalEntry.FiscalYear = MM.FiscalYear
WHERE
I_JournalEntry.JournalEntryType IN ('KR', 'RE') -- Standard Vendor Invoice Types
AND I_JournalEntry.CompanyCode IN ('[Your Company Code 1]', '[Your Company Code 2]')
AND I_JournalEntry.CreationDateTime BETWEEN '[YYYY-MM-DD]T00:00:00Z' AND '[YYYY-MM-DD]T23:59:59Z'
)
-- Event: 1. Invoice Received
SELECT
B.InvoiceId AS "Invoice",
'Invoice Received' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
UNION ALL
-- Event: 2. Invoice Parked
SELECT
B.InvoiceId AS "Invoice",
'Invoice Parked' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.DocumentStatus = 'V' -- 'V' stands for Parked
UNION ALL
-- Event: 3. Purchase Order Matched
SELECT
B.InvoiceId AS "Invoice",
'Purchase Order Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PurchaseOrderNumber IS NOT NULL AND B.PurchaseOrderNumber <> ''
UNION ALL
-- Event: 4. Goods Receipt Matched
SELECT
B.InvoiceId AS "Invoice",
'Goods Receipt Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_SupplierInvoiceItemAPI01 AS MM_ITEM
ON B.AccountingDocument = MM_ITEM.AccountingDocument
AND B.FiscalYear = MM_ITEM.FiscalYear
WHERE MM_ITEM.GoodsReceipt IS NOT NULL AND MM_ITEM.GoodsReceipt <> ''
UNION ALL
-- Event: 5. Invoice Blocked For Payment
SELECT
B.InvoiceId AS "Invoice",
'Invoice Blocked For Payment' AS "ActivityName",
B.CreationDateTime AS "EventTime", -- Approximates block time as creation time if blocked on entry
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PaymentBlockingReason IS NOT NULL AND B.PaymentBlockingReason <> ''
UNION ALL
-- Event: 6. Discrepancy Resolved (Payment Block Removed)
SELECT
B.InvoiceId AS "Invoice",
'Discrepancy Resolved' AS "ActivityName",
CD.ChangeTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CD.UserName AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_ChangeDocument AS CD
ON CONCAT(B.CompanyCode, B.AccountingDocument, B.FiscalYear) = CD.ObjectValue
WHERE CD.ChangeDocumentObject = 'INVOICE'
AND CD.TableName = 'RBKP'
AND CD.FieldName = 'ZLSPR' -- Field for Payment Block
AND CD.NewFieldValue = '' -- Block was removed
UNION ALL
-- Event: 7, 8, 9. Workflow Events (Routed, Approved, Rejected)
SELECT
B.InvoiceId AS "Invoice",
CASE WF.WorkflowStatus
WHEN 'READY' THEN 'Invoice Routed For Approval'
WHEN 'APPROVED' THEN 'Invoice Approved'
WHEN 'REJECTED' THEN 'Invoice Rejected'
END AS "ActivityName",
WF.WorkflowStatusChangedDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
WF.WorkflowStatusChangedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_WorkflowStatusDetails AS WF
ON B.InvoiceId = WF.WorkflowScenarioInstance
WHERE WF.WorkflowStatus IN ('READY', 'APPROVED', 'REJECTED')
UNION ALL
-- Event: 10. Invoice Posted
SELECT
B.InvoiceId AS "Invoice",
'Invoice Posted' AS "ActivityName",
JE.PostingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntry AS JE
ON B.AccountingDocument = JE.AccountingDocument
AND B.CompanyCode = JE.CompanyCode
AND B.FiscalYear = JE.FiscalYear
WHERE B.DocumentStatus <> 'V' -- Any status other than Parked is considered Posted for AP
UNION ALL
-- Event: 11. Payment Proposal Created
SELECT
B.InvoiceId AS "Invoice",
'Payment Proposal Created' AS "ActivityName",
PPI.PaymentProposalRunDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
PPI.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_PaymentProposalItem AS PPI
ON B.CompanyCode = PPI.CompanyCode
AND B.AccountingDocument = PPI.AccountingDocument
AND B.FiscalYear = PPI.FiscalYear
UNION ALL
-- Event: 12. Payment Executed
-- This links the invoice to its clearing document, which is the payment document
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Executed' AS "ActivityName",
CLEAR_JE.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CLEAR_JE.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
INNER JOIN I_JournalEntry AS CLEAR_JE
ON IJE_ITEM.ClearingJournalEntry = CLEAR_JE.AccountingDocument
AND IJE_ITEM.CompanyCode = CLEAR_JE.CompanyCode
WHERE IJE_ITEM.ClearingJournalEntry IS NOT NULL AND IJE_ITEM.ClearingJournalEntry <> ''
AND CLEAR_JE.JournalEntryType = 'KZ' -- Vendor Payment Document Type
UNION ALL
-- Event: 13. Invoice Due Date Passed
SELECT
B.InvoiceId AS "Invoice",
'Invoice Due Date Passed' AS "ActivityName",
ADD_DAYS(B.NetDueDate, 1) AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
'SYSTEM' AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE B.NetDueDate < CURRENT_DATE
AND IJE_ITEM.ClearingDate IS NULL -- Invoice is not yet cleared
UNION ALL
-- Event: 14. Payment Cleared
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Cleared' AS "ActivityName",
IJE_ITEM.ClearingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
IJE_ITEM.ChangedByUser AS "UserName", -- User who cleared it
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE IJE_ITEM.ClearingDate IS NOT NULL
UNION ALL
-- Event: 15. Invoice Cancelled
SELECT
B.InvoiceId AS "Invoice",
'Invoice Cancelled' AS "ActivityName",
B.ReversalDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName", -- User who created the original document
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.IsReversed = 'X';Steps
- Prerequisites and Access: Ensure you have a user with read access to the SAP S/4HANA database schema (typically
SAPABAP1or similar) where the CDS views reside. You will need an SQL client tool that can connect to the SAP HANA database, such as SAP HANA Studio, DBeaver, or similar database query tools. - Identify Core CDS Views: The primary CDS views for this extraction are
I_JournalEntry,I_JournalEntryItem,I_SupplierInvoiceAPI01,I_ChangeDocument,I_WorkflowStatusDetails, andI_PaymentProposalItem. Familiarize yourself with their key fields. - Define Query Scope: Open your SQL client and connect to the SAP HANA database. Before running the full query, define the scope of your extraction. This involves setting the correct source system identifier, the date range for invoices (
CreationDateTime), and the relevant Company Codes. - Prepare the Main Query: Copy the complete SQL query provided in the
querysection into your SQL client. The query uses Common Table Expressions (CTEs) to first select a base population of invoices and then constructs an event log by uniting data for 15 different activities. - Set Query Parameters: In the copied SQL query, locate the placeholder variables. Replace
'[YYYY-MM-DD]'with the start and end dates for your analysis period. Replace'[Your Company Code 1]', '[Your Company Code 2]'with the list of SAP Company Codes you wish to analyze. - Execute the Extraction Query: Run the complete SQL query. Depending on the data volume and the selected date range, this may take several minutes to several hours to complete.
- Review Preliminary Results: Once the query finishes, review the first few hundred rows of the output. Check for data consistency, ensure all columns are populated as expected, and verify that different
ActivityNamevalues are present. - Export the Event Log: Export the entire result set from your SQL client to a CSV file. Ensure the file is UTF-8 encoded to prevent character issues. Name the file descriptively, for example,
sap_s4hana_ap_event_log.csv. - Prepare for Upload: Before uploading to a process mining tool, confirm that the column headers in the CSV file exactly match the required attribute names:
Invoice,ActivityName,EventTime,SourceSystem,LastDataUpdate,UserName, etc. - Upload to Process Mining Tool: Upload the generated CSV file to your process mining platform, mapping the columns to the corresponding case ID, activity, and timestamp fields.
Configuration
- Key CDS Views: The extraction relies on a combination of standard S/4HANA CDS Views. The primary views are:
I_JournalEntry&I_JournalEntryItem: For core financial document headers, items, posting details, and clearing information.I_SupplierInvoiceAPI01: For MM (Logistics) invoice-specific details, including PO references and payment blocks.I_ChangeDocument: To track the exact timestamp of changes, such as setting or removing a payment block.I_WorkflowStatusDetails: To extract events related to the invoice approval workflow.I_PaymentProposalItem: To identify when an invoice is included in a payment run proposal.I_Supplier: To enrich the data with vendor master information likeVendorName.
- Date Range Filtering: It is critical to apply a date range filter to limit the data volume. The provided query filters on
CreationDateTimein theInvoices_BaseCTE. A range of 3-6 months is recommended for an initial analysis to ensure manageable performance. - Mandatory Filters: Always filter by
CompanyCode. Analyzing data across all company codes at once can be extremely slow and may not be business-relevant. Also, filter onJournalEntryTypeto select only vendor-related documents (e.g., 'KR', 'RE'). - Prerequisites: The executing database user must have
SELECTauthorization on all CDS views used in the query and on the underlying HANA schema. Application-level access in the SAP GUI is not sufficient. - Performance Considerations: Direct queries on
I_ChangeDocumentcan be resource-intensive. The provided query attempts to mitigate this by pre-filtering invoices first. For very large datasets, consider running the extraction during off-peak hours or in smaller date range batches.
a Sample Query sql
-- Common Table Expression (CTE) to select the base set of AP Invoices
WITH Invoices_Base AS (
SELECT
I_JournalEntry.CompanyCode,
I_JournalEntry.AccountingDocument,
I_JournalEntry.FiscalYear,
CONCAT(I_JournalEntry.CompanyCode, CONCAT(I_JournalEntry.AccountingDocument, I_JournalEntry.FiscalYear)) AS InvoiceId,
I_JournalEntry.CreationDateTime,
I_JournalEntry.CreatedByUser,
I_JournalEntry.DocumentStatus,
I_JournalEntry.JournalEntryType,
I_JournalEntry.ReversalReferenceJournalEntry,
I_JournalEntry.IsReversed,
I_JournalEntry.ReversalDate,
IJE_ITEM.NetDueDate,
IJE_ITEM.Supplier,
SUP.SupplierName AS VendorName,
IJE_ITEM.AmountInCompanyCodeCurrency AS InvoiceAmount,
MM.PurchaseOrder AS PurchaseOrderNumber,
MM.PaymentBlockingReason
FROM I_JournalEntry
-- Join to get item details like due date and supplier
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON I_JournalEntry.CompanyCode = IJE_ITEM.CompanyCode
AND I_JournalEntry.AccountingDocument = IJE_ITEM.AccountingDocument
AND I_JournalEntry.FiscalYear = IJE_ITEM.FiscalYear
AND IJE_ITEM.IsSupplier = 'X'
-- Join to get vendor name from master data
LEFT JOIN I_Supplier AS SUP
ON IJE_ITEM.Supplier = SUP.Supplier
-- Join to get MM Invoice specific data like PO Number and Payment Block
LEFT JOIN I_SupplierInvoiceAPI01 AS MM
ON I_JournalEntry.AccountingDocument = MM.AccountingDocument
AND I_JournalEntry.CompanyCode = MM.CompanyCode
AND I_JournalEntry.FiscalYear = MM.FiscalYear
WHERE
I_JournalEntry.JournalEntryType IN ('KR', 'RE') -- Standard Vendor Invoice Types
AND I_JournalEntry.CompanyCode IN ('[Your Company Code 1]', '[Your Company Code 2]')
AND I_JournalEntry.CreationDateTime BETWEEN '[YYYY-MM-DD]T00:00:00Z' AND '[YYYY-MM-DD]T23:59:59Z'
)
-- Event: 1. Invoice Received
SELECT
B.InvoiceId AS "Invoice",
'Invoice Received' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
UNION ALL
-- Event: 2. Invoice Parked
SELECT
B.InvoiceId AS "Invoice",
'Invoice Parked' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.DocumentStatus = 'V' -- 'V' stands for Parked
UNION ALL
-- Event: 3. Purchase Order Matched
SELECT
B.InvoiceId AS "Invoice",
'Purchase Order Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PurchaseOrderNumber IS NOT NULL AND B.PurchaseOrderNumber <> ''
UNION ALL
-- Event: 4. Goods Receipt Matched
SELECT
B.InvoiceId AS "Invoice",
'Goods Receipt Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_SupplierInvoiceItemAPI01 AS MM_ITEM
ON B.AccountingDocument = MM_ITEM.AccountingDocument
AND B.FiscalYear = MM_ITEM.FiscalYear
WHERE MM_ITEM.GoodsReceipt IS NOT NULL AND MM_ITEM.GoodsReceipt <> ''
UNION ALL
-- Event: 5. Invoice Blocked For Payment
SELECT
B.InvoiceId AS "Invoice",
'Invoice Blocked For Payment' AS "ActivityName",
B.CreationDateTime AS "EventTime", -- Approximates block time as creation time if blocked on entry
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PaymentBlockingReason IS NOT NULL AND B.PaymentBlockingReason <> ''
UNION ALL
-- Event: 6. Discrepancy Resolved (Payment Block Removed)
SELECT
B.InvoiceId AS "Invoice",
'Discrepancy Resolved' AS "ActivityName",
CD.ChangeTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CD.UserName AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_ChangeDocument AS CD
ON CONCAT(B.CompanyCode, B.AccountingDocument, B.FiscalYear) = CD.ObjectValue
WHERE CD.ChangeDocumentObject = 'INVOICE'
AND CD.TableName = 'RBKP'
AND CD.FieldName = 'ZLSPR' -- Field for Payment Block
AND CD.NewFieldValue = '' -- Block was removed
UNION ALL
-- Event: 7, 8, 9. Workflow Events (Routed, Approved, Rejected)
SELECT
B.InvoiceId AS "Invoice",
CASE WF.WorkflowStatus
WHEN 'READY' THEN 'Invoice Routed For Approval'
WHEN 'APPROVED' THEN 'Invoice Approved'
WHEN 'REJECTED' THEN 'Invoice Rejected'
END AS "ActivityName",
WF.WorkflowStatusChangedDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
WF.WorkflowStatusChangedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_WorkflowStatusDetails AS WF
ON B.InvoiceId = WF.WorkflowScenarioInstance
WHERE WF.WorkflowStatus IN ('READY', 'APPROVED', 'REJECTED')
UNION ALL
-- Event: 10. Invoice Posted
SELECT
B.InvoiceId AS "Invoice",
'Invoice Posted' AS "ActivityName",
JE.PostingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntry AS JE
ON B.AccountingDocument = JE.AccountingDocument
AND B.CompanyCode = JE.CompanyCode
AND B.FiscalYear = JE.FiscalYear
WHERE B.DocumentStatus <> 'V' -- Any status other than Parked is considered Posted for AP
UNION ALL
-- Event: 11. Payment Proposal Created
SELECT
B.InvoiceId AS "Invoice",
'Payment Proposal Created' AS "ActivityName",
PPI.PaymentProposalRunDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
PPI.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_PaymentProposalItem AS PPI
ON B.CompanyCode = PPI.CompanyCode
AND B.AccountingDocument = PPI.AccountingDocument
AND B.FiscalYear = PPI.FiscalYear
UNION ALL
-- Event: 12. Payment Executed
-- This links the invoice to its clearing document, which is the payment document
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Executed' AS "ActivityName",
CLEAR_JE.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CLEAR_JE.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
INNER JOIN I_JournalEntry AS CLEAR_JE
ON IJE_ITEM.ClearingJournalEntry = CLEAR_JE.AccountingDocument
AND IJE_ITEM.CompanyCode = CLEAR_JE.CompanyCode
WHERE IJE_ITEM.ClearingJournalEntry IS NOT NULL AND IJE_ITEM.ClearingJournalEntry <> ''
AND CLEAR_JE.JournalEntryType = 'KZ' -- Vendor Payment Document Type
UNION ALL
-- Event: 13. Invoice Due Date Passed
SELECT
B.InvoiceId AS "Invoice",
'Invoice Due Date Passed' AS "ActivityName",
ADD_DAYS(B.NetDueDate, 1) AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
'SYSTEM' AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE B.NetDueDate < CURRENT_DATE
AND IJE_ITEM.ClearingDate IS NULL -- Invoice is not yet cleared
UNION ALL
-- Event: 14. Payment Cleared
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Cleared' AS "ActivityName",
IJE_ITEM.ClearingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
IJE_ITEM.ChangedByUser AS "UserName", -- User who cleared it
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE IJE_ITEM.ClearingDate IS NOT NULL
UNION ALL
-- Event: 15. Invoice Cancelled
SELECT
B.InvoiceId AS "Invoice",
'Invoice Cancelled' AS "ActivityName",
B.ReversalDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName", -- User who created the original document
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.IsReversed = 'X';Steps
- Specification and Design: Before coding, collaborate with business analysts to confirm the exact trigger conditions and data fields for each of the 15 required activities. Identify the relevant SAP tables, document types (e.g., 'KR', 'RE'), and company codes to be included in the scope.
- Create ABAP Program: Launch the ABAP Editor using transaction code
SE38. Create a new executable program, for instance,Z_PM_AP_INVOICE_EXTRACT. Provide a descriptive title and set the application to 'Financial Accounting'. - Define Selection Screen: In the program, define a selection screen (using the
PARAMETERSandSELECT-OPTIONSkeywords) to allow users to specify the extraction date range (for invoice creation date), target Company Codes (BUKRS), and relevant invoice Document Types (BLART). Also include a parameter for the output file path on the application server. - Data Declarations: Define an internal table structure that matches the final event log format (e.g.,
TY_EVENT_LOG) including all required and recommended attributes. Declare internal tables to hold data selected from various SAP source tables likeBKPF,BSEG,RBKP,RSEG,CDHDR,CDPOS, andREGUH. - Main Data Selection: Start the extraction logic by selecting the primary set of invoices from
RBKP(Logistics Invoices) andBKPF(Financial Invoices) based on the user's selection screen criteria. Store these primary invoice keys in an internal table to drive subsequent data lookups. - Extract Activities Sequentially: For each invoice in the main set, perform a series of selections to find the timestamps and details for each business activity. For example, query
CDHDRandCDPOSfor payment block changes, queryREGUHandREGUPfor payment run data, and queryBKPFfor reversal document details. Append a new record to the final event log table for each activity found. - Logic for Calculated Events: Implement ABAP logic for activities that are not directly stored in a table field. For the 'Invoice Due Date Passed' event, use the invoice due date (
BSEG-ZFBDT+ payment terms) and the clearing date (BSEG-AUGDT). If the clearing date is later than the due date, create a new event record with the timestamp set to the due date. - Data Transformation and Enrichment: As you gather data for each activity, populate all required attributes. This involves looking up vendor names from
LFA1, converting dates and times into a single timestamp string (CONCATENATE...INTO...), and setting theSourceSystemvalue. - Generate Output File: Once all invoices and their corresponding activities have been processed and collected into the final internal table, use the
OPEN DATASET,LOOP AT ... TRANSFER, andCLOSE DATASETstatements to write the data to a file on the application server path specified on the selection screen. - Download and Prepare for Upload: Use transaction code
CG3Yto download the generated file from the application server to your local machine. Ensure the file is saved in a UTF-8 encoded CSV format. Verify the column headers match the required attributes (Invoice,ActivityName,EventTime, etc.) before uploading to the process mining tool.
Configuration
- Date Range: Define the
P_CPUDTselection-option for the invoice creation date (BKPF-CPUDTorRBKP-CPUDT). A range of 6-12 months of data is recommended for an initial analysis. - Company Code (
P_BUKRS): A mandatorySELECT-OPTIONSparameter to filter for specific company codes. Processing for all company codes at once is not recommended unless absolutely necessary. - Invoice Document Type (
P_BLART): ASELECT-OPTIONSparameter to filter for relevant invoice document types. Common types include 'KR' (Vendor Invoice), 'KG' (Vendor Credit Memo), 'RE' (Logistics Invoice Verification). - Execution Mode: The program should be executed as a background job (
SM36/SM37) for large data volumes to avoid timeouts in the foreground dialog process. Schedule it to run during off-peak hours. - Output File Path: A
PARAMETERto specify the file path and name on the SAP application server (e.g., in the/tmp/directory). The file is written here before being downloaded. - Prerequisites: The user executing the report needs authorization to read from FI, CO, and MM tables (
BKPF,BSEG,RBKP,RSEG,LFA1), change document tables (CDHDR,CDPOS), and workflow tables. Additionally, authorization objectS_DATASETis required to write files to the application server.
a Sample Query abap
*&---------------------------------------------------------------------*
*& Report Z_PM_AP_INVOICE_EXTRACT
*&---------------------------------------------------------------------*
*& This report extracts Accounts Payable invoice lifecycle events for
*& process mining analysis.
*&---------------------------------------------------------------------*
REPORT z_pm_ap_invoice_extract.
*&---------------------------------------------------------------------*
*& Data Structures
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
invoice TYPE belnr_d,
activityname TYPE string,
eventtime TYPE string,
sourcesystem TYPE logsys,
lastdataupdate TYPE string,
username TYPE uname,
companycode TYPE bukrs,
vendorname TYPE name1_gp,
invoiceamount TYPE wrbtr,
purchaseordernumber TYPE ebeln,
invoiceduedate TYPE d,
END OF ty_event_log.
DATA: gt_event_log TYPE TABLE OF ty_event_log.
DATA: gv_system_id TYPE logsys.
DATA: gv_last_update TYPE string.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_bukrs FOR bkpf-bukrs OBLIGATORY,
s_cpudt FOR bkpf-cpudt OBLIGATORY DEFAULT sy-datum,
s_blart FOR bkpf-blart.
PARAMETERS: p_fpath TYPE string OBLIGATORY DEFAULT '/tmp/ap_extract.csv'.
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
" Get System ID and Update Timestamp
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = gv_system_id
EXCEPTIONS
own_logical_system_not_defined = 1
OTHERS = 2.
CONCATENATE sy-datum sy-uzeit INTO gv_last_update.
" Internal tables for SAP data
DATA: lt_bkpf TYPE TABLE OF bkpf,
lt_rbkp TYPE TABLE OF rbkp.
" Select base documents
SELECT * FROM bkpf INTO TABLE lt_bkpf
WHERE bukrs IN s_bukrs
AND cpudt IN s_cpudt
AND blart IN s_blart
AND ( blart = 'KR' OR blart = 'KG' ). " Example FI Invoice Types
SELECT * FROM rbkp INTO TABLE lt_rbkp
WHERE bukrs IN s_bukrs
AND cpudt IN s_cpudt
AND blart IN s_blart
AND blart = 'RE'. " Example MM Invoice Type
" --- Process each invoice document ---
LOOP AT lt_bkpf ASSIGNING FIELD-SYMBOL(<fs_bkpf>).
PERFORM process_invoice USING <fs_bkpf>.
ENDLOOP.
LOOP AT lt_rbkp ASSIGNING FIELD-SYMBOL(<fs_rbkp>).
PERFORM process_mm_invoice USING <fs_rbkp>.
ENDLOOP.
" Write output to file
PERFORM write_output_file.
*&---------------------------------------------------------------------*
*& Form PROCESS_INVOICE (Handles FI Invoices)
*&---------------------------------------------------------------------*
FORM process_invoice USING iv_bkpf TYPE bkpf.
DATA: ls_bseg TYPE bseg,
ls_lfa1 TYPE lfa1,
ld_due_date TYPE d.
DATA: ls_event TYPE ty_event_log.
" Get Vendor and other details from first line item
SELECT SINGLE * FROM bseg INTO ls_bseg
WHERE bukrs = iv_bkpf-bukrs
AND belnr = iv_bkpf-belnr
AND gjahr = iv_bkpf-gjahr
AND koart = 'K'.
IF sy-subrc = 0.
SELECT SINGLE name1 FROM lfa1 INTO ls_lfa1-name1 WHERE lifnr = ls_bseg-lifnr.
CALL FUNCTION 'DETERMINE_DUE_DATE'
EXPORTING
i_zfbdt = ls_bseg-zfbdt
i_zbd1t = ls_bseg-zbd1t
i_zbd2t = ls_bseg-zbd2t
i_zbd3t = ls_bseg-zbd3t
i_zbd1p = ls_bseg-zbd1p
i_zbd2p = ls_bseg-zbd2p
i_zterm = ls_bseg-zterm
IMPORTING
e_faedt = ld_due_date.
ENDIF.
" Helper function to populate common fields
MACRO set_common_fields.
ls_event-invoice = iv_bkpf-belnr.
ls_event-sourcesystem = gv_system_id.
ls_event-lastdataupdate = gv_last_update.
ls_event-companycode = iv_bkpf-bukrs.
ls_event-vendorname = ls_lfa1-name1.
ls_event-invoiceduedate = ld_due_date.
SELECT SINGLE wrbtr FROM bseg INTO ls_event-invoiceamount WHERE belnr = iv_bkpf-belnr AND gjahr = iv_bkpf-gjahr AND koart = 'K'.
ENDMACRO.
" 1. Invoice Received
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Received'.
CONCATENATE iv_bkpf-cpudt iv_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
" 2. Invoice Parked (if document was created as parked)
IF iv_bkpf-bstat = 'V'.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Parked'.
CONCATENATE iv_bkpf-cpudt iv_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
" 10. Invoice Posted (For non-parked, same as received. For parked, this needs CDHDR/CDPOS logic not shown for brevity)
IF iv_bkpf-bstat <> 'V'.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Posted'.
CONCATENATE iv_bkpf-budat iv_bkpf-cputm INTO ls_event-eventtime. " Using posting date
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
" 5. & 7. Invoice Blocked / Discrepancy Resolved from Change Docs
DATA: lt_cdhdr TYPE TABLE OF cdhdr, lt_cdpos TYPE TABLE OF cdpos.
DATA(ld_objectkey) = |{ iv_bkpf-bukrs }{ iv_bkpf-belnr }{ iv_bkpf-gjahr }|.
SELECT * FROM cdhdr INTO TABLE lt_cdhdr WHERE objectclas = 'BELEG' AND objectid = ld_objectkey.
IF sy-subrc = 0.
SELECT * FROM cdpos INTO TABLE lt_cdpos FOR ALL ENTRIES IN lt_cdhdr
WHERE changenr = lt_cdhdr-changenr AND tabname = 'BSEG' AND fname = 'ZLSPR'.
LOOP AT lt_cdpos ASSIGNING FIELD-SYMBOL(<fs_cdpos>).
READ TABLE lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>) WITH KEY changenr = <fs_cdpos>-changenr.
IF sy-subrc = 0.
CLEAR ls_event.
set_common_fields.
IF <fs_cdpos>-value_new IS NOT INITIAL AND <fs_cdpos>-value_old IS INITIAL.
ls_event-activityname = 'Invoice Blocked For Payment'.
ELSEIF <fs_cdpos>-value_new IS INITIAL AND <fs_cdpos>-value_old IS NOT INITIAL.
ls_event-activityname = 'Discrepancy Resolved'.
ELSE.
CONTINUE.
ENDIF.
CONCATENATE <fs_cdhdr>-udate <fs_cdhdr>-utime INTO ls_event-eventtime.
ls_event-username = <fs_cdhdr>-username.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDIF.
" 6. 8. 9. Workflow Events (Routed, Approved, Rejected) - Simplified Example
" This requires knowledge of specific workflow templates. Placeholder logic:
" SELECT ... FROM SWW_WI2OBJ ... WHERE INSTID = [Invoice Object]
" SELECT ... FROM SWWWIHEAD ... to get status and times
" 11. & 12. & 14. Payment Proposal, Executed, Cleared
IF ls_bseg-augbl IS NOT INITIAL.
DATA: ls_regup TYPE regup.
SELECT SINGLE * FROM regup INTO ls_regup WHERE vblnr = ls_bseg-belnr.
IF sy-subrc = 0.
DATA(ld_rundate) = ls_regup-laufd.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Proposal Created'.
CONCATENATE ld_rundate '000000' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Executed'.
CONCATENATE ls_bseg-augdt '120000' INTO ls_event-eventtime. " Using clearing date as proxy
APPEND ls_event TO gt_event_log.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Cleared'.
CONCATENATE ls_bseg-augdt '120001' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
" 13. Invoice Due Date Passed (Calculated)
IF ls_bseg-augdt IS NOT INITIAL AND ld_due_date IS NOT INITIAL.
IF ls_bseg-augdt > ld_due_date.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Due Date Passed'.
CONCATENATE ld_due_date '235959' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDIF.
" 15. Invoice Cancelled
IF iv_bkpf-stblg IS NOT INITIAL.
DATA: ls_rev_bkpf TYPE bkpf.
SELECT SINGLE * FROM bkpf INTO ls_rev_bkpf WHERE belnr = iv_bkpf-stblg.
IF sy-subrc = 0.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Cancelled'.
CONCATENATE ls_rev_bkpf-cpudt ls_rev_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = ls_rev_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form PROCESS_MM_INVOICE (Handles MM/Logistics Invoices)
*&---------------------------------------------------------------------*
FORM process_mm_invoice USING iv_rbkp TYPE rbkp.
" This form would be similar to PROCESS_INVOICE, but starts with RBKP.
" It needs to find the corresponding FI document in BKPF via AWKEY.
" The logic for PO/GR Matched would be included here.
" For demonstration, creating placeholder events for MM-specific activities.
DATA: ls_event TYPE ty_event_log.
ls_event-invoice = iv_rbkp-belnr.
ls_event-sourcesystem = gv_system_id.
ls_event-lastdataupdate = gv_last_update.
ls_event-companycode = iv_rbkp-bukrs.
" 1. Invoice Received (MM)
ls_event-activityname = 'Invoice Received'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" 3. Purchase Order Matched (Implicit)
ls_event-activityname = 'Purchase Order Matched'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" 4. Goods Receipt Matched (Implicit)
ls_event-activityname = 'Goods Receipt Matched'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" NOTE: The rest of the events (Block, Pay, etc.) would be found by linking
" RBKP to BKPF and then reusing the logic from PROCESS_INVOICE.
" Link: BKPF-AWKEY = CONCATENATE( RBKP-BELNR, RBKP-GJAHR ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form WRITE_OUTPUT_FILE
*&---------------------------------------------------------------------*
FORM write_output_file.
DATA: lv_string TYPE string.
OPEN DATASET p_fpath FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc <> 0.
MESSAGE 'Error opening file.' TYPE 'E'.
RETURN.
ENDIF.
" Write Header
lv_string = 'Invoice,ActivityName,EventTime,SourceSystem,LastDataUpdate,UserName,CompanyCode,VendorName,InvoiceAmount,PurchaseOrderNumber,InvoiceDueDate'.
TRANSFER lv_string TO p_fpath.
" Write Data
LOOP AT gt_event_log ASSIGNING FIELD-SYMBOL(<fs_event>).
" Create a comma-separated string, handling potential commas in data
CONCATENATE <fs_event>-invoice
<fs_event>-activityname
<fs_event>-eventtime
<fs_event>-sourcesystem
<fs_event>-lastdataupdate
<fs_event>-username
<fs_event>-companycode
<fs_event>-vendorname
<fs_event>-invoiceamount
<fs_event>-purchaseordernumber
<fs_event>-invoiceduedate
INTO lv_string SEPARATED BY ','.
TRANSFER lv_string TO p_fpath.
ENDLOOP.
CLOSE DATASET p_fpath.
WRITE: / 'Extraction complete. File written to:', p_fpath.
ENDFORM.