Data Template: Procure-to-Pay - Ordine di acquisto
Il suo Template dati Procure‑to‑Pay - Ordine d’acquisto
- Attributi consigliati da raccogliere
- Attività chiave da tracciare
- Guida all’estrazione per SAP ECC
Purchase to Pay - Attributi dell’ordine di acquisto
| Nome | Descrizione | ||
|---|---|---|---|
Activity Activity | Il nome dello specifico evento o passaggio di processo avvenuto nel ciclo di vita dell’Ordine di acquisto. | ||
Descrizione Questo attributo descrive un singolo passaggio del processo, ad esempio 'Purchase Order Created', 'Purchase Order Approved' o 'Goods Receipt Posted'. La sequenza di queste attività costituisce il flusso di processo per ogni ordine d'acquisto. L'analisi della sequenza, della frequenza e della durata tra le attività è il cuore del Process Mining. Consente di identificare colli di bottiglia, cicli di rilavorazione e deviazioni dallo standard, abilitando interventi mirati e iniziative di standardizzazione. Perché è importante Le attività definiscono le fasi del processo. Analizzarne la sequenza e i tempi rivela il flusso reale, i colli di bottiglia e le deviazioni. Dove trovare Derivato da diverse tabelle SAP e log di transazione, come CDHDR/CDPOS per le modifiche, EKBE per GR/IR ed EBAN per le richieste di acquisto. Spesso richiede una logica personalizzata o un programma di estrazione dedicato. Esempi Ordine di acquisto creatoOrdine di acquisto approvatoRicevimento merci contabilizzato | |||
Ordine d'Acquisto PurchaseOrder | Identificativo univoco del documento di ordine d'acquisto (PO), che funge da istanza principale per tracciare il processo di approvvigionamento. | ||
Descrizione Il numero dell'ordine d'acquisto (PO) è l'identificativo centrale che collega tutte le attività dalla creazione fino alla registrazione finale dell'entrata merci e al completamento. Ogni numero PO univoco rappresenta una singola istanza del processo di approvvigionamento. Nel Process Mining, questo attributo è essenziale per ricostruire il percorso end-to-end di ogni acquisto. Consente analisi puntuali dei tempi di ciclo, delle varianti di processo e delle verifiche di conformità per ogni singolo ordine, fungendo da base dell'intero modello di processo. Perché è importante È l'identificativo centrale che collega tutti gli eventi correlati, consentendo di analizzare l'intero ciclo di vita di ciascun ordine d'acquisto. Dove trovare Tabella: EKKO, Campo: EBELN Esempi 450001762345000176244500017625 | |||
Timestamp Evento EventTime | La data e l'ora precise in cui si è verificata l'attività. | ||
Descrizione Questo timestamp indica l'istante esatto in cui si è verificato un evento, ad esempio quando una PO viene approvata o quando si registra un'entrata merci. Fornisce l'ordine cronologico di tutte le attività all'interno di un caso. I timestamp sono fondamentali per il Process Mining perché abilitano tutte le analisi basate sul tempo: dal calcolo dei tempi di ciclo tra le attività, all'identificazione dei ritardi, all'analisi del throughput di processo, fino alla misurazione delle performance rispetto ai Service Level Agreement (SLA). Perché è importante Questo timestamp è fondamentale per calcolare tutte le metriche basate sulla durata, come i tempi di ciclo e i colli di bottiglia, e per ordinare gli eventi in ordine cronologico. Dove trovare Derivato da vari campi data/ora nelle tabelle SAP, come EKKO-AEDAT (Data modifica), CDHDR-UDATE/UTIME (timestamp del log delle modifiche) o EKBE-BUDAT (Data registrazione). Esempi 2023-04-15T10:05:31Z2023-04-16T14:22:00Z2023-05-01T09:00:15Z | |||
Codice Società CompanyCode | Identificativo dell'entità legale o dell'azienda che avvia l'acquisto. | ||
Descrizione Nel sistema SAP, la Società (Company Code) rappresenta un'entità giuridica indipendente. Tutte le transazioni sono registrate a livello di Società, il che la rende un'unità organizzativa fondamentale. Analizzare il processo per Società consente di confrontare l'efficienza degli acquisti e la conformità tra diverse business unit o Paesi. Aiuta a individuare le best practice presenti in un'entità da replicare altrove o a evidenziare le unità che incontrano difficoltà nel processo. Perché è importante Rappresenta l'entità giuridica, consentendo il confronto delle performance di processo e le verifiche di conformità tra le diverse parti dell'organizzazione. Dove trovare Tabella: EKKO, Campo: BUKRS Esempi 10002100US01 | |||
Gruppo merceologico MaterialGroup | Una classificazione per raggruppare materiali o servizi con caratteristiche simili. | ||
Descrizione Il Gruppo merci, o categoria di acquisto, serve a classificare il tipo di beni o servizi acquistati. Esempi: 'Hardware IT', 'Forniture per ufficio' o 'Servizi professionali'. Questo attributo è cruciale per l'analisi della spesa e per comprendere i modelli di approvvigionamento. Consente di filtrare il processo per analizzare come vengono gestite le diverse categorie, chi le approva e quali fornitori le forniscono. È una dimensione chiave nella dashboard 'Purchase Order Value Analysis'. Perché è importante Consente di segmentare il processo per categoria di prodotto o servizio, mettendo in luce comportamenti, tempi di ciclo o fornitori diversi a seconda della tipologia di spesa. Dove trovare Tabella: EKPO, Campo: MATKL Esempi 00101IT_HWCONSULT | |||
Importo dell’ordine OrderAmount | Valore monetario totale della riga dell'ordine d'acquisto. | ||
Descrizione Questo attributo rappresenta il valore totale di una specifica riga dell'ordine d'acquisto, calcolato come quantità moltiplicata per il prezzo netto. Per ottenere il valore complessivo dell'ordine, è necessario aggregare gli importi delle righe. Analizzare il processo per fasce di importo è cruciale per individuare transazioni di alto valore che possono richiedere controlli più rigorosi o percorsi di approvazione differenti. Alimenta la Dashboard 'Purchase Order Value Analysis' e aiuta a dare priorità agli interventi di miglioramento sugli ordini a maggior impatto economico. Perché è importante Quantifica l'impatto finanziario di ogni acquisto, consentendo analisi basate sul valore per dare priorità agli ordini ad alto valore o individuare opportunità di risparmio. Dove trovare Tabella: EKPO, Campo: NETWR (Valore netto dell'ordine). Esempi 1500.00250.7512345.50 | |||
Nome Utente UserName | L'ID utente della persona che ha eseguito l'attività. | ||
Descrizione Questo attributo rileva lo username SAP del dipendente che ha creato, modificato o approvato un documento. Per i passaggi automatizzati può riportare un ID utente di sistema o batch. L'analisi per utente aiuta a individuare esigenze di formazione, profili ad alte prestazioni o potenziali criticità di conformità. È fondamentale per costruire dashboard sulla distribuzione del carico di lavoro, sul rispetto della matrice di approvazione e per comprendere le performance di team o singoli. Perché è importante Attribuisce le azioni degli utenti a persone specifiche, abilitando l’analisi delle prestazioni, del carico di lavoro e dell’aderenza ai protocolli di Conformità. Dove trovare Tabella: EKKO, Campo: ERNAM (Creato da); Tabella: CDHDR, Campo: USERNAME (Modificato da). Esempi JSMITHMBROWNBATCH_USER | |||
Numero del fornitore VendorNumber | Identificativo univoco del fornitore. | ||
Descrizione È il codice che identifica in modo univoco il fornitore da cui si approvvigionano beni o servizi. È un dato anagrafico critico nel processo di procurement. Questo attributo è indispensabile per le analisi incentrate sul fornitore. Consente di valutare le performance di consegna, confrontare i lead time tra fornitori diversi e analizzare i modelli di spesa. È la dimensione primaria della Dashboard 'Vendor Delivery Performance'. Perché è importante Abilita l’analisi delle prestazioni dei fornitori, aiutando a individuare quelli affidabili e quelli che causano ritardi o problemi di qualità. Dove trovare Tabella: EKKO, Campo: LIFNR Esempi 100345V-20598700112 | |||
Tipo Documento DocumentType | Un codice che classifica i diversi tipi di ordini di acquisto. | ||
Descrizione Il tipo di documento è una configurazione in SAP che controlla l'intervallo di numerazione, la selezione dei campi e il flusso complessivo del processo per un ordine d'acquisto. Ad esempio, possono esistere tipi diversi per PO standard, PO di servizi o ordini di trasferimento di stock. Questo attributo è una dimensione molto utile per l'analisi, perché i diversi tipi di documento seguono spesso processi volutamente differenti. Filtrare per tipo di documento consente un confronto omogeneo dei tempi di ciclo e dei flussi di processo. Perché è importante Distingue tra diverse tipologie di processo d’acquisto (es. standard, servizi, resi), che spesso presentano percorsi e aspettative di prestazione differenti. Dove trovare Tabella: EKKO, Campo: BSART Esempi NBFOUB | |||
Consegna puntuale IsOnTimeDelivery | Un indicatore che segnala se le merci sono state ricevute entro o prima della data di consegna richiesta. | ||
Descrizione Questo attributo booleano è vero se il timestamp dell'attività 'Goods Receipt Posted' è uguale o antecedente alla 'Requested Delivery Date'. Fornisce un esito chiaro e binario sulla performance di consegna per ciascuna riga d'ordine. Questo attributo è la base del KPI 'On-Time Goods Receipt Rate'. Semplifica l'analisi delle performance dei fornitori e dell'efficienza del ricevimento interno consentendo aggregazioni e filtri immediati tra consegne puntuali e in ritardo. Perché è importante Fornisce una metrica chiara di successo/insuccesso sulla puntualità di consegna, a supporto diretto dei KPI e delle dashboard sulle performance dei fornitori. Dove trovare Attributo calcolato ottenuto confrontando la data di registrazione del ricevimento merci (EKBE-BUDAT) con la data di consegna richiesta (EKPO-EINDT). Esempi truefalse | |||
Data di consegna richiesta RequestedDeliveryDate | La data in cui l’azienda ha richiesto al fornitore la consegna dei beni o servizi. | ||
Descrizione È la data di consegna obiettivo indicata nell'ordine d'acquisto. Costituisce il riferimento rispetto al quale misurare la performance reale di consegna. Questa data è essenziale per calcolare il KPI 'On-Time Goods Receipt Rate'. Confrontando la data effettiva di ricevimento merci con quella richiesta, le organizzazioni possono misurare in modo quantitativo l'affidabilità del fornitore e l'efficienza del ricevimento interno, a supporto diretto della Dashboard 'Vendor Delivery Performance'. Perché è importante È la data obiettivo di consegna, fondamentale per calcolare i KPI di puntualità e valutare l'affidabilità del fornitore. Dove trovare Tabella: EKPO, Campo: EINDT Esempi 2023-06-102023-07-222023-08-01 | |||
È una modifica post-approvazione IsPostApprovalChange | Un indicatore che segnala se una modifica all’ordine di acquisto (PO) è avvenuta dopo l’approvazione iniziale. | ||
Descrizione Questo attributo booleano è vero se viene rilevata un'attività 'Purchase Order Changed' successiva a 'Purchase Order Approved' per il medesimo ordine. Aiuta a isolare modifiche problematiche che avvengono nelle fasi finali del processo. Questo campo calcolato supporta direttamente il KPI 'Post-Approval PO Change Rate' e la Dashboard 'Purchase Order Rework and Changes'. Consente di quantificare e mettere in evidenza modifiche dirompenti che possono causare ritardi e richiedere una nuova approvazione, segnalando criticità nelle specifiche o nell'impostazione iniziale. Perché è importante Misura direttamente la rilavorazione dopo l’approvazione, un KPI chiave per la stabilità e l’efficienza del processo. Valori elevati indicano problemi nella definizione dei requisiti a monte. Dove trovare Attributo calcolato derivato dalla sequenza delle attività nell'Event Log. Esempi truefalse | |||
Gruppo acquisti PurchasingGroup | Il buyer specifico o il gruppo di buyer responsabile dell'attività di approvvigionamento. | ||
Descrizione Il Gruppo acquisti rappresenta il singolo buyer o il team di buyer responsabile di una specifica attività di acquisto. È il principale punto di contatto per i fornitori. Questo attributo offre un livello di analisi più granulare rispetto all'Organizzazione acquisti. Aiuta a comprendere la distribuzione del carico di lavoro tra i buyer e a individuare differenze di performance a livello di buyer, a supporto dell'allocazione delle risorse e delle iniziative di formazione. Perché è importante Offre una vista granulare su chi è responsabile dell'acquisto, consentendo analisi dettagliate di carico di lavoro e performance a livello di buyer o di team. Dove trovare Tabella: EKKO, Campo: EKGRP Esempi 001002N01 | |||
Motivo del Rigetto RejectionReason | Codice o testo della motivazione che spiega perché una richiesta d'acquisto o un ordine è stato respinto. | ||
Descrizione Questo attributo registra la motivazione specifica indicata quando un ordine d'acquisto viene respinto durante il workflow di approvazione. Queste informazioni sono cruciali per comprendere le cause profonde di rilavorazioni e ritardi. Analizzare le motivazioni di rifiuto aiuta a individuare problemi ricorrenti come prezzi errati, sforamenti di budget o scelta di fornitori non conformi. Queste evidenze consentono di affrontare le cause alla radice, migliorare la qualità della creazione iniziale del PO e snellire il processo di approvazione. Perché è importante Offre insight diretti sui motivi per cui le approvazioni falliscono, abilitando interventi mirati per ridurre le rilavorazioni e accorciare i tempi di approvazione. Dove trovare Questa informazione può essere difficile da reperire. Potrebbe trovarsi in campi di testo esteso o dipendere da configurazioni personalizzate del workflow. Spesso richiede conoscenze specifiche dell'implementazione. Esempi Prezzo erratoBudget superatoRichiesta duplicata | |||
Nome Fornitore VendorName | Denominazione legale del fornitore. | ||
Descrizione Il nome descrittivo del fornitore, più intuitivo del numero del fornitore. In genere proviene dall'anagrafica fornitori. Mentre il Numero del fornitore è usato per i join e l'identificazione univoca, il Nome fornitore è fondamentale per Dashboard e report rivolti agli utenti. Rende le analisi più intuitive e accessibili a chi non conosce i codici dei fornitori. Perché è importante Fornisce un nome leggibile per il fornitore, rendendo dashboard e report molto più comprensibili per gli utenti di business. Dove trovare Tabella: LFA1, Campo: NAME1. È necessario un join da EKKO-LIFNR a LFA1-LIFNR. Esempi Staples Inc.Global Tech SolutionsOffice Supply Co. | |||
Organizzazione acquisti PurchasingOrganization | Unità organizzativa responsabile della negoziazione dei prezzi e dell'approvvigionamento di materiali o servizi. | ||
Descrizione L'Organizzazione acquisti è un'unità organizzativa chiave in SAP responsabile delle attività di approvvigionamento. Può essere centralizzata per l'intera azienda o decentralizzata per stabilimento o area geografica. Analizzare le performance di processo per Organizzazione acquisti aiuta a identificare i team più efficienti. Consente di confrontare metriche come tempo di ciclo, tassi di rilavorazione e costi tra diverse unità organizzative, mettendo in luce best practice e aree che necessitano di supporto. Perché è importante Identifica il team acquisti responsabile, abilitando confronti di performance e analisi tra diverse unità organizzative. Dove trovare Tabella: EKKO, Campo: EKORG Esempi 1000US01DE01 | |||
Richiesta di acquisto PurchaseRequisition | L’identificativo della richiesta d’acquisto che ha preceduto l’Ordine di acquisto. | ||
Descrizione Questo attributo collega l'ordine d'acquisto alla richiesta d'acquisto da cui origina. Non tutti gli ordini sono preceduti da una richiesta. Questo collegamento è fondamentale per analizzare la Dashboard 'Requisition to Order Conversion' e il KPI 'PR to PO Conversion Rate'. Consente di misurare l'efficienza del processo a monte, dalla richiesta iniziale alla creazione dell'ordine formale, e di individuare gli ordini non conformi creati senza la relativa richiesta. Perché è importante Collega il PO alla richiesta d'acquisto (PR) di origine, consentendo l'analisi del processo di conversione da PR a PO e l'individuazione dei PO creati senza una richiesta precedente. Dove trovare Tabella: EKPO, Campo: BANFN Esempi 1001589010015891 | |||
Sistema di Origine SourceSystem | Il sistema da cui i dati sono stati estratti. | ||
Descrizione Questo attributo identifica l'origine dei dati, in genere un identificativo dell'istanza SAP ECC (ad es. 'ECC_PROD_100'). In ambienti con più sistemi, aiuta a distinguere le sorgenti dati. Ai fini di governance e data lineage, conoscere il sistema sorgente è fondamentale. Garantisce l'integrità dei dati e supporta la risoluzione di problemi di estrazione o qualità, soprattutto quando i dati confluiscono da diversi sistemi o moduli ERP. Perché è importante Individua l'origine dei dati, aspetto cruciale per la data governance, la validazione e la gestione delle analisi su più sistemi. Dove trovare Di norma è un valore statico aggiunto durante l'estrazione dei dati per etichettare il dataset con il sistema di origine. Esempi SAP_ECC_PRODECC_EU_100S4H_FIN | |||
Stabilimento Plant | Sede fisica o stabilimento in cui devono essere consegnati i beni. | ||
Descrizione Lo stabilimento è un'unità organizzativa che rappresenta un sito produttivo, un magazzino o un'altra sede in cui si ricevono beni o servizi. L'analisi per stabilimento aiuta a comprendere le variazioni geografiche nel processo di approvvigionamento. Può evidenziare differenze nei tempi di consegna dei fornitori verso determinate sedi o mettere in luce stabilimenti con processi di ricezione inefficaci, a supporto dell'analisi della puntualità delle registrazioni di entrata merci. Perché è importante Indica il luogo di consegna, utile per analizzare le differenze di processo per area e le performance logistiche. Dove trovare Tabella: EKPO, Campo: WERKS Esempi 100011002000 | |||
Tempo di ciclo end-to-end EndToEndCycleTime | Il tempo totale trascorso dalla prima all'ultima attività per un ordine d'acquisto. | ||
Descrizione Questa metrica misura la durata complessiva dell'intero processo di Ordine di Acquisto, dal primo evento registrato (ad es. "Purchase Requisition Created") fino all'evento finale (ad es. "Purchase Order Completed"). È un KPI fondamentale per misurare l'efficienza complessiva del processo. Offre una visione di alto livello delle performance e, tramite la sua analisi, aiuta a individuare i casi più lunghi e i colli di bottiglia più frequenti. Supporta direttamente la dashboard "End-to-End PO Cycle Time Analysis" e il KPI "Avg End-to-End PO Cycle Time". Perché è importante Misura la velocità e l'efficienza complessive dell'intero processo di approvvigionamento, fornendo un indicatore chiave dello stato di salute del processo. Dove trovare Attributo calcolato, determinato sottraendo il timestamp del primo evento da quello dell'ultimo per ciascun caso. Esempi 10 giorni 4 ore22 giorni e 1 ora5 giorni e 8 ore | |||
Ultimo Data Update LastDataUpdate | Il timestamp che indica quando i dati sono stati aggiornati l'ultima volta dal sistema sorgente. | ||
Descrizione Questo attributo registra data e ora dell'ultima estrazione o aggiornamento dei dati. Fornisce contesto sull'attualità dei dati analizzati. Mostrare questa informazione nelle Dashboard è essenziale per capire se le analisi si basano su dati quasi in tempo reale o su un'istantanea storica. Contribuisce a gestire le aspettative e a prendere decisioni basate su dati di cui si conosce l'anzianità. Perché è importante Informa gli utenti sulla tempestività dei dati, assicurando che comprendano se l'analisi riflette lo stato più aggiornato delle operazioni. Dove trovare Questo timestamp viene generato e aggiunto dal processo di estrazione dati o dall'ETL al momento dell'esecuzione. Esempi 2023-10-27T02:00:00Z2023-10-28T02:00:00Z | |||
Valuta Currency | Il codice valuta per l'importo dell'ordine d'acquisto. | ||
Descrizione Questo attributo indica la valuta in cui è espresso il valore dell'ordine d'acquisto, ad esempio USD, EUR o GBP. Fornisce il contesto indispensabile per ogni valore monetario. Per le organizzazioni globali, la valuta è essenziale per un'analisi finanziaria corretta. Consente una corretta aggregazione e confronto dei valori degli ordini e tutti i KPI monetari devono essere interpretati nel contesto della valuta di riferimento. Perché è importante Fornisce il contesto necessario per tutti i valori monetari, garantendo analisi finanziarie accurate, soprattutto nelle organizzazioni multinazionali. Dove trovare Tabella: EKKO, Campo: WAERS Esempi USDEURJPY | |||
Purchase to Pay - Attività dell’ordine di acquisto
| Activity | Descrizione | ||
|---|---|---|---|
Ordine di acquisto approvato | Rappresenta l'approvazione finale dell'ordine d'acquisto, che ne autorizza l'invio al fornitore. Questa tappa chiave è solitamente dedotta da un cambio dello stato di rilascio dell'ordine a "completamente rilasciato" o "approvato". | ||
Perché è importante Questa attività è determinante per calcolare il KPI PO Approval Cycle Time e per individuare i colli di bottiglia nel workflow di approvazione. È un prerequisito per molte delle attività successive, come l'invio dell'ordine al fornitore. Dove trovare Inferito tracciando i log di modifica (CDHDR/CDPOS) della tabella di testata degli ordini di acquisto (EKKO) per rilevare quando viene applicato il codice di release finale o quando l'indicatore di stato di release complessivo (EKKO-FRGKE) viene impostato su 'rilasciato'. Acquisisci Identifichi il timestamp in cui lo stato di release complessivo del PO (EKKO-FRGKE) passa allo stato di approvazione finale. Tipo di evento inferred | |||
Ordine di acquisto completato | Indica che una riga d'ordine di acquisto è considerata completamente consegnata. Si tratta di un evento inferito, tipicamente derivato dall'impostazione automatica o manuale dell'indicatore 'Delivery Completed' sulla riga del PO. | ||
Perché è importante Questa attività funge da punto di chiusura logico per la parte di evasione dell'ordine. È essenziale per calcolare il tempo di ciclo end-to-end del PO dalla creazione al completamento. Dove trovare Inferito dai documenti di modifica (CDHDR/CDPOS) che registrano quando l'indicatore 'Delivery Completed' (EKPO-ELIKZ) viene impostato su 'X' per una riga del PO. L'ultima riga contrassegnata come completata può indicare il completamento dell'intero PO. Acquisisci Identifichi il timestamp nei documenti di modifica quando il flag EKPO-ELIKZ viene impostato. Tipo di evento inferred | |||
Ordine di acquisto creato | Questa attività indica la creazione di un Ordine d'acquisto formale, che costituisce un contratto vincolante con un fornitore. È un evento esplicito, registrato quando un utente crea e salva un PO (ad es. tramite transazione ME21N), con conseguente generazione di voci nelle tabelle EKKO ed EKPO. | ||
Perché è importante Segna l'inizio ufficiale del ciclo di vita dell'ordine di acquisto. È una tappa chiave per misurare sia il tempo di conversione da PR a PO sia il tempo di evasione dell'ordine end-to-end. Dove trovare Ricavato dalla data di creazione (EKKO-AEDAT) nella tabella di testata degli ordini di acquisto (EKKO) per il relativo numero di PO (EKKO-EBELN). Acquisisci Usi il timestamp di creazione dalla tabella EKKO per ogni nuovo Ordine di Acquisto. Tipo di evento explicit | |||
Ordine di acquisto inviato al fornitore | Questa attività indica il momento in cui l'ordine d'acquisto approvato viene trasmesso ufficialmente al fornitore, ad esempio via EDI, e-mail o stampa. È un evento esplicito registrato nelle tabelle di controllo messaggi quando un messaggio di output viene elaborato correttamente. | ||
Perché è importante È una tappa critica che fa partire il conteggio del lead time del fornitore. Analizzare il tempo da questo evento al ricevimento merci è essenziale per valutare le performance del fornitore e la puntualità di consegna. Dove trovare Registrato nella tabella degli stati dei messaggi (NAST). Il timestamp può essere ricavato da NAST-DATVR e NAST-UHRVR quando lo stato di elaborazione (NAST-VSTAT) è '1' (elaborato correttamente) per il relativo tipo di output dell'ordine d'acquisto. Acquisisci Usi il timestamp di elaborazione dalla tabella NAST per il messaggio di output della PO. Tipo di evento explicit | |||
Requisizione d’acquisto creata | Questa attività segna la creazione di una richiesta formale di beni o servizi. È un evento esplicito registrato quando un utente salva una nuova richiesta d'acquisto (ad es. tramite transazione ME51N), che genera un record univoco nella tabella EBAN. | ||
Perché è importante È il punto di partenza principale del processo di approvvigionamento. Analizzare il tempo da questo evento alla creazione dell'ordine d'acquisto aiuta a misurare l'efficienza di conversione della domanda interna in ordini effettivi. Dove trovare Registrato alla creazione di una voce nella tabella testata della richiesta di acquisto (EBAN). La data (EBAN-BADAT) e l'ora di creazione fungono da timestamp per questo evento. Acquisisci Identifichi le nuove registrazioni nella tabella EBAN in base alla data di creazione. Tipo di evento explicit | |||
Ricevimento merci contabilizzato | Questa attività indica la ricezione fisica dei beni da un fornitore a fronte di uno specifico ordine d'acquisto. La registrazione dell'entrata merci è un'azione esplicita (ad es. tramite transazione MIGO) che crea un documento di materiale e aggiorna le giacenze. | ||
Perché è importante Tappa fondamentale per monitorare le performance di consegna del fornitore e l'avvio del processo di verifica delle fatture. Viene utilizzata per calcolare i tassi di consegna puntuale e la tempestività dei ricevimenti merci. Dove trovare Registrato alla creazione di un documento di magazzino. Il timestamp dell'evento è la data di registrazione (MKPF-BUDAT) o la data di creazione (MKPF-CPUDT) dalla tabella testata dei documenti di magazzino (MKPF), collegata all'ordine d'acquisto tramite la tabella posizioni (MSEG). Acquisisci Usi il timestamp di contabilizzazione/creazione dalla tabella MKPF per i documenti di materiale riferiti alla PO. Tipo di evento explicit | |||
Conferma dei servizi registrata | Per gli ordini di acquisto di servizi, questa attività rappresenta la conferma che le prestazioni sono state erogate. È un evento esplicito registrato tramite la creazione di un Service Entry Sheet (ad es., transazione ML81N). | ||
Perché è importante È l'equivalente, per i servizi, del ricevimento merci ed è essenziale per tracciare l'evasione degli ordini di servizio. Attiva il processo contabile per il pagamento dei servizi. Dove trovare Ricavato dalla data di creazione (ESSR-ERDAT) nella tabella di testata del foglio di registrazione servizi (ESSR). Il collegamento all’ordine di acquisto si trova nella tabella ESLL. Acquisisci Usi il timestamp di creazione dalla tabella ESSR per le schede di registrazione dei servizi collegate alla PO. Tipo di evento explicit | |||
Ispezione qualità eseguita | Indica che le merci ricevute sono state sottoposte a un controllo qualità. Questa attività è in genere inferita quando, per il lotto di ispezione creato al momento dell'entrata merci, viene registrata una decisione d'impiego nel modulo Quality Management. | ||
Perché è importante Nei settori in cui la qualità è decisiva, questa attività consente di analizzare durata ed esiti del processo di ispezione. I ritardi in questa fase possono creare colli di bottiglia tra l'Entrata Merci e la disponibilità all'uso. Dove trovare Inferito dal modulo Quality Management. All'entrata merci viene creato un lotto di ispezione (tabella QALS) e l'attività è contrassegnata dalla creazione di una decisione d'impiego (tabella QAVE), che include un timestamp. Acquisisci Identifichi il timestamp della decisione d'impiego nella tabella QAVE per il lotto di ispezione collegato al documento di magazzino. Tipo di evento inferred | |||
Merci restituite | Rappresenta il reso al fornitore di merci precedentemente ricevute, spesso per problemi di qualità o spedizioni errate. È un evento esplicito, registrato mediante la contabilizzazione di un documento di magazzino con un tipo di movimento specifico per il reso. | ||
Perché è importante Questa attività evidenzia problemi di qualità del fornitore o di accuratezza dell'ordine ed è un indicatore chiave di rilavorazioni di processo. È fondamentale per calcolare il KPI Goods Receipt Variance Rate. Dove trovare Registrato nelle tabelle dei documenti di magazzino (MKPF/MSEG) quando si utilizza un tipo di movimento di reso (ad es. '122' per Reso al fornitore). La data di registrazione (MKPF-BUDAT) funge da timestamp. Acquisisci Identifichi i documenti di materiale con un tipo di movimento di reso (es. 122) che fanno riferimento al PO originale. Tipo di evento explicit | |||
Ordine di acquisto cancellato | Rappresenta l'annullamento o la cancellazione logica di una posizione dell'ordine d'acquisto, impedendo ulteriori elaborazioni come la registrazione dell'entrata merci o la fatturazione. Si tratta di un evento dedotto, rilevato quando sulla posizione dell'ordine è impostato l'indicatore di cancellazione. | ||
Perché è importante Attività terminale che indica l'annullamento di un ordine. Analizzare il perché e il momento della cancellazione può far emergere problemi di pianificazione della domanda o di selezione del fornitore. Dove trovare Inferito dai documenti di modifica (CDHDR/CDPOS) che mostrano l'impostazione dell'indicatore di cancellazione (EKPO-LOEKZ) su 'L' per una riga del PO. Acquisisci Identifichi il timestamp nei documenti di modifica quando il flag EKPO-LOEKZ viene impostato. Tipo di evento inferred | |||
Ordine di acquisto modificato | Rappresenta qualsiasi modifica apportata a un ordine d'acquisto dopo la sua creazione iniziale, come variazioni di quantità, prezzo o date di consegna. Queste modifiche sono registrate in modo esplicito nel sistema dei documenti di modifica di SAP. | ||
Perché è importante Modifiche frequenti, soprattutto dopo l'approvazione, sono indice di inefficienze di processo, scarsa pianificazione iniziale o estensione incontrollata dell'ambito. Questa attività è fondamentale per la dashboard PO Rework and Changes e i KPI collegati. Dove trovare Registrato esplicitamente nelle tabelle di testata (CDHDR) e di dettaglio (CDPOS) dei documenti di modifica per l’oggetto Ordine di Acquisto (EINKBELEG). Ogni modifica crea una nuova voce con timestamp. Acquisisci Estragga gli eventi di modifica e i relativi timestamp dalle tabelle CDHDR e CDPOS collegate al numero dell'ordine di acquisto. Tipo di evento explicit | |||
Ordine di acquisto rifiutato | Questa attività si verifica quando un approvatore respinge un ordine d'acquisto durante il workflow di approvazione. È un evento inferito, derivato da una variazione di stato nei dati della strategia di rilascio del PO, che indica l'avvenuto rifiuto. | ||
Perché è importante Il tracciamento dei rigetti aiuta a individuare problemi nella qualità dei dati della PO, violazioni di Conformità alle policy o criticità nella matrice di approvazione. Spesso comporta rilavorazioni e allunga il tempo di ciclo complessivo. Dove trovare Inferito dai documenti di modifica (CDHDR/CDPOS) relativi allo stato di release dell'ordine di acquisto. Un rifiuto è in genere registrato quando un codice di release viene annullato o quando viene impostato uno specifico stato di rifiuto. Acquisisci Monitori i log delle modifiche per l'annullamento di un codice di rilascio o per variazioni di stato che indichino un rifiuto. Tipo di evento inferred | |||
Requisizione d’acquisto approvata | Rappresenta l'approvazione formale di una richiesta di acquisto, che ne autorizza la conversione in ordine d'acquisto. Questo evento è dedotto dai cambiamenti nei campi di stato di rilascio all'interno dei dati della richiesta, come tracciato dal workflow della strategia di rilascio SAP. | ||
Perché è importante Il tracciamento delle approvazioni è cruciale per individuare colli di bottiglia nella fase pre-ordine e garantire la Conformità alle policy di approvazione. I ritardi in questa fase incidono direttamente sul tempo di ciclo complessivo dell'approvvigionamento. Dove trovare Inferito dai log di modifica della tabella delle richieste di acquisto (EBAN), monitorando in particolare i cambiamenti nei campi di stato di release (es. EBAN-FRGZU) oppure analizzando i documenti di modifica in CDHDR/CDPOS per l'oggetto EBAN. Acquisisci Monitori i documenti di modifica per i campi di stato di rilascio di EBAN per identificare data e ora dell'approvazione finale. Tipo di evento inferred | |||
Richiesta di approvazione dell'ordine di acquisto | Indica che un ordine di acquisto creato o modificato è stato inviato in approvazione secondo la release strategy configurata. Questo evento è inferito quando la release strategy viene attivata e il PO entra in stato di attesa di approvazione. | ||
Perché è importante Distinguere tra la creazione dell’ordine di acquisto (PO) e l’avvio del processo di approvazione consente di misurare con precisione il KPI sul tempo di approvazione. Evidenzia eventuali ritardi prima che inizi il workflow di approvazione. Dove trovare Inferito dai documenti di modifica (CDHDR/CDPOS) dell'ordine di acquisto (oggetto EINKBELEG) che mostrano l'impostazione iniziale di uno stato di release, oppure quando lo stato di release complessivo (EKKO-FRGKE) viene per la prima volta impostato su un valore che indica che è attivo un processo di approvazione. Acquisisci Identifichi la prima registrazione nei documenti di modifica che attiva la release strategy del PO. Tipo di evento inferred | |||
Guide all'Estrazione
Fasi
- Creare un programma ABAP: Apra l'Editor ABAP con la transazione SE38. Inserisca un nome per il nuovo programma, ad esempio Z_PM_PO_EXTRACT, e faccia clic su 'Create'. Indichi un titolo come 'Process Mining PO Data Extraction' e imposti il tipo su 'Executable Program'.
- Definire la schermata di selezione: Nel programma, definisca i parametri della schermata di selezione, così gli utenti possono filtrare i dati da estrarre. Tra i parametri principali rientrano l'intervallo di date di creazione dell'ordine d'acquisto, il Company Code (BUKRS) e il tipo di documento d'acquisto (BSART).
- Definire le strutture dati: Dichiari una struttura di tabella interna allineata al formato finale dell'Event Log. La struttura deve includere tutti gli attributi obbligatori e consigliati: PurchaseOrder, Activity, EventTime, UserName, VendorNumber, OrderAmount, MaterialGroup, CompanyCode e DocumentType.
- Implementare la logica di selezione dei dati: Scriva la logica ABAP principale per selezionare i dati per ciascuna delle 14 attività richieste. Questo comporta l'interrogazione di diverse tabelle SAP, ad esempio EKKO, EKPO, EKBE, EBAN, CDHDR, CDPOS e NAST. Usi una subroutine separata (PERFORM) per ogni attività, così da mantenere il codice ordinato.
- Selezionare i dati della richiesta d'acquisto: Interroghi la tabella EBAN per gli eventi 'Purchase Requisition Created', collegandoli agli ordini d'acquisto tramite la tabella EKPO. Utilizzi le tabelle di log delle modifiche (CDHDR, CDPOS) per identificare gli eventi 'Purchase Requisition Approved' tracciando le variazioni dei campi di stato di rilascio.
- Selezionare gli eventi principali dell'ordine d'acquisto: Interroghi le tabelle EKKO e EKPO per l'evento 'Purchase Order Created'. Usi le tabelle di log delle modifiche (CDHDR, CDPOS) sull'oggetto EINKBELEG per estrarre gli eventi 'Purchase Order Changed', 'Purchase Order Approved', 'Purchase Order Rejected', 'Purchase Order Completed' e 'Purchase Order Deleted' in base alle variazioni di campi specifici, come indicatori di rilascio e flag di cancellazione.
- Selezionare gli eventi di comunicazione dell'ordine d'acquisto: Interroghi la tabella NAST per individuare i record in cui l'ordine d'acquisto è stato trasmesso con successo, così da rilevare l'attività 'Purchase Order Sent to Vendor'.
- Selezionare gli eventi di beni e servizi: Interroghi la tabella EKBE per le registrazioni dei documenti materiali e identifichi le attività 'Goods Receipt Posted' e 'Goods Returned' in base al tipo di movimento. Interroghi ESSR e ESLL per i fogli di entrata servizi, così da rilevare 'Services Confirmation Entered'.
- Selezionare gli eventi di Quality Management: Se è in uso il modulo Quality Management (QM), interroghi le tabelle QALS e QAVE per identificare quando è stata presa una decisione d'uso per un lotto di ispezione legato a un ordine d'acquisto; questo corrisponde all'attività 'Quality Inspection Performed'.
- Combinare e formattare i dati: Consolidi i dati di tutte le selezioni in un'unica tabella interna finale. Si assicuri che il campo EventTime sia formattato in modo coerente (ad es. YYYY-MM-DDTHH:MI:SS).
- Implementare il download del file: Aggiunga la funzionalità per scaricare la tabella interna finale come file. Il formato consigliato è un file con tabulazioni (TSV) o CSV; può ottenerlo con il modulo di funzione GUI_DOWNLOAD.
- Eseguire e salvare: Esegua il programma tramite le transazioni SE38 o SA38. Compili i criteri di selezione ed esegua il report. Quando richiesto, salvi il file di output in locale con estensione .csv, pronto per l'upload.
Configurazione
- Intervallo di date: È fondamentale definire un intervallo di date preciso per l'estrazione, di norma basato sulla data di creazione dell'ordine di acquisto (EKKO-AEDAT). Un intervallo di 3–6 mesi è spesso un buon punto di partenza per bilanciare volume dei dati e informazioni sul processo.
- Codice società (BUKRS): Filtri per uno o più codici società per limitare l'estrazione alle entità legali rilevanti. È un parametro chiave per prestazioni e pertinenza.
- Tipo di documento di acquisto (BSART): Filtri per tipi di documento specifici (ad es. 'NB' per ordine di acquisto standard) per concentrare l'analisi sui processi standard ed escludere, se necessario, tipologie speciali di approvvigionamento.
- Granularità dei dati: L'estrazione è progettata a livello di posizione dell'ordine di acquisto. Il Case ID è il numero dell'ordine di acquisto (EBELN). Tutti gli eventi, compresi quelli a livello di posizione come le entrate merci, sono ricondotti a questo Case ID principale.
- Considerazioni sulle prestazioni: Per insiemi di dati di grandi dimensioni, pianifichi il programma come job in background (SM36) per evitare errori di timeout. Verifichi l'esistenza di indici di database sui campi chiave usati nelle clausole WHERE, in particolare per tabelle come CDHDR e CDPOS.
- Prerequisiti: L'utente che esegue il report deve avere l'autorizzazione per accedere all'ABAP Workbench (SE38) e i diritti di sviluppo ed esecuzione per il programma. Sono inoltre necessarie autorizzazioni di lettura su tutte le tabelle sottostanti, incluse EKKO, EKPO, EKBE, CDHDR, CDPOS, EBAN, NAST, ESSR e le tabelle di QM.
a Query di Esempio 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.Fasi
- Stabilire la connessione al database: Ottenga credenziali in sola lettura e i dettagli di connessione (hostname, porta, nome del database) per il database SAP ECC sottostante. Si assicuri di avere installati gli strumenti client necessari, come DBeaver, SQL Developer o SSMS.
- Identificare lo schema SAP: Si connetta al database e individui lo schema SAP principale in cui risiedono le tabelle. Spesso è SAPSR3, SAPHANADB o un nome specifico del sistema simile. Se non è lo schema predefinito per il suo utente, dovrà anteporre questo schema a tutti i nomi di tabella nella query.
- Esaminare la query SQL: Apra lo script SQL fornito nel suo client. Questo script è pensato per estrarre 14 attività distinte dal processo Purchase-to-Pay (ciclo passivo) mettendo in join diverse tabelle SAP.
- Personalizzare i parametri della query: Individui la Common Table Expression (CTE) PO_BASE all'inizio dello script. Modifichi i segnaposto per definire l'ambito dell'estrazione:
- [START_DATE] e [END_DATE]: Imposti l'intervallo di date per l'analisi (ad es. '20230101' e '20230630'). Si consiglia di filtrare sul campo AEDAT (Data modifica).
- [COMPANY_CODE_1], [COMPANY_CODE_2]: Specifichi i Company Code SAP da includere.
- [DOC_TYPE_1], [DOC_TYPE_2]: Specifichi i tipi di documento dell'ordine d'acquisto da includere.
- [Your SAP Schema]: Sostituisca questo segnaposto con il suo schema SAP effettivo in tutto lo script.
- Eseguire la query: Esegua lo script SQL personalizzato sul database SAP. Il tempo di esecuzione varia in base all'intervallo di date, al volume dei dati e alle prestazioni del database.
- Verificare i risultati: Una volta completata l'esecuzione, effettui una verifica rapida dell'output. Controlli che il numero di righe sia ragionevole e che colonne chiave come PurchaseOrder, Activity e EventTime siano valorizzate come previsto.
- Esportare i dati in CSV: Esporti l'intero set di risultati dal client SQL in un file CSV. Usi la codifica UTF-8 per evitare problemi di caratteri.
- Preparare l'upload: Si assicuri che le intestazioni di colonna nel file CSV corrispondano esattamente ai nomi degli attributi richiesti: PurchaseOrder, Activity, EventTime, UserName, VendorNumber, OrderAmount, MaterialGroup, CompanyCode, DocumentType.
- Caricare nello strumento di Process Mining: Carichi il file CSV finale nella sua applicazione di Process Mining per l'analisi e la visualizzazione.
Configurazione
- Prerequisiti: È necessario un accesso diretto in sola lettura al database SAP ECC sottostante. Gli utenti devono disporre di autorizzazioni sufficienti per interrogare tabelle come EKKO, EKPO, EKBE, EBAN, CDHDR, CDPOS e NAST.
- Filtraggio per intervallo di date: È fondamentale applicare un filtro temporale per limitare il volume dei dati. Un punto di partenza comune è filtrare EKKO.AEDAT (Data di modifica dell'ordine, PO) per un periodo di 3–6 mesi. Intervalli ampi possono portare a tempi di esecuzione delle query molto lunghi.
- Filtri chiave sui dati: Per un'analisi mirata, filtri sempre per EKKO.BUKRS (Codice società) e EKKO.BSART (Tipo di documento). Questo restringe l'ambito alle entità legali e ai processi aziendali rilevanti.
- Considerazioni sulle prestazioni: La query esegue join tra diverse tabelle di grandi dimensioni, incluse quelle della cronologia delle modifiche (CDHDR, CDPOS). L'operazione è dispendiosa in termini di risorse. Si raccomanda vivamente di eseguire l'estrazione nelle ore di minor carico o su un database replicato in un ambiente non produttivo, per evitare impatti sulle prestazioni del sistema.
- Registrazione dei documenti di modifica: L'accuratezza di attività come 'Approved', 'Rejected', 'Completed' e 'Changed' dipende dall'attivazione della registrazione dei documenti di modifica per i campi rilevanti in SAP. Verificare con l'amministratore SAP che tale registrazione sia abilitata (tramite transazione SCDO).
a Query di Esempio 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 indicatorFasi
- Prerequisiti e connessione: Si assicuri che lo strumento ETL di terze parti disponga del SAP Certified Connector installato e licenziato. Nella console di amministrazione del Suo strumento ETL, configuri una nuova connessione al sistema SAP ECC. Le serviranno l'host del server applicativo, il numero di sistema, il mandante e un utente SAP dedicato con le opportune autorizzazioni RFC e di lettura delle tabelle.
- Identifichi le tabelle sorgente: All'interno del job ETL o del flusso di dati, definisca le tabelle SAP necessarie come origini dati. Le principali includono EKKO (testata Ordine di Acquisto), EKPO (posizione Ordine di Acquisto), EBAN (Richiesta di Acquisto), CDHDR (testata documento di modifica), CDPOS (posizione documento di modifica), MSEG (segmento del documento materiale), MKPF (testata documento materiale), NAST (stato del messaggio), ESSR (testata conferma servizi) e QALS (lotto di ispezione).
- Estrarre 'Ordine di acquisto creato': Crei un flusso di dati a partire dalla tabella EKKO. Filtri i record in base all'intervallo di date desiderato (ad es. usando AEDAT) e all'ambito organizzativo (ad es. BUKRS per il codice società, BSART per il tipo di documento). Mappi EKKO.EBELN su PurchaseOrder, 'Ordine di acquisto creato' su Activity e combini AEDAT e ERZET per EventTime. Mappi gli altri attributi richiesti.
- Estrarre 'Entrata merci registrata': Crei un flusso di dati separato con origine MSEG ed esegua un join con MKPF su MBLNR e MJAHR. Filtri i tipi di movimento rilevanti, ad esempio '101'. Mappi MSEG.EBELN su PurchaseOrder, 'Entrata merci registrata' su Activity e usi MKPF.CPUDT e MKPF.CPUTM per EventTime.
- Estrarre eventi basati sulle modifiche (approvazioni, variazioni, cancellazioni): Crei un flusso di dati con origine CDHDR e CDPOS, uniti su CHANGENR. Da questa singola fonte può derivare diverse attività.
- Filtri OBJECTCLAS = 'EINKBELEG' e TABNAME = 'EKPO'.
- Per 'Ordine di acquisto approvato', filtri le modifiche al campo dello stato di rilascio (ad es. FNAME = 'FRGZU') in cui il nuovo valore (VALUE_NEW) indica l'approvazione finale.
- Per 'Ordine di acquisto cancellato', filtri le modifiche all'indicatore di cancellazione (FNAME = 'LOEKZ') in cui il nuovo valore è 'L'.
- Per 'Ordine di acquisto modificato', filtri le altre modifiche di campo rilevanti, escludendo gli specifici campi di stato usati per le altre attività.
- Per tutti questi eventi, usi CDHDR.UDATE e CDHDR.UTIME per EventTime.
- Estrarre eventi di 'Richiesta di acquisto': Crei un flusso di dati da EBAN per 'Richiesta di acquisto creata'. Per collegarla a un caso PurchaseOrder, esegua un join tra EBAN ed EKPO usando il numero di richiesta (BANFN) e la posizione (BNFPO). Per 'Richiesta di acquisto approvata', usi CDHDR/CDPOS con OBJECTCLAS = 'BANF'. È necessaria una mappatura accurata per assicurare che l'evento sia associato all'Ordine di acquisto finale.
- Estrarre 'Ordine di acquisto inviato al fornitore': Crei un flusso di dati con origine la tabella NAST. Filtri su OBJECTKEY (che contiene il numero dell'Ordine di acquisto), sul tipo di output rilevante (KSCHL) e su uno stato di elaborazione riuscito (VSTAT = '1'). Usi ERDAT e UHR per EventTime.
- Combini i flussi di attività: Usi una trasformazione 'Union' o 'Merge' nel Suo strumento ETL per combinare gli output di tutti i singoli flussi di dati creati nei passaggi precedenti. Verifichi che i nomi di colonna e i tipi di dato siano coerenti in tutti i flussi (PurchaseOrder, Activity, EventTime, ecc.).
- Conversione di tipi e formati: Si assicuri che la colonna EventTime sia convertita in un formato di timestamp coerente (ad es. YYYY-MM-DD HH:MM:SS). Converta OrderAmount in un formato decimale standard.
- Definisca la destinazione: Configuri una destinazione o 'sink' per il flusso di dati combinato. Di norma si tratta di un file flat, ad esempio CSV o Parquet. Imposti il delimitatore, i qualificatori di testo e le opzioni di intestazione.
- Esegua e convalidi: Esegua l'intero job ETL. Esegua verifiche di validazione sul file di output per assicurarsi che tutte le 14 attività siano presenti, che i conteggi delle righe siano ragionevoli e che gli attributi chiave siano valorizzati correttamente.
- Pianifichi ed esporti: Una volta validato, pianifichi il job ETL per esecuzioni periodiche (ad es. notturne) per mantenere i dati aggiornati. Il file generato è pronto per il caricamento nel Suo strumento di Process Mining.
Configurazione
- Prerequisiti: Uno strumento ETL commerciale (ad es. Informatica PowerCenter, Talend, SAP Data Services) con il relativo SAP Certified Connector per ECC. Un utente SAP dialog o di sistema con autorizzazioni S_RFC e S_TABU_DIS per le tabelle richieste.
- Connessione SAP: Il connettore deve essere configurato con l'application server SAP, il numero di sistema, il mandante, l'utente e la password. Si consiglia l'uso di Secure Network Communications (SNC).
- Filtro per intervallo di date: È essenziale applicare un filtro temporale per limitare il volume dei dati. È prassi comune filtrare EKKO.AEDAT (Data di creazione dell'ordine, PO) per gli ultimi 3–12 mesi. Questo filtro va applicato alla fonte per evitare di estrarre da SAP quantità eccessive di dati.
- Filtri di ambito organizzativo: Filtri sempre per EKKO.BUKRS (Codice società) e valuti anche EKPO.WERKS (Stabilimento) o EKKO.EKORG (Organizzazione acquisti) per restringere l'analisi a una specifica unità aziendale.
- Filtro per tipo di documento: Usi EKKO.BSART per includere solo i tipi di ordine di acquisto rilevanti ed escludere trasferimenti di magazzino o altri documenti interni che non fanno parte del processo P2P standard.
- Ottimizzazione delle prestazioni: L'estrazione dalle tabelle dei documenti di modifica (CDHDR, CDPOS) può essere lenta. Si assicuri di applicare filtri su OBJECTCLAS, OBJECTID e UDATE. Regoli l'impostazione 'Packet Size' nel connettore SAP per ottimizzare il trasferimento dei dati. Per sistemi molto grandi, valuti un caricamento storico iniziale seguito da caricamenti delta pianificati.
a Query di Esempio 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]);