Decyzja o tym, na którą lokację trafi paleta, zapada raz, przy odkładaniu. Skutki trwają do końca życia zapasu w tym miejscu: każda kompletacja i każde uzupełnianie pokonują drogę wyznaczoną przez ten wybór, a inwentaryzacja liczy zapas w tym właśnie miejscu. Program do magazynowania towarów nie powinien więc zostawiać tej decyzji operatorowi. Powinien ją podejmować według reguł zapisanych w bazie.

Artykuł pokazuje trzy warstwy tych reguł. Pierwsza to adresacja lokacji. Druga to strategia odkładania z klasą ABC jako parametrem strefy. Trzecia to rotacja zapasu przy wydaniu w wariantach FIFO i FEFO. Każdą warstwę zilustrowano przykładem w T-SQL. Warunki specjalne, takie jak chłodnia i towary ADR, opisano w tekście o programie do magazynowania w chłodni i przy towarach ADR.

Program do magazynowania towarów a adresacja lokacji

Adres lokacji jest kluczem, po którym program odnajduje towar i prowadzi pracownika. Składa się z kilku segmentów opisanych w tabeli poniżej, na przykład A-03-12-2. Kolejność segmentów odpowiada kierunkowi poruszania się po magazynie, dzięki czemu sortowanie adresów odtwarza trasę.

SegmentPrzykładFunkcja w programie
AlejaAWyznacza korytarz i kierunek trasy pracownika
Regał03Numer regału w alei, parzyste po jednej stronie, nieparzyste po drugiej
Pole12Kolumna wzdłuż regału, podstawa sortowania trasy
Poziom2Wysokość, od której zależą nośność i wybór wózka

Adres drukuje się jako kod kreskowy na etykiecie lokacji. Skanowanie etykiety przy odkładaniu potwierdza, że pracownik stoi przy właściwym miejscu. Bez tego skanu program wie tylko, gdzie towar powinien być, a nie gdzie faktycznie jest.

Typ lokacji i pojemność

Adres opisuje położenie, a typ lokacji opisuje to, co można tam odłożyć. Lokacja paletowa przyjmuje nośnik o określonych wymiarach i nośności, lokacja półkowa przyjmuje pojemniki, a kanał przepływowy działa w kolejności wjazd-wyjazd. Program zapisuje przy lokacji maksymalną liczbę nośników oraz nośność i porównuje je z odkładaną jednostką.

Dobór typu lokacji zaczyna się od kartoteki towaru, która podaje wymiary i masę nośnika. Strukturę takich danych omawia tekst o kartotekach magazynowych. Kryteria wyboru miejsca składowania przedstawia artykuł o kryteriach wyboru lokalizacji.

Lokacje wirtualne i bufory

Nie każde miejsce w bazie odpowiada półce. Program prowadzi także lokacje wirtualne, na przykład bufor przyjęć lub kwarantannę. Osobne lokacje opisują strefę wysyłki i towar w drodze. Paleta zdjęta z rampy dostaje najpierw adres bufora, a dopiero skan lokacji docelowej przenosi ją na regał. Dzięki temu w każdej chwili wiadomo, gdzie paleta jest, także gdy stoi w przejściu i czeka na wózek.

Lokacje wirtualne mają własne reguły. Bufor przyjęć nie ma limitu wysokości, ale ma limit czasu przebywania. Strefa wysyłki przyjmuje tylko towar ze zlecenia wydania. Lokacja kwarantanny odrzuca alokację wydań, co opisano w tekście o warunkach specjalnych.

Strategie odkładania towaru na lokacje

Strategia odkładania określa, z jakiej puli lokacji program wybiera miejsce. Istnieją cztery podstawowe podejścia, które porównuje tabela. Ich szczegółowy opis zawiera tekst o miejscach składowania w magazynie.

StrategiaZasadaZaletaRyzyko
Lokacja stałaJeden indeks ma przypisaną jedną lokacjęProsty układ, łatwa naukaPuste miejsca po wyczerpaniu zapasu
Lokacja losowaDowolna wolna lokacja właściwego typuDobre wykorzystanie przestrzeniRozproszenie towaru, dłuższe trasy
Najbliższa wolnaWolna lokacja najbliżej strefy przyjęćKrótkie odkładanieWolno rotujący towar zajmuje dogodne miejsca
Strefy klasoweStrefa według klasy ABC, wewnątrz strefy losowoKompromis odległości i przestrzeniWymaga okresowego przeliczania klas
Dwaj pracownicy przy paletach z kartonami w hali z monitorem pokazującym schemat stref
Strefy klasowe: układ magazynu dzieli się na obszary według klasy ABC, a odkładanie wybiera lokację wewnątrz obszaru.

Kolejność reguł przy odkładaniu

W praktyce program łączy kilka strategii w kaskadę. Reguły sprawdza się od najbardziej szczegółowej do najogólniejszej i zatrzymuje na pierwszej, która zwróci lokację. Cztery kroki wystarczają w większości magazynów.

  1. Rezerwacja indeksu - lokacja stała przypisana do towaru, jeśli ma wolne miejsce.
  2. Dołożenie do partii - lokacja, na której leży ta sama partia, jeśli mieszanie nośników jest dozwolone.
  3. Strefa klasy - wolna lokacja właściwego typu w strefie klasy ABC towaru.
  4. Najbliższa wolna - wolna lokacja właściwego typu poza strefą klasy, gdy strefa jest pełna.

Osobnej reguły wymaga mieszanie zawartości w lokacji. Lokacja przyjmuje jeden indeks (w jednej lub w wielu partiach) albo mieszankę indeksów. Ograniczenie ustawia się przy typie lokacji. Mieszanie partii jednego indeksu ułatwia wykorzystanie miejsca, ale utrudnia FEFO, bo pracownik musi sprawdzić etykietę przy pobraniu.

Każdy krok powinien mieć własny kod powodu wyboru. Kod trafia do dziennika odkładania, co ułatwia analizę, dlaczego towar leży tam, gdzie leży. Sposób prezentowania lokacji operatorowi opisano w tekście o aplikacji magazynowej na Androida.

Klasyfikacja ABC jako parametr strefy

Klasa ABC nie opisuje towaru, tylko jego rolę w ruchu magazynowym. Liczy się ją z historii wydań, a wynik wyznacza, jak blisko strefy wydań powinna leżeć lokacja. Zwykle przyjmuje się podział, w którym klasa A odpowiada za około 80 procent pobrań, klasa B za kolejne 15 procent, a klasa C za resztę. Progi bywają ustawiane inaczej.

Do klasyfikacji lepiej użyć liczby pobrań niż wartości obrotu. Wartość mówi, ile towar kosztuje, a liczba pobrań mówi, ile razy pracownik musi do niego dojść. Ruch pracownika jest kosztem, który rozmieszczenie ma zmniejszać. Poniższe zapytanie liczy klasy z trzech miesięcy wydań, z użyciem funkcji okna OVER.

WITH obrot AS (
    SELECT KodTowaru, COUNT(*) AS Pobrania
    FROM dbo.RuchWydania
    WHERE DataRuchu >= DATEADD(MONTH, -3, CAST(SYSDATETIME() AS date))
    GROUP BY KodTowaru
), udzial AS (
    SELECT KodTowaru, Pobrania,
           SUM(Pobrania) OVER (ORDER BY Pobrania DESC, KodTowaru
                               ROWS UNBOUNDED PRECEDING) * 1.0
           / SUM(Pobrania) OVER () AS Narastajaco
    FROM obrot
)
SELECT KodTowaru, Pobrania,
       CASE WHEN Narastajaco <= 0.80 THEN 'A'
            WHEN Narastajaco <= 0.95 THEN 'B'
            ELSE 'C' END AS Klasa
FROM udzial;

Towar, którego narastający udział przekracza próg, trafia do niższej klasy. Drugi klucz sortowania, kod towaru, jest niezbędny. Bez niego remisy w liczbie pobrań dawałyby niestabilny wynik przy kolejnych uruchomieniach.

Reguła: klasę przelicza zadanie okresowe, a przesunięcia wynikają ze zmiany klasy, nie z każdego wahania liczby pobrań.

Nowy towar nie ma historii wydań, więc jego klasa nie wynika z obliczeń. Program przypisuje mu klasę startową z kartoteki, na przykład według klasy podobnego indeksu, i zastępuje ją wynikiem obliczenia po kilku tygodniach sprzedaży. Bez takiej reguły towar bez historii wszedłby do klasy C i trafił w najdalszy kąt, mimo że sprzedaje się szybko.

Klasyfikacja XYZ i wielkość zapasu w lokacji

Klasyfikacja XYZ opisuje regularność zapotrzebowania. Mierzy się ją współczynnikiem zmienności, czyli odchyleniem standardowym podzielonym przez średnią. Progi bywają ustalane na poziomie 0,5 i 1,0. Towar z klasy X wymaga stabilnego, niewielkiego zapasu w lokacji kompletacyjnej, a towar z klasy Z zapasu większego, bo jego popyt trudno przewidzieć.

Macierz ABC-XYZ łączy obie osie i przekłada się na wielkość lokacji oraz częstotliwość uzupełniania. Szersze omówienie zawiera materiał o metodach klasyfikacji asortymentu. Wariant dla regałów sięgających wielu metrów opisuje tekst o slottingu w magazynie wysokiego składowania, a podstawy metody omawia artykuł o analizie ABC w magazynie.

FIFO i FEFO przy wydaniu zapasu

Reguła rotacji działa po drugiej stronie procesu, przy alokacji wydania. Odkładanie decyduje, gdzie towar leży, a rotacja decyduje, który wiersz stanu zostanie pobrany jako pierwszy. Oba mechanizmy korzystają z tych samych danych, ale rozstrzygają inne pytania.

RegułaKlucz sortowaniaZastosowanie
FIFOData przyjęcia rosnącoTowar bez terminu ważności
FEFOTermin ważności rosnąco, potem data przyjęciaTowar z terminem ważności
LIFOData przyjęcia malejącoMateriały masowe, do których dostęp ma tylko górna warstwa

Alokacja bierze wiersze w kolejności reguły i zdejmuje z nich potrzebną ilość, aż suma pokryje zamówienie. Zapytanie z sumą narastającą robi to jednym przebiegiem. Przykład dla FEFO pobiera 120 sztuk jednego indeksu.

DECLARE @KodTowaru varchar(30) = 'TOW-001', @Potrzeba int = 120;

WITH kolejka AS (
    SELECT s.LokacjaId, s.NumerPartii, s.Ilosc,
           SUM(s.Ilosc) OVER (ORDER BY s.DataWaznosci, s.DataPrzyjecia, s.LokacjaId
                              ROWS UNBOUNDED PRECEDING) AS Narastajaco
    FROM dbo.StanPartii AS s
    WHERE s.KodTowaru = @KodTowaru AND s.StatusKod = 'DOSTEPNY'
)
SELECT LokacjaId, NumerPartii,
       CASE WHEN Narastajaco <= @Potrzeba THEN Ilosc
            ELSE @Potrzeba - (Narastajaco - Ilosc) END AS DoPobrania
FROM kolejka
WHERE Narastajaco - Ilosc < @Potrzeba;

Osobnym przypadkiem są palety niepełne. Reguła może preferować pobranie z palety już rozpoczętej, zanim program ruszy pełną. Skraca to okres, w którym w magazynie leżą dwie palety tego samego indeksu z częściowym zapasem. Kolejność uwzględnia się w kluczu sortowania jako pierwszą kolumnę, przed terminem ważności lub datą przyjęcia, jeśli firma tak zdecyduje.

Reguła: sortowanie alokacji musi być jednoznaczne; remis w terminie ważności rozstrzyga data przyjęcia, a potem identyfikator lokacji.

Filtr statusu pomija partie zablokowane, co opisano w tekście o warunkach specjalnych. Zastosowanie FIFO w magazynie towaru płynnego przedstawia materiał o metodzie FIFO w magazynie oleju. Wyniki zapytania trafiają na listę pobrań, którą opisuje tekst o kompletacji zamówień.

Palety na regałach wysokiego składowania i wózek widłowy w korytarzu magazynu
Zestawienie stanu w lokalizacjach: alokacja czyta wiersze stanu w kolejności FIFO albo FEFO i wskazuje lokacje do pobrania.

Wybór lokacji w procedurze składowanej

Wybór lokacji musi być bezpieczny współbieżnie. Dwóch operatorów odkładających jednocześnie ten sam indeks nie może dostać tej samej wolnej lokacji. Rozwiązuje to podpowiedź UPDLOCK w połączeniu z READPAST, użyta w jednym poleceniu, które wybiera lokację i od razu ją rezerwuje.

CREATE PROCEDURE dbo.usp_RezerwujLokacje
    @KodTowaru  varchar(30),
    @TypNosnika varchar(10),
    @Operator   sysname
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @klasa char(1) =
        (SELECT KlasaABC FROM dbo.Towar WHERE KodTowaru = @KodTowaru);

    WITH kandydat AS (
        SELECT TOP (1) l.*
        FROM dbo.Lokacja AS l WITH (UPDLOCK, READPAST, ROWLOCK)
        WHERE l.TypNosnika = @TypNosnika
          AND l.Zablokowana = 0
          AND l.StrefaId IN (SELECT StrefaId FROM dbo.StrefaKlasy
                             WHERE KlasaABC = @klasa)
          AND (l.RezerwacjaDo IS NULL OR l.RezerwacjaDo < SYSDATETIME())
          AND NOT EXISTS (SELECT 1 FROM dbo.StanPartii AS s
                          WHERE s.LokacjaId = l.LokacjaId)
        ORDER BY l.OdlegloscOdWydan, l.Adres
    )
    UPDATE kandydat
    SET RezerwacjaDo = DATEADD(MINUTE, 10, SYSDATETIME()),
        Rezerwujacy  = @Operator
    OUTPUT inserted.LokacjaId, inserted.Adres;
END;

READPAST pomija wiersze zablokowane przez inną transakcję zamiast na nie czekać. Drugi operator dostaje więc następną lokację z listy, a nie komunikat o oczekiwaniu. Opis podpowiedzi zawiera dokumentacja podpowiedzi tabelowych.

Rezerwacja z czasem wygaśnięcia

Rezerwacja jest zapisem w tabeli, a nie długą transakcją. Transakcja trwa milisekundy, a rezerwacja przykładowo dziesięć minut. Utrzymywanie otwartej transakcji przez czas oczekiwania na skan blokowałoby innych użytkowników i zwiększało ryzyko zakleszczeń. Warunek na kolumnie RezerwacjaDo w zapytaniu zwalnia lokację samoczynnie, gdy operator nie potwierdzi odłożenia.

Zapytanie wymaga indeksu obejmującego kolumny filtrowane i kolumnę sortowania. Wpływ indeksów na wydajność zapytań magazynowych omawia tekst o systemie magazynowym opartym na SQL Server.

Trasa kompletacji i uzupełnianie lokacji

Lista pobrań posortowana według kolejności adresów odtwarza trasę pracownika. Prosty porządek po adresie tekstowym prowadzi w każdej alei od tej samej strony. Sortowanie wężykowe odwraca kierunek w co drugiej alei: pole rośnie w alejach parzystych i maleje w nieparzystych. Pracownik nie wraca wtedy na początek alei, tylko przechodzi do następnej z miejsca, w którym skończył.

Grupowanie zamówień zmienia obraz trasy. Gdy kilka zamówień wymaga towaru z tej samej alei, program może połączyć je w jedną listę i rozdzielić towar dopiero na stanowisku pakowania. Grupowanie ma sens tylko przy stabilnych strefach klasowych. Przy losowym rozmieszczeniu każda pozycja leży gdzie indziej i wspólna trasa niczego nie skraca.

Lokacja kompletacyjna klasy A ma niewielki zapas, więc opróżnia się szybko. Program utrzymuje dla niej minimum i maksimum. Gdy stan spadnie poniżej minimum, generuje zlecenie przesunięcia z lokacji rezerwowej. Rezerwę dobiera się tą samą regułą rotacji co wydania, czyli FEFO albo FIFO. Wypełnienie stref pokazuje wizualizacja zajętości magazynu.

Przeliczanie klas i koszt przesunięć

Klasyfikacja starzeje się wraz z ofertą i sezonem. Zadanie SQL Agent przelicza klasy raz w tygodniu i zapisuje wynik w tabeli obok poprzedniej klasy. Zmiana klasy uruchamia zlecenie przesunięcia dopiero wtedy, gdy przekroczy margines, zwany histerezą. Towar leżący na granicy klas A i B nie wędrowałby wtedy między strefami co tydzień.

Każde przesunięcie kosztuje pracę magazyniera i chwilowo zajmuje dwie lokacje. Korzyść z bliższego położenia musi ten koszt przewyższyć. Zlecenia przesunięć układa się więc w partie o stałej wielkości, wykonywane w godzinach o mniejszym ruchu, a nie wszystkie naraz po każdym przeliczeniu.