Datatemplate voor het Purchase to Pay-proces voor inkooporders
Datatemplate voor het Purchase to Pay-proces voor inkooporders
- Aanbevolen attributen voor een gedetailleerde analyse
- Belangrijke activiteiten om in het proces te volgen
- Stapsgewijze uitleg voor data-extractie
Attributen voor het Purchase to Pay-proces voor inkooporders
| Naam | Beschrijving | ||
|---|---|---|---|
| Activiteit ActivityName | De naam van de bedrijfsgebeurtenis of processtap in het inkooporderproces. | ||
| Beschrijving Dit attribuut beschrijft een specifieke actie of statuswijziging in de levenscyclus van een inkooporder, zoals ‘Inkooporder aangemaakt’, ‘Inkooporder goedgekeurd’ of ‘Goederenontvangst geboekt’. De volgorde van deze activiteiten vormt de processtroom. De volgorde en frequentie van activiteiten analyseren is de kern van process mining. Zo ontdek je hoe het proces werkelijk verloopt, vergelijk je dit met het ontworpen model en spoor je bottlenecks op, zoals lange wachttijden na ‘Factuur ontvangen’. Ook kun je herstelwerk kwantificeren, bijvoorbeeld door herhaalde activiteiten als ‘Inkooporder gewijzigd’ te tellen. Waarom dit belangrijk is Dit attribuut beschrijft de processtappen en maakt visualisatie en analyse van de volledige processtroom, procesvarianten en bottlenecks mogelijk. Waar vind je dit? Meestal afgeleid uit een combinatie van tabellen en velden, zoals statusvelden in EKKO/EKPO of wijzigingsdocumentlogs in CDHDR/CDPOS, om belangrijke bedrijfsgebeurtenissen weer te geven. Voorbeelden Inkooporder aangemaaktInkooporder goedgekeurdGoederenontvangst geboektFactuur ontvangen | |||
| Inkooporder PurchaseOrderNumber | De unieke identificatiecode van de inkooporder (PO), die als primaire case-ID dient om de levenscyclus van de inkoop te volgen. | ||
| Beschrijving Het inkoopordernummer is de centrale identificatiecode die alle bijbehorende activiteiten verbindt, van het aanmaken tot de uiteindelijke goederenontvangst en afronding. Bij process mining dient het als case-ID. Door gebeurtenissen in analyses op dit nummer te groeperen, kun je het verloop van elke afzonderlijke inkooporder reconstrueren. Dat is nodig om doorlooptijden te berekenen, procesvarianten te analyseren en bottlenecks of afwijkingen bij een specifieke order op te sporen. Waarom dit belangrijk is Dit is de sleutel waarmee je alle inkoopgebeurtenissen samenbrengt in één end-to-endproces en de levenscyclus van elke inkooporder in detail kunt analyseren. Waar vind je dit? Dit attribuut staat in tabel EKKO van SAP S/4HANA, veld EBELN. Voorbeelden 450001712345000171244500017125 | |||
| Tijdstip van gebeurtenis EventTime | De timestamp die aangeeft wanneer de activiteit plaatsvond. | ||
| Beschrijving Dit attribuut legt de exacte datum en tijd van elke procesactiviteit vast. Het vormt de basis voor alle tijdsanalyses in process mining. Met het tijdstip van de gebeurtenis zet je activiteiten in chronologische volgorde en bouw je de processtroom op. Ook gebruik je het om tijdsgebonden metrieken te berekenen, zoals doorlooptijden tussen activiteiten, wachttijden en verwerkingstijden. Die zijn belangrijk voor prestatieanalyses en het opsporen van bottlenecks. Waarom dit belangrijk is Deze timestamp is nodig om gebeurtenissen in de juiste volgorde te zetten en prestatiemetrieken te berekenen, zoals doorlooptijden, levertijden en wachttijden. Waar vind je dit? Timestampvelden van specifieke activiteiten, zoals de aanmaakdatum (EKKO-AEDAT voor wijzigingen) of boekingsdatum (MKPF-BUDAT voor goederenontvangsten). Vaak moet je hiervoor data uit meerdere tabellen combineren. Voorbeelden 2023-04-15T10:00:00Z2023-04-15T14:30:00Z2023-05-01T09:15:00Z | |||
| Bronsysteem SourceSystem | Geeft aan uit welk bronsysteem de data is geëxtraheerd. | ||
| Beschrijving Dit attribuut geeft aan uit welk systeem de gebeurtenisdata afkomstig is, bijvoorbeeld ‘SAP S/4HANA Production’ of ‘SAP ECC’. In omgevingen met meerdere systemen is dit veld belangrijk om de herkomst van data te volgen, problemen op te lossen en data uit verschillende bronnen goed te interpreteren. Het geeft context aan de data en kan worden gebruikt om analyses op specifieke systeemomgevingen te filteren. Waarom dit belangrijk is Geeft belangrijke context over de herkomst van de data. Dat is nodig voor datagovernance, validatie en analyse in omgevingen met meerdere systemen. Waar vind je dit? Dit is meestal een statische waarde die tijdens het ETL-proces (extractie, transformatie en laden) wordt toegevoegd om de herkomst van de dataset aan te geven. Voorbeelden S4H_PROD_100ECC_EU_200S4H_US_300 | |||
| Laatste data-update LastDataUpdate | De timestamp waarop de data voor het laatst is vernieuwd of uit het bronsysteem is geëxtraheerd. | ||
| Beschrijving Dit attribuut geeft aan hoe actueel de geanalyseerde data is. Het toont de datum en tijd waarop de data voor het laatst uit SAP S/4HANA is opgehaald. Met de datum en tijd van de laatste data-update kunnen gebruikers beoordelen hoe actueel de analyse is. Zo weten ze of ze realtime-informatie bekijken of een momentopname. Dat bepaalt mede hoe relevant acties op basis van de analyse zijn. Waarom dit belangrijk is Laat gebruikers zien hoe actueel de data is, zodat ze de context en relevantie van hun analyse goed kunnen beoordelen. Waar vind je dit? Dit is een metadatatimestamp die tijdens het ETL-proces (extractie, transformatie en laden) wordt toegevoegd. Voorbeelden 2024-05-21T02:00:00Z2024-05-20T02:00:00Z2024-05-19T02:00:00Z | |||
| Gebruiker UserName | De identificatiecode van de gebruiker die een specifieke activiteit heeft uitgevoerd. | ||
| Beschrijving Dit attribuut legt de SAP-gebruikers-ID vast van degene die een document heeft aangemaakt, gewijzigd of goedgekeurd. Zo kun je acties in het systeem herleiden. Met analyses per gebruiker kun je opleidingsbehoeften, werkverdeling en individuele prestaties in kaart brengen. Je kunt bijvoorbeeld nagaan of bepaalde gebruikers vaak betrokken zijn bij lange goedkeuringstijden of wijzigingen na goedkeuring. Die informatie helpt bij gebruikersbeheer en procesverbetering. Waarom dit belangrijk is Maakt duidelijk wie waarvoor verantwoordelijk is en ondersteunt prestatieanalyses per persoon of team. Zo kun je opleidingsbehoeften en beperkte capaciteit herkennen. Waar vind je dit? Deze informatie staat in velden als ERNAM (Gemaakt door) in EKKO of in het gebruikersveld van wijzigingsdocumenttabellen (CDHDR-USERNAME). Voorbeelden CB9980000012JSMITHRROE | |||
| Gevraagde leverdatum RequestedDeliveryDate | De datum waarop het bedrijf de leverancier heeft gevraagd de goederen of diensten te leveren. | ||
| Beschrijving Dit attribuut geeft de beoogde leverdatum uit de inkooporder aan. Deze datum is het uitgangspunt voor het meten van de leverprestaties van leveranciers. Bij process mining vergelijk je deze datum met de werkelijke datum van goederenontvangst (de timestamp van ‘Goederenontvangst geboekt’) om de KPI ‘Leveringen op tijd per leverancier’ te berekenen. Afwijkingen helpen je de betrouwbaarheid van leveranciers te beoordelen en risico’s in de toeleveringsketen te beheersen. Waarom dit belangrijk is Is het uitgangspunt voor het meten van tijdige leveringen door leveranciers, een belangrijke KPI voor het beheer van de toeleveringsketen en de operationele planning. Waar vind je dit? Dit veld staat in de planningregeltabel EKET, veld EINDT. Voorbeelden 2023-06-012023-06-152023-07-01 | |||
| Inkoopaanvraag PurchaseRequisitionNumber | De identificatiecode van de inkoopaanvraag (PR) waarmee de inkooporder is gestart. | ||
| Beschrijving Dit attribuut koppelt de inkooporder aan de oorspronkelijke inkoopaanvraag. Niet elke inkooporder heeft een aanvraag, bijvoorbeeld wanneer de order rechtstreeks wordt aangemaakt. Deze koppeling is nodig om het volledige inkoopproces vanaf de eerste aanvraag te analyseren. Ze ondersteunt KPI’s als ‘Goedkeuringstijd van inkoopaanvragen’ en helpt ongeautoriseerde uitgaven op te sporen, waarbij inkooporders zonder voorafgaande goedgekeurde aanvraag worden aangemaakt. Waarom dit belangrijk is Verbindt de inkooporder met de oorspronkelijke aanvraag. Zo kun je het hele proces analyseren en ongeautoriseerde uitgaven opsporen. Waar vind je dit? Dit attribuut staat in tabel EKPO van SAP S/4HANA (niveau van inkooporderitems), veld BANFN. Voorbeelden 1001005110010052 | |||
| Inkoopordertype DocumentType | Een classificatie voor verschillende soorten inkooporders, zoals standaardorders, dienstenorders of voorraadtransportorders. | ||
| Beschrijving Het documenttype is een belangrijk configuratie-element in SAP. Het bepaalt de processtroom, nummerreeks en velden van een inkooporder. Zo kunnen bedrijven het inkoopproces aanpassen aan verschillende situaties. Door het proces per documenttype te analyseren, krijg je inzicht in procesvarianten. Een standaardorder voor goederen kan bijvoorbeeld heel anders verlopen dan een dienstenorder of voorraadtransportorder. Met dit attribuut kun je die processtromen filteren en vergelijken om gerichte verbeterpunten te vinden. Waarom dit belangrijk is Deelt inkooporders in categorieën in. Zo kun je verschillende inkoopprocessen vergelijken en verschillen in processtromen en doorlooptijden verklaren. Waar vind je dit? Dit attribuut staat in tabel EKKO van SAP S/4HANA, veld BSART. Voorbeelden NBFOUB | |||
| Leveranciers-ID VendorId | De unieke identificatiecode van de leverancier die de goederen of diensten levert. | ||
| Beschrijving De leveranciers-ID is belangrijke stamdata die een inkooporder aan een specifieke leverancier koppelt. De ID wordt gebruikt voor communicatie, levering en betaling tijdens het inkoopproces. Met dit attribuut kun je leveranciersprestaties analyseren. Het is nodig voor dashboards als ‘Prestaties van de levertijd per leverancier’ en ‘Retourpercentage van goederen per leverancier’. Zo zie je welke leveranciers betrouwbaar zijn en wie mogelijk vertragingen of kwaliteitsproblemen veroorzaakt. Waarom dit belangrijk is Maakt analyses per leverancier mogelijk. Zo kun je prestaties beoordelen, goed en minder goed presterende leveranciers herkennen en de toeleveringsketen verbeteren. Waar vind je dit? Dit attribuut staat in tabel EKKO van SAP S/4HANA, veld LIFNR. Voorbeelden 100023100045100088 | |||
| Totaal nettobedrag TotalNetAmount | De totale waarde van de inkooporder, exclusief belastingen en vrachtkosten. | ||
| Beschrijving Dit attribuut geeft de nettowaarde van de inkooporder weer. Het is een belangrijk financieel gegeven dat de omvang van de inkooptransactie aangeeft. Dit bedrag is nuttig voor financiële analyses, bijvoorbeeld om inkooporders op waarde in te delen en te zien of de processtromen verschillen. Je kunt het ook gebruiken om analyses te prioriteren en te beginnen bij orders met een hoge waarde, die meer financieel risico kunnen opleveren of meer impact op het bedrijf hebben. Waarom dit belangrijk is Maakt financiële analyses mogelijk. Je kunt inkooporders op waarde indelen en procesverbeteringen richten op gebieden met hoge uitgaven. Waar vind je dit? Dit attribuut staat in tabel EKKO van SAP S/4HANA, veld NETWR. Voorbeelden 1500.0025000.50125.75 | |||
| Bedrijfscode CompanyCode | De identificatiecode van de rechtspersoon of het bedrijf waarvoor de inkooporder wordt aangemaakt. | ||
| Beschrijving De bedrijfscode staat voor een zelfstandige administratieve eenheid binnen een organisatie. Alle financiële transacties voor een inkooporder worden op een specifieke bedrijfscode geboekt. Dit is een belangrijk organisatieattribuut waarmee je inkoopprocessen van verschillende rechtspersonen kunt filteren en vergelijken. Analyse per bedrijfscode kan verschillen in de uitvoering van processen, efficiëntie of compliance aan het licht brengen. Waarom dit belangrijk is Hiermee kun je procesanalyses uitsplitsen naar rechtspersoon en prestaties en compliance tussen bedrijfsonderdelen vergelijken. Waar vind je dit? Dit attribuut staat in de SAP S/4HANA-tabel EKKO, veld BUKRS. Voorbeelden 101017102000 | |||
| Inkoopgroep PurchasingGroup | De specifieke groep inkopers die verantwoordelijk is voor bepaalde inkoopactiviteiten. | ||
| Beschrijving Een inkoopgroep bestaat uit één of meer inkopers die verantwoordelijk zijn voor specifieke inkoopactiviteiten, materialen of leveranciers. Zij zijn het eerste aanspreekpunt voor leveranciers. Met dit attribuut kun je de werkdruk en prestaties gedetailleerder analyseren dan met de inkooporganisatie. Je kunt er overbelaste teams mee opsporen, de efficiëntie van verschillende inkoopgroepen meten en nagaan welke groepen vaker afwijken van het proces, bijvoorbeeld door buiten contracten om in te kopen. Waarom dit belangrijk is Geeft inzicht in de prestaties van inkoopgroepen, zodat je werkdruk, efficiëntie en naleving van processen op teamniveau kunt analyseren. Waar vind je dit? Dit attribuut staat in de SAP S/4HANA-tabel EKKO, veld EKGRP. Voorbeelden 001002N00 | |||
| Inkooporganisatie PurchasingOrganization | De organisatie-eenheid die verantwoordelijk is voor de inkoop van materialen en diensten en voor onderhandelingen met leveranciers. | ||
| Beschrijving De inkooporganisatie is een belangrijke organisatie-eenheid binnen de inkoop. Deze kan op concern-, bedrijfs- of fabrieksniveau zijn ingericht en is verantwoordelijk voor alle inkoopactiviteiten. Met een analyse per inkooporganisatie kun je de efficiëntie en prestaties van verschillende inkoopteams of regio’s beoordelen. Zo worden verschillen zichtbaar in onderhandelingen met leveranciers, naleving van processen of vertragingen bij goedkeuringen. Waarom dit belangrijk is Hiermee kun je prestaties van verschillende inkoopafdelingen of regio’s vergelijken en goede werkwijzen en verbeterpunten vinden. Waar vind je dit? Dit attribuut staat in de SAP S/4HANA-tabel EKKO, veld EKORG. Voorbeelden 10101710US01 | |||
| Is herstelwerk IsRework | Een berekende indicator die aangeeft of de inkooporder herstelwerk vereiste, bijvoorbeeld door een wijziging na goedkeuring of een retour van goederen. | ||
| Beschrijving Dit booleaanse attribuut wordt berekend aan de hand van de activiteitenvolgorde voor elke inkooporder. De waarde is 'true' als de gebeurtenis 'Inkooporder gewijzigd' plaatsvindt na 'Inkooporder goedgekeurd', of als de gebeurtenis 'Goederen retour' voorkomt. Deze indicator vereenvoudigt de berekening van de KPI 'Percentage volledig automatisch verwerkte orders'. Je kunt hiermee eenvoudig alle inkooporders filteren en weergeven waarvoor handmatige tussenkomst of correctie nodig was. Zo wordt duidelijk hoe vaak herstelwerk voorkomt en wat het kost. Waarom dit belangrijk is Maakt inefficiëntie zichtbaar door cases met herstelwerk te markeren. Dit helpt bij het berekenen van het percentage volledig automatisch verwerkte orders en het opsporen van oorzaken van afwijkingen. Waar vind je dit? Berekend veld op basis van de activiteitenvolgorde. De logica controleert of de gebeurtenis 'Inkooporder gewijzigd' volgt op een goedkeuring, of dat de gebeurtenis 'Goederen retour' voorkomt. Voorbeelden truefalse | |||
| Is inkoop buiten contract IsMaverickSpend | Een berekende indicator die aangeeft of een inkooporder is aangemaakt zonder voorafgaande, goedgekeurde inkoopaanvraag. | ||
| Beschrijving Deze booleaanse indicator wordt tijdens de gegevensverwerking berekend. De waarde is 'true' als er geen inkoopaanvraag aan een inkooporder is gekoppeld of als de inkooporder buiten de standaardgoedkeuringsworkflow om is aangemaakt. Dit attribuut ondersteunt het dashboard 'Inkoop buiten contract opsporen' en de bijbehorende KPI’s. Het maakt zichtbaar hoe vaak er niet volgens het inkoopbeleid wordt ingekocht. Zo kunnen bedrijven specifieke afdelingen of gebruikersgroepen aanspreken en het inkoopbeleid en de controles versterken. Waarom dit belangrijk is Spoort inkopen op die niet aan de regels voldoen. Zo kun je procesafwijkingen meten en financiële controles en inkoopbeleid handhaven. Waar vind je dit? Berekend veld op basis van een ontbrekende waarde in 'PurchaseRequisitionNumber' voor bepaalde documenttypen, of op basis van de analyse van de gebeurtenisvolgorde. Voorbeelden truefalse | |||
| Itemcategorie ItemCategory | Classificeert een inkooporderregel, bijvoorbeeld als standaard, consignatie, onderaanneming of dienst. | ||
| Beschrijving De itemcategorie bepaalt hoe de inkoop van een specifiek materiaal of een specifieke dienst wordt beheerd en verwerkt. Ze is van invloed op vervolgstappen zoals goederenontvangst en factuurcontrole. Dit attribuut is nuttig om procesvarianten te analyseren op basis van wat er wordt ingekocht. Voor een dienst is bijvoorbeeld een service-entrysheet nodig, terwijl een standaardvoorraadartikel een heel ander proces volgt. Met analyses per itemcategorie kun je die verschillen verklaren en gerichte procesverbeteringen doorvoeren. Waarom dit belangrijk is Licht procesvarianten toe door onderscheid te maken tussen verschillende soorten inkoop, zoals goederen, diensten en onderaanneming. Waar vind je dit? Dit attribuut staat in de SAP S/4HANA-tabel EKPO, veld PSTYP. Voorbeelden 093 | |||
| Materiaalnummer MaterialNumber | De identificatiecode van het materiaal of product dat wordt ingekocht. | ||
| Beschrijving Het materiaalnummer is een unieke code die in SAP aan elk materiaalstamrecord wordt toegekend. De code wordt gebruikt voor alle transacties met dat materiaal, waaronder inkoop, voorraadbeheer en verkoop. Met een analyse per materiaalnummer of materiaalgroep kun je inkoop per productgroep bekijken. Zo zie je of de inkoop van bepaalde materialen minder efficiënt verloopt, langere doorlooptijden heeft of vaker tot retouren leidt. Die informatie helpt bij het beheer van productgroepen. Waarom dit belangrijk is Maakt analyse per productgroep mogelijk, zodat je procesproblemen of problemen met leveranciersprestaties voor specifieke producten of materialen kunt opsporen. Waar vind je dit? Dit attribuut staat in de SAP S/4HANA-tabel EKPO, veld MATNR. Voorbeelden RM100-100FG210SERV-CONSULT | |||
| Tijdige levering door leverancier SupplierOnTimeDelivery | Een berekende indicator die aangeeft of de goederenontvangst op of vóór de gevraagde leverdatum is geboekt. | ||
| Beschrijving Dit booleaanse attribuut wordt berekend door de timestamp van de activiteit 'Goederenontvangst geboekt' te vergelijken met de 'Gevraagde leverdatum'. Als de goederenontvangst op of vóór de gevraagde datum plaatsvindt, is de waarde 'true'. Dit attribuut ondersteunt de KPI 'Percentage tijdige leveringen door leveranciers'. Je kunt er eenvoudig tijdige en te late leveringen mee filteren. Dat is belangrijk voor dashboards over leveranciersprestaties en leveranciersbeoordelingen. Waarom dit belangrijk is Meet de betrouwbaarheid van leveranciers en vormt de basis voor de KPI voor tijdige leveringen. Zo kun je leveranciersprestaties goed beheren. Waar vind je dit? Berekend door de timestamp van de activiteit 'Goederenontvangst geboekt' te vergelijken met het attribuut 'RequestedDeliveryDate'. Voorbeelden truefalse | |||
| Vestiging Plant | De locatie waar goederen worden afgeleverd of diensten worden uitgevoerd. | ||
| Beschrijving In SAP is een vestiging een fysieke locatie waar goederen worden geproduceerd of opgeslagen, of waar diensten worden uitgevoerd. De vestiging speelt een belangrijke rol in logistiek en planning. Door procesanalyses per vestiging uit te splitsen, worden regionale of locatiespecifieke verschillen in het inkoopproces zichtbaar. Zo zie je of bepaalde vestigingen langere levertijden hebben of vaker goederen retour sturen. Dat kan wijzen op lokale problemen met logistiek of kwaliteitscontrole. Waarom dit belangrijk is Maakt analyse per locatie mogelijk en laat verschillen in procesprestaties tussen vestigingen, fabrieken en magazijnen zien. Waar vind je dit? Dit attribuut staat in de SAP S/4HANA-tabel EKPO, veld WERKS. Voorbeelden 10101710DE01 | |||
Activiteiten in het Purchase to Pay-proces voor inkooporders
| Activiteit | Beschrijving | ||
|---|---|---|---|
| Factuur ontvangen | Dit staat voor het invoeren van een leveranciersfactuur in SAP en het koppelen ervan aan de bijbehorende inkooporder. Dit is een expliciete financiële boeking die een boekhoudkundig document aanmaakt. | ||
| Waarom dit belangrijk is Dit is een belangrijk moment dat het inkoopproces verbindt met het crediteurenproces. Je kunt hiermee de tijd tussen goederenontvangst en factuurverwerking analyseren. Waar vind je dit? Een boekhoudkundig document wordt aangemaakt in tabel BKPF (kopgegevens); de regelitems staan in BSEG of in het universele journaal ACDOCA. Tabel RSEG koppelt het document aan de inkooporder. Vastleggen Documentinvoerdatum (CPUDT) uit de kopgegevenstabel BKPF van het boekhoudkundige document. Gebeurtenistype explicit | |||
| Goederenontvangst geboekt | Dit staat voor de fysieke ontvangst van goederen van de leverancier en de bijbehorende registratie in het systeem. Het is een expliciete transactie die de inkooporderhistorie bijwerkt. | ||
| Waarom dit belangrijk is Dit is een belangrijk moment: de levertijd van de leverancier eindigt en de interne controle van de factuur begint. Het is essentieel om leveringen op tijd te volgen. Waar vind je dit? Vastgelegd als materiaaldocument in tabellen MKPF (kopgegevens) en MSEG (items), en gekoppeld aan de inkooporder in historietabel EKBE met een specifiek bewegingstype, bijvoorbeeld 101. Vastleggen Boekingsdatum (BUDAT) uit de kopgegevens van het materiaaldocument (MKPF), gekoppeld via EKBE. Gebeurtenistype explicit | |||
| Inkoopaanvraag aangemaakt | Deze activiteit markeert de formele aanvraag van goederen of diensten en start het inkoopproces. De gebeurtenis wordt vastgelegd wanneer een gebruiker een nieuwe inkoopaanvraag opslaat, bijvoorbeeld met transactie ME51N. | ||
| Waarom dit belangrijk is Dit is voor veel inkooporderprocessen het belangrijkste startpunt. Door de tijd tussen deze gebeurtenis en het aanmaken van de inkooporder te analyseren, spoor je vertragingen op bij de inkoop en interne verwerking. Waar vind je dit? Vastgelegd in tabel EBAN (Purchase Requisition). De timestamp van het aanmaken is te vinden in de wijzigingshistorietabellen CDHDR en CDPOS voor het EBAN-object. Vastleggen Gebeurtenis vastgelegd bij het aanmaken van een document in tabel EBAN. Gebeurtenistype explicit | |||
| Inkoopaanvraag goedgekeurd | Dit staat voor de formele goedkeuring van een inkoopaanvraag door een manager of aangewezen goedkeurder. Meestal wordt dit afgeleid uit een statuswijziging in het aanvraagdocument. De aanvraag is dan klaar om te worden omgezet in een inkooporder. | ||
| Waarom dit belangrijk is Dit is een belangrijk moment om goedkeuringstijden te volgen en bottlenecks op te sporen. Vertragingen hebben direct invloed op hoe snel een inkooporder kan worden aangemaakt en naar een leverancier kan worden gestuurd. Waar vind je dit? Afgeleid uit de vrijgavestatusvelden in tabel EBAN, bijvoorbeeld FRGZU (vrijgave-indicator). De timestamp wordt bepaald aan de hand van wijzigingsdocumenten (CDHDR/CDPOS), waarin staat wanneer de definitieve vrijgavestatus is ingesteld. Vastleggen Afgeleid uit wijzigingslogs (CDHDR/CDPOS) voor de vrijgavestatusvelden in tabel EBAN. Gebeurtenistype inferred | |||
| Inkooporder aangemaakt | Dit markeert het aanmaken van het officiële inkooporderdocument, met of zonder verwijzing naar een inkoopaanvraag. De gebeurtenis wordt expliciet vastgelegd wanneer het inkooporderdocument voor het eerst in het systeem wordt opgeslagen. | ||
| Waarom dit belangrijk is Deze activiteit kan als alternatief startpunt voor het proces dienen, vooral bij analyses van ongeautoriseerde aankopen. Het is een belangrijke gebeurtenis om de totale verwerkingstijd van inkooporders te volgen. Waar vind je dit? Vastgelegd in de kopgegevenstabel EKKO voor inkooporders. De aanmaakdatum (AEDAT) en -tijd van het document staan rechtstreeks in deze tabel. Vastleggen Aanmaaktimestamp (AEDAT) in tabel EKKO voor het inkooporderdocument. Gebeurtenistype explicit | |||
| Inkooporder afgerond | Deze activiteit geeft aan dat een inkooporderitem logistiek gezien is afgesloten. Dit wordt afgeleid wanneer zowel de indicator ‘Levering voltooid’ als ‘Eindfactuur’ is ingesteld. | ||
| Waarom dit belangrijk is Dit is het eindpunt voor de analyse van de levenscyclus van een inkooporder. De tijd tot deze gebeurtenis geeft de totale doorlooptijd van het inkoopproces. Waar vind je dit? Afgeleid uit statusvlaggen in de tabel met inkooporderitems EKPO. De gebeurtenis vindt plaats wanneer zowel de indicator ‘Levering voltooid’ (ELIKZ) als ‘Eindfactuur’ (EREKZ) op waar staat. Vastleggen Afgeleid uit wijzigingslogs wanneer de EKPO-velden ELIKZ en EREKZ allebei als voltooid zijn gemarkeerd. Gebeurtenistype inferred | |||
| Inkooporder goedgekeurd | Dit betekent dat de inkooporder alle benodigde interne goedkeuringen heeft gekregen en naar de leverancier mag worden gestuurd. De gebeurtenis wordt afgeleid uit een statuswijziging in de vrijgavemethode van de inkooporder. | ||
| Waarom dit belangrijk is Dit is een belangrijk moment om de efficiëntie van goedkeuringen en herstelwerk na goedkeuring te meten. Analyse van de tijd tussen het aanmaken en goedkeuren van een inkooporder maakt interne vertragingen zichtbaar. Waar vind je dit? Afgeleid uit de vrijgave-indicator (FRGKE) in tabel EKKO. De timestamp wordt bepaald aan de hand van de wijzigingshistorie (CDHDR/CDPOS), waaruit blijkt wanneer dit veld de status ‘vrijgegeven’ kreeg. Vastleggen Afgeleid uit wijzigingslogs voor het veld van de vrijgave-indicator (FRGKE) in tabel EKKO. Gebeurtenistype inferred | |||
| Dienstbevestiging ingevoerd | Deze activiteit markeert de bevestiging dat een dienst uit een inkooporder is uitgevoerd. De gebeurtenis wordt expliciet vastgelegd bij het aanmaken van een service-entrysheet. | ||
| Waarom dit belangrijk is Bij inkoop van diensten is dit het equivalent van een goederenontvangst. Het is belangrijk om de levertijden van diensten te volgen en leveranciers op tijd te betalen. Waar vind je dit? Vastgelegd bij het aanmaken van een service-entrysheet. De data staat in tabellen ESSR (kopgegevens) en ESLL (regels). De aanmaakdatum dient als timestamp. Vastleggen Aanmaakdatum van het service-entrysheetdocument in tabel ESSR. Gebeurtenistype explicit | |||
| Factuur betaald | Dit markeert de definitieve afwikkeling van de leveranciersfactuur via een betalingsrun of handmatige betaling. Deze expliciete financiële transactie maakt een vereffeningsdocument aan. | ||
| Waarom dit belangrijk is Deze activiteit hoort technisch gezien bij het betalingsproces, maar geeft een volledig beeld van de inkoop-tot-betalingcyclus. Ze is belangrijk voor de analyse van betalingsvoorwaarden en prestaties. Waar vind je dit? De betaling wordt geregistreerd als vereffeningsdocument in BKPF/ACDOCA. De vereffeningsdatum (AUGDT) op de factuurregel in tabel BSEG of ACDOCA geeft de betalingsgebeurtenis aan. Vastleggen Vereffeningsdatum (AUGDT) van het factuurdocument, te vinden in BSEG of ACDOCA. Gebeurtenistype explicit | |||
| Goederen geretourneerd | Geeft aan dat eerder ontvangen goederen naar de leverancier zijn teruggestuurd, meestal vanwege kwaliteitsproblemen, schade of een verkeerde levering. Dit wordt vastgelegd als een expliciete tegenboeking van de goederenbeweging. | ||
| Waarom dit belangrijk is Deze activiteit maakt herstelwerk en mogelijke problemen met de leverancierskwaliteit of ordernauwkeurigheid zichtbaar. Veel retouren voor een bepaalde leverancier of materiaal wijzen op een probleem. Waar vind je dit? Vastgelegd als materiaaldocument met een specifiek retourbewegingstype, bijvoorbeeld 122. De gebeurtenis wordt geregistreerd in MKPF/MSEG en gekoppeld aan de inkooporder in historietabel EKBE. Vastleggen Boekingsdatum uit het materiaaldocument met een retourbewegingstype in EKBE. Gebeurtenistype explicit | |||
| Inkooporder gewijzigd | Deze activiteit geeft aan dat de inkooporder na het aanmaken is gewijzigd, bijvoorbeeld wat betreft hoeveelheid, prijs of leverdatum. De wijziging wordt expliciet vastgelegd in de wijzigingslogs van het systeem. | ||
| Waarom dit belangrijk is Door wijzigingen te volgen, vooral na goedkeuring, kun je inefficiënties, herstelwerk en mogelijke complianceproblemen opsporen. Veel wijzigingen kunnen wijzen op onvolledige initiële specificaties. Waar vind je dit? Vastgelegd in de wijzigingsdocumenttabellen CDHDR (kopgegevens) en CDPOS (items) voor inkooporderobjecten (EINKBELEG). Elke wijziging levert een gedetailleerde logregel op. Vastleggen Gebeurtenis vastgelegd bij wijzigingen aan belangrijke velden in tabellen EKKO of EKPO, geregistreerd in CDHDR/CDPOS. Gebeurtenistype explicit | |||
| Inkooporder naar leverancier verzonden | Dit is het moment waarop de inkooporder naar de leverancier wordt verstuurd, bijvoorbeeld via EDI, e-mail of op papier. Deze gebeurtenis wordt vaak vastgelegd in de logs voor uitvoerbeheer van het systeem. | ||
| Waarom dit belangrijk is Met deze activiteit begint de levertijd van de leverancier. Zo kun je de leveranciersprestaties meten vanaf het moment dat de leverancier de order ontvangt. Waar vind je dit? Vastgelegd in de uitvoerbeheertabel NAST, waarin berichten voor een inkoopdocument worden bijgehouden. Je kunt de datum en tijd van het relevante uitvoertype gebruiken, bijvoorbeeld EDI of e-mail. Vastleggen Timestamp van het eerste geslaagde uitvoerbericht voor de inkooporder in tabel NAST. Gebeurtenistype inferred | |||
| Inkooporder verwijderd | Dit staat voor het annuleren of logisch verwijderen van een inkooporderitem of het volledige document. Dit wordt vastgelegd wanneer een gebruiker een verwijderingsvlag op het document instelt. | ||
| Waarom dit belangrijk is Dit is een alternatief eindpunt van het proces en wijst op een mislukking of annulering. Door te analyseren waarom inkooporders worden verwijderd, kun je problemen met de vraagplanning of het vaststellen van behoeften opsporen. Waar vind je dit? Vastgelegd aan de hand van de verwijderingsindicator (LOEKZ) in de kopgegevens (EKKO) of items (EKPO) van de inkooporder. De timestamp wordt afgeleid uit de wijzigingsdocumenten (CDHDR/CDPOS). Vastleggen Timestamp uit wijzigingsdocumenten (CDHDR/CDPOS) wanneer de verwijderingsvlag (LOEKZ) wordt ingesteld. Gebeurtenistype explicit | |||
Extractiegidsen
Stappen
- Vereisten en toegang: Zorg dat je een gebruiker hebt met de juiste autorisaties om Core Data Services-weergaven (CDS-weergaven) in SAP S/4HANA op te vragen. Je kunt toegang krijgen via SAP HANA Studio, ABAP Development Tools (ADT) voor Eclipse of een externe data-extractietool die SQL-verbindingen met de SAP HANA-database ondersteunt.
- Gegevens voor de systeemverbinding achterhalen: Verzamel de benodigde verbindingsgegevens voor SAP S/4HANA, waaronder de host, het instantienummer en je aanmeldgegevens.
- Verbinding maken met de database: Maak met de SQL-client van je keuze verbinding met de SAP S/4HANA-database waarin de CDS-weergaven staan.
- De SQL-query voorbereiden: Kopieer de volledige SQL-query uit het querygedeelte van dit document naar je SQL-editor. De query haalt alle benodigde activiteiten en attributen op.
- Filterparameters instellen: Zoek de tijdelijke waarden in de query. Vervang _start_date en _end_date door de gewenste datums voor je analyse, bijvoorbeeld '20230101' en '20231231'. Pas het filter poh.CompanyCode aan zodat alleen de bedrijfscodes worden meegenomen die je wilt analyseren.
- De query uitvoeren: Voer de aangepaste SQL-query uit op de S/4HANA-database. Afhankelijk van de hoeveelheid data en de gekozen periode kan dit even duren.
- De eerste resultaten controleren: Controleer de uitvoer in je SQL-client zodra de query klaar is. Kijk of de verschillende activiteiten aanwezig zijn, of de timestamps correct zijn ingevuld en of de case-ID (PurchaseOrderNumber) consistent is.
- De data exporteren: Exporteer de volledige resultatenset vanuit je SQL-tool naar een CSV-bestand (Comma Separated Values). Gebruik UTF-8-codering om problemen met tekens te voorkomen.
- De upload voorbereiden: Open het CSV-bestand voordat je het naar ProcessMind uploadt en controleer of de kolomkoppen exact overeenkomen met de attributen in de datavereisten (PurchaseOrderNumber, ActivityName, EventTime enzovoort). Pas kolomnamen aan als je exporttool ze heeft gewijzigd.
- Uploaden naar ProcessMind: Upload het definitieve CSV-bestand naar je ProcessMind-project. Koppel tijdens het importeren de kolommen in het bestand aan de bijbehorende velden voor case-ID, activiteit en timestamp.
Configuratie
- Gebruikte CDS-weergaven: De extractielogica gebruikt een aantal standaard-CDS-weergaven met een duidelijke betekenis. De belangrijkste zijn:
- I_PurchaseOrderItemAPI01: Voor de belangrijkste gegevens van inkooporderregels.
- I_PurchaseRequisitionItemAPI01: Voor gegevens over inkoopaanvragen.
- I_MaterialDocumentItem: Voor goederenbewegingen, zoals ontvangsten en retouren.
- I_ServiceEntrySheetAPI01: Voor gebeurtenissen rond servicebevestigingen.
- I_SupplierInvoiceAPI01: Voor gegevens over leveranciersfacturen.
- I_OperationalAcctgDocItem: Om facturen te koppelen aan financiële documenten en betalingen te volgen.
- I_ChangeDocument: Om wijzigingen aan inkooporders vast te leggen.
- Filteren op datumbereik: Pas een datumbereikfilter toe om de prestaties en hoeveelheid data beheersbaar te houden. De query gebruikt de tijdelijke waarden _start_date en _end_date voor de aanmaakdatum van de inkooporder (PurchaseOrderDate). Een periode van 3 tot 6 maanden is een goed startpunt.
- Filteren op organisatie: Filter de query altijd op CompanyCode, zodat alleen relevante bedrijfseenheden worden meegenomen. Je kunt extra filters voor PurchaseOrderType of PurchasingOrganization toevoegen aan de algemene tabeluitdrukking PO_base om de selectie verder te verfijnen.
- Vereisten: De gebruiker die de query uitvoert, heeft SELECT-autorisatie nodig voor alle hierboven genoemde CDS-weergaven. Toegang tot deze weergaven wordt doorgaans verleend via specifieke bedrijfs- of analyticsrollen in S/4HANA. Zonder de juiste rechten mislukt de query.
Voorbeeldquery sql
WITH PO_base AS (
SELECT
poh.PurchaseOrder AS PurchaseOrderNumber,
poi.PurchaseOrderItem AS PurchaseOrderItem,
poh.CompanyCode,
poh.PurchaseOrderType AS DocumentType,
poh.Supplier AS VendorId,
poh.PurchaseOrderDate,
poi.PurchaseRequisition AS PurchaseRequisitionNumber,
poi.NetPriceAmount * poi.OrderQuantity AS TotalNetAmount, -- Note: This is item-level net amount
poh.CreationDate AS POCreationDate,
poh.CreationTime AS POCreationTime,
poh.LastChangeDateTime AS POLastChangeDateTime,
poi.IsDeleted,
poi.DeliveryIsCompleted,
poi.FinalInvoiceIsExpected,
poi.GoodsReceiptIsExpected,
poi.LastGoodsReceiptDate,
poi.LastInvoiceReceiptDate
FROM I_PurchaseOrderAPI01 poh
JOIN I_PurchaseOrderItemAPI01 poi
ON poh.PurchaseOrder = poi.PurchaseOrder
WHERE
poh.PurchaseOrderDate BETWEEN '_start_date' AND '_end_date' -- Placeholder: e.g., '20230101' and '20230630'
AND poh.CompanyCode IN ('[YourCompanyCode]') -- Placeholder: e.g., '1010'
)
-- 1. Purchase Requisition Created
SELECT
po.PurchaseOrderNumber,
'Purchase Requisition Created' AS ActivityName,
CAST(CONCAT(pr.CreationDate, 'T', pr.CreationTime) AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem, -- Placeholder
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
pr.CreatedByUser AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate, -- Available in PR, add if needed
po.DocumentType
FROM I_PurchaseRequisitionItemAPI01 pr
JOIN PO_base po
ON pr.PurchaseRequisition = po.PurchaseRequisitionNumber AND pr.PurchaseRequisitionItem = po.PurchaseOrderItem
UNION ALL
-- 2. Purchase Requisition Approved
SELECT
po.PurchaseOrderNumber,
'Purchase Requisition Approved' AS ActivityName,
CAST(CONCAT(pr.PurReqnReleaseDate, 'T', '000000') AS TIMESTAMP) AS EventTime, -- Time is not available in this view
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
NULL AS UserName, -- Approver info requires complex joins
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM I_PurchaseRequisitionItemAPI01 pr
JOIN PO_base po
ON pr.PurchaseRequisition = po.PurchaseRequisitionNumber AND pr.PurchaseRequisitionItem = po.PurchaseOrderItem
WHERE
pr.PurReqnReleaseDate IS NOT NULL
UNION ALL
-- 3. Purchase Order Created
SELECT
po.PurchaseOrderNumber,
'Purchase Order Created' AS ActivityName,
CAST(CONCAT(po.POCreationDate, 'T', po.POCreationTime) AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
poh.CreatedByUser AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
poi.RequestedDeliveryDate,
po.DocumentType
FROM PO_base po
JOIN I_PurchaseOrderAPI01 poh ON po.PurchaseOrderNumber = poh.PurchaseOrder
JOIN I_PurchaseOrderItemAPI01 poi ON po.PurchaseOrderNumber = poi.PurchaseOrder AND po.PurchaseOrderItem = poi.PurchaseOrderItem
UNION ALL
-- 4. Purchase Order Approved
SELECT DISTINCT
po.PurchaseOrderNumber,
'Purchase Order Approved' AS ActivityName,
CAST(poh.ReleaseDate AS TIMESTAMP) AS EventTime, -- Assuming ReleaseDate reflects final approval
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
NULL AS UserName, -- Approver info requires complex joins
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
poi.RequestedDeliveryDate,
po.DocumentType
FROM PO_base po
JOIN I_PurchaseOrderAPI01 poh ON po.PurchaseOrderNumber = poh.PurchaseOrder
JOIN I_PurchaseOrderItemAPI01 poi ON po.PurchaseOrderNumber = poi.PurchaseOrder AND po.PurchaseOrderItem = poi.PurchaseOrderItem
WHERE poh.ReleaseDate IS NOT NULL
UNION ALL
-- 5. Purchase Order Sent to Vendor
SELECT DISTINCT
po.PurchaseOrderNumber,
'Purchase Order Sent to Vendor' AS ActivityName,
CAST(poh.ReleaseDate AS TIMESTAMP) AS EventTime, -- Using ReleaseDate as a proxy for sending time
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
NULL AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
poi.RequestedDeliveryDate,
po.DocumentType
FROM PO_base po
JOIN I_PurchaseOrderAPI01 poh ON po.PurchaseOrderNumber = poh.PurchaseOrder
JOIN I_PurchaseOrderItemAPI01 poi ON po.PurchaseOrderNumber = poi.PurchaseOrder AND po.PurchaseOrderItem = poi.PurchaseOrderItem
WHERE poh.ReleaseDate IS NOT NULL
UNION ALL
-- 6. Purchase Order Changed
SELECT DISTINCT
ch.OBJECTID AS PurchaseOrderNumber,
'Purchase Order Changed' AS ActivityName,
CAST(CONCAT(ch.ChangeDocumentDate, 'T', ch.ChangeDocumentTime) AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
ch.UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM I_ChangeDocument ch
JOIN PO_base po ON ch.OBJECTID = po.PurchaseOrderNumber
WHERE
ch.ObjectClassName = 'EINKBELEG' -- Object Class for Purchase Documents
AND CAST(CONCAT(ch.ChangeDocumentDate, 'T', ch.ChangeDocumentTime) AS TIMESTAMP) > CAST(CONCAT(po.POCreationDate, 'T', po.POCreationTime) AS TIMESTAMP)
UNION ALL
-- 7. Goods Receipt Posted
SELECT
po.PurchaseOrderNumber,
'Goods Receipt Posted' AS ActivityName,
CAST(CONCAT(md.PostingDate, 'T', md.CreationTime) AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
md.CreatedByUser AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM I_MaterialDocumentItem md
JOIN PO_base po
ON md.PurchaseOrder = po.PurchaseOrderNumber AND md.PurchaseOrderItem = po.PurchaseOrderItem
WHERE
md.GoodsMovementType = '101'
UNION ALL
-- 8. Services Confirmation Entered
SELECT
po.PurchaseOrderNumber,
'Services Confirmation Entered' AS ActivityName,
CAST(se.PostingDate AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
se.CreatedByUser AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM I_ServiceEntrySheetAPI01 se
JOIN PO_base po
ON se.PurchaseOrder = po.PurchaseOrderNumber AND se.PurchaseOrderItem = po.PurchaseOrderItem
UNION ALL
-- 9. Goods Returned
SELECT
po.PurchaseOrderNumber,
'Goods Returned' AS ActivityName,
CAST(CONCAT(md.PostingDate, 'T', md.CreationTime) AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
md.CreatedByUser AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM I_MaterialDocumentItem md
JOIN PO_base po
ON md.PurchaseOrder = po.PurchaseOrderNumber AND md.PurchaseOrderItem = po.PurchaseOrderItem
WHERE
md.GoodsMovementType = '122'
UNION ALL
-- 10. Invoice Received
SELECT
po.PurchaseOrderNumber,
'Invoice Received' AS ActivityName,
CAST(inv.PostingDate AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
inv.CreatedByUser AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM I_SupplierInvoiceAPI01 inv
JOIN PO_base po
ON inv.PurchaseOrderReference = po.PurchaseOrderNumber
WHERE
inv.DebitCreditCode = 'H' -- 'H' for Credit (Supplier Invoice)
UNION ALL
-- 11. Invoice Paid
SELECT
po.PurchaseOrderNumber,
'Invoice Paid' AS ActivityName,
CAST(doc.ClearingDate AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
doc.CreatedByUser AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM I_SupplierInvoiceAPI01 inv
JOIN I_OperationalAcctgDocItem doc
ON inv.AccountingDocument = doc.AccountingDocument
JOIN PO_base po
ON inv.PurchaseOrderReference = po.PurchaseOrderNumber
WHERE
doc.IsCleared = 'X' AND doc.ClearingDate IS NOT NULL
UNION ALL
-- 12. Purchase Order Completed
SELECT
po.PurchaseOrderNumber,
'Purchase Order Completed' AS ActivityName,
CAST(GREATEST(po.LastGoodsReceiptDate, po.LastInvoiceReceiptDate) AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
'SYSTEM' AS UserName,
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM PO_base po
WHERE
po.DeliveryIsCompleted = 'X'
AND (po.FinalInvoiceIsExpected = 'X' OR po.GoodsReceiptIsExpected = '') -- Logic for completion
AND GREATEST(po.LastGoodsReceiptDate, po.LastInvoiceReceiptDate) IS NOT NULL
UNION ALL
-- 13. Purchase Order Deleted
SELECT
po.PurchaseOrderNumber,
'Purchase Order Deleted' AS ActivityName,
CAST(po.POLastChangeDateTime AS TIMESTAMP) AS EventTime,
'[Your S/4HANA System ID]' AS SourceSystem,
CURRENT_UTCTIMESTAMP AS LastDataUpdate,
po.VendorId,
NULL AS UserName, -- User who set the flag is in change docs
po.TotalNetAmount,
po.PurchaseRequisitionNumber,
NULL AS RequestedDeliveryDate,
po.DocumentType
FROM PO_base po
WHERE
po.IsDeleted = 'X' Stappen
- Controleer of je rechtstreeks via SQL toegang hebt tot het SAP HANA-schema met EKKO en EKPO en vraag de benodigde leesrechten aan. Vervang de tijdelijke waarden voor schema en verbinding door de waarden die voor je systeem zijn ingesteld.
- Stel de extractieperiode in met [Start timestamp] en [End timestamp]. Voor de eerste extractie wordt een periode van drie tot zes maanden aanbevolen. Gebruik alleen filters voor bedrijfscode en documenttype als die nodig zijn voor de rapportagescope.
- Haal de inkooporders op uit EKKO en EKPO. Neem het inkoopordernummer, de leverancier, het documenttype, de bedrijfscode, de aanmaakdatum en -tijd en de attributen op regelniveau mee. Tel de nettowaarden van EKPO op om TotalNetAmount op inkooporderniveau te berekenen.
- Haal gebeurtenissen rond het aanmaken en goedkeuren van inkoopaanvragen op uit EBAN. Gebruik het nummer van de inkoopaanvraag en de regelverwijzing in EKPO om aanvragen aan inkooporders te koppelen. Omdat goedkeuringsindicatoren en timestamps per releaseconfiguratie verschillen, stel je de expressies voor de goedkeuringsstatus en timestamp in op basis van de actieve SAP-releaseprocedure via [Configure based on your system].
- Haal gebeurtenissen op voor het aanmaken, goedkeuren, wijzigen, verwijderen en afronden van inkooporders. Gebruik voor het aanmaken de aanmaakdatum en -tijd uit EKKO. Voor goedkeuringen, wijzigingen en verwijderingen zijn bronnen met release- of wijzigingshistorie nodig. Stel de bijbehorende bronexpressies in met [Your table name] en [Your column name] als de relevante historie niet beschikbaar is in het gekozen schema.
- Haal gebeurtenissen op voor leverancierscommunicatie, goederenontvangst, servicebevestiging, retouren, factuurontvangst en factuurbetaling uit de toepasselijke bronnen voor uitvoer, materiaaldocumenten, serviceboekingen, facturen, boekhouding en aflettering. De query bevat expliciete tijdelijke waarden voor systeemspecifieke objecten, omdat EKKO en EKPO alleen deze bronnen niet afdekken.
- Zet alle brongebeurtenissen om naar dezelfde eventlogstructuur. Elke rij moet PurchaseOrderNumber, ActivityName, EventTime, SourceSystem, LastDataUpdate, VendorId, UserName, TotalNetAmount, PurchaseRequisitionNumber, RequestedDeliveryDate en DocumentType bevatten. Behoud meerdere voorkomens van een activiteit als de bron meerdere geldige gebeurtenissen bevat.
- Controleer de timestamps, verwijder alleen exacte dubbele bronrijen en leid geen activiteiten af waarvoor geen bronrecord bestaat. ProcessMind leest het event log zoals het is aangeleverd. Elke activiteit in de procesvisualisatie moet daarom als expliciete rij aanwezig zijn.
- Exporteer het resultaat als een bestand met scheidingstekens of als een resultatenset uit de database, met één kopregel en vaste kolomnamen. Gebruik een timestampnotatie die door de uploadinstellingen van ProcessMind wordt ondersteund, behandel PurchaseOrderNumber als tekst en upload het volledige event log via de ingestelde ProcessMind-dataverbinding.
Configuratie
- Bronobjecten: EKKO en EKPO zijn de bevestigde bronnen voor de kop- en regelgegevens van inkooporders. Stel aanvullende objecten voor aanvragen, vrijgavestatus, wijzigingshistorie, uitvoer, goederenbewegingen, serviceboekingen, facturen, betalingen en aflettering in op basis van de SAP S/4HANA-release en het actieve datamodel.
- Case-identificatie: Gebruik PurchaseOrderNumber als case-ID. Koppel gebeurtenissen op regelniveau aan het inkoopordernummer. Bewaar regelverwijzingen zo nodig in een extra kolom die specifiek is voor de bron.
- Datumbereik: Begin met drie tot zes maanden. Verwerk historische data in kleinere perioden en stem overlappende grenzen op elkaar af om hiaten te voorkomen.
- Filters: Stel filters in voor Company Code, Document Type, VendorId, inkooporganisatie, inkoopgroep en gebeurtenisdatum, afhankelijk van de gewenste scope. De filters voor bedrijfscode en documenttype moeten waarden gebruiken die geldig zijn in het doelsysteem.
- Betekenis van gebeurtenissen: Aanmaken en verwijderen kunnen expliciet worden vastgelegd als de relevante documentvelden of logs beschikbaar zijn. Goedkeuring en afronding zijn gebeurtenissen op basis van een status en vereisen ingestelde statustimestamps. Maak geen rijen aan op basis van alleen een huidige status als er geen betrouwbare gebeurtenistimestamp is.
- Prestaties: Filter vroeg op gebeurtenisdatum en organisatiescope. Tel EKPO waar mogelijk op voordat je de tabel koppelt aan gebeurtenisbronnen en verwerk grote historische extracties in perioden. Zorg voor passende databasestatistieken en vermijd onbeperkte joins tussen bronnen voor regels, boekhouding en wijzigingshistorie.
- Verversingstimestamp: Stel LastDataUpdate voor elke rij in een extractie in op het tijdstip waarop de extractie is uitgevoerd.
- Vereisten: Je hebt een verbinding met SAP HANA nodig, leesrechten voor alle ingestelde bronobjecten, toegang tot de relevante data voor inkoop, voorraadbeheer, diensteninkoop, factuurcontrole en crediteurenadministratie, en een ProcessMind-verbinding die het gekozen bestand of de resultatenset kan importeren.
- Systeemspecifieke instellingen: Vervang elke tijdelijke bronwaarde tussen vierkante haken in de query door een goedgekeurde tabel, weergave, kolom of expressie uit het doelsysteem SAP S/4HANA. Neem geen aanmeldgegevens op in de query of extractie-instellingen.
Voorbeeldquery sql
WITH
params AS (
SELECT
CAST('[Start timestamp]' AS TIMESTAMP) AS start_ts,
CAST('[End timestamp]' AS TIMESTAMP) AS end_ts,
CAST(CURRENT_TIMESTAMP AS TIMESTAMP) AS last_data_update,
CAST('[Source system]' AS NVARCHAR(100)) AS source_system
FROM DUMMY
),
po_base AS (
SELECT
h.MANDT,
h.EBELN AS PurchaseOrderNumber,
h.LIFNR AS VendorId,
h.BSART AS DocumentType,
h.BUKRS AS CompanyCode,
CAST(h.AEDAT AS DATE) AS POChangedDate,
CAST(h.AEDAT AS TIMESTAMP) AS POChangedTimestamp,
CAST(h.ERNAM AS NVARCHAR(100)) AS POCreatedBy,
CAST(h.BEDAT AS DATE) AS PODate,
CAST(h.EBELN AS NVARCHAR(20)) AS PurchaseOrderKey,
CAST(SUM(COALESCE(i.NETWR, 0)) AS DECIMAL(23, 2)) AS TotalNetAmount,
CAST(MIN(i.BEDNR) AS NVARCHAR(20)) AS PurchaseRequisitionNumber,
CAST(MIN(i.EINDT) AS DATE) AS RequestedDeliveryDate
FROM EKKO h
INNER JOIN EKPO i
ON i.MANDT = h.MANDT
AND i.EBELN = h.EBELN
WHERE h.AEDAT >= (SELECT start_ts FROM params)
AND h.AEDAT < (SELECT end_ts FROM params)
AND h.BUKRS IN ([Company Code filter])
AND h.BSART IN ([Document Type filter])
GROUP BY
h.MANDT,
h.EBELN,
h.LIFNR,
h.BSART,
h.BUKRS,
h.AEDAT,
h.ERNAM,
h.BEDAT
),
po_items AS (
SELECT
i.MANDT,
i.EBELN AS PurchaseOrderNumber,
i.EBELP,
i.BANFN AS PurchaseRequisitionNumber,
i.BEDNR,
i.EINDT AS RequestedDeliveryDate
FROM EKPO i
),
events AS (
SELECT
p.PurchaseOrderNumber,
'Purchase Requisition Created' AS ActivityName,
CAST(r.[Purchase requisition creation timestamp] AS TIMESTAMP) AS EventTime,
s.source_system AS SourceSystem,
s.last_data_update AS LastDataUpdate,
p.VendorId,
CAST(r.[Purchase requisition created by] AS NVARCHAR(100)) AS UserName,
p.TotalNetAmount,
CAST(r.[Purchase requisition number] AS NVARCHAR(20)) AS PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your requisition source table or view] r
ON r.[Client] = p.MANDT
AND r.[Purchase requisition number] = p.PurchaseRequisitionNumber
CROSS JOIN params s
WHERE r.[Purchase requisition creation timestamp] >= s.start_ts
AND r.[Purchase requisition creation timestamp] < s.end_ts
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Purchase Requisition Approved' AS ActivityName,
CAST(r.[Purchase requisition approval timestamp] AS TIMESTAMP) AS EventTime,
s.source_system,
s.last_data_update,
p.VendorId,
CAST(r.[Purchase requisition approver] AS NVARCHAR(100)),
p.TotalNetAmount,
CAST(r.[Purchase requisition number] AS NVARCHAR(20)),
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your requisition approval history table or view] r
ON r.[Client] = p.MANDT
AND r.[Purchase requisition number] = p.PurchaseRequisitionNumber
CROSS JOIN params s
WHERE r.[Purchase requisition approval timestamp] >= s.start_ts
AND r.[Purchase requisition approval timestamp] < s.end_ts
AND r.[Approval status] = '[Approved status value]'
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Purchase Order Created',
CAST(p.PODate AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
p.POCreatedBy,
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
CROSS JOIN params s
WHERE p.PODate >= CAST(s.start_ts AS DATE)
AND p.PODate < CAST(s.end_ts AS DATE)
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Purchase Order Approved',
CAST(a.[Purchase order approval timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(a.[Approver] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your purchase order release history table or view] a
ON a.[Client] = p.MANDT
AND a.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE a.[Purchase order approval timestamp] >= s.start_ts
AND a.[Purchase order approval timestamp] < s.end_ts
AND a.[Release status] = '[Approved release status value]'
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Purchase Order Sent to Vendor',
CAST(o.[Output timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(o.[Output user] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your purchase order output source table or view] o
ON o.[Client] = p.MANDT
AND o.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE o.[Output timestamp] >= s.start_ts
AND o.[Output timestamp] < s.end_ts
AND o.[Output status] = '[Successfully processed output status]'
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Purchase Order Changed',
CAST(c.[Change timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(c.[Changed by] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your purchase order change history table or view] c
ON c.[Client] = p.MANDT
AND c.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE c.[Change timestamp] >= s.start_ts
AND c.[Change timestamp] < s.end_ts
AND c.[Change indicator] = '[Changed indicator value]'
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Goods Receipt Posted',
CAST(g.[Goods movement timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(g.[Posted by] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your goods movement source table or view] g
ON g.[Client] = p.MANDT
AND g.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE g.[Goods movement timestamp] >= s.start_ts
AND g.[Goods movement timestamp] < s.end_ts
AND g.[Movement type] IN ([Goods receipt movement types])
AND g.[Reversal indicator] IS NULL
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Services Confirmation Entered',
CAST(v.[Service entry timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(v.[Entered by] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your service entry sheet source table or view] v
ON v.[Client] = p.MANDT
AND v.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE v.[Service entry timestamp] >= s.start_ts
AND v.[Service entry timestamp] < s.end_ts
AND v.[Service entry status] = '[Accepted service entry status]'
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Goods Returned',
CAST(g.[Goods movement timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(g.[Posted by] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your goods movement source table or view] g
ON g.[Client] = p.MANDT
AND g.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE g.[Goods movement timestamp] >= s.start_ts
AND g.[Goods movement timestamp] < s.end_ts
AND g.[Movement type] IN ([Goods return movement types])
AND g.[Reversal indicator] IS NULL
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Invoice Received',
CAST(i.[Invoice posting timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(i.[Posted by] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your supplier invoice source table or view] i
ON i.[Client] = p.MANDT
AND i.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE i.[Invoice posting timestamp] >= s.start_ts
AND i.[Invoice posting timestamp] < s.end_ts
AND i.[Invoice status] = '[Posted invoice status]'
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Invoice Paid',
CAST(i.[Clearing timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(i.[Cleared by] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your supplier invoice clearing source table or view] i
ON i.[Client] = p.MANDT
AND i.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE i.[Clearing timestamp] >= s.start_ts
AND i.[Clearing timestamp] < s.end_ts
AND i.[Clearing status] = '[Cleared status value]'
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Purchase Order Completed',
CAST(x.[Completion timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(x.[Completion user] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your purchase order item status source table or view] x
ON x.[Client] = p.MANDT
AND x.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE x.[Completion timestamp] >= s.start_ts
AND x.[Completion timestamp] < s.end_ts
AND x.[Delivery completed indicator] = '[Set indicator value]'
AND x.[Final invoice indicator] = '[Set indicator value]'
UNION ALL
SELECT
p.PurchaseOrderNumber,
'Purchase Order Deleted',
CAST(d.[Deletion timestamp] AS TIMESTAMP),
s.source_system,
s.last_data_update,
p.VendorId,
CAST(d.[Deleted by] AS NVARCHAR(100)),
p.TotalNetAmount,
p.PurchaseRequisitionNumber,
p.RequestedDeliveryDate,
p.DocumentType
FROM po_base p
INNER JOIN [Your purchase order deletion history table or view] d
ON d.[Client] = p.MANDT
AND d.[Purchase order number] = p.PurchaseOrderNumber
CROSS JOIN params s
WHERE d.[Deletion timestamp] >= s.start_ts
AND d.[Deletion timestamp] < s.end_ts
AND d.[Deletion indicator] = '[Set deletion indicator value]'
)
SELECT
PurchaseOrderNumber,
ActivityName,
EventTime,
SourceSystem,
LastDataUpdate,
VendorId,
UserName,
TotalNetAmount,
PurchaseRequisitionNumber,
RequestedDeliveryDate,
DocumentType
FROM events
WHERE PurchaseOrderNumber IS NOT NULL
AND ActivityName IS NOT NULL
AND EventTime IS NOT NULL
ORDER BY PurchaseOrderNumber, EventTime, ActivityName; Stappen
- Specificatie en ontwerp: Bepaal de definitieve structuur van het eventlogbestand, met alle verplichte en aanbevolen attributen. Leg vast welke SAP-tabellen (bijvoorbeeld EKKO, EKPO, EKBE, CDHDR en CDPOS) als bron dienen voor elk van de 13 verplichte activiteiten.
- Programma maken: Ga in SAP GUI naar de ABAP-editor via transactiecode SE38 of SE80. Maak een nieuw uitvoerbaar programma, bijvoorbeeld Z_PM_PO_EXTRACT.
- Selectiescherm definiëren: Programmeer het selectiescherm voor het rapport. Hiermee kunnen gebruikers de data filteren die ze willen extraheren. Voeg parameters toe voor het datumbereik van de aanmaakdatum van de inkooporder (P_AEDAT), de bedrijfscode (P_BUKRS) en het inkoopdocumenttype (P_BSART).
- Datadeclaraties: Definieer de interne tabellen en datastructuren die het programma nodig heeft. Maak ook een interne tabel voor het definitieve event log, met de structuur die in de specificatie is vastgelegd.
- Selectielogica implementeren: Schrijf de ABAP-logica om data voor elk van de 13 activiteiten te selecteren. Hiervoor gebruik je SELECT-statements op de relevante SAP-tabellen, met joins waar nodig. Lees voor gebeurtenissen op basis van wijzigingen de wijzigingslogtabellen CDHDR en CDPOS uit.
- Data omzetten en koppelen: Koppel voor elk opgehaald record de SAP-tabelvelden aan de bijbehorende kolommen in de interne tabel voor het definitieve event log. Stel ActivityName in op basis van de gebeurtenis, bijvoorbeeld 'Purchase Order Created'. Zet datum- en tijdvelden om naar een vaste timestampnotatie voor EventTime.
- Gebeurtenisdata samenvoegen: Zorg dat de data van alle 13 activiteitstypen na verwerking in één interne tabel staat. Deze tabel bevat nu het volledige event log voor de geselecteerde inkooporders.
- Bestandsuitvoer instellen: Voeg functionaliteit toe om de definitieve interne tabel naar een bestand te schrijven. Gebruik bij voorkeur de methode cl_gui_frontend_services=>gui_download, zodat gebruikers het bestand lokaal als CSV kunnen opslaan. Je kunt ook OPEN DATASET gebruiken om het bestand voor achtergrondverwerking op de SAP-applicatieserver op te slaan.
- Transactiecode maken (optioneel): Maak het programma eenvoudig toegankelijk voor zakelijke gebruikers door via transactiecode SE93 een aangepaste transactiecode te maken, bijvoorbeeld ZPM_PO_EXTRACT, die het ABAP-programma uitvoert.
- Achtergrondtaak plannen: Gebruik voor grote hoeveelheden data of geautomatiseerde extracties transactiecode SM36 om het programma als achtergrondtaak in te plannen. Het uitvoerbestand wordt opgeslagen op het pad op de applicatieserver dat in de programmalogica is opgegeven.
Configuratie
- Selectiecriteria: Het programma moet selectieparameters bevatten om de data gericht te filteren. De belangrijkste filters zijn:
- Datumbereik: Een verplicht datumbereik voor de aanmaakdatum van de inkooporder (EKKO-AEDAT). Begin bij voorkeur met een periode van 3 tot 6 maanden om de hoeveelheid data en de rapportprestaties beheersbaar te houden.
- Bedrijfscode (BUKRS): Essentieel voor organisaties met meerdere juridische entiteiten, zodat de extractie beperkt blijft tot de juiste scope.
- Inkoopdocumenttype (BSART): Hiermee filter je op specifieke typen inkooporders, zoals een standaardinkooporder, raamorder of voorraadtransportorder.
- Wijzigingslog uitlezen: Voor het extraheren van activiteiten zoals 'Purchase Order Approved' of 'Purchase Order Changed' moeten de SAP-wijzigingslogtabellen (CDHDR, CDPOS) worden uitgelezen. Dit kan veel systeembronnen vragen. Optimaliseer de ABAP-logica door alleen de benodigde objectklassen (EINKBELEG, BANF) en combinaties van tabellen en velden te selecteren.
- Autorisaties: De gebruiker of technische account waarmee het rapport wordt uitgevoerd, heeft uitgebreide leesrechten nodig voor tabellen uit meerdere SAP-modules, waaronder Materials Management (MM), Financial Accounting (FI) en systeembrede tabellen. Dit geldt onder meer voor EKKO, EKPO, EBAN, EKBE, BKPF, BSAK, RBKP, NAST, CDHDR en CDPOS.
- Uitvoering op de achtergrond: Voer extracties van meer dan enkele maanden aan data, of extracties op een systeem met veel transacties, altijd op de achtergrond uit. Zo voorkom je dat de dialoogprocessen een time-out krijgen.
Voorbeeldquery abap
REPORT z_pm_po_extract.
" ====================================================================
" SELECTION SCREEN
" ====================================================================
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
SELECT-OPTIONS: s_aedat FOR sy-datum OBLIGATORY.
SELECT-OPTIONS: s_bukrs FOR ekko-bukrs.
SELECT-OPTIONS: s_bsart FOR ekko-bsart.
PARAMETERS: p_sysid TYPE string DEFAULT '[Your SAP System ID]'.
SELECTION-SCREEN END OF BLOCK b1.
" ====================================================================
" DATA DECLARATIONS
" ====================================================================
TYPES: BEGIN OF ty_event_log,
purchaseordernumber TYPE ebeln,
activityname TYPE string,
eventtime TYPE timestamp,
sourcesystem TYPE string,
lastdataupdate TYPE timestamp,
vendorid TYPE lifnr,
username TYPE ernam,
totalnetamount TYPE netwr,
purchaserequisitionnumber TYPE banfn,
requesteddeliverydate TYPE eedat,
documenttype TYPE bsart,
END OF ty_event_log.
DATA: lt_event_log TYPE TABLE OF ty_event_log,
ls_event_log TYPE ty_event_log.
DATA: lt_ekko TYPE TABLE OF ekko,
lt_ekpo TYPE TABLE OF ekpo.
" ====================================================================
" START OF SELECTION
" ====================================================================
START-OF-SELECTION.
" Get current timestamp for LastDataUpdate
GET TIME STAMP FIELD ls_event_log-lastdataupdate.
ls_event_log-sourcesystem = p_sysid.
" --- Initial Data Selection: Purchase Orders in Scope ---
SELECT * FROM ekko INTO TABLE lt_ekko
WHERE aedat IN s_aedat
AND bukrs IN s_bukrs
AND bsart IN s_bsart.
IF lt_ekko IS INITIAL.
MESSAGE 'No Purchase Orders found for the given criteria.' TYPE 'S' DISPLAY LIKE 'E'.
RETURN.
ENDIF.
SELECT * FROM ekpo INTO TABLE lt_ekpo
FOR ALL ENTRIES IN lt_ekko
WHERE ebeln = lt_ekko-ebeln.
" --- 1. Purchase Requisition Created ---
SELECT ban.banfn, ban.erdat, ban.erzet, ban.ernam,
ekpo.ebeln, ekpo.netwr, ekpo.eindt, ekpo.bsart, ekpo.lifnr, ekko.bukrs
FROM eban AS ban
INNER JOIN ekpo AS ekpo ON ban.banfn = ekpo.banfn AND ban.bnfpo = ekpo.bnfpo
INNER JOIN ekko AS ekko ON ekpo.ebeln = ekko.ebeln
WHERE ekko.ebeln IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
INTO TABLE @DATA(lt_pr_created).
LOOP AT lt_pr_created INTO DATA(ls_pr_created).
ls_event_log-purchaseordernumber = ls_pr_created-ebeln.
ls_event_log-activityname = 'Purchase Requisition Created'.
CONVERT DATE ls_pr_created-erdat TIME ls_pr_created-erzet INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-vendorid = ls_pr_created-lifnr.
ls_event_log-username = ls_pr_created-ernam.
ls_event_log-totalnetamount = ls_pr_created-netwr.
ls_event_log-purchaserequisitionnumber = ls_pr_created-banfn.
ls_event_log-requesteddeliverydate = ls_pr_created-eindt.
ls_event_log-documenttype = ls_pr_created-bsart.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 2. Purchase Requisition Approved (via Change Docs on Release Indicator) ---
SELECT h.objectid, h.udate, h.utime, h.username
FROM cdhdr AS h
INNER JOIN cdpos AS p ON h.objectclas = p.objectclas AND h.objectid = p.objectid AND h.changenr = p.changenr
INNER JOIN ekpo AS ekpo ON h.objectid = ekpo.banfn
INNER JOIN ekko AS ekko ON ekpo.ebeln = ekko.ebeln
WHERE h.objectclas = 'BANF'
AND p.tabname = 'EBAN'
AND p.fname = 'FRGZU'
AND p.value_new = 'X' "Configure based on your system release indicator for 'Approved'
AND ekko.ebeln IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
INTO TABLE @DATA(lt_pr_approved).
LOOP AT lt_pr_approved INTO DATA(ls_pr_approved).
SELECT SINGLE ebeln FROM ekpo INTO ls_event_log-purchaseordernumber WHERE banfn = ls_pr_approved-objectid.
ls_event_log-activityname = 'Purchase Requisition Approved'.
CONVERT DATE ls_pr_approved-udate TIME ls_pr_approved-utime INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_pr_approved-username.
" Other attributes can be populated with another SELECT if needed.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 3. Purchase Order Created ---
LOOP AT lt_ekko INTO DATA(ls_ekko_created).
ls_event_log-purchaseordernumber = ls_ekko_created-ebeln.
ls_event_log-activityname = 'Purchase Order Created'.
CONVERT DATE ls_ekko_created-aedat TIME ls_ekko_created-erzet INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-vendorid = ls_ekko_created-lifnr.
ls_event_log-username = ls_ekko_created-ernam.
ls_event_log-totalnetamount = ls_ekko_created-rlwrt.
ls_event_log-purchaserequisitionnumber = ''. "Can be enriched later if needed
ls_event_log-requesteddeliverydate = ''. "Can be enriched from EKPO
ls_event_log-documenttype = ls_ekko_created-bsart.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 4. Purchase Order Approved (via Change Docs on Release Indicator) ---
SELECT h.objectid, h.udate, h.utime, h.username
FROM cdhdr AS h
INNER JOIN cdpos AS p ON h.objectclas = p.objectclas AND h.objectid = p.objectid AND h.changenr = p.changenr
WHERE h.objectclas = 'EINKBELEG'
AND p.tabname = 'EKKO'
AND p.fname = 'FRGKE'
AND p.value_new = 'R' "R for Released
AND h.objectid IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
INTO TABLE @DATA(lt_po_approved).
LOOP AT lt_po_approved INTO DATA(ls_po_approved).
ls_event_log-purchaseordernumber = ls_po_approved-objectid.
ls_event_log-activityname = 'Purchase Order Approved'.
CONVERT DATE ls_po_approved-udate TIME ls_po_approved-utime INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_po_approved-username.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 5. Purchase Order Sent to Vendor ---
SELECT n.objky, n.vstat, n.datvr, n.uhrvr, e.ernam
FROM nast AS n
INNER JOIN ekko AS e ON n.objky = e.ebeln
WHERE n.kappl = 'EF' "Application for Purchasing
AND n.kschl = '[Your PO Output Type]' "e.g. NEU
AND n.vstat = '1' "Successfully processed
AND n.objky IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
INTO TABLE @DATA(lt_po_sent).
LOOP AT lt_po_sent INTO DATA(ls_po_sent).
ls_event_log-purchaseordernumber = ls_po_sent-objky.
ls_event_log-activityname = 'Purchase Order Sent to Vendor'.
CONVERT DATE ls_po_sent-datvr TIME ls_po_sent-uhrvr INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_po_sent-ernam.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 6. Purchase Order Changed ---
SELECT objectid, udate, utime, username FROM cdhdr
WHERE objectclas = 'EINKBELEG'
AND tcode IN ('ME22', 'ME22N')
AND objectid IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
INTO TABLE @DATA(lt_po_changed).
LOOP AT lt_po_changed INTO DATA(ls_po_changed).
ls_event_log-purchaseordernumber = ls_po_changed-objectid.
ls_event_log-activityname = 'Purchase Order Changed'.
CONVERT DATE ls_po_changed-udate TIME ls_po_changed-utime INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_po_changed-username.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 7. Goods Receipt Posted & 9. Goods Returned ---
SELECT e.ebeln, m.budat, m.cpudt, m.cputm, m.usnam, b.shkzg, b.bwart
FROM mkpf AS m
INNER JOIN mseg AS s ON m.mblnr = s.mblnr AND m.mjahr = s.mjahr
INNER JOIN t156 AS t ON s.bwart = t.bwart
INNER JOIN ekbe AS e ON s.ebeln = e.ebeln AND s.ebelp = e.ebelp AND s.mblnr = e.belnr AND s.mjahr = e.gjahr
WHERE e.ebeln IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
AND e.bwart IN ('101', '102', '122', '123') "GR, GR Reversal, Return
INTO TABLE @DATA(lt_goods_mvmt).
LOOP AT lt_goods_mvmt INTO DATA(ls_goods_mvmt).
ls_event_log-purchaseordernumber = ls_goods_mvmt-ebeln.
IF ls_goods_mvmt-bwart = '101'.
ls_event_log-activityname = 'Goods Receipt Posted'.
ELSE.
ls_event_log-activityname = 'Goods Returned'.
ENDIF.
CONVERT DATE ls_goods_mvmt-cpudt TIME ls_goods_mvmt-cputm INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_goods_mvmt-usnam.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 8. Services Confirmation Entered ---
SELECT h.erdat, h.erzeit, h.ernam, l.ebeln
FROM essr AS h
INNER JOIN esll AS l ON h.lblni = l.lblni
WHERE l.ebeln IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
INTO TABLE @DATA(lt_services).
LOOP AT lt_services INTO DATA(ls_services).
ls_event_log-purchaseordernumber = ls_services-ebeln.
ls_event_log-activityname = 'Services Confirmation Entered'.
CONVERT DATE ls_services-erdat TIME ls_services-erzeit INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_services-ernam.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 10. Invoice Received ---
SELECT r.ebeln, r.cpudt, r.cputm, r.usnam
FROM rbkp AS r
WHERE r.ebeln IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
INTO TABLE @DATA(lt_invoice_rcvd).
LOOP AT lt_invoice_rcvd INTO DATA(ls_invoice_rcvd).
ls_event_log-purchaseordernumber = ls_invoice_rcvd-ebeln.
ls_event_log-activityname = 'Invoice Received'.
CONVERT DATE ls_invoice_rcvd-cpudt TIME ls_invoice_rcvd-cputm INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_invoice_rcvd-usnam.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 11. Invoice Paid ---
SELECT b.ebeln, s.augdt, s.augbl, b.usnam
FROM rbkp AS b
INNER JOIN bseg AS e ON b.belnr = e.belnr AND b.gjahr = e.gjahr
INNER JOIN bsak AS s ON e.bukrs = s.bukrs AND e.belnr = s.belnr AND e.gjahr = s.gjahr AND e.buzei = s.buzei
WHERE b.ebeln IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
AND s.augdt IS NOT NULL
INTO TABLE @DATA(lt_invoice_paid).
LOOP AT lt_invoice_paid INTO DATA(ls_invoice_paid).
ls_event_log-purchaseordernumber = ls_invoice_paid-ebeln.
ls_event_log-activityname = 'Invoice Paid'.
CONVERT DATE ls_invoice_paid-augdt INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_invoice_paid-usnam.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- 12. Purchase Order Completed & 13. Purchase Order Deleted (via Change Docs) ---
SELECT h.objectid, h.udate, h.utime, h.username, p.fname
FROM cdhdr AS h
INNER JOIN cdpos AS p ON h.changenr = p.changenr
INNER JOIN ekpo AS ekpo ON h.objectid = |{ ekpo.ebeln }{ ekpo.ebelp }|
WHERE h.objectclas = 'EINKBELEG'
AND p.tabname = 'EKPO'
AND p.fname IN ('ELIKZ', 'EREKZ', 'LOEKZ')
AND p.value_new = 'X'
AND ekpo.ebeln IN @( VALUE #( FOR ls_ekko IN lt_ekko ( ls_ekko-ebeln ) ) )
INTO TABLE @DATA(lt_po_status_change).
LOOP AT lt_po_status_change INTO DATA(ls_po_status_change).
ls_event_log-purchaseordernumber = substring( val = ls_po_status_change-objectid, off = 0, len = 10 ).
CASE ls_po_status_change-fname.
WHEN 'LOEKZ'.
ls_event_log-activityname = 'Purchase Order Deleted'.
WHEN 'ELIKZ' OR 'EREKZ'.
"This logic may need refinement to check if both are now set.
ls_event_log-activityname = 'Purchase Order Completed'.
ENDCASE.
CONVERT DATE ls_po_status_change-udate TIME ls_po_status_change-utime INTO TIME STAMP ls_event_log-eventtime TIME ZONE sy-zonlo.
ls_event_log-username = ls_po_status_change-username.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
" --- Final Output to CSV ---
CALL METHOD cl_gui_frontend_services=>gui_download
EXPORTING
filename = 'C:\temp\po_event_log.csv'
filetype = 'ASC'
CHANGING
data_tab = lt_event_log. Klaar om aan de slag te gaan?
Deze template biedt een goede basis voor process mining. Gebruik je SAP S/4HANA-data om verbeterkansen te vinden en het Purchase to Pay-proces vandaag nog te verbeteren.
Verbeter het P2P-proces voor inkooporders en verkort de doorlooptijd
Verwijder inefficiënties en verkort de doorlooptijd van inkooporders in het P2P-proces met 30%.
Geen creditcard nodig. Binnen enkele minuten ingesteld.