Skip to main content

Picking list canceled

Fires when picking lines are canceled: when a picking list (a WMSPickingRoute picking route) is canceled as a whole and that cancels at least one of its lines, or when an individual line of a picking list is canceled. The payload lists only the lines the cancellation canceled. These are the picking lists of the inventory picking-list process (for example, sales order and transfer order picking lists handled through picking list registration); work in warehouse management (WHS) is covered by Warehouse Work Completed and Warehouse Picking Completed instead. Downstream systems can use this event to stop pick tasks in an external warehouse or automation system, release reserved pick capacity, or alert customer service.

Event classMGCLatticePickingListCanceledBusinessEvent
Contract classMGCLatticeOrderPickingBusinessEventContract (shared with Transfer order picking list created)
CategoryInventory management
ModuleModuleAxapta::Inventory
Label IDsPickingListCancelledBusinessEventName / PickingListCancelledBusinessEventDescription
TriggerWMSPickingRoute.cancel() when it cancels at least one line (whole picking list), or WMSOrderTransType_Output_OrderPick.cancel() with _checkRoute = true (single line)

Trigger / Hook​

  • Whole picking list: extension class MGCLatticeWMSPickingRoute_Table_Extension, [ExtensionOf(tableStr(WMSPickingRoute))], CoC method public void cancel().
    • The standard cancel() does nothing when the route has no record, is already Canceled, or is physically updated (Picked, Staged, Loaded or Complete); otherwise it cancels every line that is Registered, Activated or Started.
    • Before next cancel(), when the event is activated and the route is one the standard method acts on, the extension records the route's Registered, Activated and Started lines. After next cancel(), it keeps those of them that are now Canceled and sends one event listing exactly those lines. When no line was canceled, nothing is sent.
    • Lines that were canceled earlier on their own (and raised their own event then) and lines that are already picked are never listed.
  • Single line: handler class MGCLatticePickingListCancelledEventHandlers, [PostHandlerFor(classStr(WmsOrderTransType_Output_OrderPick), methodStr(WmsOrderTransType_Output_OrderPick, cancel))] on public static void WmsOrderTransType_Output_OrderPick_Post_cancel(XppPrePostArgs _args). The event is sent only when the method's _checkRoute argument is true, which is the case when a line is canceled on its own; the standard callers of that path cancel only a line that can be canceled, and the method always sets the line to Canceled. The event is built with newFromWMSOrderTrans(orderTrans) from the line the order-pick type object holds.
  • No double events: the standard WMSPickingRoute.cancel() cancels each line with _checkRoute = false, so canceling a whole picking list sends one route-level event, not one event per line. Canceling several lines individually sends one event per line.
  • Transaction: WMSPickingRoute.cancel() runs its own ttsbegin/ttscommit, and the event is sent after it. When a cancellation runs inside a larger transaction, the event is written to the business events commit log inside it and is delivered only if that transaction commits.
  • Enablement gate: both hooks check BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticePickingListCanceledBusinessEvent)).
public void cancel()
{
Set openLineRecIds;

// The cached activation check comes first; isRouteCancellable reads the route's physical updates.
if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticePickingListCanceledBusinessEvent))
&& MGCLatticePickingListCanceledBusinessEvent::isRouteCancellable(this))
{
openLineRecIds = MGCLatticePickingListCanceledBusinessEvent::openLineRecIds(this.PickingRouteID);
}

next cancel();

if (openLineRecIds && openLineRecIds.elements() > 0)
{
Set cancelledLineRecIds = MGCLatticePickingListCanceledBusinessEvent::cancelledLineRecIds(this.PickingRouteID, openLineRecIds);

if (cancelledLineRecIds.elements() > 0)
{
MGCLatticePickingListCanceledBusinessEvent::newFromCancelledRouteLines(this, cancelledLineRecIds).send();
}
}
}

Payload Contract​

One row per [DataMember], in declaration order. MGCLatticeOrderPickingBusinessEventContract is shared with Transfer order picking list created; the payload carries no cancellation flag: the event id says the lines were canceled. Header fields come from the picking route: the canceled route, or for a single-line cancel, the route of the canceled line (WMSOrderTrans.wmsPickingRoute()).

JSON fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaIdWMSPickingRoute.dataAreaIdCompany of the picking list
pickingRouteIdPicking RouteWMSPickingRouteIDWMSPickingRoute.pickingRouteIDPicking list (route) number
orderNumberOrder NumberInventTransRefIdWMSPickingRoute.transRefIdSource order, for example the sales order or transfer order
transTypeTransaction Typeintenum2int(WMSPickingRoute.transType)InventTransType value, for example 0 = Sales, 21 = TransferOrderShip
transTypeNameTransaction Type Namestrenum2Symbol(enumNum(InventTransType), ...)Symbol, for example Sales
routeStatusPicking Route Statusintenum2int(WMSPickingRoute.ExpeditionStatus)Status of the picking route after the cancellation, as the WMSExpeditionStatus integer (20 = Canceled when every line of the route is now canceled)
routeStatusNamePicking Route Status Namestrenum2Symbol(enumNum(WMSExpeditionStatus), routeStatus)Symbol of routeStatus, for example "Cancelled" (the Microsoft enum symbol)
deliveryModeIdDelivery ModeDlvModeIdWMSPickingRoute.DlvModeId
deliveryTermsIdDelivery TermsDlvTermIdWMSPickingRoute.DlvTermId
linesLinesList of MGCLatticeOrderPickingLineContractSee belowJSON array. Whole-list cancel: the lines this cancellation canceled, in record order. Single-line cancel: just the canceled line

Each element of lines (MGCLatticeOrderPickingLineContract, built by newFromWMSOrderTrans() from a WMSOrderTrans picking line):

JSON fieldDisplay labelType / EDTSourceNotes
itemIdItem NumberItemIdWMSOrderTrans.itemId
quantityQuantityQtyWMSOrderTrans.qtyQuantity of the picking line
inventTransIdInventory Transaction IDInventTransIdWMSOrderTrans.inventTransIdLot ID of the source order line
lineNumberLine NumberLineNumSalesLine.LineNum, otherwise InventTransferLine.LineNum, matched on InventTransId0 when the line belongs to neither a sales line nor a transfer order line
inventDimIdInventory Dimension IDInventDimIdWMSOrderTrans.inventDim().InventDimId
siteIdSiteInventSiteIdWMSOrderTrans.inventDim().InventSiteId
warehouseIdWarehouseInventLocationIdWMSOrderTrans.inventDim().InventLocationId
locationIdLocationWMSLocationIdWMSOrderTrans.inventDim().wMSLocationId

Every Lattice event also carries the Lattice ordering and correlation envelope, inherited from MGCLatticeBusinessEventContractBase: eventSequence (Int64 - increasing across the whole catalog and all companies, allocated when the event is raised inside the business transaction rather than when it commits; it orders the events of one business record, gaps are permanent and normal, and it must not be used to re-sequence the whole stream), correlationId (String, always Scope:Key - groups emissions that belong to one logical run; Event:<GUID> unique to this emission when the event belongs to no run) and schemaVersion (Int - the payload shape version; 1 for this contract). D365 F&O also adds its standard envelope fields to every business event payload: BusinessEventId, BusinessEventLegalEntity, ContextRecordSubject, ControlNumber, EventId, EventTime, EventTimeIso8601, InitiatingUserAADObjectId, MajorVersion, MinorVersion, and ParentContextRecordSubjects. Do not rely on the order of members in the delivered JSON.

Example Payload​

A whole sales order picking list canceled:

{
"BusinessEventId": "MGCLatticePickingListCanceledBusinessEvent",
"ControlNumber": 5637146325,
"EventId": "B85D0E3A-6F12-4C9B-8D47-3A1E9C0F5B62",
"EventTime": "\/Date(1790260337000)\/",
"EventTimeIso8601": "2026-09-24T14:32:17.9383437Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{4B6ECBDD-25B5-766D-78CB-ED43EB4E6817}",
"ParentContextRecordSubjects": [],
"eventSequence": 48451,
"correlationId": "Event:44bdb86d-783a-4198-86c1-63f2dc847b34",
"schemaVersion": 1,
"legalEntity": "usmf",
"pickingRouteId": "000318",
"orderNumber": "000874",
"transType": 0,
"transTypeName": "Sales",
"routeStatus": 20,
"routeStatusName": "Cancelled",
"deliveryModeId": "10",
"deliveryTermsId": "FOB",
"lines": [
{
"itemId": "A0001",
"quantity": 12.0,
"inventTransId": "012587",
"lineNumber": 1.0,
"inventDimId": "002147",
"siteId": "1",
"warehouseId": "11",
"locationId": "11-01-02"
},
{
"itemId": "A0002",
"quantity": 4.0,
"inventTransId": "012588",
"lineNumber": 2.0,
"inventDimId": "002166",
"siteId": "1",
"warehouseId": "11",
"locationId": "11-03-01"
}
]
}

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Picking list canceled") or by filtering the Category column to Inventory management. Select it and use Activate to bind it to a configured endpoint (for example, an Azure Service Bus queue, Event Grid topic, or HTTPS webhook).

No other setup is needed.