Jouw datatemplate voor het Purchase to Pay-proces voor inkooporders
Jouw 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
Purchase to Pay - Purchase Order-attributen
| Naam | Beschrijving | ||
|---|---|---|---|
| Activiteit ActivityName | De naam van de bedrijfsgebeurtenis of stap die in het Purchase Order-proces heeft plaatsgevonden. | ||
| Beschrijving Dit attribuut beschrijft een specifieke actie of statuswijziging binnen de lifecycle van de Purchase Order, zoals 'Purchase Order Created', 'Purchase Order Approved' of 'Goods Receipt Posted'. De volgorde van deze activiteiten vormt de procesflow. Het analyseren van de volgorde en frequentie van activiteiten vormt de kern van process mining. Hiermee ontdek je het werkelijke proces, vergelijk je dit met het ontworpen model, identificeer je knelpunten, zoals lange wachttijden na 'Invoice Received', en meet je herstelwerk, bijvoorbeeld door herhaalde activiteiten 'Purchase Order Changed'. Waarom dit belangrijk is Het definieert de stappen in het proces en maakt visualisatie en analyse van de end-to-end-flow, procesvarianten en knelpunten mogelijk. Waar je het vindt Meestal afgeleid uit een combinatie van tabellen en velden, zoals statusvelden in EKKO/EKPO of wijzigingsdocumentlogs in CDHDR/CDPOS, om belangrijke bedrijfsmeetpunten weer te geven. Voorbeelden Purchase Order aangemaaktPurchase Order goedgekeurdGoederenontvangst geboektFactuur ontvangen | |||
| Inkooporder PurchaseOrderNumber | De unieke identificatie van de Purchase Order (PO), die dient als primaire case-ID voor het volgen van de inkooplifecycle. | ||
| Beschrijving Het Purchase Order-nummer is de centrale identificatie die alle gerelateerde activiteiten koppelt, van het eerste aanmaken tot de uiteindelijke goederenontvangst en voltooiing. Het dient als case-ID voor process mining-analyses. Door gebeurtenissen in de analyse op dit nummer te groeperen, kun je de reis van elke afzonderlijke PO reconstrueren. Dat is nodig om doorlooptijden te berekenen, procesvarianten te analyseren en knelpunten of afwijkingen voor één order te identificeren. Waarom dit belangrijk is Dit is de essentiële sleutel om alle inkoopgebeurtenissen tot één end-to-end-proces te verbinden en de lifecycle van elke Purchase Order gedetailleerd te analyseren. Waar je het vindt Dit attribuut staat in SAP S/4HANA-tabel EKKO, veld EBELN. Voorbeelden 450001712345000171244500017125 | |||
| Tijdstip van gebeurtenis EventTime | De timestamp die aangeeft wanneer de activiteit heeft plaatsgevonden. | ||
| Beschrijving Dit attribuut registreert de exacte datum en tijd van elke activiteit in het proces. Het vormt de basis voor alle tijdgebaseerde analyses in process mining. Event Time wordt gebruikt om activiteiten chronologisch te ordenen en de procesflow op te bouwen. Daarnaast vormt het de basis voor het berekenen van alle duurmetingen, zoals doorlooptijden tussen activiteiten, wachttijden en verwerkingstijden. Die zijn belangrijk voor prestatieanalyses en het identificeren van knelpunten. Waarom dit belangrijk is Deze timestamp is belangrijk om gebeurtenissen correct te ordenen en alle prestatiemaatstaven te berekenen, waaronder doorlooptijden, levertijden en wachttijden. Waar je het vindt Timestampvelden die aan specifieke activiteiten zijn gekoppeld, zoals Creation Date (EKKO-AEDAT voor wijzigingen) of Posting Date (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 | Identificeert het bronsysteem waaruit de data is geëxtraheerd. | ||
| Beschrijving Dit attribuut geeft het systeem van herkomst van de eventdata aan, bijvoorbeeld 'SAP S/4HANA Production' of 'SAP ECC'. In omgevingen met meerdere systemen is dit veld belangrijk voor dataherkomst, probleemoplossing en een juiste interpretatie van data uit verschillende bronnen. Het helpt de context van de data te begrijpen en kan worden gebruikt om analyses op specifieke systeemomgevingen te filteren. Waarom dit belangrijk is Geeft essentiële context over de herkomst van de data. Dat is belangrijk voor datagovernance, validatie en analyse in omgevingen met meerdere systemen. Waar je het vindt Dit is meestal een statische waarde die tijdens het ETL-proces wordt toegevoegd om de herkomst van de dataset te markeren. 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 van de meest recente data-extractie uit SAP S/4HANA. Als je weet wanneer de data voor het laatst is bijgewerkt, kun je de actualiteit van je analyse beter beoordelen. Je ziet dan of je realtime-informatie bekijkt of een momentopname uit een specifiek tijdstip. Dat bepaalt mede hoe relevant acties op basis van de analyse zijn. Waarom dit belangrijk is Informeert gebruikers over de actualiteit van de data, zodat ze de context en relevantie van hun analytische bevindingen goed kunnen beoordelen. Waar je het vindt Dit is een metadata-timestamp die tijdens het ETL-proces wordt toegevoegd. Voorbeelden 2024-05-21T02:00:00Z2024-05-20T02:00:00Z2024-05-19T02:00:00Z | |||
| Aangevraagde leverdatum RequestedDeliveryDate | De datum waarop het bedrijf de leverancier heeft gevraagd de goederen of diensten te leveren. | ||
| Beschrijving Dit attribuut geeft de gewenste leverdatum uit de Purchase Order aan. Het is de basis voor het meten van leveranciersprestaties. In process mining vergelijk je deze datum met de werkelijke datum van goederenontvangst, de timestamp van 'Goods Receipt Posted', om de KPI 'Supplier On-Time Delivery Rate' te berekenen. Door afwijkingen van deze datum te analyseren, beoordeel je de betrouwbaarheid van leveranciers en beheers je risico's in de toeleveringsketen. Waarom dit belangrijk is Vormt de basis voor het meten van tijdige levering door leveranciers, een belangrijke KPI voor beheer van de toeleveringsketen en operationele planning. Waar je het vindt Dit veld staat in de tabel met schedule lines EKET, veld EINDT. Voorbeelden 2023-06-012023-06-152023-07-01 | |||
| Documenttype van de PO DocumentType | Een classificatie waarmee je verschillende typen Purchase Orders onderscheidt, zoals standaard-PO's, service-PO's of stock transport orders. | ||
| Beschrijving Het documenttype is een belangrijk configuratie-element in SAP. Het bepaalt de procesflow, nummerreeks en velden van een Purchase Order. Zo kun je het inkoopproces aanpassen aan verschillende situaties. Door het proces per documenttype te analyseren, begrijp je procesvarianten beter. Het proces voor een standaard-PO voor goederen kan bijvoorbeeld sterk verschillen van dat voor een service-PO of stock transfer. Met dit attribuut kun je deze procesflows filteren en vergelijken om specifieke verbeterpunten te vinden. Waarom dit belangrijk is Categoriseert Purchase Orders, zodat je verschillende inkoopprocessen kunt vergelijken en variaties in procesflows en doorlooptijden kunt verklaren. Waar je het vindt Dit attribuut staat in SAP S/4HANA-tabel EKKO, veld BSART. Voorbeelden NBFOUB | |||
| Gebruiker UserName | De identificatie 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. Door op gebruiker te analyseren, zie je waar training nodig is, hoe het werk verdeeld is en hoe prestaties verschillen. Je kunt bijvoorbeeld nagaan of bepaalde gebruikers structureel betrokken zijn bij lange goedkeuringstijden of veel wijzigingen na goedkeuring. Dat helpt bij gebruikersbeheer en procesverbetering. Waarom dit belangrijk is Zorgt voor verantwoordelijkheid en maakt prestatieanalyse op individueel of teamniveau mogelijk. Zo kun je trainingsmogelijkheden of capaciteitsproblemen identificeren. Waar je het vindt Deze informatie staat in velden zoals ERNAM (Created by) in EKKO of in het gebruikersveld van wijzigingsdocumenttabellen (CDHDR-USERNAME). Voorbeelden CB9980000012JSMITHRROE | |||
| Inkoopaanvraag PurchaseRequisitionNumber | De identificatie van de Purchase Requisition waarmee de Purchase Order is gestart. | ||
| Beschrijving Dit attribuut koppelt de Purchase Order terug aan de oorspronkelijke Purchase Requisition. Niet elke PO heeft een PR, bijvoorbeeld wanneer de PO rechtstreeks is aangemaakt. Deze koppeling is nodig om het volledige end-to-end-inkoopproces vanaf het eerste verzoek te analyseren. Het ondersteunt KPI's zoals 'Purchase Requisition Approval Time' en helpt bij het identificeren van 'Maverick Spend', waarbij PO's zonder voorafgaande goedgekeurde requisition worden aangemaakt. Waarom dit belangrijk is Verbindt de PO met het oorspronkelijke verzoek en maakt end-to-end-procesanalyse en identificatie van niet-conforme ongeautoriseerde uitgaven mogelijk. Waar je het vindt Dit attribuut staat in SAP S/4HANA-tabel EKPO, op itemniveau van de PO, veld BANFN. Voorbeelden 1001005110010052 | |||
| Leveranciers-ID VendorId | De unieke identificatie van de leverancier die de goederen of diensten levert. | ||
| Beschrijving De leveranciers-ID is belangrijke stamdata die een Purchase Order aan een specifieke leverancier koppelt. De ID wordt tijdens het hele inkoopproces gebruikt voor communicatie, levering en betaling. Met process mining kun je prestaties op leveranciersniveau analyseren. Dit attribuut is essentieel voor dashboards zoals 'Supplier Lead Time Performance' en 'Goods Return Rate by Vendor'. Zo zie je welke leveranciers het meest betrouwbaar zijn en welke mogelijk vertragingen of kwaliteitsproblemen veroorzaken. Waarom dit belangrijk is Maakt leveranciersgerichte analyses mogelijk. Zo kun je prestaties beoordelen, goed en minder goed presterende leveranciers identificeren en de toeleveringsketen verbeteren. Waar je het vindt Dit attribuut staat in SAP S/4HANA-tabel EKKO, veld LIFNR. Voorbeelden 100023100045100088 | |||
| Totale nettowaarde TotalNetAmount | De totale waarde van de Purchase Order, exclusief belastingen en vrachtkosten. | ||
| Beschrijving Dit attribuut vertegenwoordigt de netto geldwaarde van de Purchase Order. Het is een belangrijk financieel gegeven dat de omvang van de inkooptransactie aangeeft. Dit bedrag is belangrijk voor financiële analyses, bijvoorbeeld om PO's op waarde in te delen en te zien of hun procespaden verschillen. Je kunt het ook gebruiken om analyses te prioriteren en je te richten op orders met een hoge waarde, die meer financieel risico of een grotere bedrijfsimpact kunnen hebben. Waarom dit belangrijk is Maakt financiële analyses mogelijk. Zo kun je Purchase Orders op waarde indelen en verbeteracties prioriteren voor gebieden met hoge uitgaven. Waar je het vindt Dit attribuut staat in SAP S/4HANA-tabel EKKO, veld NETWR. Voorbeelden 1500.0025000.50125.75 | |||
| Bedrijfsnummer CompanyCode | De identificatie van de juridische entiteit of het bedrijf waarvoor de inkooporder wordt aangemaakt. | ||
| Beschrijving Het bedrijfsnummer vertegenwoordigt een zelfstandige boekhoudeenheid binnen een organisatie. Alle financiële transacties voor een inkooporder worden op een specifiek bedrijfsnummer geboekt. Dit is een belangrijk organisatorisch attribuut waarmee je inkoopprocessen bij verschillende juridische entiteiten kunt filteren en vergelijken. Een analyse per bedrijfsnummer kan verschillen in procesuitvoering, efficiëntie en compliance binnen de organisatie zichtbaar maken. Waarom dit belangrijk is Hiermee kun je procesanalyses per juridische entiteit uitvoeren en prestaties en compliance tussen verschillende bedrijfsonderdelen vergelijken. Waar je het vindt 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 werkdruk en prestaties gedetailleerder analyseren dan met de inkooporganisatie. Je kunt er overbelaste teams mee vinden, de efficiëntie van verschillende inkopersgroepen meten en zien welke groepen vaker afwijken van het proces, bijvoorbeeld door ongecontroleerde inkoop. Waarom dit belangrijk is Geeft een gedetailleerd beeld van de prestaties van inkopersgroepen. Zo kun je werkdruk, efficiëntie en procesnaleving op teamniveau analyseren. Waar je het vindt Dit attribuut staat in de SAP S/4HANA-tabel EKKO, veld EKGRP. Voorbeelden 001002N00 | |||
| Inkooporganisatie PurchasingOrganization | De organisatorische eenheid die verantwoordelijk is voor de inkoop van materialen en diensten en voor onderhandelingen met leveranciers. | ||
| Beschrijving De inkooporganisatie is een belangrijke organisatorische eenheid binnen inkoop. Deze kan op concern-, bedrijfs- of fabrieksniveau zijn ingericht en is verantwoordelijk voor alle inkoopactiviteiten. Door het proces per inkooporganisatie te analyseren, kun je de efficiëntie en prestaties van verschillende inkoopteams of regio's beoordelen. Zo worden verschillen in leveranciersonderhandelingen, naleving van processen en goedkeuringsvertragingen tussen organisatieonderdelen zichtbaar. Waarom dit belangrijk is Hiermee kun je prestaties van verschillende inkoopafdelingen of regio's vergelijken en best practices en verbeterpunten vinden. Waar je het vindt Dit attribuut staat in de SAP S/4HANA-tabel EKKO, veld EKORG. Voorbeelden 10101710US01 | |||
| Is herstelwerk IsRework | Een berekende vlag die aangeeft of aan een inkooporder herstelwerk is uitgevoerd, zoals een wijziging na goedkeuring of een retourzending van goederen. | ||
| Beschrijving Dit boolean-attribuut wordt berekend door de activiteitenvolgorde van elke inkooporder te analyseren. De waarde is 'true' als de gebeurtenis 'Purchase Order Changed' plaatsvindt na 'Purchase Order Approved', of als de gebeurtenis 'Goods Returned' voorkomt. Deze vlag vereenvoudigt de berekening van de KPI 'Straight-Through Processing Rate'. Je kunt hiermee alle inkooporders die handmatige interventie of correctie nodig hadden eenvoudig filteren en visualiseren. Zo krijg je zicht op de kosten en frequentie van herstelwerk. Waarom dit belangrijk is Helpt procesinefficiëntie te kwantificeren door cases met herstelwerk te markeren. Dat is belangrijk voor het berekenen van straight-through processing rates en het vinden van oorzaken van afwijkingen. Waar je het vindt Berekend veld op basis van de activiteitenvolgorde. De logica controleert of de gebeurtenis 'Purchase Order Changed' na een goedkeuring plaatsvindt of dat de gebeurtenis 'Goods Returned' voorkomt. Voorbeelden truefalse | |||
| Is ongecontroleerde inkoop IsMaverickSpend | Een berekende vlag die aangeeft of een inkooporder is aangemaakt zonder voorafgaande, goedgekeurde inkoopaanvraag. | ||
| Beschrijving Deze boolean-vlag wordt tijdens de dataverwerking berekend. De waarde is 'true' als een inkooporder geen gekoppelde inkoopaanvraag heeft of als het aanmaken van de inkooporder de standaardgoedkeuringsworkflow omzeilt. Dit attribuut ondersteunt rechtstreeks het dashboard 'Identificatie van ongecontroleerde inkoop' en de bijbehorende KPI's. Het helpt organisaties om niet-conform inkoopgedrag te kwantificeren en specifieke afdelingen of gebruikersgroepen te selecteren voor betere naleving van inkoopbeleid en controles. Waarom dit belangrijk is Identificeert niet-conforme inkoop rechtstreeks. Zo kun je procesafwijkingen kwantificeren en financiële controles en inkoopbeleid beter handhaven. Waar je het vindt Berekend veld op basis van het ontbreken van een waarde in 'PurchaseRequisitionNumber' voor specifieke documenttypen, of op basis van de analyse van de eventvolgorde. Voorbeelden truefalse | |||
| Itemcategorie ItemCategory | Classificeert een regelitem van een Purchase Order, zoals standaard, consignatie, onderaanneming of service. | ||
| Beschrijving De itemcategorie bepaalt hoe de inkoop van een specifiek materiaal of een specifieke dienst wordt beheerd en verwerkt. De categorie heeft invloed op vervolgstappen zoals goederenontvangst en factuurcontrole. Dit attribuut is belangrijk voor het analyseren van procesvarianten op basis van wat je inkoopt. Het proces voor een service-item, waarvoor een service entry sheet nodig is, verschilt bijvoorbeeld sterk van dat voor een standaardvoorraaditem. Door per itemcategorie te analyseren, verklaar je deze verschillen en kun je gericht verbeteren. Waarom dit belangrijk is Verklaart procesvarianten door verschillende typen inkoop te onderscheiden, zoals goederen, diensten of onderaanneming. Waar je het vindt Dit attribuut staat in de SAP S/4HANA-tabel EKPO, veld PSTYP. Voorbeelden 093 | |||
| Materiaalnummer MaterialNumber | De identificatie van het specifieke materiaal of product dat wordt ingekocht. | ||
| Beschrijving Het materiaalnummer is een unieke code voor elk materiaal in de SAP-materiaalstam. De code wordt gebruikt voor alle transacties rond dat materiaal, zoals inkoop, voorraadbeheer en verkoop. Met een analyse per materiaalnummer of materiaalgroep kun je inkoop per productcategorie bekijken. Zo zie je bijvoorbeeld of bepaalde materialen minder efficiënt worden ingekocht, langere doorlooptijden hebben of vaker worden geretourneerd. Dat levert input voor category management. Waarom dit belangrijk is Maakt een analyse per productcategorie mogelijk. Zo kun je procesproblemen of problemen met leveranciersprestaties voor specifieke producten of materialen vinden. Waar je het vindt Dit attribuut staat in de SAP S/4HANA-tabel EKPO, veld MATNR. Voorbeelden RM100-100FG210SERV-CONSULT | |||
| Tijdige levering door leverancier SupplierOnTimeDelivery | Een berekende vlag die aangeeft of de goederenontvangst op of vóór de gevraagde leverdatum is geboekt. | ||
| Beschrijving Dit boolean-attribuut wordt berekend door de timestamp van de activiteit 'Goods Receipt Posted' te vergelijken met de 'Requested Delivery Date'. Als de goederenontvangst op of vóór de gevraagde datum plaatsvindt, krijgt het attribuut de waarde 'true'. Dit attribuut ondersteunt rechtstreeks de KPI 'Supplier On-Time Delivery Rate'. Je kunt er tijdige en te late leveringen eenvoudig mee filteren. Dat is belangrijk voor dashboards over leveranciersprestaties en leveranciersbeoordelingen. Waarom dit belangrijk is Meet de betrouwbaarheid van leveranciers rechtstreeks. Het vormt de basis voor de KPI voor tijdige levering en helpt bij het beheren van leveranciersprestaties. Waar je het vindt Berekend door de timestamp van de activiteit 'Goods Receipt Posted' te vergelijken met het attribuut 'RequestedDeliveryDate'. Voorbeelden truefalse | |||
| Vestiging Plant | De locatie of operationele vestiging waar goederen worden geleverd 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 de procesanalyse per vestiging uit te voeren, worden regionale of locatiespecifieke verschillen in het inkoopproces zichtbaar. Zo zie je bijvoorbeeld of bepaalde vestigingen langere levertijden hebben of vaker goederen retourneren. Dat kan wijzen op lokale problemen in logistiek of kwaliteitscontrole. Waarom dit belangrijk is Maakt een locatiegerichte analyse mogelijk. Zo worden verschillen in procesprestaties tussen operationele locaties, vestigingen en magazijnen zichtbaar. Waar je het vindt Dit attribuut staat in de SAP S/4HANA-tabel EKPO, veld WERKS. Voorbeelden 10101710DE01 | |||
Purchase to Pay - Purchase Order-activiteiten
| Activiteit | Beschrijving | ||
|---|---|---|---|
| Factuur ontvangen | Staat voor het invoeren van een leveranciersfactuur in het SAP-systeem en de koppeling aan de bijbehorende Purchase Order. Dit is een expliciete financiële boeking die een boekhoudkundig document aanmaakt. | ||
| Waarom dit belangrijk is Dit is een belangrijk meetpunt dat het inkoopproces koppelt aan het proces voor crediteurenadministratie. Hiermee kun je de tijd tussen goederenontvangst en factuurverwerking analyseren. Waar je het vindt Een boekhoudkundig document wordt aangemaakt in tabel BKPF (header). De regels staan in BSEG of in het universal journal ACDOCA. Het document is in tabel RSEG aan de PO gekoppeld. Vastleggen Invoerdatum van het document (CPUDT) uit de header van het boekhoudkundige document in tabel BKPF. Eventtype explicit | |||
| Goederenontvangst geboekt | Staat voor de fysieke ontvangst van goederen van de leverancier en de bijbehorende registratie in het systeem. Dit is een expliciete transactie die de Purchase Order-historie bijwerkt. | ||
| Waarom dit belangrijk is Dit is een belangrijk meetpunt dat de doorlooptijd bij de leverancier beëindigt en het interne proces van factuurcontrole start. Het is essentieel voor het meten van tijdige leveringen. Waar je het vindt Vastgelegd als een materiaaldocument in tabellen MKPF (header) en MSEG (item), en gekoppeld in de Purchase Order-historietabel EKBE met een specifieke bewegingsoort, bijvoorbeeld 101. Vastleggen Boekingsdatum (BUDAT) uit de header van het materiaaldocument (MKPF), gekoppeld via EKBE. Eventtype explicit | |||
| Purchase Order aangemaakt | Markeert het aanmaken van het officiële Purchase Order-document. Dit kan met of zonder verwijzing naar een Purchase Requisition gebeuren. Het is een expliciete gebeurtenis die wordt vastgelegd wanneer het PO-document voor het eerst in het systeem wordt opgeslagen. | ||
| Waarom dit belangrijk is Deze activiteit kan een alternatief startpunt van het proces zijn, vooral voor analyses van ongeautoriseerde aankopen. Het is een belangrijke gebeurtenis voor het meten van de totale verwerkingstijd van de PO. Waar je het vindt Vastgelegd in de Purchase Order-headerstabel EKKO. De aanmaakdatum (AEDAT) en tijd staan voor het document rechtstreeks in deze tabel. Vastleggen Timestamp van het aanmaken (AEDAT) in tabel EKKO voor het Purchase Order-document. Eventtype explicit | |||
| Purchase Order goedgekeurd | Geeft aan dat de Purchase Order alle benodigde interne goedkeuringen heeft ontvangen en mag worden vrijgegeven aan de leverancier. De gebeurtenis wordt afgeleid uit een statuswijziging in de vrijgavestrategie van de Purchase Order. | ||
| Waarom dit belangrijk is Dit is een belangrijk meetpunt voor de efficiëntie van goedkeuringen en herstelwerk na goedkeuring. Door de tijd tussen het aanmaken en goedkeuren van de PO te analyseren, worden interne procesvertragingen zichtbaar. Waar je het vindt Afgeleid uit de vrijgave-indicator (FRGKE) in tabel EKKO. De timestamp wordt bepaald aan de hand van de wijzigingshistorie (CDHDR/CDPOS), op het moment dat dit veld de status 'released' kreeg. Vastleggen Afgeleid uit wijzigingslogs voor het veld van de vrijgave-indicator (FRGKE) in tabel EKKO. Eventtype inferred | |||
| Purchase Order voltooid | Deze activiteit geeft aan dat een Purchase Order-item logistiek gezien is gesloten. Dit wordt afgeleid wanneer zowel de indicatoren 'Delivery Completed' als 'Final Invoice' zijn ingesteld. | ||
| Waarom dit belangrijk is Dit is het eindpunt voor de analyse van de Purchase Order-lifecycle. Door de tijd tot deze gebeurtenis te meten, bereken je de end-to-end-doorlooptijd van het inkoopproces. Waar je het vindt Afgeleid uit statusvlaggen in de Purchase Order-itemtabel EKPO. De gebeurtenis vindt plaats wanneer zowel de indicator 'Delivery Completed' (ELIKZ) als de indicator 'Final Invoice' (EREKZ) op true staat. Vastleggen Afgeleid uit wijzigingslogs wanneer de EKPO-velden ELIKZ en EREKZ beide als voltooid zijn gemarkeerd. Eventtype inferred | |||
| Purchase Requisition aangemaakt | Deze activiteit markeert het formele verzoek om goederen of diensten en start het inkoopproces. De gebeurtenis wordt expliciet vastgelegd wanneer een gebruiker een nieuwe Purchase Requisition opslaat, bijvoorbeeld met transactie ME51N. | ||
| Waarom dit belangrijk is Dit is voor veel Purchase Order-lifecycles het eerste startpunt. Door de tijd tussen deze gebeurtenis en het aanmaken van de PO te analyseren, zie je vertragingen in sourcing en interne verwerking. Waar je het vindt Vastgelegd in tabel EBAN (Purchase Requisition). De timestamp van het aanmaken staat in de wijzigingshistorietabellen CDHDR en CDPOS voor het EBAN-object. Vastleggen Gebeurtenis vastgelegd bij het aanmaken van een document in tabel EBAN. Eventtype explicit | |||
| Purchase Requisition goedgekeurd | Dit staat voor de formele goedkeuring van een Purchase Requisition door een manager of aangewezen goedkeurder. De gebeurtenis wordt meestal afgeleid uit een statuswijziging in het requisition-document, waarmee het klaar is voor omzetting naar een Purchase Order. | ||
| Waarom dit belangrijk is Dit is een belangrijk meetpunt voor goedkeuringsdoorlooptijden en het opsporen van knelpunten. Vertragingen hier hebben direct invloed op hoe snel een Purchase Order kan worden aangemaakt en naar een leverancier kan worden gestuurd. Waar je het vindt Afgeleid uit de vrijgavestatusvelden in tabel EBAN, bijvoorbeeld FRGZU (Release indicator). De timestamp wordt bepaald aan de hand van wijzigingsdocumenten in CDHDR/CDPOS, waarin staat wanneer de definitieve vrijgavestatus is ingesteld. Vastleggen Afgeleid uit wijzigingslogs voor vrijgavestatusvelden in tabel EBAN, in CDHDR/CDPOS. Eventtype inferred | |||
| Factuur betaald | Markeert de definitieve afwikkeling van de leveranciersfactuur via een betalingsrun of handmatige betaling. Dit is een expliciete financiële transactie die een vereffeningsdocument aanmaakt. | ||
| Waarom dit belangrijk is Hoewel deze activiteit technisch onderdeel is van het betalingsproces, geeft opname ervan een volledig beeld van de procure-to-pay-cyclus. Dit is belangrijk voor het analyseren van betalingstermijnen en prestaties. Waar je het vindt 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, in BSEG of ACDOCA. Eventtype 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 terugdraaiing van de goederenbeweging. | ||
| Waarom dit belangrijk is Deze activiteit maakt herstelwerk en mogelijke problemen met leverancierskwaliteit of ordernauwkeurigheid zichtbaar. Veel retouren voor een specifieke leverancier of een bepaald materiaal wijzen op een probleem. Waar je het vindt Vastgelegd als een materiaaldocument met een specifieke retourbeweging, bijvoorbeeld 122. De gebeurtenis wordt geregistreerd in MKPF/MSEG en gekoppeld aan de PO in historietabel EKBE. Vastleggen Boekingsdatum uit het materiaaldocument met een retourbeweging in EKBE. Eventtype explicit | |||
| Purchase Order gewijzigd | Deze activiteit geeft aan dat de Purchase Order na het eerste aanmaken is gewijzigd, bijvoorbeeld in hoeveelheid, prijs of leverdatum. De wijziging wordt expliciet vastgelegd in de wijzigingslogs van het systeem. | ||
| Waarom dit belangrijk is Het volgen van wijzigingen, vooral na goedkeuring, is belangrijk om inefficiënties, herstelwerk en mogelijke complianceproblemen te vinden. Veel wijzigingen kunnen wijzen op onvolledige of onjuiste specificaties bij de start. Waar je het vindt Vastgelegd in de wijzigingsdocumenttabellen CDHDR (header) en CDPOS (item) voor Purchase Order-objecten (EINKBELEG). Elke wijziging maakt een gedetailleerde logvermelding aan. Vastleggen Gebeurtenis vastgelegd voor wijzigingen in belangrijke velden in tabellen EKKO of EKPO, geregistreerd in CDHDR/CDPOS. Eventtype explicit | |||
| Purchase Order naar leverancier verzonden | Geeft het moment aan waarop de Purchase Order met de leverancier wordt gedeeld, bijvoorbeeld via EDI, e-mail of print. Deze gebeurtenis wordt vaak vastgelegd in de logs van het outputbeheer van het systeem. | ||
| Waarom dit belangrijk is Deze activiteit is het echte startpunt van de doorlooptijd bij de leverancier. Dat is belangrijk om leveranciersprestaties nauwkeurig te meten vanaf het moment waarop de leverancier de order ontvangt. Waar je het vindt Vastgelegd in controletabel NAST, waarin berichten voor een inkoopdocument worden geregistreerd. De datum en tijd van het relevante outputtype, bijvoorbeeld EDI of e-mail, kunnen hiervoor worden gebruikt. Vastleggen Timestamp van het eerste succesvolle outputbericht voor de PO in tabel NAST. Eventtype inferred | |||
| Purchase Order verwijderd | Staat voor het annuleren of logisch verwijderen van een Purchase Order-item of het volledige document. Dit wordt vastgelegd wanneer een gebruiker een verwijderingsvlag op het document instelt. | ||
| Waarom dit belangrijk is Deze activiteit is een alternatief eindpunt van het proces en wijst op een mislukking of annulering. Door te analyseren waarom PO's worden verwijderd, kun je problemen in vraagplanning of het vaststellen van behoeften vinden. Waar je het vindt Vastgelegd via de verwijderingsindicator (LOEKZ) in de Purchase Order-header (EKKO) of itemtabel (EKPO). De timestamp wordt afgeleid uit de wijzigingsdocumenten (CDHDR/CDPOS). Vastleggen Timestamp uit wijzigingsdocumenten (CDHDR/CDPOS) op het moment dat de verwijderingsvlag (LOEKZ) wordt ingesteld. Eventtype explicit | |||
| Servicebevestiging ingevoerd | Deze activiteit markeert de bevestiging dat een dienst uit een Purchase Order is geleverd. De gebeurtenis wordt expliciet vastgelegd door het aanmaken van een service entry sheet. | ||
| Waarom dit belangrijk is Bij inkoop van diensten is dit het equivalent van een goederenontvangst. Het is belangrijk om doorlooptijden van dienstverlening te volgen en tijdige betalingen aan leveranciers mogelijk te maken. Waar je het vindt Vastgelegd bij het aanmaken van een service entry sheet. De data staat in tabellen ESSR (header) en ESLL (regels). De aanmaakdatum dient als timestamp. Vastleggen Aanmaakdatum van het Service Entry Sheet-document in tabel ESSR. Eventtype explicit | |||
Extractiegidsen
Stappen
- Voorwaarden en toegang: Zorg dat je een gebruiker hebt met de juiste autorisaties om Core Data Services (CDS)-views in het SAP S/4HANA-systeem 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 verzamelen: Verzamel de benodigde verbindingsparameters voor je SAP S/4HANA-systeem, waaronder de host, het instantienummer en je authenticatiegegevens.
- Verbinding maken met de database: Maak met je favoriete SQL-client verbinding met de SAP S/4HANA-database waarin de CDS-views staan.
- De SQL-query voorbereiden: Kopieer de volledige SQL-query uit het querygedeelte van dit document naar je SQL-editor. Deze query haalt alle benodigde activiteiten en attributen op.
- Filterparameters instellen: Zoek de placeholderwaarden in de query. Vervang _start_date en _end_date door de gewenste datums voor je analyse, bijvoorbeeld '20230101' en '20231231'. Pas het poh.CompanyCode-filter aan met de specifieke bedrijfs codes 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 enige tijd duren.
- De eerste resultaten controleren: Controleer na afloop kort de uitvoer in je SQL-client. Kijk of verschillende activiteiten aanwezig zijn, of 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 data-eisen, zoals PurchaseOrderNumber, ActivityName en EventTime. Pas kolomnamen aan als je exporttool deze heeft gewijzigd.
- Uploaden naar ProcessMind: Upload het definitieve CSV-bestand naar je ProcessMind-project. Koppel tijdens het importeren de kolommen in je bestand aan de bijbehorende velden voor case-ID, activiteit en timestamp.
Configuratie
- Belangrijkste CDS-views: De extractielogica gebruikt een reeks standaard-CDS-views met semantische informatie. De belangrijkste views zijn:
- I_PurchaseOrderItemAPI01: Voor de kerngegevens van inkooporderitems.
- I_PurchaseRequisitionItemAPI01: Voor gegevens over inkoopaanvragen.
- I_MaterialDocumentItem: Voor goederenbewegingen, zoals ontvangsten en retouren.
- I_ServiceEntrySheetAPI01: Voor gebeurtenissen rond servicebevestigingen.
- I_SupplierInvoiceAPI01: Voor informatie over leveranciersfacturen.
- I_OperationalAcctgDocItem: Voor het koppelen van facturen aan financiële documenten voor het volgen van betalingen.
- I_ChangeDocument: Voor het vastleggen van wijzigingen aan de inkooporder.
- Filteren op datumbereik: Pas altijd een datumbereikfilter toe om de prestaties en hoeveelheid data beheersbaar te houden. De query gebruikt de placeholders _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 om de extractie te beperken tot relevante bedrijfsonderdelen. Je kunt extra filters op PurchaseOrderType of PurchasingOrganization toevoegen aan de PO_base common table expression voor verdere verfijning.
- Voorwaarden: De gebruiker die de query uitvoert, heeft SELECT-autorisatie nodig voor alle hierboven genoemde CDS-views. Toegang tot deze views wordt meestal geregeld via specifieke bedrijfs- of analyticsrollen in S/4HANA. Zonder de juiste rechten mislukt de query.
a 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 directe SQL-toegang beschikbaar is tot het SAP HANA-schema met EKKO en EKPO en regel de benodigde leesautorisaties. Vervang schema- en verbindingsplaceholders door de waarden die voor je systeem zijn ingesteld.
- Bepaal het extractievenster met [Start timestamp] en [End timestamp]. Voor de eerste lading wordt een periode van drie tot zes maanden aanbevolen. Gebruik filters voor bedrijfs code en documenttype alleen als deze nodig zijn voor de rapportagescope.
- Identificeer inkooporders in EKKO en EKPO. Behoud het inkoopordernummer, de leverancier, het documenttype, de bedrijfscode, de aanmaakdatum, de aanmaaktijd en de attributen op itemniveau. Tel de nettowaarden uit 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 itemreferentie uit EKPO om aanvragen aan inkooporders te koppelen. Omdat indicatoren en timestamps voor goedkeuring verschillen per releaseconfiguratie, configureer je de expressies voor goedkeuringsstatus en timestamp op basis van de actieve SAP-releasestrategie in [Configure based on your system].
- Haal gebeurtenissen op voor het aanmaken, goedkeuren, wijzigen, verwijderen en afronden van inkooporders. Voor het aanmaken gebruik je de aanmaakdatum en -tijd uit EKKO. Voor goedkeuring, wijziging en verwijdering zijn bronnen voor release- of wijzigingshistorie nodig. Configureer de bijbehorende bronexpressies met [Your table name] en [Your column name] als de relevante historie niet beschikbaar is in het geselecteerde schema.
- Haal gebeurtenissen op voor communicatie met leveranciers, goederenontvangst, servicebevestiging, retouren, factuurontvangst en factuurbetaling uit de toepasselijke bronnen voor output, materiaaldocumenten, service-entrybladen, facturen, boekhouding en clearing. De query bevat expliciete placeholders voor systeem specifieke objecten, omdat EKKO en EKPO alleen deze bronnen niet volledig afdekken.
- Breng elke brongebeurtenis onder in dezelfde event-logstructuur. 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 timestamps, verwijder alleen exact 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 databaseresultaat met één kopregel en vaste kolomnamen. Gebruik een timestampindeling die door de ProcessMind-uploadconfiguratie wordt ondersteund, behoud 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 items van inkooporders. Configureer aanvullende objecten voor aanvragen, releasestatus, wijzigingshistorie, output, goederenbewegingen, service-entrybladen, facturen, betalingen en clearing volgens de SAP S/4HANA-release en het actieve datamodel.
- Case-identificatie: Gebruik PurchaseOrderNumber als case-identificatie. Koppel gebeurtenissen op itemniveau aan het inkoopordernummer. Bewaar itemreferenties in een extra bron specifieke kolom als dat nodig is.
- Datumbereik: Begin met drie tot zes maanden. Verwerk voor historische ladingen kleinere perioden en stem overlappende grenzen op elkaar af om ontbrekende data te voorkomen.
- Filters: Configureer Company Code, Document Type, VendorId, inkooporganisatie, inkoopgroep en filters voor de gebeurtenisdatum volgens de gewenste scope. Filters voor bedrijfscode en documenttype moeten waarden gebruiken die in het doelsysteem geldig zijn.
- Betekenis van gebeurtenissen: Aanmaken en verwijderen kunnen expliciet worden vastgelegd als de relevante documentvelden of logs beschikbaar zijn. Goedkeuring en afronding zijn statusgebaseerde gebeurtenissen waarvoor geconfigureerde statustimestamps nodig zijn. Maak geen rijen aan op basis van alleen een huidige status als daar geen verdedigbare gebeurtenistimestamp voor is.
- Prestaties: Filter vroeg op gebeurtenisdatums en organisatiescope, aggregeer EKPO waar mogelijk voordat je deze aan gebeurtenisbronnen koppelt en voer grote historische ladingen uit in tijdvensters. Zorg voor geschikte databasestatistieken en vermijd onbeperkte joins tussen item-, boekhoud- en wijzigingshistoriebronnen.
- Timestamp van verversing: Stel LastDataUpdate voor elke rij in een run in op de timestamp waarop de extractie is uitgevoerd.
- Voorwaarden: Benodigde voorwaarden zijn SAP HANA-connectiviteit, leestoegang tot alle geconfigureerde bronobjecten, toegang tot relevante data voor inkoop, voorraadbeheer, service-inkoop, factuurcontrole en crediteurenadministratie, plus een ProcessMind-verbinding die het gekozen bestand of resultaat kan importeren.
- Systeemspecifieke configuratie: Vervang elke bronplaceholder tussen blokhaken in de query door een goedgekeurde tabel, view, kolom of expressie uit het SAP S/4HANA-doelsysteem. Neem geen inloggegevens op in de query of extractieconfiguratie.
a 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 datastructuur voor het event-logbestand, inclusief alle verplichte en aanbevolen attributen. Leg vast welke SAP-tabellen, zoals EKKO, EKPO, EKBE, CDHDR, CDPOS en BKPF, worden gebruikt als bron voor elk van de 13 verplichte activiteiten.
- Programma maken: Open in de SAP GUI 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 te extraheren data filteren. Voeg parameters toe voor het aanmaakdatumbereik 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. Dit omvat een interne tabel voor het uiteindelijke event log, met dezelfde structuur als in de specificatiestap.
- Logica voor dataselectie implementeren: Schrijf de centrale ABAP-logica om data voor elk van de 13 activiteiten te selecteren. Dit bestaat uit meerdere SELECT-statements op de relevante SAP-tabellen, met joins waar nodig. Lees voor wijzigingsgebaseerde gebeurtenissen de wijzigingslogtabellen CDHDR en CDPOS uit.
- Data transformeren en koppelen: Koppel voor elk opgehaald record de SAP-tabelvelden aan de bijbehorende kolommen in de interne tabel van het event log. Stel ActivityName in op basis van de verwerkte gebeurtenis, bijvoorbeeld 'Purchase Order Created'. Zet datum- en tijdvelden om naar één consistente timestampindeling voor EventTime.
- Gebeurtenisdata samenvoegen: Zorg dat alle data na verwerking van de 13 activiteitstypen in één uniforme interne tabel staat. Deze tabel vormt het volledige event log voor de geselecteerde inkooporders.
- Bestandsuitvoer implementeren: 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 als CSV op hun lokale computer kunnen opslaan. Je kunt ook OPEN DATASET gebruiken om het bestand op te slaan op de SAP-applicatieserver voor verwerking op de achtergrond.
- Transactiecode maken, optioneel: Maak met transactiecode SE93 een aangepaste transactiecode, bijvoorbeeld ZPM_PO_EXTRACT, die je ABAP-programma uitvoert. Zo is het programma eenvoudig toegankelijk voor zakelijke gebruikers.
- 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 van de applicatieserver dat in de programmalogica is opgegeven.
Configuratie
- Selectiecriteria: Het programma moet selectieparameters bevatten om de data gericht te filteren. Belangrijke 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 rapportageprestaties beheersbaar te houden.
- Bedrijfscode (BUKRS): Essentieel voor organisaties met meerdere juridische entiteiten om de extractiescope te beperken.
- Inkoopdocumenttype (BSART): Hiermee kun je specifieke PO-typen filteren, zoals Standard PO, Framework Order of Stock Transport Order, zodat je de analyse kunt richten.
- Wijzigingslog lezen: Voor het extraheren van activiteiten zoals 'Purchase Order Approved' of 'Purchase Order Changed' moeten de SAP-wijzigingslogtabellen CDHDR en CDPOS worden gelezen. Dit kan veel capaciteit 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 die dit rapport uitvoert, heeft uitgebreide leesautorisaties nodig voor tabellen uit meerdere SAP-modules, waaronder Materials Management (MM), Financial Accounting (FI) en systeembrede tabellen. Dit omvat onder andere EKKO, EKPO, EBAN, EKBE, BKPF, BSAK, RBKP, NAST, CDHDR en CDPOS.
- Uitvoering op de achtergrond: Voer extracties over meer dan enkele maanden, of extracties in een systeem met veel transacties, altijd op de achtergrond uit om time-outs van dialoogprocessen te voorkomen.
a 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 je process mining-traject. Gebruik je SAP S/4HANA-data om efficiëntie te vinden en verbeter vandaag nog je Purchase to Pay-proces.
Optimaliseer je P2P-inkooporder: verkort de doorlooptijd nu
Elimineer inefficiënties en verkort de doorlooptijd van je P2P-inkooporders met 30%.
Je hebt geen creditcard nodig. Je kunt binnen enkele minuten aan de slag.