Datatemplate voor de verwerking van crediteurenfacturen
Datatemplate voor de verwerking van crediteurenfacturen
- Aanbevolen attributen voor een volledige analyse
- Belangrijke procesactiviteiten om bij te houden
- Stapsgewijze uitleg voor data-extractie
Attributen voor de verwerking van crediteurenfacturen
| Naam | Beschrijving | ||
|---|---|---|---|
| Activiteit ActivityName | De naam van een specifieke bedrijfsgebeurtenis of stap in het factuurverwerkingsproces. | ||
| Beschrijving De activiteit staat voor een afzonderlijke fase of handeling in het crediteurenproces, zoals 'Factuur ontvangen', 'Factuur geboekt' of 'Betaling uitgevoerd'. Deze activiteiten vormen de bouwstenen van de proceskaart. Activiteiten analyseren is een belangrijk onderdeel van process mining. Je kunt er de processtroom mee visualiseren, veelvoorkomende routes herkennen, afwijkingen van het standaardproces opsporen en de frequentie en duur van elke stap meten. De volgorde van activiteiten voor een factuur vormt het traject door het proces. Waarom dit belangrijk is De activiteit beschrijft de processtappen. Zo kun je de processtroom visualiseren, bottlenecks opsporen en herstelcycli herkennen. Waar vind je dit? Afgeleid uit verschillende bronnen, zoals wijzigingen in de documentstatus (bijvoorbeeld BKPF-BSTAT), wijzigingsdocumenten (tabellen CDHDR/CDPOS) of workflowlogboeken. Hiervoor is doorgaans aangepaste extractielogica nodig. Voorbeelden Factuur ontvangenFactuur goedgekeurdBetaling uitgevoerdFactuur geblokkeerd voor betaling | |||
| Factuur Invoice | De unieke identificatiecode van een factuurdocument. Deze dient als de primaire case-ID voor het crediteurenproces. | ||
| Beschrijving De factuur is het centrale object dat alle bijbehorende activiteiten verbindt, van ontvangst tot betaling. In SAP S/4HANA bestaat de samengestelde sleutel doorgaans uit de bedrijfscode (BUKRS), een uniek documentnummer (BELNR) en het boekjaar (GJAHR). Door facturen te analyseren, krijg je een volledig beeld van het hele factuurproces. Dit vormt de basis voor het berekenen van belangrijke metrieken, zoals de totale doorlooptijd, het opsporen van bottlenecks bij afzonderlijke facturen en inzicht in de verschillende routes die een factuur door het proces kan volgen. Waarom dit belangrijk is Deze code identificeert het traject van elke factuur. Zo kun je het volledige proces volgen en de prestaties per case analyseren. Waar vind je dit? Dit is een samengestelde sleutel die wordt afgeleid uit tabellen BKPF (kop van boekhoudkundig document) of RBKP (documentkop: ontvangst van factuur), met de velden BUKRS, BELNR en GJAHR. Voorbeelden 1000-1900000001-20231710-1900000002-20232000-5100000003-2024 | |||
| Tijdstip van gebeurtenis EventTime | De exacte datum en tijd waarop de activiteit plaatsvond. | ||
| Beschrijving Het tijdstip van de gebeurtenis is de timestamp van elke activiteit en geeft de chronologische volgorde van gebeurtenissen voor een factuur weer. Deze data is nodig om de processtroom te begrijpen en analyses op basis van tijd uit te voeren. Bij analyses gebruik je het tijdstip van de gebeurtenis om activiteiten in de juiste volgorde te zetten, doorlooptijden tussen stappen te berekenen, wachttijden vast te stellen en de procesprestaties over verschillende perioden te vergelijken, bijvoorbeeld van maand tot maand. Dit vormt de basis voor alle KPI’s op basis van tijdsduur. Waarom dit belangrijk is Deze timestamp is nodig om gebeurtenissen chronologisch te ordenen en alle tijdsgebonden metrieken te berekenen, zoals doorlooptijden en tijdsduur. Die zijn essentieel voor process mining. Waar vind je dit? Afkomstig uit verschillende datum- en tijdvelden in SAP-tabellen, zoals aanmaakdatum (BKPF-CPUDT), boekingsdatum (BKPF-BUDAT), afletterdatum (BSAK-AUGDT) of timestamps in wijzigingslogboeken (CDHDR-UDATE/UTIME). Voorbeelden 2023-10-01T09:00:00Z2023-10-05T14:30:15Z2023-10-15T11:21:05Z | |||
| Bronsysteem SourceSystem | Het systeem waaruit de data is opgehaald. | ||
| Beschrijving Dit attribuut geeft aan waar de procesdata vandaan komt. Voor deze weergave is de waarde doorgaans 'SAP S/4HANA'. In omgevingen met meerdere ERP-systemen of geïntegreerde systemen is dit veld belangrijk om de herkomst van data te volgen en gegevens gescheiden te houden. Het zorgt ervoor dat je de juiste dataset analyseert en helpt problemen met de datakwaliteit op te sporen door ze naar de bron te herleiden. Waarom dit belangrijk is Geeft aan waar de data vandaan komt. Dit is belangrijk voor datagovernance, probleemoplossing en omgevingen met meerdere systemen. Waar vind je dit? Dit is doorgaans een vaste waarde die tijdens het ophalen van de data wordt toegevoegd om de herkomst van de dataset aan te geven. Voorbeelden SAP S/4HANASAP ECC 6.0S4H_PROD_100 | |||
| Laatste data-update LastDataUpdate | De timestamp die aangeeft wanneer de data voor deze registratie voor het laatst vanuit het bronsysteem is bijgewerkt. | ||
| 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 aangeeft hoe actueel de data in de analyse is. Zo weet je hoe actueel de procesanalyse is. Dit helpt bij het bepalen van verwachtingen over vertraging in de data, het plannen van data-updates en het bewaken van de data-integriteit. Waarom dit belangrijk is Geeft aan hoe actueel de data is, zodat je weet hoe recent de procesanalyse is. Waar vind je dit? Deze waarde wordt gegenereerd en aan elke registratie toegevoegd wanneer de data uit het bronsysteem wordt opgehaald. Voorbeelden 2024-05-20T04:00:00Z2024-05-21T04:00:00Z | |||
| Bedrijfscode CompanyCode | De organisatie-eenheid waarvoor de factuur wordt verwerkt. | ||
| Beschrijving Een bedrijfscode is de kleinste organisatie-eenheid waarvoor een volledige, zelfstandige boekhouding kan worden opgesteld voor externe verslaglegging. In het crediteurenproces staat deze voor de juridische entiteit die de leverancier moet betalen. Door bedrijfscodes te vergelijken, kun je de procesprestaties van verschillende juridische entiteiten binnen de organisatie naast elkaar zetten. Zo zie je welke onderdelen volgens de standaardprocessen werken en waar de efficiëntie lager is, de doorlooptijden langer zijn of meer herstelwerk nodig is. Waarom dit belangrijk is Maakt het mogelijk om procesprestaties tussen juridische entiteiten te vergelijken. Zo spoor je problemen en goede werkwijzen per regio of bedrijfseenheid op. Waar vind je dit? Te vinden in documentkopgegevenstabellen, voornamelijk 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 het totale bedrag van de factuur zoals de leverancier die heeft ingediend. Het omvat de kosten van goederen of diensten, belastingen en eventuele andere kosten, vóór aftrek van kortingen of andere bedragen. Het factuurbedrag is een belangrijk financieel attribuut voor allerlei analyses. Je kunt er facturen met hoge bedragen mee prioriteren, de financiële gevolgen van procesvertragingen vaststellen, zoals kosten voor te late betaling van grote facturen, en het proces opdelen in segmenten. Zo kun je nagaan of facturen met hoge bedragen een andere goedkeuringsroute volgen. Het bedrag is ook nodig om mogelijke dubbele betalingen op te sporen. Waarom dit belangrijk is Geeft financiële context aan het proces. Zo kun je op basis van bedragen analyseren, facturen met hoge bedragen prioriteren en financiële gevolgen berekenen. Waar vind je dit? Te vinden in tabellen zoals RBKP-RMWWR (brutofactuurbedrag) voor MM-facturen, of te berekenen op basis van 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 bevat de SAP-gebruikers-ID van degene die een activiteit heeft uitgevoerd, zoals het boeken, goedkeuren of afletteren van een factuur. Zo worden processtappen aan individuele gebruikers gekoppeld. Door gebruikersnamen te analyseren, krijg je inzicht in de verdeling van het werk, zie je wie goed presteert en ontdek je wie mogelijk extra training nodig heeft. Dit is ook belangrijk voor het analyseren van bottlenecks bij goedkeuringen in dashboards. Zo zie je welke goedkeurders vertraging veroorzaken. Waarom dit belangrijk is Koppelt activiteiten aan specifieke personen. Zo kun je prestaties, werkbelasting en naleving van functiescheiding analyseren. Waar vind je dit? Meestal te vinden in kopgegevenstabellen, zoals BKPF-USNAM (ingevoerd door), of in wijzigingsdocumenttabellen, zoals CDHDR-USERNAME (gewijzigd door). Voorbeelden ABROWNJSMITHAP_AUTOMATION | |||
| Inkoopordernummer PurchaseOrderNumber | De unieke identificatiecode van de inkooporder die bij de factuur hoort, indien van toepassing. | ||
| Beschrijving Dit attribuut koppelt een factuur aan een vooraf goedgekeurde inkooporder (PO). De aanwezigheid van een inkoopordernummer vormt de basis voor het 3-way matching-proces (inkooporder-factuur-goederenontvangst). Dit attribuut is belangrijk voor analyses van compliance en efficiëntie. Je gebruikt het om de KPI 'Percentage facturen zonder inkooporder' te berekenen, die laat zien in hoeverre het inkoopbeleid wordt nageleefd. Het vormt ook de basis voor het dashboard 'Prestaties van 3-way matching', waarmee je het matchproces voor facturen met een inkooporder analyseert. Waarom dit belangrijk is Belangrijk om de efficiëntie van 3-way matching te analyseren en naleving van het inkoopbeleid te meten door facturen zonder inkooporder op te sporen. Waar vind je dit? Te vinden in factuurregelstabellen, 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. De naam is gekoppeld via het leveranciersnummer op het factuurdocument. Met leveranciersanalyse krijg je inzicht in leveranciersrelaties en procesproblemen bij specifieke leveranciers. Je kunt bijvoorbeeld nagaan welke leveranciers de meeste facturen met afwijkingen indienen en of strategische leveranciers steeds op tijd worden betaald. Samen met het factuurnummer en het bedrag is dit ook een belangrijk veld om mogelijke dubbele betalingen op te sporen. Waarom dit belangrijk is Maakt het mogelijk om procesprestaties per leverancier te analyseren. Zo spoor je problematische leveranciers op en beheer je strategische leveranciersrelaties beter. Waar vind je dit? Opgehaald uit de leveranciersstamgegevenstabel LFA1 (veld NAME1), via het leveranciersnummer (LIFNR) in BKPF of RBKP. Voorbeelden Kantoorbenodigdheden Inc.Global Consulting GroupMachineonderdelen GmbH | |||
| Vervaldatum factuur InvoiceDueDate | De datum waarop de factuur aan de leverancier betaald moet zijn. | ||
| Beschrijving De vervaldatum van de factuur is de uiterste betaaldatum. Door vóór die datum te betalen, voorkom je kosten voor te late betaling en houd je de relatie met de leverancier goed. De datum wordt berekend op basis van de basisdatum van de factuur en de betalingsvoorwaarden die met de leverancier zijn afgesproken. Deze datum is belangrijk voor het dashboard 'Naleving van betalingsafspraken en ouderdom' en de KPI 'Percentage betalingen op tijd'. Door de vervaldatum met de werkelijke betaaldatum te vergelijken, zie je of betalingen op tijd, eerder of te laat worden gedaan. Dat heeft financiële gevolgen en beïnvloedt de relatie met de leverancier. Waarom dit belangrijk is Dit is de belangrijkste basis voor analyses van betalingen op tijd. Je kunt er de betaalprestaties mee meten en de gevolgen voor leveranciersrelaties en kosten voor te late betaling vaststellen. Waar vind je dit? 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 | |||
| Automatisch uitgevoerd IsAutomated | Een aanduiding die aangeeft of de activiteit automatisch door het systeem is uitgevoerd of door een gebruiker. | ||
| Beschrijving Dit booleaanse attribuut maakt onderscheid tussen activiteiten die door een persoon zijn gestart en activiteiten die zijn uitgevoerd door systeemtaken, workflows of bots. Een automatische betaalrun of een door het systeem geboekte factuur krijgt bijvoorbeeld de aanduiding automatisch. Door dit attribuut te analyseren, krijg je inzicht in de mate van automatisering van het crediteurenproces. Je kunt het gebruiken om het resultaat van automatiseringsinitiatieven te meten, de efficiëntie van automatische en handmatige stappen te vergelijken en mogelijkheden voor verdere automatisering op te sporen. Waarom dit belangrijk is Helpt de mate van automatisering in het proces te meten. Zo kun je de effectiviteit ervan analyseren en mogelijkheden voor verdere verbetering opsporen. Waar vind je dit? Afgeleid van de gebruikersnaam, bijvoorbeeld systeemgebruikers-ID’s zoals 'SAP_SYSTEM' of 'BATCHUSER', of van specifieke transactiecodes voor geautomatiseerde taken. Voorbeelden truefalse | |||
| Betalingsvoorwaarden PaymentTerms | De afspraken met de leverancier over de betaling van een factuur, vaak met mogelijkheden voor korting. | ||
| Beschrijving Betalingsvoorwaarden bepalen wanneer een factuur betaald moet zijn en of er korting geldt bij vroege betaling. Zo kan de voorwaarde ‘Z001’ betekenen: ‘Betaling binnen 30 dagen, met 2% korting bij betaling binnen 10 dagen’. Dit attribuut vormt de basis voor het dashboard ‘Percentage benutting van betalingskortingen’. Door de betalingsvoorwaarden te analyseren, kun je vaststellen voor welke facturen korting mogelijk was. Vergelijk dit met de daadwerkelijk verkregen kortingen om gemiste besparingen te vinden en de efficiëntie van het betalingsproces te meten. Waarom dit belangrijk is Dit is essentieel om mogelijkheden voor betalingskorting te analyseren, de financiële prestaties van het betalingsproces te meten en gemiste besparingen op te sporen. Waar vind je dit? Te vinden in leveranciersposten, in tabel BSEG-ZTERM of in de factuurkop in RBKP-ZTERM. Voorbeelden Z0010001NT30 | |||
| Clearingdatum ClearingDate | De datum waarop de betaling is gedaan en de factuur is afgeboekt van de openstaande posten. | ||
| Beschrijving De clearingdatum geeft aan wanneer de factuur financieel is afgewikkeld. Op deze datum vindt de activiteit ‘Betaling verwerkt’ plaats. Voor de meeste succesvol afgehandelde facturen is dit de laatste stap. Deze datum wordt gebruikt om de daadwerkelijke betaaldatum te vergelijken met de vervaldatum van de factuur. Daarom is de datum essentieel voor de KPI ‘Percentage tijdige betalingen’ en voor analyses van de betalingsprestaties. Ook is dit het eindpunt voor de berekening van de totale doorlooptijd van een factuur. Waarom dit belangrijk is Geeft aan wanneer een factuur definitief is afgewikkeld. Dit is het eindpunt voor de berekening van de doorlooptijd en de basis voor analyses van tijdige betalingen. Waar vind je dit? Te vinden in tabellen met afgeboekte posten, zoals BSAK-AUGDT voor leveranciers. Voorbeelden 2023-10-282023-11-142024-01-09 | |||
| Factuurdocumentsoort InvoiceDocumentType | Een classificatie van het factuurdocument die bepaalt hoe het in SAP wordt verwerkt. | ||
| Beschrijving De documentsoort is een belangrijk configuratie-element in SAP waarmee boekhoudkundige documenten worden ingedeeld. 'KR' wordt bijvoorbeeld doorgaans gebruikt voor leveranciersfacturen, 'RE' voor MM-facturen en 'KG' voor creditnota’s van leveranciers. De documentsoort bepaalt onder meer de nummerreeks en welke velden verplicht zijn. Door in procesanalyses op documentsoort te filteren, kun je de processtromen voor verschillende soorten facturen vergelijken. Zo kan de goedkeuringsroute voor een creditnota afwijken van die voor een gewone factuur. Dit is handig voor het dashboard 'Varianten in de goedkeuringsroute van facturen'. Waarom dit belangrijk is Maakt het mogelijk het proces op te delen naar factuursoort. Zo zie je verschillen in verwerkingsroutes en doorlooptijden. Waar vind je dit? Rechtstreeks uit de documentkopgegevenstabel, veld BKPF-BLART. Voorbeelden KRREKG | |||
| Factuurnummer leverancier VendorInvoiceNumber | Het factuurnummer dat de leverancier op de factuur heeft vermeld. | ||
| Beschrijving Dit is het referentienummer uit de eigen boekhouding van de leverancier, zoals vermeld op de papieren of digitale factuur. Het wordt handmatig ingevoerd of bij ontvangst van de factuur met OCR uitgelezen. Dit veld is belangrijk voor de dagelijkse bedrijfsvoering en voor analyses, met name voor het dashboard ‘Mogelijke dubbele factuurbetalingen’. Een veelgebruikte manier om dubbele betalingen op te sporen, is zoeken naar meerdere interne facturen met dezelfde leveranciersnaam, hetzelfde factuurnummer van de leverancier en hetzelfde factuurbedrag. Dit is de belangrijkste externe referentie voor een factuur. Waarom dit belangrijk is Dit veld is belangrijk om mogelijke dubbele betalingen op te sporen en is de belangrijkste externe referentie in de communicatie met leveranciers. Waar vind je dit? Opgeslagen in het veld ‘Referentie’ 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. Zo weet je hoe je financiële bedragen moet interpreteren. Bij een internationale 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 correct verwerken, bijvoorbeeld door alle bedragen om te rekenen naar één rapportagevaluta of de analyse per valuta uit te splitsen om financiële activiteiten per regio te bekijken. Waarom dit belangrijk is Geeft de context die nodig is om het factuurbedrag goed te interpreteren en financiële analyses en rapportages correct uit te voeren, vooral bij internationale organisaties. Waar vind je dit? Te vinden in tabellen met documentkoppen, voornamelijk BKPF-WAERS of RBKP-WAERS. Voorbeelden USDEURGBPJPY | |||
| Korting verkregen DiscountTaken | Een booleaanse vlag die aangeeft of een betalingskorting succesvol is toegepast. | ||
| Beschrijving Dit attribuut geeft aan of er daadwerkelijk betalingskorting is verkregen bij de betaling van de factuur. Het is een belangrijk onderdeel van het meten van de financiële efficiëntie van het crediteurenproces. Deze vlag vormt de basis voor de KPI ‘Percentage benutting van betalingskortingen’. Filter op facturen waarvoor korting mogelijk was op basis van de betalingsvoorwaarden en analyseer vervolgens deze vlag. Zo bereken je precies hoeveel geld is bespaard en hoeveel kortingsmogelijkheden zijn gemist. Dit geeft een helder, meetbaar beeld van de prestaties van het crediteurenproces. Waarom dit belangrijk is Meet rechtstreeks hoe goed beschikbare betalingskortingen worden benut. Dit heeft direct invloed op het bedrijfsresultaat. Waar vind je dit? Afgeleid door te controleren of het kortingsbedrag (BSEG-SKNTO) op het betalingsdocument groter is dan nul. Voorbeelden truefalse | |||
| Reden voor betalingsblokkade BlockingReason | De reden waarom een factuur is geblokkeerd voor betaling, bijvoorbeeld vanwege een afwijking. | ||
| Beschrijving Als een factuur niet door een controle komt tijdens de 3-way match of een andere verificatiestap, wordt de betaling geblokkeerd. De reden voor de betalingsblokkade geeft aan wat er aan de hand is, bijvoorbeeld een afwijking in de hoeveelheid of prijs, of een ontbrekende goederenontvangst. Dit attribuut is essentieel voor het dashboard ‘Analyse van herhaalwerk bij factuurafwijkingen’. Door te analyseren hoe vaak verschillende redenen voor een betalingsblokkade voorkomen, kun je de oorzaken van inefficiënte processen achterhalen. Komt bijvoorbeeld ‘Prijsafwijking’ vaak voor, dan kan dat wijzen op problemen met stamgegevens in het inkoopsysteem. Waarom dit belangrijk is Geeft direct inzicht in de oorzaken van factuurafwijkingen en herhaalwerk, zodat je gericht processen kunt verbeteren. Waar vind je dit? Opgeslagen in tabellen met factuurregels, zoals RSEG, in velden die beginnen met SPGR* (bijvoorbeeld SPGRP, SPGRQ, SPGRT). Ook te vinden in RBKP_BLOCKED. Voorbeelden PrijsafwijkingHoeveelheidsafwijkingOntbrekende goederenontvangst | |||
| Te laat betaald IsLatePayment | Een booleaanse vlag die aangeeft of de factuur na de vervaldatum is betaald. | ||
| Beschrijving Dit berekende attribuut is een eenvoudige waar/onwaar-vlag die aangeeft of een factuur na de officiële vervaldatum is betaald. De waarde wordt bepaald door de ‘Clearingdatum’ te vergelijken met de ‘Vervaldatum van de factuur’. Deze vlag vereenvoudigt analyses voor het dashboard ‘Betalingscompliance en ouderdom’ en de KPI ‘Percentage tijdige betalingen’. Je kunt er eenvoudig mee filteren en totalen berekenen, zoals het aantal te late betalingen en het percentage tijdige betalingen. Ook kun je leveranciers of bedrijfscodes opsporen waarbij betalingen vaak te laat zijn. Waarom dit belangrijk is Meet rechtstreeks of de betalingsvoorwaarden worden nageleefd, vereenvoudigt de berekening van de KPI voor tijdige betalingen en helpt gebieden met slechte betalingsprestaties op te sporen. Waar vind je dit? Berekend attribuut. De logica is: IF ClearingDate > InvoiceDueDate THEN true ELSE false. Voorbeelden truefalse | |||
Activiteiten voor de verwerking van crediteurenfacturen
| Activiteit | Beschrijving | ||
|---|---|---|---|
| Betaling afgeletterd | Deze activiteit markeert de definitieve afsluiting van de factuur. De betaling en de factuur worden in het subgrootboek met elkaar verrekend. Hiermee is het proces afgerond. | ||
| Waarom dit belangrijk is Als definitief eindpunt van het proces is deze activiteit nodig voor een nauwkeurige berekening van de totale doorlooptijd. De activiteit bevestigt dat de verplichting is voldaan. Waar vind je dit? Dit is een expliciete gebeurtenis. De gebeurtenis wordt vastgelegd wanneer het veld voor de afletterdatum (AUGDT) op de leveranciersregel van het factuurdocument (tabel BSEG) is ingevuld. Vastleggen Gebruik de afletterdatum (BSEG-AUGDT) van de factuurregel. Gebeurtenistype explicit | |||
| Betaling uitgevoerd | De factuur is betaald. Dit wordt vastgelegd wanneer de betaalrun is voltooid en een betalingsdocument is aangemaakt en geboekt. | ||
| Waarom dit belangrijk is Deze activiteit is belangrijk voor de analyse van de kasstroom en voor het meten van de KPI 'Percentage betalingen op tijd'. Vergelijk hiervoor de betaaldatum met de vervaldatum van de factuur. Waar vind je dit? Dit wordt vastgelegd aan de hand van de boekingsdatum van het betalingsdocument waarmee de factuur wordt afgeletterd. Het nummer van het betalingsdocument staat in het veld voor het afletterdocument (AUGBL) op de factuurregel (BSEG). Vastleggen Zoek de boekingsdatum (BUDAT) van het betalingsdocument waarmee de factuurregel wordt afgeletterd. Gebeurtenistype explicit | |||
| Factuur geannuleerd | Het factuurdocument is teruggeboekt, waardoor de financiële gevolgen ervan ongedaan zijn gemaakt. Dit is een alternatieve eindstatus van het proces, vaak vanwege onjuiste invoer of een geschil met de leverancier. | ||
| Waarom dit belangrijk is Door annuleringen te volgen, ontdek je oorzaken van procesproblemen, zoals dubbele inzendingen of onjuiste factuurgegevens. Dat kan wijzen op problemen eerder in het proces. Waar vind je dit? Dit wordt expliciet vastgelegd wanneer een terugboekingsdocument wordt aangemaakt. In de kop van het oorspronkelijke document (BKPF) worden het nummer van het terugboekingsdocument (STBLG) en de reden voor terugboeking ingevuld. Vastleggen Zoek de boekingsdatum van het terugboekingsdocument. Dit document is gekoppeld via de kop van het oorspronkelijke document (BKPF-STBLG). Gebeurtenistype explicit | |||
| Factuur geblokkeerd voor betaling | Het systeem heeft de factuur automatisch of handmatig geblokkeerd, waardoor betaling niet mogelijk is. Dit komt meestal door afwijkingen in prijs of hoeveelheid, of doordat goedkeuringen ontbreken. | ||
| Waarom dit belangrijk is Dit is een belangrijke aanwijzing voor problemen en herstelwerk. Door de redenen en duur van blokkades te analyseren, ontdek je de oorzaken van betalingsvertragingen en inefficiënties in het proces. Waar vind je dit? Dit is een expliciete status in het veld voor de betalingsblokkadecode (ZLSPR) op de leveranciersregel van het boekhoudkundige document (tabel BSEG). Vastleggen Vastgelegd via wijzigingsdocumenten wanneer het veld BSEG-ZLSPR een blokkeringsreden bevat. Gebeurtenistype explicit | |||
| Factuur geboekt | De factuur is officieel vastgelegd in het grootboek en vormt daarmee een financiële verplichting. Een geparkeerd document wordt geboekt, of de factuur wordt meteen geboekt. | ||
| Waarom dit belangrijk is Dit is een belangrijke financiële mijlpaal. De boeking bevestigt dat het bedrijf moet betalen en is vaak een voorwaarde om de betaling in te plannen. Waar vind je dit? Deze gebeurtenis wordt vastgesteld aan de hand van de boekingsdatum (BUDAT) in de documentkop (BKPF). Bij een geboekt document is de documentstatus (BKPF-BSTAT) leeg. Vastleggen Gebruik de boekingstimestamp (BKPF-BUDAT) voor documenten die niet zijn geparkeerd (BKPF-BSTAT is leeg). Gebeurtenistype explicit | |||
| Factuur goedgekeurd | De factuur heeft alle vereiste goedkeuringen in het workflowsysteem gekregen. 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ëntiemetriek. Waar vind je dit? Vastgelegd in SAP Business Workflow-logboeken als een voltooiings- of definitieve vrijgavestap. Je kunt dit ook afleiden uit het opheffen van een betalingsblokkade nadat de factuur is doorgestuurd. Vastleggen Haal voltooiingsgebeurtenissen van workflows op uit SAP-workflowlogboeken of zoek de laatste gebeurtenis voor 'vrijgave'. Gebeurtenistype explicit | |||
| Factuur ontvangen | Deze activiteit markeert het aanmaken van een factuurdocument in SAP, handmatig of via een geautomatiseerde interface zoals OCR/VIM. Deze gebeurtenis wordt doorgaans vastgelegd aan de hand van de aanmaakdatum en -tijd van de kop van het boekhoudkundige document. | ||
| Waarom dit belangrijk is Als startpunt van het proces is deze activiteit nodig om de totale doorlooptijd van de factuur te berekenen en de doorvoer van het volledige crediteurenproces te meten. Waar vind je dit? Deze gebeurtenis wordt vastgelegd in de tabel met kopgegevens van boekhoudkundige documenten (BKPF), op basis van de aanmaakdatum (CPUDT) en -tijd (CPUTM) van het document. Vastleggen Gebruik de timestamp voor het aanmaken van het factuurdocument (BKPF-CPUDT, BKPF-CPUTM). Gebeurtenistype explicit | |||
| Afwijking opgelost | Deze activiteit geeft aan dat een eerder vastgesteld probleem, dat waarschijnlijk tot een betalingsblokkade heeft geleid, is onderzocht en opgelost. Dit wordt vastgelegd wanneer de betalingsblokkade van een factuur wordt opgeheven. | ||
| Waarom dit belangrijk is Door deze herstelcyclus te volgen, krijg je de gegevens voor het dashboard 'Analyse van herhaalwerk bij factuurafwijkingen'. Zo meet je hoeveel tijd en werk het kost om fouten te herstellen. Waar vind je dit? Dit wordt afgeleid uit wijzigingsdocumenten die laten zien dat een betalingsblokkade is opgeheven. Het wijzigingslogboek voor het veld BSEG-ZLSPR is hiervoor de belangrijkste bron. Vastleggen Zoek wijzigingsdocumenten voor tabel BSEG waarin de waarde van het veld ZLSPR wordt gewist. Gebeurtenistype inferred | |||
| Betaalvoorstel aangemaakt | De factuur is opgenomen in een betaalvoorstel als onderdeel van een betaalrun, bijvoorbeeld F110. De betaling staat nu gepland, in afwachting van de definitieve uitvoering van de run. | ||
| Waarom dit belangrijk is Deze activiteit laat zien hoe een openstaande verplichting wordt klaargemaakt voor betaling. Zo kun je de efficiëntie van de betaalprocessen analyseren. Waar vind je dit? Deze gebeurtenis wordt expliciet vastgelegd in de gegevenstabellen voor betaalruns, met name REGUP (verwerkte posten van het betaalprogramma) en REGUH (kopgegevens). Vastleggen Zoek wanneer een factuur voorkomt in tabel REGUP voor een betaalrun die in REGUH is vastgelegd. Gebeurtenistype explicit | |||
| Factuur afgewezen | Een goedkeurder heeft de factuur tijdens de goedkeuringsworkflow afgewezen. De factuur wordt dan meestal teruggestuurd naar de verwerker voor correctie of toelichting. | ||
| Waarom dit belangrijk is Afwijzingen laten herstelcycli in het goedkeuringsproces zien. Ze kunnen ook wijzen op problemen met naleving van beleid of onjuiste factuurcodering. Waar vind je dit? Dit wordt vastgelegd als een specifieke uitkomstgebeurtenis in de SAP Business Workflow-logboeken die bij de factuur horen. Vastleggen Haal gebeurtenissen met de status 'afgewezen' op uit de SAP-workflowlogboeken. Gebeurtenistype explicit | |||
| Factuur geparkeerd | De factuur is ingevoerd in het systeem, maar nog niet geboekt in het grootboek. Vaak wordt deze stap bewust gebruikt om een onvolledig document op te slaan voor latere verwerking of goedkeuring. | ||
| Waarom dit belangrijk is Door geparkeerde facturen te volgen, zie je waar vertraging ontstaat voordat het formele boekingsproces begint. Ook kunnen problemen met ontbrekende gegevens of de eerste controle aan het licht komen. Waar vind je dit? Deze status wordt afgeleid uit het statusveld in de kop van het boekhoudkundige document (BKPF-BSTAT = 'V' voor geparkeerd). De gebeurtenis vindt plaats zodra deze status wordt ingesteld. Vastleggen Zoek wijzigingsdocumenten voor tabel BKPF waarin het veld BSTAT de waarde 'V' heeft (Vor-erfasst/vooraf ingevoerd). Gebeurtenistype inferred | |||
| Factuur ter goedkeuring doorgestuurd | De factuur is op basis van bedrijfsregels naar een workflow gestuurd voor de vereiste goedkeuringen. Hiermee begint het goedkeuringssubproces. | ||
| Waarom dit belangrijk is Deze activiteit is het startpunt voor het meten van de KPI 'Gemiddelde goedkeuringstijd van facturen' en het analyseren van bottlenecks bij goedkeuringen. Waar vind je dit? Dit kan worden vastgelegd in de SAP Business Workflow-logboeken (tabellen SWW*), waarin de start wordt geregistreerd van een workflowinstantie die aan het factuurobject is gekoppeld, bijvoorbeeld BUS2081. Vastleggen Haal startgebeurtenissen van workflows op uit SAP-workflowlogboeken, bijvoorbeeld tabel SWW_WIHEAD, die aan het factuurdocument zijn gekoppeld. Gebeurtenistype explicit | |||
| Goederenontvangst gematcht | Deze activiteit geeft aan dat de hoeveelheden en bedragen op de factuur succesvol zijn gematcht met het bijbehorende document voor goederenontvangst. Dit is de laatste controle bij 3-way matching. | ||
| Waarom dit belangrijk is Door dit te volgen, spoor je inefficiënties in het 3-way matching-proces op en ontdek je afwijkingen tussen de ontvangen goederen en wat de leverancier factureert. Waar vind je dit? Dit wordt afgeleid uit de aanwezigheid van een materiaaldocumentreferentie (goederenontvangst) op de factuurregel. Vaak is die gekoppeld via de historie van de inkooporderregel. Vastleggen Afgeleid uit de aanwezigheid van een referentie naar een document voor goederenontvangst op de factuurregel, bijvoorbeeld in RSEG voor MIRO-facturen. Gebeurtenistype inferred | |||
| Inkooporder gematcht | Deze activiteit geeft aan dat de factuur succesvol is gematcht met de bijbehorende inkooporder. Dit is een belangrijke stap in het 3-way matching-proces voor facturen op basis van inkoop. | ||
| Waarom dit belangrijk is Met deze activiteit meet je hoe efficiënt het matchproces verloopt. De activiteit vormt ook de basis voor de KPI’s 'Prestaties van 3-way matching' en 'Percentage facturen zonder inkooporder'. Waar vind je dit? Dit wordt afgeleid wanneer een factuurregel in tabel BSEG of ACDOCA een geldig inkoopordernummer (EBELN) en een geldig regelnummer (EBELP) bevat. Vastleggen Afgeleid uit de aanwezigheid van een inkooporderreferentie (BSEG-EBELN) op het factuurdocument bij het aanmaken ervan. Gebeurtenistype inferred | |||
| Vervaldatum factuur verstreken | Een berekende gebeurtenis die aangeeft dat de nettovervaldatum van de factuur is verstreken zonder dat er een betaling is afgeletterd. Dit betekent dat de betaling te laat is of achterstallig is. | ||
| Waarom dit belangrijk is Deze activiteit is essentieel voor het dashboard 'Naleving van betalingsafspraken en ouderdom'. Je kunt er achterstallige facturen mee opsporen en beheren, en de oorzaken van betalingsvertragingen analyseren. Waar vind je dit? Dit is geen expliciete gebeurtenis in SAP. De gebeurtenis wordt berekend door de huidige systeemdatum te vergelijken met de nettovervaldatum (berekend op basis van BSEG-ZFBDT of de basisdatum en de betalingsvoorwaarden). Vastleggen Berekende gebeurtenis die wordt geactiveerd wanneer de timestamp van de gebeurtenis later is dan de nettovervaldatum van de factuur. Gebeurtenistype 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 querytool.
- Belangrijke CDS-views identificeren: Voor deze extractie gebruik je de CDS-views I_JournalEntry, I_JournalEntryItem, I_SupplierInvoiceAPI01, I_ChangeDocument, I_WorkflowStatusDetails en I_PaymentProposalItem. Maak jezelf vertrouwd met de belangrijkste velden.
- De query afbakenen: Open je SQL-client en maak verbinding met de SAP HANA-database. Bepaal vóór je de volledige query uitvoert de omvang van de extractie. Stel hiervoor de juiste bronsysteem-ID, de periode voor facturen (CreationDateTime) en de relevante Company Codes in.
- De hoofdquery voorbereiden: Kopieer de volledige SQL-query uit het querygedeelte naar je SQL-client. De query gebruikt Common Table Expressions (CTE’s): eerst wordt een basisselectie van facturen gemaakt, daarna wordt een event log opgebouwd door gegevens van 15 verschillende activiteiten samen te voegen.
- Queryparameters instellen: Zoek in de gekopieerde SQL-query de tijdelijke waarden. Vervang '[YYYY-MM-DD]' door de begin- en einddatum van de analyseperiode. Vervang '[Your Company Code 1]' en '[Your Company Code 2]' door de SAP Company Codes die je wilt analyseren.
- De extractiequery uitvoeren: Voer de volledige SQL-query uit. Afhankelijk van de hoeveelheid data en de gekozen periode kan dit enkele minuten tot enkele uren duren.
- Eerste resultaten controleren: Bekijk na afloop de eerste paar honderd rijen. Controleer of de data consistent is, alle kolommen naar verwachting zijn gevuld en er verschillende ActivityName-waarden voorkomen.
- Het event log exporteren: 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.
- De upload voorbereiden: Controleer vóór het uploaden naar een process mining-tool of de kolomkoppen in het CSV-bestand exact overeenkomen met de vereiste attribuutnamen: Invoice, ActivityName, EventTime, SourceSystem, LastDataUpdate, UserName enzovoort.
- Uploaden naar de process mining-tool: Upload het CSV-bestand naar je process mining-platform en koppel de kolommen aan de velden voor case-ID, activiteit en timestamp.
Configuratie
- Belangrijke CDS-views: De extractie combineert standaard CDS-views uit S/4HANA. De belangrijkste views zijn:
- I_JournalEntry en I_JournalEntryItem: voor financiële documentkoppen en -regels, boekingsgegevens en vereffeningsinformatie.
- I_SupplierInvoiceAPI01: voor details van MM-facturen (Logistics), waaronder PO-verwijzingen en betalingsblokkades.
- I_ChangeDocument: om de exacte timestamp van wijzigingen bij te houden, zoals het instellen of verwijderen van een betalingsblokkade.
- I_WorkflowStatusDetails: om gebeurtenissen uit de goedkeuringsworkflow voor facturen op te halen.
- I_PaymentProposalItem: om vast te stellen wanneer een factuur in een betalingsvoorstel wordt opgenomen.
- I_Supplier: om de data aan te vullen met stamgegevens van leveranciers, zoals VendorName.
- Filteren op periode: Filter altijd op een periode om de hoeveelheid data te beperken. De query filtert op CreationDateTime in de CTE Invoices_Base. Voor een eerste analyse is een periode van 3 tot 6 maanden aan te raden, zodat de query beheersbaar blijft.
- Verplichte filters: Filter altijd op CompanyCode. Data van alle bedrijfscodes tegelijk analyseren kan erg traag zijn en is mogelijk niet relevant voor de bedrijfsvoering. Filter ook op JournalEntryType om alleen documenten voor leveranciers 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 via SAP GUI is niet voldoende.
- Prestaties: Rechtstreekse queries op I_ChangeDocument kunnen veel systeembronnen vragen. De query beperkt dit door eerst de facturen te filteren. Overweeg bij zeer grote datasets de extractie buiten piekuren uit te voeren of in kleinere perioden op te delen.
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 je rechtstreekse leestoegang hebt tot het SAP HANA-schema met de relevante SAP S/4HANA-tabellen. Vraag de verbindingsgegevens, inloggegevens, schemanaam en autorisaties op die nodig zijn om BKPF, ACDOCA en eventuele aanvullende tabellen te lezen voor geparkeerde documenten, workflows, inkoop, goederenontvangst, betalingsvoorstellen, vereffeningen en terugboekingen.
- Controleer vóór uitvoering het technische datamodel van het doelsysteem. Verifieer de fysieke namen, sleutelvelden, timestampvelden, relaties voor terugboekingen en betalingen en de workflowopslag die het systeem gebruikt. Vervang elke waarde tussen vierkante haken in de query door het bijbehorende object of veld uit het systeem. Ga er niet van uit dat workflowdata of gegevens over geparkeerde documenten in één universele tabel staan.
- Stel de extractieparameters in. Vul [Start date], [End date], [Company code filter], [Document type filter] en [Schema name] in. Begin met een periode van drie tot zes maanden en verleng die pas nadat je de prestaties en volledigheid hebt 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 opgehaalde activiteit. ProcessMind leidt geen gebeurtenissen af.
- Controleer de resultatenset. Bevestig dat Invoice de case-ID is, ActivityName alle 15 vereiste activiteitsnamen bevat, EventTime is ingevuld en chronologisch aannemelijk is, SourceSystem SAP S/4HANA aanduidt en LastDataUpdate de timestamp van de extractie bevat. Controleer dubbele gebeurtenissen, relaties tussen terugboekingen en documentkoppelingen voordat je de data laadt.
- Pas eventuele systeemspecifieke koppelingen toe. Koppel bijvoorbeeld de ingestelde bron voor geparkeerde documenten aan Invoice Parked, de workflowbron aan Invoice Routed For Approval, Invoice Approved en Invoice Rejected, en de betalingsbron aan Payment Proposal Created en Payment Executed. Bewaar de bron-ID’s in extra kolommen als je een auditspoor nodig hebt.
- Exporteer het resultaat als een bestand met scheidingstekens of als een database-resultatenset, met één gebeurtenis per rij. Gebruik UTF-8-codering, houd timestamps in één tijdzone en behoud exact deze kolomnamen: Invoice, ActivityName, EventTime, SourceSystem, LastDataUpdate, UserName, CompanyCode, VendorName, InvoiceAmount, PurchaseOrderNumber en InvoiceDueDate. Voeg activiteiten per factuur niet samen.
- Upload het event log naar ProcessMind en stel Invoice in als case-ID, ActivityName als activiteitskolom en EventTime als tijdskolom voor gebeurtenissen. Controleer of optionele attributen aan de juiste velden zijn gekoppeld. ProcessMind leest het event log zoals het is aangeleverd. Zorg dus dat elke activiteit die je wilt visualiseren vóór het uploaden al als rij aanwezig is.
Configuratie
- Periode: Begin met drie tot zes maanden. Gebruik de boekingsdatum, aanmaakdatum van het document of de relevante datum van de brongebeurtenis, afhankelijk van de activiteit die je ophaalt. Verleng de periode pas nadat je de queryduur en de bewaartermijn van de brondata hebt gecontroleerd.
- Filteren op bedrijfscode: Stel [Company code filter] in om de extractie te beperken tot de vereiste bedrijfscodes. Is er geen beperking nodig, gebruik dan een gecontroleerde selectie van alle bedrijven in plaats van een onbeperkte query op productie.
- Filteren op documenttype: Stel [Document type filter] pas in nadat je hebt gecontroleerd welke documenttypen het doelsysteem gebruikt voor leveranciersfacturen, creditnota’s, geparkeerde documenten, betalingsdocumenten en terugboekingen.
- Schema- en objectkoppelingen: Vervang [Schema name] en elk bronobject of veld 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.
- Timestamps verwerken: Zet alle timestamps uit de bron om naar één tijdzone. Is alleen een datum beschikbaar, gebruik dan een vastgelegde standaardtijd en noteer deze beperking in het datadictionary.
- Betekenis van gebeurtenissen: Haal elke activiteit op als een aparte rij. Voeg meerdere activiteiten niet samen in één factuurrecord en verwacht niet dat ProcessMind gebeurtenissen voor matching, goedkeuring, vervaldatums of vereffening afleidt.
- Gebeurtenis voor vervaldatum: Genereer Invoice Due Date Passed alleen voor facturen waarvan de vervaldatum vóór de ingestelde evaluatietimestamp ligt en waarvoor op dat moment geen vereffeningsgebeurtenis bestaat. De query gebruikt hiervoor [Evaluation timestamp].
- Prestaties: Beperk de beginperiode en het aantal bedrijfscodes, filter op geïndexeerde velden of velden die relevant zijn voor partitionering, vermijd onnodig brede selecties en voer de query uit binnen een goedgekeurd rapportagevenster. Overweeg subsets van de brondata tijdelijk op te slaan als de query op productie langer duurt dan afgesproken.
- Verversing: Stel LastDataUpdate in op de timestamp waarop de extractie is uitgevoerd. Gebruik bij incrementele ladingen een watermark op basis van de relevante wijzigingstimestamp uit de bron en neem een terugkijkperiode op om late wijzigingen en terugboekingen mee te nemen.
- Vereisten: Benodigde databaseautorisaties, goedgekeurde toegang tot productie, kennis van de Universal Journal-inrichting van het systeem, toegang tot de ingestelde bronnen voor geparkeerde documenten, inkoop, goederenontvangst, workflows, betalingen, vereffeningen en terugboekingen, en eventuele vereiste SAP-licenties of goedkeuringen vanuit governance.
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 af wat de exacte voorwaarden en datavelden zijn voor elk van de 15 vereiste activiteiten. Bepaal welke SAP-tabellen, documenttypen (bijvoorbeeld 'KR' en 'RE') en bedrijfscodes binnen de scope vallen.
- ABAP-programma aanmaken: Open de ABAP Editor via transactiecode SE38. Maak een nieuw uitvoerbaar programma aan, bijvoorbeeld Z_PM_AP_INVOICE_EXTRACT. Geef het een duidelijke titel en stel de applicatie in op 'Financial Accounting'.
- Selectiescherm definiëren: Definieer in het programma een selectiescherm met de trefwoorden PARAMETERS en SELECT-OPTIONS. Hiermee kunnen gebruikers de extractieperiode voor de aanmaakdatum van facturen, de doelbedrijfscodes (BUKRS) en de relevante factuurdocumenttypen (BLART) opgeven. Voeg ook een parameter toe voor het bestandspad op de applicatieserver.
- Datadeclaraties: Definieer een interne tabelstructuur die overeenkomt met het uiteindelijke event log-formaat, bijvoorbeeld TY_EVENT_LOG, met alle vereiste en aanbevolen attributen. Declareer interne tabellen voor data uit SAP-brontabellen zoals BKPF, BSEG, RBKP, RSEG, CDHDR, CDPOS en REGUH.
- Hoofdselectie van data: Begin de extractielogica met het selecteren van de primaire factuurset uit RBKP (Logistics Invoices) en BKPF (Financial Invoices), op basis van de criteria op het selectiescherm. Sla de primaire factuursleutels op in een interne tabel om de volgende zoekopdrachten aan te sturen.
- Activiteiten achtereenvolgens ophalen: Voer voor elke factuur in de hoofdset selecties uit om timestamps en details van elke bedrijfsactiviteit te vinden. Vraag bijvoorbeeld CDHDR en CDPOS op voor wijzigingen in betalingsblokkades, REGUH en REGUP voor gegevens 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 gebeurtenissen: Implementeer ABAP-logica voor activiteiten die niet rechtstreeks in een tabelveld zijn opgeslagen. Gebruik voor de gebeurtenis 'Invoice Due Date Passed' de vervaldatum van de factuur (BSEG-ZFBDT + betalingstermijn) en de vereffeningsdatum (BSEG-AUGDT). Als de vereffeningsdatum na de vervaldatum ligt, maak je een gebeurtenisrecord aan met de vervaldatum als timestamp.
- Data omzetten en aanvullen: Vul tijdens het ophalen van data voor elke activiteit alle vereiste attributen in. Zoek hiervoor leveranciersnamen op in LFA1, zet datums en tijden om naar één timestampstring (CONCATENATE...INTO...) en vul de waarde van SourceSystem in.
- Uitvoerbestand genereren: Schrijf de data naar een bestand op de applicatieserver, op het pad dat op het selectiescherm is opgegeven. Gebruik hiervoor de statements OPEN DATASET, LOOP AT ... TRANSFER en CLOSE DATASET nadat alle facturen en bijbehorende activiteiten in de uiteindelijke interne tabel zijn verzameld.
- Downloaden en upload voorbereiden: Download het gegenereerde bestand met transactiecode CG3Y van de applicatieserver naar je computer. Sla het op als CSV-bestand met UTF-8-codering. Controleer vóór het uploaden of de kolomkoppen overeenkomen met de vereiste attributen (Invoice, ActivityName, EventTime enzovoort).
Configuratie
- Periode: Definieer de selectieoptie P_CPUDT voor de aanmaakdatum van de factuur (BKPF-CPUDT of RBKP-CPUDT). Voor een eerste analyse is een periode van 6 tot 12 maanden aan te raden.
- Bedrijfscode (P_BUKRS): Een verplichte SELECT-OPTIONS-parameter om specifieke bedrijfscodes te selecteren. Verwerking van alle bedrijfscodes tegelijk is niet aan te raden, tenzij dat echt nodig is.
- Factuurdocumenttype (P_BLART): Een SELECT-OPTIONS-parameter om relevante factuurdocumenttypen te selecteren. Veelgebruikte typen zijn 'KR' (leveranciersfactuur), 'KG' (creditnota van leverancier) en 'RE' (logistieke factuurcontrole).
- Uitvoermodus: Voer het programma bij grote hoeveelheden data uit als achtergrondtaak (SM36/SM37) om time-outs in de voorgrond te voorkomen. Plan de taak buiten piekuren.
- Pad van het uitvoerbestand: Gebruik een PARAMETER om het pad 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, moet leesautorisatie hebben voor FI-, CO- en MM-tabellen (BKPF, BSEG, RBKP, RSEG, LFA1), wijzigingsdocumenttabellen (CDHDR, CDPOS) en workflowtabellen. Voor het schrijven van bestanden naar de applicatieserver is ook autorisatieobject S_DATASET nodig.
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 als startpunt voor process mining en ontdek waar je de bedrijfsvoering efficiënter kunt maken. Zet vandaag de eerste stap naar een beter ingericht en efficiënter proces.
Voorkom boetes voor te late betaling: verbeter vandaag nog de factuurverwerking
Verlaag de verwerkingskosten met 60% en voorkom dubbele betalingen.
Geen creditcard nodig. Je kunt binnen enkele minuten aan de slag.