Zum Inhalt springen

Policy Hooks

Der Ereigniskatalog ist das, was Stockly meldet. Diese Seite ist die andere Richtung: die wenigen Stellen, an denen der Code der Integration entscheidet und das Modul gehorcht.

Drei Formen, in aufsteigendem Gewicht: einen Vorgang ablehnen, eine Entscheidung umsortieren, eine Fähigkeit ergänzen.

BeforeStockOperationEvent wird vor jedem manuellen Zugang, Abgang oder jeder Bewegung ausgelöst — außerhalb der Transaktion, ein Listener darf also eigene Schreibvorgänge ausführen, ohne in Stocklys Arbeitseinheit hineingezogen (oder mit ihr wiederholt) zu werden. Es wird unter seinem Klassennamen ausgelöst, nicht unter einem mit Punkten.

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

Was es bereitstellt:

Getter
getProductId()der Artikel
getOperation()add, remove oder move
getQuantity()immer positiv
getWarehouseId(), getBinLocationId()bei einem Zugang, wo die Ware landet; sonst die Quelle
getTargetWarehouseId(), getTargetBinLocationId()das ferne Ende einer Bewegung
getMovementType()der Grund, den der Aufrufer gleich festhalten wird
getOrderId(), getOperationId()der Beleg dahinter, sofern es einen gibt
getContext()

Zwei Arten abzulehnen, beide dauerhaft unterstützt:

// Der ursprüngliche Vertrag: werfen Sie irgendetwas, und es erreicht den Aufrufer unverändert.
throw new MyPluginException('not allowed here');
// Der sanftere Weg: ein Grundcode, den das Frontend als "nicht erlaubt" statt als Absturz zeigt.
$event->deny('DERIVED_STOCK', 'This product carries no stock of its own.');

deny() wird zu einem einheitlichen P2LAB_STOCKLY__STOCK__OPERATION_DENIED (HTTP 409), das den übergebenen Code und die übergebene Meldung trägt. Eine geworfene Exception geht unverändert hindurch, denn Plugins hängen an dem genauen Typ, den sie werfen. Die erste Ablehnung gewinnt; spätere werden übergangen.

Der übliche Anwendungsfall ist ein zusammenarbeitendes Plugin, das körperliche Ware an einem Produkt ablehnt, dessen Bestand aus einem anderen abgeleitet ist und auf null bleiben muss.

Vier Entscheidungen werden zur Überschreibung angeboten. Jede wird synchron innerhalb der Entscheidung ausgelöst und trägt die Antwort, zu der Stockly von selbst gekommen ist:

EventEntscheidetVoreinstellungDürfen Sie mit nichts antworten?
p2lab_stockly.resolve_backorder_prioritywelche wartenden Positionen eintreffenden Bestand bekommen und in welcher Reihenfolgeältester Bedarf zuerstja
p2lab_stockly.resolve_sourcing_warehouseswelche Lager einen Bedarf bedienen dürfen und in welcher Reihenfolgedie Zuweisung des Kanals, nach Prioritätnein — der Bedarf muss irgendwo leben
p2lab_stockly.resolve_pick_locationszu welchen Lagerplätzen ein Kommissionierer geschickt wirdfrühestes Ablaufdatum, dann das vollere Fachja — es heißt „keiner davon”
p2lab_stockly.resolve_putaway_locationwohin eintreffende Ware eingelagert wirdStocklys eigene Lagerplatzbewertungja — es heißt „nirgends passend”

Lesen Sie getResolved(), antworten Sie mit 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);
}

Gar nicht zu antworten ist ein unterstützter Zustand, kein herabgestufter: Die Voreinstellung ist genau das, was Stockly allein entschieden hätte, „kein Listener” und „keine Integration” sind also dasselbe, und es muss nichts konfiguriert werden, damit es weiter funktioniert.

Drei Regeln binden jeden Policy-Listener.

Die Antwort wird geprüft und als Ganzes verworfen. Ein Eintrag darf weggelassen werden, dann wartet er weiter, aber keiner darf erfunden oder wiederholt werden. Eine ungültige Antwort wird protokolliert, und Stockly fällt auf seine eigene Entscheidung zurück; sie wird nie teilweise angewandt, denn eine halb angewandte Priorität leitet körperliche Ware falsch.

Rufen Sie nicht in Stockly zurück. Kein StockService, kein Abgleich. Der Listener ist innerhalb der Entscheidung, meist innerhalb einer Transaktion.

Keine Nebenwirkungen. Schreibvorgänge gehören an einen Tatsachen-Listener, nach dem Commit, und dort sind sie auch sicher: Die Exception eines Policy-Listeners pflanzt sich fort, statt geschluckt zu werden, denn das Ergebnis zu beeinflussen ist der ganze Zweck.

Zu implementierende Schnittstellen, mit einem Service-Tag registriert. Diese ergänzen etwas, das das Modul nicht mitbringt, statt etwas zu ändern, das es tut.

SchnittstelleErgänzt
ParcelSplitStrategyInterfaceeine Art, Ware auf Pakete zu legen
CarrierProfileInterfaceeinen Dienstleister: seine Grenzen, seine Produkte, seine Prüfungen
CarrierManifestGatewayInterfaceeinem Dienstleister mitzuteilen, dass eine Übergabe abgeschlossen ist
ExtractionEngineInterfaceeine Lese-Engine für den PDF-Import

Die Versandhälfte nimmt außerdem Hooks über den Namen statt über eine Schnittstelle entgegen — p2lab.stockly.parcels.plan, p2lab.stockly.label.print und ihre Geschwister. Diese sind unter Stockly anbinden beschrieben.

Sie wollenVerwenden
verhindern, dass etwas geschiehtBeforeStockOperationEvent
ändern, welches von mehreren gültigen Ergebnissen gewählt wirddas passende resolve_…-Event
im Nachhinein reagiereneine Tatsache aus dem Katalog
etwas tun, was das Modul überhaupt nicht kanneine Schnittstelle von oben

Der häufigste Fehler ist, eine Tatsache zu verwenden, wo eine Richtlinie hingehört. Wenn eine Tatsache veröffentlicht wird, hat die Ware sich bewegt und die Transaktion ist geschlossen; es bleibt nichts mehr zu beeinflussen, nur noch etwas festzuhalten.