Skip to main content

Warehouse picking completed

Fires when warehouse management (WHS) picking work for an order is closed: sales picking, transfer order issue, production raw material picking, or kanban picking work with at least one completed Pick line. The payload carries the work order type, the order, shipment and load references, and one entry per completed Pick line with its own item, quantity, unit, location, and the warehouse user who picked it. Downstream WMS, OMS, or customer-notification systems can use it as a "pick completed with quantities" signal without querying the work lines. It's raised from the same hook as Warehouse Work Completed, and each of the two can be activated on its own.

Event classMGCLatticeWarehousePickingCompletedBusinessEvent
Contract classMGCLatticeWarehousePickingCompletedBusinessEventContract
CategoryWarehouse management
ModuleModuleAxapta::Warehouse
Label IDsWarehousePickingCompletedBusinessEventName / WarehousePickingCompletedBusinessEventDescription
TriggerWHSWorkTable.update() -> WorkStatus changes to WHSWorkStatus::Closed for picking work with at least one closed Pick line

Trigger / Hook​

  • Extension class: MGCLatticeWHSWorkTable_Table_Extension, decorated with [ExtensionOf(tableStr(WHSWorkTable))].
  • CoC method signature: public void update() (Chain of Command wrap of WHSWorkTable.update()).
  • Firing condition: the original WorkStatus is captured with this.orig().WorkStatus before next update(). After the update, when the status actually changed and the new status is WHSWorkStatus::Closed, and the event is activated, newFromWorkIfPicking(this):
    • returns null unless the work order type (WorkTransType) is Sales, TransferIssue, ProdPick or KanbanPick;
    • returns null unless the work has at least one WHSWorkLine with WorkType == Pick and WorkStatus == Closed. No event is sent when it returns null.
  • Which work qualifies: order picking only. Put-away, replenishment, movement, counting and other work whose template starts with a Pick line (the pick half of a pick and put pair) doesn't qualify. Packed container picking and sorted inventory picking don't qualify either, because they move goods that the order's picking work has already picked.
  • Not raised: when work is closed by a set-based update, because the hook wraps update() only. Picking work isn't created already closed by the standard application, so there's no insert hook for this event (a work header is inserted before its lines).
  • Transaction: the event is sent inside the work-closing transaction; it's written to the business events commit log and delivered only if that transaction commits.
  • Enablement gate: BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeWarehousePickingCompletedBusinessEvent)) is checked before any lookup, so nothing runs when the event isn't activated.
public static MGCLatticeWarehousePickingCompletedBusinessEvent newFromWorkIfPicking(WHSWorkTable _whsWorkTable)
{
WHSWorkLine workLine;

if (!MGCLatticeWarehousePickingCompletedBusinessEvent::isPickingWorkTransType(_whsWorkTable.WorkTransType))
{
return null;
}

select firstonly RecId from workLine
where workLine.WorkId == _whsWorkTable.WorkId
&& workLine.WorkType == WHSWorkType::Pick
&& workLine.WorkStatus == WHSWorkStatus::Closed;

if (!workLine.RecId)
{
return null;
}

// ... builds the event ...
}

Payload Contract​

One row per [DataMember], in declaration order. Header fields come from the closed WHSWorkTable record; lines is read from the work's closed Pick lines (WHSWorkLine with WorkType == Pick and WorkStatus == Closed, in line number order) in initialize(). Canceled and skipped Pick lines picked nothing and aren't listed.

JSON fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaIdWHSWorkTable.DataAreaIdCompany of the work
workIdWork IDWHSWorkIdWHSWorkTable.WorkId
workTransTypeWork Transaction Typeintenum2int(WHSWorkTable.WorkTransType)WHSWorkTransType value: 2 = Sales, 3 = ProdPick, 5 = TransferIssue, 13 = KanbanPick
workTransTypeNameWork Transaction Type Namestrenum2Symbol(enumNum(WHSWorkTransType), ...)Symbol of the work order type, for example Sales
orderNumberOrder NumberWHSOrderNumWHSWorkTable.OrderNumOrder that generated the work
shipmentIdShipment IDWHSShipmentIdWHSWorkTable.ShipmentIdBlank when the work has no shipment
loadIdLoad IDWHSLoadIdWHSWorkTable.LoadIdBlank when the work has no load
warehouseIdWarehouse IDInventLocationIdWHSWorkTable.InventLocationId
siteIdSite IDInventSiteIdWHSWorkTable.InventSiteId
pickLineCountPick Line CountintNumber of entries in linesClosed Pick lines only
workClosedDateTimeWork Closed Date TimeWHSWorkClosedUTCDateTimeWHSWorkTable.WorkClosedUTCDateTimeUTC date and time the work closed
linesLinesList of MGCLatticeWarehousePickLineContractSee belowJSON array, one element per closed Pick line

Each element of lines (MGCLatticeWarehousePickLineContract, built by newFromWHSWorkLine() from a closed Pick line):

JSON fieldDisplay labelType / EDTSourceNotes
lineNumberLine NumberLineNumWHSWorkLine.LineNumWork line number
itemIdItem NumberItemIdWHSWorkLine.ItemId
quantityQuantityQtyWHSWorkLine.QtyWorkQuantity picked on the line, in unitId
unitIdUnitUnitOfMeasureSymbolWHSWorkLine.UnitIdUnit of quantity
inventoryQuantityInventory QuantityInventQtyWHSWorkLine.InventQtyWorkQuantity picked on the line, in the item's inventory unit; add these up to total an item across lines
locationIdLocationWMSLocationIdWHSWorkLine.WMSLocationIdLocation picked from
inventTransIdInventory Transaction IDInventTransIdWHSWorkLine.InventTransIdLot ID of the order line the pick is for
pickedByUserPicked By UserWHSUserIdWHSWorkLine.UserIdWarehouse (mobile device) user who picked the line
pickedDateTimePicked Date TimeWHSWorkClosedUTCDateTimeWHSWorkLine.WorkClosedUTCDateTimeUTC date and time the line was closed

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​

{
"BusinessEventId": "MGCLatticeWarehousePickingCompletedBusinessEvent",
"ControlNumber": 5637146377,
"EventId": "2F6A9D31-7B04-4E5C-9C28-E1B3F07A6D94",
"EventTime": "\/Date(1790268112000)\/",
"EventTimeIso8601": "2026-09-24T16:41:52.5147490Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{4B42D8BA-0B64-11F3-2278-EF002884D372}",
"ParentContextRecordSubjects": [],
"eventSequence": 48519,
"correlationId": "Event:74f6e9e7-a50f-4523-8f6f-e63b402299e5",
"schemaVersion": 1,
"legalEntity": "usmf",
"workId": "USMF-004821",
"workTransType": 2,
"workTransTypeName": "Sales",
"orderNumber": "000874",
"shipmentId": "USMF-000291",
"loadId": "USMF-000137",
"warehouseId": "24",
"siteId": "2",
"pickLineCount": 2,
"workClosedDateTime": "\/Date(1790268110000)\/",
"lines": [
{
"lineNumber": 1.0,
"itemId": "A0001",
"quantity": 24.0,
"unitId": "ea",
"inventoryQuantity": 24.0,
"locationId": "24-01-01",
"inventTransId": "012587",
"pickedByUser": "24",
"pickedDateTime": "\/Date(1790267950000)\/"
},
{
"lineNumber": 3.0,
"itemId": "A0002",
"quantity": 1.0,
"unitId": "box",
"inventoryQuantity": 12.0,
"locationId": "24-02-03",
"inventTransId": "012588",
"pickedByUser": "24",
"pickedDateTime": "\/Date(1790268080000)\/"
}
]
}

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Warehouse picking completed") or by filtering the Category column to Warehouse 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; the event doesn't depend on Warehouse Work Completed being activated.