Warehouse load shipped
Fires when a warehouse load completes outbound shipping and its load status transitions to Shipped. This is the moment a consolidated load (one or more shipments assigned to a carrier) physically leaves the warehouse, making it the natural trigger point for downstream transportation notifications, advance ship notices (ASN), customer shipment confirmations, and freight-cost reconciliation. It fires for load ship confirmation and for transport load ship confirmation, including the mobile app's transport loading flow.
| Event class | MGCLatticeWarehouseLoadShippedBusinessEvent |
| Contract class | MGCLatticeWarehouseLoadShippedBusinessEventContract |
| Category | Warehouse management |
| Module | ModuleAxapta::Warehouse (from the [BusinessEvents] attribute) |
| Label IDs | WarehouseLoadShippedBusinessEventName / WarehouseLoadShippedBusinessEventDescription |
| Trigger | WHSShipConfirm.shipConfirm(WHSLoadId) or WHSShipConfirmationActionTransportLoad.shipConfirm() -> a load's LoadStatus changes to WHSLoadStatus::Shipped |
Trigger / Hook
-
Extension class:
MGCLatticeWHSShipConfirm_Class_Extension, decorated with[ExtensionOf(classStr(WHSShipConfirm))]. -
CoC method wrapped:
WHSShipConfirm.shipConfirm(WHSLoadId). Exact signature in source:public void shipConfirm(WHSLoadId _loadId) -
Hooks the outbound ship-confirm process method (the business moment) rather than the
WHSLoadTable.update()table write. This funnels the single-load form action,shipConfirmAllLoads, and the batch/ODataWHSShipConfirmServicepath for outbound loads while avoiding entity/import/set-based false-fires. The whole status flip happens inside this method'stts, so firing afternext shipConfirm(_loadId)is post-commit; when ship confirmation runs inside a larger transaction, the event is delivered only if that transaction commits. Inbound loads, whichWHSShipConfirmServiceconfirms throughWHSPostPackingSlipinstead, don't raise this event. -
Transport loads:
MGCLatticeWHSShipConfirmationActionTransportLoad_Class_Extension, decorated with[ExtensionOf(classStr(WHSShipConfirmationActionTransportLoad))], wrapspublic void shipConfirm(WHSLoadShipConfirmUTCDateTime _shipDateTime). Transport load ship confirmation (the transport load page and the mobile app's transport loading flow) sets each related load's status directly and never callsWHSShipConfirm, so the wrapper records every related load's status (WHSTransportLoad::getAllRelatedLoads) beforenextand sends one event per load that moved intoShipped. It records nothing when the event is not activated. Loads that only becomePartiallyShippedare not reported, and a load is never reported by both hooks. -
Firing condition: each hook captures the load status before
next, then callsMGCLatticeWarehouseLoadShippedBusinessEvent::raiseIfShipped(loadId, statusBefore). That method re-reads the load (WHSLoadTable::find) and sends whenisShippedTransition(before, after)holds: the status before wasn'tShippedand the status after isShipped. The status-delta guard suppresses the already-shipped no-op early return and partial loads that do not reach Shipped. -
Enablement gate:
BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeWarehouseLoadShippedBusinessEvent))is checked before sending, so the event is only dispatched when activated against an endpoint.
// MGCLatticeWHSShipConfirm_Class_Extension
public void shipConfirm(WHSLoadId _loadId)
{
// The activation check is a cached lookup and comes first, so an environment that has not activated the
// event pays no database read. next is always called.
boolean eventEnabled = BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeWarehouseLoadShippedBusinessEvent));
WHSLoadStatus origStatus;
if (eventEnabled)
{
origStatus = WHSLoadTable::find(_loadId).LoadStatus;
}
next shipConfirm(_loadId);
if (eventEnabled)
{
MGCLatticeWarehouseLoadShippedBusinessEvent::raiseIfShipped(_loadId, origStatus);
}
}
// MGCLatticeWHSShipConfirmationActionTransportLoad_Class_Extension
public void shipConfirm(WHSLoadShipConfirmUTCDateTime _shipDateTime)
{
Map statusBefore = this.latticeRelatedLoadStatuses();
next shipConfirm(_shipDateTime);
if (statusBefore)
{
MapEnumerator enumerator = statusBefore.getEnumerator();
while (enumerator.moveNext())
{
WHSLoadStatus loadStatusBefore = enumerator.currentValue();
MGCLatticeWarehouseLoadShippedBusinessEvent::raiseIfShipped(enumerator.currentKey(), loadStatusBefore);
}
}
}
// MGCLatticeWarehouseLoadShippedBusinessEvent
public static void raiseIfShipped(WHSLoadId _loadId, WHSLoadStatus _statusBefore)
{
if (!_loadId
|| !BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeWarehouseLoadShippedBusinessEvent)))
{
return;
}
WHSLoadTable loadTable = WHSLoadTable::find(_loadId);
if (loadTable.RecId
&& MGCLatticeWarehouseLoadShippedBusinessEvent::isShippedTransition(_statusBefore, loadTable.LoadStatus))
{
MGCLatticeWarehouseLoadShippedBusinessEvent::newFromWHSLoadTable(loadTable).send();
}
}
Payload Contract
Fields are listed in contract declaration order. Source expressions are taken verbatim from MGCLatticeWarehouseLoadShippedBusinessEventContract.initialize().
| JSON field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | _whsLoadTable.DataAreaId | Company/data area of the load. |
loadId | Load ID | WHSLoadId | _whsLoadTable.LoadId | The warehouse load identifier. |
shipmentId | Shipment ID | WHSShipmentId | _whsLoadTable.displayShipment() | Display method on WHSLoadTable; returns the load's shipment ID when the load has exactly one shipment, and blank when it has none or several. |
shipmentIds | Shipment IDs | List of str | WHSShipmentTable.ShipmentId where LoadId = the load | Every shipment on the load, in shipment ID order; use it instead of shipmentId for loads with several shipments. [] when the load has no shipment. |
carrierCode | Carrier Code | str | _whsLoadTable.CarrierCode | Carrier assigned to the load. |
loadStatus | Load Status | int | enum2int(_whsLoadTable.LoadStatus) | Integer value of the WHSLoadStatus enum. For Shipped this is 6. |
loadStatusName | Load Status Name | str | enum2Symbol(enumNum(WHSLoadStatus), enum2int(_whsLoadTable.LoadStatus)) | Symbolic (non-localized) name of the enum value, e.g. Shipped. |
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": "MGCLatticeWarehouseLoadShippedBusinessEvent",
"ControlNumber": 587213,
"EventId": "1F8D3C2A-7B54-4E90-9A1C-2E6F4B8D0C11",
"EventTime": "\/Date(1790289000000)\/",
"EventTimeIso8601": "2026-09-24T22:30:00.5410395Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{58C80ED0-4923-C9F5-CF0B-13AAF5273332}",
"ParentContextRecordSubjects": [],
"eventSequence": 48615,
"correlationId": "Event:1cc78df7-9ae1-43c3-8649-19323646699a",
"schemaVersion": 1,
"legalEntity": "usmf",
"loadId": "USMF-000142",
"shipmentId": "USMF-000198",
"shipmentIds": [
"USMF-000198"
],
"carrierCode": "FEDEX",
"loadStatus": 6,
"loadStatusName": "Shipped"
}
Activation
In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Warehouse load shipped") 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).
Related Events
- Transfer Order Shipped - companion outbound shipping moment for transfer orders.
- Transfer Order Received - the inbound counterpart that closes the in-transit cycle.
- Sales Packing Slip Posted - sales-side fulfillment confirmation often correlated with a shipped load.
- Warehouse Work Completed - raised when the warehouse work for the load's orders is closed.
- Warehouse Picking Completed - pick-specific signal raised when picking work closes.