Sales return order created
Fires when a sales return order is created in D365FO. A sales return order is a SalesTable record of type return item (SalesType::ReturnItem), used to bring customer-returned goods back into inventory. This event lets downstream systems (RMA portals, warehouse/return-processing workflows, customer-service tooling, analytics) react the moment a return is logged, capturing which customer is returning, against which return order, and why.
| Event class | MGCLatticeSalesReturnOrderCreatedBusinessEvent |
| Contract class | MGCLatticeSalesReturnOrderCreatedBusinessEventContract |
| Category | Sales orders |
| Module | ModuleAxapta::SalesOrder |
| Label IDs | SalesReturnOrderCreatedBusinessEventName / SalesReturnOrderCreatedBusinessEventDescription |
| Trigger | SalesTableType_ReturnItem.inserted() -> business event enabled |
Trigger / Hook
- Extension class
MGCLatticeSalesTableType_ReturnItem_Class_Extension,[ExtensionOf(classStr(SalesTableType_ReturnItem))]. SalesTableType_ReturnItemis the type-specific class for sales return orders, so the hook only ever fires for return-item orders - no additional order-type check is needed.- CoC method signature:
void inserted(). SalesTable.insert()calls the order type'sinserted()right after the header record has been written. The wrapper callsnext inserted()first, then resolves theSalesTableviathis.parmSalesTable()and sends the event.- Firing condition: the event is sent only when
BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeSalesReturnOrderCreatedBusinessEvent))returns true. There is noorig()transition guard or recipient/type filter beyond the inherently return-item-scoped extension target, so every return order created throughSalesTable.insert()fires once - whether it is created on the Return orders page, by a data entity import or by code. Inserts that bypassSalesTable.insert()(for exampledoInsert()) do not callinserted()and raise no event. - Transaction:
SalesTable.insert()refuses to run outside a transaction, so the event is always written to the commit log inside the creating transaction and delivered after commit; a creation that is rolled back never delivers. - Enablement gate:
BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeSalesReturnOrderCreatedBusinessEvent)).
void inserted()
{
next inserted();
SalesTable salesTable = this.parmSalesTable();
if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeSalesReturnOrderCreatedBusinessEvent)))
{
MGCLatticeSalesReturnOrderCreatedBusinessEvent::newFromSalesTable(salesTable).send();
}
}
Payload Contract
One row per [DataMember], in declaration order. All sources are fields on the inserted SalesTable record, mapped in initialize(); the values are those of the header at the moment it is created.
| JSON field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | SalesTable.DataAreaId | Company/legal entity of the return order. |
salesOrderId | Sales Order ID | SalesId | SalesTable.SalesId | The return order's order number (SalesId); the RMA number (SalesTable.ReturnItemNum) is not included. |
customerAccount | Customer Account | CustAccount | SalesTable.CustAccount | Account of the customer returning goods. |
returnReasonCodeId | Return Reason Code | ReturnReasonCodeId | SalesTable.ReturnReasonCodeId | Reason code captured on the return header; blank if it was not specified when the order was created (a reason code added later is not reported). |
crossReferences | Cross references | List of MGCLatticeCrossReferenceEventContract | MGCLatticeCrossReferenceEventHelper::listFor(SalesTable) | Keys external systems hold for the return order: one { externalSystem, externalKey } object per external system, ordered by external system, historical keys included; [] when it has none. See Cross-reference keys. |
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 sent inside the business transaction; it orders the events of one record, but two transactions can commit in the opposite order of their values, and gaps are normal and permanent - see the events overview), correlationId (String - always Scope:Key: Event: followed by a GUID unique to this emission, unless the event joins a 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": "MGCLatticeSalesReturnOrderCreatedBusinessEvent",
"ControlNumber": 5637148960,
"EventId": "923E0E7F-DE83-4B31-95A0-9FD24D755C84",
"EventTime": "\/Date(1790268245000)\/",
"EventTimeIso8601": "2026-09-24T16:44:05.4189433Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{1646F568-66C5-228A-7810-00CE7930974C}",
"ParentContextRecordSubjects": [],
"eventSequence": 48240,
"correlationId": "Event:99fd6a7d-2a77-448a-84f1-6d8df19dcd57",
"schemaVersion": 1,
"legalEntity": "usmf",
"salesOrderId": "001788",
"customerAccount": "US-004",
"returnReasonCodeId": "21",
"crossReferences": [
{
"externalSystem": "SHOP",
"externalKey": "RMA-20931"
}
]
}
Activation
In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Locate the event by name ("Sales return order created") or filter the Category column to Sales orders. Select it and activate it against the desired endpoint (for example an Azure Service Bus queue, Event Grid, or Power Automate flow) for the relevant legal entity.
Related Events
- Return order received - the next step, when the returned goods arrive.
- Return credit note posted - the credit note that closes the return.
- Purchase return order created - the procurement-side sibling for vendor returns.
- Sales order confirmed - another
SalesTable-driven Sales orders event. - Sales order canceled - companion sales order lifecycle event.