Przejdź do głównej zawartości

Punkty decyzyjne

Katalog zdarzeń to jest to, co Stockly zgłasza. Ta strona opisuje kierunek odwrotny: nieliczne miejsca, w których decyduje kod integracji, a moduł się do tego stosuje.

Trzy kształty, coraz cięższe: odmówić wykonania operacji, zmienić kolejność decyzji, dołożyć zdolność.

BeforeStockOperationEvent wysyłane jest przed każdym ręcznym dodaniem, zdjęciem i przewozem — poza transakcją, więc nasłuchujący może wykonać własne zapisy bez wciągania ich do (ani powtarzania z) jednostki pracy Stockly. Wysyłane jest pod nazwą klasy, nie pod nazwą z kropkami.

public static function getSubscribedEvents(): array
{
return [BeforeStockOperationEvent::class => 'onBeforeStockOperation'];
}

Co udostępnia:

Getter
getProductId()artykuł
getOperation()add, remove albo move
getQuantity()zawsze dodatnie
getWarehouseId(), getBinLocationId()przy przyjęciu miejsce, do którego towar trafia; poza tym źródło
getTargetWarehouseId(), getTargetBinLocationId()drugi koniec przewozu
getMovementType()powód, który wołający zamierza zapisać
getOrderId(), getOperationId()dokument za tym stojący, o ile jest
getContext()

Dwa sposoby odmowy, oba wspierane na stałe:

// Pierwotny kontrakt: rzuć czymkolwiek, a dotrze do wołającego nietknięte.
throw new MyPluginException('not allowed here');
// Łagodniejsza droga: kod powodu, który front pokaże jako „niedozwolone", a nie jako awarię.
$event->deny('DERIVED_STOCK', 'This product carries no stock of its own.');

deny() zamienia się w jeden jednolity P2LAB_STOCKLY__STOCK__OPERATION_DENIED (HTTP 409) niosący podany kod i komunikat. Rzucony wyjątek przechodzi wprost, bo wtyczki polegają na dokładnym typie, którym rzucają. Wygrywa pierwsza odmowa; kolejne są pomijane.

Wzorcowe zastosowanie to współpracująca wtyczka odmawiająca przyjęcia fizycznego towaru na produkt, którego zapas wyprowadzany jest z innego produktu i musi zostać zerowy.

Cztery decyzje są udostępnione do nadpisania. Każda wysyłana jest synchronicznie, wewnątrz podejmowania decyzji, i niesie odpowiedź, do której Stockly doszło samo:

ZdarzenieRozstrzygaDomyślnieCzy wolno odpowiedzieć pustką?
p2lab_stockly.resolve_backorder_priorityktóre czekające pozycje dostaną przychodzący towar i w jakiej kolejnościnajstarszy popyt pierwszytak
p2lab_stockly.resolve_sourcing_warehousesktóre magazyny mogą obsłużyć popyt i w jakiej kolejnościprzypisanie kanału sprzedaży, według priorytetunie — popyt musi gdzieś mieszkać
p2lab_stockly.resolve_pick_locationsdo których binów wysyłany jest kompletującynajkrótszy termin, potem pełniejsza półkatak — znaczy „żaden z tych”
p2lab_stockly.resolve_putaway_locationgdzie odkładany jest przychodzący towarwłasna punktacja binów Stocklytak — znaczy „nie ma odpowiedniego miejsca”

Czytaj getResolved(), odpowiadaj przez setResolved():

public function onResolve(object $event): void
{
if (!method_exists($event, 'getResolved')) {
return;
}
$lines = $event->getResolved();
usort($lines, fn ($a, $b) => $this->tierOf($b['orderId']) <=> $this->tierOf($a['orderId']));
$event->setResolved($lines);
}

Brak odpowiedzi to stan wspierany, a nie ułomny: wartość domyślna jest dokładnie tym, co Stockly zdecydowałoby samo, więc „brak nasłuchującego” i „brak integracji” to jedno i to samo i nic nie trzeba konfigurować, żeby działało dalej.

Każdego nasłuchującego na decyzje wiążą trzy zasady.

Odpowiedź jest sprawdzana i odrzucana w całości. Pozycję wolno usunąć, wtedy czeka dalej, ale nie wolno jej wymyślić ani powtórzyć. Niepoprawna odpowiedź trafia do logu, a Stockly wraca do własnej decyzji; nigdy nie jest stosowana częściowo, bo w połowie zastosowany priorytet kieruje fizyczny towar w złe miejsce.

Nie wołaj z powrotem do Stockly. Żadnego StockService, żadnego uzgadniania. Nasłuchujący jest w środku podejmowania decyzji, zwykle w transakcji.

Żadnych efektów ubocznych. Zapisy należą do nasłuchującego na fakt, po zatwierdzeniu transakcji, i tam też są bezpieczne: wyjątek nasłuchującego na decyzję idzie w górę, zamiast zostać połknięty, bo wpływ na wynik jest tu całym sensem.

Interfejsy do zaimplementowania, rejestrowane znacznikiem serwisu. Dokładają coś, czego moduł nie ma, zamiast zmieniać coś, co ma.

InterfejsDokłada
ParcelSplitStrategyInterfacesposób rozkładania towaru po paczkach
CarrierProfileInterfaceprzewoźnika: jego limity, produkty i walidacje
CarrierManifestGatewayInterfacepowiadomienie przewoźnika o zamknięciu przekazania
ExtractionEngineInterfacesilnik czytający dokumenty przy imporcie

Wysyłkowa połowa przyjmuje też hooki po nazwie, a nie po interfejsie: p2lab.stockly.parcels.plan, p2lab.stockly.label.print i pokrewne. Opisuje je Integracja ze Stockly.

ChceszUżyj
nie dopuścić, żeby coś się wydarzyłoBeforeStockOperationEvent
zmienić, który z kilku poprawnych wyników zostanie wybranypasującego zdarzenia resolve_…
zareagować po fakciefaktu z katalogu
zrobić coś, czego moduł nie umie wcaleinterfejsu z tabeli wyżej

Najczęstszym błędem jest sięgnięcie po fakt tam, gdzie należy decyzja. Kiedy fakt jest publikowany, towar już się ruszył, a transakcja jest zamknięta; nie ma na co wpływać, jest co najwyżej co odnotować.