Datatemplate voor Record to Report - journaalposten
Datatemplate voor Record to Report - journaalposten
- Aanbevolen attributen om te verzamelen
- Belangrijke activiteiten om bij te houden
- Praktische aanwijzingen voor data-extractie
Attributen voor Record to Report - journaalposten
| Naam | Beschrijving | ||
|---|---|---|---|
| Activiteit ActivityName | De naam van de bedrijfsactiviteit die op een bepaald moment in het journaalpostproces plaatsvond. | ||
| Beschrijving De activiteit is een specifieke stap of gebeurtenis in de levenscyclus van een journaalpost, zoals ‘Journaalpost aangemaakt’, ‘Journaalpost ingediend ter beoordeling’ of ‘Journaalpost geboekt’. Activiteiten worden meestal afgeleid uit wijzigingslogs, statusupdates of transactiecodes die in het systeem zijn vastgelegd. Door activiteiten te analyseren, kun je de processtroom visualiseren, veelvoorkomende routes herkennen en afwijkingen van de standaardprocedure opsporen. Dit is nodig om metrieken te berekenen, zoals de frequentie van activiteiten, wachttijden tussen stappen en nalevingspercentages. Waarom dit belangrijk is Dit attribuut beschrijft de processtappen. Daarmee kun je proceskaarten maken en workflowpatronen analyseren. Waar vind je dit? Afgeleid uit verschillende bronnen, waaronder statusvelden in kop- en regeltabellen (zoals BKPF-BSTAT), wijzigingsdocumenten (CDHDR/CDPOS) en workflowlogs. Voorbeelden Journaalpost aangemaaktJournaalpost geparkeerdJournaalpost ingediend ter beoordelingJournaalpost goedgekeurdJournaalpost geboekt | |||
| ID van journaalpost JournalEntryId | De unieke identificatie van een financiële journaalpost. Dit is de belangrijkste case-identificatie voor het proces. | ||
| Beschrijving Het ID van de journaalpost is een uniek nummer dat SAP S/4HANA bij het aanmaken toekent aan elk boekhoudkundig document. Met dit ID kun je de volledige levenscyclus van een journaalpost volgen: van aanmaken of parkeren, via de goedkeuringsworkflows, tot de definitieve boeking en eventuele terugboeking of vereffening. Bij process mining wordt dit ID gebruikt om alle bijbehorende activiteiten aan één case te koppelen. Door gebeurtenissen onder hetzelfde journaalpost-ID te groeperen, kunnen analisten het proces van begin tot eind reconstrueren, doorlooptijden meten en varianten of bottlenecks per financiële transactie opsporen. Dit attribuut vormt de basis voor het volledige procesoverzicht. Waarom dit belangrijk is Dit ID koppelt alle bijbehorende processtappen aan elkaar. Zo kun je het volledige verloop van elke journaalpost analyseren. Waar vind je dit? Dit is een samengestelde sleutel, meestal opgebouwd uit de bedrijfsnummercode (BKPF-BUKRS), het documentnummer (BKPF-BELNR) en het boekjaar (BKPF-GJAHR). Voorbeelden 1000-1000000001-20231710-1900000055-20242000-2100003412-2023 | |||
| Tijdstip van gebeurtenis EventTime | De timestamp die aangeeft wanneer een specifieke activiteit voor de journaalpost plaatsvond. | ||
| Beschrijving Het tijdstip van de gebeurtenis is de exacte datum en tijd waarop een bedrijfsactiviteit is uitgevoerd en in het systeem is vastgelegd. Elke activiteit in een case heeft een eigen timestamp. Samen vormen ze een chronologische reeks gebeurtenissen. Dit attribuut is nodig voor alle tijdsanalyses van processen. Je gebruikt het om doorlooptijden, tijd tussen activiteiten en wachttijden te berekenen en te zien wanneer het werk plaatsvindt. Nauwkeurige timestamps zijn essentieel voor een betrouwbaar procesmodel en voor het berekenen van belangrijke prestatie-indicatoren, zoals de goedkeuringsdoorlooptijd. Waarom dit belangrijk is Dit attribuut bepaalt de chronologische volgorde van gebeurtenissen. Die volgorde is nodig om doorlooptijden en andere tijdsmetrieken te berekenen en het verloop van het proces te begrijpen. Waar vind je dit? Afkomstig uit wijzigingslogs (CDHDR-UDATE, CDHDR-UTIME), workflowlogs of aanmaak- en invoertimestamps in tabellen zoals BKPF (CPUDT, CPUTM). Voorbeelden 2023-10-26T10:05:00Z2023-11-15T14:30:15Z2024-01-20T09:00:45Z | |||
| Bedrag in lokale valuta AmountInLocalCurrency | De totale waarde van de journaalpost, uitgedrukt in de lokale valuta van de bedrijfscode. | ||
| Beschrijving Dit attribuut geeft de financiële omvang van de journaalpost weer. Meestal is dit de som van de absolute bedragen van alle debet- of creditregels in het document, omgerekend naar de lokale valuta van de bedrijfscode. Door op bedrag te analyseren, kun je processen indelen naar financiële impact. Voor boekingen met een hoge waarde kan bijvoorbeeld een strengere goedkeuringsprocedure gelden dan voor boekingen met een lage waarde. Zo kun je verbeteringen richten op transacties met het grootste financiële risico. Waarom dit belangrijk is Geeft de financiële waarde van de boeking weer, zodat je kunt analyseren hoe het procesgedrag verandert naargelang het bedrag. Waar vind je dit? Berekend door de bedragen uit regelpostentabel BSEG (veld DMBTR) voor een journaalpost (BELNR) op te tellen en om te zetten naar een positieve waarde. Voorbeelden 1500.75125000.0050.20 | |||
| Bedrijfscode CompanyCode | De unieke identificatie van het bedrijf of de juridische entiteit waarvoor de journaalpost wordt geboekt. | ||
| Beschrijving De bedrijfscode is een organisatorische basiseenheid in SAP Financials. Deze vertegenwoordigt een zelfstandige juridische entiteit waarvoor financiële overzichten worden opgesteld. Elke journaalpost wordt aan een specifieke bedrijfscode toegewezen. Met dit attribuut kun je procesprestaties in verschillende delen van de organisatie vergelijken. Analisten kunnen de procesweergave filteren op een juridische entiteit, afwijzingspercentages tussen bedrijfscodes vergelijken of procesverschillen per regio opsporen. Waarom dit belangrijk is Maakt het mogelijk om het journaalpostproces voor verschillende juridische entiteiten of bedrijfseenheden binnen de organisatie te filteren en te vergelijken. Waar vind je dit? SAP S/4HANA-tabel BKPF, veld BUKRS (bedrijfscode). Voorbeelden 10001710US01 | |||
| Boekingsdatum PostingDate | De datum waarop de journaalpost in het grootboek wordt geboekt en die daarmee de financiële periode bepaalt. | ||
| Beschrijving De boekingsdatum bepaalt in welke boekingsperiode de transactie in de financiële overzichten verschijnt. Deze datum is belangrijk voor de boekhouding en kan afwijken van de datum waarop het document is aangemaakt of in het systeem is ingevoerd. Bij process mining gebruik je de boekingsdatum voor cohortanalyses op basis van tijd, bijvoorbeeld om afsluitprocessen aan het einde van de maand te vergelijken of prestatietrends over verschillende boekingsperioden te analyseren. Je kunt er ook vertragingen mee meten tussen het aanmaken van een boeking en de daadwerkelijke verwerking in het grootboek. Waarom dit belangrijk is Geeft financiële context en maakt het mogelijk om procesprestaties binnen specifieke boekingsperioden te analyseren, zoals aan het einde van een maand of boekjaar. Waar vind je dit? SAP S/4HANA-tabel BKPF, veld BUDAT (boekingsdatum in het document). Voorbeelden 2023-10-312023-11-012024-02-29 | |||
| Gebruiker die de journaalpost heeft aangemaakt CreatedByUser | De gebruikers-ID van degene die de journaalpost heeft aangemaakt. | ||
| Beschrijving Dit attribuut bevat de unieke identificatie van de gebruiker die het proces van de journaalpost startte door het eerste document aan te maken. Dit kan een accountant, een zakelijke gebruiker of een systeem-ID voor automatisch aangemaakte posten zijn. Door het proces te analyseren op basis van de maker, kun je patronen bij specifieke gebruikers of teams herkennen. Zo zie je bijvoorbeeld of bepaalde gebruikers vaker afwijzingen krijgen en extra training nodig hebben, of juist opvallend goed presteren. Dit attribuut is essentieel voor het dashboard ‘Gebruikersactiviteit en doorvoer’. Waarom dit belangrijk is Koppelt procesactiviteiten aan specifieke gebruikers. Zo kun je prestaties analyseren, de werklast verdelen en zien waar training nodig is. Waar vind je dit? SAP S/4HANA-tabel BKPF, veld USNAM (gebruikersnaam). Voorbeelden ABROWNCJONESBATCH_USER | |||
| Type journaalpost JournalEntryType | Deelt journaalposten in op basis van hun zakelijke doel, zoals een activaboeking, leveranciersfactuur of grootboekboeking. | ||
| Beschrijving Het type journaalpost, in SAP-termen het documenttype, is een sleutel waarmee boekhoudkundige documenten worden ingedeeld. Het bepaalt onder meer welk nummerbereik aan het document wordt toegewezen en welke rekeningtypen zijn toegestaan voor de boeking. Analyse op type journaalpost maakt duidelijk welk gedrag bij een bepaalde context hoort. Zo kan de goedkeuringsprocedure voor een eenvoudige overlopende post (type SA) veel eenvoudiger zijn dan die voor een complexe aanschaf van een bedrijfsmiddel (type AA). Deze dimensie is belangrijk voor het dashboard ‘Compliance per boekingstype’. Waarom dit belangrijk is Deelt boekingen in op basis van hun zakelijke context, zodat je procesverschillen en prestaties voor verschillende financiële transacties kunt analyseren. Waar vind je dit? SAP S/4HANA-tabel BKPF, veld BLART (documenttype). Voorbeelden SAKRAA | |||
| Boekjaar FiscalYear | Het boekjaar waartoe de journaalpost behoort. | ||
| Beschrijving Het boekjaar maakt, samen met de bedrijfscode en het documentnummer, deel uit van de unieke sleutel van een journaalpost. Het geeft aan in welk boekjaar het document relevant is. Bij analyses gebruik je het boekjaar voor trendanalyses op de lange termijn en om de unieke identificatie van de case te waarborgen. Door procesmaatstaven van verschillende boekjaren te vergelijken, zie je hoe de prestaties zich in de loop van de tijd hebben ontwikkeld. Waarom dit belangrijk is Levert een belangrijk onderdeel voor de unieke identificatie van documenten en maakt het mogelijk om procesprestaties van jaar tot jaar te analyseren. Waar vind je dit? SAP S/4HANA-tabel BKPF, veld GJAHR (boekjaar). Voorbeelden 202320242022 | |||
| Bronsysteem SourceSystem | Geeft aan uit welk bronsysteem de data over journaalposten is gehaald. | ||
| Beschrijving Dit attribuut geeft aan uit welk bronsysteem de gegevens van de journaalpost afkomstig zijn. Bij bedrijven met meerdere ERP-instanties of een combinatie van oudere en moderne systemen helpt dit om de verschillende databronnen van elkaar te onderscheiden. Bij analyses kun je hiermee de procesprestaties van verschillende systemen vergelijken of de data filteren op een specifieke bron. Dit is belangrijk voor datagovernance en om de context van de data goed te begrijpen. Waarom dit belangrijk is Geeft context over de herkomst van de data. Dat is belangrijk voor een nauwkeurige procesanalyse en vergelijking in omgevingen met meerdere systemen. Waar vind je dit? Dit is meestal een statische waarde die tijdens de data-extractie wordt toegevoegd. De waarde geeft aan om welke SAP S/4HANA-instantie het gaat, bijvoorbeeld de SID of de naam van het logische systeem. Voorbeelden S4H_PROD_100ECC_FIN_200S4C_US_EAST | |||
| Documentstatus DocumentStatus | De huidige verwerkingsstatus van de journaalpost, bijvoorbeeld voorlopig opgeslagen, geboekt of vereffend. | ||
| Beschrijving De documentstatus geeft aan waar de journaalpost zich in de levenscyclus bevindt. Een voorlopig opgeslagen document is bijvoorbeeld wel opgeslagen, maar nog niet in het grootboek geboekt. Een geboekt document is definitief verwerkt. Met een analyse van de status krijg je zicht op de werkstroom en kun je bottlenecks opsporen. Veel documenten die lang de status ‘voorlopig opgeslagen’ of ‘wacht op goedkeuring’ houden, kunnen wijzen op inefficiënties in het proces. De status is ook een belangrijke bron voor het afleiden van procesactiviteiten. Waarom dit belangrijk is Geeft een momentopname van de status van een journaalpost in de levenscyclus en helpt wachtrijen en bottlenecks op te sporen. Waar vind je dit? SAP S/4HANA-tabel BKPF, veld BSTAT (documentstatus). Voorbeelden VAB | |||
| Doorlooptijd goedkeuring ApprovalCycleTime | De tijd vanaf het moment waarop een journaalpost ter goedkeuring wordt ingediend tot het moment waarop deze wordt goedgekeurd of afgewezen. | ||
| Beschrijving Deze berekende metriek meet specifiek de duur van de goedkeuringsfase. De tijd tussen de activiteit ‘Journaalpost ingediend ter beoordeling’ en de daaropvolgende activiteit ‘Journaalpost goedgekeurd’ of ‘Journaalpost afgewezen’ wordt gemeten. Deze KPI helpt bottlenecks in de goedkeuringsworkflow op te sporen. Een lange doorlooptijd voor goedkeuring kan het hele proces flink vertragen. Door deze metriek per goedkeurder, bedrijfscode of type journaalpost te analyseren, zie je waar verbetering mogelijk is. Waarom dit belangrijk is Meet alleen de duur van de goedkeuringsstap, zodat je bottlenecks in de beoordelings- en goedkeuringsworkflow kunt opsporen en aanpakken. Waar vind je dit? Berekend door het tijdsverschil te bepalen tussen de gebeurtenis ‘Journaalpost ingediend ter beoordeling’ en de gebeurtenis ‘Journaalpost goedgekeurd’ of ‘Journaalpost afgewezen’. Voorbeelden 1 dag 2 uur4 uur 25 minuten5 dagen 0 uur | |||
| Eindtijd EndTime | De timestamp waarop de activiteit is afgerond. | ||
| Beschrijving De eindtijd geeft aan wanneer een activiteit is afgerond. In veel event logs zijn de starttijd en eindtijd van een activiteit gelijk, omdat het om een gebeurtenis op één moment gaat. Bij activiteiten met een meetbare duur, zoals het actief beoordelen van een document door een gebruiker, kan dit attribuut die duur vastleggen. Met een aparte eindtijd kun je de verwerkingstijd van een activiteit nauwkeuriger berekenen en onderscheiden van de wachttijd. Zo zie je hoeveel tijd iemand actief aan een taak heeft gewerkt en hoelang die taak ongebruikt in een wachtrij stond. Waarom dit belangrijk is Maakt een nauwkeurige berekening van de verwerkingstijd van activiteiten mogelijk, waarbij actieve werktijd wordt onderscheiden van wachttijd. Waar vind je dit? Bij gebeurtenissen die op één moment plaatsvinden, is deze waarde meestal gelijk aan StartTime. Voor activiteiten met een duur kan de waarde afkomstig zijn uit workflowlogs of worden berekend op basis van latere gebeurtenissen. Voorbeelden 2023-10-26T10:05:00Z2023-11-15T14:45:20Z2024-01-20T09:10:30Z | |||
| Goedkeurder ApproverUser | De gebruikers-ID van degene die de journaalpost heeft goedgekeurd of afgewezen. | ||
| Beschrijving Dit attribuut geeft aan welke gebruiker verantwoordelijk is voor de beoordeling en beslissing over een ingediende journaalpost. Bij een workflow met meerdere goedkeuringsniveaus kunnen meerdere goedkeurders bij één journaalpost betrokken zijn. Met deze informatie kun je het goedkeuringsproces in detail analyseren. Je kunt de werklast van goedkeurders meten, individuele goedkeuringstijden berekenen en bottlenecks in de goedkeuringsketen opsporen. Dit attribuut ondersteunt het dashboard ‘Gebruikersactiviteit en doorvoer’. Waarom dit belangrijk is Geeft aan wie verantwoordelijk is voor de goedkeuring, zodat je de werklast, prestaties en bottlenecks in het goedkeuringsproces kunt analyseren. Waar vind je dit? Afkomstig uit workflowlogs, zoals SWW_WI2OBJ en SWWLOG, of uit wijzigingsdocumenttabellen (CDHDR/CDPOS). De goedkeurder wordt bepaald aan de hand van wie de goedkeuringsstap heeft uitgevoerd. Voorbeelden DMILLERFWHITEKCHEN | |||
| Is handmatige boeking IsManualPosting | Een booleaanse vlag die aangeeft of een gebruiker de journaalpost handmatig heeft geboekt. | ||
| Beschrijving Dit attribuut geeft aan welke journaalposten handmatig door een gebruiker zijn geboekt, in plaats van automatisch via een systeemtaak of interface. De waarde wordt doorgaans afgeleid van de transactiecode waarmee het document is geboekt. Met deze vlag kun je het percentage handmatige boekingen berekenen en de voortgang van de automatisering van het Record to Report-proces volgen. Door handmatig geboekte posten te filteren, zie je voor welke situaties nog menselijke tussenkomst nodig is en of automatisering mogelijk is. Waarom dit belangrijk is Onderscheidt boekingen door medewerkers van boekingen door systemen. Zo kun je de mate van automatisering meten en mogelijkheden voor verdere automatisering vinden. Waar vind je dit? Dit berekende attribuut is afgeleid van de transactiecode. Een vooraf bepaalde lijst met handmatige transactiecodes, zoals ‘FB01’ en ‘F-02’, wordt gebruikt om de vlag op ‘true’ te zetten. Voorbeelden truefalse | |||
| Is herstelwerk IsRework | Een booleaanse vlag die aangeeft of de journaalpost is hersteld, bijvoorbeeld na een afwijzing. | ||
| Beschrijving Dit berekende attribuut markeert journaalposten die afwijken van de ideale route. De waarde wordt doorgaans op true gezet als er in de case een activiteit voorkomt zoals ‘Journaalpost afgewezen’ of ‘Journaalpost gecorrigeerd’. Met deze vlag kun je de procesefficiëntie eenvoudiger analyseren. Je kunt er snel het percentage herstelwerk mee berekenen en de doorlooptijden en kosten vergelijken van cases met en zonder herstelwerk. Veel initiatieven voor procesverbetering richten zich op het opsporen van oorzaken van herstelwerk. Waarom dit belangrijk is Markeert cases waarvoor correcties of extra procesrondes nodig waren. Zo kun je inefficiënties eenvoudig meten en de oorzaken ervan analyseren. Waar vind je dit? Dit berekende attribuut is afgeleid van de volgorde van activiteiten in een case. De waarde wordt op ‘true’ gezet als er bijvoorbeeld een activiteit als ‘Journaalpost afgewezen’ voorkomt. Voorbeelden truefalse | |||
| Laatste data-update LastDataUpdate | Timestamp die aangeeft wanneer de data voor dit record 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 het bronsysteem. Zo zie je hoe actueel de data is die je analyseert. De tijd van de laatste update is belangrijk om te bepalen hoe actueel de procesanalyse is. Zo kun je dashboards en KPI’s goed interpreteren en weet je of je naar bijna realtime data kijkt of naar een momentopname uit een eerdere periode. Waarom dit belangrijk is Geeft aan hoe actueel de data is, zodat duidelijk is hoe recent de procesanalyse is. Waar vind je dit? Dit is een metadata-attribuut dat doorgaans tijdens de data-invoer voor elk record wordt gegenereerd en vastgelegd. Voorbeelden 2024-03-10T02:00:00Z2024-03-11T02:00:00Z2024-03-12T02:00:00Z | |||
| Reden voor terugboeking ReversalReason | Een code die aangeeft waarom een geboekte journaalpost is teruggeboekt. | ||
| Beschrijving Een onjuiste geboekte journaalpost kan niet worden verwijderd, maar moet met een nieuw document worden teruggeboekt. De code voor de reden van terugboeking geeft aan waarom dit is gebeurd, bijvoorbeeld vanwege een onjuiste boekingsdatum of een verkeerd bedrag. Door redenen voor terugboekingen te analyseren, kun je de oorzaken van fouten in het Record to Report-proces opsporen. Als een bepaalde reden vaak voorkomt, kan dat wijzen op structurele problemen, zoals onvoldoende training of tekortkomingen in controles. Die problemen kun je aanpakken om de kwaliteit in één keer goed te verbeteren. Waarom dit belangrijk is Helpt de oorzaak te achterhalen van fouten die tot terugboekingen leiden, zodat je herstelwerk kunt verminderen en de proceskwaliteit kunt verbeteren. Waar vind je dit? SAP S/4HANA-tabel BKPF, veld STGRD (reden voor terugboeking). Voorbeelden 010205 | |||
| Transactiecode TransactionCode | De SAP-transactiecode waarmee de journaalpost is aangemaakt of gewijzigd. | ||
| Beschrijving De transactiecode (T-Code) is een snelkoppeling naar een specifieke functie of programma in SAP. Bij journaalposten kunnen verschillende T-Codes aangeven hoe de boeking is aangemaakt. FB01 wordt bijvoorbeeld gebruikt voor handmatige grootboekboekingen, FV50 voor het voorlopig opslaan van boekingen en een automatische code voor boekingen die door het systeem zijn aangemaakt. Dit attribuut laat goed zien of een activiteit handmatig door een gebruiker of automatisch door het systeem is uitgevoerd. Het is belangrijk voor de berekening van de KPI voor het percentage handmatige boekingen en helpt mogelijkheden voor automatisering te vinden. Waarom dit belangrijk is Geeft aan hoe een boeking is verwerkt, bijvoorbeeld handmatig of automatisch. Dit is belangrijk voor automatiseringsanalyse en om procesverschillen te begrijpen. Waar vind je dit? SAP S/4HANA-tabel BKPF, veld TCODE (transactiecode). Voorbeelden FB01FV50F-02 | |||
Activiteiten voor Record to Report - journaalposten
| Activiteit | Beschrijving | ||
|---|---|---|---|
| Journaalpost aangemaakt | Deze activiteit markeert het moment waarop een journaalpostdocument voor het eerst in het systeem wordt aangemaakt. De kopgegevens worden opgeslagen in de tabel BKPF, maar de journaalpost is nog niet in het grootboek geboekt. Dit is het begin van de levenscyclus van de journaalpost. | ||
| Waarom dit belangrijk is Dit is de belangrijkste startgebeurtenis van het proces. De tijd tussen deze gebeurtenis en de boeking laat zien wat de totale doorlooptijd is en helpt vertragingen bij de eerste gegevensinvoer op te sporen. Waar vind je dit? Deze gebeurtenis is rechtstreeks vast te leggen in de SAP-tabel BKPF met de velden voor aanmaakdatum (CPUDT) en aanmaaktijd (CPUTM) van een bepaald documentnummer (BELNR). Vastleggen Gebruik BKPF-CPUDT en BKPF-CPUTM voor de timestamp van de gebeurtenis. Gebeurtenistype explicit | |||
| Journaalpost geboekt | De journaalpost wordt officieel vastgelegd in het grootboek en heeft invloed op de financiële overzichten van het bedrijf. Vanaf dit moment is het document een permanent financieel record. | ||
| Waarom dit belangrijk is Dit is het belangrijkste moment waarop het proces succesvol is afgerond. Het markeert het einde van de verwerkingscyclus. De doorvoer van geboekte journaalposten en de tijd tot deze stap zijn belangrijke metrieken voor process mining. Waar vind je dit? Dit is een expliciete gebeurtenis, vastgelegd met de boekingsdatum (BUDAT) in de tabel BKPF. Bij een geboekt document is de documentstatus (BSTAT) leeg. Zo onderscheid je het van geparkeerde (‘V’) of vastgehouden (‘D’) documenten. Vastleggen Gebruik de boekingsdatum (BKPF-BUDAT) en de invoerdatum (BKPF-CPUDT) voor de timestamp van de gebeurtenis. Een lege BKPF-BSTAT geeft aan dat het document is geboekt. Gebeurtenistype explicit | |||
| Journaalpost goedgekeurd | Een bevoegde manager keurt de journaalpost definitief goed en bevestigt daarmee dat deze geldig en correct is. Dit is de laatste controle voordat het document in het grootboek kan worden geboekt. | ||
| Waarom dit belangrijk is Dit belangrijke moment sluit de goedkeuringscyclus af. De tijd tot deze stap vormt een groot deel van de totale procesduur en geeft aan hoe efficiënt goedkeurders werken. Waar vind je dit? Deze gebeurtenis is af te leiden uit een workflowlog met de laatste goedkeuringsstap of uit een statuswijziging op het document. De gebruikers-ID van de goedkeurder en de timestamp zijn terug te vinden in workflowdata of wijzigingslogs. Vastleggen Zoek in workflowlogs naar de timestamp van de laatste goedkeuringsstap, of in wijzigingsdocumenten naar een statuswijziging in ‘Goedgekeurd’. Gebeurtenistype inferred | |||
| Journaalpost ingediend ter beoordeling | De maker van de journaalpost dient het document formeel in voor beoordeling en goedkeuring. Deze activiteit markeert de overdracht van gegevensinvoer naar het formele controleproces en start de goedkeuringscyclus. | ||
| Waarom dit belangrijk is Dit is het begin van de goedkeuringsdoorlooptijd. Door vanaf dit moment te meten tot de definitieve goedkeuring of afwijzing, zie je waar bottlenecks ontstaan tijdens de beoordeling en goedkeuring. Waar vind je dit? Dit wordt vaak vastgelegd in workflowlogs (tabellen SWW_WIHEAD, SWWLOG) die aan het bedrijfsobject zijn gekoppeld. Je kunt het ook afleiden uit een statuswijziging in een aangepast veld op de documentkop (BKPF). Vastleggen Timestamp waarop het workflow-item is aangemaakt, of waarop een statusveld verandert in ‘Ingediend’ of ‘In beoordeling’. Gebeurtenistype inferred | |||
| Journaalpost vereffend | Een open regelpost in een journaalpost wordt afgeboekt met een andere boeking, bijvoorbeeld wanneer een betaling een factuur vereffent. Deze activiteit markeert de afstemming van specifieke regelposten en sluit ze af. | ||
| Waarom dit belangrijk is Voor veel journaalposten is dit de laatste stap in de afstemming, vooral bij tussenrekeningen of rekeningen die met open posten werken. Door de tijd tussen boeken en vereffenen te meten, zie je hoe efficiënt de afstemming verloopt. Waar vind je dit? Deze gebeurtenis is af te leiden uit de tabel met regelposten (BSEG of de ACDOCA-weergave). Zodra een post is vereffend, zijn de velden voor vereffeningsdatum (AUGDT) en vereffeningsdocument (AUGBL) voor die regel ingevuld. Vastleggen Gebruik de vereffeningsdatum (BSEG-AUGDT) van de regelpost als timestamp van de gebeurtenis. Gebeurtenistype inferred | |||
| Terugboeking van journaalpost verwerkt | Een eerder geboekte journaalpost wordt teruggeboekt door een nieuw document met omgekeerde boekingen aan te maken. Dit is een expliciete, auditeerbare transactie om fouten in geboekte documenten te corrigeren. | ||
| Waarom dit belangrijk is Terugboekingen wijzen op een fout in een geboekt document. Veel terugboekingen kunnen duiden op problemen met het goedkeuringsproces of de kwaliteit van de gegevensinvoer. Door ze te volgen, verbeter je de nauwkeurigheid in één keer. Waar vind je dit? De terugboeking is een expliciete gebeurtenis. De kopgegevens (BKPF) van het nieuwe terugboekingsdocument verwijzen naar het oorspronkelijke document via het veld Reversed Document No. (STBLG). De boekingsdatum van het nieuwe document is het tijdstip van de gebeurtenis. Vastleggen Zoek naar documenten waarvoor BKPF-STBLG is ingevuld. De boekingsdatum van het terugboekingsdocument is de timestamp van de gebeurtenis. Gebeurtenistype explicit | |||
| Handmatige boeking vastgesteld | De journaalpost is geboekt met een handmatige transactiecode, niet via een geautomatiseerde interface of batchtaak. Dit is geen gebeurtenis met een tijdstip, maar een classificatie van de boekingsactiviteit. | ||
| Waarom dit belangrijk is Handmatige boekingen opsporen is belangrijk voor automatiseringsinitiatieven. Veel handmatige boekingen wijzen op kansen om processen efficiënter te maken door subsystemen te koppelen of automatische boekingsprogramma’s te gebruiken. Waar vind je dit? Dit wordt berekend door het veld voor de transactiecode (TCODE) in de documentkop (BKPF) te analyseren. Een lijst met bekende handmatige transactiecodes, zoals FB01, F-02 en FB50, wordt gebruikt om de journaalpost te classificeren. Vastleggen Classificeer de gebeurtenis op basis van BKPF-TCODE en een vooraf vastgestelde lijst met handmatige transactiecodes op het moment van boeken. Gebeurtenistype calculated | |||
| Journaalpost afgewezen | Een beoordelaar of goedkeurder wijst de journaalpost af, waardoor deze niet kan worden geboekt. Het document wordt meestal teruggestuurd naar de maker voor correctie. Daarmee begint een herstelronde. | ||
| Waarom dit belangrijk is Door afwijzingen te volgen, krijg je inzicht in de proceskwaliteit en veelvoorkomende fouten. Veel afwijzingen wijzen op problemen met de nauwkeurigheid van data, kennis van het beleid of ontbrekende ondersteunende documentatie. Waar vind je dit? Deze gebeurtenis is af te leiden uit een statuswijziging in een workflowlog of een aangepast statusveld op het journaalpostdocument. Wijzigingsdocumenten (CDHDR/CDPOS) voor het betreffende statusveld kunnen de timestamp leveren. Vastleggen Zoek via wijzigingsdocumenten (CDHDR/CDPOS) of workflowlogs naar een statuswijziging in ‘Afgewezen’. Gebeurtenistype inferred | |||
| Journaalpost gecorrigeerd | Na een afwijzing of verzoek om wijzigingen past een gebruiker de journaalpost aan. Dit is het herstelwerk dat nodig is om problemen uit de beoordeling op te lossen voordat de post opnieuw wordt ingediend. | ||
| Waarom dit belangrijk is Met deze activiteit meet je hoeveel herstelrondes er zijn. Door de frequentie en duur van correcties te analyseren, spoor je inefficiënties op en zie je waar training of verduidelijking van het proces nodig is. Waar vind je dit? Dit is af te leiden uit de datum ‘Last Changed On’ (AEDAT) in de tabel BKPF voor een document dat eerder de status ‘Afgewezen’ had. Wijzigingsdocumenten geven meer details over wat er is aangepast. Vastleggen Gebruik de timestamp uit de kopgegevens van wijzigingsdocumenten (CDHDR-UDATE) voor wijzigingen na een afwijzing. Gebeurtenistype inferred | |||
| Journaalpost geparkeerd | Een gebruiker slaat een onvolledige journaalpost op zonder deze te boeken, zodat die later kan worden aangevuld of beoordeeld. Bij deze expliciete handeling wordt een documentkop aangemaakt met de status ‘geparkeerd’. Het document is dan nog niet geboekt. | ||
| Waarom dit belangrijk is Parkeren is een gebruikelijke stap vóór indiening. Door te meten hoe lang een document geparkeerd blijft, zie je waar het aanvullen en voorbereiden van gegevens vertraging oploopt, voordat de formele beoordeling en goedkeuring begint. Waar vind je dit? In de tabel BKPF herken je een geparkeerd document aan de documentstatus (BSTAT) met de waarde ‘V’. De timestamp van de gebeurtenis is de aanmaakdatum (CPUDT). Vastleggen Filter op documenten waarvoor BKPF-BSTAT = 'V' op het moment van aanmaken. Gebeurtenistype explicit | |||
| Journaalpost gewijzigd na boeking | Na de boeking in het grootboek kan een gebruiker een beperkt aantal velden van de journaalpost wijzigen. De meeste financiële data kan daarna niet meer worden aangepast, maar velden zoals tekst of toewijzingen soms wel. | ||
| Waarom dit belangrijk is Deze activiteit is een belangrijk signaal voor compliance. Wijzigingen na het boeken kunnen wijzen op pogingen om gegevens aan te passen. Houd ze daarom goed in de gaten om fraude te voorkomen en de dataintegriteit te waarborgen. Waar vind je dit? Dit is betrouwbaar af te leiden uit de tabellen met wijzigingsdocumenten (CDHDR en CDPOS). Een CDHDR-record voor het document met een wijzigingsdatum na de boekingsdatum wijst op een wijziging na het boeken. Vastleggen Zoek in CDHDR naar records waarvan de wijzigingstimestamp (UDATE/UTIME) na de boekingsdatum van het document (BKPF-BUDAT) valt. Gebeurtenistype inferred | |||
| Ondersteunende documentatie toegevoegd | Een gebruiker voegt een of meer ondersteunende documenten, zoals facturen of spreadsheets, toe aan de journaalpost. Zo is er tijdens de beoordeling en audit bewijs en context beschikbaar voor de financiële transactie. | ||
| Waarom dit belangrijk is Voor compliance en een efficiënt goedkeuringsproces is het belangrijk dat documentatie vóór de beoordeling is toegevoegd. Met deze activiteit meet je of het documentatiebeleid wordt nageleefd en wat het effect daarvan is op de goedkeuringsdoorlooptijd. Waar vind je dit? Dit wordt meestal afgeleid door de aanmaaktimestamp te controleren van bijlagen die via Generic Object Services (GOS) zijn gekoppeld. De tabel SRGBTBREL koppelt het bedrijfsobject, bijvoorbeeld een BKPF-document, aan de bijlage. Vastleggen Zoek in de GOS-bijlagentabellen, zoals SRGBTBREL, naar koppelingen met het BKPF-object en gebruik de aanmaaktimestamp van de bijlage. Gebeurtenistype inferred | |||
Extractiegidsen
Stappen
- Vereisten en toegang: Zorg dat je een gebruiker hebt met de juiste autorisaties om de onderliggende database van SAP S/4HANA te raadplegen of ABAP-rapporten uit te voeren. Je hebt leestoegang nodig tot de CDS views I_JournalEntry en I_JournalEntryItem en tot de tabellen CDHDR, CDPOS, SRGBREL, SOOD, SWW_WI2OBJ en SWWLOGHIST. Toegang verloopt meestal via een databaseclient zoals SAP HANA Studio of DBeaver, of via SAP ABAP Development Tools (ADT) voor Eclipse.
- Systeemspecifieke instellingen bepalen: Bepaal voordat je de query uitvoert welke taakcodes worden gebruikt in de goedkeuringsworkflow voor journaalposten. Vraag de SAP-workflowbeheerder om de taak-ID’s (bijvoorbeeld TS12345678) voor indienen, afwijzen en goedkeuren. Deze heb je nodig voor de tijdelijke aanduidingen in de uiteindelijke query.
- De SQL-query voorbereiden: Kopieer de volledige SQL-query uit de sectie
querynaar de SQL-client of ontwikkelomgeving van je keuze. - Queryparameters instellen: Zoek de tijdelijke aanduidingen in de query en vervang ze door de juiste waarden. Vul
[YourCompanyCode],[StartDate]en[EndDate]in. Vervang ook de tijdelijke aanduidingen voor de workflowtaak-ID’s ([Workflow Submitted Task ID],[Workflow Rejected Task ID],[Workflow Approved Task ID]) door de waarden die je in de vorige stap hebt opgezocht. - De extractiequery uitvoeren: Voer de aangepaste SQL-query uit op de SAP S/4HANA-database. Afhankelijk van de periode en de hoeveelheid data kan dit lang duren. Voer de query bij voorkeur buiten piekuren uit.
- De eerste resultaten controleren: Bekijk na afloop de eerste rijen van de uitvoer. Controleer of kolommen zoals JournalEntryId, ActivityName en EventTime de verwachte waarden bevatten. De resultaten moeten één rij bevatten voor elke afzonderlijke bedrijfsgebeurtenis in de levenscyclus van een journaalpost.
- Data exporteren naar CSV: Exporteer alle resultaten vanuit je SQL-tool naar één CSV-bestand. Gebruik UTF-8-codering om problemen met speciale tekens te voorkomen.
- De upload voorbereiden: Controleer voordat je het bestand uploadt naar een process mining-tool of de CSV de vereiste kolomkoppen bevat. De data heeft al de structuur van een event log, dus verdere transformatie of pivotering is niet nodig.
Configuratie
- Core Data Services (CDS) views: De extractie gebruikt vooral
I_JournalEntryvoor kopgegevens enI_JournalEntryItemvoor gegevens over regels en bedragen. Deze views bieden een vereenvoudigde, semantisch rijke toegang tot het universele journaal (ACDOCA). - Ondersteunende tabellen: Voor een volledig beeld van het proces voegt de query ook verschillende standaard SAP-tabellen samen:
CDHDRenCDPOSom wijzigingen in documenten bij te houden.SRGBRELenSOODom vast te stellen wanneer bijlagen via Generic Object Services (GOS) zijn gekoppeld.SWW_WI2OBJenSWWLOGHISTom belangrijke gebeurtenissen uit de goedkeuringsworkflow op te halen.
- Filteren op periode: Filter de data op een specifieke periode om de prestaties op peil te houden. Gebruik het veld
I_JournalEntry.CreationDateTimein deWHERE-clausule. Voor een eerste analyse raden we een periode van 3 tot 6 maanden aan. - Filteren op organisatie: Filter altijd op
CompanyCode, zodat je alleen relevante juridische entiteiten ophaalt. In een groot systeem kunnen queries voor alle bedrijfscodes tegelijk erg lang duren. - Workflowtaak-ID’s: De query bevat tijdelijke aanduidingen voor workflowtaak-ID’s (bijvoorbeeld
[Workflow Approved Task ID]). Deze zijn uniek voor elke SAP-installatie en moeten correct worden ingesteld om workflowactiviteiten op te halen. Zonder deze ID’s worden gebeurtenissen voor indienen, goedkeuren en afwijzen niet vastgelegd. - Vereisten: De gebruiker die de query uitvoert, heeft ruime leestoegang nodig tot financiële, systeem- en workflowtabellen. Deze rechten zijn niet standaard en moeten apart worden toegekend.
Voorbeeldquery sql
WITH JournalEntryAmountCTE AS (
SELECT
CompanyCode,
AccountingDocument,
FiscalYear,
SUM(AmountInCompanyCodeCurrency) AS AmountInLocalCurrency
FROM I_JournalEntryItem
GROUP BY CompanyCode, AccountingDocument, FiscalYear
),
JournalEntryBaseCTE AS (
SELECT
JE.CompanyCode,
JE.AccountingDocument,
JE.FiscalYear,
JE.CreatedByUser,
JE.CreationDateTime,
JE.PostingDateTime,
JE.PostingDate,
JE.AccountingDocumentType,
JE.DocumentIsParked,
JE.ReversedJournalEntry,
JE.TransactionCode,
JEA.AmountInLocalCurrency
FROM I_JournalEntry AS JE
LEFT JOIN JournalEntryAmountCTE AS JEA
ON JE.CompanyCode = JEA.CompanyCode
AND JE.AccountingDocument = JEA.AccountingDocument
AND JE.FiscalYear = JEA.FiscalYear
WHERE JE.CompanyCode IN ('[YourCompanyCode]')
AND JE.CreationDateTime BETWEEN '[StartDate]' AND '[EndDate]'
)
-- 1. Journal Entry Created
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Created' AS "ActivityName",
BJE.CreationDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
UNION ALL
-- 2. Journal Entry Parked
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Parked' AS "ActivityName",
BJE.CreationDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.DocumentIsParked = 'X'
UNION ALL
-- 3. Supporting Documentation Attached
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Supporting Documentation Attached' AS "ActivityName",
TO_TIMESTAMP(SOOD.CREDAT || ' ' || SOOD.CRETIM, 'YYYYMMDD HH24MISS') AS "EventTime",
SOOD.OWNER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SRGBREL ON SRGBREL.INSTID_A = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND SRGBREL.TYPEID_A = 'BKPF'
AND SRGBREL.CATID_A = 'BO'
JOIN SOOD ON SOOD.OBJTP = SRGBREL.TYPEID_B
AND SOOD.OBJYR = SRGBREL.INSTID_B(3)
AND SOOD.OBJNO = SRGBREL.INSTID_B(5)
UNION ALL
-- 4. Journal Submitted For Review
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Submitted For Review' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Submitted Task ID]'
UNION ALL
-- 5. Journal Entry Rejected
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Rejected' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Rejected Task ID]'
UNION ALL
-- 6. Journal Entry Corrected (changed while parked)
SELECT DISTINCT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Corrected' AS "ActivityName",
TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') AS "EventTime",
CH.USERNAME AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN CDHDR AS CH ON CH.OBJECTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND CH.OBJECTCLASS = 'BELEG'
WHERE BJE.DocumentIsParked = 'X'
UNION ALL
-- 7. Journal Entry Approved
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Approved' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Approved Task ID]'
UNION ALL
-- 8. Manual Posting Identified
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Manual Posting Identified' AS "ActivityName",
BJE.PostingDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.PostingDateTime IS NOT NULL AND BJE.TransactionCode IN ('FB01', 'F-02', 'FB50', 'FV50', 'FBB1', 'FBV1')
UNION ALL
-- 9. Journal Entry Posted
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Posted' AS "ActivityName",
BJE.PostingDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.PostingDateTime IS NOT NULL
UNION ALL
-- 10. Journal Entry Changed After Posting
SELECT DISTINCT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Changed After Posting' AS "ActivityName",
TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') AS "EventTime",
CH.USERNAME AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN CDHDR AS CH ON CH.OBJECTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND CH.OBJECTCLASS = 'BELEG'
WHERE BJE.PostingDateTime IS NOT NULL AND TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') > BJE.PostingDateTime
UNION ALL
-- 11. Journal Entry Cleared
SELECT
JEI.AccountingDocument AS "JournalEntryId",
'Journal Entry Cleared' AS "ActivityName",
MIN(JEI.ClearingDateTime) AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser", -- Note: Clearing user is not directly available here
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM I_JournalEntryItem AS JEI
JOIN JournalEntryBaseCTE AS BJE ON JEI.AccountingDocument = BJE.AccountingDocument
AND JEI.CompanyCode = BJE.CompanyCode
AND JEI.FiscalYear = BJE.FiscalYear
WHERE JEI.ClearingDateTime IS NOT NULL
GROUP BY JEI.AccountingDocument, BJE.CreatedByUser, BJE.CompanyCode, BJE.AccountingDocumentType, BJE.PostingDate, BJE.AmountInLocalCurrency
UNION ALL
-- 12. Journal Entry Reversal Processed
SELECT
OriginalDoc.AccountingDocument AS "JournalEntryId",
'Journal Entry Reversal Processed' AS "ActivityName",
ReversalDoc.PostingDateTime AS "EventTime",
ReversalDoc.CreatedByUser AS "CreatedByUser",
OriginalDoc.CompanyCode AS "CompanyCode",
OriginalDoc.AccountingDocumentType AS "JournalEntryType",
OriginalDoc.PostingDate AS "PostingDate",
OriginalDoc.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS ReversalDoc
JOIN JournalEntryBaseCTE AS OriginalDoc
ON ReversalDoc.ReversedJournalEntry = OriginalDoc.AccountingDocument
AND ReversalDoc.CompanyCode = OriginalDoc.CompanyCode
AND ReversalDoc.ReversalFiscalYear = OriginalDoc.FiscalYear
WHERE ReversalDoc.ReversedJournalEntry IS NOT NULL; Stappen
- Controleer of rechtstreekse SQL-toegang tot de SAP HANA-database is goedgekeurd en of de gebruiker voor de extractie leestoegang heeft tot BKPF en ACDOCA. Controleer ook de toegang tot eventuele geconfigureerde bronnen voor workflows, bijlagen, wijzigingshistorie, aflettering of terugboekingen. Rechtstreekse databasetoegang verloopt meestal via SAP HANA Database Explorer, SAP HANA Studio of een goedgekeurde SQL-client. Voer geen extractiequeries uit in een SAP-applicatietransactie, tenzij je systeem die toegang expliciet ondersteunt.
- Controleer het fysieke schema van BKPF en ACDOCA, waaronder de velden voor client, bedrijfscode, boekjaar, documentnummer, documenttype, boekingsdatum, aanmaakdatum, aanmaaktijd, gebruiker, bedrag in lokale valuta en eventuele terugboekings- of afletteringsgegevens. SAP S/4HANA-implementaties kunnen verschillen in schema en beschikbare velden. Vervang daarom de tijdelijke aanduidingen tussen vierkante haken in de query door velden die in je systeem zijn gecontroleerd.
- Bepaal welke bronnen leidend zijn voor workflow- en bijlagegebeurtenissen. BKPF en ACDOCA bevatten gegevens over boekhoudkundige documenten en regels, maar geven niet altijd alle geparkeerde, ingediende, afgewezen, gecorrigeerde, goedgekeurde of bijgevoegde gebeurtenissen weer. Vervang de tijdelijke aanduidingen voor workflow- en bijlagebronnen door goedgekeurde views of tabellen uit je implementatie. Is een bron niet beschikbaar, verzin dan geen gebeurtenissen. Configureer de betreffende bron of sluit de activiteit uit na gedocumenteerde goedkeuring.
- Stel de extractieparameters in voor de gewenste periode, bedrijfscodes, documenttypen en client. Voor de eerste validatie raden we een periode van drie tot zes maanden aan. Gebruik voor operationele gebeurtenissen de periode van de event-timestamps en voor boekhoudkundige gebeurtenissen de boekingsdatum, volgens de afgesproken procesafbakening.
- Voer de volledige SQL-query uit in de goedgekeurde HANA SQL-client. De query maakt één eventrij voor elke expliciet opgehaalde activiteit. Voor boekhoudkundige gebeurtenissen gebruikt de query BKPF en ACDOCA. Voor workflow-, bijlage-, wijzigings-, afletterings- en terugboekingsgebeurtenissen gebruikt de query de geconfigureerde bronviews. Activiteiten worden niet afgeleid uit het enkele feit dat een document bestaat.
- Controleer het uitvoerschema. JournalEntryId is de case-ID, ActivityName is het activiteitenlabel en EventTime is de event-timestamp. De aanbevolen bedrijfsattributen worden opgenomen als ze beschikbaar zijn. Controleer of EventTime een timestamp is en of elke rij een niet-lege JournalEntryId en ActivityName bevat.
- Stem de boekhoudkundige populatie af door het aantal unieke JournalEntryId-waarden te vergelijken met de verwachte BKPF-populatie voor de geselecteerde client, bedrijfscodes, boekjaren en periode. Stem workflow- en bijlagepopulaties apart af, omdat de bewaartermijnen en timestampregels kunnen afwijken van die voor boekhoudkundige data.
- Controleer de volgorde van gebeurtenissen en de verwerking van duplicaten. Meerdere regels in ACDOCA mogen geen dubbele boekhoudkundige gebeurtenissen opleveren, tenzij het procesontwerp bewust gebeurtenissen op regelniveau vereist. Gebruik de aggregatielogica in de query voor één boekhoudkundige gebeurtenis per journaalpost en gebeurtenistype. Behoud waar mogelijk de geconfigureerde bron-ID’s van gebeurtenissen.
- Exporteer de resultaten als UTF-8-CSV of in een ander door ProcessMind ondersteund tabelbestand. Behoud exact de kolomnamen JournalEntryId, ActivityName en EventTime. Sorteer het bestand op JournalEntryId en EventTime en behoud aanvullende attributen als kolommen. Upload het bestand naar ProcessMind en stel JournalEntryId in als case-ID, ActivityName als activiteit en EventTime als event-timestamp.
Configuratie
- Periode: Begin met drie tot zes maanden. Gebruik voor prestatietests een kortere periode en breid die pas uit nadat het aantal rijen en de dekking van gebeurtenissen zijn gecontroleerd.
- Client en bedrijfsscope: Stel [Client parameter] in en beperk CompanyCode tot de vereiste juridische entiteiten. Laat het clientfilter niet weg in een systeem met meerdere clients.
- Boekhoudkundige scope: Stel [Document type filter] in en filter waar nodig ook op boekjaar en boekingsdatum. Neem geboekte en niet-geboekte documenten alleen op als de geselecteerde bron deze betrouwbaar weergeeft.
- Workflowscope: Stel [Workflow event source] en de koppeling met gebeurtenistypen in voor ingediende, afgewezen, gecorrigeerde en goedgekeurde activiteiten. Controleer of timestamps het aanmaken, uitvoeren of afronden van de workflowactie weergeven.
- Bijlagenscope: Stel [Attachment event source] in, evenals het relatieveld dat een bijlage aan de journaalpost koppelt. Controleer of de bron het aanmaken, vervangen of verwijderen van bijlagen registreert.
- Wijzigingsscope: Stel [Change history source] in voor wijzigingen na het boeken. Controleer of de bron de journaalpost identificeert en een betrouwbare wijzigingstimestamp bevat.
- Afletteringsscope: Stel [Clearing source] in en configureer de relatie tussen het afgeletterde boekhoudkundige document en het afletteringsdocument. Bepaal of de gebeurtenis wordt gekoppeld aan de oorspronkelijke journaalpost, het afletteringsdocument of beide.
- Terugboekingsscope: Stel [Reversal source] in en configureer de relatie tussen het oorspronkelijke document en de terugboeking. Als die relatie beschikbaar is, koppelt de query de terugboekingsactiviteit aan de oorspronkelijke JournalEntryId.
- Classificatie van handmatige boekingen: Stel [Manual posting source] of een gecontroleerd veld voor de herkomst van de boeking in. Manual Posting Identified is een classificatiegebeurtenis. Gebruik hiervoor consequent de boekingstimestamp of een andere goedgekeurde timestamp.
- Valutabedrag: ACDOCA bevat gegevens op regelniveau. De query telt bedragen in lokale valuta per journaalpost op. Controleer de tekenconventie en bepaal of statistische regels, grootboekspecifieke regels of regels uit een uitbreidingsgrootboek moeten worden opgenomen.
- Prestaties: Selecteer alleen de benodigde kolommen, filter vroeg en vermijd onbeperkte scans van ACDOCA. Voer de query uit binnen een goedgekeurd rapportagevenster. Gebruik waar mogelijk partition pruning met filters op client, boekjaar, bedrijfscode en boekingsdatum.
- Duplicaten verwerken: Gebruik waar mogelijk bron-ID’s van gebeurtenissen. Bevat een bron herhaalde technische records, pas dan de gedocumenteerde deduplicatieregel toe zonder afzonderlijke workflowacties samen te voegen.
- Vereisten: Vereiste databaserechten, goedgekeurde SAP HANA-connectiviteit, toegang tot de geconfigureerde workflow- en bijlagebronnen, de juiste configuratie van SAP Financial Accounting en workflows, en een door ProcessMind ondersteund exportformaat.
Voorbeeldquery sql
WITH
accounting_base AS (
SELECT
b.[Client field] AS ClientId,
b.[Company code field] AS CompanyCode,
b.[Fiscal year field] AS FiscalYear,
b.[Document number field] AS AccountingDocumentNumber,
b.[Document type field] AS JournalEntryType,
b.[Created by field] AS CreatedByUser,
b.[Document date field] AS DocumentDate,
b.[Posting date field] AS PostingDate,
b.[Creation date field] AS CreationDate,
b.[Creation time field] AS CreationTime,
b.[Reversal document field] AS ReversalDocumentNumber,
b.[Reversed document field] AS ReversedDocumentNumber,
b.[Reversal fiscal year field] AS ReversalFiscalYear,
SUM(a.[Local currency amount field]) AS AmountInLocalCurrency,
MAX(a.[Local currency field]) AS LocalCurrency
FROM [Your schema].[BKPF] b
INNER JOIN [Your schema].[ACDOCA] a
ON a.[Client field] = b.[Client field]
AND a.[Company code field] = b.[Company code field]
AND a.[Fiscal year field] = b.[Fiscal year field]
AND a.[Document number field] = b.[Document number field]
WHERE b.[Client field] = '[Client parameter]'
AND b.[Company code field] IN ([Company code filter])
AND b.[Posting date field] BETWEEN '[Start date parameter]' AND '[End date parameter]'
AND b.[Document type field] IN ([Document type filter])
GROUP BY
b.[Client field],
b.[Company code field],
b.[Fiscal year field],
b.[Document number field],
b.[Document type field],
b.[Created by field],
b.[Document date field],
b.[Posting date field],
b.[Creation date field],
b.[Creation time field],
b.[Reversal document field],
b.[Reversed document field],
b.[Reversal fiscal year field]
),
base_cases AS (
SELECT
ClientId,
CompanyCode,
FiscalYear,
AccountingDocumentNumber,
CAST(CompanyCode || '/' || FiscalYear || '/' || AccountingDocumentNumber AS NVARCHAR(100)) AS JournalEntryId,
JournalEntryType,
CreatedByUser,
PostingDate,
AmountInLocalCurrency,
LocalCurrency,
CreationDate,
CreationTime,
ReversalDocumentNumber,
ReversedDocumentNumber,
ReversalFiscalYear
FROM accounting_base
),
created_events AS (
SELECT
JournalEntryId,
'Journal Entry Created' AS ActivityName,
CAST(CreationDate || ' ' || CreationTime AS TIMESTAMP) AS EventTime,
CreatedByUser,
CompanyCode,
JournalEntryType,
PostingDate,
AmountInLocalCurrency,
LocalCurrency
FROM base_cases
),
parked_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Parked' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Parked event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
attachment_events AS (
SELECT
CAST(x.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Supporting Documentation Attached' AS ActivityName,
CAST(x.[Event timestamp field] AS TIMESTAMP) AS EventTime,
x.[User field] AS CreatedByUser,
x.[Company code field] AS CompanyCode,
x.[Journal entry type field] AS JournalEntryType,
x.[Posting date field] AS PostingDate,
x.[Amount in local currency field] AS AmountInLocalCurrency,
x.[Local currency field] AS LocalCurrency
FROM [Your schema].[Attachment event source] x
WHERE x.[Client field] = '[Client parameter]'
AND x.[Event type field] = '[Attachment created event type]'
AND CAST(x.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
submitted_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Submitted For Review' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Submitted event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
rejected_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Rejected' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Rejected event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
corrected_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Corrected' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Corrected event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
approved_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Approved' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Approved event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
manual_events AS (
SELECT
JournalEntryId,
'Manual Posting Identified' AS ActivityName,
CAST(PostingDate AS TIMESTAMP) AS EventTime,
CreatedByUser,
CompanyCode,
JournalEntryType,
PostingDate,
AmountInLocalCurrency,
LocalCurrency
FROM base_cases
WHERE [Manual posting condition verified for this system]
),
posted_events AS (
SELECT
JournalEntryId,
'Journal Entry Posted' AS ActivityName,
CAST(PostingDate AS TIMESTAMP) AS EventTime,
CreatedByUser,
CompanyCode,
JournalEntryType,
PostingDate,
AmountInLocalCurrency,
LocalCurrency
FROM base_cases
WHERE [Posted document condition verified for this system]
),
changed_events AS (
SELECT
CAST(c.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Changed After Posting' AS ActivityName,
CAST(c.[Change timestamp field] AS TIMESTAMP) AS EventTime,
c.[User field] AS CreatedByUser,
c.[Company code field] AS CompanyCode,
c.[Journal entry type field] AS JournalEntryType,
c.[Posting date field] AS PostingDate,
c.[Amount in local currency field] AS AmountInLocalCurrency,
c.[Local currency field] AS LocalCurrency
FROM [Your schema].[Change history source] c
WHERE c.[Client field] = '[Client parameter]'
AND c.[Post posting change indicator field] = '[Post posting change value]'
AND CAST(c.[Change timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
cleared_events AS (
SELECT
CAST(cl.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Cleared' AS ActivityName,
CAST(cl.[Clearing timestamp field] AS TIMESTAMP) AS EventTime,
cl.[User field] AS CreatedByUser,
cl.[Company code field] AS CompanyCode,
cl.[Journal entry type field] AS JournalEntryType,
cl.[Posting date field] AS PostingDate,
cl.[Amount in local currency field] AS AmountInLocalCurrency,
cl.[Local currency field] AS LocalCurrency
FROM [Your schema].[Clearing source] cl
WHERE cl.[Client field] = '[Client parameter]'
AND CAST(cl.[Clearing timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
reversal_events AS (
SELECT
CAST(r.[Original journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Reversal Processed' AS ActivityName,
CAST(r.[Reversal timestamp field] AS TIMESTAMP) AS EventTime,
r.[User field] AS CreatedByUser,
r.[Company code field] AS CompanyCode,
r.[Journal entry type field] AS JournalEntryType,
r.[Posting date field] AS PostingDate,
r.[Amount in local currency field] AS AmountInLocalCurrency,
r.[Local currency field] AS LocalCurrency
FROM [Your schema].[Reversal source] r
WHERE r.[Client field] = '[Client parameter]'
AND CAST(r.[Reversal timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
)
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM created_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM parked_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM attachment_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM submitted_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM rejected_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM corrected_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM approved_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM manual_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM posted_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM changed_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM cleared_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM reversal_events
ORDER BY JournalEntryId, EventTime, ActivityName; Stappen
- Het ABAP-programma maken: Open de ABAP Editor met transactiecode
SE38. Geef het nieuwe programma een naam, bijvoorbeeldZ_PM_JE_EXTRACT, en klik op ‘Create’. Vul een passende titel in, stel ‘Type’ in op ‘Executable Program’ en sla het programma op als lokaal object of in een package. - Het selectiescherm definiëren: Definieer in het programma parameters en select-options waarmee gebruikers de data kunnen filteren. Voeg een periode voor de aanmaakdatum van de journaalpost toe (
P_CPUDT_FR,P_CPUDT_TO), een select-option voor de bedrijfscode (SO_BUKRS) en een bestandspad voor de uitvoer op de applicatieserver (P_FPATH). - Datastructuren definiëren: Definieer een interne tabelstructuur die overeenkomt met het vereiste event log-formaat. Deze structuur bevat de uiteindelijke uitvoer. Declareer ook interne tabellen en werkgebieden voor de SAP-tabellen waaruit je data ophaalt, zoals BKPF, ACDOCA, CDHDR, CDPOS en verschillende workflowtabellen.
- De dataselectie implementeren: Schrijf de ABAP-logica om data op te halen voor elk van de 12 vereiste activiteiten. Maak voor elke activiteit een aparte subroutine (FORM), zodat de code overzichtelijk blijft. Maak bijvoorbeeld een FORM voor
get_created_events,get_parked_eventsenget_workflow_events. - Gebeurtenissen ‘Created’ en ‘Posted’ ophalen: Lees tabel BKPF uit op basis van de criteria op het selectiescherm. Een regel in BKPF betekent dat het document is aangemaakt. Een document met status
BSTAT = ' 'geldt als geboekt. Gebruik de aanmaaktimestamp (CPUDT,CPUTM) als eventtijd. - Gebeurtenissen ‘Parked’ ophalen: Lees tabel VBKPF, waarin de kopgegevens van geparkeerde documenten staan. De aanmaaktimestamp in deze tabel geeft het parkeermoment weer.
- Workflowgebeurtenissen ophalen (Submitted, Approved, Rejected): Raadpleeg workflowtabellen zoals SWW_WI2OBJ (om een journaalpostobject aan een workflowinstantie te koppelen) en SWWLOGHIST of SWWIHEAD (voor details en tijdstippen van specifieke stappen). Zoek de taak-ID’s op die in je systeem worden gebruikt voor indienen, goedkeuren en afwijzen.
- Gebeurtenissen ‘Change’ en ‘Correction’ ophalen: Raadpleeg de wijzigingsdocumenttabellen CDHDR (kopgegevens) en CDPOS (regels) voor
OBJECTCLAS = 'BELEG'. Filter voor ‘Changed After Posting’ op wijzigingen met een timestamp na de boekingsdatum van het document. Filter voor ‘Corrected’ op wijzigingen aan geparkeerde of afgewezen documenten. - Gebeurtenissen ‘Reversal’ en ‘Cleared’ ophalen: Zoek terugboekingen aan de hand van documenten waarin het veld
STBLG(teruggeboekt documentnummer) in BKPF is ingevuld. De eventtijd van de terugboeking is de aanmaaktijd van het terugboekingsdocument. Zoek afletteringsgebeurtenissen door de meest recente afletteringsdatum (AUGDT) op te halen uit tabel ACDOCA voor de regels van een journaalpost. - Data samenvoegen en sorteren: Voeg de opgehaalde gegevens van elke activiteit toe aan de uiteindelijke interne hoofdtabel. Sorteer de tabel na afloop op
JournalEntryIdenEventTime, zodat de gebeurtenissen per case chronologisch staan. - Het uitvoerbestand maken: Gebruik de statements
OPEN DATASET,LOOP AT... TRANSFERenCLOSE DATASETom de gesorteerde interne hoofdtabel naar het opgegeven bestandspad op de SAP-applicatieserver te schrijven. Het bestand moet CSV-formaat hebben en een kopregel bevatten. - De uitvoering plannen: Gebruik voor regelmatige extracties transactiecode
SM36om een achtergrondtaak te maken die het programmaZ_PM_JE_EXTRACTvolgens een vast schema uitvoert, bijvoorbeeld wekelijks of maandelijks. Zo verloopt de data-export automatisch.
Configuratie
- Periode: Het selectiescherm moet een verplichte periode bevatten voor de aanmaakdatum van de journaalpost (
CPUDT). Haal de data bij voorkeur op in behapbare perioden van bijvoorbeeld 3 tot 6 maanden, zodat de prestaties goed blijven. - Bedrijfscode (
BUKRS): Dit filter beperkt de extractie tot de juridische entiteiten die relevant zijn voor de process mining-analyse. Het is niet aan te raden alle bedrijfscodes tegelijk op te halen. - Documenttype (
BLART): Je kunt dit optionele filter gebruiken om je te richten op specifieke typen journaalposten, zoals ‘SA’ voor een grootboekboeking of ‘KR’ voor leveranciersfacturen. Zo beperk je de hoeveelheid data en verhoog je de relevantie van de dataset. - Bestandspad: Het programma heeft een logisch bestandspad nodig op de SAP-applicatieserver om het uitvoerbestand op te slaan. Controleer of het pad geldig is en of de SAP-systeemgebruiker schrijfrechten heeft voor die map. Gebruik transactie
AL11om servermappen te beheren en te bekijken. - Workflowtaak-ID’s: Configureer de logica voor het ophalen van workflowgebeurtenissen (Submitted, Approved, Rejected) met de specifieke taak-ID’s uit de goedkeuringsworkflow voor journaalposten van je organisatie. Deze zijn vaak aangepast en moeten worden opgezocht door een workflowconsultant of ontwikkelaar.
- Vereisten: De gebruiker of het systeemaccount dat het programma uitvoert, heeft ontwikkelaarsrechten nodig om ABAP-programma’s te maken en uit te voeren (
S_DEVELOP). Ook is ruime leestoegang nodig tot financiële tabellen (BKPF, ACDOCA), wijzigingslogtabellen (CDHDR, CDPOS) en workflowtabellen (SWW*).
Voorbeeldquery abap
REPORT Z_PM_JE_EXTRACT.
*&---------------------------------------------------------------------*
*&-- Data Structures for Event Log --*
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
journalentryid TYPE string,
activityname TYPE string,
eventtime TYPE string,
createdbyuser TYPE uname,
companycode TYPE bukrs,
journalentrytype TYPE blart,
postingdate TYPE budat,
amountinlocalcurrency TYPE wrbtr,
END OF ty_event_log.
*&---------------------------------------------------------------------*
*&-- Selection Screen Definition --*
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
PARAMETERS: p_erdat_fr TYPE dats OBLIGATORY DEFAULT sy-datum-30,
p_erdat_to TYPE dats OBLIGATORY DEFAULT sy-datum.
SELECT-OPTIONS: so_bukrs FOR bkpf-bukrs OBLIGATORY.
PARAMETERS: p_fpath TYPE string OBLIGATORY DEFAULT '/usr/sap/trans/tmp/je_event_log.csv'.
SELECTION-SCREEN END OF BLOCK b1.
*&---------------------------------------------------------------------*
*&-- Internal Tables --*
*&---------------------------------------------------------------------*
DATA: gt_event_log TYPE TABLE OF ty_event_log.
*&---------------------------------------------------------------------*
*&-- Main Processing Block --*
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM get_created_posted_events.
PERFORM get_parked_events.
PERFORM get_attachment_events.
PERFORM get_workflow_events.
PERFORM get_change_events.
PERFORM get_cleared_events.
PERFORM get_reversal_events.
SORT gt_event_log BY journalentryid eventtime.
PERFORM write_output_file.
*&---------------------------------------------------------------------*
*&-- Subroutines for Extracting Individual Activities --*
*&---------------------------------------------------------------------*
FORM get_created_posted_events.
DATA: lt_bkpf TYPE TABLE OF bkpf,
ls_event_log TYPE ty_event_log,
lv_timestamp TYPE string.
SELECT * FROM bkpf INTO TABLE lt_bkpf
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to.
LOOP AT lt_bkpf ASSIGNING FIELD-SYMBOL(<fs_bkpf>).
CLEAR ls_event_log.
CONCATENATE <fs_bkpf>-bukrs <fs_bkpf>-belnr <fs_bkpf>-gjahr INTO ls_event_log-journalentryid.
ls_event_log-companycode = <fs_bkpf>-bukrs.
ls_event_log-journalentrytype = <fs_bkpf>-blart.
ls_event_log-postingdate = <fs_bkpf>-budat.
ls_event_log-createdbyuser = <fs_bkpf>-usnam.
" Timestamp format YYYY-MM-DDTHH:MI:SS
CONCATENATE <fs_bkpf>-cpudt(4) '-' <fs_bkpf>-cpudt+4(2) '-' <fs_bkpf>-cpudt+6(2) 'T' <fs_bkpf>-cputm(2) ':' <fs_bkpf>-cputm+2(2) ':' <fs_bkpf>-cputm+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
" Activity: Journal Entry Created
ls_event_log-activityname = 'Journal Entry Created'.
SELECT SUM( hsl ) INTO ls_event_log-amountinlocalcurrency FROM acdoca WHERE belnr = <fs_bkpf>-belnr AND gjahr = <fs_bkpf>-gjahr AND bukrs = <fs_bkpf>-bukrs.
APPEND ls_event_log TO gt_event_log.
" Activity: Journal Entry Posted (if not parked)
IF <fs_bkpf>-bstat = ' '.
ls_event_log-activityname = 'Journal Entry Posted'.
APPEND ls_event_log TO gt_event_log.
" Activity: Manual Posting Identified (based on T-Code)
CASE <fs_bkpf>-tcode.
WHEN 'FB01' OR 'F-02' OR 'FB50' OR 'F-22' OR 'F-43'.
ls_event_log-activityname = 'Manual Posting Identified'.
APPEND ls_event_log TO gt_event_log.
ENDCASE.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_parked_events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM vbkpf
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to.
CLEAR ls_event_log.
CONCATENATE vbkpf-bukrs vbkpf-belnr vbkpf-gjahr INTO ls_event_log-journalentryid.
CONCATENATE vbkpf-cpudt(4) '-' vbkpf-cpudt+4(2) '-' vbkpf-cpudt+6(2) 'T' vbkpf-cputm(2) ':' vbkpf-cputm+2(2) ':' vbkpf-cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Journal Entry Parked'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = vbkpf-usnam.
ls_event_log-companycode = vbkpf-bukrs.
ls_event_log-journalentrytype = vbkpf-blart.
ls_event_log-postingdate = vbkpf-budat.
APPEND ls_event_log TO gt_event_log.
ENDSELECT.
ENDFORM.
FORM get_attachment_events.
DATA: lt_bdocs TYPE TABLE OF srgbtbrel, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM srgbtbrel INTO TABLE lt_bdocs
WHERE typeid_a = 'BUS2081' " Object type for Accounting Document
AND catid_a = 'BO'.
LOOP AT lt_bdocs ASSIGNING FIELD-SYMBOL(<fs_bdocs>).
CHECK <fs_bdocs>-instid_a(4) IN so_bukrs.
DATA(lv_bukrs) = <fs_bdocs>-instid_a(4).
DATA(lv_belnr) = <fs_bdocs>-instid_a+4(10).
DATA(lv_gjahr) = <fs_bdocs>-instid_a+14(4).
SELECT SINGLE cpudt, cputm, usnam, blart, budat FROM bkpf
INTO (DATA(lv_cpudt), DATA(lv_cputm), DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = lv_bukrs AND belnr = lv_belnr AND gjahr = lv_gjahr.
IF sy-subrc = 0 AND lv_cpudt BETWEEN p_erdat_fr AND p_erdat_to.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
" Note: Using document creation time as a proxy for attachment time.
CONCATENATE lv_cpudt(4) '-' lv_cpudt+4(2) '-' lv_cpudt+6(2) 'T' lv_cputm(2) ':' lv_cputm+2(2) ':' lv_cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Supporting Documentation Attached'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = lv_bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_workflow_events.
" This is a simplified example. Real workflow logic can be complex.
" You must identify your specific Task IDs for these events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
DATA: BEGIN OF ls_wi, wi_id TYPE sww_wiid, cr_date TYPE sww_cd, cr_time TYPE sww_ct, task TYPE sww_task, instid TYPE swo_typeid, END OF ls_wi.
SELECT h~wi_id h~cr_date h~cr_time h~wi_rh_task o~instid
FROM swwwihead AS h
JOIN sww_wi2obj AS o ON h~wi_id = o~wi_id
INTO @ls_wi
WHERE o~typeid = 'BUS2081' AND o~catid = 'BO'
AND h~cr_date BETWEEN @p_erdat_fr AND @p_erdat_to.
DATA(lv_bukrs) = ls_wi-instid(4).
DATA(lv_belnr) = ls_wi-instid+4(10).
DATA(lv_gjahr) = ls_wi-instid+14(4).
IF lv_bukrs IN so_bukrs.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
CONCATENATE ls_wi-cr_date(4) '-' ls_wi-cr_date+4(2) '-' ls_wi-cr_date+6(2) 'T' ls_wi-cr_time(2) ':' ls_wi-cr_time+2(2) ':' ls_wi-cr_time+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-companycode = lv_bukrs.
CASE ls_wi-task.
WHEN '[Your Submit Task ID]'. " e.g., TS20000139
ls_event_log-activityname = 'Journal Submitted For Review'.
APPEND ls_event_log TO gt_event_log.
WHEN '[Your Approve Task ID]'. " e.g., TS20000142
ls_event_log-activityname = 'Journal Entry Approved'.
APPEND ls_event_log TO gt_event_log.
WHEN '[Your Reject Task ID]'. " e.g., TS20000141
ls_event_log-activityname = 'Journal Entry Rejected'.
APPEND ls_event_log TO gt_event_log.
ENDCASE.
ENDIF.
ENDSELECT.
ENDFORM.
FORM get_change_events.
DATA: lt_cdhdr TYPE TABLE OF cdhdr, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM cdhdr INTO TABLE lt_cdhdr
WHERE objectclas = 'BELEG'
AND udate BETWEEN p_erdat_fr AND p_erdat_to.
LOOP AT lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>).
DATA(lv_bukrs) = <fs_cdhdr>-objectid(4).
DATA(lv_belnr) = <fs_cdhdr>-objectid+4(10).
DATA(lv_gjahr) = <fs_cdhdr>-objectid+14(4).
IF lv_bukrs IN so_bukrs.
SELECT SINGLE bstat, budat, blart FROM bkpf
INTO (DATA(lv_bstat), DATA(lv_budat), DATA(lv_blart))
WHERE bukrs = lv_bukrs AND belnr = lv_belnr AND gjahr = lv_gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
CONCATENATE <fs_cdhdr>-udate(4) '-' <fs_cdhdr>-udate+4(2) '-' <fs_cdhdr>-udate+6(2) 'T' <fs_cdhdr>-utime(2) ':' <fs_cdhdr>-utime+2(2) ':' <fs_cdhdr>-utime+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = <fs_cdhdr>-username.
ls_event_log-companycode = lv_bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
IF lv_bstat = ' ' AND <fs_cdhdr>-udate > lv_budat.
ls_event_log-activityname = 'Journal Entry Changed After Posting'.
APPEND ls_event_log TO gt_event_log.
ELSEIF lv_bstat <> ' '.
ls_event_log-activityname = 'Journal Entry Corrected'.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_cleared_events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
DATA: BEGIN OF ls_clear, belnr TYPE belnr_d, gjahr TYPE gjahr, bukrs TYPE bukrs, augdt TYPE augdt, END OF ls_clear, lt_clear LIKE TABLE OF ls_clear.
SELECT belnr, gjahr, bukrs, MAX( augdt ) AS augdt FROM acdoca
INTO TABLE @lt_clear
WHERE bukrs IN @so_bukrs
AND augdt NE '00000000'
AND augdt BETWEEN @p_erdat_fr AND @p_erdat_to
GROUP BY belnr, gjahr, bukrs.
LOOP AT lt_clear INTO ls_clear.
SELECT SINGLE usnam, blart, budat FROM bkpf
INTO (DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = ls_clear-bukrs AND belnr = ls_clear-belnr AND gjahr = ls_clear-gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE ls_clear-bukrs ls_clear-belnr ls_clear-gjahr INTO ls_event_log-journalentryid.
CONCATENATE ls_clear-augdt(4) '-' ls_clear-augdt+4(2) '-' ls_clear-augdt+6(2) 'T12:00:00' INTO lv_timestamp. " Clearing date has no time, use midday
ls_event_log-activityname = 'Journal Entry Cleared'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = ls_clear-bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_reversal_events.
DATA: lt_reversals TYPE TABLE OF bkpf, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM bkpf INTO TABLE lt_reversals
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to
AND stblg IS NOT NULL.
LOOP AT lt_reversals ASSIGNING FIELD-SYMBOL(<fs_rev>).
SELECT SINGLE usnam, blart, budat FROM bkpf
INTO (DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = <fs_rev>-bukrs AND belnr = <fs_rev>-stblg AND gjahr = <fs_rev>-gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE <fs_rev>-bukrs <fs_rev>-stblg <fs_rev>-gjahr INTO ls_event_log-journalentryid.
CONCATENATE <fs_rev>-cpudt(4) '-' <fs_rev>-cpudt+4(2) '-' <fs_rev>-cpudt+6(2) 'T' <fs_rev>-cputm(2) ':' <fs_rev>-cputm+2(2) ':' <fs_rev>-cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Journal Entry Reversal Processed'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = <fs_rev>-bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM write_output_file.
DATA: lv_line TYPE string.
FIELD-SYMBOLS: <fs_event_log> TYPE ty_event_log.
OPEN DATASET p_fpath FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc NE 0.
MESSAGE 'Error opening file.' TYPE 'E'.
RETURN.
ENDIF.
" Write Header
lv_line = 'JournalEntryId,ActivityName,EventTime,CreatedByUser,CompanyCode,JournalEntryType,PostingDate,AmountInLocalCurrency'.
TRANSFER lv_line TO p_fpath.
LOOP AT gt_event_log ASSIGNING <fs_event_log>.
CONCATENATE <fs_event_log>-journalentryid <fs_event_log>-activityname <fs_event_log>-eventtime <fs_event_log>-createdbyuser <fs_event_log>-companycode <fs_event_log>-journalentrytype <fs_event_log>-postingdate <fs_event_log>-amountinlocalcurrency
INTO lv_line SEPARATED BY ','.
TRANSFER lv_line TO p_fpath.
ENDLOOP.
CLOSE DATASET p_fpath.
WRITE: / 'File successfully written to', p_fpath.
ENDFORM. Klaar om aan de slag te gaan?
Gebruik deze template om je data voor te bereiden en met zekerheid inzicht te krijgen in het Record to Report-proces voor journaalposten. Zet vandaag de eerste stap naar betere processen.
Maak Record to Report-journaalposten efficiënter
Verbeter het proces en verkort de doorlooptijd van Record to Report-journaalposten met 30%.
Geen creditcard nodig. Binnen enkele minuten ingesteld.