Dlaczego nie warto realizować zamówień 
w kolejności ich wpływania?

W sytuacji gdy dzienna ilość zamówień nie zbliża się do górnej granicy możliwości wydajnościowych magazynu, kolejkowanie zamówień jest rzeczą dość drugorzędną. Co się jednak stanie gdy ilość zamówień zacznie nagle rosnąć?

Najczęściej spotykanym w magazynach e-commerce schematem realizacji zamówień (kompletacja, pakowanie i wysyłka) jest kolejka FIFO (First In First Out), czyli realizowanie zamówień w kolejności ich wpływania. Przy niewielkiej ilości zamówień jest to najbardziej naturalna kolejka, bo zamówienie, które wpada do magazynu może być realizowane natychmiast. Niestety w przypadku dużej ilości zamówień, sztywne trzymanie się kolejki FIFO oznacza, że odbieramy sobie możliwość optymalizacji pracy magazynu i osiągnięcia jego maksymalnej wydajności.

Na przykładzie jednego z naszych klientów postaram się zaprezentować jak odejście od sztywnej kolejki FIFO pozwoliło nam poradzić sobie ze zwiększoną (nieraz prawie dwukrotnie) dzienną liczbą zamówień bez konieczności zwiększania ilości magazynierów przydzielonych do obsługi tego klienta.

Case Study

Nasz klient sprzedaje alkohole. Codziennie realizuje kilkaset zamówień, średnio zamówienie zawiera od 6 do kilkudziesięciu butelek. Wynika to z tego, że występują dwa typy zamówień. Część zamówień to tzw. zestawy miesiąca, wysyłane do odbiorców indywidualnych. Zestaw liczy zazwyczaj 6 do 12 butelek i w miesiącu jest kilka takich zestawów, czyli zamówienia te są bardzo powtarzalne. Drugi typ zamówień to zamówienia B2B, czyli zaopatrzenie restauracji, sklepów i innych punktów sprzedaży. Te zamówienia zawierają zazwyczaj od kilkudziesięciu do kilkuset butelek (wysyłki paletowe) i są praktycznie niepowtarzalne.

Dlaczego powtarzalność zamówień ma znaczenie dla magazynu?

Oczywiście dlatego, że jeśli wiemy, że np. 6 różnych butelek jest zawsze wydawanych razem, to mamy możliwość umieszczenia ich na sąsiadujących lokacjach, co ogromnie skraca czas kompletacji. Z kolei zlecenia niepowtarzalne oznaczają, że szansa jakiejkolwiek optymalizacji czasu kompletacji poprzez modyfikację rozmieszczenia towaru w magazynie jest co najmniej bardzo utrudniona a często wręcz niemożliwa.

Do tego dochodzi też sama struktura zamówień, czyli ich zawartość. Oczywistym jest, że zamówienie zawierające 6 czy nawet 12 butelek będzie się kompletowało znacznie szybciej niż zamówienie zawierające 200 lub więcej butelek. Kolejka FIFO jednak nie zwraca uwagi na takie „subtelności”, wg tej kolejki zamówienie to zamówienie i powinno być realizowane w takiej kolejności w jakiej trafiło do magazynu. Oznacza to, że pomimo oczywistych różnic, wszystkie zamówienia są traktowane tak samo, co z kolei prowadzi do tego, że magazyn nie jest w stanie uzyskać swojej maksymalnej wydajności.

Tak jak wspomniałem, w sytuacji gdy dzienna ilość zamówień nie zbliża się do górnej granicy możliwości wydajnościowych magazynu, kolejkowanie zamówień jest rzeczą dość drugorzędną (bo magazyn i tak jest w stanie realizować wszystkie zamówienia w terminie). Co się jednak stanie gdy ilość zamówień zacznie nagle rosnąć, aż do punktu gdy zaczynają się pojawiać ryzyko opóźnień w realizacji zamówień? Takie rzeczy zdarzają się zazwyczaj w okresie szczytowego ruchu. Każda branża ma swój gorący okres w różnych miesiącach, ale “gorączka przedświąteczna”, która zaczyna się zazwyczaj w listopadzie i trwa aż do samych Świąt jest najczęstszym przypadkiem. Tak też było w przypadku naszego klienta.

Analiza danych

Dosłownie w ciągu kilku dni w listopadzie dzienna ilość zamówień wzrosła nagle o ok. 30% i magazyn zaczął zgłaszać, że pojawiają się problemy z wydajnością. W oczywisty sposób wzbudziło to zaniepokojenie klienta, który spodziewał się, że w niektórych dniach ilość zamówień może wzrosnąć nawet o 100% w porównaniu do średniej z reszty roku. Nas zastanowiło jednak przede wszystkim dlaczego nagle stosunkowo jeszcze niewielki wzrost ilości zamówień praktycznie natychmiast zbliżył nas do niemalże maksymalnej wydajności? Z dnia na dzień praktycznie okazało się, że magazyn, który bez najmniejszego problemu radził sobie z terminową realizacją zamówień przez cały rok, najprawdopodobniej nie będzie w stanie obsłużyć zwiększonego ruchu przedświątecznego o ile nie podejmiemy jakichś działań natychmiast.

Zaczęliśmy więc weryfikować co tak naprawdę się zmienia. Sam wzrost dziennej ilości zamówień o 30% absolutnie jeszcze nie powinien powodować tak dużego zagrożenia jeśli chodzi o terminową realizację zamówień. W ciągu roku okresowo zdarzały się przecież dni gdy ilość zamówień wzrastała jednorazowo nawet i o ponad 50% (na przykład w ostatnich dniach miesiąca) i magazyn radził sobie z tym bez problemu. I tu wracamy do głównego motywu tej opowieści: każde zamówienie jest inne, a my starając się stosować kolejkę FIFO traktowaliśmy je tak jakby były równorzędne. Szybka analiza pokazała, że z tego 30% wzrostu, nieproporcjonalnie więcej wzrosła ilość zamówień handlowych (duże, niepowtarzalne) w porównaniu do zamówień dla odbiorców indywidualnych. Dało to nam sygnał, że nie powinniśmy patrzeć na dzienną ilość zamówień jako wyznacznik wydajności magazynu, bo zaczęła się zmieniać struktura zamówień i to niestety w niekorzystną stronę (z punktu widzenia magazynu). Zaczęło przybywać zamówień znacznie trudniejszych w realizacji i wymagających więcej czasu na kompletację.

Wkrótce nasz klient potwierdził, że rzeczywiście ich statystyki pokazują, iż przed świętami najprawdopodobniej najbardziej wzrośnie ilość zamówień handlowych dla sklepów i restauracji. Zaczęliśmy się zastanawiać czy przypadkiem nie oznacza to, że będziemy musieli przydzielić większą ilość magazynierów do obsługi tego klienta. Ale wtedy co z pozostałymi klientami, którzy przecież też w większości mają zwiększony ruch przedświąteczny? Czyżby trzeba było myśleć o zatrudnieniu dodatkowych pracowników?

Dokładniejsza analiza struktury zamówień pokazała, że choć wzrost ilości zamówień jest stosunkowo jeszcze niewielki, to praktycznie wszystkie zamówienia stają się trochę trudniejsze w realizacji. Z tych 30% dodatkowych zamówień, blisko 20% to były zamówienia handlowe. W dodatku w tych zamówieniach ilość butelek zwiększyła się o ok. 40%. Czyli przeciętne zamówienie handlowe, które liczyło zazwyczaj 50 butelek, teraz ma ich 70! Jakby tego było mało, wzrost ilości butelek nie dotyczył samej ilości (czyli jeśli do tej pory było 50 butelek Produktu A to teraz jest 70 butelek Produktu A) ale również różnych produktów (czyli na przykład zamiast samego produktu A w zamówieniu nagle mamy produkty od A do N). Każdy nowy produkt w zamówieniu wydłuża czas kompletacji bo dodaje jeszcze jedną lokację, do której magazynier musi podejść, żeby pobrać produkt. Widząc te wyniki szybko postanowiliśmy nie zajmować się rosnącą ilością zamówień dla klientów indywidualnych a skupić się na zamówieniach handlowych.

Teraz przyszła pora na kluczową analizę – jaka jest rzeczywista maksymalna wydajność magazynu w przypadku obsługi tego klienta, zakładając, że nic nie zmieniamy, tj. nie dodajemy dodatkowych pracowników. Co jest końcowym wyznacznikiem wydajności magazynu w zakresie realizacji zamówień? Oczywiście zdolność do pakowania zamówień. Magazyn nie jest w stanie zrealizować więcej zamówień niż jest w stanie ich zapakować w ciągu dnia. W naszym przypadku mieliśmy cztery stanowiska do pakowania, które były przeznaczone dla tego klienta. Szybkie testy pokazały, że czas pakowania zamówień indywidualnych oraz zamówień handlowych nie różni się tak bardzo w skali dnia (np. czas zamknięcia typowego zamówienia indywidualnego, czyli zaklejenie pudła i wydrukowanie listu wynosił ok. 15-20 sekund. Czas zamknięcia przeciętnego zamówienia handlowego wynosił też poniżej minuty i nie wydłużał się już znacząco nawet w przypadku zamówień paletowych, gdzie wynosił nieco ponad dwie minuty, bo tyle czasu potrzebowała maszyna, żeby ostrechować paletę). Przyjęliśmy więc najdłuższy czas pakowania, zbliżony do dwóch minut jako średni czas. Na tej podstawie okazało się, że zakładając ciągłą pracę przez 14 godzin (tyle godzin codziennie magazyn jest otwarty) tylko jedno stanowisko do pakowania byłoby w stanie obsłużyć 420 zamówień. Ponieważ stanowisk do pakowania mieliśmy cztery, oznaczało to, że maksymalnie w ciągu dnia bylibyśmy w stanie zamykać nawet 1680 zamówień, co znacznie przekracza zapotrzebowanie klienta, nawet podczas gorączki przedświątecznej. Zatem pakowanie samo w sobie w żaden sposób nie uniemożliwiało realizacji naszych zadań.

Kompletacja zamówień

Tutaj różnice pomiędzy zamówieniami indywidualnymi a handlowymi były już drastyczne. O ile jeden magazynier był w stanie skompletować nawet 10 zamówień indywidualnych w ciągu ok. 13-15 minut, o tyle ten sam magazynier potrzebował nawet ponad godzinę, żeby skompletować jedno zamówienie handlowe. W najbardziej drastycznych przypadkach (zamówienia liczące ok. 100 szt przy czym z dużą ilością różnych produktów) czas kompletacji mógł wynosić nawet i blisko dwie godziny. Znaleźliśmy nasz problem. Potężna dysproporcja czasu potrzebnego na skompletowanie zamówienia a na jego spakowanie oznaczała, że musimy zupełnie odejść od przyjętych szablonów pracy.

W ciągu roku zazwyczaj rozpoczynaliśmy kompletację zamówień ok. godziny 8-9 rano, delegując do tej pracy dwóch magazynierów. W ciągu kilku godzin zazwyczaj byli oni w stanie stworzyć wystarczającą kolejkę skompletowanych zamówień i jedno lub dwa stanowiska do pakowania były uruchamiane ok. godziny 12-13, po czym pracowały aż do zamknięcia magazynu, czyli do 21:00. Również o 12:00-13:00 do kompletacji zamówień przystępował kolejny magazynier (w zależności od potrzeb – nawet kilku). Dzięki temu byliśmy w stanie realizować spływające zamówienia mniej więcej wg kolejki FIFO, przynajmniej w zakresie kompletacji.

Dysproporcja czasu potrzebnego na kompletację i pakowanie oznaczała, że w grudniu nie możemy liczyć na taką stabilność podziału zadań. Po pierwsze, jeśli chcieliśmy obsłużyć rosnącą ilość bardziej czasochłonnych zamówień, oznaczało to, że musimy znacznie bardziej kreatywnie przydzielać magazynierów do zadań, jak również minimalizować ilość jednocześnie uruchomionych stanowisk do pakowania. Dzięki temu mielibyśmy więcej osób mogących kompletować zamówienia. Wcześniej obliczyliśmy, że jedno stanowisko do pakowania w ciągu 14 godzin jest w stanie zamknąć ok. 420 zamówień. Wiedzieliśmy, że dzienna ilość zamówień raczej nie powinna przekraczać 1000, nawet biorąc pod uwagę zwiększony ruch. Oznacza to, że cztery stanowiska do pakowania były w stanie zamykać 1000 zamówień w około 8 godzin. W tym zakresie mieliśmy spory zapas czasowy.

Wiedząc to, postanowiliśmy przyjąć zasadę, że:

dopóki się da to będziemy pracować tylko z jednym czynnym stanowiskiem pakowania, przeznaczając jak najwięcej magazynierów do zadań kompletacji.

Dalsze obliczenia pokazały, że aby zapewnić ciągłą pracę jednego stanowiska pakowania, w przypadku czasochłonnych zamówień handlowych, potrzebowalibyśmy co najmniej czterech lub pięciu magazynierów kompletujących zamówienia. Oczywistym stało się, że nie możemy sobie dłużej pozwolić na zachowanie kolejki FIFO na etapie kompletacji. Ponieważ zamówienia handlowe kompletowało się dużo dłużej niż indywidualne, musieliśmy zacząć dobierać zamówienia do kompletacji tak, żeby nigdy nie dopuścić do sytuacji, że stanowisko pakowania nie ma co robić.

Zaczęliśmy więc równoważyć ilość aktualnie kompletowanych zamówień tak, żeby skutecznie zapełniać kolejkę aktualnie czynnych stanowisk do pakowania. Oznaczało to, że jeśli np. dwóch magazynierów „utknęło” na kompletowaniu zamówień handlowych, trzeci musiał zająć się kompletacją szybkich zamówień indywidualnych. W ciągu dnia najwyższy priorytet otrzymywały zamówienia handlowe, niezależnie od tego kiedy wpłynęły do magazynu a zamówienia indywidualne były kompletowane głównie jako uzupełnienie bufora kolejki do pakowania gdy zaczynała się wyczerpywać.

Podsumowanie

Całkowite uwolnienie się od sztywnych wymogów kolejki FIFO pozwoliło na znacznie bardziej elastyczne i kreatywne realizowanie zadań magazynowych, dzięki czemu udało nam się opanować w sumie blisko 130% procentowy wzrost sprzedaży klienta, mierzony w wydanych butelkach. Dodatkowo okazało się, że pomimo pierwszego wrażenia, że tym razem nie obejdzie się bez konieczności głębszych zmian jaką byłaby decyzja o zatrudnieniu dodatkowych pracowników, nawet stosunkowo skomplikowany problem logistyczny znalazł rozwiązanie w ramach istniejących zasobów. Wymagało to głównie podważenia zasady, którą domyślnie nieraz uważa się za kluczową – zrezygnowania ze sztywnych reguł kolejkowania zamówień do kompletacji.


O Autorze:

image

Komentarze

Debug turned on!

0.42 select * from `eventjuicer_hosts` where `eventjuicer_hosts`.`host` = ? limit 1
0.27 select * from `bob_event_groups` where `bob_event_groups`.`id` = ? and `bob_event_groups`.`id` is not null limit 1
0.29 select * from `bob_organizers` where `bob_organizers`.`id` = ? limit 1
0.34 select * from `eventjuicer_settings` where `eventjuicer_settings`.`settingable_id` = ? and `eventjuicer_settings`.`settingable_id` is not null and `eventjuicer_settings`.`settingable_type` = ?
0.28 select * from `eventjuicer_settings` where `eventjuicer_settings`.`settingable_id` = ? and `eventjuicer_settings`.`settingable_id` is not null and `eventjuicer_settings`.`settingable_type` = ?
0.25 select * from `eventjuicer_texts` where `eventjuicer_texts`.`textable_id` = ? and `eventjuicer_texts`.`textable_id` is not null and `eventjuicer_texts`.`textable_type` = ?
0.19 select * from `eventjuicer_texts` where `eventjuicer_texts`.`textable_id` = ? and `eventjuicer_texts`.`textable_id` is not null and `eventjuicer_texts`.`textable_type` = ?
0.23 select * from `eventjuicer_pages` where `eventjuicer_pages`.`pageable_id` = ? and `eventjuicer_pages`.`pageable_id` is not null and `eventjuicer_pages`.`pageable_type` = ?
0.18 select * from `eventjuicer_pages` where `eventjuicer_pages`.`pageable_id` = ? and `eventjuicer_pages`.`pageable_id` is not null and `eventjuicer_pages`.`pageable_type` = ?
0.11 select * from `editorapp_posts` where `editorapp_posts`.`id` = ? limit 1
0.08 select * from `editorapp_post_meta` where `editorapp_post_meta`.`post_id` in (?)
0.06 select * from `eventjuicer_users` where `eventjuicer_users`.`id` in (?)
0.08 select * from `editorapp_posts` where `group_id` = ? and `is_published` = ? order by `published_at` desc limit 10 offset 0
0.11 select * from `editorapp_post_meta` where `editorapp_post_meta`.`post_id` in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
0.05 select * from `eventjuicer_users` where `eventjuicer_users`.`id` in (?)
0.08 select `bob_tags`.*, `editorapp_post_tag`.`xref_id` as `pivot_xref_id`, `editorapp_post_tag`.`tag_id` as `pivot_tag_id`, `editorapp_post_tag`.`group_id` as `pivot_group_id`, `editorapp_post_tag`.`organizer_id` as `pivot_organizer_id`, `editorapp_post_tag`.`published_at` as `pivot_published_at`, `editorapp_post_tag`.`is_published` as `pivot_is_published` from `bob_tags` inner join `editorapp_post_tag` on `bob_tags`.`id` = `editorapp_post_tag`.`tag_id` where `editorapp_post_tag`.`xref_id` = ?
3.02