Jouw datatemplate voor de verwerking van crediteurenfacturen
Jouw datatemplate voor de verwerking van crediteurenfacturen
- Aanbevolen attributen voor een volledige analyse
- Belangrijke procesactiviteiten om goed te volgen
- Stapsgewijze uitleg voor data-extractie
Attributen voor factuurverwerking bij crediteuren
| Naam | Beschrijving | ||
|---|---|---|---|
| Activiteit ActivityName | De naam van een specifieke bedrijfsgebeurtenis of stap die tijdens de levenscyclus van de factuur heeft plaatsgevonden. | ||
| Beschrijving De activiteit staat voor een afzonderlijke fase of handeling binnen het Accounts Payable-proces, zoals 'Factuur ontvangen', 'Factuur geboekt' of 'Betaling uitgevoerd'. Dit zijn de bouwstenen van de procesmap. Activiteiten analyseren is een kernonderdeel van process mining. Je maakt er de procesflow mee zichtbaar, vindt veelvoorkomende routes, ontdekt afwijkingen van het standaardproces en meet de frequentie en duur van elke stap. De volgorde van deze activiteiten voor een bepaalde factuur vormt de procesroute. Waarom dit belangrijk is Hiermee worden de processtappen gedefinieerd. Zo kun je de procesflow visualiseren en analyseren, knelpunten opsporen en herstelwerkcycli ontdekken. Waar je het vindt Afgeleid uit verschillende bronnen, waaronder wijzigingen in documentstatussen, bijvoorbeeld BKPF-BSTAT, wijzigingsdocumenten, de tabellen CDHDR/CDPOS, of workflowlogboeken. Hiervoor is meestal aangepaste extractielogica nodig. Voorbeelden Factuur ontvangenFactuur goedgekeurdBetaling uitgevoerdFactuur geblokkeerd voor betaling | |||
| Eventtijd EventTime | De exacte datum en tijd waarop de activiteit plaatsvond. | ||
| Beschrijving Eventtijd is de timestamp die aan elke activiteit is gekoppeld en de chronologische volgorde van events voor een factuur bepaalt. Deze data is essentieel om de procesflow te begrijpen en tijdsanalyses uit te voeren. In analyses gebruik je eventtijd om activiteiten in de juiste volgorde te zetten, doorlooptijden tussen stappen te berekenen, wachttijden te vinden en procesprestaties over verschillende perioden te analyseren, bijvoorbeeld maand op maand. Dit is de basis van alle tijdsgebonden KPI's. Waarom dit belangrijk is Deze timestamp is belangrijk om events chronologisch te ordenen en alle tijdsgebonden metingen te berekenen, zoals doorlooptijden en duur. Die vormen de basis van process mining. Waar je het vindt Afkomstig uit verschillende datum- en tijdvelden in SAP-tabellen, zoals aanmaakdatum (BKPF-CPUDT), boekingsdatum (BKPF-BUDAT), vereffeningsdatum (BSAK-AUGDT) of timestamps uit wijzigingslogboeken (CDHDR-UDATE/UTIME). Voorbeelden 2023-10-01T09:00:00Z2023-10-05T14:30:15Z2023-10-15T11:21:05Z | |||
| Factuur Invoice | De unieke identificatie van een factuurdocument, die dient als de primaire case-ID voor het Accounts Payable-proces. | ||
| Beschrijving De factuur is het centrale object dat alle gerelateerde activiteiten verbindt, van ontvangst tot betaling. In SAP S/4HANA bestaat dit meestal uit een samengestelde sleutel met de company code (BUKRS), een uniek documentnummer (BELNR) en het boekjaar (GJAHR). Door op factuur te analyseren, krijg je een volledig end-to-end-overzicht van de levenscyclus van de factuur. Dit is de basis voor KPI's zoals de totale doorlooptijd, het opsporen van knelpunten bij afzonderlijke facturen en het begrijpen van de verschillende routes die een factuur door het proces kan volgen. Waarom dit belangrijk is Hiermee wordt de route van elke factuur uniek geïdentificeerd. Zo kun je de volledige levenscyclus volgen en de procesprestaties per case analyseren. Waar je het vindt Dit is een samengestelde sleutel uit de tabellen BKPF (kop van boekingsdocument) of RBKP (kop van document: factuurontvangst), met de velden BUKRS, BELNR en GJAHR. Voorbeelden 1000-1900000001-20231710-1900000002-20232000-5100000003-2024 | |||
| Bronsysteem SourceSystem | Het systeem waaruit de data is geëxtraheerd. | ||
| Beschrijving Dit attribuut identificeert de herkomst van de procesdata. In deze weergave is de waarde meestal 'SAP S/4HANA'. In omgevingen met meerdere ERP's of geïntegreerde systemen is dit veld belangrijk voor data lineage en scheiding van data. Het zorgt ervoor dat je de juiste dataset analyseert en helpt problemen met datakwaliteit op te sporen door ze naar de bron terug te leiden. Waarom dit belangrijk is Identificeert de herkomst van de data. Dit is belangrijk voor datagovernance, probleemoplossing en omgevingen met meerdere systemen. Waar je het vindt Dit is meestal een statische waarde die tijdens het data-extractieproces wordt toegevoegd om de herkomst van de dataset te markeren. Voorbeelden SAP S/4HANASAP ECC 6.0S4H_PROD_100 | |||
| Laatste data-update LastDataUpdate | De timestamp die aangeeft wanneer de data voor dit record voor het laatst vanuit het bronsysteem is vernieuwd. | ||
| Beschrijving Dit attribuut bevat de datum en tijd van de meest recente data-extractie of update vanuit SAP S/4HANA. Het is een metadataveld dat belangrijk is om te begrijpen hoe actueel de geanalyseerde data is. Met deze informatie weet je hoe actueel de procesanalyse is. Je kunt er verwachtingen over datavertraging mee beheren, datarefreshes plannen en de dataintegriteit bewaken. Waarom dit belangrijk is Geeft aan hoe actueel de data is, zodat je weet hoe recent je procesanalyse is. Waar je het vindt Deze waarde wordt tijdens de data-extractie uit het bronsysteem gegenereerd en aan elk record toegevoegd. Voorbeelden 2024-05-20T04:00:00Z2024-05-21T04:00:00Z | |||
| Company code CompanyCode | De organisatorische eenheid waarvoor de factuur wordt verwerkt. | ||
| Beschrijving Een company code is de kleinste organisatorische eenheid waarvoor een volledige, zelfstandige boekhouding voor externe rapportage kan worden opgesteld. In de context van AP staat deze voor de juridische entiteit die de leverancier moet betalen. Door op company code te analyseren, kun je procesprestaties tussen verschillende juridische entiteiten binnen de organisatie vergelijken. Zo zie je welke onderdelen volgens standaardprocessen werken en waar de efficiëntie lager is, de doorlooptijden langer zijn of meer herstelwerk voorkomt. Waarom dit belangrijk is Maakt het mogelijk om procesprestaties tussen verschillende juridische entiteiten te vergelijken. Zo vind je regionale problemen of problemen die specifiek zijn voor een bedrijfsonderdeel, en zie je waar goede werkwijzen worden toegepast. Waar je het vindt Te vinden in documentkoptabellen, vooral BKPF-BUKRS voor FI-facturen en RBKP-BUKRS voor MM-facturen. Voorbeelden 10001710US01DE01 | |||
| Factuurbedrag InvoiceAmount | Het totale brutobedrag van de factuur in de oorspronkelijke documentvaluta. | ||
| Beschrijving Dit is de totale waarde van de factuur zoals de leverancier die heeft ingediend. Het bedrag omvat de kosten van goederen of diensten, belastingen en andere kosten, vóór aftrek van inhoudingen of kortingen. Het factuurbedrag is een belangrijk financieel attribuut voor allerlei analyses. Je kunt er facturen met een hoge waarde mee prioriteren, de financiële impact van procesvertragingen begrijpen, zoals kosten voor te late betaling van grote facturen, en het proces segmenteren. Bijvoorbeeld: 'Volgen facturen met een hoge waarde een andere goedkeuringsroute?'. Het is ook belangrijk voor het opsporen van mogelijke dubbele betalingen. Waarom dit belangrijk is Geeft financiële context aan het proces. Zo kun je op waarde analyseren, facturen met een hoge waarde prioriteren en financiële gevolgen kwantificeren. Waar je het vindt Te vinden in tabellen zoals RBKP-RMWWR (brutofactuurbedrag) voor MM-facturen, of berekend uit factuurregels in BSEG (veld WRBTR) voor FI-facturen. Voorbeelden 1500.00250.7512345.50 | |||
| Gebruikersnaam UserName | De gebruikers-ID van de persoon die de activiteit heeft uitgevoerd. | ||
| Beschrijving Dit attribuut legt de SAP-gebruikers-ID vast van degene die een specifieke activiteit uitvoerde, zoals het boeken, goedkeuren of vereffenen van een factuur. Zo worden processtappen aan individuele gebruikers gekoppeld. Analyseren op gebruikersnaam is belangrijk om de werkverdeling te begrijpen, goed presterende gebruikers te herkennen en gebruikers te vinden die extra training nodig hebben. Het is ook belangrijk voor het analyseren van goedkeuringsknelpunten in dashboards, omdat je ziet welke goedkeurders vertraging veroorzaken. Waarom dit belangrijk is Koppelt activiteiten aan specifieke personen. Zo kun je gebruikersprestaties, werkbelasting en compliance met beleid voor functiescheiding analyseren. Waar je het vindt Meestal te vinden in koptabellen, zoals BKPF-USNAM (ingevoerd door), of in wijzigingsdocumenttabellen zoals CDHDR-USERNAME (gewijzigd door). Voorbeelden ABROWNJSMITHAP_AUTOMATION | |||
| Inkoopordernummer PurchaseOrderNumber | De unieke identificatie van de inkooporder die aan de factuur is gekoppeld, indien van toepassing. | ||
| Beschrijving Dit attribuut koppelt een factuur aan een vooraf goedgekeurde inkooporder (PO). De aanwezigheid van een PO-nummer vormt de basis voor het 3-way-matchproces (PO-factuur-goederenontvangst). Dit attribuut is belangrijk voor compliance- en efficiëntieanalyses. Je gebruikt het om de KPI 'PO-Less Invoice Percentage' te berekenen, die meet in hoeverre het inkoopbeleid wordt gevolgd. Het vormt ook de basis voor het dashboard '3-Way Matching Performance', waarmee je het matchingproces voor facturen met een PO analyseert. Waarom dit belangrijk is Belangrijk voor het analyseren van de efficiëntie van 3-way matching en het meten van compliance met inkoopbeleid, door facturen zonder PO te identificeren. Waar je het vindt Te vinden in factuurregeltabellen, zoals RSEG-EBELN voor MM-facturen of BSEG-EBELN voor FI-facturen. Voorbeelden 45000012344500005678 | |||
| Leveranciersnaam VendorName | De naam van de leverancier die de factuur heeft ingediend. | ||
| Beschrijving Dit attribuut bevat de officiële naam van de leverancier. Het is gekoppeld via het leveranciersnummer dat op het factuurdocument staat. Leveranciersanalyse is belangrijk voor het beheren van leveranciersrelaties en het opsporen van procesproblemen bij specifieke leveranciers. Je kunt er vragen mee beantwoorden als: 'Welke leveranciers dienen de meeste facturen met verschillen in?' en 'Betalen we bepaalde strategische leveranciers steeds op tijd?'. Samen met het factuurnummer en bedrag is dit ook een belangrijk veld voor het opsporen van mogelijke dubbele betalingen. Waarom dit belangrijk is Maakt analyse van procesprestaties per leverancier mogelijk. Zo kun je problematische leveranciers vinden en strategische leveranciersrelaties beter beheren. Waar je het vindt Opgehaald uit de leveranciersstamgegevenstabel LFA1 (veld NAME1), via het leveranciersnummer (LIFNR) in BKPF of RBKP. Voorbeelden Office Supplies Inc.Global Consulting GroupMachine Parts GmbH | |||
| Vervaldatum factuur InvoiceDueDate | De datum waarop de betaling van de factuur aan de leverancier uiterlijk moet zijn voldaan. | ||
| Beschrijving De vervaldatum van de factuur is de uiterste betaaldatum om kosten voor te late betaling te voorkomen en een goede leveranciersrelatie te behouden. Deze datum wordt berekend op basis van de basisdatum van de factuur en de met de leverancier afgesproken betalingsvoorwaarden. Deze datum is belangrijk voor het dashboard 'Payment Compliance & Aging' en de KPI 'On-Time Payment Rate'. Door de vervaldatum met de werkelijke betaaldatum te vergelijken, zie je of betalingen op tijd, vroeg of te laat worden uitgevoerd. Dat heeft directe financiële gevolgen en gevolgen voor de relatie met de leverancier. Waarom dit belangrijk is Dit is de belangrijkste factor voor analyses van tijdige betalingen. Je kunt er de betaalprestaties en de impact ervan op leveranciersrelaties en kosten voor te late betaling mee meten. Waar je het vindt Deze datum wordt vaak berekend. De nettovervaldatum staat in veld BSEG-NETDT. Je kunt deze ook afleiden uit de basisdatum voor betaling (BSEG-ZFBDT) en de betalingsvoorwaarden (BSEG-ZTERM). Voorbeelden 2023-10-312023-11-152024-01-10 | |||
| Betalingsvoorwaarden PaymentTerms | De voorwaarden die met de leverancier zijn afgesproken voor het betalen van een factuur, vaak inclusief mogelijkheden voor korting. | ||
| Beschrijving Betalingsvoorwaarden bepalen de regels voor vervaldatums en mogelijke kortingen bij vroeg betalen. Een voorwaarde als 'Z001' kan bijvoorbeeld betekenen: 'Betaalbaar binnen 30 dagen, 2% korting bij betaling binnen 10 dagen'. Dit attribuut vormt de basis voor het dashboard 'Early Payment Discount Capture Rate'. Door de betalingsvoorwaarden te analyseren, kun je alle facturen vinden waarvoor een korting mogelijk was. Door dit te vergelijken met de werkelijk ontvangen kortingen, zie je gemiste besparingen en meet je de efficiëntie van het betalingsproces. Waarom dit belangrijk is Essentieel voor het analyseren van kortingsmogelijkheden bij vroeg betalen, het meten van de financiële prestaties van het betalingsproces en het opsporen van gemiste besparingen. Waar je het vindt Te vinden op leveranciersregels in tabel BSEG-ZTERM of op de factuurkop in RBKP-ZTERM. Voorbeelden Z0010001NT30 | |||
| Blokkeerreden BlockingReason | De reden waarom een factuur voor betaling is geblokkeerd, wat wijst op een verschil. | ||
| Beschrijving Wanneer een factuur een validatiecontrole tijdens de 3-way match of een andere verificatiestap niet doorstaat, wordt deze voor betaling geblokkeerd. De blokkeerreden beschrijft het probleem, zoals een verschil in aantal of prijs, of een ontbrekende goederenontvangst. Dit attribuut is belangrijk voor het dashboard 'Invoice Discrepancy Rework Analysis'. Door de frequentie van verschillende blokkeerredenen te analyseren, zie je de oorzaken van inefficiënties in het proces. Als 'Price variance' bijvoorbeeld vaak voorkomt, kan dat wijzen op problemen met stamdata in het inkoopsysteem. Waarom dit belangrijk is Geeft rechtstreeks inzicht in de oorzaken van factuurverschillen en herstelwerk. Zo kun je gerichte verbeteringen in het proces doorvoeren. Waar je het vindt Opgeslagen in factuurregelitemtabellen zoals RSEG, in velden die beginnen met SPGR*, bijvoorbeeld SPGRP, SPGRQ en SPGRT. Je vindt deze informatie ook in RBKP_BLOCKED. Voorbeelden PrijsverschilVerschil in aantalOntvangst van goederen ontbreekt | |||
| Clearingdatum ClearingDate | De datum waarop de betaling is gedaan en de factuur uit de openstaande posten is afgeboekt. | ||
| Beschrijving De clearingdatum staat voor de financiële afwikkeling van de factuur. Dit is de datum waarop de activiteit 'Payment Cleared' plaatsvindt en meestal de laatste stap in een succesvol factuurproces. Deze datum wordt gebruikt om de werkelijke betaaldatum te berekenen en die te vergelijken met de vervaldatum van de factuur. Daarom is de datum essentieel voor het berekenen van de KPI 'Percentage op tijd betaalde facturen' en voor analyses van betalingsprestaties. Ook markeert de datum het eindpunt voor het berekenen van de end-to-end-doorlooptijd van een factuur. Waarom dit belangrijk is Markeert de definitieve afwikkeling van een factuur. De datum vormt het eindpunt voor doorlooptijdberekeningen en de basis voor analyses van tijdige betalingen. Waar je het vindt Te vinden in de tabellen voor afgeboekte posten, zoals BSAK-AUGDT voor leveranciers. Voorbeelden 2023-10-282023-11-142024-01-09 | |||
| Factuurdocumenttype InvoiceDocumentType | Een classificatie van het factuurdocument die bepaalt hoe het in SAP wordt verwerkt. | ||
| Beschrijving Het documenttype is een belangrijk configuratie-element in SAP waarmee boekingsdocumenten worden ingedeeld. 'KR' wordt bijvoorbeeld meestal gebruikt voor leveranciersfacturen, 'RE' voor MM-facturen en 'KG' voor creditnota's van leveranciers. Dit type bepaalt onder andere de nummerreeks en welke velden verplicht zijn. Door in procesanalyses op documenttype te filteren, kun je procesflows voor verschillende soorten facturen vergelijken. Het goedkeuringsproces voor een creditnota kan bijvoorbeeld anders zijn dan dat voor een standaardfactuur. Dit is nuttig voor het dashboard 'Invoice Approval Routing Variants'. Waarom dit belangrijk is Maakt segmentatie van het proces mogelijk op basis van de manier waarop verschillende factuurtypen worden verwerkt. Zo worden verschillen in procesroutes en doorlooptijden zichtbaar. Waar je het vindt Rechtstreeks uit de tabel met documentkopgegevens, veld BKPF-BLART. Voorbeelden KRREKG | |||
| Factuurnummer van leverancier VendorInvoiceNumber | Het factuurnummer dat de leverancier op zijn document vermeldt. | ||
| Beschrijving Dit is het referentienummer uit het eigen boekhoudsysteem van de leverancier, zoals afgedrukt op de fysieke of elektronische factuur. Het nummer wordt bij ontvangst van de factuur handmatig ingevoerd of met OCR vastgelegd. Dit veld is erg belangrijk voor de bedrijfsvoering en voor analyses, vooral voor het dashboard 'Mogelijke dubbele betalingen van facturen'. Een veelgebruikte methode om dubbele facturen te detecteren, is zoeken naar meerdere interne factuurdocumenten met dezelfde leveranciersnaam, hetzelfde factuurnummer van de leverancier en hetzelfde factuurbedrag. Het is de belangrijkste externe referentie voor een factuur. Waarom dit belangrijk is Dit is een belangrijk veld voor het detecteren van mogelijke dubbele betalingen en de belangrijkste externe referentie voor communicatie met leveranciers. Waar je het vindt Opgeslagen in het veld 'Reference' in de documentkop, meestal BKPF-XBLNR. Voorbeelden INV-2023-9876733401120231015-001 | |||
| Factuurvaluta InvoiceCurrency | De valutacode voor het factuurbedrag, bijvoorbeeld USD of EUR. | ||
| Beschrijving Dit attribuut geeft aan in welke valuta het factuurbedrag is uitgedrukt. Het biedt essentiële context voor alle financiële waarden. Bij een multinationale organisatie kan een analyse van facturen zonder rekening te houden met de valuta een vertekend beeld geven. Met dit veld kun je financiële data goed verwerken, bijvoorbeeld door alle bedragen om te rekenen naar één rapportagevaluta of de analyse per valuta uit te voeren om regionale financiële activiteiten te begrijpen. Waarom dit belangrijk is Biedt de nodige context voor het factuurbedrag en maakt nauwkeurige financiële analyses en rapportages mogelijk, vooral in een multinationale omgeving. Waar je het vindt Te vinden in documentkoptabellen, voornamelijk BKPF-WAERS of RBKP-WAERS. Voorbeelden USDEURGBPJPY | |||
| Geautomatiseerd IsAutomated | Een vlag die aangeeft of de activiteit automatisch door het systeem is uitgevoerd in plaats van door een menselijke gebruiker. | ||
| Beschrijving Dit booleaanse attribuut maakt onderscheid tussen activiteiten die door mensen zijn gestart en activiteiten die door systeemtaken, workflows of bots zijn uitgevoerd. Een geautomatiseerde betalingsrun of een door het systeem gegenereerde factuurboeking krijgt bijvoorbeeld de waarde geautomatiseerd. Door dit attribuut te analyseren, begrijp je de mate van automatisering in het Accounts Payable-proces. Je kunt het gebruiken om het succes van automatiseringsinitiatieven te meten, de efficiëntie van geautomatiseerde en handmatige stappen te vergelijken en nieuwe mogelijkheden voor automatisering te vinden. Waarom dit belangrijk is Helpt de mate van automatisering in het proces te meten. Zo kun je de effectiviteit van automatisering analyseren en mogelijkheden voor verdere verbetering vinden. Waar je het vindt Afgeleid op basis van de gebruikersnaam, bijvoorbeeld systeemgebruikers-ID's zoals 'SAP_SYSTEM' of 'BATCHUSER', of specifieke transactietcodes die aan geautomatiseerde taken zijn gekoppeld. Voorbeelden truefalse | |||
| Is te laat betaald IsLatePayment | Een boolean-vlag die aangeeft of de factuur na de vervaldatum is betaald. | ||
| Beschrijving Dit berekende attribuut is een eenvoudige true/false-vlag die aangeeft of een factuur na de officiële vervaldatum is betaald. De waarde wordt bepaald door de 'Clearing Date' te vergelijken met de 'Invoice Due Date'. Deze vlag vereenvoudigt de analyse voor het dashboard 'Betalingscompliance en ouderdom' en de KPI 'Percentage op tijd betaalde facturen'. Je kunt eenvoudig filteren en groeperen om het aantal te late betalingen te tellen, het percentage tijdige betalingen te berekenen en leveranciers of bedrijfscodes met veel te late betalingen te identificeren. Waarom dit belangrijk is Meet rechtstreeks de naleving van betalingsvoorwaarden, vereenvoudigt de berekening van de KPI voor tijdige betalingen en helpt gebieden met slechte betalingsprestaties te vinden. Waar je het vindt Berekend attribuut. De logica is: IF ClearingDate > InvoiceDueDate THEN true ELSE false. Voorbeelden truefalse | |||
| Verkregen korting DiscountTaken | Een boolean-vlag die aangeeft of een vroegbetalingskorting daadwerkelijk is toegepast. | ||
| Beschrijving Dit attribuut geeft aan of bij de betaling van de factuur daadwerkelijk een betalingskorting is toegepast. Het is een belangrijk onderdeel van het meten van financiële efficiëntie in het AP-proces. Deze vlag vormt de basis van de KPI 'Percentage vastgelegde vroegbetalingskortingen'. Door te filteren op facturen waarvoor een korting mogelijk was, op basis van de betalingsvoorwaarden, en deze vlag vervolgens te analyseren, kan een organisatie precies berekenen hoeveel geld is bespaard en hoeveel besparingsmogelijkheden zijn gemist. Zo ontstaat een duidelijke, meetbare indicatie van de prestaties van het crediteurenproces. Waarom dit belangrijk is Meet rechtstreeks hoe succesvol beschikbare vroegbetalingskortingen worden vastgelegd. Dat heeft direct invloed op het bedrijfsresultaat. Waar je het vindt Afgeleid door te controleren of het veld voor het kortingsbedrag, BSEG-SKNTO, op het betalingsdocument groter is dan nul. Voorbeelden truefalse | |||
Activiteiten in de factuurverwerking bij crediteuren
| Activiteit | Beschrijving | ||
|---|---|---|---|
| Betaling uitgevoerd | De factuur is betaald. Dit wordt vastgelegd wanneer de betalingsrun is voltooid en een betalingsdocument is aangemaakt en geboekt. | ||
| Waarom dit belangrijk is Deze activiteit is belangrijk voor cashflowanalyse en voor het meten van de KPI 'On-Time Payment Rate', door deze datum te vergelijken met de vervaldatum van de factuur. Waar je het vindt Dit wordt vastgelegd aan de hand van de boekingsdatum van het betalingsdocument waarmee de factuur wordt vereffend. Het nummer van het betalingsdocument staat in het veld voor het vereffeningsdocument (AUGBL) van de factuurregel (BSEG). Vastleggen Identificeer de boekingsdatum (BUDAT) van het betalingsdocument waarmee de factuurregel wordt vereffend. Eventtype explicit | |||
| Betaling vereffend | Deze activiteit markeert de definitieve afsluiting van de factuur. De betaling en factuur worden in het subgrootboek met elkaar vereffend. Daarmee is het proces voltooid. | ||
| Waarom dit belangrijk is Als definitief eindpunt van het proces is deze activiteit essentieel voor een nauwkeurige berekening van de end-to-end-doorlooptijd. Ze bevestigt dat de verplichting is voldaan. Waar je het vindt Dit is een expliciet event dat wordt gemarkeerd zodra het veld voor de vereffeningsdatum (AUGDT) op de leveranciersregel van het factuurdocument is gevuld, in tabel BSEG. Vastleggen Gebruik de vereffeningsdatum (BSEG-AUGDT) van de factuurregel. Eventtype explicit | |||
| Factuur geannuleerd | Het factuurdocument is teruggeboekt, waardoor de financiële impact ervan feitelijk vervalt. Dit is een alternatieve eindstatus van het proces, vaak door onjuiste invoer of een geschil met de leverancier. | ||
| Waarom dit belangrijk is Door annuleringen te volgen, zie je oorzaken van procesfouten, zoals dubbele inzendingen of onjuiste factuurdata. Dat kan wijzen op problemen eerder in het proces. Waar je het vindt Dit wordt expliciet vastgelegd wanneer een terugboekingsdocument wordt aangemaakt. De kop van het oorspronkelijke document (BKPF) bevat dan het nummer van het terugboekingsdocument (STBLG) en de reden voor terugboeking. Vastleggen Identificeer de boekingsdatum van het terugboekingsdocument dat via de oorspronkelijke documentkop (BKPF-STBLG) is gekoppeld. Eventtype explicit | |||
| Factuur geblokkeerd voor betaling | Het systeem heeft de factuur automatisch of handmatig geblokkeerd, waardoor betaling niet mogelijk is. Meestal komt dit door verschillen in prijs of aantal, of door ontbrekende goedkeuringen. | ||
| Waarom dit belangrijk is Dit is een belangrijke aanwijzing voor problemen en herstelwerk. Door blokkeerredenen en -duur te analyseren, zie je de oorzaken van betalingsvertragingen en inefficiënties in het proces. Waar je het vindt Dit is een expliciete status in het veld Payment Block Key (ZLSPR) op de leveranciersregel van het boekingsdocument, in tabel BSEG. Vastleggen Vastgelegd via wijzigingsdocumenten wanneer het veld BSEG-ZLSPR een blokkeerreden bevat. Eventtype explicit | |||
| Factuur geboekt | De factuur is formeel in het grootboek vastgelegd en creëert daarmee een financiële verplichting. Een geparkeerd document wordt een geboekt document, of er wordt meteen geboekt. | ||
| Waarom dit belangrijk is Dit is een belangrijke financiële mijlpaal. De boeking bevestigt de betalingsverplichting van het bedrijf en is vaak een voorwaarde om de betaling in te plannen. Waar je het vindt Dit event wordt geïdentificeerd aan de hand van de boekingsdatum (BUDAT) in de documentkop (BKPF). Bij een geboekt document is de documentstatus (BKPF-BSTAT) leeg. Vastleggen Gebruik de boektimestamp (BKPF-BUDAT) voor documenten die niet zijn geparkeerd (BKPF-BSTAT is leeg). Eventtype explicit | |||
| Factuur goedgekeurd | De factuur heeft alle benodigde goedkeuringen in het workflowsysteem ontvangen. Dit is vaak de laatste stap voordat de factuur kan worden geboekt of de betalingsblokkade kan worden opgeheven. | ||
| Waarom dit belangrijk is Deze belangrijke mijlpaal markeert het einde van de goedkeuringscyclus. De tijd tussen doorsturen en goedkeuren is een belangrijke efficiëntiemaatstaf. Waar je het vindt Vastgelegd in de SAP Business Workflow-logboeken als een voltooiings- of definitieve vrijgavestap. Je kunt dit ook afleiden uit het verwijderen van een betalingsblokkade na het doorsturen. Vastleggen Extraheer voltooiingsevents van workflows uit de SAP-workflowlogboeken of identificeer het laatste 'release'-event. Eventtype explicit | |||
| Factuur ontvangen | Deze activiteit markeert het aanmaken van een factuurdocument in SAP, handmatig of via een geautomatiseerde interface zoals OCR/VIM. Dit event wordt meestal vastgelegd met de aanmaakdatum en -tijd van de kop van het boekingsdocument. | ||
| Waarom dit belangrijk is Als startpunt van het proces is deze activiteit essentieel voor het berekenen van de end-to-end-doorlooptijd van facturen en het meten van de throughput van het volledige AP-proces. Waar je het vindt Dit event komt uit de tabel met kopgegevens van boekingsdocumenten (BKPF), met de aanmaakdatum (CPUDT) en -tijd (CPUTM) van het document. Vastleggen Gebruik de aanmaaktimestamp (BKPF-CPUDT, BKPF-CPUTM) van het factuurdocument. Eventtype explicit | |||
| Betalingsvoorstel aangemaakt | De factuur is opgenomen in een betalingsvoorstel als onderdeel van een betalingsrun, bijvoorbeeld F110. De betaling staat nu gepland, onder voorbehoud van de definitieve uitvoering van de run. | ||
| Waarom dit belangrijk is Deze activiteit laat de overgang zien van een open verplichting naar een post die actief wordt voorbereid voor betaling. Zo kun je de efficiëntie van de bedrijfsvoering rond betalingen analyseren. Waar je het vindt Dit event wordt expliciet vastgelegd in de datatabellen van de betalingsrun, met name REGUP (verwerkte posten van het betalingsprogramma) en REGUH (kopgegevens). Vastleggen Identificeer wanneer een factuur voorkomt in tabel REGUP voor een betalingsrun die in REGUH is geïdentificeerd. Eventtype explicit | |||
| Factuur afgewezen | Een goedkeurder heeft de factuur tijdens de goedkeuringsworkflow afgewezen. Meestal gaat de factuur dan terug naar de verwerker voor correctie of toelichting. | ||
| Waarom dit belangrijk is Door afwijzingen te volgen, zie je herstelwerkcycli in het goedkeuringsproces. Ze kunnen ook wijzen op problemen met compliancebeleid of een onjuiste codering van facturen. Waar je het vindt Dit wordt vastgelegd als een specifiek resultaat-event in de SAP Business Workflow-logboeken die aan de factuur zijn gekoppeld. Vastleggen Extraheer events met de workflowstatus 'rejected' uit de SAP-workflowlogboeken. Eventtype explicit | |||
| Factuur doorgestuurd voor goedkeuring | De factuur is op basis van bedrijfsregels in een workflow geplaatst voor de benodigde goedkeuringen. Hiermee begint het goedkeuringssubproces. | ||
| Waarom dit belangrijk is Deze activiteit is het startpunt voor het meten van de KPI 'Average Invoice Approval Time' en het analyseren van knelpunten in het goedkeuringsproces. Waar je het vindt Dit kan worden vastgelegd in de SAP Business Workflow-logboeken, de SWW*-tabellen. Daarin staat het begin van een workflowinstantie die aan het factuurobject is gekoppeld, bijvoorbeeld BUS2081. Vastleggen Extraheer start-events van workflows uit de SAP-workflowlogboeken, bijvoorbeeld tabel SWW_WIHEAD, die aan het factuurdocument zijn gekoppeld. Eventtype explicit | |||
| Factuur geparkeerd | Dit is een factuur die in het systeem is ingevoerd, maar nog niet in het grootboek is geboekt. Vaak is dit een bewuste stap om een onvolledig document op te slaan voor latere verwerking of goedkeuring. | ||
| Waarom dit belangrijk is Door geparkeerde facturen te volgen, zie je vertragingen voordat het formele boekingsproces begint. Ook kunnen problemen met datavolledigheid of de eerste validatie zichtbaar worden. Waar je het vindt Deze status wordt afgeleid uit het documentstatusveld in de kop van het boekingsdocument (BKPF-BSTAT = 'V' voor geparkeerd). Het event vindt plaats zodra de status wordt ingesteld. Vastleggen Identificeer wijzigingsdocumenten voor tabel BKPF waarin het veld BSTAT is ingesteld op 'V' (Vor-erfasst/vooraf ingevoerd). Eventtype inferred | |||
| Goederenontvangst gematcht | Deze activiteit betekent dat de aantallen en bedragen op de factuur succesvol zijn gematcht met het bijbehorende document voor goederenontvangst. Dit is de laatste validatie in een 3-way-matchingscenario. | ||
| Waarom dit belangrijk is Door dit te volgen, zie je waar het 3-way-matchingproces niet efficiënt verloopt. Ook worden verschillen zichtbaar tussen ontvangen goederen en wat de leverancier factureert. Waar je het vindt Dit wordt afgeleid uit de aanwezigheid van een verwijzing naar een materiaaldocument voor de goederenontvangst op de factuurregel, vaak via de historie van het inkooporderitem. Vastleggen Afgeleid uit de aanwezigheid van een verwijzing naar een document voor goederenontvangst op de factuurregel, bijvoorbeeld in RSEG voor MIRO-facturen. Eventtype inferred | |||
| Inkooporder gematcht | Deze activiteit betekent dat de factuur succesvol is gematcht met de bijbehorende inkooporder. Dit is een belangrijke stap in het 3-way-matchingproces voor facturen op basis van inkoop. | ||
| Waarom dit belangrijk is Met deze activiteit meet je de efficiëntie van het matchingproces. Ook vormt ze de basis voor de KPI's '3-Way Matching Performance' en 'PO-Less Invoice Percentage'. Waar je het vindt Dit wordt afgeleid wanneer een factuurregel in tabel BSEG of ACDOCA een geldig inkoopordernummer (EBELN) en itemnummer (EBELP) bevat. Vastleggen Afgeleid uit de aanwezigheid van een verwijzing naar een inkooporder (BSEG-EBELN) op het factuurdocument bij het aanmaken ervan. Eventtype inferred | |||
| Verschil opgelost | Deze activiteit geeft aan dat een eerder vastgesteld probleem, dat waarschijnlijk een betalingsblokkade veroorzaakte, is onderzocht en opgelost. Dit wordt vastgelegd wanneer een betalingsblokkade van een factuur wordt verwijderd. | ||
| Waarom dit belangrijk is Door deze herstelwerkcyclus te volgen, krijg je de informatie voor het dashboard 'Invoice Discrepancy Rework Analysis'. Zo kun je meten hoeveel tijd en moeite het oplossen van fouten kost. Waar je het vindt Dit wordt afgeleid uit wijzigingsdocumenten waarin een betalingsblokkade wordt verwijderd. Het wijzigingslogboek voor het veld BSEG-ZLSPR is de belangrijkste bron. Vastleggen Identificeer wijzigingsdocumenten voor tabel BSEG waarin het veld ZLSPR van een waarde naar leeg wordt gewijzigd. Eventtype inferred | |||
| Vervaldatum van factuur verstreken | Een berekend event dat aangeeft dat de nettovervaldatum van de factuur is verstreken zonder dat er een betaling tegen is vereffend. Dit betekent dat de betaling te laat is of achterstallig is. | ||
| Waarom dit belangrijk is Deze activiteit is belangrijk voor het dashboard 'Payment Compliance & Aging'. Je kunt er achterstallige facturen proactief mee opsporen en beheren, en de oorzaken van te late betalingen analyseren. Waar je het vindt Dit is geen expliciet event in SAP. Het wordt berekend door de huidige systeemdatum te vergelijken met de nettovervaldatum, die is berekend op basis van BSEG-ZFBDT, de basisdatum, en de betalingsvoorwaarden. Vastleggen Berekend event dat wordt geactiveerd wanneer de timestamp van het event later is dan de nettovervaldatum van de factuur. Eventtype calculated | |||
Extractiegidsen
Stappen
- Vereisten en toegang: Zorg dat je een gebruiker hebt met leestoegang tot het SAP S/4HANA-databaseschema, meestal SAPABAP1 of vergelijkbaar, waarin de CDS-views staan. Je hebt een SQL-client nodig die verbinding kan maken met de SAP HANA-database, zoals SAP HANA Studio, DBeaver of een vergelijkbare databasetool.
- Bepaal de belangrijkste CDS-views: Voor deze extractie gebruik je vooral I_JournalEntry, I_JournalEntryItem, I_SupplierInvoiceAPI01, I_ChangeDocument, I_WorkflowStatusDetails en I_PaymentProposalItem. Maak jezelf vertrouwd met de belangrijkste velden.
- Bepaal de scope van de query: Open je SQL-client en maak verbinding met de SAP HANA-database. Bepaal voordat je de volledige query uitvoert welke data je wilt ophalen. Stel het juiste bronsysteem-ID, de periode voor facturen (CreationDateTime) en de relevante company codes in.
- Bereid de hoofdquery voor: Kopieer de volledige SQL-query uit het querygedeelte naar je SQL-client. De query gebruikt Common Table Expressions (CTE's) om eerst een basisselectie van facturen te maken en daarna een event log op te bouwen met data voor 15 verschillende activiteiten.
- Stel de queryparameters in: Zoek in de gekopieerde SQL-query de tijdelijke variabelen. Vervang '[YYYY-MM-DD]' door de begin- en einddatum van je analyseperiode. Vervang '[Your Company Code 1]' en '[Your Company Code 2]' door de lijst met SAP company codes die je wilt analyseren.
- Voer de extractiequery uit: Voer de volledige SQL-query uit. Afhankelijk van de hoeveelheid data en de gekozen periode kan dit enkele minuten tot enkele uren duren.
- Controleer de eerste resultaten: Bekijk na afloop de eerste paar honderd rijen. Controleer of de data consistent is, alle kolommen naar verwachting zijn gevuld en verschillende waarden voor ActivityName aanwezig zijn.
- Exporteer het event log: Exporteer de volledige resultatenset vanuit je SQL-client naar een CSV-bestand. Gebruik UTF-8-codering om problemen met tekens te voorkomen. Geef het bestand een duidelijke naam, bijvoorbeeld sap_s4hana_ap_event_log.csv.
- Bereid de upload voor: Controleer voordat je het bestand naar een process mining-tool uploadt of de kolomkoppen in het CSV-bestand exact overeenkomen met de vereiste attribuutnamen: Invoice, ActivityName, EventTime, SourceSystem, LastDataUpdate, UserName enzovoort.
- Upload naar een process mining-tool: Upload het gegenereerde CSV-bestand naar je process mining-platform. Koppel de kolommen aan de bijbehorende velden voor case-ID, activiteit en timestamp.
Configuratie
- Belangrijkste CDS-views: De extractie gebruikt een combinatie van standaard S/4HANA CDS-views. De belangrijkste views zijn:
- I_JournalEntry en I_JournalEntryItem: voor financiële documentkoppen, posten, boekingsgegevens en clearinginformatie.
- I_SupplierInvoiceAPI01: voor factuurspecifieke MM-gegevens, waaronder inkooporderverwijzingen en betalingsblokkeringen.
- I_ChangeDocument: om het exacte tijdstip van wijzigingen vast te leggen, zoals het instellen of verwijderen van een betalingsblokkering.
- I_WorkflowStatusDetails: om events uit de goedkeuringsworkflow van facturen op te halen.
- I_PaymentProposalItem: om te bepalen wanneer een factuur in een voorstel voor een betalingsrun is opgenomen.
- I_Supplier: om de data aan te vullen met leveranciersstamgegevens, zoals VendorName.
- Filteren op periode: Het is belangrijk om een periodefilter toe te passen om de hoeveelheid data te beperken. De meegeleverde query filtert op CreationDateTime in de CTE Invoices_Base. Voor een eerste analyse wordt een periode van 3 tot 6 maanden aanbevolen, zodat de prestaties beheersbaar blijven.
- Verplichte filters: Filter altijd op CompanyCode. Analyse van alle bedrijfs codes tegelijk kan zeer traag zijn en is mogelijk niet relevant voor de bedrijfsvoering. Filter ook op JournalEntryType om alleen leveranciersgerelateerde documenten te selecteren, bijvoorbeeld 'KR' en 'RE'.
- Vereisten: De databasegebruiker die de query uitvoert, moet SELECT-autorisatie hebben voor alle gebruikte CDS-views en het onderliggende HANA-schema. Toegang op applicatieniveau in de SAP GUI is niet voldoende.
- Aandacht voor prestaties: Rechtstreekse queries op I_ChangeDocument kunnen veel bronnen gebruiken. De meegeleverde query probeert dit te beperken door facturen eerst te filteren. Bij zeer grote datasets kun je de extractie buiten piekuren uitvoeren of in kleinere perioden opdelen.
a Voorbeeldquery 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'; Stappen
- Controleer of rechtstreekse leestoegang beschikbaar is tot het SAP HANA-schema met de relevante SAP S/4HANA-tabellen. Verzamel de connection string, inloggegevens, schemanaam en autorisaties die nodig zijn om BKPF, ACDOCA en eventuele aanvullende tabellen voor geparkeerde documenten, workflow, inkoop, goederenontvangst, betalingsvoorstellen, vereffening en terugboekingen te lezen.
- Controleer vóór uitvoering het technische datamodel in het doelsysteem. Valideer de fysieke namen, sleutelvelden, timestampvelden, relaties voor terugboekingen, betalingsrelaties en workflowopslag die het systeem gebruikt. Vervang elke placeholder tussen vierkante haken in de query door het bijbehorende object of veld uit het systeem. Ga er niet van uit dat workflowdata of data over geparkeerde documenten in één universele tabel staat.
- Configureer de extractieparameters. Stel [Start date], [End date], [Company code filter], [Document type filter] en [Schema name] in. Gebruik eerst een datumbereik van drie tot zes maanden. Breid dit pas uit nadat de prestaties en volledigheid zijn gecontroleerd.
- Voer de SQL-query uit in een goedgekeurde SAP HANA SQL-client, zoals SAP HANA Database Explorer of een andere geautoriseerde SQL-tool. De query levert één rij op voor elke expliciet geëxtraheerde activiteit en laat ProcessMind geen events afleiden.
- Valideer de resultatenset. Controleer of Invoice de case-identificatie bevat, ActivityName alle 15 vereiste activiteitsnamen bevat, EventTime is ingevuld en chronologisch plausibel is, SourceSystem SAP S/4HANA identificeert en LastDataUpdate het tijdstip van de extractievernieuwing bevat. Controleer dubbele events, relaties voor terugboekingen en documentkoppelingen voordat je de data laadt.
- Pas eventuele systeemspecifieke mappings toe. Koppel bijvoorbeeld de geconfigureerde bron voor geparkeerde documenten aan Invoice Parked, de geconfigureerde workflowbron aan Invoice Routed For Approval, Invoice Approved en Invoice Rejected, en de geconfigureerde betalingsbron aan Payment Proposal Created en Payment Executed. Bewaar de bronidentificaties in extra kolommen als controleerbaarheid nodig is.
- Exporteer het resultaat als een bestand met scheidingstekens of als een databaseresultatenset met één event per rij. Gebruik UTF-8-codering, bewaar timestamps in één consistente tijdzone, behoud exact de kolomnamen Invoice, ActivityName, EventTime, SourceSystem, LastDataUpdate, UserName, CompanyCode, VendorName, InvoiceAmount, PurchaseOrderNumber en InvoiceDueDate, en aggregeer activiteiten niet per factuur.
- Upload het event log naar ProcessMind en configureer Invoice als case-identificatie, ActivityName als activiteitskolom en EventTime als kolom voor het eventtijdstip. Controleer of optionele attributen aan de juiste velden zijn gekoppeld. Omdat ProcessMind het event log ongewijzigd inleest, moet elke activiteit die je wilt visualiseren vóór het uploaden al als rij aanwezig zijn.
Configuratie
- Datumbereik: Begin met drie tot zes maanden. Gebruik de boekingsdatum, aanmaakdatum van het document of de relevante datum van het bron-event, afhankelijk van de activiteit die je extraheert. Breid het bereik pas uit nadat je de queryduur en bronretentie hebt gecontroleerd.
- Filteren op company: Configureer [Company code filter] om de extractie te beperken tot de vereiste company codes. Als een beperking niet nodig is, gebruik dan een gecontroleerde selectie voor alle companies in plaats van een onbeperkte productiequery.
- Documentfilter: Configureer [Document type filter] pas nadat je hebt gecontroleerd welke documenttypen in het doelsysteem worden gebruikt voor leveranciersfacturen, creditnota's, geparkeerde documenten, betalingsdocumenten en terugboekingen.
- Mapping van schema en objecten: Vervang [Schema name] en elke bronverwijzing of elk bronveld tussen vierkante haken door waarden die je in het SAP S/4HANA-doelsysteem hebt gecontroleerd. Een rechtstreekse HANA-query moet worden aangepast aan de geactiveerde applicaties, uitbreidingen, workflowinrichting en het datamodel van het systeem.
- Omgaan met timestamps: Normaliseer alle timestamps naar één tijdzone. Als alleen een datum beschikbaar is, gebruik dan een gedocumenteerd standaardtijdstip en leg deze beperking vast in het datadictionary.
- Betekenis van events: Extraheer elke activiteit als een aparte rij. Voeg meerdere activiteiten niet samen tot één factuurrecord en verwacht niet dat ProcessMind matching-, goedkeurings-, vervaldatum- of vereffenings-events afleidt.
- Event voor vervaldatum: Genereer Invoice Due Date Passed alleen voor facturen waarvan de vervaldatum vóór het geconfigureerde evaluatietijdstip ligt en waarvoor op dat tijdstip geen vereffenings-event bestaat. De query gebruikt [Evaluation timestamp] voor deze berekening.
- Prestaties: Beperk de eerste periode en companyscope, filter op geïndexeerde of voor partitionering relevante velden, vermijd onnodig brede selecties en voer de query uit binnen een goedgekeurd rapportagevenster. Overweeg subsets van de brondata tijdelijk op te slaan als de productiequery langer duurt dan afgesproken.
- Vernieuwingsstrategie: Stel LastDataUpdate in op het tijdstip waarop de extractie is uitgevoerd. Gebruik voor incrementele loads een watermark op basis van de relevante wijzigingstimestamp uit de bron en neem een terugkijkperiode op om late updates en terugboekingen mee te nemen.
- Vereisten: Vereiste databaseautorisaties, goedgekeurde productietoegang, kennis van de Universal Journal-configuratie van het systeem, toegang tot de geconfigureerde bronnen voor geparkeerde documenten, inkoop, goederenontvangst, workflow, betalingen, vereffening en terugboekingen, plus eventuele vereiste SAP-licenties of goedkeuringen vanuit governance.
a Voorbeeldquery sql
WITH
params AS (
SELECT
TO_DATE('[Start date]') AS start_date,
TO_DATE('[End date]') AS end_date,
TO_TIMESTAMP('[Evaluation timestamp]') AS evaluation_ts,
TO_TIMESTAMP('[Extraction timestamp]') AS extraction_ts
FROM DUMMY
),
base_invoice AS (
SELECT
b.mandt,
b.bukrs,
b.belnr,
b.gjahr,
b.bldat,
b.budat,
b.cpudt,
b.cputm,
b.usnam,
b.blart,
b.xblnr,
b.stblg,
b.stjah,
a.lifnr,
a.wrbtr,
a.waers,
a.zfbdt,
a.zbd1t,
a.zbd2t,
a.zbd3t,
a.ebeln,
a.ebelp,
a.augbl,
a.augdt,
a.buzei,
v.name1 AS vendor_name,
CASE
WHEN a.zfbdt IS NOT NULL THEN ADD_DAYS(a.zfbdt, COALESCE(a.zbd1t, 0))
ELSE NULL
END AS invoice_due_date
FROM [Schema name].BKPF b
INNER JOIN [Schema name].ACDOCA a
ON a.mandt = b.mandt
AND a.rbukrs = b.bukrs
AND a.belnr = b.belnr
AND a.gjahr = b.gjahr
LEFT JOIN [Schema name].[Vendor master table] v
ON v.[Vendor key field] = a.lifnr
CROSS JOIN params p
WHERE b.bukrs IN ([Company code filter])
AND b.blart IN ([Document type filter])
AND b.cpudt BETWEEN p.start_date AND p.end_date
),
invoice_received AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Received' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(cpudt, 'YYYY-MM-DD') || ' ' || COALESCE(TO_VARCHAR(cputm), '00:00:00')) AS event_time,
CAST(usnam AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
),
invoice_parked AS (
SELECT
CAST([Parked invoice key field] AS NVARCHAR(40)) AS invoice,
'Invoice Parked' AS activity_name,
[Parked event timestamp field] AS event_time,
CAST([Parked user field] AS NVARCHAR(80)) AS user_name,
[Parked company code field] AS company_code,
[Parked vendor name field] AS vendor_name,
[Parked amount field] AS invoice_amount,
[Parked currency field] AS document_currency,
CAST([Parked purchase order field] AS NVARCHAR(40)) AS purchase_order_number,
[Parked due date field] AS invoice_due_date
FROM [Schema name].[Parked document source]
WHERE [Parked event date field] BETWEEN (SELECT start_date FROM params) AND (SELECT end_date FROM params)
AND [Parked company code field] IN ([Company code filter])
),
purchase_order_matched AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Purchase Order Matched' AS activity_name,
COALESCE([Purchase order match timestamp field], TO_TIMESTAMP(TO_VARCHAR(i.cpudt, 'YYYY-MM-DD') || ' ' || COALESCE(TO_VARCHAR(i.cputm), '00:00:00'))) AS event_time,
CAST(COALESCE([Purchase order match user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrBtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Purchase order match source] m
ON m.[Invoice document key field] = i.belnr
AND m.[Invoice company code field] = i.bukrs
AND m.[Invoice fiscal year field] = i.gjahr
WHERE i.ebeln IS NOT NULL
),
goods_receipt_matched AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Goods Receipt Matched' AS activity_name,
[Goods receipt match timestamp field] AS event_time,
CAST(COALESCE([Goods receipt match user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Goods receipt match source] g
ON g.[Invoice document key field] = i.belnr
AND g.[Invoice company code field] = i.bukrs
AND g.[Invoice fiscal year field] = i.gjahr
WHERE i.ebeln IS NOT NULL
),
invoice_blocked AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Blocked For Payment' AS activity_name,
[Payment block timestamp field] AS event_time,
CAST(COALESCE([Payment block user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment block source] b
ON b.[Invoice document key field] = i.belnr
AND b.[Invoice company code field] = i.bukrs
AND b.[Invoice fiscal year field] = i.gjahr
WHERE [Payment block value field] IS NOT NULL
),
discrepancy_resolved AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Discrepancy Resolved' AS activity_name,
[Payment block removal timestamp field] AS event_time,
CAST(COALESCE([Payment block removal user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment block history source] h
ON h.[Invoice document key field] = i.belnr
AND h.[Invoice company code field] = i.bukrs
AND h.[Invoice fiscal year field] = i.gjahr
WHERE [Previous payment block value field] IS NOT NULL
AND [New payment block value field] IS NULL
),
invoice_routed_for_approval AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Routed For Approval' AS activity_name,
[Workflow routed timestamp field] AS event_time,
CAST([Workflow initiator field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow routed event value]'
),
invoice_approved AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Approved' AS activity_name,
[Workflow approval timestamp field] AS event_time,
CAST([Workflow approver field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow approved event value]'
),
invoice_rejected AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Rejected' AS activity_name,
[Workflow rejection timestamp field] AS event_time,
CAST([Workflow rejector field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow rejected event value]'
),
invoice_posted AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Posted' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(budat, 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(usnam AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
WHERE stblg IS NULL
),
payment_proposal_created AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Proposal Created' AS activity_name,
[Payment proposal timestamp field] AS event_time,
CAST([Payment proposal user field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment proposal source] p
ON p.[Invoice document key field] = i.belnr
AND p.[Invoice company code field] = i.bukrs
AND p.[Invoice fiscal year field] = i.gjahr
),
payment_executed AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Executed' AS activity_name,
[Payment execution timestamp field] AS event_time,
CAST([Payment execution user field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment execution source] p
ON p.[Invoice document key field] = i.belnr
AND p.[Invoice company code field] = i.bukrs
AND p.[Invoice fiscal year field] = i.gjahr
),
invoice_due_date_passed AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Due Date Passed' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(i.invoice_due_date, 'YYYY-MM-DD') || ' 23:59:59') AS event_time,
CAST(i.usnam AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
WHERE i.invoice_due_date IS NOT NULL
AND TO_TIMESTAMP(TO_VARCHAR(i.invoice_due_date, 'YYYY-MM-DD') || ' 23:59:59') < (SELECT evaluation_ts FROM params)
AND i.augbl IS NULL
),
payment_cleared AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Cleared' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(i.augdt, 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(i.usnam AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
WHERE i.augbl IS NOT NULL
AND i.augdt IS NOT NULL
),
invoice_cancelled AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Cancelled' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR([Reversal posting date field], 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(COALESCE([Reversal user field], usnam) AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
WHERE stblg IS NOT NULL
),
all_events AS (
SELECT * FROM invoice_received
UNION ALL SELECT * FROM invoice_parked
UNION ALL SELECT * FROM purchase_order_matched
UNION ALL SELECT * FROM goods_receipt_matched
UNION ALL SELECT * FROM invoice_blocked
UNION ALL SELECT * FROM discrepancy_resolved
UNION ALL SELECT * FROM invoice_routed_for_approval
UNION ALL SELECT * FROM invoice_approved
UNION ALL SELECT * FROM invoice_rejected
UNION ALL SELECT * FROM invoice_posted
UNION ALL SELECT * FROM payment_proposal_created
UNION ALL SELECT * FROM payment_executed
UNION ALL SELECT * FROM invoice_due_date_passed
UNION ALL SELECT * FROM payment_cleared
UNION ALL SELECT * FROM invoice_cancelled
)
SELECT
invoice AS "Invoice",
activity_name AS "ActivityName",
event_time AS "EventTime",
'SAP S/4HANA' AS "SourceSystem",
(SELECT extraction_ts FROM params) AS "LastDataUpdate",
user_name AS "UserName",
company_code AS "CompanyCode",
vendor_name AS "VendorName",
invoice_amount AS "InvoiceAmount",
purchase_order_number AS "PurchaseOrderNumber",
invoice_due_date AS "InvoiceDueDate"
FROM all_events
WHERE invoice IS NOT NULL
AND event_time IS NOT NULL
ORDER BY "Invoice", "EventTime", "ActivityName"; Stappen
- Specificatie en ontwerp: Stem vóór het programmeren met businessanalisten de exacte triggercondities en datavelden voor elk van de 15 vereiste activiteiten af. Bepaal welke SAP-tabellen, documenttypen, bijvoorbeeld 'KR' en 'RE', en company codes binnen de scope vallen.
- ABAP-programma aanmaken: Open de ABAP Editor met transactiecode SE38. Maak een nieuw uitvoerbaar programma aan, bijvoorbeeld Z_PM_AP_INVOICE_EXTRACT. Geef het programma een duidelijke titel en stel de applicatie in op 'Financial Accounting'.
- Selectiescherm definiëren: Definieer in het programma een selectiescherm met de sleutelwoorden PARAMETERS en SELECT-OPTIONS. Hiermee kunnen gebruikers het extractiedatumbereik voor de aanmaakdatum van facturen, de doel-Company Codes (BUKRS) en relevante factuurdocumenttypen (BLART) opgeven. Voeg ook een parameter toe voor het pad naar het uitvoerbestand op de applicatieserver.
- Datadeclaraties: Definieer een interne tabelstructuur die overeenkomt met het uiteindelijke event log-formaat, bijvoorbeeld TY_EVENT_LOG, inclusief alle vereiste en aanbevolen attributen. Declareer interne tabellen voor data uit verschillende SAP-brontabellen, zoals BKPF, BSEG, RBKP, RSEG, CDHDR, CDPOS en REGUH.
- Hoofdselectie van data: Start de extractielogica door de primaire factuurset uit RBKP, logistieke facturen, en BKPF, financiële facturen, te selecteren op basis van de criteria op het selectiescherm. Sla de primaire factuursleutels op in een interne tabel om de daaropvolgende data-opzoekacties aan te sturen.
- Activiteiten na elkaar extraheren: Voer voor elke factuur in de hoofdset een reeks selecties uit om de timestamps en details van elke bedrijfsactiviteit te vinden. Vraag bijvoorbeeld CDHDR en CDPOS op voor wijzigingen in betalingsblokkades, REGUH en REGUP voor data over betalingsruns en BKPF voor details van terugboekingsdocumenten. Voeg voor elke gevonden activiteit een nieuw record toe aan de uiteindelijke event log-tabel.
- Logica voor berekende events: Implementeer ABAP-logica voor activiteiten die niet rechtstreeks in een tabelveld staan. Gebruik voor het event 'Invoice Due Date Passed' de vervaldatum van de factuur, BSEG-ZFBDT plus betalingsvoorwaarden, en de vereffeningsdatum, BSEG-AUGDT. Als de vereffeningsdatum na de vervaldatum ligt, maak je een nieuw eventrecord aan met de vervaldatum als timestamp.
- Datatransformatie en verrijking: Vul tijdens het verzamelen van de data voor elke activiteit alle vereiste attributen in. Zoek hiervoor leveranciersnamen op in LFA1, zet datums en tijden om naar één timestampstring met CONCATENATE...INTO... en stel de waarde van SourceSystem in.
- Uitvoerbestand genereren: Gebruik, nadat alle facturen en bijbehorende activiteiten zijn verwerkt en verzameld in de uiteindelijke interne tabel, de statements OPEN DATASET, LOOP AT ... TRANSFER en CLOSE DATASET om de data naar het bestandspad op de applicatieserver te schrijven.
- Downloaden en voorbereiden voor upload: Gebruik transactiecode CG3Y om het gegenereerde bestand van de applicatieserver naar je lokale computer te downloaden. Sla het bestand op als CSV in UTF-8-indeling. Controleer vóór het uploaden naar de process mining-tool of de kolomkoppen overeenkomen met de vereiste attributen, zoals Invoice, ActivityName en EventTime.
Configuratie
- Datumbereik: Definieer de selectieoptie P_CPUDT voor de aanmaakdatum van de factuur (BKPF-CPUDT of RBKP-CPUDT). Voor een eerste analyse raden we een periode van 6 tot 12 maanden aan.
- Company code (P_BUKRS): Een verplichte SELECT-OPTIONS-parameter om op specifieke company codes te filteren. Verwerking van alle company codes tegelijk wordt afgeraden, tenzij dit echt nodig is.
- Factuurdocumenttype (P_BLART): Een SELECT-OPTIONS-parameter om op relevante factuurdocumenttypen te filteren. Veelvoorkomende typen zijn 'KR' (leveranciersfactuur), 'KG' (creditnota van leverancier) en 'RE' (logistieke factuurverificatie).
- Uitvoeringsmodus: Voer het programma bij grote hoeveelheden data uit als background job (SM36/SM37) om time-outs in het voorgrondproces te voorkomen. Plan de job buiten piekuren.
- Pad naar uitvoerbestand: Een PARAMETER om het bestandspad en de bestandsnaam op de SAP-applicatieserver op te geven, bijvoorbeeld in de map /tmp/. Het bestand wordt hier opgeslagen voordat je het downloadt.
- Vereisten: De gebruiker die het rapport uitvoert, heeft autorisatie nodig om FI-, CO- en MM-tabellen te lezen, waaronder BKPF, BSEG, RBKP, RSEG en LFA1, plus de tabellen voor wijzigingsdocumenten, CDHDR en CDPOS, en workflowtabellen. Daarnaast is autorisatieobject S_DATASET nodig om bestanden naar de applicatieserver te schrijven.
a Voorbeeldquery 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. Klaar om aan de slag te gaan?
Gebruik deze template om je process mining-initiatief te starten en flinke efficiëntiewinst te behalen in je crediteurenproces. Zet vandaag de stap naar een efficiënter proces.
Voorkom boetes voor te late betaling: optimaliseer vandaag je factuurverwerking
Verlaag de verwerkingskosten met 60% en voorkom dubbele betalingen.
Je hebt geen creditcard nodig. Je kunt binnen enkele minuten beginnen.