Je Purchase-to-Pay - Inkooporder datatemplate
Je Purchase-to-Pay - Inkooporder datatemplate
- Aanbevolen attributen om vast te leggen
- Belangrijkste activiteiten om te volgen
- Extractiehandleiding voor SAP ECC
Inkoop tot betaling - Inkooporder-attributen
| Naam | Omschrijving | ||
|---|---|---|---|
| Activiteit Activity | De naam van de specifieke bedrijfs-gebeurtenis of stap die plaatsvond binnen de levenscyclus van de inkooporder. | ||
| Omschrijving Dit attribuut beschrijft een enkele stap in het proces, zoals 'Inkooporder Aangemaakt', 'Inkooporder Goedgekeurd' of 'Goederenontvangst Geboekt'. De volgorde van deze activiteiten vormt de processtroom voor elke inkooporder. Het analyseren van de volgorde, frequentie en duur tussen activiteiten is de basis van Process Mining. Het helpt bij het vinden van knelpunten, herstelwerk-loops en afwijkingen van het standaardproces, wat gerichte verbeteringen en standaardisatie-inspanningen mogelijk maakt. Het belang Activiteiten definiëren de stappen van het proces. Het analyseren van hun volgorde en timing brengt de werkelijke processtroom in kaart, knelpunten en afwijkingen. Vindplaats Afgeleid van verschillende SAP-tabellen en transactielogs, zoals CDHDR/CDPOS voor wijzigingen, EKBE voor GR/IR, en EBAN voor aanvragen. Verplicht vaak custom logic of een extractieprogramma om te genereren. Voorbeelden Inkooporder AangemaaktInkooporder GoedgekeurdGoederenontvangst geboekt | |||
| Inkooporder PurchaseOrder | De unieke ID voor de inkooporder (IO), dat dient als de primaire case voor het volgen van het inkoopproces. | ||
| Omschrijving Het inkoopordernummer is de centrale identificatie die alle activiteiten koppelt, van aanmaak tot definitieve goederenontvangst en voltooiing. Elk uniek inkoopordernummer vertegenwoordigt een enkele case van het inkoopproces. Binnen Process Mining is dit attribuut belangrijk voor het reconstrueren van het end-to-end traject van elke aankoop. Het maakt gedetailleerde analyse van doorlooptijden, procesvariaties en compliance-checks mogelijk voor elke individuele order, en vormt zo de basis van het gehele procesmodel. Het belang Dit is de basis-id die alle gerelateerde gebeurtenissen verbindt, waardoor het mogelijk wordt om de complete levenscyclus van elke individuele inkooporder te analyseren. Vindplaats Table: EKKO, Field: EBELN Voorbeelden 450001762345000176244500017625 | |||
| TijdsTip Gebeurtenis EventTime | De exacte datum en tijd waarop de activiteit plaatsvond. | ||
| Omschrijving Deze timestamp markeert het exacte moment dat een gebeurtenis plaatsvond, zoals het tijdsTip waarop een PO werd goedgekeurd of wanneer een goederenontvangst werd geboekt. Het bepaalt de chronologische volgorde voor alle activiteiten binnen een case. Timestamps zijn belangrijk voor process mining, aangezien ze alle tijdgebonden analyses mogelijk maken. Dit omvat het berekenen van cyclustijden tussen activiteiten, het vinden van vertragingen, het analyseren van de procesdoorvoer en het meten van prestaties ten opzichte van Service Level Agreements (SLA's). Het belang Deze timestamp is belangrijk voor het berekenen van alle duurgerelateerde meetwaarden, zoals cyclustijden en knelpunten, en voor het chronologisch rangschikken van gebeurtenissen. Vindplaats Afgeleid van verschillende datum- en tijdvelden in SAP-tabellen, zoals EKKO-AEDAT (Wijzigingsdatum), CDHDR-UDATE/UTIME (Wijzigingslogboek Timestamp) of EKBE-BUDAT (Boekingsdatum). Voorbeelden 2023-04-15T10:05:31Z2023-04-16T14:22:00Z2023-05-01T09:00:15Z | |||
| Bedrijfscode CompanyCode | De identificatie voor de juridische entiteit of het bedrijf dat de aankoop initieert. | ||
| Omschrijving De Bedrijfscode vertegenwoordigt een onafhankelijke juridische entiteit in SAP. Alle transacties worden geboekt op bedrijfscodeniveau, waardoor het een fundamentele onderdeel is. Het analyseren van het proces per Bedrijfscode maakt vergelijking mogelijk van de inkoopefficiëntie en compliance tussen verschillende bedrijfseenheden of landen. Het helpt best practices in de ene entiteit te vinden die elders kunnen worden gerepliceerd, of specifieke eenheden aan te wijzen die moeite hebben met het proces. Het belang Vertegenwoordigt de juridische entiteit, wat het vergelijken van procesprestaties en compliance-checks tussen verschillende onderdelen van de organisatie mogelijk maakt. Vindplaats Table: EKKO, Field: BUKRS Voorbeelden 10002100US01 | |||
| Documenttype DocumentType | Een code die verschillende soorten inkooporders classificeert. | ||
| Omschrijving Het documenttype is een configuratie in SAP die de nummerreeks, veldselectie en de algehele processtroom voor een inkooporder beheert. Zo kunnen er bijvoorbeeld verschillende typen zijn voor standaard inkooporders, service-inkooporders of voorraadoverboekingsorders. Dit attribuut is een waardevolle factor voor analyse, aangezien verschillende documenttypen vaak opzettelijk verschillende processen volgen. Filteren op documenttype maakt een nauwkeurigere, eerlijke vergelijking mogelijk van doorlooptijden en processtromen. Het belang Onderscheidt verschillende soorten inkoopprocessen (bijv. standaard, service, retour), die vaak verschillende paden en prestatieverwachtingen hebben. Vindplaats Table: EKKO, Field: BSART Voorbeelden NBFOUB | |||
| Gebruikersnaam UserName | De `gebruikers-id` van de persoon die de `activiteit` heeft uitgevoerd. | ||
| Omschrijving Dit attribuut legt de SAP username vast van de medewerker die een document heeft aangemaakt, gewijzigd of goedgekeurd. Voor geautomatiseerde stappen kan het een systeem of batch user ID weergeven. Analyseren per gebruiker helpt bij het vinden van trainingsbehoeften, goed presterende individuen, of potentiële compliance-kwesties. Het is belangrijk voor het bouwen van dashboards voor werklastverdeling, approval matrix compliance en het begrijpen van de prestaties van verschillende teams of individuen. Het belang Koppelt gebruikersacties aan specifieke individuen, waardoor analyse van gebruikersprestaties, werkdruk en naleving van compliance-protocollen mogelijk worden. Vindplaats Table: EKKO, Field: ERNAM (Aangemaakt door); Table: CDHDR, Field: USERNAME (Gewijzigd door). Voorbeelden JSMITHMBROWNBATCH_USER | |||
| Leveranciersnummer VendorNumber | De unieke ID voor de leverancier. | ||
| Omschrijving Dit is de code die de leverancier van wie de goederen of diensten worden ingekocht uniek identificeert. Het is een belangrijk onderdeel van de stamdata in het inkoopproces. Dit attribuut is belangrijk voor leveranciersgerichte analyse. Het maakt de evaluatie van leveranciersprestaties, de vergelijking van doorlooptijden tussen verschillende leveranciers, en de analyse van uitgavenpatronen mogelijk. Het is de primaire dimensie voor het 'Leveranciersprestaties' dashboard. Het belang Maakt leveranciersprestatieanalyse mogelijk, wat helpt bij het vinden van betrouwbare leveranciers en degenen die vertragingen of kwaliteitsproblemen veroorzaken. Vindplaats Table: EKKO, Field: LIFNR Voorbeelden 100345V-20598700112 | |||
| Materiaalgroep MaterialGroup | Een classificatie voor het groeperen van materialen of diensten met vergelijkbare kenmerken. | ||
| Omschrijving De artikelgroep, of inkoopcategorie, wordt gebruikt om het type goederen of diensten te classificeren dat wordt ingekocht. Voorbeelden zijn 'IT Hardware', 'Kantoorbenodigdheden' of 'Professionele Diensten'. Dit attribuut is belangrijk voor uitgavenanalyse en het begrijpen van inkooppatronen. Het maakt het mogelijk om het proces te filteren om te analyseren hoe verschillende categorieën worden afgehandeld, wie deze goedkeurt, en welke leveranciers deze leveren. Het is een belangrijke dimensie in het dashboard 'Analyse van de waarde van inkooporders'. Het belang Maakt segmentatie van het proces mogelijk op product- of servicecategorie, waardoor verschillende gedragingen, doorlooptijden of leveranciers voor verschillende soorten uitgaven zichtbaar worden. Vindplaats Table: EKPO, Field: MATKL Voorbeelden 00101IT_HWCONSULT | |||
| Orderbedrag OrderAmount | De totale financiële waarde van de inkooporderregel. | ||
| Omschrijving Dit attribuut vertegenwoordigt de totale waarde van een specifiek regelitem op de inkooporder, berekend als hoeveelheid vermenigvuldigd met de nettoprijs. Voor een volledige inkooporderwaarde moeten artikelbedragen worden geaggregeerd. Het analyseren van het proces op basis van orderbedrag is belangrijk voor het vinden van waardevolle transacties die mogelijk strengere controles of afwijkende goedkeuringstrajecten vereisen. Dit is de basis voor het 'Waardeanalyse Inkooporders' dashboard en helpt bij het prioriteren van procesverbeteringsinspanningen op de financieel meest significante orders. Het belang Kwantificeert de financiële impact van elke aankoop, waardoor analyses op basis van waarde mogelijk wordt om orders met hoogwaardige te prioriteren of kostenbesparingsmogelijkheden te vinden. Vindplaats Table: EKPO, Field: NETWR (Netto Orderwaarde). Voorbeelden 1500.00250.7512345.50 | |||
| Bronsysteem SourceSystem | Het systeem waaruit de data is opgehaald. | ||
| Omschrijving Dit attribuut identificeert de herkomst van de data, wat doorgaans een SAP ECC instantie-ID is (bijv. 'ECC_PROD_100'). In omgevingen met meerdere systemen helpt het om databronnen te onderscheiden. Voor governance en datalineage is kennis van het bronsysteem belangrijk. Het waarborgt de dataintegriteit en helpt bij het oplossen van problemen met data-extractie of datakwaliteit, vooral wanneer data wordt samengevoegd uit verschillende ERP-systemen of modules. Het belang Identificeert de herkomst van de data, wat belangrijk is voor data-governance, validatie en het beheren van analyses over meerdere systemen. Vindplaats Dit is doorgaans een statische waarde die tijdens het dataextractieproces wordt toegevoegd om de dataset te labelen met het bronsysteem. Voorbeelden SAP_ECC_PROD`ECC_EU_100`S4H_FIN | |||
| Gewenste leverdatum RequestedDeliveryDate | De datum waarop het bedrijf de leverancier verzocht de goederen of diensten te leveren. | ||
| Omschrijving Dit is de streefleveringsdatum die in de inkooporder is gespecificeerd. Het dient als de basislijn waartegen de werkelijke leveringsprestaties worden gemeten. Deze datum is belangrijk voor het berekenen van de 'Percentage Tijdige Goederenontvangsten' KPI. Door de feitelijke datum van goederenontvangst te vergelijken met deze aangevraagde datum, kunnen organisaties kwantitatief de leveranciersbetrouwbaarheid en interne ontvangstefficiëntie meten, wat het 'Leveranciersprestaties' dashboard direct ondersteunt. Het belang Dit is de streefdatum voor levering, belangrijk voor het berekenen van tijdige prestatie-KPI's en het ewaarderen van leveranciersbetrouwbaarheid. Vindplaats Table: EKPO, Field: EINDT Voorbeelden 2023-06-102023-07-222023-08-01 | |||
| Inkoopaanvraag PurchaseRequisition | De identificatie van de inkoopaanvraag die voorafging aan de inkooporder. | ||
| Omschrijving Dit attribuut koppelt de inkooporder terug aan de oorspronkelijke inkoopaanvraag. Niet alle inkooporders zullen een voorafgaande aanvraag hebben. Deze koppeling is belangrijk voor de analyse van het dashboard 'Aanvraag-naar-Order Conversie' en de KPI 'Inkoopaanvraag-naar-Inkooporder Conversiepercentage'. Het maakt het mogelijk de efficiëntie van het voorafgaande proces te meten, van de initiële aanvraag tot de creatie van een formele order, en om niet-conforme inkooporders te vinden die zonder aanvraag zijn aangemaakt. Het belang Koppelt de inkooporder aan de oorspronkelijke inkoopaanvraag, waardoor analyse van het inkoopaanvraag-naar-inkooporder conversieproces mogelijk wordt en inkooporders worden geïdentificeerd die zonder voorafgaande aanvraag zijn aangemaakt. Vindplaats Table: EKPO, Field: BANFN Voorbeelden 1001589010015891 | |||
| Inkoopgroep PurchasingGroup | De specifieke inkoper of groep van inkopers die verantwoordelijk is voor de inkoopactiviteit. | ||
| Omschrijving De inkoopgroep vertegenwoordigt de persoon of het team van inkopers die verantwoordelijk zijn voor een bepaalde inkoopactiviteit. Zij zijn het belangrijkste contactpunt voor leveranciers. Dit attribuut biedt een gedetailleerder analyseniveau dan de inkooporganisatie. Het helpt bij het begrijpen van de werkverdeling onder inkopers en het vinden van prestatieverschillen op het niveau van de inkoper, wat kan dienen als input voor bron-allocatie en trainingsinitiatieven. Het belang Biedt een gedetailleerd overzicht van wie verantwoordelijk is voor een aankoop, wat een gedetailleerde workload- en prestatieanalyse op inkoper- of teamniveau mogelijk maakt. Vindplaats Table: EKKO, Field: EKGRP Voorbeelden 001002N01 | |||
| Inkooporganisatie PurchasingOrganization | De onderdeel die verantwoordelijk is voor het onderhandelen over prijzen en de inkoop van materialen of diensten. | ||
| Omschrijving De inkooporganisatie is een belangrijke onderdeel in SAP die verantwoordelijk is voor inkoopactiviteiten. Deze kan gecentraliseerd zijn voor het gehele bedrijf of gedecentraliseerd per vestiging of regio. Het analyseren van procesprestaties per inkooporganisatie helpt bij het vinden welke inkoopteams het meest efficiënt zijn. Het maakt het vergelijken van meetwaarden zoals doorlooptijd, herstelwerk rates en kosten tussen verschillende organisatorische eenheden mogelijk, waardoor best practices en gebieden die ondersteuning behoeven worden belicht. Het belang Identificeert het verantwoordelijke inkoopteam, waardoor prestatievergelijkingen en analyses over verschillende organisatorische eenheden mogelijk zijn. Vindplaats Table: EKKO, Field: EKORG Voorbeelden 1000US01DE01 | |||
| Is Tijdige Levering IsOnTimeDelivery | Een flag die aangeeft of de goederen op of voor de gevraagde leverdatum zijn ontvangen. | ||
| Omschrijving Deze vlag is waar als de timestamp van de activiteit 'Goederenontvangst Geboekt' op of voor de 'Aangevraagde Leveringsdatum' ligt. Het biedt een duidelijk, binair resultaat voor de leveringsprestaties per regelitem van de inkooporder. Dit attribuut vormt de basis voor de 'Percentage Tijdige Goederenontvangsten' KPI. Het vereenvoudigt de analyse van leveranciersprestaties en interne ontvangstefficiëntie door eenvoudige aggregatie en filtering van tijdige versus late leveringen mogelijk te maken. Het belang Biedt een duidelijke succes- of faalmetriek voor tijdige levering, ter directe ondersteuning van KPI's voor leveranciersprestaties en dashboards. Vindplaats Dit is een berekend attribuut dat is afgeleid door de boekingsdatum van de goederenontvangst (EKBE-BUDAT) te vergelijken met de aangevraagde leveringsdatum (EKPO-EINDT). Voorbeelden truefalse | |||
| Is Wijziging na Goedkeuring IsPostApprovalChange | Een flag die aangeeft of een PO-wijziging heeft plaatsgevonden na de initiële goedkeuring. | ||
| Omschrijving Deze vlag is waar als een 'Inkooporder Gewijzigd' activiteit wordt gedetecteerd na een 'Inkooporder Goedgekeurd' activiteit voor dezelfde inkooporder. Het helpt problematische wijzigingen te isoleren die laat in het proces optreden. Dit berekende veld ondersteunt direct het 'Wijzigingspercentage Inkooporder na Goedkeuring' KPI en het 'Herstelwerk en Wijzigingen Inkooporder' dashboard. Het helpt disruptieve wijzigingen te kwantificeren en te benadrukken die vertragingen kunnen veroorzaken en hergoedkeuring vereisen, wat wijst op problemen in het initiële specificatie- of scopebepalingsproces. Het belang Meet direct rework na goedkeuring, een belangrijke KPI voor processtabiliteit en efficiëntie. Hoge percentages duiden op problemen in de stroomopwaartse vereistendefinitie. Vindplaats Dit is een berekende attribuut afgeleid uit de volgorde van activiteiten in de event log. Voorbeelden truefalse | |||
| Naam Leverancier VendorName | De statutaire naam van de leverancier. | ||
| Omschrijving De beschrijvende naam van de leverancier, die gebruiksvriendelijker is dan het leveranciersnummer. Deze wordt doorgaans verkregen uit de stamgegevens van leveranciers. Hoewel het leveranciersnummer wordt gebruikt voor koppelingen en unieke identificatie, is de leveranciersnaam belangrijk voor gebruikersgerichte dashboards en rapporten. Dit maakt analyses intuïtiever en toegankelijker voor zakelijke gebruikers die mogelijk niet bekend zijn met leverancierscodes. Het belang Biedt een menselijk leesbare naam voor de leverancier, waardoor dashboards en rapporten veel gemakkelijker te begrijpen zijn voor zakelijke gebruikers. Vindplaats Table: LFA1, Field: NAME1. This requires a join from EKKO-LIFNR to LFA1-LIFNR. Voorbeelden Staples Inc.Wereldwijd Tech SolutionsOffice Supply Co. | |||
| Reden van afwijzing RejectionReason | De redencode of tekst die verklaart waarom een inkoopaanvraag of -order werd afgewezen. | ||
| Omschrijving Dit attribuut legt de specifieke reden vast die is opgegeven wanneer een inkooporder wordt afgewezen tijdens de goedkeuringsworkflow. Deze Informatie is belangrijk voor het begrijpen van de grondoorzaken van herstelwerk en vertragingen. Het analyseren van afkeuringsredenen helpt bij het vinden van veelvoorkomende problemen zoals onjuiste prijsstelling, budgetoverschrijdingen of niet-compliant leveranciersselectie. Dit inzicht stelt de organisatie in staat om de grondoorzaken aan te pakken, de kwaliteit van de initiële inkooporder aanmaak te verbeteren en het goedkeuringsproces te vereenvoudigen. Het belang Biedt direct inzicht in waarom goedkeuringen mislukken, wat gerichte verbeteringen mogelijk maakt om rework te verlagen en goedkeuringsdoorlooptijden te verkorten. Vindplaats Deze Informatie kan moeilijk te lokaliseren zijn. Het kan zijn opgeslagen in lange tekstvelden of afhankelijk zijn van een aangepaste workflowconfiguratie. Vaak is specifieke implementatiekennis vereist. Voorbeelden Onjuiste prijsBudget overschreden.Dubbele aanvraag | |||
| Tijdstip van extractie LastDataUpdate | De `timestamp` die aangeeft wanneer de `data` voor het voor het laatst is bijgewerkt vanuit het bronsysteem. | ||
| Omschrijving Dit attribuut registreert de datum en tijd van de meest recente data-extractie of -update. Het biedt context over de relevantie van de geanalyseerde data. Het tonen van deze Informatie in dashboards is belangrijk voor gebruikers om te begrijpen of de inzichten gebaseerd zijn op bijna realtime-data of een historische momentopname. Het beheert de verwachtingen van gebruikers en zorgt ervoor dat beslissingen worden genomen op basis van data van een bekende leeftijd. Het belang Informeert gebruikers door de tijd heenigheid van de data, waarbij gewaarborgd wordt dat zij begrijpen of de analyse de meest actuele operationele status weergeeft. Vindplaats Deze timestamp wordt gegenereerd en toegevoegd door het data-extractie- of ETL-proces tijdens de uitvoering. Voorbeelden 2023-10-27T02:00:00Z2023-10-28T02:00:00Z | |||
| Valuta Currency | De valutacode voor het inkooporderbedrag. | ||
| Omschrijving Dit attribuut specificeert de valuta waarin de waarde van de inkooporder is gedenomineerd, zoals USD, EUR of GBP. Het biedt essentiële context voor alle geldelijke waarden. Voor wereldwijde organisaties is valuta belangrijk voor een correcte financiële analyse. Het maakt de juiste aggregatie en vergelijking van orderwaarden mogelijk, en alle monetaire KPI's moeten worden geïnterpreteerd in de context van hun valuta. Het belang Biedt de noodzakelijke context voor alle financiële waarden, wat zorgt voor een nauwkeurige financiële analyse, vooral in multinationale organisaties. Vindplaats Table: EKKO, Field: WAERS Voorbeelden USDEURJPY | |||
| Vestiging Plant | De fysieke locatie of vestiging waar de goederen geleverd moeten worden. | ||
| Omschrijving De vestiging is een onderdeel die een productiefaciliteit, magazijn of een andere locatie vertegenwoordigt waar goederen of diensten worden ontvangen. Analyseren per vestiging helpt bij het begrijpen van geografische variaties in het inkoopproces. Het kan verschillen in levertijden van leveranciers naar bepaalde locaties inzichtelijk maken of specifieke vestigingen vinden met inefficiënte ontvangstprocessen, wat de analyse van de tijdigheid van goederenontvangst ondersteunt. Het belang Specificeert de leveringslocatie, wat nuttig is voor het analyseren van regionale procesverschillen en logistieke prestaties. Vindplaats Table: EKPO, Field: WERKS Voorbeelden 100011002000 | |||
Inkoop tot betaling - Inkooporder-activiteiten
| Activiteit | Omschrijving | ||
|---|---|---|---|
| Goederenontvangst geboekt | Deze activiteit duidt op de fysieke ontvangst van goederen van een leverancier tegen een specifieke inkooporder. Het boeken van de goederenontvangst is een expliciete actie (bijv. via transactie MIGO) die een materiaaldocument aanmaakt en de voorraad bijwerkt. | ||
| Het belang Dit is een kritieke mijlpaal voor het volgen van de leveranciersprestaties en de start van het factuurverificatieproces. Het wordt gebruikt om percentages tijdige leveringen en de tijdigheid van de goederenontvangst te berekenen. Vindplaats Vastgelegd bij de aanmaak van een materiaaldocument. De gebeurtenis timestamp is de boekingsdatum (MKPF-BUDAT) of aanmaakdatum (MKPF-CPUDT) uit de header-tabel van het materiaaldocument (MKPF), gekoppeld aan de PO via de itemtabel (MSEG). Vastleggen Gebruik de boekings-/aanmaak-timestamp van de MKPF table voor materiaaldocumenten die verwijzen naar de PO. Gebeurtenistype explicit | |||
| Inkoopaanvraag Aangemaakt | Deze activiteit markeert de aanmaak van een formeel verzoek voor goederen of diensten. Het is een expliciete gebeurtenis die wordt vastgelegd wanneer een gebruiker een nieuw inkoopaanvraagdocument opslaat (via transacties zoals ME51N), wat een uniek record genereert in de EBAN table. | ||
| Het belang Dit is het primaire startpunt voor het inkoopproces. Het analyseren van de tijd van dit gebeurtenis tot de creatie van de inkooporder helpt de efficiëntie te meten van het omzetten van interne vraag in uitvoerbare orders. Vindplaats Vastgelegd bij de aanmaak van een entry in de header-tabel van de inkoopaanvraag (EBAN). De aanmaakdatum (EBAN-BADAT) en -tijd dienen als de timestamp voor deze gebeurtenis. Vastleggen Identificeer nieuwe vermeldingen in de EBAN-tabel op basis van aanmaakdatum. Gebeurtenistype explicit | |||
| Inkooporder Aangemaakt | Deze activiteit markeert de aanmaak van een formeel inkooporderdocument, wat een bindend contract is met een leverancier. Dit is een expliciete gebeurtenis, vastgelegd wanneer een gebruiker een inkooporder aanmaakt en opslaat (bijv. via transactie ME21N), wat resulteert in entries in de EKKO en EKPO tables. | ||
| Het belang Dit markeert de officiële start van de levenscyclus van de inkooporder. Het dient als een belangrijke mijlpaal voor het meten van zowel de doorlooptijd van aanvraag naar inkooporder als de end-to-end doorlooptijd van orderafhandeling. Vindplaats Vastgelegd vanuit de aanmaakdatum (EKKO-AEDAT) in de Purchase Order headertabel (EKKO) voor het corresponderende PO-nummer (EKKO-EBELN). Vastleggen Gebruik de aanmaak-timestamp van de EKKO table voor elke nieuwe Inkooporder. Gebeurtenistype explicit | |||
| Inkooporder Goedgekeurd | Vertegenwoordigt de definitieve goedkeuring van de inkooporder, waarmee deze geautoriseerd wordt om naar de leverancier te worden verzonden. Deze belangrijke mijlpaal wordt doorgaans afgeleid uit een wijziging in de vrijgavestatus van de PO naar een 'volledig vrijgegeven' of 'goedgekeurde' status. | ||
| Het belang Deze activiteit is belangrijk voor het berekenen van de KPI PO Approval Cycle Time en het vinden van knelpunten in de goedkeuringsworkflow. Het is een vereiste voor de meeste daaropvolgende activiteiten zoals het versturen van de order naar de leverancier. Vindplaats Afgeleid door het volgen van de wijzigingslogs (CDHDR/CDPOS) voor de inkooporderheader-tabel (EKKO) om te bepalen wanneer de definitieve vrijgavecode wordt toegepast of wanneer de algehele vrijgavestatusindicator (EKKO-FRGKE) op 'vrijgegeven' wordt ingesteld. Vastleggen Identificeer de timestamp wanneer de algehele vrijgavestatus van de inkooporder (EKKO-FRGKE) verandert naar de definitief goedgekeurde status. Gebeurtenistype inferred | |||
| Inkooporder naar Leverancier Verzonden | Deze activiteit markeert het punt waarop de goedgekeurde inkooporder officieel wordt verzonden naar de leverancier, bijvoorbeeld via EDI, email of print. Het is een expliciete gebeurtenis die wordt vastgelegd in de message control tables wanneer een output message succesvol is verwerkt. | ||
| Het belang Dit is een kritieke mijlpaal die het begin van de doorlooptijd van de leverancier markeert. Het analyseren van de tijd van dit gebeurtenis tot de goederenontvangst is belangrijk voor het ewaarderen van leveranciersprestaties en leveringstijdigheid. Vindplaats Vastgelegd in de berichtstatustabel (NAST). De timestamp kan worden ontleend aan NAST-DATVR en NAST-UHRVR wanneer de verwerkingsstatus (NAST-VSTAT) '1' is (succesvol verwerkt) voor het relevante PO-uitvoertype. Vastleggen Gebruik de verwerkings-timestamp van de NAST table voor de uitvoermelding van de PO. Gebeurtenistype explicit | |||
| Purchase Order voltooid | Geeft aan dat een inkooporderitem als volledig geleverd wordt beschouwd. Dit is een afgeleide gebeurtenis, doorgaans afgeleid van de 'Levering voltooid'-indicator die automatisch of handmatig wordt ingesteld op het inkooporderitem. | ||
| Het belang Deze activiteit dient als een logisch eindpunt voor het orderafhandelingsgedeelte van het proces. Het is belangrijk voor het berekenen van de end-to-end doorlooptijd van de inkooporder van aanmaak tot voltooiing. Vindplaats Afgeleid uit de wijzigingsdocumenten (CDHDR/CDPOS) die vastleggen wanneer de 'Levering voltooid'-indicator (EKPO-ELIKZ) op 'X' wordt ingesteld voor een inkooporderitem. Het als voltooid markeren van het laatste item kan de voltooiing van de gehele inkooporder betekenen. Vastleggen Identificeer de timestamp uit wijzigingsdocumenten wanneer de EKPO-ELIKZ flag is ingesteld. Gebeurtenistype inferred | |||
| Dienstenbevestiging Ingevuld | Voor servicegerichte inkooporders vertegenwoordigt deze activiteit de bevestiging dat diensten zijn geleverd. Het is een expliciet gebeurtenis dat wordt vastgelegd via het aanmaken van een Service Entry Sheet (bijv. via transactie ML81N). | ||
| Het belang Dit is het equivalent van een goederenontvangst voor diensten en is belangrijk voor het volgen van de uitvoering van serviceorders. Het activeert het financiële proces voor dienstbetaling. Vindplaats Vastgelegd vanuit de aanmaakdatum (ESSR-ERDAT) in de Service Entry Sheet headertabel (ESSR). De link naar de inkooporder bevindt zich in de ESLL-tabel. Vastleggen Gebruik de aanmaak-timestamp van de ESSR table voor dienstfiches gekoppeld aan de PO. Gebeurtenistype explicit | |||
| Goederen Geretourneerd | Vertegenwoordigt de retourzending van eerder ontvangen goederen aan de leverancier, vaak als gevolg van kwaliteitsproblemen of onjuiste leveringen. Dit is een expliciete gebeurtenis die wordt vastgelegd door het boeken van een materiaaldocument met een retourspecifiek bewegingstype. | ||
| Het belang Deze activiteit brengt problemen met leverancierskwaliteit of ordernauwkeurigheid aan het licht en is een belangrijke indicator voor herstelwerk. Het is belangrijk voor het berekenen van de KPI Goods Receipt Variance Rate. Vindplaats Vastgelegd in de materiaaldocumenttabellen (MKPF/MSEG) wanneer een retourbewegingstype (bijv. '122' voor 'Retourlevering aan Leverancier') wordt gebruikt. De boekingsdatum (MKPF-BUDAT) dient als de timestamp. Vastleggen Identificeer materiaaldocumenten met een type retourbeweging (bijv. 122) die verwijzen naar de oorspronkelijke inkooporder. Gebeurtenistype explicit | |||
| Inkoopaanvraag Goedgekeurd | Vertegenwoordigt de formele goedkeuring van een inkoopaanvraag, waarmee deze geautoriseerd wordt om te worden omgezet in een inkooporder. Deze gebeurtenis wordt afgeleid uit wijzigingen in de vrijgavestatusvelden binnen de data van de inkoopaanvraag, zoals bijgehouden door SAP's vrijgavestrategie workflow. | ||
| Het belang Het volgen van goedkeuringen is belangrijk voor het vinden van knelpunten in de pre-orderfase en het waarborgen van naleving van goedkeuringsbeleid. Vertragingen hier hebben directe impact op de algehele inkoopcyclustijd. Vindplaats Afgeleid uit de wijzigingslogs voor de inkoopaanvraagtabel (EBAN), specifiek door het monitoren van wijzigingen in de vrijgavestatusvelden (bijv. EBAN-FRGZU) of door het analyseren van wijzigingsdocumenten in CDHDR/CDPOS voor het EBAN-object. Vastleggen Bewaak wijzigingsdocumenten voor EBAN-vrijgavestatusvelden om de timestamp van de definitieve goedkeuring vast te stellen. Gebeurtenistype inferred | |||
| Inkooporder Afgewezen | Deze activiteit vindt plaats wanneer een goedkeurder een inkooporder afwijst tijdens de goedkeuringsworkflow. Het is een afgeleide gebeurtenis, voortkomend uit een statuswijziging in de release strategy data van de inkooporder, wat aangeeft dat een afwijzing heeft plaatsgevonden. | ||
| Het belang Het volgen van afwijzingen helpt bij het vinden van problemen met de PO datakwaliteit, niet-naleving van beleid, of problemen binnen de goedkeuringsmatrix. Dit leidt vaak tot herstelwerk en verhoogt de algehele cyclustijd. Vindplaats 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 Bewaak wijzigingslogs op intrekking van een vrijgavecode of een statuswijziging die afwijzing aanduidt. Gebeurtenistype inferred | |||
| Inkooporder Gewijzigd | Vertegenwoordigt elke wijziging aan een inkooporder na de initiële aanmaak, zoals wijzigingen in kwantiteit, prijs of leveringsdata. Deze wijzigingen worden expliciet vastgelegd in het wijzigingsdocumentsysteem van SAP. | ||
| Het belang Frequente wijzigingen, vooral na goedkeuring, duiden op procesinefficiënties, gebrekkige initiële planning of scope creep. Deze activiteit is belangrijk voor het dashboard 'Inkooporder Herwerkingen en Wijzigingen' en gerelateerde KPI's. Vindplaats Expliciet gelogd in de wijzigingsdocumentkop (CDHDR) en itemtabellen (CDPOS) voor het Purchase Order object (EINKBELEG). Elke wijziging creëert een nieuwe entry met een timestamp. Vastleggen Extraheer wijzigings-gebeurtenissen en tijdstempels uit CDHDR- en CDPOS-tabellen die gekoppeld zijn aan het inkoopordernummer. Gebeurtenistype explicit | |||
| Inkooporder Verwijderd | Vertegenwoordigt de annulering of logische verwijdering van een inkooporderitem, waardoor verdere verwerking zoals goederenontvangsten of facturering wordt voorkomen. Dit is een afgeleide gebeurtenis, vastgelegd wanneer de verwijderingsindicator op het PO-item is ingesteld. | ||
| Het belang Dit is een eindactiviteit die aangeeft dat een order is geannuleerd. Het analyseren van waarom en wanneer orders worden verwijderd, kan problemen in de vraagplanning of leveranciersselectie inzichtelijk maken. Vindplaats Afgeleid uit wijzigingsdocumenten (CDHDR/CDPOS) die tonen dat de verwijderingsindicator (EKPO-LOEKZ) op 'L' wordt ingesteld voor een inkooporderitem. Vastleggen Identificeer de timestamp uit wijzigingsdocumenten wanneer de EKPO-LOEKZ flag is ingesteld. Gebeurtenistype inferred | |||
| Inkoopordergoedkeuring Aangevraagd | Geeft aan dat een aangemaakte of gewijzigde inkooporder is ingediend ter goedkeuring volgens de geconfigureerde vrijgavestrategie. Deze gebeurtenis wordt afgeleid wanneer de vrijgavestrategie wordt geactiveerd en de inkooporder een status van 'in afwachting van goedkeuring' krijgt. | ||
| Het belang Het onderscheiden van PO-creatie en de start van het goedkeuringsproces helpt om de goedkeuringscyclus-KPI nauwkeurig te meten. Het benadrukt eventuele vertragingen voordat de goedkeuringsworkflow begint. Vindplaats Afgeleid uit wijzigingsdocumenten (CDHDR/CDPOS) voor de inkooporder (object EINKBELEG) die de initiële instelling van een vrijgavestatus tonen, of wanneer de algehele vrijgavestatus (EKKO-FRGKE) voor het eerst wordt ingesteld op een waarde die aangeeft dat een goedkeuringsproces actief is. Vastleggen Identificeer de eerste wijzigingsdocumentvermelding die de vrijgavestrategie voor de inkooporder activeert. Gebeurtenistype inferred | |||
| Kwaliteitsinspectie Uitgevoerd | Geeft aan dat ontvangen goederen een kwaliteitsinspectie hebben ondergaan. Deze activiteit wordt doorgaans afgeleid wanneer voor een inspectiepartij, aangemaakt op het moment van goederenontvangst, een gebruiksbeslissing is genomen in de Quality Management-module. | ||
| Het belang Voor sectoren waar kwaliteit van belangrijk belang is, helpt deze activiteit bij het analyseren van de duur en resultaten van het inspectieproces. Vertragingen hier kunnen knelpunten veroorzaken tussen goederenontvangst en beschikbaarheid voor gebruik. Vindplaats Afgeleid uit de Quality Management-module. Een inspectiepartij wordt aangemaakt (QALS-tabel) bij goederenontvangst, en de activiteit wordt gemarkeerd door het aanmaken van een gebruiksbeslissing (QAVE-tabel), die een timestamp bevat. Vastleggen Identificeer de timestamp van de gebruiksbeslissing in tabel QAVE voor de inspectiepartij gekoppeld aan het materiaaldocument. Gebeurtenistype inferred | |||
Extractiegidsen
Stappen
- ABAP-programma maken: Open de ABAP Bewerkenor met transactiecode SE38. Voer een naam in voor je nieuwe programma, bijvoorbeeld Z_PM_PO_EXTRACT, en klik op 'Maken'. Geef een titel op zoals 'Process Mining PO-data-extractie' en stel het type in op 'Executable Program'.
- Selectiescherm definiëren: Definieer in het programma de parameters voor het selectiescherm. Dit stelt gebruikers in staat de data te filteren die ze willen extraheren. Belangrijke parameters zijn onder meer het aanmaakdatumbereik 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 log-formaat. Deze structuur moet alle vereiste en aanbevolen attributen bevatten: PurchaseOrder, Activiteit, EventTime, GebruikerNaam, VendorNumber, OrderBedrag, MaterialGroup, CompanyCode, en DocumentType.
- Datalogica implementeren: Schrijf de kern ABAP-logica om data te selecteren voor elk van de 14 vereiste activiteiten. Dit omvat het query'en van meerdere SAP-tabellen zoals EKKO, EKPO, EKBE, EBAN, CDHDR, CDPOS, en NAST. Gebruik een aparte subroutine (PERFORM) voor elke activity om de code georganiseerd te houden.
- Inkoopaanvraagdata selecteren: Query de EBAN-tabel voor 'Purchase Requisition Created' gebeurtenissen, en koppel deze aan Purchase Orders via de EKPO-tabel. Gebruik de changelogtabellen (CDHDR, CDPOS) om 'Purchase Requisition Approved' gebeurtenissen te vinden door wijzigingen in de velden voor de vrijgavestatus te volgen.
- Kern inkooporder-gebeurtenissen selecteren: Query de EKKO- en EKPO-tabellen voor de 'Purchase Order Created' gebeurtenis. Gebruik de changelogtabellen (CDHDR, CDPOS) op object EINKBELEG om 'Purchase Order Changed', 'Purchase Order Approved', 'Purchase Order Rejected', 'Purchase Order Completed', en 'Purchase Order Verwijderend' gebeurtenissen te extraheren, gebaseerd op wijzigingen in specifieke velden zoals release indicators en deletion flags.
- PO-communicatie-gebeurtenissen selecteren: Query de NAST-tabel om records te vinden waarbij de PO succesvol werd verzonden, waarmee de 'Purchase Order Sent to Vendor' activity wordt vastgelegd.
- Events voor goederen en diensten selecteren: Query de EKBE-tabel voor materiaaldocumentboekingen om 'Goods Receipt Posted' en 'Goods Returned' activiteiten te vinden, gebaseerd op de bewegingstypecategorie. Query ESSR en ESLL voor service entry sheets om 'Services Confirmation Entered' vast te leggen.
- Kwaliteitsbeheer-gebeurtenissen selecteren: Indien de Quality Management-module in gebruik is, query tabellen QALS en QAVE om te vinden wanneer een usage decision werd genomen voor een inspectielot gekoppeld aan een PO, wat de 'Quality Inspection Performed' activity vertegenwoordigt.
- Data combineren en formatteren: Consolidereer de data van alle individuele selecties in één uiteindelijke internal table. Zorg ervoor dat het EventTime-veld consistent is geformatteerd (bijv. YYYY-MM-DDTHH:MI:SS).
- Bestandsdownload implementeren: Voeg functionaliteit toe om de uiteindelijke internal table als een bestand te downloaden. Het aanbevolen formaat is een tabgescheiden of CSV-bestand, wat kan worden bereikt met behulp van de GUI_DOWNLOAD-functieblok.
- Uitvoeren en opslaan: Voer het programma uit met transactie SE38 of SA38. Vul de selectiecriteria in en draai het rapport. Sla desgevraagd het uitvoerbestand op je lokale machine op met een .csv-extensie, klaar voor upload.
Configuratie
- Datumtraject: Het is belangrijk om een specifiek datumtraject te definiëren voor de extractie, doorgaans gebaseerd op de aanmaakdatum van de inkooporder (EKKO-AEDAT). Een periode van 3-6 maanden is vaak een goed startpunt om een balans te vinden tussen datavolume en procesinzicht.
- Bedrijfscode (BUKRS): Filter op één of meerdere bedrijfscodes om de extractie te beperken tot relevante juridische entiteiten. Dit is een belangrijke parameter voor prestaties en relevantie.
- Type inkoopdocument (BSART): Filter op specifieke documenttypen (bijv. 'NB' voor standaard inkooporder) om de analyse te richten op standaardprocessen en zo nodig speciale inkooptypen uit te sluiten.
- Datagranulariteit: De extractie is ontworpen voor het inkooporder-itemniveau. De Case-ID is het inkoopordernummer (EBELN). Alle gebeurtenissen, inclusief die op itemniveau zoals goederenontvangsten, worden gekoppeld aan deze hoofdcase-ID.
- Prestatieoverwegingen: Voor grote datasets is het raadzaam het programma als achtergrondtaak (SM36) in te plannen om timeout-fouten te voorkomen. Zorg ervoor dat database-indexen bestaan op sleutelvelden die worden gebruikt in WHERE-clausules, met name voor tabellen zoals CDHDR en CDPOS.
- Verplichten: De gebruiker die het rapport uitvoert, heeft autorisatie nodig voor de ABAP-workbench (SE38) voor ontwikkelings- en uitvoerrechten van het programma. De gebruiker heeft tevens 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 tot stand brengen: Verkrijg read-only-inloggegevens en verbindingsdetails (hostname, port, database name) voor de onderliggende SAP ECC-database. Zorg ervoor dat je de benodigde clienttools, zoals DBeaver, SQL Developer, of SSMS, geïnstalleerd heeft.
- SAP-schema vinden: Maak verbinding met de database en identificeer het primaire SAP schema waar de tabellen zich bevinden. Dit is vaak SAPSR3, SAPHANADB, of een vergelijkbare systeem-specifieke naam. Je moet alle tabelnamen in de query van dit schema voorzien als het niet de standaard is voor je gebruiker.
- SQL-query controleren: Open het meegeleverde SQL-script in je clienttool. Deze volledige query is ontworpen om 14 afzonderlijke activiteiten uit het Purchase-to-Pay-proces te extraheren door meerdere SAP-tabellen te joinen.
- Queryparameters aanpassen: Zoek de PO_BASE Common Table Expression (CTE) aan het begin van het script. Pas de placeholder-waarden aan om de reikwijdte van je extractie te definiëren:
- [START_DATE] en [END_DATE]: Stel het datumbereik voor de analyse in (bijv. '20230101' en '20230630'). Filteren op het AEDAT (Changed On)-veld wordt aanbevolen.
- [COMPANY_CODE_1], [COMPANY_CODE_2]: Specificeer de SAP-bedrijfscodes die moeten worden opgenomen.
- [DOC_TYPE_1], [DOC_TYPE_2]: Specificeer de PO-documenttypen die moeten worden opgenomen.
- [Your SAP Schema]: Vervang deze placeholder door je daadwerkelijke SAP-schemanaam in het hele script.
- De query uitvoeren: Voer het aangepaste SQL-script uit op de SAP-database. De uitvoeringstijd varieert afhankelijk van het datumbereik, datavolume en de databaseprestaties.
- De resultaten inspecteren: Zodra de query is voltooid, voert je een snelle controle uit van de output. Controleer op een redelijk aantal rijen en zorg ervoor dat belangrijke kolommen zoals PurchaseOrder, Activiteit, en EventTime naar verwachting zijn gevuld.
- Data exporteren naar CSV: Exporteer de gehele resultaatset vanuit je SQL-client naar een CSV-bestand. Gebruik UTF-8-codering om tekenproblemen te voorkomen.
- Voorbereiden op upload: Zorg ervoor dat de kolomkoppen in je CSV-bestand precies overeenkomen met de vereiste attribuut names: PurchaseOrder, Activiteit, EventTime, GebruikerNaam, VendorNumber, OrderBedrag, MaterialGroup, CompanyCode, DocumentType.
- Uploaden naar Process Mining-tool: Upload de uiteindelijke CSV-bestand naar je process mining-applicatie voor analyse en visualisatie.
Configuratie
- Verplichten: Directe, alleen-lezen toegang tot de onderliggende SAP ECC-database is vereist. Gebruikers hebben voldoende autorisatie nodig om tabellen zoals EKKO, EKPO, EKBE, EBAN, CDHDR, CDPOS en NAST te bevragen.
- Datumtrajectfiltering: Het is belangrijk om een datumtrajectfilter toe te passen om het datavolume te beperken. Filteren op EKKO.AEDAT (wijzigingsdatum inkooporder) voor een periode van 3-6 maanden is een gangbaar startpunt. Grote datumtrajecten kunnen leiden tot extreem lange query-uitvoeringstijden.
- Sleuteldatafilters: Om een gerichte analyse te garanderen, filter altijd op EKKO.BUKRS (bedrijfscode) en EKKO.BSART (documenttype). Dit vernauwt de reikwijdte tot relevante juridische entiteiten en bedrijfsprocessen.
- Prestatieoverwegingen: De query voegt meerdere grote tabellen samen, inclusief de wijzigingshistorietabellen (CDHDR, CDPOS). Dit kan bron-intensief zijn. Het wordt sterk aanbevolen om deze extractie buiten piekuren uit te voeren of tegen een gerepliceerde, niet-productiedatabase om impact op de systeemprestaties te voorkomen.
- Wijzigingsdocumentlogging: De nauwkeurigheid van activiteiten zoals 'Goedgekeurd', 'Afgewezen', 'Voltooid' en 'Gewijzigd' is afhankelijk van actieve wijzigingsdocumentlogging voor de relevante velden in SAP. Bevestig met je SAP-beheerder dat 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
- Verplichten en verbinding: Zorg ervoor dat je externe ETL-tool de SAP Certified Connector geïnstalleerd en gelicentieerd heeft. Configureer in de administratieconsole 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 met de juiste RFC- en tabelleesautorisaties nodig.
- Identificeer brontabellen: Definieer binnen je ETL-taak of dataflow de vereiste SAP-tabellen als databronnen. De belangrijkste tabellen zijn onder andere 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).
- Extraheer 'Inkooporder gecreëerd': Maak een dataflow die de EKKO-tabel als bron gebruikt. Filter records op basis van het gewenste datumbereik (bijv. met AEDAT) en de organisatorische reikwijdte (bijv. BUKRS voor Company Code, BSART voor Document Type). Koppel EKKO.EBELN aan PurchaseOrder, 'Inkooporder gecreëerd' aan Activiteit, en combineer AEDAT en ERZET voor de EventTime. Koppel andere vereiste attributen.
- Extraheer 'Goederenontvangst geboekt': Maak een aparte dataflow die MSEG als bron gebruikt en deze koppelt aan MKPF op basis van MBLNR en MJAHR. Filter op relevante bewegingstypen, zoals '101'. Koppel MSEG.EBELN aan PurchaseOrder, 'Goederenontvangst geboekt' aan Activiteit, en gebruik MKPF.CPUDT en MKPF.CPUTM voor de EventTime.
- Extraheer wijzigingsgerelateerde gebeurtenissen (goedkeuringen, wijzigingen, verwijderingen): Maak een dataflow die CDHDR en CDPOS als bron gebruikt, gekoppeld op CHANGENR. Deze enkele bron kan worden gebruikt om meerdere activiteiten af te leiden.
- Filter op OBJECTCLAS = 'EINKBELEG' en TABNAME = 'EKPO'.
- Voor 'Inkooporder goedgekeurd', filter op wijzigingen in het vrijgavestatusveld (bijv. FNAME = 'FRGZU') waarbij de nieuwe waarde (VALUE_NEW) de definitieve goedkeuring aangeeft.
- Voor 'Inkooporder verwijderd', filter op wijzigingen in de verwijderingsindicator (FNAME = 'LOEKZ') waarbij de nieuwe waarde 'L' is.
- Voor 'Inkooporder gewijzigd', filter op andere relevante veldwijzigingen, met uitzondering van de specifieke statusvelden die voor andere activiteiten worden gebruikt.
- Gebruik voor al deze gebeurtenissen CDHDR.UDATE en CDHDR.UTIME voor de EventTime.
- Extraheer 'Inkoopaanvraag'-gebeurtenissen: Maak een dataflow vanuit EBAN voor 'Inkoopaanvraag gecreëerd'. Om dit te koppelen aan een PurchaseOrder case, koppel EBAN aan EKPO met behulp van het aanvraagnummer (BANFN) en item (BNFPO). Voor 'Inkoopaanvraag goedgekeurd', gebruik CDHDR/CDPOS met OBJECTCLAS = 'BANF'. Dit vereist zorgvuldige koppeling om te garanderen dat de gebeurtenis wordt gekoppeld aan de uiteindelijke PO.
- Extraheer 'PO verzonden naar leverancier': Maak een dataflow die de NAST-tabel als bron gebruikt. Filter op OBJECTKEY (dat het PO-nummer bevat), het relevante uitvoertype (KSCHL) en een succesvolle verwerkingsstatus (VSTAT = '1'). Gebruik ERDAT en UHR voor EventTime.
- Combineer activiteitsstromen: Gebruik een 'Union'- of 'Merge'-transformatie in je ETL-tool om de outputs van alle individuele dataflows, gemaakt in de vorige stappen, te combineren. Zorg ervoor dat de kolomnamen en gegevenstypen consistent zijn voor alle stromen (PurchaseOrder, Activiteit, EventTime, etc.).
- Conversie van gegevenstypen en -formaten: Zorg ervoor dat de kolom EventTime wordt geconverteerd naar een consistent timestamp-formaat (bijv. JJJJ-MM-DD UU:MM:SS). Converteer OrderBedrag naar een standaard decimaal formaat.
- Definieer de doelbestemming: Configureer een target of 'sink' voor je gecombineerde datastroom. Dit is doorgaans een plat bestand, zoals een CSV- of Parquet-bestand. Configureer het scheidingsteken, de tekstomgrenzers en de koptekstopties.
- Uitvoeren en bevestigen: Voer de volledige ETL-taak uit. Voer validatiecontroles uit op het uitvoerbestand om te controleren of alle 14 activiteiten aanwezig zijn, het aantal rijen redelijk is en de belangrijkste attributen correct zijn ingevuld.
- Plannen en exporteren: Eenmaal gevalideerd, plant je de ETL-taak voor periodieke uitvoering (bijv. nachtelijk) om de data actueel te houden. Het gegenereerde bestand is nu klaar om te worden geüpload naar je process mining-tool.
Configuratie
- Verplichten: Een commerciële ETL-tool (bijv. Informatica PowerCenter, talend, SAP Data Services) met de bijbehorende SAP Certified Connector voor ECC. Een SAP dialoog- of systeemgebruiker met autorisaties voor S_RFC en S_TABU_DIS voor de vereiste tabellen.
- SAP-verbinding: De connector moet worden geconfigureerd met de SAP-applicatieserver, het systeemnummer, de client, gebruiker en het wachtwoord. Het gebruik van Secure Network Communications (SNC) wordt aanbevolen.
- Datumtrajectfilter: Het is belangrijk om een datumtrajectfilter toe te passen om het datavolume te beperken. Een gangbare praktijk is om te filteren op EKKO.AEDAT (aanmaakdatum inkooporder) voor de laatste 3 tot 12 maanden. Dit filter moet bij de bron worden toegepast om te voorkomen dat er overmatige data uit SAP wordt opgehaald.
- Filters voor organisatorische reikwijdte: Filter altijd op EKKO.BUKRS (bedrijfscode) en overweeg te filteren op EKPO.WERKS (fabriek) of EKKO.EKORG (inkooporganisatie) om de analyse te versmallen tot een specifieke bedrijfseenheid.
- Documenttypefilter: Gebruik EKKO.BSART om alleen relevante inkoopordertypen op te nemen en voorraadtransfers of andere interne documenten uit te sluiten die geen deel uitmaken van het standaard P2P-proces.
- Prestatie-optimalisatie: Extractie uit wijzigingsdocumenttabellen (CDHDR, CDPOS) kan traag zijn. Zorg ervoor dat filters op OBJECTCLAS, OBJECTID en UDATE worden toegepast. Pas de instelling 'Packet Size' in de SAP-connector aan om de gegevensoverdrachtssnelheden te optimaliseren. Voor zeer grote systemen kun je een initiële historische datalading overwegen, gevolgd door geplande delta-ladingen.
a Voorbeeldquery config
/*
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]);