Magazyn wysokiego składowania wymusza rozwiązania, których nie ma w prostym programie magazynowym. Towar leży na poziomach niedostępnych bez wózka o dużym zasięgu, korytarze bywają wąskie, a każda pomyłka adresu kosztuje ponowny przejazd. Gdy gotowy system nie odwzorowuje takich procesów, firma rozważa program pisany pod jej wymagania.

Poniższy tekst opisuje, w jakich sytuacjach ma to sens i jak taki projekt wygląda od strony technicznej. Definicje wysokiego składowania różnią się w zależności od źródła, więc w praktyce liczy się zasięg wózków i sposób obsługi regałów, a nie jedna wartość progowa.

Programy na zamówienie w logistyce magazynowej

Program na zamówienie powstaje według procesów jednej firmy. Zespół programistów przygotowuje specyfikację z pracownikami firmy, a następnie pisze aplikację. Po odbiorze przekazuje ją do wdrożenia. SoftwareStudio jest producentem oprogramowania i realizuje takie projekty jako aplikacje internetowe oraz mobilne, uzupełniane w razie potrzeby przez outsourcing usług programistycznych.

W logistyce magazynowej program na zamówienie może występować w trzech rolach. Pierwsza to samodzielny system dla procesu, którego rynek nie obsługuje. Druga to moduł uzupełniający gotowy WMS, na przykład specjalne kolejkowanie zadań dla wózków. Trzecia to warstwa integracyjna między istniejącymi systemami. Wybór roli decyduje o kosztach i ryzyku.

KryteriumGotowy WMSProgram na zamówienie
Pokrycie procesówstandardowe, konfigurowane parametramidokładnie według specyfiki firmy
Czas do pierwszego uruchomieniakrótszy, bo funkcje istniejądłuższy, bo trzeba je zaprojektować i napisać
Utrzymaniewydania producenta dla wszystkich klientówpoprawki i rozwój zamawiane osobno
Ryzykoprocesy trzeba dopasować do systemubłędy w specyfikacji ujawniają się po napisaniu kodu

Rozstrzygnięcie nie musi być zero-jedynkowe. W wielu obiektach sprawdza się gotowy system z dedykowanym dodatkiem tam, gdzie standard nie sięga. Ogólne porównanie podejść zawiera artykuł o programach na zamówienie, a temat wdrożeń w chmurze i na maszynach wirtualnych omawia tekst o programach na zamówienie a chmurze i VMware.

Kiedy gotowy WMS nie wystarcza w magazynie wysokiego składowania

Magazyn wysokiego składowania ma cechy, które trudno ująć w standardowym parametrze systemu. Pierwszą jest flota wózków o różnym zasięgu. Wózek czołowy nie dosięgnie gniazda na dużej wysokości, a wózek wysokiego podnoszenia nie przejedzie każdym korytarzem. System musi więc wiedzieć, który sprzęt obsłuży które gniazdo, zanim wyśle zadanie na terminal.

Drugą cechą są punkty przekazania między strefami, na przykład miejsca, w których paleta zmienia wózek. Trzecią jest sekwencja ruchów: paleta nie może opuścić poziomu bez potwierdzenia skanem, a zadanie odkładania musi uwzględniać wysokość i nośność gniazda. Szczegółowe reguły adresacji i odkładania opisuje artykuł o aplikacji dla magazynu wysokiego składowania.

Reguła: nie pisze się programu dla funkcji, którą gotowy system realizuje parametrem. Program na zamówienie uzasadnia dopiero proces, którego żadna konfiguracja nie odwzorowuje.

Trzy osoby w kamizelkach odblaskowych z tabletami w alejce regałowej obok wózka paletowego
Rozmowa z obsługą regałów na hali - z niej wynika lista procesów, które trzeba odwzorować w programie.
Wymaganie procesuGotowy WMS ustawia parametremWymaga własnego kodu
Adres z poziomem regałutak, struktura lokalizacji jest konfigurowalnanie
Zasięg wózka a wysokość gniazdazwykle w podstawowej postacigdy zasięg zależy też od korytarza i zmiany
Kolejka zadań z priorytetamiczęściowo, według stałych regułgdy priorytet wynika z okna wysyłki klienta
Wymiana z automatyką regałówrzadko, zwykle przez osobny interfejstak, jeśli sterownik ma własny protokół

Na decyzję wpływa także skala. Przy kilkuset gniazdach wystarcza zwykle konfiguracja gotowego systemu. Przy kilkunastu tysiącach lokalizacji, kilku typach wózków i zmianowej pracy operatorów rośnie znaczenie kolejkowania zadań i optymalizacji tras w korytarzach. To właśnie tam programiści dostają zadania, których nie zaspokaja standard. Przegląd argumentów za wdrożeniem systemu w takim obiekcie zawiera tekst o systemie WMS w magazynie wysokiego składowania.

Zakres projektu - od listy procesów do specyfikacji

Projekt zaczyna się od listy procesów, które mają zostać zautomatyzowane. Bez niej wycena jest szacunkiem, a analiza przedwdrożeniowa trwa dłużej. Każdy proces ma na niej cztery pola, opisane niżej. Dla przyjęcia palety wejściem jest awizacja i etykieta, a wynikiem zapis stanu w lokalizacji z potwierdzeniem skanem.

Na tej podstawie powstaje specyfikacja funkcjonalna. Opisuje ona role użytkowników i ekrany. Dodaje reguły walidacji oraz integracje. Osobne miejsce zajmują wymagania niefunkcjonalne: liczba jednoczesnych użytkowników, dopuszczalny czas odpowiedzi na terminalu i sposób postępowania przy utracie łączności Wi-Fi. Przebieg analizy opisuje artykuł o analizie przedwdrożeniowej.

Zespół pięciu osób przy stole podczas spotkania analitycznego, na pierwszym planie heksagonalne elementy graficzne
Warsztat analityczny z użytkownikami - etap, na którym powstaje lista procesów i specyfikacja.
  • Proces - nazwa czynności w słowniku firmy, na przykład odkładanie palety albo uzupełnienie strefy kompletacji.
  • Użytkownik - rola wykonująca czynność i urządzenie, na którym pracuje, na przykład operator wózka z terminalem.
  • Dane wejściowe - dokument albo etykieta, od której proces się zaczyna.
  • Wynik - zmiana stanu w bazie i dokument, który ją potwierdza.

Specyfikacja jest gotowa, gdy każdy proces z listy ma opis w tym czteropolowym formacie i został zatwierdzony przez osobę, która go wykonuje. Zatwierdzenie tylko przez kierownictwo zostawia luki, bo szczegóły pracy przy regale zna operator, a nie kierownik.

Architektura programu pod SQL Server

W typowym rozwiązaniu warstwa danych to SQL Server, logika działa w aplikacji napisanej w C#, a interfejs w przeglądarce (JavaScript) oraz na terminalach z Androidem. Baza przechowuje stany i ruchy, a także kolejkę zadań, a procedury składowane zapewniają, że reguły biznesowe obowiązują niezależnie od tego, z którego klienta przyszło żądanie.

Kolejka zadań dla wózków to wzorzec, który w takim magazynie sprawia najwięcej kłopotów. Kilku operatorów pobiera zadania jednocześnie i żaden nie powinien dostać zadania już przyjętego przez innego. Rozwiązuje to pobieranie zadania w jednym poleceniu z blokadą wiersza i pomijaniem wierszy zablokowanych. Przykład pokazuje procedurę, w której operator podaje maksymalny zasięg swojego wózka. Nazwy tabel są przykładowe.

CREATE PROCEDURE dbo.PobierzZadanie
    @OperatorId int,
    @ZasiegMaxCm smallint
AS
BEGIN
    SET NOCOUNT ON;

    ;WITH nastepne AS (
        SELECT TOP (1) *
        FROM dbo.ZadanieMagazynowe WITH (ROWLOCK, UPDLOCK, READPAST)
        WHERE Status = 0
          AND WysokoscGniazdaCm <= @ZasiegMaxCm
        ORDER BY Priorytet DESC, ZadanieId
    )
    UPDATE nastepne
       SET Status = 1,
           OperatorId = @OperatorId,
           PobranoO = SYSDATETIME()
    OUTPUT inserted.ZadanieId, inserted.LokalizacjaId;
END;

Reguła: zadanie wybiera się i oznacza jako pobrane jednym poleceniem. Osobne zapytanie SELECT, a po nim UPDATE, dopuszcza wyścig, w którym dwie sesje odczytają to samo zadanie.

Podpowiedź UPDLOCK zakłada blokadę na wybranym wierszu, a READPAST każe innym sesjom pominąć wiersze zablokowane zamiast czekać. Dzięki temu dwaj operatorzy nie pobiorą tego samego zadania i żaden nie stoi w kolejce do blokady. Opis podpowiedzi zawiera dokumentacja podpowiedzi tabel w T-SQL w Microsoft Learn.

Status zadaniaZnaczenieKto zmienia
0 - oczekującezadanie czeka na operatora z odpowiednim zasięgiemsystem po odebraniu dokumentu
1 - pobranezadanie przypisane do operatora, ruch jeszcze niepotwierdzonyprocedura pobierania
2 - potwierdzoneruch wykonany i zapisany skanem etykietyterminal operatora
3 - anulowanezadanie wycofane przez kierownika zmianyużytkownik z uprawnieniem

Odczyty raportowe w takiej bazie nie powinny blokować operatorów. Domyślny poziom izolacji READ COMMITTED w SQL Server używa blokad współdzielonych, więc długie zapytanie raportowe może zatrzymywać zapisy. Rozwiązaniem jest włączenie wersjonowania wierszy (READ_COMMITTED_SNAPSHOT), po którym czytelnicy widzą spójną wersję danych bez czekania. Opis mechanizmu zawiera przewodnik po blokowaniu i wersjonowaniu wierszy.

Warunek na wysokość gniazda realizuje wcześniej omówioną zasadę: wózek dostaje tylko zadania, które fizycznie obsłuży. Warunek Status = 0 najlepiej wesprzeć indeksem filtrowanym na zadania oczekujące, żeby zapytanie nie przeglądało zadań zakończonych. Przykładowa definicja to CREATE INDEX IX_Zadanie_Oczekujace ON dbo.ZadanieMagazynowe (Priorytet DESC, ZadanieId) INCLUDE (WysokoscGniazdaCm) WHERE Status = 0. Praca operatora na terminalu odbywa się przez aplikację opisaną w artykule o aplikacji magazynowej na Androidzie.

Integracja z ERP i urządzeniami

Program na zamówienie rzadko działa sam. Odbiera zamówienia i kartoteki z ERP, a potwierdzenia przyjęć i wydań odsyła w drugą stronę. Wymianę realizuje się przez interfejs REST albo kolejkę komunikatów, z odrębną obsługą błędów, ponieważ komunikat może dotrzeć dwukrotnie lub wcale. Wzorce wymiany danych opisuje artykuł o integracji WMS z ERP przez REST i kolejki.

Po stronie terminala mobilnego zapis ruchu musi być odporny na powtórzenie. Operator w korytarzu regałowym traci zasięg Wi-Fi i ponawia skan, a aplikacja wysyła to samo żądanie drugi raz. Rozwiązaniem jest klucz idempotentności generowany na terminalu i sprawdzany po stronie serwera. Poniższy fragment JavaScript pokazuje wywołanie z takim kluczem.

async function potwierdzRuch(ruch) {
  const odpowiedz = await fetch('/api/ruchy', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Idempotency-Key': ruch.klucz
    },
    body: JSON.stringify(ruch)
  });
  if (!odpowiedz.ok) {
    throw new Error('Serwer odrzucił ruch: ' + odpowiedz.status);
  }
  return odpowiedz.json();
}

Serwer zapisuje klucz w tabeli z ograniczeniem unikalności. Powtórzone żądanie z tym samym kluczem zwraca wynik pierwszego zapisu i nie zmienia stanu. Składnię wywołań opisuje dokumentacja interfejsu Fetch. Dane o towarach i lokalizacjach pochodzą z kartotek opisanych w tekście o systemie zarządzania magazynem WMS.

Etykiety i jednostki logistyczne

Osobnym tematem są etykiety. Etykiety palet drukuje się zwykle na drukarkach termotransferowych, sterowanych językiem ZPL, a program generuje treść etykiety z numerem jednostki logistycznej. Jeżeli firma stosuje numery SSCC według standardu GS1, numer nadaje się raz przy tworzeniu palety, a etykietę można wydrukować ponownie z tym samym numerem. Ponowny wydruk nie tworzy wtedy drugiej jednostki, tylko kopię tej samej etykiety. Zasadę tę program egzekwuje w bazie: numer jednostki ma ograniczenie unikalności, a operacja wydruku jedynie odczytuje istniejący rekord.

Testy i odbiór projektu w magazynie

Testy programu dla magazynu wysokiego składowania wykonuje się na kopii danych i na sprzęcie, który będzie używany na hali. Terminal pokazuje inne ekrany niż przeglądarka, a skaner odczytuje etykiety inaczej przy różnym oświetleniu. Błąd wykryty w korytarzu na dużej wysokości kosztuje wielokrotnie więcej niż ten sam błąd wykryty na stanowisku testowym.

EtapWynikKryterium odbioru
Prototyp ekranówmakiety zatwierdzone przez operatorówkażdy proces z listy ma ekran
Wersja testowaprogram na kopii danych klientascenariusze z listy procesów przechodzą bez błędów
Pilotażpraca w jednej strefie magazynuzgodność stanów po inwentaryzacji strefy
Wdrożenieuruchomienie w całym obiekcieprotokół odbioru podpisany przez klienta

Scenariusze testowe obejmują nie tylko przebieg prawidłowy. Sprawdza się paletę większą od gniazda, lokalizację zablokowaną w trakcie odkładania, skan etykiety spoza zadania i utratę łączności w połowie operacji. Test obciążeniowy odtwarza liczbę terminali pracujących jednocześnie na największej zmianie i mierzy czas odpowiedzi procedury pobierania zadań. Kopia danych produkcyjnych, jeśli zawiera dane osobowe pracowników lub kontrahentów, przechodzi przed testami anonimizację.

Kryteria odbioru zapisuje się przed rozpoczęciem programowania, a nie po jego zakończeniu. Umowa powinna także określać, kto po odbiorze dysponuje kodem źródłowym i dokumentacją oraz jak wygląda przekazanie środowiska. Zakres praw autorskich i licencji ustala się z prawnikiem, a stronie technicznej projektu dedykowaną uwagę poświęca artykuł o relacji producenta i klienta przy oprogramowaniu na zamówienie.

Utrzymanie programu po wdrożeniu

Program w magazynie działa codziennie, więc po odbiorze zaczyna się etap, który trwa najdłużej. Obejmuje kopie zapasowe bazy, monitorowanie zadań cyklicznych i wprowadzanie poprawek. Zadania cykliczne, takie jak nocna kontrola zgodności stanów, uruchamia SQL Server Agent, a jego opis zawiera dokumentacja SQL Server Agent.

Zmiany zgłaszane po wdrożeniu mają zwykle charakter drobnych rozszerzeń: nowy typ wózka, dodatkowa strefa, inny format etykiety. Przy dobrze rozdzielonych warstwach takie zmiany dotyczą jednej procedury lub jednego ekranu, więc wydanie poprawki jest krótkie. Przy programie, w którym reguły są rozproszone po aplikacji, każda zmiana wymaga przeglądu całości.

Zgłoszenie po wdrożeniuMiejsce zmianySposób weryfikacji
Nowy typ wózkasłownik typów i zasięgówtest przydziału zadań na kopii danych
Dodatkowa strefa składowaniastruktura lokalizacjiprzyjęcie testowej palety skanem
Inny format etykietyszablon wydrukuodczyt etykiety terminalem na hali

Ważne jest też zachowanie dokumentacji aktualnej. Opis struktury bazy i kontraktów interfejsów aktualizuje się przy każdym wydaniu, a nie raz w roku. Nowy programista, który dołącza do utrzymania, korzysta z niej w pierwszym tygodniu pracy. Zakres usług programistycznych, w tym tworzenia aplikacji i ich rozwoju, opisuje strona o oprogramowaniu na zamówienie.