Magazyn generuje dziesiątki tysięcy zdarzeń na dobę, głównie skanów i przesunięć. Pojedyncze zdarzenie nic nie mówi kierownikowi, dopóki nie trafi do zestawienia, które da się porównać z poprzednim tygodniem albo z planem. Ta strona opisuje wyłącznie warstwę raportową. Definicję samego systemu i jego architekturę zawiera artykuł system WMS - zakres funkcji i budowa.

Systemy typu WMS przechowują dane w bazie relacyjnej, więc raport jest zapytaniem, a wskaźnik wynikiem agregacji. O jakości raportu decydują dwie rzeczy: jednoznaczna definicja wskaźnika oraz sposób odczytu danych, który nie spowalnia terminali. Kolejne sekcje omawiają je na przykładach T-SQL i wskazują, gdzie kończy się rola widoku, a zaczyna raport.

Skąd systemy typu WMS biorą dane do raportów

Każda operacja zapisuje się w chwili wykonania w tabeli ruchów. Wiersz zawiera lokację i towar wraz z ilością, a także identyfikator operatora i czas nadany przez serwer bazy. Z takiego dziennika można odtworzyć stan na dowolny dzień oraz przebieg każdego zlecenia.

Dziennik ruchów jako jedyne źródło danych

Raporty nie powinny mieć własnych kopii stanów, bo wtedy dwa zestawienia pokażą dwie różne liczby. Wszystkie wskaźniki wynikają z tych samych tabel: dziennika ruchów i stanów lokacji oraz skanów kompletacji. Jeżeli wskaźnik zmienia definicję, zmienia się w jednym widoku, a nie w kilkunastu raportach naraz.

Jakość raportów zależy od jakości zapisu. Skan bez identyfikatora operatora nie pozwala policzyć obciążenia, a czas z zegara terminala może być przesunięty o minuty. Przy wdrożeniu sprawdza się więc, czy każdy typ operacji zapisuje komplet pól, a czas nadaje serwer bazy, a nie urządzenie. Poprawka tej reguły po roku pracy oznacza dane historyczne, których nie da się już uzupełnić.

Widoki T-SQL zamiast zapytań w raporcie

Widok jest zapisanym zapytaniem, które baza traktuje jak tabelę. Raport odwołuje się do widoku i dostaje gotową definicję wskaźnika. Zmiana reguły, na przykład wyłączenie lokacji zablokowanych z liczenia zajętości, wymaga edycji jednego obiektu w bazie. Opis mechanizmu zawiera dokumentacja Microsoft o widokach w SQL Server.

Ilustracja zestawień i analiz opartych na danych magazynowych zapisanych w bazie systemu WMS
Dane z dziennika ruchów trafiają do widoków, a z widoków do raportów użytkowników

Wskaźniki magazynowe i ich definicje

Wskaźnik ma sens, gdy jego definicja jest jednoznaczna. „Czas kompletacji” liczony od przydzielenia zlecenia daje inną liczbę niż liczony od pierwszego skanu, a różnica bywa równa czasowi oczekiwania w kolejce. Poniższa tabela zestawia definicje możliwe do policzenia z danych zapisywanych przez system w każdej operacji.

WskaźnikDefinicja liczona z danychGłówne źródło w bazie
Rotacja zapasuWydania w okresie podzielone przez średni stanDziennik ruchów, stany lokacji
Wykorzystanie lokacjiLokacje z dodatnim stanem podzielone przez lokacje aktywneSłownik lokacji, stany lokacji
Dokładność inwentaryzacjiPozycje bez różnicy podzielone przez pozycje policzoneWyniki spisu, stany systemowe
Czas kompletacjiRóżnica między pierwszym a ostatnim skanem zleceniaSkany kompletacji

Reguła: wskaźnik bez zapisanej definicji i okresu liczenia nie nadaje się do porównań między zmianami.

Terminowość wydań i pełność zamówień

Wskaźnik OTIF (On Time In Full) wyraża odsetek zamówień wydanych w terminie i w pełnej ilości. Zamówienie spóźnione o godzinę albo niepełne o jedną sztukę nie wchodzi do licznika. Wskaźnik odzwierciedla to, co klient widzi bezpośrednio, więc jego spadek zwykle poprzedza pierwsze reklamacje. Do policzenia potrzeba dwóch dat: terminu z zamówienia i czasu zamknięcia wydania, oraz porównania ilości zamówionej z wydaną w każdej pozycji.

Rotacja zapasu i wykorzystanie lokacji

Rotacja pokazuje, ile razy w okresie zapas został wydany i uzupełniony. Niska rotacja zamraża kapitał w towarze, który leży, a wysoka wskazuje pozycje wymagające częstszego uzupełniania strefy zbiórki. Wykorzystanie lokacji odpowiada na inne pytanie: ile miejsca składowania jest zajęte. Poniższy widok liczy je dla każdej strefy (nazwy tabel i kolumn są poglądowe, to nie schemat konkretnego produktu):

CREATE VIEW dbo.vWykorzystanieLokacji
AS
SELECT  l.StrefaId,
        COUNT(*) AS LiczbaLokacji,
        SUM(CASE WHEN st.Ilosc > 0 THEN 1 ELSE 0 END) AS LokacjeZajete,
        CAST(100.0 * SUM(CASE WHEN st.Ilosc > 0 THEN 1 ELSE 0 END)
             / COUNT(*) AS decimal(5,1)) AS ProcentZajetosci
FROM    dbo.Lokacja AS l
LEFT JOIN (SELECT LokacjaId, SUM(Ilosc) AS Ilosc
           FROM dbo.StanLokacji
           GROUP BY LokacjaId) AS st
       ON st.LokacjaId = l.LokacjaId
WHERE   l.Aktywna = 1
GROUP BY l.StrefaId;

Wynik wygodnie zestawić z rozmieszczeniem regałów na planie hali, co pokazuje artykuł o wizualizacji zajętości magazynu. Wartość bliska stu procent w strefie zbiórki sygnalizuje problem z uzupełnianiem, a bliska zeru w strefie rezerwy wskazuje niewykorzystany regał.

Czas kompletacji i funkcje okna

Czas kompletacji liczy się z dziennika skanów. Zapytanie z funkcją okna zwraca czas każdego zlecenia i średnią operatora obok siebie, bez osobnego zapytania podsumowującego:

WITH Zlecenia AS (
    SELECT  ZlecenieId,
            OperatorId,
            MIN(DataSkanu) AS Poczatek,
            MAX(DataSkanu) AS Koniec
    FROM    dbo.SkanKompletacji
    GROUP BY ZlecenieId, OperatorId
)
SELECT  ZlecenieId,
        OperatorId,
        DATEDIFF(SECOND, Poczatek, Koniec) AS CzasSekundy,
        AVG(DATEDIFF(SECOND, Poczatek, Koniec))
            OVER (PARTITION BY OperatorId) AS SredniCzasOperatora
FROM    Zlecenia;

Klauzula OVER (PARTITION BY ...) liczy średnią w obrębie operatora i nie zwija wierszy, więc kierownik widzi zlecenia odstające od normy. Składnię i ograniczenia opisuje dokumentacja klauzuli OVER. Czas mierzony od pierwszego do ostatniego skanu obejmuje przerwy w pracy, więc przed porównaniem operatorów warto wyłączyć zlecenia przerwane.

Raportowanie w systemie WMS z użyciem SSRS i RDL

Widok liczy wskaźnik, a raport nadaje mu formę dla odbiorcy. W Studio WMS.net raporty i wydruki działają na SQL Server Reporting Services, a ich definicje są zapisane w formacie RDL (Report Definition Language), czyli w pliku XML opisującym źródło danych oraz układ raportu. Projekt raportu można edytować w Report Builderze i publikować na serwerze raportów bez zmiany programu magazynowego.

Parametry raportu i zapytanie odporne na zakres dat

Raport z parametrem daty powinien porównywać kolumnę z zakresem, a nie przekształcać kolumnę funkcją. Zapis z funkcją na kolumnie uniemożliwia użycie indeksu, więc raport czyta całą tabelę ruchów:

SELECT  LokacjaId, TowarId, SUM(Ilosc) AS Suma
FROM    dbo.RuchMagazynowy
WHERE   DataRuchu >= @Od
  AND   DataRuchu <  DATEADD(DAY, 1, @Do)
GROUP BY LokacjaId, TowarId;

Górna granica jest wyłączna, a dzień końcowy obejmuje całą dobę, także wiersze z godzinami po północy. Indeks założony na kolumnie DataRuchu obsługuje takie zapytanie zakresem, a nie skanem tabeli. Szersze omówienie definicji raportów i wydruków zawiera artykuł SQL Report Builder - raporty RDL i wydruki, a opis samej usługi strona o Microsoft SQL Reporting Services. Oficjalne informacje o typach raportów podaje dokumentacja Reporting Services.

Izolacja odczytów i wpływ raportu na terminale

Długi raport czyta miliony wierszy, a terminale w tym samym czasie zapisują nowe ruchy. Przy domyślnym poziomie izolacji READ COMMITTED odczyt i zapis mogą czekać na siebie na tych samych wierszach. Opcja bazy READ_COMMITTED_SNAPSHOT przełącza odczyty na wersje wierszy przechowywane w tempdb, więc raport nie zakłada blokad współdzielonych:

ALTER DATABASE MagazynPrzyklad
SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;

Zmiana wymaga chwilowego rozłączenia pozostałych sesji, więc wykonuje się ją w oknie serwisowym. Wersjonowanie zwiększa użycie tempdb, co trzeba uwzględnić przy doborze dysków. Ten sam mechanizm opisuje przewodnik Microsoft o blokowaniu i wersjonowaniu wierszy. Zaplecze bazodanowe, w tym replikę do raportów, omawia tekst system magazynowy na SQL Server.

Raporty dla kierownika zmiany i dla zarządu

Ten sam widok obsługuje dwóch odbiorców, ale forma raportu jest inna. Kierownik zmiany potrzebuje danych z ostatnich godzin i podziału na operatorów. Zarząd potrzebuje trendu w tygodniach i porównania z poprzednim okresem.

OdbiorcaZakres czasuTypowy wskaźnikForma
Kierownik zmianyBieżąca zmianaZlecenia do skompletowania, obciążenie operatorówLista odświeżana w przeglądarce
Kierownik magazynuTydzieńCzas kompletacji, wykorzystanie lokacjiRaport SSRS z parametrem strefy
Dział zakupówMiesiącRotacja zapasu, zapasy zalegająceZestawienie eksportowane do arkusza
ZarządKwartałTrend kosztów i terminowość wydańKrótki raport z porównaniem okresów

Częstotliwość raportu wynika z tempa, w jakim odbiorca może zareagować. Dane zmianowe czytane raz w tygodniu nie zmienią obsady, a trend kwartalny przeglądany co godzinę tylko zaśmieca ekran. Zakres danych ograniczają role użytkowników. Kierownik zmiany nie musi widzieć wartości zapasu, a dział zakupów nie potrzebuje podziału na operatorów, co opisuje artykuł role i użytkownicy w systemie WMS. Aktualne ilości dla obu grup pochodzą z tego samego zestawienia, które omawia strona o stanach magazynowych.

Ilustracja zarządzania zapasami na podstawie zestawień i wskaźników z systemu magazynowego
Wskaźniki rotacji wspierają decyzje zakupowe, a wskaźniki czasu decyzje o obsadzie zmian

Raporty wyjątków zamiast zestawień okresowych

Zestawienie okresowe odpowiada na pytanie, co się stało. Raport wyjątków odpowiada na pytanie, co wymaga reakcji teraz, i zwykle jest krótszy o rząd wielkości. Przykład to lista pozycji leżących na lokacji dłużej niż przyjęty próg, czyli zapasów zalegających:

SELECT  st.TowarId, st.LokacjaId, st.Ilosc,
        MAX(r.DataRuchu) AS OstatnieWydanie
FROM    dbo.StanLokacji AS st
LEFT JOIN dbo.RuchMagazynowy AS r
       ON r.TowarId = st.TowarId
      AND r.LokacjaId = st.LokacjaId
      AND r.Ilosc < 0
WHERE   st.Ilosc > 0
GROUP BY st.TowarId, st.LokacjaId, st.Ilosc
HAVING  MAX(r.DataRuchu) IS NULL
     OR MAX(r.DataRuchu) < DATEADD(DAY, -90, SYSDATETIME());

Próg dziewięćdziesięciu dni jest przykładowy i zależy od asortymentu, bo towar sezonowy leży dłużej niż szybko rotujący. Wydanie oznaczają w dzienniku ruchy z ujemną ilością, dlatego warunek r.Ilosc < 0 wybiera tylko je. Do raportów wyjątków należą też lokacje z ujemnym stanem, które nie powinny istnieć przy poprawnie zaprojektowanej transakcji, oraz zlecenia otwarte od kilku godzin. Każdy z takich raportów ma być pusty, a niepusty wynik jest sygnałem do interwencji.

Widoki mogą zasilać także narzędzia analityczne, na przykład Power BI, bez zmiany w programie magazynowym. Dla wskaźników pokazywanych na ekranie hali sprawdza się jednak zwykła lista w przeglądarce, ponieważ nie wymaga osobnego serwera ani licencji.

Dokładność inwentaryzacji i raport rozbieżności

Dokładność inwentaryzacji wyraża odsetek pozycji, w których liczba policzona zgadza się z zapisaną w systemie. Wskaźnik ocenia jakość procesów, a nie pracę zespołu liczącego. Spadek oznacza, że rozbieżności powstają między spisami: przez skany na niewłaściwej lokacji, wydania bez skanu albo błędy przy przesunięciach.

Raport rozbieżności zestawia stan systemowy ze spisanym i sortuje różnice według wartości oraz lokacji. Dopiero rozkład rozbieżności po lokacjach i operatorach wskazuje przyczynę. Skupienie w jednej strefie sugeruje błąd adresacji, a rozproszenie po całym magazynie wskazuje na brak kontroli skanem przy wydaniu. Organizację samego spisu opisuje artykuł inwentaryzacja w magazynie.

Odświeżanie danych i obciążenie bazy

Widok liczy wskaźnik na bieżąco, więc przy dużym zakresie dat obciąża bazę produkcyjną. Trzy sposoby udostępniania danych różnią się opóźnieniem i kosztem. Wybór zależy od tego, jak świeże liczby są potrzebne odbiorcy.

SposóbOpóźnienie danychWpływ na terminale
Widok czytany na żywoBrakWysoki przy dużym zakresie dat
Tabela agregatów z zadania SQL AgentDo kolejnego uruchomienia zadaniaNiski, agregat jest małą tabelą
Replika odczytu na osobnym serwerzeZależne od replikacjiBrak, raport czyta drugi serwer

Dla raportów codziennych wystarcza tabela agregatów, którą zadanie SQL Agent uzupełnia w nocy o dane poprzedniej doby. Dla widoku zmiany, gdzie liczy się aktualność, czyta się widok na żywo z krótkim zakresem czasu. Odrębny serwer raportowy opłaca się dopiero wtedy, gdy analizy historyczne trwają na tyle długo, że konkurują z pracą terminali mimo wersjonowania wierszy.

Minimalny zestaw raportów na start

Wdrożenie nie musi zaczynać się od dwudziestu zestawień. Cztery raporty pokrywają większość codziennych decyzji i pozwalają sprawdzić, czy dane w bazie są kompletne, zanim powstaną raporty dla zarządu.

  • Zapasy zalegające - pozycje bez wydania od przyjętego progu, pokazywane na tle wykorzystania lokacji.
  • Czas kompletacji - zlecenia i średnie operatorów z pominięciem przerw i zleceń przerwanych.
  • Rozbieżności inwentaryzacyjne - różnice po każdym spisie z podziałem na strefy.
  • Zlecenia otwarte - lista zleceń przekraczających zakładany czas, odświeżana dla kierownika zmiany.

Po kilku tygodniach pracy okazuje się, które definicje wymagają poprawy, na przykład czy przerwy w kompletacji trzeba wyłączyć z czasu. Dopiero wtedy warto dopisywać raporty tygodniowe i kwartalne, korzystając z tych samych widoków.

Demonstrację raportów można obejrzeć w demo magazynu online, a opis modułów produktu zawiera strona Studio WMS.net. Kryteria wyboru systemu, w tym możliwości raportowe, porządkuje strona systemy WMS.