Magazynier, który potwierdza przyjęcie palety na terminalu, nie zna kodów transakcji SAP i nie musi ich znać. Za jego skanem stoi jednak konkretne wywołanie: odczyt stanu, kontrola zamówienia zakupu albo zaksięgowanie ruchu materiałowego. Aplikacja WMS wykonuje je jako funkcję SAP, a nie jako sekwencję ekranów.
Poniżej opisano, czym różni się transakcja od wywołania RFC i od funkcji BAPI oraz jak odczytać parametry funkcji przed jej użyciem. Dalej znajduje się katalog funkcji według obszaru procesu, zasady zatwierdzania zmian i sposób ponawiania wywołań po błędzie. Sposób nawiązania połączenia i konfigurację kanału opisuje osobna strona o połączeniu aplikacji z systemem SAP.
Różnica między transakcją SAP a funkcją BAPI
Transakcja SAP, na przykład MMBE albo MB52, to zestaw ekranów dla człowieka pracującego w SAP GUI. RFC (Remote Function Call) jest protokołem, który pozwala programowi zewnętrznemu uruchomić moduł funkcyjny ABAP oznaczony jako dostępny zdalnie. BAPI jest wąskim, udokumentowanym podzbiorem takich modułów: każdy reprezentuje metodę obiektu biznesowego, na przykład zamówienia zakupu albo dokumentu materiałowego.
| Sposób dostępu | Warstwa | Kontrole biznesowe | Typowe użycie w integracji z WMS |
|---|---|---|---|
| Transakcja SAP GUI | ekrany dialogowe | wykonywane w dialogu z użytkownikiem | praca ręczna administratora lub księgowego |
| Moduł funkcyjny RFC | funkcja ABAP wywołana zdalnie | zależą od autora funkcji i nie mają gwarancji | odczyty raportowe, na przykład RFC_READ_TABLE |
| BAPI | metoda obiektu biznesowego | te same co w transakcji, wykonywane w tle | księgowanie ruchów i tworzenie dokumentów |
RFC_READ_TABLE odczytuje dowolną tabelę, ale zwraca wiersz w polu o ograniczonej szerokości i omija logikę biznesową. Nadaje się do jednorazowego raportu. Do operacji, które zmieniają dane, wybiera się BAPI, ponieważ wywołanie przechodzi przez te same walidacje co ręczne księgowanie.
Reguła: dane w SAP zapisuje się wyłącznie przez BAPI albo przez inny udokumentowany interfejs biznesowy. Bezpośredni zapis do tabel omija kontrole i może zostawić niespójny dokument.
Jak odczytać parametry funkcji przed wywołaniem
Definicję funkcji ogląda się w transakcji SE37 (Function Builder), a listę BAPI pogrupowaną według obiektów biznesowych w BAPI Explorer, który uruchamia się transakcją BAPI. Zakładki definicji pokazują cztery rodzaje parametrów, a każdy ma inne znaczenie dla programisty aplikacji WMS.
- Import - wartości wysyłane do funkcji, na przykład numer materiału i ilość; część pól jest obowiązkowa.
- Export - wartości zwracane przez funkcję, na przykład numer dokumentu materiałowego i rok dokumentu.
- Changing - parametry przekazywane w obie strony; funkcja może zmienić ich wartość.
- Tables - tabele wewnętrzne wysyłane i odbierane razem, w tym pozycje dokumentu oraz obowiązkowa tabela RETURN.
Wywołanie z zewnątrz najlepiej najpierw wykonać ręcznie w SE37, klawiszem F8, na danych testowych. Programista widzi wtedy dokładnie te typy pól i formaty, których oczekuje SAP, na przykład numer materiału z zerami wiodącymi. Oficjalny opis obiektów i metod udostępnia portal dokumentacji SAP Help Portal, a dokładna nazwa i dostępność funkcji zależą od wersji systemu, więc każdą z nich sprawdza się w SE37 przed użyciem.
Odczyt stanów i danych podstawowych z poziomu WMS
Odczyt jest bezpieczniejszy od zapisu, bo nie zmienia danych i nie wymaga zatwierdzania. Integrację zwykle zaczyna się więc od odczytu kartotek materiałów i stanów. Aplikacja magazynowa pobiera dane w chwili, gdy operator ich potrzebuje, więc nie opiera się na kopii z ostatniej synchronizacji.
Stany magazynowe i dostępność towaru
Listę stanów magazynowych dla wskazanych miejsc składowania zwraca funkcja BAPI_WHSE_STOCK_GET_LIST. Zestawienie zapotrzebowań i zapasów dla materiału daje BAPI_MATERIAL_STOCK_REQ_LIST, a dostępność do sprzedaży sprawdza BAPI_MATERIAL_AVAILABILITY, która uwzględnia rezerwacje oraz otwarte zamówienia. Te trzy wyniki odpowiadają na różne pytania i nie należy ich porównywać jak jednej liczby.
Stan fizyczny mówi, ile sztuk leży w lokalizacji. Dostępność mówi, ile z nich można jeszcze obiecać klientowi. Operator kompletacji potrzebuje pierwszej wartości, a planista zamówień drugiej, więc aplikacja pokazuje każdą osobno i podpisuje ją jednostką miary z odpowiedzi SAP.

Kartoteki materiałów
Dane podstawowe materiału zapisuje i zmienia BAPI_MATERIAL_SAVEDATA, a szczegóły odczytuje BAPI_MATERIAL_GET_ALL. Funkcja zapisu przyjmuje osobne struktury dla każdego widoku materiału, na przykład danych ogólnych i danych zakładu, wraz z równoległymi strukturami znaczników zmiany (pola X). SAP zmienia tylko te pola, które mają znacznik, więc pominięty znacznik oznacza brak zapisu, a nie błąd.
Formaty pól i jednostki miary
Funkcje SAP oczekują wartości w formacie wewnętrznym, który różni się od tego, co skanuje magazynier. Numer materiału bywa uzupełniany zerami wiodącymi do stałej długości, data ma postać RRRRMMDD, a jednostka miary występuje w kodzie wewnętrznym (ST dla sztuki) i osobno w kodzie ISO (PCE). Warstwa integracyjna zamienia te formaty w obie strony, zwykle przez moduły konwersji SAP (CONVERSION_EXIT_*), żeby aplikacja WMS nie musiała ich znać.
Pominięta konwersja daje objaw mylący dla programisty: funkcja odczytu nie zgłasza błędu, tylko zwraca pustą listę, bo materiał o numerze bez zer wiodących w SAP nie istnieje. Przy pierwszym teście warto więc porównać dokładny łańcuch znaków wysłany do SAP z tym, który widać w SE37.
Księgowanie ruchów magazynowych funkcją BAPI_GOODSMVT_CREATE
Każdy ruch towaru, który ma zmienić stan w SAP, przechodzi przez BAPI_GOODSMVT_CREATE. Funkcja przyjmuje nagłówek z datami oraz kod ruchu (GM_CODE), a do tego pozycje z materiałem i ilością oraz rodzajem ruchu. Zwraca numer i rok utworzonego dokumentu materiałowego.
| Operacja w WMS | GM_CODE | Rodzaj ruchu | Wymagane pola pozycji |
|---|---|---|---|
| przyjęcie do zamówienia zakupu | 01 | 101 | PO_NUMBER, PO_ITEM, MVT_IND |
| wydanie na zlecenie produkcyjne | 03 | 261 | ORDERID |
| wydanie na centrum kosztów | 03 | 201 | COSTCENTER |
| przesunięcie między lokalizacjami | 04 | 311 | STGE_LOC, MOVE_STLOC |
Wartości w tabeli pokazują typowe ustawienia, a konkretne rodzaje ruchu zależą od konfiguracji SAP w danej firmie. Osobno uzgadnia się z konsultantem, które z nich są dopuszczone dla konta integracyjnego. Powstały dokument materiałowy odpowiada dokumentom magazynowym widocznym w WMS, na przykład PZ albo WZ, więc jego numer trafia z powrotem do rekordu operacji.
Zatwierdzanie i wycofanie zmian po tabeli RETURN
Funkcja księgująca nie zatwierdza transakcji bazy danych sama. Po wywołaniu aplikacja sprawdza tabelę RETURN, w której każdy komunikat ma typ: S (sukces), I (informacja), W (ostrzeżenie), E (błąd) albo A (przerwanie). Przy typie E lub A wywołuje się BAPI_TRANSACTION_ROLLBACK, a przy pozostałych BAPI_TRANSACTION_COMMIT z parametrem WAIT ustawionym na X, żeby wywołanie wróciło dopiero po zapisie do bazy.
Reguła: commit i wywołanie księgujące muszą przebiegać w tej samej sesji RFC. Commit wysłany osobnym połączeniem nie zatwierdzi niczego, a dokument nie powstanie mimo pozornie poprawnej odpowiedzi.
// Przykład poglądowy: interfejs IRfcSession jest umowny, nie pochodzi z biblioteki SAP.
public interface IRfcSession
{
IDictionary<string, object> Call(string function, IDictionary<string, object> input);
}
public static string PostGoodsReceipt(IRfcSession session, string operationId,
string material, string plant, string storageLoc, decimal qty, string po, string poItem)
{
var input = new Dictionary<string, object>
{
["GOODSMVT_HEADER"] = new Dictionary<string, object>
{
["PSTNG_DATE"] = DateTime.Today,
["DOC_DATE"] = DateTime.Today,
["REF_DOC_NO"] = operationId // numer operacji WMS w nagłówku
},
["GOODSMVT_CODE"] = new Dictionary<string, object> { ["GM_CODE"] = "01" },
["GOODSMVT_ITEM"] = new[]
{
new Dictionary<string, object>
{
["MATERIAL"] = material, ["PLANT"] = plant, ["STGE_LOC"] = storageLoc,
["MOVE_TYPE"] = "101", ["ENTRY_QNT"] = qty, ["PO_NUMBER"] = po,
["PO_ITEM"] = poItem, ["MVT_IND"] = "B"
}
}
};
var result = session.Call("BAPI_GOODSMVT_CREATE", input);
var errors = ((IEnumerable<IDictionary<string, object>>)result["RETURN"])
.Where(r => (string)r["TYPE"] == "E" || (string)r["TYPE"] == "A");
if (errors.Any())
{
session.Call("BAPI_TRANSACTION_ROLLBACK", new Dictionary<string, object>());
throw new InvalidOperationException((string)errors.First()["MESSAGE"]);
}
session.Call("BAPI_TRANSACTION_COMMIT", new Dictionary<string, object> { ["WAIT"] = "X" });
return (string)result["MATERIALDOCUMENT"];
}
Jedno wywołanie na dokument, nie na pozycję
Każde wywołanie RFC niesie narzut sieciowy i tworzy osobną sesję kontroli w SAP. Dokument z kilkudziesięcioma pozycjami wysyła się więc jednym wywołaniem, z całą tabelą GOODSMVT_ITEM, a nie w pętli po pozycjach. Zmniejsza to liczbę zapytań i daje jeden numer dokumentu materiałowego, który łatwo przypisać do zlecenia w WMS. Wadą jest to, że błąd w jednej pozycji odrzuca cały dokument, więc aplikacja pokazuje operatorowi numer pozycji z komunikatu RETURN.
Symulacja przed księgowaniem
BAPI_GOODSMVT_CREATE ma parametr TESTRUN. Ustawiony na X uruchamia wszystkie kontrole i zwraca komunikaty, ale nie tworzy dokumentu. Warstwa integracyjna może więc wywołać symulację, gdy operator jeszcze skanuje pozycje, i pokazać błąd, na przykład brak zamówienia albo zablokowany materiał, zanim operator zeskanuje kolejne palety.
Funkcje BAPI według obszarów procesu
Poza ruchami materiałowymi integracja WMS z SAP obejmuje sprzedaż i zakupy, a także dostawy. Zestawienie poniżej grupuje funkcje według dokumentu, który tworzą lub odczytują.
| Obszar | Funkcje | Zastosowanie w WMS |
|---|---|---|
| zlecenia sprzedaży | BAPI_SALESORDER_CREATEFROMDAT2, BAPI_SALESORDER_CHANGE, BAPI_SALESORDER_SIMULATE | utworzenie i zmiana zlecenia oraz symulacja bez zapisu |
| zamówienia zakupu | BAPI_PO_CREATE1, BAPI_PO_CHANGE | utworzenie i zmiana zamówienia u dostawcy |
| dostawy przychodzące | BAPI_INB_DELIVERY_SAVEREPLICA | zapis dostawy związanej z awizacją |
| dostawy wychodzące | BAPI_OUTB_DELIVERY_CREATE_SLS, BAPI_OUTB_DELIVERY_CREATE_STO, BAPI_OUTB_DELIVERY_CHANGE | dostawa do zlecenia sprzedaży lub zamówienia przesunięcia |
| dokumenty transportowe | BAPI_SHIPMENT_CREATE, BAPI_SHIPMENT_CHANGE | grupowanie dostaw w transport |
| zlecenia przeniesienia WM | BAPI_WHSE_TO_GET_LIST, BAPI_WHSE_TO_GET_DETAIL | lista zleceń i szczegóły pojedynczego zlecenia |
Dostawa przychodząca opisuje towar, który ma dotrzeć od dostawcy, więc jej dane wykorzystuje się przy przyjęciu do magazynu, zanim ruch zostanie zaksięgowany. Dostawy wychodzące tworzą punkt wyjścia dla ewidencji wydań: kompletacja realizuje pozycje dostawy, a księgowanie wydania następuje po jej potwierdzeniu.
Inwentaryzacja jako sekwencja wywołań BAPI
Spis z natury w SAP przechodzi trzy etapy i każdy ma własną funkcję. Najpierw powstają dokumenty inwentaryzacyjne, potem wpisuje się do nich wyniki liczenia, a na końcu księguje się różnice. Aplikacja na terminalu pokrywa środkowy etap, bo to na hali pada liczba, którą trzeba przenieść do SAP.
| Etap | Funkcja | Skutek w SAP | Zatwierdzenie |
|---|---|---|---|
| utworzenie dokumentów | BAPI_MATPHYSINV_CREATE_MULT | dokumenty inwentaryzacyjne z blokadą pozycji | BAPI_TRANSACTION_COMMIT |
| wpisanie wyników liczenia | BAPI_MATPHYSINV_COUNT | ilości policzone przypisane do pozycji | BAPI_TRANSACTION_COMMIT |
| zaksięgowanie różnic | BAPI_MATPHYSINV_POSTDIFF | korekta stanu i dokument materiałowy | BAPI_TRANSACTION_COMMIT |
Szerszy opis samego liczenia oraz spisów cyklicznych zawiera tekst o inwentaryzacji zapasów w programie magazynowym. Tutaj istotne jest to, że każdy etap zatwierdza się osobno, więc błąd na trzecim nie cofa wyników wpisanych na drugim.

Transakcje SAP GUI a funkcje BAPI
Zestawienie łączy ręczną transakcję z funkcją o zbliżonym zakresie. Służy administratorowi, który porównuje wynik wywołania z tym, co widzi na ekranie SAP GUI podczas testów integracji.
| Transakcja SAP | Funkcja o zbliżonym zakresie | Moduł | Zastosowanie |
|---|---|---|---|
| MMBE, MB52 | BAPI_WHSE_STOCK_GET_LIST | MM | przegląd stanów materiału |
| MIGO | BAPI_GOODSMVT_CREATE | MM | ruchy towarowe w magazynie |
| VA01, VA02 | BAPI_SALESORDER_CREATEFROMDAT2, BAPI_SALESORDER_CHANGE | SD | zlecenia sprzedaży |
| ME21N, ME22N | BAPI_PO_CREATE1, BAPI_PO_CHANGE | MM | zamówienia zakupu |
| MI01, MI04, MI07 | BAPI_MATPHYSINV_CREATE_MULT, BAPI_MATPHYSINV_COUNT, BAPI_MATPHYSINV_POSTDIFF | MM | inwentaryzacja i różnice |
Funkcja i transakcja nie muszą zwracać identycznych pól. Mapowanie zatwierdza konsultant SAP, a diagnozę uprawnień ułatwia transakcja SU53, która pokazuje ostatni odrzucony obiekt autoryzacji.
Ślad wywołań i ponawianie w warstwie WMS
Sieć zawodzi częściej niż SAP. Jeśli odpowiedź na BAPI_GOODSMVT_CREATE nie wróci w limicie czasu, aplikacja nie wie, czy dokument powstał, więc ślepe ponowienie grozi podwójnym przyjęciem. Rozwiązaniem jest numer operacji WMS wpisany w polu REF_DOC_NO nagłówka: przed powtórzeniem wywołania warstwa integracyjna szuka w SAP dokumentu materiałowego z tym numerem odniesienia i wysyła ruch ponownie tylko wtedy, gdy go nie znajdzie.
Reguła: ponowienie wywołania księgującego jest dopuszczalne dopiero po sprawdzeniu, że dokument z danym numerem odniesienia nie istnieje w SAP.
Po stronie WMS każde wywołanie zostawia wiersz w dzienniku z nazwą funkcji i statusem wraz z komunikatem z tabeli RETURN. Tabela poniżej w T-SQL jest schematem przykładowym, a nie strukturą konkretnego produktu.
CREATE TABLE dbo.SapCallLog
(
CallId bigint IDENTITY(1,1) PRIMARY KEY,
OperationId varchar(40) NOT NULL, -- ten sam numer trafia do REF_DOC_NO
FunctionName varchar(60) NOT NULL,
Status varchar(10) NOT NULL, -- OK, ERROR, TIMEOUT
ReturnType char(1) NULL, -- S, I, W, E, A
ReturnMessage nvarchar(220) NULL,
MaterialDoc varchar(10) NULL,
CreatedAt datetime2 NOT NULL DEFAULT SYSUTCDATETIME()
);
CREATE INDEX IX_SapCallLog_Retry
ON dbo.SapCallLog (Status, CreatedAt)
INCLUDE (OperationId, FunctionName);
Indeks na kolumnach Status i CreatedAt obsługuje zadanie, które co kilka minut wybiera wywołania oczekujące na ponowienie. Rozwiązanie SoftwareStudio wywołuje funkcje SAP bezpośrednio z aplikacji magazynowej, o czym opisuje strona o wywoływaniu funkcji SAP z poziomu WMS. Ogólne tryby wymiany danych (synchroniczny oraz wsadowy) porównuje tekst o integracji WMS z SAP, a produktowe ujęcie tematu zawiera opis wdrożenia WMS z integracją SAP dla magazynu chemicznego.

Szersze warianty architektury, w tym pośredników takich jak SAP PI/PO i Integration Suite, wyjaśnia strona integracja z SAP. Model, w którym kilka systemów wymienia dokumenty przez kolejkę i interfejs REST, opisuje tekst o integracji WMS z ERP.




