Jouw datatemplate voor Purchase to Pay, Purchase Order
Jouw datatemplate voor Purchase to Pay, Purchase Order
- Aanbevolen attributen om te verzamelen
- Belangrijke activiteiten om te volgen
- Extractie-instructies voor SAP ECC
Purchase to Pay - Purchase Order-attributen
| Naam | Beschrijving | ||
|---|---|---|---|
| Activiteit Activity | De naam van de specifieke bedrijfsgebeurtenis of processtap die binnen de levenscyclus van de inkooporder heeft plaatsgevonden. | ||
| Beschrijving Dit attribuut beschrijft één stap in het proces, zoals ‘Inkooporder aangemaakt’, ‘Inkooporder goedgekeurd’ of ‘Goederenontvangst geboekt’. De volgorde van deze activiteiten vormt de procesflow voor elke inkooporder. Het analyseren van de volgorde, frequentie en tijd tussen activiteiten vormt de kern van process mining. Zo vind je knelpunten, herstelwerklussen en afwijkingen van het standaardproces. Dat helpt bij gerichte verbeteringen en standaardisatie. Waarom dit belangrijk is Activiteiten bepalen de stappen van het proces. Door hun volgorde en timing te analyseren, zie je de werkelijke procesflow, knelpunten en afwijkingen. Waar je het vindt Afgeleid uit verschillende SAP-tabellen en transactielogboeken, zoals CDHDR/CDPOS voor wijzigingen, EKBE voor goederenontvangsten en factuurontvangsten, en EBAN voor inkoopaanvragen. Vaak is aangepaste logica of een extractieprogramma nodig om dit te genereren. Voorbeelden Inkooporder aangemaaktInkooporder goedgekeurdGoederenontvangst geboekt | |||
| Inkooporder PurchaseOrder | De unieke identificatie van het document van de inkooporder, dat als primaire case dient voor het volgen van het inkoopproces. | ||
| Beschrijving Het inkoopordernummer is de centrale identificatie die alle activiteiten koppelt, van het aanmaken van de order tot de uiteindelijke goederenontvangst en voltooiing. Elk uniek inkoopordernummer staat voor één afzonderlijke uitvoering van het inkoopproces. In process mining is dit attribuut essentieel om het volledige verloop van elke aankoop te reconstrueren. Je kunt er doorlooptijden, procesvarianten en compliancecontroles per order mee analyseren. Daarmee vormt het de basis van het volledige procesmodel. Waarom dit belangrijk is Dit is de belangrijkste identificatie die alle gerelateerde gebeurtenissen koppelt. Zo kun je de volledige levenscyclus van elke afzonderlijke inkooporder analyseren. Waar je het vindt Tabel: EKKO, veld: EBELN Voorbeelden 450001762345000176244500017625 | |||
| Tijdstip gebeurtenis EventTime | De exacte datum en tijd waarop de activiteit plaatsvond. | ||
| Beschrijving Deze timestamp markeert het exacte moment waarop een gebeurtenis plaatsvond, bijvoorbeeld wanneer een inkooporder werd goedgekeurd of een goederenontvangst werd geboekt. De timestamp bepaalt de chronologische volgorde van alle activiteiten binnen een case. Timestamps zijn essentieel voor process mining, omdat ze alle tijdsanalyses mogelijk maken. Denk aan het berekenen van doorlooptijden tussen activiteiten, het vinden van vertragingen, het analyseren van procesdoorvoer en het meten van prestaties ten opzichte van servicelevelafspraken (SLA’s). Waarom dit belangrijk is Deze timestamp is belangrijk voor het berekenen van alle metriek op basis van tijdsduur, zoals doorlooptijden en knelpunten, en voor het chronologisch ordenen van gebeurtenissen. Waar je het vindt Afgeleid uit verschillende datum- en tijdvelden in SAP-tabellen, zoals EKKO-AEDAT (wijzigingsdatum), CDHDR-UDATE/UTIME (timestamp van wijzigingslogboek) of EKBE-BUDAT (boekingsdatum). Voorbeelden 2023-04-15T10:05:31Z2023-04-16T14:22:00Z2023-05-01T09:00:15Z | |||
| Bedrijfsnummer CompanyCode | De identificatie van de juridische entiteit of onderneming die de aankoop initieert. | ||
| Beschrijving Het bedrijfsnummer staat in SAP voor een zelfstandige juridische entiteit. Alle transacties worden op bedrijfsnummerniveau geboekt, waardoor dit een fundamentele organisatorische eenheid is. Door het proces per bedrijfsnummer te analyseren, vergelijk je de efficiëntie en compliance van het inkoopproces tussen bedrijfsonderdelen of landen. Zo ontdek je best practices die je elders kunt toepassen en zie je welke onderdelen moeite hebben met het proces. Waarom dit belangrijk is Staat voor de juridische entiteit en maakt vergelijking van procesprestaties en compliancecontroles tussen verschillende delen van de organisatie mogelijk. Waar je het vindt Tabel: EKKO, veld: BUKRS Voorbeelden 10002100US01 | |||
| Documenttype DocumentType | Een code die verschillende typen inkooporders classificeert. | ||
| Beschrijving Het documenttype is een configuratie in SAP die het nummerbereik, de veldselectie en de algemene procesflow van een inkooporder bepaalt. Er kunnen bijvoorbeeld verschillende typen zijn voor standaardinkooporders, service-inkooporders of voorraadtransportorders. Dit attribuut is een sterke dimensie voor analyse, omdat verschillende documenttypen vaak bewust verschillende processen volgen. Door op documenttype te filteren, vergelijk je doorlooptijden en procesflows nauwkeuriger. Waarom dit belangrijk is Maakt onderscheid tussen verschillende soorten inkoopprocessen, zoals standaard, diensten en retouren. Deze volgen vaak verschillende routes en hebben andere prestatieverwachtingen. Waar je het vindt Tabel: EKKO, veld: BSART Voorbeelden NBFOUB | |||
| Gebruikersnaam UserName | De gebruikers-ID van de persoon die de activiteit heeft uitgevoerd. | ||
| Beschrijving Dit attribuut legt de SAP-gebruikersnaam vast van de medewerker die een document heeft aangemaakt, gewijzigd of goedgekeurd. Bij geautomatiseerde stappen kan hier de ID van een systeem- of batchgebruiker staan. Door per gebruiker te analyseren, zie je waar training nodig is, wie goed presteert en waar mogelijke complianceproblemen zitten. Dit is belangrijk voor dashboards over werkverdeling, naleving van de goedkeuringsmatrix en de prestaties van verschillende teams of personen. Waarom dit belangrijk is Koppelt gebruikersacties aan specifieke personen. Zo kun je prestaties, werkbelasting en naleving van complianceprotocollen analyseren. Waar je het vindt Tabel: EKKO, veld: ERNAM (aangemaakt door); tabel: CDHDR, veld: USERNAME (gewijzigd door). Voorbeelden JSMITHMBROWNBATCH_USER | |||
| Leveranciersnummer VendorNumber | De unieke identificatie van de leverancier. | ||
| Beschrijving Dit is de code die de leverancier van de goederen of diensten uniek identificeert. Het is een belangrijk onderdeel van de stamdata in het inkoopproces. Dit attribuut is essentieel voor leveranciersanalyses. Je kunt er leverprestaties mee beoordelen, doorlooptijden van verschillende leveranciers vergelijken en uitgavenpatronen analyseren. Het vormt de belangrijkste dimensie voor het dashboard ‘Leveranciersprestaties bij levering’. Waarom dit belangrijk is Maakt analyse van leveranciersprestaties mogelijk, zodat je betrouwbare leveranciers en leveranciers die vertragingen of kwaliteitsproblemen veroorzaken kunt herkennen. Waar je het vindt Tabel: EKKO, veld: LIFNR Voorbeelden 100345V-20598700112 | |||
| Materiaalgroep MaterialGroup | Een classificatie om materialen of diensten met vergelijkbare kenmerken te groeperen. | ||
| Beschrijving De materiaalgroep, of inkoopcategorie, wordt gebruikt om het type ingekochte goederen of diensten te classificeren. Voorbeelden zijn ‘IT-hardware’, ‘kantoorbenodigdheden’ en ‘professionele diensten’. Dit attribuut is belangrijk voor uitgavenanalyses en inzicht in inkooppatronen. Je kunt het proces filteren om te analyseren hoe verschillende categorieën worden afgehandeld, wie ze goedkeurt en welke leveranciers ze leveren. Het is een belangrijke dimensie in het dashboard ‘Waardeanalyse inkooporders’. Waarom dit belangrijk is Maakt het mogelijk om het proces per product- of dienstcategorie te segmenteren. Zo zie je verschillend gedrag, andere doorlooptijden of andere leveranciers per type uitgave. Waar je het vindt Tabel: EKPO, veld: MATKL Voorbeelden 00101IT_HWCONSULT | |||
| Orderbedrag OrderAmount | De totale geldwaarde van het item op de inkooporder. | ||
| Beschrijving Dit attribuut staat voor de totale waarde van een specifiek item op de inkooporder, berekend als hoeveelheid vermenigvuldigd met de nettoprijs. Voor de totale waarde van een inkooporder moeten de bedragen van de items worden opgeteld. Door het proces op orderbedrag te analyseren, vind je transacties met een hoge waarde die mogelijk strengere controles of een andere goedkeuringsroute nodig hebben. Dit vormt de basis voor het dashboard ‘Waardeanalyse inkooporders’ en helpt om verbeteringen te richten op orders met de grootste financiële impact. Waarom dit belangrijk is Maakt de financiële impact van elke aankoop meetbaar. Zo kun je analyses op basis van waarde uitvoeren, orders met een hoge waarde prioriteren en mogelijkheden voor kostenbesparing vinden. Waar je het vindt Tabel: EKPO, veld: NETWR (netto orderwaarde). Voorbeelden 1500.00250.7512345.50 | |||
| Bronsysteem SourceSystem | Het systeem waaruit de data is geëxtraheerd. | ||
| Beschrijving Dit attribuut identificeert de herkomst van de data, doorgaans een identificatie van een SAP ECC-instantie, bijvoorbeeld ‘ECC_PROD_100’. In omgevingen met meerdere systemen helpt het om databronnen van elkaar te onderscheiden. Voor governance en data lineage is het belangrijk om het bronsysteem te kennen. Zo bewaak je de integriteit van de data en los je problemen met data-extractie of datakwaliteit makkelijker op, vooral wanneer data uit verschillende ERP-systemen of modules wordt samengevoegd. Waarom dit belangrijk is Identificeert de herkomst van de data. Dat is belangrijk voor datagovernance, validatie en het beheren van analyses over meerdere systemen. Waar je het vindt Dit is doorgaans een statische waarde die tijdens de data-extractie wordt toegevoegd om de dataset van het bronsysteem te voorzien. Voorbeelden SAP_ECC_PRODECC_EU_100S4H_FIN | |||
| Gewenste leverdatum RequestedDeliveryDate | De datum waarop de organisatie de leverancier heeft gevraagd de goederen of diensten te leveren. | ||
| Beschrijving Dit is de gewenste leverdatum die in de inkooporder staat. De datum vormt de basis voor het meten van de werkelijke leverprestatie. Deze datum is essentieel voor het berekenen van de KPI voor het percentage tijdige goederenontvangsten. Door de werkelijke datum van goederenontvangst met deze gewenste datum te vergelijken, meet je de betrouwbaarheid van de leverancier en de efficiëntie van de interne ontvangst. Dit ondersteunt rechtstreeks het dashboard ‘Leveranciersprestaties bij levering’. Waarom dit belangrijk is Dit is de streefdatum voor de levering. De datum is nodig voor KPI’s over tijdige prestaties en voor het beoordelen van de betrouwbaarheid van leveranciers. Waar je het vindt Tabel: EKPO, veld: EINDT Voorbeelden 2023-06-102023-07-222023-08-01 | |||
| Inkoopaanvraag PurchaseRequisition | De identificatie van de inkoopaanvraag die aan de inkooporder voorafging. | ||
| Beschrijving Dit attribuut koppelt de inkooporder aan de oorspronkelijke inkoopaanvraag. Niet elke inkooporder heeft een voorafgaande aanvraag. Deze koppeling is belangrijk voor het analyseren van het dashboard ‘Conversie van aanvraag naar order’ en de KPI ‘Conversiepercentage van inkoopaanvraag naar inkooporder’. Je meet er de efficiëntie van het voorafgaande proces mee, van het eerste verzoek tot het aanmaken van een formele order. Ook zie je welke inkooporders zonder aanvraag zijn aangemaakt en dus niet aan het beleid voldoen. Waarom dit belangrijk is Koppelt de inkooporder aan het oorspronkelijke verzoek. Zo kun je de conversie van inkoopaanvraag naar inkooporder analyseren en inkooporders vinden die zonder voorafgaande aanvraag zijn aangemaakt. Waar je het vindt Tabel: EKPO, veld: BANFN Voorbeelden 1001589010015891 | |||
| Inkoopgroep PurchasingGroup | De specifieke inkoper of groep inkopers die verantwoordelijk is voor de inkoopactiviteit. | ||
| Beschrijving De inkoopgroep staat voor de individuele inkoper of het team van inkopers dat verantwoordelijk is voor een bepaalde inkoopactiviteit. Zij zijn het belangrijkste aanspreekpunt voor leveranciers. Dit attribuut biedt een gedetailleerder analyseniveau dan de inkooporganisatie. Je krijgt inzicht in de werkverdeling tussen inkopers en ziet prestatieverschillen op inkoperniveau. Dat helpt bij het verdelen van capaciteit en het bepalen van trainingsbehoeften. Waarom dit belangrijk is Geeft een gedetailleerd beeld van wie verantwoordelijk is voor een aankoop. Zo kun je werkbelasting en prestaties per inkoper of team analyseren. Waar je het vindt Tabel: EKKO, veld: EKGRP Voorbeelden 001002N01 | |||
| Inkooporganisatie PurchasingOrganization | De organisatorische eenheid die verantwoordelijk is voor het onderhandelen over prijzen en het inkopen van materialen of diensten. | ||
| Beschrijving De inkooporganisatie is een belangrijke organisatorische eenheid in SAP die verantwoordelijk is voor inkoopactiviteiten. Deze kan voor het hele bedrijf centraal zijn ingericht of per fabriek of regio decentraal worden georganiseerd. Door procesprestaties per inkooporganisatie te analyseren, zie je welke inkoopteams het efficiëntst werken. Je kunt KPI’s zoals doorlooptijd, herstelwerkpercentages en kosten tussen organisatorische eenheden vergelijken. Zo ontdek je best practices en onderdelen die ondersteuning nodig hebben. Waarom dit belangrijk is Identificeert het verantwoordelijke inkoopteam en maakt prestatievergelijkingen en analyses tussen verschillende organisatorische eenheden mogelijk. Waar je het vindt Tabel: EKKO, veld: EKORG Voorbeelden 1000US01DE01 | |||
| Is wijziging na goedkeuring IsPostApprovalChange | Een vlag die aangeeft of er na de eerste goedkeuring een wijziging in een PO heeft plaatsgevonden. | ||
| Beschrijving Dit booleaanse attribuut is waar als voor dezelfde PO een activiteit 'Purchase Order Changed' wordt gedetecteerd na een activiteit 'Purchase Order Approved'. Hiermee kun je problematische wijzigingen isoleren die laat in het proces plaatsvinden. Dit berekende veld ondersteunt rechtstreeks de KPI 'Post-Approval PO Change Rate' en het dashboard 'Purchase Order Rework and Changes'. Hiermee kun je ingrijpende wijzigingen kwantificeren en zichtbaar maken. Zulke wijzigingen kunnen vertraging veroorzaken en opnieuw goedkeuring vereisen. Ze wijzen vaak op problemen in de eerste specificatie of afbakening van het proces. Waarom dit belangrijk is Meet rechtstreeks hoeveel herstelwerk er na goedkeuring nodig is. Dit is een belangrijke KPI voor processtabiliteit en efficiëntie. Hoge percentages wijzen op problemen in de voorafgaande definitie van de vereisten. Waar je het vindt Dit is een berekend attribuut dat is afgeleid van de volgorde van activiteiten in het event log. Voorbeelden truefalse | |||
| Laatste data-update LastDataUpdate | De timestamp die aangeeft wanneer de data voor het laatst vanuit het bronsysteem is vernieuwd. | ||
| Beschrijving Dit attribuut registreert de datum en tijd van de meest recente data-extractie of update. Zo zie je hoe actueel de geanalyseerde data is. Door deze informatie in dashboards te tonen, begrijpen gebruikers of de inzichten zijn gebaseerd op data die bijna realtime is of op een historische momentopname. Dat maakt verwachtingen duidelijk en helpt om beslissingen te nemen op basis van data waarvan de ouderdom bekend is. Waarom dit belangrijk is Laat gebruikers zien hoe actueel de data is, zodat ze weten of de analyse de meest recente stand van de bedrijfsvoering weergeeft. Waar je het vindt Deze timestamp wordt door het data-extractie- of ETL-proces gegenereerd en toegevoegd wanneer het proces wordt uitgevoerd. Voorbeelden 2023-10-27T02:00:00Z2023-10-28T02:00:00Z | |||
| Leveranciersnaam VendorName | De wettelijke naam van de leverancier. | ||
| Beschrijving De beschrijvende naam van de leverancier, die gebruiksvriendelijker is dan het leveranciersnummer. Deze naam komt doorgaans uit de leveranciersstamdata. Het leveranciersnummer gebruik je voor koppelingen en unieke identificatie. De leveranciersnaam is vooral belangrijk in dashboards en rapporten voor gebruikers. Analyses worden begrijpelijker voor zakelijke gebruikers die de leverancierscodes niet kennen. Waarom dit belangrijk is Geeft de leverancier een leesbare naam, waardoor dashboards en rapporten voor zakelijke gebruikers veel makkelijker te begrijpen zijn. Waar je het vindt Tabel: LFA1, veld: NAME1. Hiervoor is een koppeling nodig van EKKO-LIFNR naar LFA1-LIFNR. Voorbeelden Staples Inc.Global Tech SolutionsOffice Supply Co. | |||
| Op tijd geleverd IsOnTimeDelivery | Een vlag die aangeeft of de goederen op of vóór de gevraagde leverdatum zijn ontvangen. | ||
| Beschrijving Dit booleaanse attribuut is waar als de timestamp van de activiteit 'Goods Receipt Posted' op of vóór de 'Requested Delivery Date' ligt. Het geeft per PO-regel een duidelijke binaire uitkomst voor de leverprestatie. Dit attribuut vormt de basis voor de KPI 'On-Time Goods Receipt Rate'. Het vereenvoudigt de analyse van leveranciersprestaties en de efficiëntie van de interne ontvangst, omdat je leveringen op tijd en te late leveringen eenvoudig kunt groeperen en filteren. Waarom dit belangrijk is Geeft een duidelijke maatstaf voor succes of mislukking van tijdige levering en ondersteunt rechtstreeks KPI's en dashboards voor leveranciersprestaties. Waar je het vindt Dit is een berekend attribuut dat ontstaat door de boekingsdatum van de goederenontvangst (EKBE-BUDAT) te vergelijken met de gevraagde leverdatum (EKPO-EINDT). Voorbeelden truefalse | |||
| Reden van afwijzing RejectionReason | De code of tekst die uitlegt waarom een inkoopaanvraag of bestelling is afgewezen. | ||
| Beschrijving Dit attribuut legt de specifieke reden vast die is opgegeven toen een inkooporder tijdens de goedkeuringsworkflow werd afgewezen. Deze informatie is belangrijk om de oorzaken van herstelwerk en vertragingen te begrijpen. Door afwijsredenen te analyseren, zie je veelvoorkomende problemen zoals onjuiste prijzen, budgetoverschrijdingen of een leverancierskeuze die niet aan de compliance-eisen voldoet. Met dit inzicht kan de organisatie de oorzaken aanpakken, de kwaliteit van de eerste PO-aanmaak verbeteren en het goedkeuringsproces efficiënter maken. Waarom dit belangrijk is Geeft direct inzicht in waarom goedkeuringen mislukken. Zo kun je gerichte verbeteringen doorvoeren, herstelwerk verminderen en goedkeuringsdoorlooptijden verkorten. Waar je het vindt Deze informatie kan lastig te vinden zijn. Ze kan zijn opgeslagen in lange tekstvelden of afhankelijk zijn van een aangepaste workflowconfiguratie. Vaak is specifieke kennis van de implementatie nodig. Voorbeelden Onjuiste prijsBudget overschredenDubbel verzoek | |||
| Valuta Currency | De valutacode voor het bedrag van de inkooporder. | ||
| Beschrijving Dit attribuut geeft aan in welke valuta de waarde van de inkooporder is uitgedrukt, zoals USD, EUR of GBP. Het biedt de nodige context voor geldbedragen. Voor internationale organisaties is valuta essentieel voor een correcte financiële analyse. Je kunt orderwaarden goed optellen en vergelijken. Alle financiële KPI’s moeten worden geïnterpreteerd in de context van de gebruikte valuta. Waarom dit belangrijk is Biedt de nodige context voor alle geldbedragen en zorgt voor een correcte financiële analyse, vooral bij multinationale organisaties. Waar je het vindt Tabel: EKKO, veld: WAERS Voorbeelden USDEURJPY | |||
| Vestiging Plant | De fysieke locatie of vestiging waar de goederen worden geleverd. | ||
| Beschrijving De vestiging is een organisatorische eenheid die staat voor een productielocatie, magazijn of andere locatie waar goederen of diensten worden ontvangen. Door per vestiging te analyseren, zie je geografische verschillen in het inkoopproces. Zo ontdek je verschillen in levertijden van leveranciers naar bepaalde locaties of vestigingen met inefficiënte ontvangstprocessen. Dit ondersteunt analyses van de tijdigheid van goederenontvangsten. Waarom dit belangrijk is Geeft de leverlocatie aan. Dat is nuttig voor het analyseren van regionale procesverschillen en logistieke prestaties. Waar je het vindt Tabel: EKPO, veld: WERKS Voorbeelden 100011002000 | |||
Purchase to Pay - Purchase Order-activiteiten
| Activiteit | Beschrijving | ||
|---|---|---|---|
| Goederenontvangst geboekt | Deze activiteit staat voor de fysieke ontvangst van goederen van een leverancier voor een specifieke inkooporder. Het boeken van de goederenontvangst is een expliciete handeling, bijvoorbeeld via transactie MIGO, die een materiaaldocument aanmaakt en de voorraad bijwerkt. | ||
| Waarom dit belangrijk is Dit is een belangrijk meetpunt voor het volgen van de leverprestaties van de leverancier en het starten van het factuurcontroleproces. Je gebruikt deze gebeurtenis om het percentage tijdige leveringen en de tijdigheid van de goederenontvangst te berekenen. Waar je het vindt Wordt vastgelegd wanneer een materiaaldocument wordt aangemaakt. De timestamp van de gebeurtenis is de boekingsdatum (MKPF-BUDAT) of aanmaakdatum (MKPF-CPUDT) uit de koptekstabel van het materiaaldocument, MKPF, gekoppeld aan de inkooporder via de itemtabel MSEG. Vastleggen Gebruik de boekings- of aanmaaktimestamp uit de tabel MKPF voor materiaaldocumenten die naar de inkooporder verwijzen. Eventtype explicit | |||
| Inkoopaanvraag aangemaakt | Deze activiteit markeert het aanmaken van een formeel verzoek voor goederen of diensten. Het is een expliciete gebeurtenis die wordt vastgelegd wanneer een gebruiker een nieuwe inkoopaanvraag opslaat, bijvoorbeeld met transactie ME51N. Daarbij ontstaat een unieke record in de tabel EBAN. | ||
| Waarom dit belangrijk is Dit is het belangrijkste startpunt van het inkoopproces. Door de tijd tussen deze gebeurtenis en het aanmaken van de inkooporder te analyseren, meet je hoe efficiënt interne vraag wordt omgezet in uitvoerbare orders. Waar je het vindt Wordt vastgelegd wanneer een record wordt aangemaakt in de koptekstabel van de inkoopaanvraag, EBAN. De aanmaakdatum (EBAN-BADAT) en -tijd vormen de timestamp van deze gebeurtenis. Vastleggen Identificeer nieuwe records in de tabel EBAN op basis van de aanmaakdatum. Eventtype explicit | |||
| Inkooporder aangemaakt | Deze activiteit staat voor het aanmaken van een formele inkooporder, die een bindend contract met een leverancier vormt. Het is een expliciete gebeurtenis die wordt gelogd wanneer een gebruiker een inkooporder aanmaakt en opslaat, bijvoorbeeld via transactie ME21N. Dit leidt tot records in de tabellen EKKO en EKPO. | ||
| Waarom dit belangrijk is Dit markeert de officiële start van de levenscyclus van de inkooporder. Het is een belangrijk meetpunt voor zowel de doorlooptijd van inkoopaanvraag naar inkooporder als de totale doorlooptijd van order tot levering. Waar je het vindt Wordt vastgelegd op basis van de aanmaakdatum (EKKO-AEDAT) in de koptekstabel van de inkooporder, EKKO, voor het bijbehorende inkoopordernummer (EKKO-EBELN). Vastleggen Gebruik de aanmaaktimestamp uit de tabel EKKO voor elke nieuwe inkooporder. Eventtype explicit | |||
| Inkooporder goedgekeurd | Dit staat voor de definitieve goedkeuring van de inkooporder, waarmee deze naar de leverancier mag worden gestuurd. Dit belangrijke meetpunt wordt doorgaans afgeleid uit een wijziging van de vrijgavestatus van de inkooporder naar ‘volledig vrijgegeven’ of ‘goedgekeurd’. | ||
| Waarom dit belangrijk is Deze activiteit is belangrijk voor het berekenen van de KPI voor de goedkeuringsdoorlooptijd van de inkooporder en voor het vinden van knelpunten in de goedkeuringsworkflow. Voor de meeste vervolgstappen, zoals het versturen van de order naar de leverancier, is deze goedkeuring vereist. Waar je het vindt Afgeleid door de wijzigingslogboeken (CDHDR/CDPOS) voor de koptekstabel van de inkooporder, EKKO, te volgen. Zo bepaal je wanneer de definitieve vrijgavecode wordt toegepast of wanneer de algemene vrijgavestatusindicator (EKKO-FRGKE) op ‘vrijgegeven’ wordt gezet. Vastleggen Bepaal de timestamp waarop de algemene vrijgavestatus van de inkooporder (EKKO-FRGKE) verandert naar de definitieve goedgekeurde status. Eventtype inferred | |||
| Inkooporder naar leverancier verstuurd | Deze activiteit markeert het moment waarop de goedgekeurde inkooporder officieel naar de leverancier wordt verstuurd, bijvoorbeeld via EDI, e-mail of print. Het is een expliciete gebeurtenis die wordt vastgelegd in de tabellen voor berichtbeheer wanneer een uitvoerbericht succesvol is verwerkt. | ||
| Waarom dit belangrijk is Dit is een belangrijk meetpunt en het startpunt voor de doorlooptijd bij de leverancier. Door de tijd tussen deze gebeurtenis en de goederenontvangst te analyseren, meet je de prestaties van de leverancier en de tijdigheid van leveringen. Waar je het vindt Wordt vastgelegd in de tabel voor berichtstatussen, NAST. De timestamp kan worden gehaald uit NAST-DATVR en NAST-UHRVR wanneer de verwerkingsstatus (NAST-VSTAT) voor het relevante uitvoertype van de inkooporder ‘1’ is, oftewel succesvol verwerkt. Vastleggen Gebruik de verwerkingstimestamp uit de tabel NAST voor het uitvoerbericht van de inkooporder. Eventtype explicit | |||
| Inkooporder voltooid | Geeft aan dat een item van een inkooporder volledig is geleverd. Het is een afgeleide gebeurtenis, doorgaans gebaseerd op de indicator ‘Levering voltooid’ die automatisch of handmatig op het item van de inkooporder wordt ingesteld. | ||
| Waarom dit belangrijk is Deze activiteit vormt het logische eindpunt van het orderfulfillmentgedeelte van het proces. De activiteit is belangrijk voor het berekenen van de totale doorlooptijd van de inkooporder, van aanmaak tot voltooiing. Waar je het vindt Afgeleid uit de wijzigingsdocumenten (CDHDR/CDPOS) die vastleggen wanneer de indicator ‘Levering voltooid’ (EKPO-ELIKZ) voor een item van de inkooporder op ‘X’ wordt gezet. Wanneer het laatste item als voltooid wordt gemarkeerd, kan dat betekenen dat de volledige inkooporder is afgerond. Vastleggen Bepaal de timestamp uit de wijzigingsdocumenten waarop de vlag EKPO-ELIKZ wordt ingesteld. Eventtype inferred | |||
| Dienstenbevestiging ingevoerd | Voor inkooporders voor diensten staat deze activiteit voor de bevestiging dat de diensten zijn geleverd. Het is een expliciete gebeurtenis die wordt vastgelegd bij het aanmaken van een service-entry sheet, bijvoorbeeld via transactie ML81N. | ||
| Waarom dit belangrijk is Dit is het equivalent van een goederenontvangst voor diensten en is belangrijk om de uitvoering van dienstenorders te volgen. De gebeurtenis start het financiële proces voor de betaling van de dienst. Waar je het vindt Wordt vastgelegd op basis van de aanmaakdatum (ESSR-ERDAT) in de koptekstabel van de service-entry sheet, ESSR. De koppeling met de inkooporder staat in de tabel ESLL. Vastleggen Gebruik de aanmaaktimestamp uit de tabel ESSR voor service-entry sheets die aan de inkooporder zijn gekoppeld. Eventtype explicit | |||
| Goederen geretourneerd | Dit staat voor het terugsturen van eerder ontvangen goederen naar de leverancier, vaak vanwege kwaliteitsproblemen of een verkeerde levering. Het is een expliciete gebeurtenis die wordt vastgelegd door een materiaaldocument te boeken met een specifiek retourbewegingstype. | ||
| Waarom dit belangrijk is Deze activiteit maakt problemen met de kwaliteit van de leverancier of de juistheid van de order zichtbaar en is een belangrijke indicator voor herstelwerk in het proces. De activiteit is belangrijk voor het berekenen van de KPI voor het afwijkingspercentage van goederenontvangsten. Waar je het vindt Wordt vastgelegd in de tabellen voor materiaaldocumenten (MKPF/MSEG) wanneer een retourbewegingstype wordt gebruikt, bijvoorbeeld ‘122’ voor retourlevering aan de leverancier. De boekingsdatum (MKPF-BUDAT) vormt de timestamp. Vastleggen Identificeer materiaaldocumenten met een retourbewegingstype, bijvoorbeeld 122, die naar de oorspronkelijke inkooporder verwijzen. Eventtype explicit | |||
| Goedkeuring inkooporder aangevraagd | Geeft aan dat een aangemaakte of gewijzigde inkooporder ter goedkeuring is ingediend volgens de geconfigureerde vrijgavestrategie. Deze gebeurtenis wordt afgeleid wanneer de vrijgavestrategie wordt geactiveerd en de inkooporder de status ‘wacht op goedkeuring’ krijgt. | ||
| Waarom dit belangrijk is Door het aanmaken van de inkooporder te onderscheiden van de start van het goedkeuringsproces, meet je de KPI voor de goedkeuringsdoorlooptijd nauwkeuriger. Zo wordt zichtbaar hoeveel tijd verstrijkt voordat de goedkeuringsworkflow begint. Waar je het vindt Afgeleid uit wijzigingsdocumenten (CDHDR/CDPOS) voor de inkooporder, object EINKBELEG. Deze laten zien wanneer een vrijgavestatus voor het eerst wordt ingesteld, of wanneer de algemene vrijgavestatus (EKKO-FRGKE) voor het eerst een waarde krijgt die aangeeft dat een goedkeuringsproces actief is. Vastleggen Identificeer de eerste record in de wijzigingsdocumenten die de vrijgavestrategie voor de inkooporder activeert. Eventtype inferred | |||
| Inkoopaanvraag goedgekeurd | Dit staat voor de formele goedkeuring van een inkoopaanvraag, waarmee deze mag worden omgezet in een inkooporder. De gebeurtenis wordt afgeleid uit wijzigingen in de vrijgavestatusvelden van de inkoopaanvraag, zoals bijgehouden door de vrijgaveworkflow van SAP. | ||
| Waarom dit belangrijk is Door goedkeuringen te volgen, zie je knelpunten in de fase vóór het bestellen en controleer je of het proces aan het goedkeuringsbeleid voldoet. Vertragingen in deze fase hebben direct invloed op de totale doorlooptijd van het inkoopproces. Waar je het vindt Afgeleid uit de wijzigingslogboeken voor de tabel met inkoopaanvragen, EBAN. Hierbij worden specifiek wijzigingen in de vrijgavestatusvelden gevolgd, zoals EBAN-FRGZU, of wijzigingsdocumenten in CDHDR/CDPOS voor het EBAN-object geanalyseerd. Vastleggen Monitor wijzigingsdocumenten voor de vrijgavestatusvelden van EBAN om de timestamp van de definitieve goedkeuring te bepalen. Eventtype inferred | |||
| Inkooporder afgewezen | Deze activiteit vindt plaats wanneer een goedkeurder een inkooporder tijdens de goedkeuringsworkflow afwijst. Het is een afgeleide gebeurtenis, gebaseerd op een statuswijziging in de gegevens van de vrijgavestrategie van de inkooporder die aangeeft dat de order is afgewezen. | ||
| Waarom dit belangrijk is Door afwijzingen te volgen, zie je problemen met de datakwaliteit van inkooporders, niet-naleving van beleid of problemen in de goedkeuringsmatrix. Afwijzingen leiden vaak tot herstelwerk en verhogen de totale doorlooptijd. Waar je het vindt Afgeleid uit wijzigingsdocumenten (CDHDR/CDPOS) voor de vrijgavestatus van de inkooporder. Een afwijzing wordt doorgaans vastgelegd wanneer een vrijgavecode wordt geannuleerd of een specifieke afwijzingsstatus wordt ingesteld. Vastleggen Monitor wijzigingslogboeken op het annuleren van een vrijgavecode of een statuswijziging die op een afwijzing wijst. Eventtype inferred | |||
| Inkooporder gewijzigd | Dit staat voor elke wijziging aan een inkooporder na het oorspronkelijke aanmaken, zoals wijzigingen in hoeveelheid, prijs of leverdatum. Deze wijzigingen worden expliciet vastgelegd in het SAP-systeem voor wijzigingsdocumenten. | ||
| Waarom dit belangrijk is Veel wijzigingen, vooral na goedkeuring, wijzen op inefficiënte processen, een gebrekkige planning vooraf of scope creep. Deze activiteit is belangrijk voor het dashboard voor herstelwerk en wijzigingen in inkooporders en de bijbehorende KPI’s. Waar je het vindt Wordt expliciet vastgelegd in de koptekstabel (CDHDR) en itemtabel (CDPOS) van de wijzigingsdocumenten voor het inkooporderobject (EINKBELEG). Elke wijziging maakt een nieuwe record met een timestamp aan. Vastleggen Extraheer wijzigingsgebeurtenissen en timestamps uit de tabellen CDHDR en CDPOS die aan het inkoopordernummer zijn gekoppeld. Eventtype explicit | |||
| Inkooporder verwijderd | Dit staat voor het annuleren of logisch verwijderen van een item van een inkooporder, waardoor verdere verwerking, zoals goederenontvangsten of facturatie, wordt voorkomen. Het is een afgeleide gebeurtenis die wordt vastgelegd wanneer de verwijderingsindicator op het item van de inkooporder wordt ingesteld. | ||
| Waarom dit belangrijk is Dit is een eindactiviteit die aangeeft dat een order is geannuleerd. Door te analyseren waarom en wanneer orders worden verwijderd, ontdek je problemen in de vraagplanning of leveranciersselectie. Waar je het vindt Afgeleid uit wijzigingsdocumenten (CDHDR/CDPOS) die laten zien dat de verwijderingsindicator (EKPO-LOEKZ) voor een item van de inkooporder op ‘L’ is gezet. Vastleggen Bepaal de timestamp uit de wijzigingsdocumenten waarop de vlag EKPO-LOEKZ wordt ingesteld. Eventtype inferred | |||
| Kwaliteitsinspectie uitgevoerd | Geeft aan dat ontvangen goederen een kwaliteitsinspectie hebben ondergaan. Deze activiteit wordt doorgaans afgeleid wanneer voor een inspectielot, dat bij de goederenontvangst is aangemaakt, een gebruiksbeslissing wordt genomen in de module Quality Management. | ||
| Waarom dit belangrijk is In sectoren waar kwaliteit zwaar weegt, helpt deze activiteit om de duur en resultaten van het inspectieproces te analyseren. Vertragingen in deze fase kunnen een knelpunt veroorzaken tussen goederenontvangst en beschikbaarheid voor gebruik. Waar je het vindt Afgeleid uit de module Quality Management. Bij de goederenontvangst wordt een inspectielot aangemaakt in de tabel QALS. De activiteit wordt gemarkeerd door het aanmaken van een gebruiksbeslissing in de tabel QAVE, inclusief timestamp. Vastleggen Bepaal de timestamp van de gebruiksbeslissing in tabel QAVE voor het inspectielot dat aan het materiaaldocument is gekoppeld. Eventtype inferred | |||
Extractiegidsen
Stappen
- ABAP-programma maken: Open de ABAP Editor met transact code SE38. Geef je nieuwe programma een naam, bijvoorbeeld Z_PM_PO_EXTRACT, en klik op 'Create'. Geef het programma een titel, zoals 'Process Mining PO Data Extraction', en stel het type in op 'Executable Program'.
- Selectiescherm definiëren: Definieer in het programma de parameters voor het selectiescherm. Hiermee kunnen gebruikers de data filteren die ze willen extraheren. Belangrijke parameters zijn het datumbereik voor het aanmaken van de Purchase Order, de Company Code (BUKRS) en het Purchasing Document Type (BSART).
- Datastructuren definiëren: Declareer een interne tabelstructuur die overeenkomt met het uiteindelijke event-logformaat. Neem alle vereiste en aanbevolen attributen op: PurchaseOrder, Activity, EventTime, UserName, VendorNumber, OrderAmount, MaterialGroup, CompanyCode en DocumentType.
- Logica voor dataselectie implementeren: Schrijf de kernlogica in ABAP om data voor elk van de 14 vereiste activiteiten te selecteren. Hiervoor moet je meerdere SAP-tabellen raadplegen, zoals EKKO, EKPO, EKBE, EBAN, CDHDR, CDPOS en NAST. Gebruik voor elke activiteit een aparte subroutine (PERFORM), zodat de code overzichtelijk blijft.
- Data voor Purchase Requisition selecteren: Raadpleeg de tabel EBAN voor gebeurtenissen 'Purchase Requisition Created' en koppel deze via de tabel EKPO aan Purchase Orders. Gebruik de wijzigingslogtabellen (CDHDR, CDPOS) om gebeurtenissen 'Purchase Requisition Approved' te vinden door wijzigingen in de vrijgavestatusvelden te volgen.
- Kerngebeurtenissen van de Purchase Order selecteren: Raadpleeg de tabellen EKKO en EKPO voor de gebeurtenis 'Purchase Order Created'. Gebruik de wijzigingslogtabellen (CDHDR, CDPOS) voor object EINKBELEG om gebeurtenissen 'Purchase Order Changed', 'Purchase Order Approved', 'Purchase Order Rejected', 'Purchase Order Completed' en 'Purchase Order Deleted' te extraheren. Baseer dit op wijzigingen in specifieke velden, zoals vrijgave-indicatoren en verwijderingsvlaggen.
- Communicatiegebeurtenissen van de PO selecteren: Raadpleeg de tabel NAST om records te vinden waarin de PO succesvol is verzonden. Leg de activiteit 'Purchase Order Sent to Vendor' vast.
- Gebeurtenissen voor goederen en diensten selecteren: Raadpleeg de tabel EKBE voor boekingen van materiaaldocumenten. Gebruik de categorie van het bewegingstype om de activiteiten 'Goods Receipt Posted' en 'Goods Returned' te vinden. Raadpleeg ESSR en ESLL voor service entry sheets en leg de activiteit 'Services Confirmation Entered' vast.
- Gebeurtenissen voor kwaliteitsbeheer selecteren: Als de module Quality Management wordt gebruikt, raadpleeg je de tabellen QALS en QAVE om te bepalen wanneer een gebruiksbeslissing is genomen voor een inspectielot dat aan een PO is gekoppeld. Dit staat voor de activiteit 'Quality Inspection Performed'.
- Data combineren en opmaken: Voeg de data uit alle afzonderlijke selecties samen in één definitieve interne tabel. Zorg dat het veld EventTime overal dezelfde indeling gebruikt, bijvoorbeeld YYYY-MM-DDTHH:MI:SS.
- Bestandsdownload implementeren: Voeg functionaliteit toe om de definitieve interne tabel als bestand te downloaden. Gebruik bij voorkeur een tabgescheiden bestand of CSV-bestand. Dat kan met de functiemodule GUI_DOWNLOAD.
- Uitvoeren en opslaan: Voer het programma uit met transactie SE38 of SA38. Vul de selectiecriteria in en voer het rapport uit. Sla het uitvoerbestand op je lokale computer op met de extensie .csv. Het bestand is daarna klaar om te uploaden.
Configuratie
- Datumbereik: Het is belangrijk om voor de extractie een specifiek datumbereik in te stellen, meestal op basis van de aanmaakdatum van de Purchase Order (EKKO-AEDAT). Een periode van 3 tot 6 maanden is vaak een goed startpunt om de hoeveelheid data en de bruikbaarheid van de analyse in balans te houden.
- Company Code (BUKRS): Filter op een of meer company codes om de extractie te beperken tot relevante juridische entiteiten. Dit is belangrijk voor de prestaties en relevantie van de analyse.
- Purchasing Document Type (BSART): Filter op specifieke documenttypen, bijvoorbeeld 'NB' voor een standaard-PO, om je te richten op standaardprocessen. Sluit indien nodig bijzondere inkooptypen uit.
- Detailniveau van de data: De extractie is ontworpen op het niveau van de Purchase-Order-regel. De Case ID is het Purchase-Order-nummer (EBELN). Alle gebeurtenissen, ook gebeurtenissen op regelniveau zoals goederenontvangsten, worden aan deze hoofd-case-ID gekoppeld.
- Aandacht voor prestaties: Plan het programma bij grote datasets als achtergrondtaak (SM36) om time-outs te voorkomen. Controleer of er database-indexen bestaan op belangrijke velden in WHERE-clausules, vooral voor tabellen zoals CDHDR en CDPOS.
- Vereisten vooraf: De gebruiker die het rapport uitvoert, heeft autorisatie nodig voor de ABAP-workbench (SE38), plus uitvoeringsrechten voor het programma. Ook is leestoegang nodig tot alle onderliggende tabellen, waaronder EKKO, EKPO, EKBE, CDHDR, CDPOS, EBAN, NAST, ESSR en QM-tabellen.
a Voorbeeldquery abap
REPORT Z_PM_PO_EXTRACT.
TABLES: ekko, ekpo, eban.
*&---------------------------------------------------------------------*
*& Data Structures for Event Log
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
purchaseorder TYPE ebeln,
activity TYPE string,
eventtime TYPE timestamp,
username TYPE ernam,
vendornumber TYPE lifnr,
orderamount TYPE netwr_ak,
materialgroup TYPE matkl,
companycode TYPE bukrs,
documenttype TYPE bsart,
END OF ty_event_log.
DATA: gt_event_log TYPE TABLE OF ty_event_log.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_aedat FOR ekko-aedat OBLIGATORY, " PO Creation Date
s_bukrs FOR ekko-bukrs, " Company Code
s_bsart FOR ekko-bsart, " PO Document Type
s_ebeln FOR ekko-ebeln. " PO Number
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM get_po_headers.
IF gt_event_log IS NOT INITIAL.
PERFORM get_pr_created.
PERFORM get_pr_approved.
PERFORM get_po_created.
PERFORM get_po_release_events. " Approved, Rejected, Approval Requested
PERFORM get_po_sent_to_vendor.
PERFORM get_po_changed.
PERFORM get_goods_receipt_posted.
PERFORM get_services_confirmed.
PERFORM get_quality_inspection.
PERFORM get_goods_returned.
PERFORM get_po_completed.
PERFORM get_po_deleted.
PERFORM download_to_csv.
ELSE.
MESSAGE 'No Purchase Orders found for the given criteria.' TYPE 'I'.
ENDIF.
*&---------------------------------------------------------------------*
*& Form GET_PO_HEADERS (Base data)
*&---------------------------------------------------------------------*
FORM get_po_headers.
SELECT h~ebeln, h~lifnr, h~bukrs, h~bsart, p~netwr, p~matkl
FROM ekko AS h
INNER JOIN ekpo AS p ON h~ebeln = p~ebeln
INTO TABLE @DATA(lt_po_base)
WHERE h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND h~bsart IN @s_bsart
AND h~ebeln IN @s_ebeln.
SORT lt_po_base BY ebeln.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PR_CREATED
*&---------------------------------------------------------------------*
FORM get_pr_created.
DATA: lt_pr_events TYPE TABLE OF ty_event_log.
SELECT p~ebeln AS purchaseorder,
'Purchase Requisition Created' AS activity,
b~erdat AS event_date,
'000000' AS event_time,
b~ernam AS username,
h~lifnr AS vendornumber,
p~netwr AS orderamount,
p~matkl AS materialgroup,
h~bukrs AS companycode,
h~bsart AS documenttype
FROM ekpo AS p
JOIN eban AS b ON p~banfn = b~banfn AND p~bnfpo = b~bnfpo
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE p~ebeln IN @s_ebeln
AND p~banfn IS NOT NULL AND p~banfn <> ''
AND h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND h~bsart IN @s_bsart
INTO TABLE @DATA(lt_pr_created).
LOOP AT lt_pr_created ASSIGNING FIELD-SYMBOL(<fs_pr>).
DATA(ls_event) = CORRESPONDING ty_event_log(<fs_pr>).
CONCATENATE <fs_pr>-event_date <fs_pr>-event_time INTO DATA(lv_ts).
CONVERT DATE <fs_pr>-event_date TIME '000000' INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PR_APPROVED
*&---------------------------------------------------------------------*
FORM get_pr_approved.
DATA: lt_pr_list TYPE TABLE OF eban-banfn.
SELECT DISTINCT p~banfn FROM ekpo AS p
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND p~banfn IS NOT NULL AND p~banfn <> ''
INTO TABLE @lt_pr_list.
IF lt_pr_list IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime, p~fname, p~value_new
FROM cdhdr AS h
JOIN cdpos AS p ON h~objectid = p~objectid AND h~changenr = p~changenr
FOR ALL ENTRIES IN @lt_pr_list
WHERE h~objectclas = 'BANF'
AND h~objectid = @lt_pr_list-table_line
AND p~tabname = 'EBAN'
AND p~fname = 'FRGZU'
INTO TABLE @DATA(lt_cd_pr).
LOOP AT lt_cd_pr ASSIGNING FIELD-SYMBOL(<fs_cd>) WHERE <fs_cd>-value_new = 'X'.
SELECT SINGLE p~ebeln, p~netwr, p~matkl, h~lifnr, h~bukrs, h~bsart
FROM ekpo AS p
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE p~banfn = @<fs_cd>-objectid(10)
INTO @DATA(ls_po_info).
IF sy-subrc = 0.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = ls_po_info-ebeln
activity = 'Purchase Requisition Approved'
username = <fs_cd>-username
vendornumber = ls_po_info-lifnr
orderamount = ls_po_info-netwr
materialgroup = ls_po_info-matkl
companycode = ls_po_info-bukrs
documenttype = ls_po_info-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_CREATED
*&---------------------------------------------------------------------*
FORM get_po_created.
LOOP AT lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>).
SELECT SINGLE aedat, ernam FROM ekko INTO @DATA(ls_ekko)
WHERE ebeln = @<fs_po>-ebeln.
IF sy-subrc = 0.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Created'
username = ls_ekko-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE ls_ekko-aedat TIME '000000' INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_RELEASE_EVENTS
*&---------------------------------------------------------------------*
FORM get_po_release_events.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime, p~value_new
FROM cdhdr AS h
JOIN cdpos AS p ON h~objectid = p~objectid AND h~changenr = p~changenr
WHERE h~objectclas = 'EINKBELEG'
AND h~objectid IN lt_ebeln
AND p~tabname = 'EKKO'
AND p~fname = 'FRGKE'
INTO TABLE @DATA(lt_cd_po).
LOOP AT lt_cd_po ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
CASE <fs_cd>-value_new.
WHEN '2' OR 'R'. " Final Release
ls_event-activity = 'Purchase Order Approved'.
WHEN '1'. " Blocked
ls_event-activity = 'Purchase Order Rejected'.
WHEN OTHERS. " Any other change implies a pending state
ls_event-activity = 'Purchase Order Approval Requested'.
ENDCASE.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_SENT_TO_VENDOR
*&---------------------------------------------------------------------*
FORM get_po_sent_to_vendor.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT objky, erdat, eruhr, ernam
FROM nast
WHERE kapol = 'EF' AND objky IN lt_ebeln AND vstat = '1'
INTO TABLE @DATA(lt_nast).
LOOP AT lt_nast ASSIGNING FIELD-SYMBOL(<fs_nast>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_nast>-objky.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Sent to Vendor'
username = <fs_nast>-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_nast>-erdat TIME <fs_nast>-eruhr INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_CHANGED
*&---------------------------------------------------------------------*
FORM get_po_changed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT DISTINCT objectid, username, udate, utime
FROM cdhdr
WHERE objectclas = 'EINKBELEG' AND objectid IN lt_ebeln AND tcode <> 'ME21N' AND tcode <> 'ME22'
INTO TABLE @DATA(lt_cdhdr_chg).
LOOP AT lt_cdhdr_chg ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Changed'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_GOODS_RECEIPT_POSTED
*&---------------------------------------------------------------------*
FORM get_goods_receipt_posted.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT k~ebeln, m~cpudt, m~cputm, m~usnam, k~bewtp
FROM ekbe AS k JOIN mkpf AS m ON k~belnr = m~mblnr AND k~gjahr = m~mjahr
WHERE k~ebeln IN lt_ebeln AND k~bewtp = 'E' AND k~shkzg = 'S'
INTO TABLE @DATA(lt_gr).
LOOP AT lt_gr ASSIGNING FIELD-SYMBOL(<fs_gr>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_gr>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Goods Receipt Posted'
username = <fs_gr>-usnam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_gr>-cpudt TIME <fs_gr>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_SERVICES_CONFIRMED
*&---------------------------------------------------------------------*
FORM get_services_confirmed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT l~ebeln, h~erdat, h~eruhr, h~ernam
FROM essr AS h JOIN esll AS l ON h~lblni = l~lblni
WHERE l~ebeln IN lt_ebeln
INTO TABLE @DATA(lt_ses).
LOOP AT lt_ses ASSIGNING FIELD-SYMBOL(<fs_ses>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_ses>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Services Confirmation Entered'
username = <fs_ses>-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_ses>-erdat TIME <fs_ses>-eruhr INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_QUALITY_INSPECTION
*&---------------------------------------------------------------------*
FORM get_quality_inspection.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT q~ebeln, v~vdatum, v~vzeit, v~vname
FROM qals AS q JOIN qave AS v ON q~prueflos = v~prueflos
WHERE q~ebeln IN lt_ebeln
INTO TABLE @DATA(lt_qm).
LOOP AT lt_qm ASSIGNING FIELD-SYMBOL(<fs_qm>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_qm>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Quality Inspection Performed'
username = <fs_qm>-vname
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_qm>-vdatum TIME <fs_qm>-vzeit INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_GOODS_RETURNED
*&---------------------------------------------------------------------*
FORM get_goods_returned.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT k~ebeln, m~cpudt, m~cputm, m~usnam
FROM ekbe AS k JOIN mkpf AS m ON k~belnr = m~mblnr AND k~gjahr = m~mjahr
WHERE k~ebeln IN lt_ebeln AND k~bwart = '122'
INTO TABLE @DATA(lt_ret).
LOOP AT lt_ret ASSIGNING FIELD-SYMBOL(<fs_ret>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_ret>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Goods Returned'
username = <fs_ret>-usnam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_ret>-cpudt TIME <fs_ret>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_COMPLETED
*&---------------------------------------------------------------------*
FORM get_po_completed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime
FROM cdhdr AS h JOIN cdpos AS p ON h~changenr = p~changenr AND h~objectid = p~objectid
WHERE h~objectclas = 'EINKBELEG' AND h~objectid IN lt_ebeln AND p~tabname = 'EKPO' AND p~fname = 'ELIKZ' AND p~value_new = 'X'
INTO TABLE @DATA(lt_cd_comp).
LOOP AT lt_cd_comp ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Completed'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_DELETED
*&---------------------------------------------------------------------*
FORM get_po_deleted.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime
FROM cdhdr AS h JOIN cdpos AS p ON h~changenr = p~changenr AND h~objectid = p~objectid
WHERE h~objectclas = 'EINKBELEG' AND h~objectid IN lt_ebeln AND p~tabname = 'EKPO' AND p~fname = 'LOEKZ' AND p~value_new = 'L'
INTO TABLE @DATA(lt_cd_del).
LOOP AT lt_cd_del ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Deleted'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DOWNLOAD_TO_CSV
*&---------------------------------------------------------------------*
FORM download_to_csv.
DATA: lv_filename TYPE string.
DATA: lt_fieldnames TYPE TABLE OF string.
APPEND 'PurchaseOrder' TO lt_fieldnames.
APPEND 'Activity' TO lt_fieldnames.
APPEND 'EventTime' TO lt_fieldnames.
APPEND 'UserName' TO lt_fieldnames.
APPEND 'VendorNumber' TO lt_fieldnames.
APPEND 'OrderAmount' TO lt_fieldnames.
APPEND 'MaterialGroup' TO lt_fieldnames.
APPEND 'CompanyCode' TO lt_fieldnames.
APPEND 'DocumentType' TO lt_fieldnames.
DATA(lv_header) = REDUCE string( INIT h = '' FOR f IN lt_fieldnames NEXT h = h && f && cl_abap_char_utilities=>horizontal_tab ).
REPLACE LAST OCCURRENCE OF cl_abap_char_utilities=>horizontal_tab IN lv_header WITH cl_abap_char_utilities=>cr_lf.
DATA(lv_file_content) = lv_header.
LOOP AT gt_event_log ASSIGNING FIELD-SYMBOL(<fs_log>).
DATA lv_line TYPE string.
DATA lv_eventtime_str TYPE string.
lv_eventtime_str = |{ <fs_log>-eventtime TIMESTAMP = ISO }|.
lv_line = <fs_log>-purchaseorder && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-activity && cl_abap_char_utilities=>horizontal_tab &&
lv_eventtime_str && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-username && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-vendornumber && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-orderamount && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-materialgroup && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-companycode && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-documenttype && cl_abap_char_utilities=>cr_lf.
CONCATENATE lv_file_content lv_line INTO lv_file_content.
ENDLOOP.
CALL METHOD cl_gui_frontend_services=>gui_download
EXPORTING
filename = 'C:\temp\po_event_log.csv'
filetype = 'ASC'
CHANGING
data_tab = lv_file_content. Stappen
- Databaseverbinding instellen: Vraag inloggegevens met alleen-lezenrechten en verbindingsgegevens op, zoals hostnaam, poort en databasenaam, voor de onderliggende SAP ECC-database. Zorg dat je de benodigde clienttools hebt geïnstalleerd, zoals DBeaver, SQL Developer of SSMS.
- SAP-schema bepalen: Maak verbinding met de database en bepaal het primaire SAP-schema waarin de tabellen staan. Dit is vaak SAPSR3, SAPHANADB of een vergelijkbare systeemnaam. Als dit schema niet de standaardinstelling voor je gebruiker is, moet je alle tabelnamen in de query van dit schema voorzien.
- SQL-query controleren: Open het meegeleverde SQL-script in je clienttool. Deze uitgebreide query haalt 14 verschillende activiteiten uit het Purchase-to-Pay-proces door meerdere SAP-tabellen aan elkaar te koppelen.
- Queryparameters aanpassen: Zoek de Common Table Expression PO_BASE aan het begin van het script. Pas de tijdelijke waarden aan om het bereik van je extractie te bepalen:
- [START_DATE] en [END_DATE]: Stel het datumbereik voor de analyse in, bijvoorbeeld '20230101' en '20230630'. Filteren op het veld AEDAT (Changed On) wordt aanbevolen.
- [COMPANY_CODE_1], [COMPANY_CODE_2]: Geef de SAP Company Codes op die je wilt opnemen.
- [DOC_TYPE_1], [DOC_TYPE_2]: Geef de documenttypen van de PO's op die je wilt opnemen.
- [Your SAP Schema]: Vervang deze tijdelijke waarde overal in het script door de naam van je SAP-schema.
- Query uitvoeren: Voer het aangepaste SQL-script uit op de SAP-database. De uitvoeringstijd hangt af van het datumbereik, de hoeveelheid data en de prestaties van de database.
- Resultaten controleren: Controleer de uitvoer kort nadat de query is afgerond. Kijk of het aantal rijen logisch is en of belangrijke kolommen zoals PurchaseOrder, Activity en EventTime naar verwachting zijn gevuld.
- Data naar CSV exporteren: Exporteer de volledige resultatenset vanuit je SQL-client naar een CSV-bestand. Gebruik UTF-8-codering om problemen met tekens te voorkomen.
- Upload voorbereiden: Controleer of de kolomkoppen in je CSV-bestand exact overeenkomen met de vereiste attribuutnamen: PurchaseOrder, Activity, EventTime, UserName, VendorNumber, OrderAmount, MaterialGroup, CompanyCode, DocumentType.
- Uploaden naar de process mining-tool: Upload het definitieve CSV-bestand naar je process mining-applicatie voor analyse en visualisatie.
Configuratie
- Vereisten vooraf: Je hebt directe, alleen-lezen toegang tot de onderliggende SAP ECC-database nodig. Gebruikers moeten voldoende autorisatie hebben om tabellen zoals EKKO, EKPO, EKBE, EBAN, CDHDR, CDPOS en NAST te raadplegen.
- Filteren op datumbereik: Het is belangrijk om een datumbereikfilter toe te passen om de hoeveelheid data te beperken. Filteren op EKKO.AEDAT, de wijzigingsdatum van de PO, over een periode van 3 tot 6 maanden is een gebruikelijk startpunt. Grote datumbereiken kunnen leiden tot zeer lange query-uitvoeringstijden.
- Belangrijke datafilters: Filter altijd op EKKO.BUKRS (Company Code) en EKKO.BSART (Document Type) voor een gerichte analyse. Zo beperk je het bereik tot relevante juridische entiteiten en bedrijfsprocessen.
- Aandacht voor prestaties: De query koppelt meerdere grote tabellen, waaronder de tabellen met wijzigingshistorie (CDHDR, CDPOS). Dit kan veel systeembronnen vragen. Voer deze extractie bij voorkeur buiten piekuren uit of op een gerepliceerde niet-productiedatabase, zodat de systeemprestaties niet worden beïnvloed.
- Logging van wijzigingsdocumenten: De nauwkeurigheid van activiteiten zoals 'Approved', 'Rejected', 'Completed' en 'Changed' hangt ervan af of logging van wijzigingsdocumenten actief is voor de relevante velden in SAP. Controleer bij je SAP-beheerder of deze logging is ingeschakeld via transactie SCDO.
a Voorbeeldquery sql
WITH PO_BASE AS (
SELECT
H.EBELN, -- Purchase Order Number
I.EBELP, -- Purchase Order Item
H.LIFNR, -- Vendor Number
H.BUKRS, -- Company Code
H.BSART, -- Document Type
I.NETWR, -- Order Amount (Item Level)
I.MATKL, -- Material Group
I.BANFN, -- Purchase Requisition Number
I.BNFPO -- Purchase Requisition Item
FROM [Your SAP Schema].EKKO AS H
JOIN [Your SAP Schema].EKPO AS I ON H.EBELN = I.EBELN
WHERE H.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' -- Filter on PO Change Date, e.g., '20230101' and '20231231'
AND H.BUKRS IN ('[COMPANY_CODE_1]', '[COMPANY_CODE_2]') -- Specify Company Codes
AND H.BSART IN ('[DOC_TYPE_1]', '[DOC_TYPE_2]') -- Specify PO Document Types
)
-- 1. Purchase Requisition Created
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Requisition Created' AS "Activity",
TO_TIMESTAMP(CONCAT(pr.ERDAT, '000000'), 'YYYYMMDDHH24MISS') AS "EventTime", -- Time is not available in EBAN
pr.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EBAN pr ON po.BANFN = pr.BANFN AND po.BNFPO = pr.BNFPO
WHERE po.BANFN IS NOT NULL AND po.BANFN <> ''
UNION ALL
-- 2. Purchase Requisition Approved
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Requisition Approved' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'BANF' AND ch.OBJECTID = po.BANFN
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EBAN' AND cp.FNAME = 'FRGZU' AND cp.VALUE_NEW = 'X' -- Release indicator set to 'released'
UNION ALL
-- 3. Purchase Order Created
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Created' AS "Activity",
TO_TIMESTAMP(CONCAT(ekko.ERDAT, ' ', ekko.ERZET), 'YYYYMMDD HH24MISS') AS "EventTime",
ekko.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKKO ekko ON po.EBELN = ekko.EBELN
UNION ALL
-- 4. Purchase Order Approval Requested / 5. Approved / 6. Rejected (from Change Docs)
SELECT
po.EBELN AS "PurchaseOrder",
CASE
WHEN cp.VALUE_NEW > cp.VALUE_OLD THEN 'Purchase Order Approval Requested'
WHEN cp.VALUE_NEW = ekko.FRGKE AND ekko.FRGKE = 'R' THEN 'Purchase Order Approved'
ELSE 'Purchase Order Rejected' -- Simplified logic, may need adjustment
END AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKKO ekko ON po.EBELN = ekko.EBELN
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID = po.EBELN
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKKO' AND cp.FNAME = 'FRGZU' -- Release status
UNION ALL
-- 7. Purchase Order Sent to Vendor
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Sent to Vendor' AS "Activity",
TO_TIMESTAMP(CONCAT(na.ERDAT, ' ', na.ERUHR), 'YYYYMMDD HH24MISS') AS "EventTime",
na.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].NAST na ON na.OBJKY = po.EBELN AND na.KSCHL = '[Your PO Output Type]' -- e.g., 'NEU'
WHERE na.VSTAT = '1' -- Successfully processed
UNION ALL
-- 8. Purchase Order Changed
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Changed' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID = po.EBELN
WHERE ch.TCODE IN ('ME22', 'ME22N') -- Filter for change transactions
UNION ALL
-- 9. Goods Receipt Posted
SELECT
ekbe.EBELN AS "PurchaseOrder",
'Goods Receipt Posted' AS "Activity",
TO_TIMESTAMP(CONCAT(mkpf.CPUDT, ' ', mkpf.CPUTM), 'YYYYMMDD HH24MISS') AS "EventTime",
mkpf.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM [Your SAP Schema].EKBE AS ekbe
JOIN [Your SAP Schema].MKPF AS mkpf ON ekbe.BELNR = mkpf.MBLNR AND ekbe.GJAHR = mkpf.MJAHR
JOIN PO_BASE AS po ON ekbe.EBELN = po.EBELN AND ekbe.EBELP = po.EBELP
WHERE ekbe.BEWTP = 'E' -- Goods Receipt
AND ekbe.SHKZG = 'S' -- Debit/Credit Indicator: Goods Receipt
UNION ALL
-- 10. Services Confirmation Entered
SELECT
po.EBELN AS "PurchaseOrder",
'Services Confirmation Entered' AS "Activity",
TO_TIMESTAMP(CONCAT(essr.ERDAT, ' ', essr.ERZET), 'YYYYMMDD HH24MISS') AS "EventTime",
essr.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKBE ekbe ON po.EBELN = ekbe.EBELN AND po.EBELP = ekbe.EBELP
JOIN [Your SAP Schema].ESSR essr ON ekbe.LBLNI = essr.LBLNI
WHERE ekbe.BEWTP = 'L' -- Service Entry Sheet
UNION ALL
-- 11. Quality Inspection Performed
SELECT
po.EBELN AS "PurchaseOrder",
'Quality Inspection Performed' AS "Activity",
TO_TIMESTAMP(CONCAT(qave.VDATUM, ' ', qave.VZEIT), 'YYYYMMDD HH24MISS') AS "EventTime",
qave.VNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKBE ekbe ON po.EBELN = ekbe.EBELN AND po.EBELP = ekbe.EBELP
JOIN [Your SAP Schema].QALS qals ON qals.MBLNR = ekbe.BELNR AND qals.MJAHR = ekbe.GJAHR
JOIN [Your SAP Schema].QAVE qave ON qals.PRUEFLOS = qave.PRUEFLOS
WHERE ekbe.BEWTP = 'E' -- Linked to a Goods Receipt
UNION ALL
-- 12. Goods Returned
SELECT
ekbe.EBELN AS "PurchaseOrder",
'Goods Returned' AS "Activity",
TO_TIMESTAMP(CONCAT(mkpf.CPUDT, ' ', mkpf.CPUTM), 'YYYYMMDD HH24MISS') AS "EventTime",
mkpf.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM [Your SAP Schema].EKBE AS ekbe
JOIN [Your SAP Schema].MKPF AS mkpf ON ekbe.BELNR = mkpf.MBLNR AND ekbe.GJAHR = mkpf.MJAHR
JOIN PO_BASE AS po ON ekbe.EBELN = po.EBELN AND ekbe.EBELP = po.EBELP
WHERE ekbe.BEWTP = 'E' -- Goods Movement
AND ekbe.SHKZG = 'H' -- Debit/Credit Indicator: Return
AND ekbe.BWART = '122' -- Movement type for return to vendor
UNION ALL
-- 13. Purchase Order Completed
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Completed' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID LIKE CONCAT(po.EBELN, po.EBELP, '%')
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKPO' AND cp.FNAME = 'ELIKZ' AND cp.VALUE_NEW = 'X' -- Delivery completed indicator
UNION ALL
-- 14. Purchase Order Deleted
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Deleted' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID LIKE CONCAT(po.EBELN, po.EBELP, '%')
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKPO' AND cp.FNAME = 'LOEKZ' AND cp.VALUE_NEW = 'L'; -- Deletion indicator Stappen
- Vereisten en verbinding: Controleer of je ETL-tool de SAP Certified Connector heeft geïnstalleerd en gelicentieerd. Configureer in de beheerconsole van je ETL-tool een nieuwe verbinding met je SAP ECC-systeem. Je hebt de host van de applicatieserver, het systeemnummer, de client-ID en een speciale SAP-gebruiker nodig met de juiste RFC- en tabelleesrechten.
- Bronnen identificeren: Definieer in je ETL-job of dataflow de benodigde SAP-tabellen als databronnen. De belangrijkste tabellen zijn EKKO (PO Header), EKPO (PO Item), EBAN (Purchase Requisition), CDHDR (Change Document Header), CDPOS (Change Document Item), MSEG (Document Segment: Material), MKPF (Material Document Header), NAST (Message Status), ESSR (Service Entry Sheet Header) en QALS (Inspection Lot).
- 'Purchase Order Created' extraheren: Maak een dataflow die gegevens uit de tabel EKKO haalt. Filter records op het gewenste datumbereik, bijvoorbeeld met AEDAT, en op de organisatorische scope, bijvoorbeeld BUKRS voor Company Code en BSART voor Document Type. Koppel EKKO.EBELN aan PurchaseOrder, 'Purchase Order Created' aan Activity en combineer AEDAT en ERZET voor EventTime. Koppel ook de overige vereiste attributen.
- 'Goods Receipt Posted' extraheren: Maak een aparte dataflow die gegevens uit MSEG haalt en deze via MBLNR en MJAHR koppelt aan MKPF. Filter op relevante bewegingstypen, zoals '101'. Koppel MSEG.EBELN aan PurchaseOrder, 'Goods Receipt Posted' aan Activity en gebruik MKPF.CPUDT en MKPF.CPUTM voor EventTime.
- Gebeurtenissen op basis van wijzigingen extraheren, goedkeuringen, wijzigingen en verwijderingen: Maak een dataflow op basis van CDHDR en CDPOS, gekoppeld via CHANGENR. Deze ene bron kan worden gebruikt om meerdere activiteiten af te leiden.
- Filter OBJECTCLAS = 'EINKBELEG' en TABNAME = 'EKPO'.
- Voor 'Purchase Order Approved' filter je op wijzigingen in het vrijgavestatusveld, bijvoorbeeld FNAME = 'FRGZU', waarbij de nieuwe waarde (VALUE_NEW) staat voor definitieve goedkeuring.
- Voor 'Purchase Order Deleted' filter je op wijzigingen in de verwijderingsindicator (FNAME = 'LOEKZ'), waarbij de nieuwe waarde 'L' is.
- Voor 'Purchase Order Changed' filter je op andere relevante veldwijzigingen en sluit je de statusvelden uit die voor andere activiteiten worden gebruikt.
- Gebruik voor al deze gebeurtenissen CDHDR.UDATE en CDHDR.UTIME voor EventTime.
- Gebeurtenissen voor Purchase Requisition extraheren: Maak een dataflow vanuit EBAN voor 'Purchase Requisition Created'. Koppel EBAN aan EKPO via het aanvraagnummer (BANFN) en de regel (BNFPO) om dit aan een PurchaseOrder-case te koppelen. Gebruik voor 'Purchase Requisition Approved' CDHDR/CDPOS met OBJECTCLAS = 'BANF'. Hiervoor is een zorgvuldige koppeling nodig, zodat de gebeurtenis aan de uiteindelijke PO wordt gekoppeld.
- 'PO Sent to Vendor' extraheren: Maak een dataflow op basis van de tabel NAST. Filter op OBJECTKEY, waarin het PO-nummer staat, het relevante outputtype (KSCHL) en een succesvolle verwerkingsstatus (VSTAT = '1'). Gebruik ERDAT en UHR voor EventTime.
- Activiteitenstromen combineren: Gebruik een transformatie 'Union' of 'Merge' in je ETL-tool om de uitvoer van alle afzonderlijke dataflows uit de vorige stappen samen te voegen. Zorg dat kolomnamen en datatypen in alle stromen overeenkomen, bijvoorbeeld PurchaseOrder, Activity en EventTime.
- Datatypen en indeling omzetten: Zorg dat de kolom EventTime wordt omgezet naar één consistente timestamp-indeling, bijvoorbeeld YYYY-MM-DD HH:MM:SS. Zet OrderAmount om naar een standaard decimaal formaat.
- Doelbestemming definiëren: Configureer een doel of 'sink' voor je gecombineerde datastroom. Dit is meestal een plat bestand, zoals een CSV- of Parquet-bestand. Stel het scheidingsteken, tekstkwalificaties en de opties voor kolomkoppen in.
- Uitvoeren en valideren: Voer de volledige ETL-job uit. Controleer het uitvoerbestand om na te gaan of alle 14 activiteiten aanwezig zijn, het aantal rijen logisch is en de belangrijkste attributen correct zijn gevuld.
- Plannen en exporteren: Plan de ETL-job na validatie periodiek in, bijvoorbeeld elke nacht, zodat de data actueel blijft. Het gegenereerde bestand kan nu naar je process mining-tool worden geüpload.
Configuratie
- Vereisten: Een commerciële ETL-tool, bijvoorbeeld Informatica PowerCenter, Talend of SAP Data Services, met de bijbehorende SAP Certified Connector voor ECC. Een SAP-dialog- of systeemgebruiker met autorisaties voor S_RFC en S_TABU_DIS voor de benodigde tabellen.
- SAP-verbinding: Configureer de connector met de SAP-applicatieserver, het systeemnummer, de client, de gebruiker en het wachtwoord. Het gebruik van Secure Network Communications (SNC) wordt aanbevolen.
- Datumbereikfilter: Pas altijd een datumbereikfilter toe om het datavolume te beperken. Vaak wordt EKKO.AEDAT, de aanmaakdatum van de inkooporder, gefilterd op de laatste 3 tot 12 maanden. Pas dit filter toe bij de bron, zodat je niet onnodig veel data uit SAP extraheert.
- Filters voor de organisatiestructuur: Filter altijd op EKKO.BUKRS, de bedrijfscode. Overweeg ook een filter op EKPO.WERKS, de plant, of EKKO.EKORG, de inkooporganisatie, om de analyse te beperken tot een specifieke bedrijfseenheid.
- Documenttypefilter: Gebruik EKKO.BSART om alleen relevante inkoopordertypen op te nemen. Sluit voorraadtransfers en andere interne documenten uit die geen onderdeel zijn van het standaard P2P-proces.
- Prestatieoptimalisatie: Extractie uit wijzigingsdocumenttabellen, CDHDR en CDPOS, kan traag zijn. Zorg dat filters op OBJECTCLAS, OBJECTID en UDATE worden toegepast. Pas de instelling 'Packet Size' in de SAP-connector aan om de gegevensoverdracht te optimaliseren. Overweeg bij zeer grote systemen eerst een historische initiële lading uit te voeren en daarna geplande delta-ladingen.
a Voorbeeldquery sql
/*
This is a logical representation of the transformations performed within the ETL tool.
The tool's graphical interface will be used to configure these separate data flows, which are then combined with a UNION transformation.
Placeholders like [Your ETL Tool Functions] and [Filter Values] must be configured in the tool.
*/
-- 1. Purchase Requisition Created
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Requisition Created' AS Activity,
[Your ETL Tool Functions].DateTime(eban.ERDAT, eban.ERZET) AS EventTime,
eban.ERNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM EBAN AS eban
INNER JOIN EKPO AS ekpo ON eban.BANFN = ekpo.BANFN AND eban.BNFPO = ekpo.BNFPO
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 2. Purchase Requisition Approved (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Requisition Approved' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EBAN AS eban ON cdhdr.OBJECTID = eban.BANFN
INNER JOIN EKPO AS ekpo ON eban.BANFN = ekpo.BANFN AND eban.BNFPO = ekpo.BNFPO
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'BANF' AND cdpos.TABNAME = 'EBAN' AND cdpos.FNAME = 'FRGZU' AND cdpos.VALUE_NEW = '[Final Release Indicator for PR]'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 3. Purchase Order Created
SELECT
EBELN AS PurchaseOrder,
'Purchase Order Created' AS Activity,
[Your ETL Tool Functions].DateTime(AEDAT, ERZET) AS EventTime,
ERNAM AS UserName,
LIFNR AS VendorNumber,
NULL AS OrderAmount, -- Amount is at item level
NULL AS MaterialGroup, -- Attribute is at item level
BUKRS AS CompanyCode,
BSART AS DocumentType
FROM EKKO
WHERE AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 4. Purchase Order Approval Requested / 5. Approved / 6. Rejected (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
CASE
WHEN cdpos.VALUE_NEW = '[Final Release Code]' THEN 'Purchase Order Approved'
WHEN cdpos.VALUE_NEW = '[Rejection Release Code]' THEN 'Purchase Order Rejected'
ELSE 'Purchase Order Approval Requested'
END AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKKO AS ekko ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKKO' AND cdpos.FNAME = 'FRGKE'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 7. Purchase Order Sent to Vendor
SELECT
ekko.EBELN AS PurchaseOrder,
'Purchase Order Sent to Vendor' AS Activity,
[Your ETL Tool Functions].DateTime(nast.ERDAT, nast.UHR) AS EventTime,
nast.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM NAST AS nast
INNER JOIN EKKO AS ekko ON nast.OBJKY = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE nast.KAPPL = 'EF' AND nast.VSTAT = '1' AND nast.KSCHL IN ([Your PO Output Types])
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 8. Purchase Order Changed (inferred from change documents, simplified example)
SELECT DISTINCT
ekko.EBELN AS PurchaseOrder,
'Purchase Order Changed' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKKO AS ekko ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.FNAME NOT IN ('FRGKE', 'FRGZU', 'LOEKZ', 'ELIKZ')
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 9. Goods Receipt Posted
SELECT
mseg.EBELN AS PurchaseOrder,
'Goods Receipt Posted' AS Activity,
[Your ETL Tool Functions].DateTime(mkpf.CPUDT, mkpf.CPUTM) AS EventTime,
mkpf.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM MSEG AS mseg
INNER JOIN MKPF AS mkpf ON mseg.MBLNR = mkpf.MBLNR AND mseg.MJAHR = mkpf.MJAHR
INNER JOIN EKPO AS ekpo ON mseg.EBELN = ekpo.EBELN AND mseg.EBELP = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE mseg.BWART = '101' AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 10. Services Confirmation Entered
SELECT
essr.EBELN AS PurchaseOrder,
'Services Confirmation Entered' AS Activity,
[Your ETL Tool Functions].DateTime(essr.ERDAT, essr.ERZET) AS EventTime,
essr.ERNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM ESSR AS essr
INNER JOIN EKKO AS ekko ON essr.EBELN = ekko.EBELN
INNER JOIN EKPO AS ekpo ON essr.EBELN = ekpo.EBELN AND essr.EBELP = ekpo.EBELP
WHERE ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 11. Quality Inspection Performed
SELECT
qals.EBELN AS PurchaseOrder,
'Quality Inspection Performed' AS Activity,
[Your ETL Tool Functions].DateTime(qals.PASTRTERM, '000000') AS EventTime, -- Time is often not available
qals.PRUEFER AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM QALS AS qals
INNER JOIN EKKO AS ekko ON qals.EBELN = ekko.EBELN
INNER JOIN EKPO AS ekpo ON qals.EBELN = ekpo.EBELN AND qals.EBELP = ekpo.EBELP
WHERE qals.VCODE <> '' -- A usage decision code exists
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 12. Goods Returned
SELECT
mseg.EBELN AS PurchaseOrder,
'Goods Returned' AS Activity,
[Your ETL Tool Functions].DateTime(mkpf.CPUDT, mkpf.CPUTM) AS EventTime,
mkpf.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM MSEG AS mseg
INNER JOIN MKPF AS mkpf ON mseg.MBLNR = mkpf.MBLNR AND mseg.MJAHR = mkpf.MJAHR
INNER JOIN EKPO AS ekpo ON mseg.EBELN = ekpo.EBELN AND mseg.EBELP = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE mseg.BWART = '122' AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 13. Purchase Order Completed (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Order Completed' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKPO AS ekpo ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekpo.EBELN AND SUBSTRING(cdhdr.OBJECTID, 11, 5) = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKPO' AND cdpos.FNAME = 'ELIKZ' AND cdpos.VALUE_NEW = 'X'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 14. Purchase Order Deleted (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Order Deleted' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKPO AS ekpo ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekpo.EBELN AND SUBSTRING(cdhdr.OBJECTID, 11, 5) = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKPO' AND cdpos.FNAME = 'LOEKZ' AND cdpos.VALUE_NEW = 'L'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]); Klaar om aan de slag te gaan?
Met deze template heb je de blauwdruk om je Purchase-to-Pay-proces, Purchase Order in SAP ECC te optimaliseren. Gebruik je data om vandaag nog inzichten te vinden en efficiënter te werken.
Optimaliseer je P2P Purchase Order: start vandaag nog je gratis proefperiode
Elimineer bottlenecks en verkort de doorlooptijd met 30% of meer.
Geen creditcard nodig. Je kunt binnen enkele minuten aan de slag.