1. Po co to jest
Magazynier po przyjęciu ma dostać adres, a nie decyzję. Sugestia odłożenia to jeden wiersz na ekranie: lokalizacja, do której ma zawieźć towar.
Bez niej odkładanie jest wiedzą w głowie — gdzie zwykle stoi ten towar, gdzie jest miejsce, gdzie akurat nie zajrzał kierownik. Nowy pracownik tej wiedzy nie ma, a stały nie zawsze jest w pracy. Podpowiedź zamienia tę wiedzę w regułę, którą da się zmienić w jednym miejscu.
Sterowanie jest trzystopniowe i po każdy kolejny stopień sięgasz dopiero wtedy, gdy poprzedni nie wystarcza:
| stopień | czym | kiedy sięgasz |
|---|---|---|
| 1. bez kodu | stała lokalizacja towaru, lokalizacje przypisane, Kolejność strefy, wymiary lokalizacji | zawsze zacznij tutaj — to załatwia większość wdrożeń |
| 2. własny filtr | cecha StrefaOdlozenia — filtr kandydatów po strefie | „odkładamy wyłącznie do magazynowania” |
| 3. własny wybór | cecha SugestiaOdlozenia — wskazanie konkretnej lokalizacji | „towary sypkie tylko na dolne półki” |
Stopnie 2 i 3 to cechy algorytmiczne enovy — kilka linijek kodu, które dodatek woła w trakcie liczenia podpowiedzi. Zakłada je gotowa akcja, opisują je rozdziały 4 i 5.
Kolejność strefy, więc warto znać obie.2. Jak wybiera się lokalizację
Pięć kroków, zawsze w tej samej kolejności. Pierwszy, który da odpowiedź, kończy sprawę.
2.0 Lokalizacje przypisane towarowi
Na kartotece towaru przypisujesz lokalizacje, a jedną z nich w każdym magazynie możesz oznaczyć jako domyślną. Te dwie rzeczy działają zupełnie inaczej.
| na kartotece | co robi przy odkładaniu |
|---|---|
| domyślna (stała lokalizacja) | kończy sprawę — towar jedzie tam bez pytania reguły i bez pytania cech |
| przypisana, bez oznaczenia domyślnej | idzie na początek listy kandydatów — wygrywa wewnątrz każdego kroku reguły, ale reguła dalej decyduje |
| nieprzypisana | zwykły kandydat — o kolejności decyduje numer strefy, a wewnątrz strefy adres regału |
Przypisanie wyprzedza nawet numer strefy: przypisana lokalizacja w namiocie (strefa 2) zostanie zaproponowana przed nieprzypisaną w hali (strefa 1). Mówi bowiem o tym towarze, a numer strefy tylko o kolejności zapełniania budynku. Numer strefy rozstrzyga dopiero wewnątrz każdej z grup — gdy towar ma przypisane lokalizacje i w hali, i w namiocie, pierwsza będzie ta z hali. Tak samo zachowuje się stała lokalizacja, która numeru strefy nie ogląda w ogóle.
2.1 Reguła dodatku — trzy przejścia po liście
To jest krok 5 z diagramu, czyli zachowanie bez żadnej cechy. Kandydaci są już posortowani (przypisane towarowi, potem numer strefy, potem adres regału) i reguła bierze pierwszego, który się mieści:
| przejście | bierze |
|---|---|
| krok 0 — filtr | zostają wyłącznie lokalizacje ze stref składowania (patrz Kolejność strefy) |
| 1. konsolidacja | lokalizacja, w której ten towar już leży i mieści się całość |
| 2. pierwsza wolna | lokalizacja pusta albo taka, w której mieści się całość |
| 3. mieści częściowo | gdy nic nie mieści całości — konsolidacja przed pustą |
„Mieści częściowo” znaczy: jest tam wolne miejsce, ale mniej, niż wynosi odkładana ilość — towar wejdzie tylko w części. Reguła rozróżnia trzy stany i traktuje je zupełnie inaczej:
| stan lokalizacji | wolne miejsce | co robi reguła |
|---|---|---|
| mieści całość | tyle, ile trzeba, albo więcej — także wtedy, gdy pojemności nikt nie zadeklarował | bierze od razu |
| mieści częściowo | jakieś jest, ale mniej niż trzeba | zapamiętuje jako zapasową i szuka dalej |
| pełna | zero albo mniej (przepełniona) | pomija zupełnie — nigdy nie zostanie zaproponowana |
Lokalizacja mieszcząca częściowo wraca do gry dopiero w kroku 3, czyli wtedy, gdy w całej hali nic nie mieści całości. Lepiej dać magazynierowi adres i ostrzec o przepełnieniu, niż odpowiedzieć „nie ma miejsca” i zostawić go z paletą na korytarzu.
0 znaczy „nikt nie zmierzył”, więc taka lokalizacja przechodzi każdy warunek pojemnościowy. Dopóki nie wprowadzisz wymiarów, cała reguła sprowadza się do „konsolidacja, potem pierwsza pusta”.2.2 Kolejność kandydatów to nie trasa
„Kolejność listy” znaczy na tej stronie zawsze jedno: kolejność, w jakiej reguła rozważa kandydatów — przypisane towarowi, potem numer strefy, potem adres regału. To kolejność wyboru, a nie kolejność, w jakiej magazynier obejdzie halę.
| co ustala | czym |
|---|---|
| Dokąd pojedzie towar — jeden adres na pozycję | ta strona |
| W jakiej kolejności magazynier obejdzie wskazane adresy | Trasa przez magazyn |
TrasaMagazynu nie bierze udziału w wyborze. Klucz trasy liczy się dopiero dla lokalizacji, którą sugestia już wskazała — najpierw wybór, potem kolejność. Choćbyś napisał najbardziej wymyślną trasę, nie zmieni ona ani jednego adresu na liście odłożenia; zmieni tylko to, w jakiej kolejności magazynier je obejdzie.SugestiaOdlozenia. Numer strefy jest przy tym jedyną daną, którą czytają oba mechanizmy naraz.3. Ustawienia bez kodu — zacznij stąd
Trzy rzeczy do ustawienia, zanim w ogóle sięgniesz po cechę algorytmiczną. U większości klientów to jest całe wdrożenie sugestii.
Stała lokalizacja towaru
- gdzie
- kartoteka towaru → cecha
Lokalizacja - zakres
- jedna na magazyn — lokalizacja z innego magazynu nie jest sugestią dla tego zasobu
- znaczenie
- domysł, nie żądanie
Towar ze stałą lokalizacją jedzie tam bez pytania kogokolwiek — ani reguły, ani Twoich cech. Ale gdy się nie mieści, sterowanie wraca do reguły i towar dostaje inną lokalizację; w dzienniku zostaje ślad z nazwą towaru i metrami. Przypisania nikt nie kasuje, więc gdy miejsce się zwolni, stała zadziała znowu sama.
Kolejność strefy
- gdzie
- element słownika Strefa → cecha
Kolejność strefy(liczba całkowita) - kto zakłada
- akcja menu Handel → Magazyn → Kolektory → Czynności → WebAPI → Konfiguracja
- zakres
- per strefa — numerujesz od 1
| wartość | co robi z odkładaniem |
|---|---|
| 1, 2, 3… | kolejność zapełniania: strefa 1 pierwsza, do 2 towar trafia dopiero, gdy w 1 nie ma miejsca |
pusta / 0 | strefa nie jest proponowana — to przystanek procesu (przyjęcie, kontrola, wydanie), nie półka |
0, więc wszystkie strefy miałyby zero i sugestia zniknęłaby w całości — dlatego filtr do pustej listy jest ignorowany. Ta sama zasada rządzi cechą StrefaOdlozenia.Wymiary lokalizacji i towarów
Pojemność lokalizacji i objętość towaru decydują o tym, czy „mieści się całość”. Dopóki ich nie ma, reguła nie ma czym mierzyć — działa, ale sprowadza się do konsolidacji i pierwszej pustej lokalizacji. To bywa wystarczające; wymiarowanie hali zaczyna się opłacać dopiero tam, gdzie realnie brakuje miejsca.
4. Cecha StrefaOdlozenia — własny filtr
Filtruje kandydatów po symbolu strefy. Najczęstsza potrzeba wdrożeniowa brzmi „nie odkładaj do strefy przyjęcia”, a nie „wybierz mi lokalizację”.
- gdzie
- Narzędzia → Opcje → Systemowe → Definicje cech, tabela
CfgNodes, zakładka Algorytm - kto zakłada
- akcja menu Magazyn → Kolektory → Czynności → WebAPI → Cechy sugestii odłożenia
- typ
- Tekst
- zakres
- globalny — ten sam kod dla każdego magazynu, rozdziel je po
magazyn.Symbol
public string Get_Feature_StrefaOdlozenia(
Soneta.Towary.Towar towar,
Soneta.Magazyny.Magazyn magazyn,
System.Collections.Generic.IReadOnlyList<EndIF.Magazyn.Lokalizacje.KandydatGniazda> kandydaci,
double potrzeba)
| zwracasz | znaczy |
|---|---|
"M" | wybieraj wyłącznie z lokalizacji strefy M |
"M|K" | kilka stref — rozdzielasz znakiem | |
| pusty tekst | bez filtra |
| symbol spoza hali | filtr pominięty — jeden wpis w dzienniku, sugestia liczy się dalej |
Zwracając samą strefę, zostawiasz całą regułę wyboru dodatkowi — nie musisz jej u siebie odtwarzać, a odtworzona rozjechałaby się z produktem przy pierwszej poprawce.
5. Cecha SugestiaOdlozenia — własny wybór
Wskazuje konkretną lokalizację i jej zdanie jest nadrzędne. Sięgasz po nią, gdy potrzebujesz reguły, której nie da się wyrazić strefą.
- gdzie
- Narzędzia → Opcje → Systemowe → Definicje cech, tabela
CfgNodes, zakładka Algorytm - kto zakłada
- akcja menu Magazyn → Kolektory → Czynności → WebAPI → Cechy sugestii odłożenia
- typ
- Liczba całkowita
- zakres
- globalny — ten sam kod dla każdego magazynu
public int Get_Feature_SugestiaOdlozenia(
Soneta.Towary.Towar towar,
Soneta.Magazyny.Magazyn magazyn,
System.Collections.Generic.IReadOnlyList<EndIF.Magazyn.Lokalizacje.KandydatGniazda> kandydaci,
double potrzeba)
Zwracasz LokId jednego z podanych kandydatów. Po założeniu nic się nie zmienia: wstawiony algorytm jest kopią reguły dodatku, więc wybór zostaje ten sam. Zmienia się tylko to, kto go liczy — od tej chwili kod z bazy, nie z DLL.
return 0; znaczy „żadna lokalizacja”, a NIE „policz to za mnie”. Od istnienia tej cechy rządzi Twój kod: cokolwiek zwróci, reguła dodatku nie dolicza się po cichu, bo dwie reguły liczące po kolei to znowu dwie prawdy o tym samym. Powrót do reguły dodatku = skasowanie definicji cechy; samo wyczyszczenie ciała metody da brak sugestii dla wszystkiego.Co dostajesz w kandydatach
| pole | znaczenie |
|---|---|
LokId | to zwracasz |
Skrot | adres {rząd}-{pion}-{poziom}, np. A-01-00 |
Strefa | symbol strefy; pusty, gdy lokalizacja strefy nie ma |
KolejnoscStrefy | numer strefy; 0 = nie jest miejscem składowania |
Kod | pełny adres {magazyn}-{strefa}-{rząd}-{pion}-{poziom}, np. F-M-A-01-00; To po nim idzie kolejność wewnątrz strefy — czyli po regale: rząd, pion, poziom |
SaZasoby | czy cokolwiek w gnieździe leży |
MaTenTowar | czy leży tu już ten towar — warunek konsolidacji |
Przypisana | czy ta lokalizacja jest przypisana temu towarowi na kartotece; takie stoją na początku listy |
Objetosc | pojemność w m³; 0 = niezadeklarowana, czyli brak limitu |
WolneMiejsce | ile jeszcze wejdzie |
Kod (adres regału) — więc sortowania nie musisz odtwarzać: wystarczy wziąć pierwszego pasującego. Jeżeli cecha StrefaOdlozenia też istnieje, kandydaci są tu już po jej filtrze.Lokalizacja spoza podanej listy jest odrzucana: liczy wtedy reguła dodatku, a w dzienniku zostaje ślad. Bez tej bramki dałoby się wskazać lokalizację, której zapis i tak nie przyjmie — czyli rozminąć to, co magazynier widzi, z tym, co naprawdę się zapisze.
6. Gotowe warianty
Wszystkie siedzą w komentarzu wstawianym do cechy przy zakładaniu. Poniżej te, po które sięga się najczęściej.
Reklamacje osobno — StrefaOdlozenia
Towar oznaczony cechą idzie do strefy kontroli, reszta do magazynowania:
if (Equals(towar.Features["Reklamacja"], true)) return "K";
return "M";
Inny magazyn, inna reguła — StrefaOdlozenia
Cecha jest globalna, więc ten sam kod wykonuje się dla każdego magazynu; rozdzielasz je po symbolu:
if (magazyn.Symbol == "SERWIS") return "K";
return "M";
Towary sypkie na dolne poziomy — SugestiaOdlozenia
Worka nie wnosi się na czwartą półkę. Skrot ma format {rząd}-{pion}-{poziom}, a poziomy liczą się od 00 — -00 to podłoga:
if (Equals(towar.Features["Sypki"], true))
foreach (var kandydat in kandydaci)
if (kandydat.Skrot.EndsWith("-00") || kandydat.Skrot.EndsWith("-01"))
return kandydat.LokId;
kandydaci zawiera jeszcze lokalizacje strefy przyjęcia i wydania, więc Twój foreach mógłby wskazać towarowi przystanek procesu zamiast półki. Gdy żaden wyjątek nie pasuje, pętla nic nie zwraca i sterowanie idzie do reguły niżej — dokładnie tak, jak ma być.StrefaOdlozenia, nie tutaj. Ona filtruje kandydatów wcześniej, więc lokalizacja z odfiltrowanej strefy w ogóle nie dojdzie do tego kodu. Sprawdź też, czy zamiast kodu nie wystarczy numer strefy — odsunięcie namiotu za halę robi się liczbą.7. Czego cechy nie obejmują
Dwie dziury w zasięgu, obie świadome. Trzeba je znać, bo inaczej sprawdzasz swój algorytm przyciskiem, którego on nie dotyczy — i nie masz jak się domyślić dlaczego.
Towar ze stałą lokalizacją
Gdy towar ma stałą lokalizację w tym magazynie i się w niej mieści, adres wynika z kartoteki i żadna z cech nie jest wołana. Chcesz, żeby szedł algorytmem — zdejmij mu stałą lokalizację.
Odłożenie z wypełnionym parametrem „Rodzaj”
Przyciski „Odłóż pozycje / zasoby / z listy” i „Relokuj” w enovie, a także to samo pole w żądaniu kolektora, przyjmują rodzaj: Konsolidacja, Pierwsza dostępna, Stała lokalizacja. Rodzaj jest świadomym żądaniem magazyniera, a cecha algorytmem podpowiedzi — więc podanie rodzaju znaczy „tym razem nie podpowiadaj”.
| ścieżka | pyta cechy? | filtr stref składowania? | przypisane pierwsze? |
|---|---|---|---|
| kolumna „Sugestia”, „Odłóż wg sugestii”, kolektor | tak | tak | tak |
| odłożenie z wypełnionym rodzajem | nie | tak | nie |
| towar ze stałą lokalizacją | nie | tak | nie dotyczy — stała kończy sprawę |
Dlatego strefa bez numeru unieważnia nawet stałą lokalizację towaru — a ścieżka rodzaju „Stała lokalizacja” wtedy odmawia, z nazwą lokalizacji i strefy, zamiast po cichu podstawić inną. Magazynier nie może widzieć na ekranie
A-01-00, a mieć zapis do B-01-00; jedyną dopuszczalną alternatywą jest odmowa, która mówi dlaczego.
8. Pułapki
Zmieniłem algorytm i nic się nie stało
Skompilowany algorytm siedzi w pamięci procesu, więc działające WebAPI liczy dalej starym ciałem, a dziennik milczy — nic się przecież nie wywróciło.
Założenie i skasowanie cechy działa natychmiast. ⚠ Ale skasowanie i założenie jej od nowa z poprawionym kodem — już nie: nazwa ta sama, więc proces bierze ciało ze swojego cache’u.
Liczba argumentów musi zgadzać się co do jednego
FeatureDefinition.CheckArgs porównuje ją z sygnaturą metody, więc zostaw sygnaturę dokładnie taką, jaką wstawiła akcja. Skreślenie argumentu, którego nie używasz, tak samo jak dopisanie własnego, sprawi że cecha przestanie działać — nie błędem, tylko cichą degradacją do reguły dodatku, ze śladem w dzienniku. Nieużywanych argumentów po prostu nie ruszaj.
9. Diagnostyka
Co dodatek mówi sam
Każde odrzucenie algorytmu zostawia ślad w dzienniku modułu. Przedrostek mówi, która z dwóch cech zawiodła:
| wpis | znaczy |
|---|---|
[SugestiaOdlozenia] „cecha … nie dała wyniku (wyjątek) — użyto reguły wbudowanej” | algorytm się wywrócił albo ma złą liczbę argumentów |
[SugestiaOdlozenia] „cecha … wskazała lokalizację N spoza listy kandydatów” | zwrócone LokId nie należy do podanych kandydatów |
[StrefaOdlozenia] „cecha … zwróciła „X”, ale żadna z N lokalizacji nie należy do tych stref” | symbol strefy nie istnieje w tej hali — filtr pominięty |
Wpis niesie wyjątek źródłowy, a nie samo opakowanie: platforma woła algorytm refleksją, więc bez rozpakowania każdy błąd wykonania czytałby się identycznie („Exception has been thrown by the target of an invocation”). W dzienniku zobaczysz obie warstwy, rozdzielone strzałką.
Gdy reguła nie ma lokalizacji
„Żadna lokalizacja” jest legalną odpowiedzią — tak brzmi kontrakt cechy (return 0) i tak samo kończy się wyczerpanie miejsca w hali. Odłożenie całej listy nie zatrzymuje się na takiej pozycji: reszta idzie na półki, a te pozycje zostają, z komunikatem, który wymienia towary:
Komunikat nie proponuje wymuszenia przepełnienia, bo ponowienie niczego nie zmieni — lokalizacji nadal nie ma. Pytanie, którego zgoda nie załatwia, uczy klikania na ślepo.
