Kontrola nad towarami jako rejestr zdarzeń
Kontrola nad towarami oznacza w praktyce coś więcej niż znajomość liczby sztuk na stanie. Chodzi o możliwość wskazania w każdej chwili, gdzie leży dany produkt, z jakiej partii pochodzi i kto ostatnio wykonał na nim operację. System WMS zastępuje w tym celu papierowe ewidencje jednym źródłem danych, dostępnym równocześnie dla magazyniera i księgowości. Warunki wdrożenia opisuje strona o wdrożeniu systemu WMS.
Bez systemu kontrola opiera się na pamięci ludzi i papierowych dokumentach, a uzupełniają ją okresowe spisy z natury. Model sprawdza się w małym magazynie, ale wraz ze wzrostem liczby indeksów traci wiarygodność: dane papierowe starzeją się z każdą minutą, a błąd przepisania wychodzi na jaw dopiero przy kolejnej inwentaryzacji. Cyfrowy rejestr zapisuje zmianę w chwili jej wystąpienia, więc kontrola przestaje być czynnością kwartalną i staje się właściwością systemu.
Podstawą takiego rejestru jest jednoznaczna identyfikacja obiektu. Towar rozpoznaje się po kodzie SKU oraz numerze partii albo serii, a miejsce po lokalizacji w formacie strefa-rząd-kolumna-poziom, na przykład A-02-05-3. Każda operacja dotyczy więc konkretnej jednostki w konkretnym miejscu, a nie przybliżonej kategorii towaru.
Zasada: stan magazynowy jest wynikiem sumowania ruchów, a nie polem, które ktoś nadpisuje.
Stan magazynowy jest w tym modelu wynikiem, a nie danymi wejściowymi. Źródłem prawdy jest rejestr ruchów tylko do dopisywania, w którym przyjęcie zapisuje ilość dodatnią, a wydanie ujemną. Ruchu nie poprawia się edycją wiersza. Błąd koryguje kolejny ruch, zwany stornem, który zostaje w historii razem z pomyłką.
CREATE TABLE dbo.StockMovements (
MovementId BIGINT IDENTITY PRIMARY KEY,
MovedAt DATETIME2(3) NOT NULL DEFAULT SYSDATETIME(),
UserId INT NOT NULL,
DocumentId INT NULL,
ItemId INT NOT NULL,
BatchNo NVARCHAR(40) NULL,
LocationId INT NOT NULL,
QuantityDelta DECIMAL(18,3) NOT NULL, -- dodatnia przy przyjęciu, ujemna przy wydaniu
MovementType NVARCHAR(10) NOT NULL
);
CREATE INDEX IX_Movements_Batch ON dbo.StockMovements (BatchNo, MovedAt);
Tabela jest przykładowa i nie odwzorowuje schematu żadnego produktu. Pokazuje jednak zasadę, którą stosuje się w wielu systemach magazynowych: pojedynczy ruch jest niezmienny, a raporty składa się z sum.
Statusy towaru i blokady
Sama ilość nie wystarcza, bo część zapasu fizycznie istnieje, ale nie wolno jej wydać. Status opisuje, w jakim stanie jest partia, i decyduje, czy system dopuści ją do kompletacji. Statusy przypisuje się partii, a nie SKU, ponieważ dwie partie tego samego towaru mogą być w różnym stanie jakości.
| Status partii | Liczy się do dostępnego stanu | Kompletacja dozwolona | Kto zdejmuje blokadę |
|---|---|---|---|
| Przyjęta do kontroli | Nie | Nie | Kontrola jakości |
| Dostępna | Tak | Tak | Nie dotyczy |
| Zarezerwowana pod zamówienie | Nie, jest przypisana | Tylko do tego zamówienia | Dyspozytor lub system po anulowaniu |
| Zablokowana jakościowo | Nie | Nie | Kierownik jakości |
| Uszkodzona | Nie | Nie | Decyzja o utylizacji lub zwrocie |
Zmiana statusu jest operacją transakcyjną. System sprawdza, czy przejście z obecnego stanu do nowego jest dozwolone, zapisuje nowy status oraz wpis w historii z autorem i przyczyną. Jeżeli którykolwiek krok się nie uda, cała zmiana zostaje wycofana.
CREATE PROCEDURE dbo.usp_ChangeBatchStatus
@BatchId INT, @NewStatus NVARCHAR(12), @UserId INT, @Reason NVARCHAR(200)
AS
BEGIN
SET XACT_ABORT ON;
BEGIN TRAN;
DECLARE @Old NVARCHAR(12) =
(SELECT Status FROM dbo.Batches WITH (UPDLOCK) WHERE BatchId = @BatchId);
IF NOT EXISTS (SELECT 1 FROM dbo.StatusRules
WHERE FromStatus = @Old AND ToStatus = @NewStatus)
THROW 50001, 'Zmiana statusu niedozwolona.', 1;
UPDATE dbo.Batches SET Status = @NewStatus WHERE BatchId = @BatchId;
INSERT INTO dbo.StatusHistory (BatchId, OldStatus, NewStatus, UserId, Reason, ChangedAt)
VALUES (@BatchId, @Old, @NewStatus, @UserId, @Reason, SYSDATETIME());
COMMIT;
END;
Reguła: partia zablokowana jakościowo nie trafia na listę kompletacji, nawet gdy jest jedyną z wymaganą ilością.
Blokada działa wtedy, gdy zapytanie tworzące zadania kompletacji pomija partie o statusie innym niż Dostępna. Sprawdzenie w interfejsie bez takiego warunku w bazie da się obejść.
Rezerwacja pod zamówienie jest osobnym statusem, a nie zmianą ilości. Zarezerwowana partia nadal leży w lokalizacji, lecz system zdejmuje ją z dostępnego stanu i przypisuje do zlecenia. Anulowanie zamówienia zwalnia rezerwację bez ruchu magazynowego, bo towar nigdzie się nie przemieścił.
Partie i identyfikowalność towaru
Identyfikowalność (ang. traceability) to zdolność odtworzenia historii partii: od dostawcy i daty przyjęcia, przez kolejne lokalizacje, po dokument wydania i odbiorcę. W branżach regulowanych, na przykład spożywczej albo farmaceutycznej, jest to wymóg formalny. Poza nimi skraca czas reakcji na reklamację lub wycofanie wadliwej partii. Podobny mechanizm w systemie ERP opisuje artykuł o śledzeniu partii produktów.
System WMS wiąże jednostkę logistyczną z numerem partii lub numerem seryjnym już przy przyjęciu, korzystając z etykiety dostawcy albo generując własną, na przykład w standardzie etykiety GS1. Ten sam numer towarzyszy towarowi przy każdym przesunięciu, więc w kilka sekund można wygenerować listę lokalizacji, przez które przeszła partia, oraz odbiorców, do których trafiła.
SELECT m.MovedAt, m.MovementType, m.LocationId, m.QuantityDelta,
d.DocumentNo, d.PartnerName
FROM dbo.StockMovements AS m
LEFT JOIN dbo.Documents AS d ON d.DocumentId = m.DocumentId
WHERE m.BatchNo = @BatchNo
ORDER BY m.MovedAt;

Śledzenie partii od przyjęcia do wydania
Śledzenie zaczyna się w strefie przyjęć, gdzie dokument PZ zostaje powiązany z numerem partii i datą ważności. Podczas składowania system pilnuje reguły FEFO lub FIFO i podpowiada pobranie partii, która powinna wyjść pierwsza. Przy kompletacji skan potwierdza, że pobrana partia zgadza się z wskazaną, a nie z dowolną sztuką leżącą najbliżej. Na dokumencie WZ numer partii zostaje w historii zamówienia, więc reklamację po miesiącach rozpatruje się bez przeszukiwania archiwum. Dokumenty opisuje strona o dokumentach magazynowych, a samo wydanie towaru - artykuł o wydaniu z magazynu.
W magazynach z towarem wielu właścicieli do klucza dochodzi identyfikator zleceniodawcy, co omawia artykuł o WMS dla operatora 3PL.

Historia ruchów i aktualność stanów
Aktualizacja stanów odbywa się zwykle na kolektorze danych lub terminalu, na którym pracownik skanuje kod towaru oraz kod lokalizacji przed przeniesieniem i po nim. Dwukrotny odczyt eliminuje ryzyko zaksięgowania produktu w innym miejscu niż faktycznie trafił. System porównuje skanowany kod z oczekiwaną operacją i sygnalizuje niezgodność, zanim pracownik odejdzie od regału.
Po potwierdzeniu operacji system od razu koryguje ilość w lokalizacji i udostępnia ją pozostałym działom. Dział zakupów widzi faktyczny zapas przed złożeniem zamówienia uzupełniającego, a obsługa klienta potwierdza dostępność w trakcie rozmowy. Rozbieżność między stanem fizycznym a księgowym, która w modelu papierowym utrzymuje się tygodniami, nie ma tu miejsca. Zasady ewidencji ilościowej opisuje strona o stanach magazynowych.
Ponieważ stan wynika z sumy ruchów, można go policzyć na dowolny dzień w przeszłości. Zapytanie poniżej odtwarza układ zapasu z początku miesiąca, co przydaje się przy uzgadnianiu inwentaryzacji i sporów z klientem.
SELECT LocationId, ItemId, BatchNo, SUM(QuantityDelta) AS Qty
FROM dbo.StockMovements
WHERE MovedAt < '2026-09-01'
GROUP BY LocationId, ItemId, BatchNo
HAVING SUM(QuantityDelta) <> 0;

Ślad audytowy w bazie danych
Audytowalność oznacza możliwość odtworzenia, kto i kiedy wykonał operację na towarze lub dokumencie. Log rejestruje się automatycznie, niezależnie od pamięci ludzi, a jego wpisy chroni się przed późniejszą zmianą. Przy rozbieżności inwentaryzacyjnej można w kilka minut sprawdzić, kto ostatnio dotykał lokalizacji. Dla firm poddawanych audytom zewnętrznym, certyfikacjom jakości lub kontrolom skarbowym raport za wskazany okres jest gotowym materiałem dowodowym.
| Mechanizm w SQL Server | Co chroni | Ograniczenie |
|---|---|---|
| Rejestr ruchów tylko do dopisywania | Historię zmian ilości | Wymaga ruchów korygujących zamiast edycji |
| Odebranie UPDATE i DELETE roli aplikacji | Rejestr przed modyfikacją przez aplikację | Nie zatrzymuje administratora bazy |
| Tabela czasowa (temporal table) | Historię zmian kartotek i uprawnień | Przyrost danych historycznych do zarządzania |
| Wpisy w tabeli statusów | Przyczynę i autora zmiany statusu | Zapis wykonuje kod procedury, więc wymaga przeglądu |
Rejestr ruchów zabezpiecza się odebraniem uprawnień do zmiany i usuwania. Dane podstawowe, na przykład kartotekę towarów, prowadzi się jako tabelę czasową, w której silnik sam zachowuje poprzednie wersje wierszy. Składnię opisuje dokumentacja tabel czasowych w SQL Server.
DENY UPDATE, DELETE ON dbo.StockMovements TO app_warehouse;
CREATE TABLE dbo.ItemMaster (
ItemId INT PRIMARY KEY,
Sku NVARCHAR(40) NOT NULL,
StatusCode NVARCHAR(12) NOT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.ItemMasterHistory));
SELECT * FROM dbo.ItemMaster
FOR SYSTEM_TIME AS OF '2026-09-15T10:00:00';
Nie wszystko musi trafić do jednego dziennika. Zakres śladu dobiera się do ryzyka, a cztery grupy zdarzeń obejmuje prawie każdy audyt:
- Ruchy magazynowe - każdy ruch towaru od przyjęcia po wydanie, z ilością i partią oraz autorem.
- Zmiany statusów - blokady i zwolnienia z przyczyną i osobą zatwierdzającą.
- Zmiany danych podstawowych - kartoteki towarów oraz uprawnienia kont, przechowywane w tabelach czasowych.
- Korekty i wyjątki - storna i korekty inwentaryzacyjne oraz operacje wykonane z podniesionymi uprawnieniami.
Okres przechowywania śladu wynika z umów i przepisów, którym podlega firma, dlatego archiwizację planuje się razem z kopiami zapasowymi, a nie po fakcie. Stare partycje rejestru ruchów można przenosić na tańsze nośniki, zachowując możliwość odtworzenia stanu na dowolny dzień z tego okresu.
Zasada: uprawnienia do zmiany rejestru ruchów ma wyłącznie procedura, a nie konto pracownika.
Uprawnienia i podział obowiązków
Kontrola dostępu przypisuje uprawnienia operacyjne do stref albo grup towarów na poziomie konta. Strefa towarów o wysokiej wartości albo materiałów niebezpiecznych bywa dostępna tylko dla wyznaczonego zespołu, a próba operacji spoza uprawnień zostaje odrzucona, zanim dojdzie do fizycznego dostępu. Konfigurację ról omawia strona o rolach i użytkownikach w systemie WMS.
Uprawnienia różnicuje się też według typu operacji. Jeden pracownik przyjmuje towar, inny go kompletuje, a korektę stanu zatwierdza wyłącznie kierownik zmiany. Taki podział obowiązków, znany z gospodarki magazynowej opartej na dokumentach, system egzekwuje automatycznie. Każda operacja jest przypisana do zalogowanego pracownika i znacznika czasu, więc wyprowadzenie towaru bez śladu w systemie jest trudne. Lokalizacje lub zmiany, w których rozbieżności pojawiają się częściej niż średnia, wskazuje zestawienie z operacji magazynowych.
Błędom kompletacji zapobiega ta sama mechanika. System wymusza skan każdej pozycji przed odłożeniem do kartonu, a gdy zeskanowany kod nie zgadza się z pozycją zamówienia, blokuje dalsze kroki i żąda korekty na miejscu, nie po fakcie.
Arkusz kalkulacyjny czy system WMS w kontroli towarów
Część małych magazynów prowadzi ewidencję w arkuszu uzupełnianym po każdej zmianie stanu. Rozwiązanie działa przy niewielkiej liczbie indeksów, ale traci wartość, gdy rosną skala i liczba osób.
| Obszar kontroli | Arkusz kalkulacyjny | System WMS |
|---|---|---|
| Aktualność stanu | Zależna od tego, kiedy ktoś zaktualizuje plik | Aktualizacja po skanie operacji |
| Identyfikowalność partii | Ręczne szukanie w historii wpisów | Ścieżka partii dostępna w kilka sekund |
| Dostęp do danych | Ograniczony hasłem do pliku | Uprawnienia na poziomie strefy i operacji |
| Ślad operacji | Zwykle brak lub niepełny | Pełny zapis każdej zmiany stanu |
| Błędy kompletacji | Wykrywane po reklamacji klienta | Blokada w chwili skanu niezgodnej pozycji |
Dla magazynu z kilkudziesięcioma zamówieniami miesięcznie arkusz bywa wystarczający. Gdy rośnie liczba indeksów oraz osób biorących udział w wydaniach, koszt utraconej kontroli przewyższa koszt wdrożenia systemu. Chodzi o błędne wysyłki oraz czas potrzebny na odtworzenie historii.
Wdrażanie kontroli etapami
Pełna kontrola nie wymaga jednorazowej przebudowy magazynu. Sprawdza się podejście etapowe, w którym mechanizmy dodaje się jeden po drugim, a bieżące kontrole inwentaryzacyjne pokazują postęp:
- Porządek lokalizacji i identyfikacji - unikalny kod każdego miejsca w formacie strefa-rząd-kolumna-poziom i oznakowane regały. Kody SKU i partii tam, gdzie to zasadne.
- Skanowanie każdej operacji - kolektory danych dla pracowników i wymuszone potwierdzanie przyjęć i wydań.
- Uprawnienia i statusy - podział ról na strefy i operacje oraz reguły przejść między statusami partii.
- Raportowanie i weryfikacja cykliczna - zestawienia rozbieżności i historii dla lokalizacji lub partii oraz zaplanowane kontrole częściowe.
Każdy etap można wdrożyć niezależnie od pozostałych, więc magazyn nie wstrzymuje bieżących operacji. Pełne wdrożenie z opisanymi mechanizmami zajmuje zwykle od kilku do kilkunastu tygodni, zależnie od liczby lokalizacji i integracji z innymi systemami. Omówienie dokumentów PZ i WZ znajduje się także w serwisie SoftwareStudio.




