Bilans zamówień i rezerwacji - definicja i wzór
Składniki bilansu
Bilans zamówień i rezerwacji odpowiada na jedno pytanie: ile towaru zostanie wolnego, gdy zrealizuje się wszystko, co już obiecano klientom, i dotrze wszystko, co już zamówiono u dostawców. Według opisu HermesSQL zestawia stan magazynowy z przyjętymi zamówieniami klientów, dzięki czemu widać ilość w drodze oraz ilość zarezerwowaną. Z różnicy wynika, ile trzeba jeszcze zamówić. Sam stan na półce niczego takiego nie mówi, bo nie zawiera przyszłych ruchów.
Wzór ogólny ma cztery składniki: stan magazynowy plus dostawy w drodze, minus rezerwacje, minus niezrealizowane zamówienia klientów. Ostatni składnik dotyczy tylko zamówień bez rezerwacji. Zamówienie z rezerwacją liczy się raz, w rezerwacjach, inaczej ta sama ilość pomniejszyłaby bilans dwukrotnie.
| Składnik | Znak we wzorze | Źródło danych |
|---|---|---|
| Stan magazynowy | Plus | Ilość dostępna na magazynie, bez towaru zablokowanego |
| Dostawy w drodze | Plus | Pozostała ilość z otwartych zamówień do dostawców |
| Rezerwacje | Minus | Ilości przypisane do konkretnych zamówień klientów |
| Zamówienia bez rezerwacji | Minus | Niezrealizowane pozycje zamówień, którym nie przypisano towaru |
Wzór i przykład liczbowy
Przykład ma charakter ilustracyjny. Towar ma 120 sztuk na magazynie i 80 sztuk w drodze, rezerwacje obejmują 60 sztuk, a zamówienia bez rezerwacji 90 sztuk. Bilans wynosi 120 plus 80 minus 60 minus 90, czyli 50 sztuk. Wynik dodatni oznacza, że nowe zamówienie klienta na nie więcej niż 50 sztuk da się obiecać bez dokupowania. Wynik ujemny wskazuje ilość do zamówienia u dostawcy.
SELECT t.TowarId,
ISNULL(s.Ilosc, 0) + ISNULL(d.WDrodze, 0)
- ISNULL(r.Zarezerwowano, 0) - ISNULL(z.BezRezerwacji, 0) AS Bilans
FROM dbo.Towar AS t
LEFT JOIN dbo.StanMagazynowy AS s ON s.TowarId = t.TowarId
LEFT JOIN (SELECT TowarId, SUM(IloscPozostala) AS WDrodze
FROM dbo.ZamowienieZakupuPozycja GROUP BY TowarId) AS d
ON d.TowarId = t.TowarId
LEFT JOIN (SELECT TowarId, SUM(Ilosc) AS Zarezerwowano
FROM dbo.Rezerwacja WHERE Status = 1 GROUP BY TowarId) AS r
ON r.TowarId = t.TowarId
LEFT JOIN (SELECT TowarId, SUM(IloscPozostala) AS BezRezerwacji
FROM dbo.ZamowienieKlientaPozycja
WHERE MaRezerwacje = 0 GROUP BY TowarId) AS z
ON z.TowarId = t.TowarId;
Nazwy tabel są przykładowe. Każdy składnik agreguje się osobno, zanim trafi do złączenia, bo złączenie surowych tabel pomnożyłoby wiersze i zawyżyło sumy. Wartości NULL z LEFT JOIN zamienia funkcja ISNULL, inaczej całe wyrażenie dla towaru bez rezerwacji dałoby NULL.
Reguła: bilans liczy się na towar, a przy partiach i terminach ważności także na partię. Suma bilansów partii nie zastąpi bilansu towaru, jeśli rezerwacja wskazuje konkretną partię.
Ilość dostępna do obiecania
W praktyce sprzedaży liczy się nie sam bilans, lecz ilość dostępna do obiecania na konkretną datę. Bierze ona pod uwagę tylko te dostawy, które przyjdą przed terminem wysyłki, i tylko te rezerwacje, które przypadają przed nim lub w tym samym dniu. Dostawa spóźniona o jeden dzień względem daty wysyłki nie zwiększa ilości dostępnej do obiecania, choć zwiększa bilans na koniec horyzontu.
Różnica ma znaczenie przy odpowiedzi na zapytanie klienta. Sprzedawca, który patrzy na bilans końcowy, obieca towar, którego w dniu wysyłki jeszcze nie będzie. Zapytanie liczące bilans narastająco do daty wysyłki daje odpowiedź, na której można polegać.
Rezerwacje twarde i miękkie
Rezerwacja twarda
Rezerwacja twarda odejmuje konkretną ilość od dostępności i uniemożliwia jej sprzedaż komukolwiek innemu. Towar pozostaje fizycznie na magazynie, lecz z punktu widzenia sprzedaży już go nie ma. Opisany podział jest ogólnym modelem stosowanym w systemach ERP i WMS, a nie deklaracją, że HermesSQL udostępnia oba typy pod tymi nazwami. Dla HermesSQL potwierdzone jest blokowanie towaru na określony czas z podaniem daty i godziny oraz automatyczne zwalnianie po jej upływie, co opisuje tekst o zamówieniach i rezerwacjach w systemie ERP.
Rezerwacja miękka
Rezerwacja miękka zapisuje zamiar, ale nie blokuje towaru. Wchodzi do bilansu jako sygnał popytu, więc planista widzi zbliżający się niedobór, a sprzedawca nadal może sprzedać ilość innemu klientowi. Takie podejście pasuje do ofert, które klient jeszcze rozważa. Przekształcenie oferty w zamówienie zamienia rezerwację miękką w twardą i dopiero wtedy ilość znika z dostępności.
| Cecha | Rezerwacja twarda | Rezerwacja miękka |
|---|---|---|
| Wpływ na dostępność | Zmniejsza ilość dostępną | Nie zmienia ilości dostępnej |
| Zastosowanie | Potwierdzone zamówienie klienta | Oferta lub zapytanie klienta |
| Ryzyko | Zamrożony towar, gdy zamówienie zostanie anulowane | Sprzedaż tej samej ilości dwa razy |
| Zwolnienie | Po terminie albo ręcznie | Automatyczne przy zmianie statusu oferty |
Wygasanie rezerwacji
Rezerwacja bez terminu blokuje towar do czasu ręcznej interwencji, a tej często brakuje. Termin ważności rezerwacji rozwiązuje problem, ponieważ zadanie okresowe zwalnia ilości po jego upływie i zwraca je do puli. Zbyt krótki termin generuje pracę sprzedawców, bo muszą odnawiać rezerwacje. Zbyt długi kumuluje martwe rezerwacje, które zaniżają bilans.
Rezerwacje partii i terminów ważności
Gdy towar podlega kontroli terminów ważności, rezerwacja wskazuje konkretną partię albo przynajmniej najkrótszy akceptowany termin. Klient z umową na towar ze świeżością powyżej trzydziestu dni nie przyjmie partii krótszej, więc bilans dla niego liczy się tylko z partii spełniających warunek. Zasady zarządzania terminami opisuje tekst o terminach ważności w HermesSQL.
Bilans w czasie i data niedoboru
Bilans narastający po datach
Bilans jednorazowy pokazuje sytuację na koniec horyzontu, lecz ukrywa niedobory w środku okresu. Dostawa za dwa tygodnie nie pomoże zamówieniu, które trzeba wysłać jutro. Z tego powodu ruchy planowane układa się na osi czasu i liczy bilans narastająco, po każdym zdarzeniu.
WITH Ruchy AS (
SELECT TerminDostawy AS Data, IloscPozostala AS Zmiana
FROM dbo.ZamowienieZakupuPozycja
WHERE TowarId = @TowarId
UNION ALL
SELECT TerminRealizacji, -Ilosc
FROM dbo.Rezerwacja
WHERE TowarId = @TowarId AND Status = 1
)
SELECT Data,
Zmiana,
@StanPoczatkowy
+ SUM(Zmiana) OVER (ORDER BY Data ROWS UNBOUNDED PRECEDING) AS Bilans
FROM Ruchy
ORDER BY Data;
Klauzula ROWS wymusza sumę po kolejnych wierszach. Bez niej domyślny zakres RANGE sumuje razem wszystkie zdarzenia z tą samą datą i bilans w środku dnia byłby nieczytelny. Składnię funkcji okna opisuje dokumentacja o klauzuli OVER w T-SQL.
Data pierwszego niedoboru
Pierwszy wiersz z bilansem ujemnym wyznacza datę, do której trzeba mieć dostawę. Od tej daty odejmuje się czas dostawy dostawcy i otrzymuje ostatni dzień na złożenie zamówienia. Sposób wyliczania tego terminu opisuje tekst o planowaniu zakupów materiałowych, który zaczyna od potrzeb produkcyjnych, a nie od zamówień klientów.

Konflikty rezerwacji i ich rozwiązywanie
Skąd bierze się konflikt
Konflikt występuje wtedy, gdy suma rezerwacji przekracza dostępną ilość. Ma dwa źródła. Pierwsze jest biznesowe: dostawa się opóźnia i rezerwacje, które miała pokryć, tracą pokrycie. Drugie jest techniczne: dwóch sprzedawców rezerwuje ostatnie sztuki w tej samej sekundzie, a oba zapisy przechodzą kontrolę, bo każdy widział stan sprzed zapisu drugiego.
Blokada przy zapisie rezerwacji
Konflikt techniczny eliminuje się na poziomie bazy. Zapis rezerwacji obejmuje odczyt stanu, odczyt sumy rezerwacji i wstawienie wiersza, więc musi przebiegać w jednej transakcji z blokadą, która uniemożliwia równoległy zapis dla tego samego towaru.
SET XACT_ABORT ON;
DECLARE @Stan DECIMAL(18,3), @Zarez DECIMAL(18,3);
BEGIN TRANSACTION;
SELECT @Stan = Ilosc
FROM dbo.StanMagazynowy WITH (UPDLOCK, HOLDLOCK)
WHERE TowarId = @TowarId;
SELECT @Zarez = ISNULL(SUM(Ilosc), 0)
FROM dbo.Rezerwacja
WHERE TowarId = @TowarId AND Status = 1;
IF @Stan - @Zarez >= @Ilosc
INSERT INTO dbo.Rezerwacja (TowarId, KlientId, Ilosc, Status)
VALUES (@TowarId, @KlientId, @Ilosc, 1);
ELSE
THROW 50001, N'Brak wolnej ilości do rezerwacji.', 1;
COMMIT TRANSACTION;
Podpowiedź UPDLOCK z HOLDLOCK zakłada blokadę aktualizacji na wierszu stanu do końca transakcji. Druga sesja czeka, aż pierwsza zatwierdzi rezerwację, i widzi już zmniejszoną dostępność. Znaczenie podpowiedzi opisuje strona o podpowiedziach tabelarycznych, a mechanizm blokad i wersjonowania wierszy omawia przewodnik po blokowaniu transakcji. Kosztem jest serializacja rezerwacji tego samego towaru, którą łagodzi krótki czas trwania transakcji.
Reguły rozstrzygania konfliktów
Konflikt biznesowy wymaga reguły, która wskaże zamówienia tracące pokrycie. Bez reguły decyzja zapada ręcznie i zależy od tego, kto pierwszy zauważył problem. Cztery reguły spotyka się najczęściej.
- Termin realizacji - pokrycie zachowują zamówienia z najbliższą datą wysyłki.
- Priorytet klienta - zamówienia klientów o wyższym priorytecie umowy tracą pokrycie na końcu.
- Kolejność zapisu - obowiązuje zasada pierwszeństwa, stosowana przy braku innych kryteriów.
- Decyzja ręczna - sprzedaż wskazuje zamówienie do odroczenia, gdy reguły automatyczne dają remis.
Ślad decyzji przy konflikcie
Każde odroczenie zamówienia z powodu konfliktu powinno zostawić ślad z nazwiskiem decydenta i regułą, według której zapadła decyzja. Do zapisu należy dołączyć dostępność z tamtej chwili. Zapis w historii dokumentu pozwala rozstrzygać reklamacje klientów, którzy nie dostali towaru w obiecanym terminie. Bez niego argumentem pozostaje pamięć sprzedawcy.
Od niedoboru do zamówienia do dostawcy
Zamówienie generowane z bilansu
Według opisu HermesSQL pozwala generować zamówienia do dostawców bezpośrednio z poziomu bilansu. Pozycje z ujemnym wynikiem trafiają do propozycji, planista uzupełnia dostawcę i termin, a system tworzy dokument. Dalszy przebieg, od zamówienia przez przyjęcie do faktury, opisuje tekst o zakupach w HermesSQL.
Obieg ma jedną pułapkę. Zamówienie do dostawcy wchodzi do bilansu jako dostawa w drodze, więc przy kolejnym przeliczeniu niedobór znika. Jeśli dostawa się opóźni, bilans nadal wygląda dobrze, dopóki ktoś nie porówna dat. Z tego powodu bilans w czasie, opisany wyżej, jest bezpieczniejszy niż jedna liczba.
Zamówienia zależne od dostawy
Część zamówień klientów obsługuje się bez zapasu, wprost z dostawy: towar przychodzi od dostawcy i od razu jedzie do odbiorcy. Taka pozycja ma powiązanie z zamówieniem do dostawcy i nie wchodzi do ogólnego bilansu jako wolna ilość. Bez takiego powiązania dostawa zwiększałaby ilość dostępną dla innych klientów i konflikt powstałby przy pierwszej próbie wydania.
Zapas minimalny w bilansie
Opis wspomina o uwzględnianiu minimalnych stanów magazynowych przy wyliczaniu zapotrzebowania. Zapas minimalny odejmuje się w bilansie jak rezerwację, ponieważ ta część towaru nie jest przeznaczona do sprzedaży. Bilans dodatni po uwzględnieniu progu oznacza więc towar rzeczywiście wolny. Podstawy pojęcia stanów omawia tekst o stanach magazynowych.
Bilans jako źródło raportów i powiadomień
Współpraca działów na jednym bilansie
Ten sam bilans obsługuje kilka działów. Sprzedaż i zakupy czytają ten sam bilans w różnym celu: pierwsza sprawdza, czy da się przyjąć zamówienie, drugie odczytują niedobory do zamówienia. Finanse wykorzystują wartości do analizy rentowności, jak wynika z opisu integracji bilansu z modułami ERP. Podstawą jest jedno źródło danych, ponieważ dwa różne zestawienia dostępności prowadzą do sprzecznych obietnic wobec klienta.

Powiadomienia o brakach
System generuje powiadomienia o konieczności złożenia nowych zamówień do dostawców, gdy bilans spada poniżej progu. Mechanizm kolejek powiadomień opisuje tekst o powiadomieniach ERP. Progi ustawia się per towar, bo materiał o długim czasie dostawy wymaga alarmu wcześniej niż towar dostępny od ręki.
Rezerwacje osierocone
Rezerwacja, której zamówienie klienta zostało anulowane albo zrealizowane, nadal zmniejsza bilans, jeśli nikt jej nie zwolnił. Takie zapisy wykrywa zapytanie kontrolne uruchamiane cyklicznie, na przykład jako zadanie SQL Agent.
SELECT r.Id, r.TowarId, r.Ilosc
FROM dbo.Rezerwacja AS r
LEFT JOIN dbo.ZamowienieKlientaPozycja AS z
ON z.Id = r.ZamowieniePozId
WHERE r.Status = 1
AND (z.Id IS NULL OR z.Status IN (3, 4));
Wartości 3 i 4 w przykładzie oznaczają umownie zamówienie zrealizowane i anulowane. Wynik zapytania trafia do osoby odpowiedzialnej za sprzedaż, która zwalnia rezerwacje albo wyjaśnia, dlaczego pozostają aktywne. Regularne czyszczenie utrzymuje bilans blisko rzeczywistej dostępności.
Raporty bilansowe i rotacja
Zestawienia bilansu na widokach SQL udostępnia platforma opisana w artykule o raportowaniu HermesSQL. Uzupełnia je analiza rotacji i zalegania towarów, bo towar o ujemnym bilansie i towar zalegający wymagają przeciwnych decyzji. Wpływ bilansu na wyniki sprzedaży opisuje z kolei strona o analizie sprzedaży w HermesSQL. Moduły magazynowe klasy WMS, które przydzielają rezerwacje do lokalizacji i partii, prezentuje strona producenta Studio WMS.net.




