Vendor ASN line changed
Fires when a vendor's advanced shipping notice (ASN) line is recorded, that is, when a purchase WHSASNItem row (ASN / item information, the packing-structure lines of an inbound load) is inserted, and again when the quantity an existing purchase ASN line announces changes. It gives receiving warehouses, yard and transport systems, and 3PLs an early signal of announced freight (purchase order, shipment, load, item, quantity, unit and batch expiry) before the product receipt is posted. ASN lines that D365 generates for outbound sales and transfer loads do not raise it.
| Event class | MGCLatticeVendorASNLineChangedBusinessEvent |
| Contract class | MGCLatticeVendorASNLineChangedBusinessEventContract |
| Category | Accounts payable |
| Module | ModuleAxapta::Vendor |
| Label IDs | VendorASNSubmittedBusinessEventName / VendorASNSubmittedBusinessEventDescription |
| Trigger | WHSASNItem.insert() -> new purchase ASN line (Module == Purch); WHSASNItem.update() -> announced quantity of a purchase ASN line changed |
Trigger / Hook
- Extension class:
MGCLatticeWHSASNItem_Table_Extension, decorated with[ExtensionOf(tableStr(WHSASNItem))]. - CoC method signatures:
public void insert()andpublic void update(). - Purchase ASN lines only: both methods raise the event only for rows with
Module == WHSModule::Purch, the same range D365's inbound load packing structure entities use. Standard warehouse outbound processing also writesWHSASNItemrows, at shipment confirmation for customers set up to generate ASNs (Sales) and for transfer order loads (Transfer); those do not raise the event, even though an outbound ASN line for an intercompany order carries the intercompany purchase order number. - New line: after
next insert()completes, every inserted purchase ASN line raises one event withisNewLine=true. An ASN with several lines raises several events; group them byshipmentId/loadId. - Quantity change: D365 keeps one ASN line per license plate, item, load line and inventory dimensions. When more quantity is announced for such a line (for example when the packing structure is extended on the page), D365 adds it to the existing line instead of inserting a new one, and an import through the inbound packing structure entities that updates an existing line replaces its quantity. After
next update(), the event is raised again when the line's quantity differs from its quantity before the update, withisNewLine=falseandpreviousQuantityset to the quantity before the change. Both quantities are in the line's current unit: when the update also changes the unit, the previous quantity is converted the wayWHSASNItem.update()itself converts it, so a unit conversion that leaves the amount unchanged raises nothing. Updates that do not change the quantity (for example receiving against the ASN) raise nothing. - Inserts and updates that bypass the table methods (
doInsert(),doUpdate(), or set-based statements with data methods skipped) do not raise it. - Timing: the event is sent inside the transaction that writes the ASN line.
send()writes it to the business events commit log in that transaction and it is delivered after commit, so an ASN import that rolls back never delivers the event. - Enablement gate: guarded by
BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeVendorASNLineChangedBusinessEvent)), so the event only sends when activated in the business events catalog.
public void insert()
{
next insert();
if (this.Module == WHSModule::Purch
&& BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeVendorASNLineChangedBusinessEvent)))
{
MGCLatticeVendorASNLineChangedBusinessEvent::newFromASNItem(this).send();
}
}
public void update()
{
WHSASNItem before = this.orig();
next update();
if (this.Module != WHSModule::Purch
|| !BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeVendorASNLineChangedBusinessEvent)))
{
return;
}
Qty previousQuantity = MGCLatticeVendorASNLineChangedBusinessEvent::previousQuantityInCurrentUnit(before, this);
if (previousQuantity != this.Qty)
{
MGCLatticeVendorASNLineChangedBusinessEvent::newForQuantityChange(this, previousQuantity).send();
}
}
Payload Contract
One row per [DataMember], in declaration order. Values are read from the inserted or updated WHSASNItem row in the contract's initialize().
| JSON field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | WHSASNItem.DataAreaId | Company ID of the ASN line, in lower case (for example usmf) |
purchaseOrderId | Purchase Order | PurchId | WHSASNItem.PurchId | Purchase order of the ASN line |
shipmentId | Shipment ID | WHSShipmentId | WHSASNItem.ShipmentId | Warehouse shipment |
loadId | Load ID | WHSLoadId | WHSASNItem.LoadId | Warehouse load |
itemId | Item Number | ItemId | WHSASNItem.ItemId | Item number |
inventTransId | Inventory Transaction ID | InventTransId | WHSASNItem.InventTransId | Lot ID of the purchase order line the ASN line belongs to |
quantity | Quantity | real | WHSASNItem.Qty | Quantity the line announces now, in unitId |
previousQuantity | Previous Quantity | real | WHSASNItem.orig().Qty, converted to the current unit | The quantity the line announced before this change; 0 for a new line. The change is quantity - previousQuantity |
isNewLine | Is New Line | boolean | Set by the trigger | true when the ASN line was just created; false when the event reports a quantity change on a line announced earlier. Written as true/false |
unitId | Unit | str | WHSASNItem.UOM | Unit of measure symbol |
description | Description | str | WHSASNItem.Description | ASN line description |
batchExpirationDate | Batch Expiration Date | date | WHSASNItem.BatchExpirationDate | "\/Date(ms)\/" form; the empty date (1900-01-01, "\/Date(-2208988800000)\/") when no batch expiration applies |
changedDateTime | Changed Date Time | utcdatetime | DateTimeUtil::utcNow() when the contract is built | Server time at which the line was created or its quantity changed; not a field of the ASN. "\/Date(ms)\/" form |
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; it orders the events of one record, gaps are normal and permanent, see the README), correlationId (String - always Scope:Key; groups emissions that belong to one logical run and defaults to Event: plus a GUID unique to this emission) 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.
This event does not join a run: correlationId is unique to each emission (lines of the same ASN do not share it).
Example Payload
{
"BusinessEventId": "MGCLatticeVendorASNLineChangedBusinessEvent",
"ControlNumber": 588214,
"EventId": "6A1F0C93-4D27-4B8E-A5C1-2E97B3D0F648",
"EventTime": "\/Date(1790245231000)\/",
"EventTimeIso8601": "2026-09-24T10:20:31.6077578Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{4A7E1674-7225-13A5-F8B4-3B6EE69B1F66}",
"ParentContextRecordSubjects": [],
"eventSequence": 48377,
"correlationId": "Event:4e8b2d61-9a3c-4f17-b0d5-7c1e6a2f9b40",
"schemaVersion": 1,
"legalEntity": "usmf",
"purchaseOrderId": "00000050",
"shipmentId": "USMF-000005",
"loadId": "USMF-000007",
"itemId": "A0001",
"inventTransId": "012491",
"quantity": 24,
"previousQuantity": 0,
"isNewLine": true,
"unitId": "Pcs",
"description": "HDMI 6' Cables",
"batchExpirationDate": "\/Date(-2208988800000)\/",
"changedDateTime": "\/Date(1790245231000)\/"
}
If 12 more pieces are later added to the same line, the event is raised again for the line with "quantity": 36, "previousQuantity": 24 and "isNewLine": false.
Activation
In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Vendor ASN line changed") or by filtering the Category column to Accounts payable. 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 required.