Szablon danych do analizy obsługi faktur zakupu
Szablon danych do analizy obsługi faktur zakupu
- Zalecane atrybuty do szczegółowej analizy
- Najważniejsze czynności procesu do śledzenia
- Instrukcja pobierania danych krok po kroku
Atrybuty procesu obsługi faktur zakupu
| Nazwa | Opis | ||
|---|---|---|---|
| Czas zdarzenia EventTime | Dokładna data i godzina wystąpienia czynności. | ||
| Opis Czas zdarzenia to znacznik czasu przypisany do każdej czynności, który określa chronologiczną kolejność zdarzeń dotyczących faktury. Dane te są niezbędne do zrozumienia przebiegu procesu i przeprowadzania analiz czasowych. W analizie czas zdarzenia służy do prawidłowego uporządkowania czynności, obliczania czasu między etapami, wykrywania czasu oczekiwania i oceny wyników procesu w różnych okresach, np. miesiąc do miesiąca. Stanowi podstawę wszystkich KPI opartych na czasie trwania. Dlaczego to ważne Ten znacznik czasu jest niezbędny do chronologicznego uporządkowania zdarzeń i obliczania mierników czasowych, takich jak czas cyklu i czas trwania. To podstawa process mining. Skąd pobrać Dane pochodzą z różnych pól daty i godziny w tabelach SAP, takich jak data utworzenia (BKPF-CPUDT), data księgowania (BKPF-BUDAT), data rozliczenia (BSAK-AUGDT) lub znaczniki czasu w dzienniku zmian (CDHDR-UDATE/UTIME). Przykłady 2023-10-01T09:00:00Z2023-10-05T14:30:15Z2023-10-15T11:21:05Z | |||
| Czynność ActivityName | Nazwa konkretnego zdarzenia biznesowego lub etapu, który wystąpił podczas obsługi faktury. | ||
| Opis Czynność oznacza odrębny etap lub działanie w procesie obsługi zobowiązań, takie jak „Otrzymano fakturę”, „Zaksięgowano fakturę” lub „Zrealizowano płatność”. Czynności tworzą mapę procesu. Analiza czynności jest podstawą process mining. Pozwala zobrazować przebieg procesu, wykryć typowe ścieżki i odstępstwa od standardowego przebiegu oraz zmierzyć częstotliwość i czas trwania poszczególnych etapów. Kolejność czynności dla danej faktury pokazuje jej przebieg przez proces. Dlaczego to ważne Czynności określają etapy procesu. Umożliwiają zobrazowanie i analizę jego przebiegu, wykrywanie wąskich gardeł oraz pętli poprawek. Skąd pobrać Dane pochodzą z różnych źródeł, w tym ze zmian statusu dokumentu (np. BKPF-BSTAT), dokumentów zmian (tabele CDHDR/CDPOS) lub dzienników workflow. Zwykle wymagają niestandardowej logiki ekstrakcji. Przykłady Otrzymano fakturęZaakceptowano fakturęZrealizowano płatnośćZablokowano płatność faktury | |||
| Faktura Invoice | Unikalny identyfikator dokumentu faktury, który pełni funkcję głównego identyfikatora case w procesie obsługi zobowiązań. | ||
| Opis Faktura jest centralnym obiektem łączącym wszystkie powiązane działania, od jej otrzymania po płatność. W SAP S/4HANA jej identyfikator jest zwykle kluczem złożonym z kodu jednostki gospodarczej (BUKRS), unikalnego numeru dokumentu (BELNR) i roku obrotowego (GJAHR). Analiza według faktury pokazuje cały cykl jej obsługi. Umożliwia obliczanie podstawowych mierników, takich jak łączny czas obsługi, wykrywanie wąskich gardeł dla poszczególnych faktur i sprawdzanie, jakimi ścieżkami przechodzą one przez proces. Dlaczego to ważne Unikalny identyfikator pozwala prześledzić pełny cykl obsługi każdej faktury i analizować wyniki procesu dla poszczególnych przypadków. Skąd pobrać Klucz złożony z pól BUKRS, BELNR i GJAHR, pochodzących z tabel BKPF (nagłówek dokumentu księgowego) lub RBKP (nagłówek dokumentu: otrzymanie faktury). Przykłady 1000-1900000001-20231710-1900000002-20232000-5100000003-2024 | |||
| Ostatnia aktualizacja danych LastDataUpdate | Znacznik czasu wskazujący, kiedy dane tego rekordu zostały ostatnio odświeżone z systemu źródłowego. | ||
| Opis Ten atrybut zawiera datę i godzinę ostatniej ekstrakcji lub aktualizacji danych z SAP S/4HANA. To pole metadanych informuje, jak aktualne są analizowane dane. Dzięki tej informacji użytkownicy wiedzą, na jak aktualnych danych opiera się analiza procesu. Pozwala ona uwzględnić opóźnienia w dostępności danych, zaplanować ich odświeżanie i dbać o ich spójność. Dlaczego to ważne Informuje o aktualności danych, dzięki czemu użytkownicy wiedzą, jak aktualna jest analiza procesu. Skąd pobrać Wartość jest generowana i zapisywana w każdym rekordzie podczas ekstrakcji danych z systemu źródłowego. Przykłady 2024-05-20T04:00:00Z2024-05-21T04:00:00Z | |||
| System źródłowy SourceSystem | System, z którego wyodrębniono dane. | ||
| Opis Ten atrybut wskazuje źródło danych o procesie. W tym widoku jego wartością będzie zwykle „SAP S/4HANA”. W środowiskach z wieloma systemami ERP lub systemami zintegrowanymi pole to ma istotne znaczenie dla śledzenia pochodzenia danych i ich rozdzielania. Pomaga analizować właściwy zbiór danych oraz diagnozować problemy z ich jakością przez wskazanie systemu źródłowego. Dlaczego to ważne Wskazuje źródło danych, co ma znaczenie dla zarządzania danymi, rozwiązywania problemów i pracy w środowiskach z wieloma systemami. Skąd pobrać Zwykle jest to stała wartość dodawana podczas ekstrakcji danych w celu oznaczenia ich źródła. Przykłady SAP S/4HANASAP ECC 6.0S4H_PROD_100 | |||
| Kod jednostki gospodarczej CompanyCode | Jednostka organizacyjna, w której obsługiwana jest faktura. | ||
| Opis Kod jednostki gospodarczej oznacza najmniejszą jednostkę organizacyjną, dla której można sporządzić kompletny, samodzielny zestaw kont na potrzeby sprawozdawczości zewnętrznej. W procesie obsługi zobowiązań reprezentuje podmiot prawny, który jest winien pieniądze dostawcy. Analiza według kodu jednostki gospodarczej pozwala porównywać wyniki procesu w różnych podmiotach prawnych organizacji. Pomaga ustalić, które części firmy stosują standardowy proces, a w których proces jest sprawniejszy, trwa dłużej lub wymaga więcej poprawek. Dlaczego to ważne Umożliwia porównanie wyników procesu w różnych podmiotach prawnych oraz wykrycie problemów i dobrych praktyk charakterystycznych dla regionu lub jednostki biznesowej. Skąd pobrać Dane znajdują się w tabelach nagłówków dokumentów, przede wszystkim w polu BKPF-BUKRS dla faktur FI i RBKP-BUKRS dla faktur MM. Przykłady 10001710US01DE01 | |||
| Kwota faktury InvoiceAmount | Łączna kwota brutto faktury w walucie dokumentu źródłowego. | ||
| Opis To łączna wartość faktury przesłanej przez dostawcę. Obejmuje koszt towarów lub usług, podatki i inne opłaty przed odliczeniem potrąceń lub rabatów. Kwota faktury to ważny atrybut finansowy, wykorzystywany w wielu analizach. Pomaga ustalać priorytety dla faktur o wysokiej wartości, oceniać finansowe skutki opóźnień w procesie, np. opłat za zwłokę przy wysokich kwotach, oraz dzielić proces na segmenty, np. sprawdzać, czy faktury o wysokiej wartości przechodzą inną ścieżkę akceptacji. Jest też niezbędna do wykrywania potencjalnych podwójnych płatności. Dlaczego to ważne Nadaje procesowi kontekst finansowy. Umożliwia analizę według wartości, ustalanie priorytetów dla faktur o wysokiej wartości i określanie skutków finansowych. Skąd pobrać Dane znajdują się w tabelach takich jak RBKP-RMWWR (kwota brutto faktury) dla faktur MM lub są obliczane na podstawie pozycji w BSEG (pole WRBTR) dla faktur FI. Przykłady 1500.00250.7512345.50 | |||
| Nazwa dostawcy VendorName | Nazwa dostawcy, który przesłał fakturę. | ||
| Opis Ten atrybut zawiera oficjalną nazwę dostawcy. Jest powiązany z numerem dostawcy zapisanym w dokumencie faktury. Analiza dostawców pomaga zarządzać relacjami z nimi i wykrywać problemy w procesie dotyczące konkretnych dostawców. Pozwala odpowiedzieć na pytania, takie jak „Którzy dostawcy najczęściej przesyłają faktury z niezgodnościami?” lub „Czy strategicznym dostawcom regularnie płacimy w terminie?”. Pole to, wraz z numerem i kwotą faktury, pomaga też wykrywać potencjalne podwójne płatności. Dlaczego to ważne Umożliwia analizę wyników procesu według dostawcy, wykrywanie problemów i skuteczniejsze zarządzanie relacjami ze strategicznymi dostawcami. Skąd pobrać Dane pobiera się z tabeli danych podstawowych dostawców LFA1 (pole NAME1), łącząc je z numerem dostawcy (LIFNR) z tabeli BKPF lub RBKP. Przykłady Office Supplies Inc.Global Consulting GroupMachine Parts GmbH | |||
| Nazwa użytkownika UserName | Identyfikator użytkownika, który wykonał czynność. | ||
| Opis Ten atrybut zapisuje identyfikator użytkownika SAP odpowiedzialnego za wykonanie określonej czynności, takiej jak księgowanie, akceptacja lub rozliczenie faktury. Łączy etapy procesu z konkretnymi użytkownikami. Analiza według nazwy użytkownika pomaga ocenić rozkład obciążenia pracą, wskazać osoby osiągające najlepsze wyniki i wykryć potrzebę dodatkowego szkolenia. Jest też przydatna przy analizie wąskich gardeł w dashboardach akceptacji, ponieważ pozwala ustalić, które osoby akceptujące powodują opóźnienia. Dlaczego to ważne Przypisuje czynności konkretnym osobom, umożliwiając analizę ich wyników i obciążenia pracą oraz zgodności z zasadami rozdziału obowiązków. Skąd pobrać Dane znajdują się zwykle w tabelach nagłówków, takich jak BKPF-USNAM (wprowadził), lub w tabelach dokumentów zmian, takich jak CDHDR-USERNAME (zmienił). Przykłady ABROWNJSMITHAP_AUTOMATION | |||
| Numer zamówienia zakupu PurchaseOrderNumber | Unikalny identyfikator zamówienia zakupu powiązanego z fakturą, jeśli dotyczy. | ||
| Opis Ten atrybut łączy fakturę z wcześniej zatwierdzonym zamówieniem zakupu (PO). Obecność numeru PO stanowi podstawę uzgadniania trójstronnego: zamówienia zakupu, faktury i przyjęcia towaru. Atrybut ten jest ważny przy analizie zgodności i sprawności procesu. Służy do obliczania KPI „Odsetek faktur bez zamówienia zakupu”, który mierzy przestrzeganie zasad zakupowych. Jest też podstawą dashboardu „Skuteczność uzgadniania trójstronnego”, który pozwala analizować uzgadnianie faktur powiązanych z zamówieniem zakupu. Dlaczego to ważne Pomaga analizować sprawność uzgadniania trójstronnego i zgodność z zasadami zakupowymi przez wskazanie faktur przetwarzanych bez zamówienia zakupu. Skąd pobrać Dane znajdują się w tabelach pozycji faktur, takich jak RSEG-EBELN dla faktur MM lub BSEG-EBELN dla faktur FI. Przykłady 45000012344500005678 | |||
| Termin płatności faktury InvoiceDueDate | Termin, do którego należy zapłacić dostawcy za fakturę. | ||
| Opis Termin płatności faktury to data, do której należy zapłacić dostawcy, aby uniknąć opłat za opóźnienie i utrzymać dobre relacje. Wyznacza się go na podstawie daty bazowej faktury i uzgodnionych z dostawcą warunków płatności. Ta data jest niezbędna w dashboardzie „Zgodność płatności i wiek zobowiązań” oraz przy obliczaniu KPI „Odsetek płatności zrealizowanych w terminie”. Porównanie terminu z datą faktycznej płatności pokazuje, czy płatności są realizowane przed terminem, w terminie czy po terminie, co ma bezpośrednie skutki finansowe i wpływa na relacje z dostawcami. Dlaczego to ważne To podstawowa wartość przy analizie płatności w terminie. Pozwala mierzyć terminowość płatności i oceniać jej wpływ na relacje z dostawcami oraz opłaty za opóźnienia. Skąd pobrać Ta data jest często obliczana. Termin płatności netto znajduje się w polu BSEG-NETDT. Można go też wyznaczyć na podstawie daty bazowej płatności (BSEG-ZFBDT) i warunków płatności (BSEG-ZTERM). Przykłady 2023-10-312023-11-152024-01-10 | |||
| Czy płatność była opóźniona IsLatePayment | Wartość logiczna wskazująca, czy fakturę opłacono po terminie. | ||
| Opis Ten obliczany atrybut przyjmuje wartość prawda lub fałsz i wskazuje, czy fakturę opłacono po wyznaczonym terminie. Jest wyliczany przez porównanie „Daty rozliczenia” z „Terminem płatności faktury”. Ułatwia analizę w dashboardzie „Zgodność z terminami płatności i zaległości” oraz obliczanie KPI „Odsetek płatności w terminie”. Pozwala łatwo filtrować i agregować dane, aby policzyć opóźnione płatności, obliczyć odsetek płatności zrealizowanych w terminie oraz wskazać dostawców lub kody spółek, w przypadku których opóźnienia występują najczęściej. Dlaczego to ważne Bezpośrednio mierzy zgodność z warunkami płatności, ułatwia obliczanie KPI dotyczącego płatności w terminie i pomaga wskazać obszary, w których płatności są realizowane z opóźnieniem. Skąd pobrać Atrybut obliczany. Reguła: IF ClearingDate > InvoiceDueDate THEN true ELSE false. Przykłady truefalse | |||
| Data rozliczenia ClearingDate | Data dokonania płatności i rozliczenia faktury w ramach pozycji otwartych. | ||
| Opis Data rozliczenia oznacza finansowe uregulowanie faktury. Jest to data wystąpienia czynności „Płatność rozliczona”, która w większości przypadków kończy obsługę faktury. Na tej podstawie ustala się faktyczną datę płatności i porównuje ją z terminem płatności faktury. Data ta jest więc niezbędna do obliczenia KPI „Odsetek płatności w terminie” oraz do analiz wyników procesu płatności. Wyznacza również koniec cyklu obsługi faktury, od początku do końca. Dlaczego to ważne Oznacza ostateczne rozliczenie faktury. Wyznacza koniec cyklu obsługi i stanowi podstawę analizy płatności dokonanych w terminie. Skąd pobrać Dane znajdują się w tabelach rozliczonych pozycji, na przykład BSAK-AUGDT dla dostawców. Przykłady 2023-10-282023-11-142024-01-09 | |||
| Numer faktury dostawcy VendorInvoiceNumber | Numer faktury podany przez dostawcę na dokumencie. | ||
| Opis To numer referencyjny z systemu księgowego dostawcy, widoczny na papierowej lub elektronicznej fakturze. Jest wprowadzany ręcznie lub odczytywany za pomocą OCR podczas przyjmowania faktury. Pole to ma duże znaczenie w codziennej obsłudze i analizie, zwłaszcza w dashboardzie „Potencjalne podwójne płatności za faktury”. Duplikaty można wykrywać, wyszukując dokumenty wewnętrzne o tej samej nazwie dostawcy, numerze faktury dostawcy i kwocie faktury. Jest to podstawowy zewnętrzny numer referencyjny faktury. Dlaczego to ważne Pole to pomaga wykrywać potencjalne podwójne płatności i stanowi podstawowy zewnętrzny numer referencyjny używany w komunikacji z dostawcami. Skąd pobrać Dane są przechowywane w polu „Referencja” w nagłówku dokumentu, zwykle BKPF-XBLNR. Przykłady INV-2023-9876733401120231015-001 | |||
| Przyczyna blokady BlockingReason | Powód zablokowania faktury do płatności, wskazujący na niezgodność. | ||
| Opis Jeśli faktura nie przejdzie kontroli w ramach dopasowania trójstronnego lub innego etapu weryfikacji, zostaje zablokowana do płatności. Przyczyna blokady określa rodzaj problemu, na przykład niezgodność ilości, różnicę w cenie lub brak potwierdzenia przyjęcia towaru. Ten atrybut ma zasadnicze znaczenie dla dashboardu „Analiza ponownej obsługi niezgodności na fakturach”. Analiza częstotliwości poszczególnych przyczyn blokady pomaga ustalić źródła nieefektywności procesu. Jeśli na przykład często występuje „Różnica w cenie”, może to wskazywać na problemy z danymi podstawowymi w systemie zakupowym. Dlaczego to ważne Pozwala bezpośrednio ustalić przyczyny niezgodności na fakturach i ponownej obsługi, co ułatwia ukierunkowane usprawnianie procesu. Skąd pobrać Dane są przechowywane w tabelach pozycji faktury, takich jak RSEG, w polach zaczynających się od SPGR* (np. SPGRP, SPGRQ, SPGRT). Można je również znaleźć w RBKP_BLOCKED. Przykłady Niezgodność cenyNiezgodność ilościBrak potwierdzenia przyjęcia towaru | |||
| Typ dokumentu faktury InvoiceDocumentType | Klasyfikacja dokumentu faktury, która określa sposób jego przetwarzania w SAP. | ||
| Opis Typ dokumentu to element konfiguracji SAP, który klasyfikuje dokumenty księgowe. Na przykład „KR” jest zwykle używany dla faktur dostawców, „RE” dla faktur MM, a „KG” dla not uznaniowych dostawców. Typ określa między innymi zakres numeracji i wymagane pola. Filtrowanie według typu dokumentu pozwala porównywać przebieg procesu dla różnych rodzajów faktur. Na przykład proces akceptacji noty uznaniowej może różnić się od procesu dla standardowej faktury. Jest to przydatne w dashboardzie „Warianty ścieżek akceptacji faktur”. Dlaczego to ważne Umożliwia podział procesu według sposobu obsługi różnych typów faktur i ujawnia różnice w ścieżkach przetwarzania oraz czasie cyklu. Skąd pobrać Bezpośrednio z tabeli nagłówków dokumentów, z pola BKPF-BLART. Przykłady KRREKG | |||
| Waluta faktury InvoiceCurrency | Kod waluty, w której podano kwotę faktury (np. USD, EUR). | ||
| Opis Ten atrybut określa walutę, w której wyrażono kwotę faktury. Jest niezbędnym kontekstem dla wszystkich wartości finansowych. W organizacji działającej w wielu krajach analiza faktur bez uwzględnienia waluty może prowadzić do błędnych wniosków. To pole pozwala prawidłowo przetwarzać dane finansowe: przeliczyć wszystkie kwoty na jedną walutę raportową albo podzielić analizę według walut, aby porównać wyniki finansowe w poszczególnych regionach. Dlaczego to ważne Uzupełnia kwotę faktury o informację o walucie, co umożliwia rzetelną analizę i raportowanie finansowe, zwłaszcza w organizacjach działających w wielu krajach. Skąd pobrać Dane znajdują się w tabelach nagłówków dokumentów, przede wszystkim BKPF-WAERS lub RBKP-WAERS. Przykłady USDEURGBPJPY | |||
| Warunki płatności PaymentTerms | Warunki uzgodnione z dostawcą dotyczące płatności za fakturę, często obejmujące możliwość uzyskania rabatu. | ||
| Opis Warunki płatności określają terminy płatności i zasady przyznawania rabatów za wcześniejszą zapłatę. Na przykład warunek „Z001” może oznaczać: „Płatność w ciągu 30 dni, rabat 2% przy zapłacie w ciągu 10 dni”. Ten atrybut stanowi podstawę dashboardu „Wykorzystanie rabatów za wcześniejszą płatność”. Analiza warunków płatności pozwala wskazać wszystkie faktury uprawniające do rabatu. Porównanie ich z faktycznie uzyskanymi rabatami pokazuje utracone oszczędności i pozwala ocenić sprawność procesu płatności. Dlaczego to ważne Atrybut ten jest niezbędny do analizy możliwości uzyskania rabatu za wcześniejszą płatność, oceny wyników finansowych procesu płatności i wykrywania utraconych oszczędności. Skąd pobrać Dane znajdują się w pozycjach dostawcy w tabeli BSEG-ZTERM lub w nagłówku faktury w RBKP-ZTERM. Przykłady Z0010001NT30 | |||
| Wykonano automatycznie IsAutomated | Flaga wskazująca, czy czynność wykonał automatycznie system, a nie użytkownik. | ||
| Opis Ten atrybut logiczny rozróżnia czynności wykonane przez ludzi od tych realizowanych przez zadania systemowe, workflow lub boty. Na przykład automatyczny przebieg płatności lub księgowanie faktury wygenerowane przez system zostaną oznaczone jako automatyczne. Analiza tego atrybutu pomaga ocenić poziom automatyzacji procesu obsługi zobowiązań. Można go użyć do pomiaru efektów wdrożonych rozwiązań, porównania sprawności etapów automatycznych i ręcznych oraz wskazania kolejnych możliwości automatyzacji. Dlaczego to ważne Pomaga mierzyć poziom automatyzacji procesu, oceniać jej skuteczność i wskazywać możliwości dalszych usprawnień. Skąd pobrać Wartość ustala się na podstawie nazwy użytkownika, np. identyfikatorów kont systemowych takich jak 'SAP_SYSTEM' lub 'BATCHUSER', albo kodów transakcji powiązanych z zadaniami automatycznymi. Przykłady truefalse | |||
| Zastosowano rabat DiscountTaken | Wartość logiczna wskazująca, czy udało się uzyskać rabat za wcześniejszą płatność. | ||
| Opis Ten atrybut wskazuje, czy przy płatności za fakturę faktycznie zastosowano rabat. Pomaga ocenić efektywność finansową procesu obsługi zobowiązań. Stanowi podstawę KPI „Wykorzystanie rabatów za wcześniejszą płatność”. Wystarczy wybrać faktury uprawniające do rabatu na podstawie warunków płatności i sprawdzić ten atrybut, aby dokładnie obliczyć uzyskane oszczędności oraz liczbę niewykorzystanych możliwości. Dzięki temu można liczbowo ocenić wyniki obsługi zobowiązań. Dlaczego to ważne Bezpośrednio mierzy skuteczność uzyskiwania dostępnych rabatów za wcześniejszą płatność, które wpływają na wynik finansowy firmy. Skąd pobrać Atrybut jest wyliczany przez sprawdzenie, czy kwota rabatu w polu BSEG-SKNTO na dokumencie płatności jest większa od zera. Przykłady truefalse | |||
Czynności w procesie obsługi faktur zakupu
| Działanie | Opis | ||
|---|---|---|---|
| Anulowano fakturę | Dokument faktury został storno, co skutecznie wyzerowało jego wpływ finansowy. Jest to alternatywny stan końcowy procesu, często wynikający z błędnego wpisu lub sporu z dostawcą. | ||
| Dlaczego to ważne Śledzenie anulowań pomaga ustalić przyczyny niepowodzeń procesu, takie jak zduplikowane zgłoszenia lub nieprawidłowe dane faktury. Może też wskazać problemy na wcześniejszych etapach. Skąd pobrać Zdarzenie jest jawnie rejestrowane po utworzeniu dokumentu storna. W nagłówku pierwotnego dokumentu (BKPF) zostają wypełnione numer dokumentu storna (STBLG) i przyczyna storna. Rejestrowanie Ustal datę księgowania dokumentu storna powiązanego z pierwotnym dokumentem w nagłówku (BKPF-STBLG). Typ zdarzenia explicit | |||
| Otrzymano fakturę | To zdarzenie oznacza utworzenie dokumentu faktury w SAP, ręcznie lub za pośrednictwem zautomatyzowanego interfejsu, takiego jak OCR/VIM. Zwykle rejestruje się je na podstawie daty i godziny utworzenia nagłówka dokumentu księgowego. | ||
| Dlaczego to ważne Jako początkowy etap procesu zdarzenie to jest niezbędne do obliczenia pełnego czasu obsługi faktury i pomiaru przepustowości całego procesu zobowiązań. Skąd pobrać Zdarzenie odczytuje się z tabeli nagłówków dokumentów księgowych (BKPF), korzystając z daty utworzenia dokumentu (CPUDT) i godziny (CPUTM). Rejestrowanie Użyj znacznika czasu utworzenia dokumentu faktury (BKPF-CPUDT, BKPF-CPUTM). Typ zdarzenia explicit | |||
| Rozliczono płatność | To zdarzenie oznacza ostateczne zamknięcie faktury. Płatność i faktura zostają wzajemnie rozliczone w księdze pomocniczej. Oznacza to zakończenie procesu. | ||
| Dlaczego to ważne Jako końcowy etap procesu zdarzenie to jest niezbędne do dokładnego obliczenia pełnego czasu obsługi faktury. Potwierdza uregulowanie zobowiązania. Skąd pobrać Jest to jawne zdarzenie. Występuje, gdy pole daty rozliczenia (AUGDT) zostaje wypełnione w pozycji dostawcy dokumentu faktury (tabela BSEG). Rejestrowanie Użyj daty rozliczenia (BSEG-AUGDT) z pozycji faktury. Typ zdarzenia explicit | |||
| Zaakceptowano fakturę | Faktura uzyskała wszystkie wymagane akceptacje w systemie workflow. Często jest to ostatni etap przed zaksięgowaniem faktury lub zdjęciem blokady płatności. | ||
| Dlaczego to ważne Ten ważny etap oznacza koniec cyklu akceptacji. Czas od przekazania faktury do akceptacji do jej zatwierdzenia jest istotnym miernikiem sprawności procesu. Skąd pobrać Zdarzenie odczytuje się z dzienników SAP Business Workflow jako zakończenie lub końcowy etap zwolnienia. Można je też ustalić na podstawie zdjęcia blokady płatności po przekazaniu faktury do akceptacji. Rejestrowanie Wyodrębnij zdarzenia zakończenia workflow z dzienników SAP workflow lub zidentyfikuj końcowe zdarzenie „release”. Typ zdarzenia explicit | |||
| Zablokowano płatność faktury | System automatycznie lub ręcznie zablokował fakturę, uniemożliwiając jej opłacenie. Przyczyną są zwykle rozbieżności w cenie lub ilości albo brak wymaganych akceptacji. | ||
| Dlaczego to ważne To ważny sygnał problemów i konieczności poprawek. Analiza przyczyn i czasu trwania blokad pomaga ustalić źródła opóźnień płatności i nieefektywności procesu. Skąd pobrać Jest to jawny status zapisany w polu klucza blokady płatności (ZLSPR) w pozycji dostawcy dokumentu księgowego (tabela BSEG). Rejestrowanie Zdarzenie jest rejestrowane w dokumentach zmian, gdy pole BSEG-ZLSPR zawiera przyczynę blokady. Typ zdarzenia explicit | |||
| Zaksięgowano fakturę | Faktura została formalnie ujęta w księdze głównej, co oznacza powstanie zobowiązania finansowego. Dokument wstępnie wprowadzony staje się zaksięgowany albo faktura jest księgowana bezpośrednio. | ||
| Dlaczego to ważne To ważny etap finansowy. Potwierdza zobowiązanie firmy do zapłaty i często jest warunkiem zaplanowania płatności. Skąd pobrać Zdarzenie identyfikuje się na podstawie daty księgowania (BUDAT) w nagłówku dokumentu (BKPF). W zaksięgowanym dokumencie pole statusu (BKPF-BSTAT) jest puste. Rejestrowanie W przypadku dokumentów, które nie są wstępnie wprowadzone (BKPF-BSTAT jest puste), użyj daty księgowania (BKPF-BUDAT). Typ zdarzenia explicit | |||
| Zrealizowano płatność | Faktura została opłacona. Zdarzenie rejestruje się po zakończeniu przebiegu płatności oraz utworzeniu i zaksięgowaniu dokumentu płatności. | ||
| Dlaczego to ważne To zdarzenie jest ważne przy analizie przepływów pieniężnych i pomiarze KPI „Odsetek płatności zrealizowanych w terminie”. W tym celu datę płatności porównuje się z terminem płatności faktury. Skąd pobrać Zdarzenie odczytuje się z daty księgowania dokumentu płatności, który rozlicza fakturę. Numer dokumentu płatności jest powiązany z fakturą w polu dokumentu rozliczającego (AUGBL) pozycji faktury (BSEG). Rejestrowanie Ustal datę księgowania (BUDAT) dokumentu płatności rozliczającego pozycję faktury. Typ zdarzenia explicit | |||
| Minął termin płatności faktury | To obliczane zdarzenie oznacza, że minął termin płatności netto faktury, a płatność nie została rozliczona. Wskazuje na opóźnienie lub zaległość w płatności. | ||
| Dlaczego to ważne To zdarzenie jest niezbędne w dashboardzie „Zgodność płatności i wiek zobowiązań”. Pomaga wcześniej wykrywać i obsługiwać przeterminowane faktury oraz analizować przyczyny opóźnień w płatnościach. Skąd pobrać SAP nie rejestruje tego jako jawnego zdarzenia. Oblicza się je, porównując bieżącą datę systemową z terminem płatności netto, wyznaczonym na podstawie BSEG-ZFBDT lub daty bazowej i warunków płatności. Rejestrowanie Zdarzenie obliczane, gdy znacznik czasu zdarzenia jest późniejszy niż termin płatności netto faktury. Typ zdarzenia calculated | |||
| Odrzucono fakturę | Osoba akceptująca odrzuciła fakturę w workflow akceptacji. Zwykle powoduje to zwrot faktury do osoby obsługującej ją w celu poprawienia lub uzupełnienia danych. | ||
| Dlaczego to ważne Śledzenie odrzuceń ujawnia pętle poprawek w procesie akceptacji i może wskazywać na problemy ze zgodnością z zasadami lub nieprawidłowe kodowanie faktur. Skąd pobrać Zdarzenie jest rejestrowane jako określony wynik w dziennikach SAP Business Workflow powiązanych z fakturą. Rejestrowanie Wyodrębnij zdarzenia statusu „rejected” z dzienników SAP workflow. Typ zdarzenia explicit | |||
| Przekazano fakturę do akceptacji | Faktura została przekazana do workflow akceptacji zgodnie z wymaganymi regułami biznesowymi. Oznacza to początek podprocesu akceptacji. | ||
| Dlaczego to ważne To zdarzenie wyznacza początek pomiaru KPI „Średni czas akceptacji faktury” i analizy wąskich gardeł w procesie akceptacji. Skąd pobrać Zdarzenie można odczytać z dzienników SAP Business Workflow (tabele SWW*), które rejestrują rozpoczęcie instancji workflow powiązanej z obiektem faktury, np. BUS2081. Rejestrowanie Wyodrębnij zdarzenia rozpoczęcia workflow z dzienników SAP workflow, np. z tabeli SWW_WIHEAD, i powiąż je z dokumentem faktury. Typ zdarzenia explicit | |||
| Rozwiązano niezgodność | To zdarzenie oznacza, że zbadano i rozwiązano wcześniej wykryty problem, który prawdopodobnie spowodował blokadę płatności. Rejestruje się je po usunięciu blokady płatności faktury. | ||
| Dlaczego to ważne Śledzenie tej pętli poprawek jest niezbędne w dashboardzie „Analiza poprawek niezgodności na fakturach”. Pozwala określić czas i nakład pracy poświęcone na usuwanie błędów. Skąd pobrać Zdarzenie ustala się na podstawie dokumentów zmian wskazujących na usunięcie blokady płatności. Głównym źródłem jest dziennik zmian pola BSEG-ZLSPR. Rejestrowanie Wyszukaj dokumenty zmian dla tabeli BSEG, w których wartość pola ZLSPR została zmieniona z niepustej na pustą. Typ zdarzenia inferred | |||
| Utworzono propozycję płatności | Faktura została uwzględniona w propozycji płatności w ramach przebiegu płatności, np. F110. Jest przeznaczona do opłacenia po ostatecznym wykonaniu przebiegu. | ||
| Dlaczego to ważne To zdarzenie pokazuje przejście od otwartego zobowiązania do pozycji przygotowywanej do płatności. Pomaga analizować sprawność operacji płatniczych. Skąd pobrać Zdarzenie jest jawnie rejestrowane w tabelach danych przebiegu płatności, w szczególności REGUP (pozycje przetworzone przez program płatności) i REGUH (nagłówek). Rejestrowanie Ustal, kiedy faktura pojawia się w tabeli REGUP dla przebiegu płatności wskazanego w REGUH. Typ zdarzenia explicit | |||
| Uzgodniono z przyjęciem towaru | To zdarzenie oznacza pomyślne uzgodnienie ilości i wartości na fakturze z odpowiednim dokumentem przyjęcia towaru. Jest to końcowy etap weryfikacji w uzgadnianiu trójstronnym. | ||
| Dlaczego to ważne Śledzenie tego zdarzenia pomaga wykryć nieefektywności w uzgadnianiu trójstronnym i rozbieżności między przyjętym towarem a pozycjami na fakturze od dostawcy. Skąd pobrać Zdarzenie ustala się na podstawie odwołania do dokumentu materiałowego (przyjęcia towaru) w pozycji faktury. Odwołanie jest często powiązane z historią pozycji zamówienia zakupu. Rejestrowanie Zdarzenie ustala się na podstawie odwołania do dokumentu przyjęcia towaru w pozycji faktury, np. w tabeli RSEG dla faktur MIRO. Typ zdarzenia inferred | |||
| Uzgodniono z zamówieniem zakupu | To zdarzenie oznacza pomyślne uzgodnienie faktury z odpowiednim zamówieniem zakupu. Jest to ważny etap uzgadniania trójstronnego faktur związanych z zakupami. | ||
| Dlaczego to ważne Analiza tego zdarzenia pozwala ocenić sprawność uzgadniania i stanowi podstawę KPI „Skuteczność uzgadniania trójstronnego” oraz „Odsetek faktur bez zamówienia zakupu”. Skąd pobrać Zdarzenie ustala się, gdy pozycja faktury w tabeli BSEG lub ACDOCA zawiera prawidłowy numer zamówienia zakupu (EBELN) i numer pozycji (EBELP). Rejestrowanie Zdarzenie ustala się na podstawie obecności odwołania do zamówienia zakupu (BSEG-EBELN) w dokumencie faktury w chwili jego utworzenia. Typ zdarzenia inferred | |||
| Wstępnie wprowadzono fakturę | Faktura została wprowadzona do systemu, ale nie zaksięgowano jej jeszcze w księdze głównej. Ten etap często pozwala zapisać niekompletny dokument i wrócić do jego przetwarzania lub akceptacji później. | ||
| Dlaczego to ważne Śledzenie wstępnie wprowadzonych faktur pomaga wykryć opóźnienia przed rozpoczęciem formalnego księgowania oraz problemy z kompletnością danych lub wstępną weryfikacją. Skąd pobrać Status ustala się na podstawie pola statusu dokumentu w nagłówku dokumentu księgowego (BKPF-BSTAT = 'V' oznacza dokument wstępnie wprowadzony). Zdarzenie występuje w chwili ustawienia tego statusu. Rejestrowanie Wyszukaj dokumenty zmian dla tabeli BKPF, w których pole BSTAT przyjmuje wartość 'V' (Vor-erfasst/Pre-entered). Typ zdarzenia inferred | |||
Instrukcje pobierania danych
Kroki
- Wymagania wstępne i dostęp: Upewnijcie się, że macie użytkownika z uprawnieniami do odczytu schematu bazy danych SAP S/4HANA (zwykle SAPABAP1 lub podobnego), w którym znajdują się widoki CDS. Potrzebne będzie narzędzie SQL umożliwiające połączenie z bazą SAP HANA, na przykład SAP HANA Studio, DBeaver lub inne narzędzie do wykonywania zapytań.
- Wybór podstawowych widoków CDS: Do ekstrakcji służą przede wszystkim widoki CDS I_JournalEntry, I_JournalEntryItem, I_SupplierInvoiceAPI01, I_ChangeDocument, I_WorkflowStatusDetails i I_PaymentProposalItem. Zapoznajcie się z ich najważniejszymi polami.
- Określenie zakresu zapytania: Otwórzcie klienta SQL i połączcie się z bazą SAP HANA. Przed uruchomieniem pełnego zapytania określcie zakres ekstrakcji: ustawcie identyfikator systemu źródłowego, zakres dat faktur (CreationDateTime) oraz właściwe kody spółek.
- Przygotowanie głównego zapytania: Skopiujcie pełne zapytanie SQL z sekcji zapytań do klienta SQL. Najpierw wybiera ono podstawowy zbiór faktur za pomocą Common Table Expressions (CTE), a następnie tworzy dziennik zdarzeń, łącząc dane dotyczące 15 różnych czynności.
- Ustawienie parametrów zapytania: W skopiowanym zapytaniu SQL znajdźcie zmienne zastępcze. Zastąpcie '[YYYY-MM-DD]' datami początku i końca analizowanego okresu. Zastąpcie '[Your Company Code 1]', '[Your Company Code 2]' listą kodów spółek SAP, które mają zostać uwzględnione w analizie.
- Uruchomienie zapytania ekstrakcyjnego: Uruchomcie całe zapytanie SQL. W zależności od ilości danych i wybranego zakresu dat wykonanie może potrwać od kilku minut do kilku godzin.
- Weryfikacja wstępnych wyników: Po zakończeniu zapytania sprawdźcie kilkaset pierwszych wierszy wyników. Zweryfikujcie spójność danych, upewnijcie się, że wszystkie kolumny zawierają oczekiwane wartości i że występują różne wartości ActivityName.
- Eksport dziennika zdarzeń: Wyeksportujcie cały zestaw wyników z klienta SQL do pliku CSV. Zapiszcie go w kodowaniu UTF-8, aby uniknąć problemów ze znakami. Nadajcie plikowi opisową nazwę, na przykład sap_s4hana_ap_event_log.csv.
- Przygotowanie do przesłania: Przed przesłaniem danych do narzędzia process mining sprawdźcie, czy nagłówki kolumn w pliku CSV dokładnie odpowiadają wymaganym nazwom atrybutów: Invoice, ActivityName, EventTime, SourceSystem, LastDataUpdate, UserName itd.
- Przesłanie danych do narzędzia process mining: Prześlijcie wygenerowany plik CSV na platformę process mining i przypiszcie kolumny do odpowiednich pól: identyfikatora case, czynności i timestampu.
Konfiguracja
- Najważniejsze widoki CDS: Ekstrakcja wykorzystuje kilka standardowych widoków CDS w S/4HANA. Najważniejsze z nich to:
- I_JournalEntry i I_JournalEntryItem: nagłówki i pozycje dokumentów finansowych, dane księgowania oraz informacje o rozliczeniu.
- I_SupplierInvoiceAPI01: szczegóły faktur MM (Logistics), w tym odwołania do zamówień zakupu i blokady płatności.
- I_ChangeDocument: dokładne timestampy zmian, takich jak założenie lub usunięcie blokady płatności.
- I_WorkflowStatusDetails: zdarzenia związane z workflow zatwierdzania faktur.
- I_PaymentProposalItem: informacja o uwzględnieniu faktury w propozycji przebiegu płatności.
- I_Supplier: dodatkowe dane z kartoteki dostawców, takie jak VendorName.
- Filtrowanie zakresu dat: Ograniczenie ilości danych filtrem dat jest niezbędne. Podane zapytanie filtruje CreationDateTime w CTE Invoices_Base. Na początek zalecany jest zakres 3–6 miesięcy, aby czas wykonania zapytania pozostał możliwy do opanowania.
- Filtry obowiązkowe: Zawsze filtrujcie dane według CompanyCode. Analiza wszystkich kodów spółek naraz może trwać bardzo długo i nie zawsze ma uzasadnienie biznesowe. Filtrujcie również JournalEntryType, aby uwzględnić tylko dokumenty dotyczące dostawców, na przykład 'KR' i 'RE'.
- Wymagania wstępne: Użytkownik bazy danych uruchamiający zapytanie musi mieć uprawnienia SELECT do wszystkich użytych widoków CDS i bazowego schematu HANA. Dostęp do aplikacji przez SAP GUI nie wystarczy.
- Wydajność: Bezpośrednie zapytania do I_ChangeDocument mogą mocno obciążać zasoby. Podane zapytanie ogranicza to obciążenie, najpierw filtrując faktury. W przypadku bardzo dużych zbiorów danych warto uruchamiać ekstrakcję poza godzinami szczytu lub dzielić ją na mniejsze zakresy dat.
Przykładowe zapytanie sql
-- Common Table Expression (CTE) to select the base set of AP Invoices
WITH Invoices_Base AS (
SELECT
I_JournalEntry.CompanyCode,
I_JournalEntry.AccountingDocument,
I_JournalEntry.FiscalYear,
CONCAT(I_JournalEntry.CompanyCode, CONCAT(I_JournalEntry.AccountingDocument, I_JournalEntry.FiscalYear)) AS InvoiceId,
I_JournalEntry.CreationDateTime,
I_JournalEntry.CreatedByUser,
I_JournalEntry.DocumentStatus,
I_JournalEntry.JournalEntryType,
I_JournalEntry.ReversalReferenceJournalEntry,
I_JournalEntry.IsReversed,
I_JournalEntry.ReversalDate,
IJE_ITEM.NetDueDate,
IJE_ITEM.Supplier,
SUP.SupplierName AS VendorName,
IJE_ITEM.AmountInCompanyCodeCurrency AS InvoiceAmount,
MM.PurchaseOrder AS PurchaseOrderNumber,
MM.PaymentBlockingReason
FROM I_JournalEntry
-- Join to get item details like due date and supplier
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON I_JournalEntry.CompanyCode = IJE_ITEM.CompanyCode
AND I_JournalEntry.AccountingDocument = IJE_ITEM.AccountingDocument
AND I_JournalEntry.FiscalYear = IJE_ITEM.FiscalYear
AND IJE_ITEM.IsSupplier = 'X'
-- Join to get vendor name from master data
LEFT JOIN I_Supplier AS SUP
ON IJE_ITEM.Supplier = SUP.Supplier
-- Join to get MM Invoice specific data like PO Number and Payment Block
LEFT JOIN I_SupplierInvoiceAPI01 AS MM
ON I_JournalEntry.AccountingDocument = MM.AccountingDocument
AND I_JournalEntry.CompanyCode = MM.CompanyCode
AND I_JournalEntry.FiscalYear = MM.FiscalYear
WHERE
I_JournalEntry.JournalEntryType IN ('KR', 'RE') -- Standard Vendor Invoice Types
AND I_JournalEntry.CompanyCode IN ('[Your Company Code 1]', '[Your Company Code 2]')
AND I_JournalEntry.CreationDateTime BETWEEN '[YYYY-MM-DD]T00:00:00Z' AND '[YYYY-MM-DD]T23:59:59Z'
)
-- Event: 1. Invoice Received
SELECT
B.InvoiceId AS "Invoice",
'Invoice Received' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
UNION ALL
-- Event: 2. Invoice Parked
SELECT
B.InvoiceId AS "Invoice",
'Invoice Parked' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.DocumentStatus = 'V' -- 'V' stands for Parked
UNION ALL
-- Event: 3. Purchase Order Matched
SELECT
B.InvoiceId AS "Invoice",
'Purchase Order Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PurchaseOrderNumber IS NOT NULL AND B.PurchaseOrderNumber <> ''
UNION ALL
-- Event: 4. Goods Receipt Matched
SELECT
B.InvoiceId AS "Invoice",
'Goods Receipt Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_SupplierInvoiceItemAPI01 AS MM_ITEM
ON B.AccountingDocument = MM_ITEM.AccountingDocument
AND B.FiscalYear = MM_ITEM.FiscalYear
WHERE MM_ITEM.GoodsReceipt IS NOT NULL AND MM_ITEM.GoodsReceipt <> ''
UNION ALL
-- Event: 5. Invoice Blocked For Payment
SELECT
B.InvoiceId AS "Invoice",
'Invoice Blocked For Payment' AS "ActivityName",
B.CreationDateTime AS "EventTime", -- Approximates block time as creation time if blocked on entry
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PaymentBlockingReason IS NOT NULL AND B.PaymentBlockingReason <> ''
UNION ALL
-- Event: 6. Discrepancy Resolved (Payment Block Removed)
SELECT
B.InvoiceId AS "Invoice",
'Discrepancy Resolved' AS "ActivityName",
CD.ChangeTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CD.UserName AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_ChangeDocument AS CD
ON CONCAT(B.CompanyCode, B.AccountingDocument, B.FiscalYear) = CD.ObjectValue
WHERE CD.ChangeDocumentObject = 'INVOICE'
AND CD.TableName = 'RBKP'
AND CD.FieldName = 'ZLSPR' -- Field for Payment Block
AND CD.NewFieldValue = '' -- Block was removed
UNION ALL
-- Event: 7, 8, 9. Workflow Events (Routed, Approved, Rejected)
SELECT
B.InvoiceId AS "Invoice",
CASE WF.WorkflowStatus
WHEN 'READY' THEN 'Invoice Routed For Approval'
WHEN 'APPROVED' THEN 'Invoice Approved'
WHEN 'REJECTED' THEN 'Invoice Rejected'
END AS "ActivityName",
WF.WorkflowStatusChangedDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
WF.WorkflowStatusChangedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_WorkflowStatusDetails AS WF
ON B.InvoiceId = WF.WorkflowScenarioInstance
WHERE WF.WorkflowStatus IN ('READY', 'APPROVED', 'REJECTED')
UNION ALL
-- Event: 10. Invoice Posted
SELECT
B.InvoiceId AS "Invoice",
'Invoice Posted' AS "ActivityName",
JE.PostingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntry AS JE
ON B.AccountingDocument = JE.AccountingDocument
AND B.CompanyCode = JE.CompanyCode
AND B.FiscalYear = JE.FiscalYear
WHERE B.DocumentStatus <> 'V' -- Any status other than Parked is considered Posted for AP
UNION ALL
-- Event: 11. Payment Proposal Created
SELECT
B.InvoiceId AS "Invoice",
'Payment Proposal Created' AS "ActivityName",
PPI.PaymentProposalRunDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
PPI.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_PaymentProposalItem AS PPI
ON B.CompanyCode = PPI.CompanyCode
AND B.AccountingDocument = PPI.AccountingDocument
AND B.FiscalYear = PPI.FiscalYear
UNION ALL
-- Event: 12. Payment Executed
-- This links the invoice to its clearing document, which is the payment document
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Executed' AS "ActivityName",
CLEAR_JE.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CLEAR_JE.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
INNER JOIN I_JournalEntry AS CLEAR_JE
ON IJE_ITEM.ClearingJournalEntry = CLEAR_JE.AccountingDocument
AND IJE_ITEM.CompanyCode = CLEAR_JE.CompanyCode
WHERE IJE_ITEM.ClearingJournalEntry IS NOT NULL AND IJE_ITEM.ClearingJournalEntry <> ''
AND CLEAR_JE.JournalEntryType = 'KZ' -- Vendor Payment Document Type
UNION ALL
-- Event: 13. Invoice Due Date Passed
SELECT
B.InvoiceId AS "Invoice",
'Invoice Due Date Passed' AS "ActivityName",
ADD_DAYS(B.NetDueDate, 1) AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
'SYSTEM' AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE B.NetDueDate < CURRENT_DATE
AND IJE_ITEM.ClearingDate IS NULL -- Invoice is not yet cleared
UNION ALL
-- Event: 14. Payment Cleared
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Cleared' AS "ActivityName",
IJE_ITEM.ClearingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
IJE_ITEM.ChangedByUser AS "UserName", -- User who cleared it
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE IJE_ITEM.ClearingDate IS NOT NULL
UNION ALL
-- Event: 15. Invoice Cancelled
SELECT
B.InvoiceId AS "Invoice",
'Invoice Cancelled' AS "ActivityName",
B.ReversalDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName", -- User who created the original document
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.IsReversed = 'X'; Kroki
- Potwierdźcie, że macie bezpośredni dostęp do odczytu schematu SAP HANA zawierającego odpowiednie tabele SAP S/4HANA. Uzyskajcie parametry połączenia, dane logowania, nazwę schematu i uprawnienia do odczytu BKPF, ACDOCA oraz innych tabel skonfigurowanych dla dokumentów wstępnie zaksięgowanych, workflow, zakupów, przyjęć towarów, propozycji płatności, rozliczeń i danych o storno.
- Przed uruchomieniem sprawdźcie techniczny model danych w systemie docelowym. Zweryfikujcie fizyczne nazwy, pola kluczy, pola timestampów, powiązania storna i płatności oraz sposób zapisu danych workflow. Zastąpcie każdy placeholder w nawiasach kwadratowych odpowiednim obiektem lub polem z systemu. Nie zakładajcie, że dane workflow lub dokumentów wstępnie zaksięgowanych są przechowywane w jednej uniwersalnej tabeli.
- Ustawcie parametry ekstrakcji: [Start date], [End date], [Company code filter], [Document type filter] i [Schema name]. Na początek użyjcie zakresu od trzech do sześciu miesięcy. Wydłużcie go dopiero po sprawdzeniu wydajności i kompletności danych.
- Uruchomcie zapytanie SQL w zatwierdzonym kliencie SQL dla SAP HANA, na przykład SAP HANA Database Explorer lub innym autoryzowanym narzędziu. Zapytanie zwraca jeden wiersz dla każdej jawnie wyodrębnionej czynności. ProcessMind nie wyznacza zdarzeń na podstawie innych danych.
- Sprawdźcie wyniki. Upewnijcie się, że Invoice jest identyfikatorem case, ActivityName zawiera wszystkie 15 wymaganych nazw czynności, EventTime jest wypełnione i ma wiarygodną chronologię, SourceSystem wskazuje SAP S/4HANA, a LastDataUpdate zawiera timestamp odświeżenia ekstrakcji. Przed wczytaniem danych sprawdźcie duplikaty zdarzeń, powiązania storna i połączenia dokumentów.
- Zastosujcie mapowania właściwe dla danego systemu. Na przykład przypiszcie skonfigurowane źródło dokumentów wstępnie zaksięgowanych do Invoice Parked, źródło workflow do Invoice Routed For Approval, Invoice Approved i Invoice Rejected, a źródło płatności do Payment Proposal Created i Payment Executed. Jeśli wymaga tego audytowalność, zachowajcie identyfikatory źródłowe w dodatkowych kolumnach.
- Wyeksportujcie wyniki do pliku rozdzielanego separatorami lub zestawu wyników bazy danych, z jednym zdarzeniem w każdym wierszu. Użyjcie kodowania UTF-8, zachowajcie timestampy w jednej strefie czasowej i pozostawcie dokładne nazwy kolumn: Invoice, ActivityName, EventTime, SourceSystem, LastDataUpdate, UserName, CompanyCode, VendorName, InvoiceAmount, PurchaseOrderNumber i InvoiceDueDate. Nie łączcie czynności w jeden rekord faktury.
- Prześlijcie dziennik zdarzeń do ProcessMind i ustawcie Invoice jako identyfikator case, ActivityName jako kolumnę czynności, a EventTime jako kolumnę czasu zdarzenia. Sprawdźcie, czy opcjonalne atrybuty przypisano do właściwych pól. ProcessMind odczytuje dziennik zdarzeń bez zmian, dlatego przed przesłaniem każdy wiersz z czynnością przeznaczoną do wizualizacji musi już znajdować się w danych.
Konfiguracja
- Zakres dat: Zacznijcie od trzech do sześciu miesięcy. W zależności od wyodrębnianej czynności użyjcie daty księgowania, daty utworzenia dokumentu lub daty odpowiedniego zdarzenia źródłowego. Wydłużcie zakres dopiero po sprawdzeniu czasu wykonania zapytania i okresu przechowywania danych w źródle.
- Filtrowanie według spółki: Skonfigurujcie [Company code filter], aby ograniczyć ekstrakcję do wymaganych kodów spółek. Jeśli ograniczenie nie jest potrzebne, wybierzcie wszystkie spółki w kontrolowany sposób, zamiast uruchamiać nieograniczone zapytanie w środowisku produkcyjnym.
- Filtrowanie dokumentów: Skonfigurujcie [Document type filter] dopiero po potwierdzeniu typów dokumentów używanych w systemie docelowym dla faktur dostawców, not kredytowych, dokumentów wstępnie zaksięgowanych, dokumentów płatności i storna.
- Mapowanie schematu i obiektów: Zastąpcie [Schema name] oraz każdy obiekt źródłowy lub pole w nawiasach kwadratowych wartościami zweryfikowanymi w docelowym systemie SAP S/4HANA. Bezpośrednie zapytanie do HANA trzeba dostosować do aktywnych aplikacji, rozszerzeń, projektu workflow i modelu danych danego systemu.
- Obsługa timestampów: Ujednolićcie wszystkie timestampy źródłowe do jednej strefy czasowej. Jeśli dostępna jest tylko data, zastosujcie udokumentowaną domyślną godzinę i opiszcie to ograniczenie w słowniku danych.
- Znaczenie zdarzeń: Wyodrębniajcie każdą czynność jako osobny wiersz. Nie łączcie wielu czynności w jeden rekord faktury i nie zakładajcie, że ProcessMind wyznaczy zdarzenia dopasowania, zatwierdzenia, terminu płatności lub rozliczenia.
- Zdarzenie dotyczące terminu płatności: Generujcie Invoice Due Date Passed tylko dla faktur, których termin płatności przypada przed skonfigurowanym timestampem oceny i które nie zostały rozliczone do tego czasu. Do obliczenia zapytanie wykorzystuje [Evaluation timestamp].
- Wydajność: Ograniczcie początkowy zakres dat i spółek, filtrujcie według pól indeksowanych lub istotnych dla partycjonowania, unikajcie pobierania niepotrzebnych kolumn i uruchamiajcie zapytanie w zatwierdzonym oknie raportowym. Jeśli zapytanie produkcyjne przekracza uzgodniony czas wykonania, rozważcie przygotowanie podzbiorów danych w obszarze pośrednim.
- Odświeżanie danych: Ustawcie LastDataUpdate na timestamp uruchomienia ekstrakcji. Przy ładowaniu przyrostowym zachowajcie punkt kontrolny oparty na odpowiednim timestampie zmiany w źródle i uwzględnijcie okres wsteczny, aby wychwycić późniejsze aktualizacje i storna.
- Wymagania wstępne: Potrzebne są uprawnienia do bazy danych, zatwierdzony dostęp do środowiska produkcyjnego, znajomość konfiguracji Universal Journal w systemie, dostęp do skonfigurowanych źródeł dokumentów wstępnie zaksięgowanych, zakupów, przyjęć towarów, workflow, płatności, rozliczeń i storna, a także wymagane licencje SAP lub zgody związane z zarządzaniem systemem.
Przykładowe zapytanie sql
WITH
params AS (
SELECT
TO_DATE('[Start date]') AS start_date,
TO_DATE('[End date]') AS end_date,
TO_TIMESTAMP('[Evaluation timestamp]') AS evaluation_ts,
TO_TIMESTAMP('[Extraction timestamp]') AS extraction_ts
FROM DUMMY
),
base_invoice AS (
SELECT
b.mandt,
b.bukrs,
b.belnr,
b.gjahr,
b.bldat,
b.budat,
b.cpudt,
b.cputm,
b.usnam,
b.blart,
b.xblnr,
b.stblg,
b.stjah,
a.lifnr,
a.wrbtr,
a.waers,
a.zfbdt,
a.zbd1t,
a.zbd2t,
a.zbd3t,
a.ebeln,
a.ebelp,
a.augbl,
a.augdt,
a.buzei,
v.name1 AS vendor_name,
CASE
WHEN a.zfbdt IS NOT NULL THEN ADD_DAYS(a.zfbdt, COALESCE(a.zbd1t, 0))
ELSE NULL
END AS invoice_due_date
FROM [Schema name].BKPF b
INNER JOIN [Schema name].ACDOCA a
ON a.mandt = b.mandt
AND a.rbukrs = b.bukrs
AND a.belnr = b.belnr
AND a.gjahr = b.gjahr
LEFT JOIN [Schema name].[Vendor master table] v
ON v.[Vendor key field] = a.lifnr
CROSS JOIN params p
WHERE b.bukrs IN ([Company code filter])
AND b.blart IN ([Document type filter])
AND b.cpudt BETWEEN p.start_date AND p.end_date
),
invoice_received AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Received' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(cpudt, 'YYYY-MM-DD') || ' ' || COALESCE(TO_VARCHAR(cputm), '00:00:00')) AS event_time,
CAST(usnam AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
),
invoice_parked AS (
SELECT
CAST([Parked invoice key field] AS NVARCHAR(40)) AS invoice,
'Invoice Parked' AS activity_name,
[Parked event timestamp field] AS event_time,
CAST([Parked user field] AS NVARCHAR(80)) AS user_name,
[Parked company code field] AS company_code,
[Parked vendor name field] AS vendor_name,
[Parked amount field] AS invoice_amount,
[Parked currency field] AS document_currency,
CAST([Parked purchase order field] AS NVARCHAR(40)) AS purchase_order_number,
[Parked due date field] AS invoice_due_date
FROM [Schema name].[Parked document source]
WHERE [Parked event date field] BETWEEN (SELECT start_date FROM params) AND (SELECT end_date FROM params)
AND [Parked company code field] IN ([Company code filter])
),
purchase_order_matched AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Purchase Order Matched' AS activity_name,
COALESCE([Purchase order match timestamp field], TO_TIMESTAMP(TO_VARCHAR(i.cpudt, 'YYYY-MM-DD') || ' ' || COALESCE(TO_VARCHAR(i.cputm), '00:00:00'))) AS event_time,
CAST(COALESCE([Purchase order match user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrBtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Purchase order match source] m
ON m.[Invoice document key field] = i.belnr
AND m.[Invoice company code field] = i.bukrs
AND m.[Invoice fiscal year field] = i.gjahr
WHERE i.ebeln IS NOT NULL
),
goods_receipt_matched AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Goods Receipt Matched' AS activity_name,
[Goods receipt match timestamp field] AS event_time,
CAST(COALESCE([Goods receipt match user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Goods receipt match source] g
ON g.[Invoice document key field] = i.belnr
AND g.[Invoice company code field] = i.bukrs
AND g.[Invoice fiscal year field] = i.gjahr
WHERE i.ebeln IS NOT NULL
),
invoice_blocked AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Blocked For Payment' AS activity_name,
[Payment block timestamp field] AS event_time,
CAST(COALESCE([Payment block user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment block source] b
ON b.[Invoice document key field] = i.belnr
AND b.[Invoice company code field] = i.bukrs
AND b.[Invoice fiscal year field] = i.gjahr
WHERE [Payment block value field] IS NOT NULL
),
discrepancy_resolved AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Discrepancy Resolved' AS activity_name,
[Payment block removal timestamp field] AS event_time,
CAST(COALESCE([Payment block removal user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment block history source] h
ON h.[Invoice document key field] = i.belnr
AND h.[Invoice company code field] = i.bukrs
AND h.[Invoice fiscal year field] = i.gjahr
WHERE [Previous payment block value field] IS NOT NULL
AND [New payment block value field] IS NULL
),
invoice_routed_for_approval AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Routed For Approval' AS activity_name,
[Workflow routed timestamp field] AS event_time,
CAST([Workflow initiator field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow routed event value]'
),
invoice_approved AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Approved' AS activity_name,
[Workflow approval timestamp field] AS event_time,
CAST([Workflow approver field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow approved event value]'
),
invoice_rejected AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Rejected' AS activity_name,
[Workflow rejection timestamp field] AS event_time,
CAST([Workflow rejector field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow rejected event value]'
),
invoice_posted AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Posted' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(budat, 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(usnam AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
WHERE stblg IS NULL
),
payment_proposal_created AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Proposal Created' AS activity_name,
[Payment proposal timestamp field] AS event_time,
CAST([Payment proposal user field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment proposal source] p
ON p.[Invoice document key field] = i.belnr
AND p.[Invoice company code field] = i.bukrs
AND p.[Invoice fiscal year field] = i.gjahr
),
payment_executed AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Executed' AS activity_name,
[Payment execution timestamp field] AS event_time,
CAST([Payment execution user field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment execution source] p
ON p.[Invoice document key field] = i.belnr
AND p.[Invoice company code field] = i.bukrs
AND p.[Invoice fiscal year field] = i.gjahr
),
invoice_due_date_passed AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Due Date Passed' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(i.invoice_due_date, 'YYYY-MM-DD') || ' 23:59:59') AS event_time,
CAST(i.usnam AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
WHERE i.invoice_due_date IS NOT NULL
AND TO_TIMESTAMP(TO_VARCHAR(i.invoice_due_date, 'YYYY-MM-DD') || ' 23:59:59') < (SELECT evaluation_ts FROM params)
AND i.augbl IS NULL
),
payment_cleared AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Cleared' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(i.augdt, 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(i.usnam AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
WHERE i.augbl IS NOT NULL
AND i.augdt IS NOT NULL
),
invoice_cancelled AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Cancelled' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR([Reversal posting date field], 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(COALESCE([Reversal user field], usnam) AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
WHERE stblg IS NOT NULL
),
all_events AS (
SELECT * FROM invoice_received
UNION ALL SELECT * FROM invoice_parked
UNION ALL SELECT * FROM purchase_order_matched
UNION ALL SELECT * FROM goods_receipt_matched
UNION ALL SELECT * FROM invoice_blocked
UNION ALL SELECT * FROM discrepancy_resolved
UNION ALL SELECT * FROM invoice_routed_for_approval
UNION ALL SELECT * FROM invoice_approved
UNION ALL SELECT * FROM invoice_rejected
UNION ALL SELECT * FROM invoice_posted
UNION ALL SELECT * FROM payment_proposal_created
UNION ALL SELECT * FROM payment_executed
UNION ALL SELECT * FROM invoice_due_date_passed
UNION ALL SELECT * FROM payment_cleared
UNION ALL SELECT * FROM invoice_cancelled
)
SELECT
invoice AS "Invoice",
activity_name AS "ActivityName",
event_time AS "EventTime",
'SAP S/4HANA' AS "SourceSystem",
(SELECT extraction_ts FROM params) AS "LastDataUpdate",
user_name AS "UserName",
company_code AS "CompanyCode",
vendor_name AS "VendorName",
invoice_amount AS "InvoiceAmount",
purchase_order_number AS "PurchaseOrderNumber",
invoice_due_date AS "InvoiceDueDate"
FROM all_events
WHERE invoice IS NOT NULL
AND event_time IS NOT NULL
ORDER BY "Invoice", "EventTime", "ActivityName"; Kroki
- Specyfikacja i projekt: Przed rozpoczęciem programowania uzgodnijcie z analitykami biznesowymi dokładne warunki wyzwalające i pola danych dla każdej z 15 wymaganych czynności. Określcie odpowiednie tabele SAP, typy dokumentów, na przykład 'KR' i 'RE', oraz kody spółek objęte zakresem.
- Utworzenie programu ABAP: Uruchomcie edytor ABAP za pomocą transakcji SE38. Utwórzcie nowy program wykonywalny, na przykład Z_PM_AP_INVOICE_EXTRACT. Nadajcie mu opisowy tytuł i ustawcie aplikację na 'Financial Accounting'.
- Definicja ekranu wyboru: W programie zdefiniujcie ekran wyboru (za pomocą słów kluczowych PARAMETERS i SELECT-OPTIONS), który pozwoli określić zakres dat ekstrakcji (datę utworzenia faktury), docelowe kody spółek (BUKRS) i odpowiednie typy dokumentów faktur (BLART). Dodajcie też parametr ścieżki pliku wyjściowego na serwerze aplikacji.
- Deklaracje danych: Zdefiniujcie strukturę tabeli wewnętrznej zgodną z końcowym formatem dziennika zdarzeń, na przykład TY_EVENT_LOG, obejmującą wszystkie wymagane i zalecane atrybuty. Zadeklarujcie tabele wewnętrzne do przechowywania danych pobranych z tabel źródłowych SAP, takich jak BKPF, BSEG, RBKP, RSEG, CDHDR, CDPOS i REGUH.
- Główny wybór danych: Rozpocznijcie ekstrakcję od wybrania podstawowego zbioru faktur z RBKP (faktury logistyczne) i BKPF (faktury finansowe) zgodnie z kryteriami ekranu wyboru. Zapiszcie klucze tych faktur w tabeli wewnętrznej, aby wykorzystać je przy kolejnych wyszukiwaniach.
- Kolejne etapy ekstrakcji czynności: Dla każdej faktury z głównego zbioru wykonajcie serię zapytań, aby znaleźć timestampy i szczegóły poszczególnych czynności biznesowych. Na przykład sprawdźcie CDHDR i CDPOS pod kątem zmian blokady płatności, REGUH i REGUP pod kątem danych o przebiegu płatności, a BKPF pod kątem szczegółów dokumentu storna. Dodajcie nowy rekord do końcowej tabeli dziennika zdarzeń dla każdej znalezionej czynności.
- Logika zdarzeń obliczanych: Zaimplementujcie w ABAP logikę dla czynności, które nie są bezpośrednio zapisane w polu tabeli. Dla zdarzenia 'Invoice Due Date Passed' użyjcie terminu płatności faktury (BSEG-ZFBDT + warunki płatności) i daty rozliczenia (BSEG-AUGDT). Jeśli rozliczenie nastąpiło po terminie płatności, utwórzcie nowy rekord zdarzenia z timestampem ustawionym na dzień terminu płatności.
- Przekształcanie i wzbogacanie danych: Podczas zbierania danych dla każdej czynności uzupełnijcie wszystkie wymagane atrybuty. Obejmuje to pobranie nazw dostawców z LFA1, połączenie daty i godziny w jeden ciąg timestampu (CONCATENATE...INTO...) oraz ustawienie wartości SourceSystem.
- Utworzenie pliku wynikowego: Po przetworzeniu wszystkich faktur i powiązanych z nimi czynności oraz zebraniu danych w końcowej tabeli wewnętrznej użyjcie instrukcji OPEN DATASET, LOOP AT ... TRANSFER i CLOSE DATASET, aby zapisać dane w pliku pod ścieżką na serwerze aplikacji wskazaną na ekranie wyboru.
- Pobranie pliku i przygotowanie do przesłania: Użyjcie transakcji CG3Y, aby pobrać wygenerowany plik z serwera aplikacji na komputer lokalny. Zapiszcie go jako plik CSV w kodowaniu UTF-8. Przed przesłaniem do narzędzia process mining sprawdźcie, czy nagłówki kolumn odpowiadają wymaganym atrybutom, takim jak Invoice, ActivityName i EventTime.
Konfiguracja
- Zakres dat: Zdefiniujcie opcję wyboru P_CPUDT dla daty utworzenia faktury (BKPF-CPUDT lub RBKP-CPUDT). Do wstępnej analizy zaleca się zakres danych obejmujący 6–12 miesięcy.
- Kod spółki (P_BUKRS): Obowiązkowy parametr SELECT-OPTIONS służący do filtrowania według określonych kodów spółek. Nie zaleca się przetwarzania wszystkich spółek naraz, chyba że jest to bezwzględnie konieczne.
- Typ dokumentu faktury (P_BLART): Parametr SELECT-OPTIONS służący do filtrowania według odpowiednich typów dokumentów faktur. Typowe wartości to 'KR' (faktura dostawcy), 'KG' (nota kredytowa dostawcy) i 'RE' (weryfikacja faktury logistycznej).
- Tryb wykonania: W przypadku dużej ilości danych uruchamiajcie program jako zadanie w tle (SM36/SM37), aby uniknąć przekroczenia limitu czasu w dialogowym trybie pierwszoplanowym. Zaplanujcie jego wykonanie poza godzinami szczytu.
- Ścieżka pliku wyjściowego: Parametr określający ścieżkę i nazwę pliku na serwerze aplikacji SAP, na przykład w katalogu /tmp/. Przed pobraniem plik jest zapisywany w tej lokalizacji.
- Wymagania wstępne: Użytkownik uruchamiający raport musi mieć uprawnienia do odczytu tabel FI, CO i MM (BKPF, BSEG, RBKP, RSEG, LFA1), tabel zmian dokumentów (CDHDR, CDPOS) oraz tabel workflow. Do zapisywania plików na serwerze aplikacji wymagany jest również obiekt autoryzacji S_DATASET.
Przykładowe zapytanie abap
*&---------------------------------------------------------------------*
*& Report Z_PM_AP_INVOICE_EXTRACT
*&---------------------------------------------------------------------*
*& This report extracts Accounts Payable invoice lifecycle events for
*& process mining analysis.
*&---------------------------------------------------------------------*
REPORT z_pm_ap_invoice_extract.
*&---------------------------------------------------------------------*
*& Data Structures
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
invoice TYPE belnr_d,
activityname TYPE string,
eventtime TYPE string,
sourcesystem TYPE logsys,
lastdataupdate TYPE string,
username TYPE uname,
companycode TYPE bukrs,
vendorname TYPE name1_gp,
invoiceamount TYPE wrbtr,
purchaseordernumber TYPE ebeln,
invoiceduedate TYPE d,
END OF ty_event_log.
DATA: gt_event_log TYPE TABLE OF ty_event_log.
DATA: gv_system_id TYPE logsys.
DATA: gv_last_update TYPE string.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_bukrs FOR bkpf-bukrs OBLIGATORY,
s_cpudt FOR bkpf-cpudt OBLIGATORY DEFAULT sy-datum,
s_blart FOR bkpf-blart.
PARAMETERS: p_fpath TYPE string OBLIGATORY DEFAULT '/tmp/ap_extract.csv'.
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
" Get System ID and Update Timestamp
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = gv_system_id
EXCEPTIONS
own_logical_system_not_defined = 1
OTHERS = 2.
CONCATENATE sy-datum sy-uzeit INTO gv_last_update.
" Internal tables for SAP data
DATA: lt_bkpf TYPE TABLE OF bkpf,
lt_rbkp TYPE TABLE OF rbkp.
" Select base documents
SELECT * FROM bkpf INTO TABLE lt_bkpf
WHERE bukrs IN s_bukrs
AND cpudt IN s_cpudt
AND blart IN s_blart
AND ( blart = 'KR' OR blart = 'KG' ). " Example FI Invoice Types
SELECT * FROM rbkp INTO TABLE lt_rbkp
WHERE bukrs IN s_bukrs
AND cpudt IN s_cpudt
AND blart IN s_blart
AND blart = 'RE'. " Example MM Invoice Type
" --- Process each invoice document ---
LOOP AT lt_bkpf ASSIGNING FIELD-SYMBOL(<fs_bkpf>).
PERFORM process_invoice USING <fs_bkpf>.
ENDLOOP.
LOOP AT lt_rbkp ASSIGNING FIELD-SYMBOL(<fs_rbkp>).
PERFORM process_mm_invoice USING <fs_rbkp>.
ENDLOOP.
" Write output to file
PERFORM write_output_file.
*&---------------------------------------------------------------------*
*& Form PROCESS_INVOICE (Handles FI Invoices)
*&---------------------------------------------------------------------*
FORM process_invoice USING iv_bkpf TYPE bkpf.
DATA: ls_bseg TYPE bseg,
ls_lfa1 TYPE lfa1,
ld_due_date TYPE d.
DATA: ls_event TYPE ty_event_log.
" Get Vendor and other details from first line item
SELECT SINGLE * FROM bseg INTO ls_bseg
WHERE bukrs = iv_bkpf-bukrs
AND belnr = iv_bkpf-belnr
AND gjahr = iv_bkpf-gjahr
AND koart = 'K'.
IF sy-subrc = 0.
SELECT SINGLE name1 FROM lfa1 INTO ls_lfa1-name1 WHERE lifnr = ls_bseg-lifnr.
CALL FUNCTION 'DETERMINE_DUE_DATE'
EXPORTING
i_zfbdt = ls_bseg-zfbdt
i_zbd1t = ls_bseg-zbd1t
i_zbd2t = ls_bseg-zbd2t
i_zbd3t = ls_bseg-zbd3t
i_zbd1p = ls_bseg-zbd1p
i_zbd2p = ls_bseg-zbd2p
i_zterm = ls_bseg-zterm
IMPORTING
e_faedt = ld_due_date.
ENDIF.
" Helper function to populate common fields
MACRO set_common_fields.
ls_event-invoice = iv_bkpf-belnr.
ls_event-sourcesystem = gv_system_id.
ls_event-lastdataupdate = gv_last_update.
ls_event-companycode = iv_bkpf-bukrs.
ls_event-vendorname = ls_lfa1-name1.
ls_event-invoiceduedate = ld_due_date.
SELECT SINGLE wrbtr FROM bseg INTO ls_event-invoiceamount WHERE belnr = iv_bkpf-belnr AND gjahr = iv_bkpf-gjahr AND koart = 'K'.
ENDMACRO.
" 1. Invoice Received
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Received'.
CONCATENATE iv_bkpf-cpudt iv_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
" 2. Invoice Parked (if document was created as parked)
IF iv_bkpf-bstat = 'V'.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Parked'.
CONCATENATE iv_bkpf-cpudt iv_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
" 10. Invoice Posted (For non-parked, same as received. For parked, this needs CDHDR/CDPOS logic not shown for brevity)
IF iv_bkpf-bstat <> 'V'.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Posted'.
CONCATENATE iv_bkpf-budat iv_bkpf-cputm INTO ls_event-eventtime. " Using posting date
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
" 5. & 7. Invoice Blocked / Discrepancy Resolved from Change Docs
DATA: lt_cdhdr TYPE TABLE OF cdhdr, lt_cdpos TYPE TABLE OF cdpos.
DATA(ld_objectkey) = |{ iv_bkpf-bukrs }{ iv_bkpf-belnr }{ iv_bkpf-gjahr }|.
SELECT * FROM cdhdr INTO TABLE lt_cdhdr WHERE objectclas = 'BELEG' AND objectid = ld_objectkey.
IF sy-subrc = 0.
SELECT * FROM cdpos INTO TABLE lt_cdpos FOR ALL ENTRIES IN lt_cdhdr
WHERE changenr = lt_cdhdr-changenr AND tabname = 'BSEG' AND fname = 'ZLSPR'.
LOOP AT lt_cdpos ASSIGNING FIELD-SYMBOL(<fs_cdpos>).
READ TABLE lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>) WITH KEY changenr = <fs_cdpos>-changenr.
IF sy-subrc = 0.
CLEAR ls_event.
set_common_fields.
IF <fs_cdpos>-value_new IS NOT INITIAL AND <fs_cdpos>-value_old IS INITIAL.
ls_event-activityname = 'Invoice Blocked For Payment'.
ELSEIF <fs_cdpos>-value_new IS INITIAL AND <fs_cdpos>-value_old IS NOT INITIAL.
ls_event-activityname = 'Discrepancy Resolved'.
ELSE.
CONTINUE.
ENDIF.
CONCATENATE <fs_cdhdr>-udate <fs_cdhdr>-utime INTO ls_event-eventtime.
ls_event-username = <fs_cdhdr>-username.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDIF.
" 6. 8. 9. Workflow Events (Routed, Approved, Rejected) - Simplified Example
" This requires knowledge of specific workflow templates. Placeholder logic:
" SELECT ... FROM SWW_WI2OBJ ... WHERE INSTID = [Invoice Object]
" SELECT ... FROM SWWWIHEAD ... to get status and times
" 11. & 12. & 14. Payment Proposal, Executed, Cleared
IF ls_bseg-augbl IS NOT INITIAL.
DATA: ls_regup TYPE regup.
SELECT SINGLE * FROM regup INTO ls_regup WHERE vblnr = ls_bseg-belnr.
IF sy-subrc = 0.
DATA(ld_rundate) = ls_regup-laufd.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Proposal Created'.
CONCATENATE ld_rundate '000000' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Executed'.
CONCATENATE ls_bseg-augdt '120000' INTO ls_event-eventtime. " Using clearing date as proxy
APPEND ls_event TO gt_event_log.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Cleared'.
CONCATENATE ls_bseg-augdt '120001' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
" 13. Invoice Due Date Passed (Calculated)
IF ls_bseg-augdt IS NOT INITIAL AND ld_due_date IS NOT INITIAL.
IF ls_bseg-augdt > ld_due_date.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Due Date Passed'.
CONCATENATE ld_due_date '235959' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDIF.
" 15. Invoice Cancelled
IF iv_bkpf-stblg IS NOT INITIAL.
DATA: ls_rev_bkpf TYPE bkpf.
SELECT SINGLE * FROM bkpf INTO ls_rev_bkpf WHERE belnr = iv_bkpf-stblg.
IF sy-subrc = 0.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Cancelled'.
CONCATENATE ls_rev_bkpf-cpudt ls_rev_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = ls_rev_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form PROCESS_MM_INVOICE (Handles MM/Logistics Invoices)
*&---------------------------------------------------------------------*
FORM process_mm_invoice USING iv_rbkp TYPE rbkp.
" This form would be similar to PROCESS_INVOICE, but starts with RBKP.
" It needs to find the corresponding FI document in BKPF via AWKEY.
" The logic for PO/GR Matched would be included here.
" For demonstration, creating placeholder events for MM-specific activities.
DATA: ls_event TYPE ty_event_log.
ls_event-invoice = iv_rbkp-belnr.
ls_event-sourcesystem = gv_system_id.
ls_event-lastdataupdate = gv_last_update.
ls_event-companycode = iv_rbkp-bukrs.
" 1. Invoice Received (MM)
ls_event-activityname = 'Invoice Received'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" 3. Purchase Order Matched (Implicit)
ls_event-activityname = 'Purchase Order Matched'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" 4. Goods Receipt Matched (Implicit)
ls_event-activityname = 'Goods Receipt Matched'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" NOTE: The rest of the events (Block, Pay, etc.) would be found by linking
" RBKP to BKPF and then reusing the logic from PROCESS_INVOICE.
" Link: BKPF-AWKEY = CONCATENATE( RBKP-BELNR, RBKP-GJAHR ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form WRITE_OUTPUT_FILE
*&---------------------------------------------------------------------*
FORM write_output_file.
DATA: lv_string TYPE string.
OPEN DATASET p_fpath FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc <> 0.
MESSAGE 'Error opening file.' TYPE 'E'.
RETURN.
ENDIF.
" Write Header
lv_string = 'Invoice,ActivityName,EventTime,SourceSystem,LastDataUpdate,UserName,CompanyCode,VendorName,InvoiceAmount,PurchaseOrderNumber,InvoiceDueDate'.
TRANSFER lv_string TO p_fpath.
" Write Data
LOOP AT gt_event_log ASSIGNING FIELD-SYMBOL(<fs_event>).
" Create a comma-separated string, handling potential commas in data
CONCATENATE <fs_event>-invoice
<fs_event>-activityname
<fs_event>-eventtime
<fs_event>-sourcesystem
<fs_event>-lastdataupdate
<fs_event>-username
<fs_event>-companycode
<fs_event>-vendorname
<fs_event>-invoiceamount
<fs_event>-purchaseordernumber
<fs_event>-invoiceduedate
INTO lv_string SEPARATED BY ','.
TRANSFER lv_string TO p_fpath.
ENDLOOP.
CLOSE DATASET p_fpath.
WRITE: / 'Extraction complete. File written to:', p_fpath.
ENDFORM. Gotowi do rozpoczęcia?
Skorzystajcie z tego szablonu, aby rozpocząć inicjatywę process mining i zwiększyć efektywność operacji związanych z zobowiązaniami. Już dziś usprawnijcie proces i ograniczcie zbędne kroki.
Ograniczcie opłaty za opóźnienia. Usprawnijcie obsługę faktur już dziś
Obniżcie koszty obsługi o 60% i łatwiej eliminujcie podwójne płatności.
Karta kredytowa nie jest wymagana. Rozpoczęcie zajmuje kilka minut.