Skip to main content

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 classMGCLatticeSalesReturnOrderCreatedBusinessEvent
Contract classMGCLatticeSalesReturnOrderCreatedBusinessEventContract
CategorySales orders
ModuleModuleAxapta::SalesOrder
Label IDsSalesReturnOrderCreatedBusinessEventName / SalesReturnOrderCreatedBusinessEventDescription
TriggerSalesTableType_ReturnItem.inserted() -> business event enabled

Trigger / Hook​

  • Extension class MGCLatticeSalesTableType_ReturnItem_Class_Extension, [ExtensionOf(classStr(SalesTableType_ReturnItem))].
  • SalesTableType_ReturnItem is 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's inserted() right after the header record has been written. The wrapper calls next inserted() first, then resolves the SalesTable via this.parmSalesTable() and sends the event.
  • Firing condition: the event is sent only when BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeSalesReturnOrderCreatedBusinessEvent)) returns true. There is no orig() transition guard or recipient/type filter beyond the inherently return-item-scoped extension target, so every return order created through SalesTable.insert() fires once - whether it is created on the Return orders page, by a data entity import or by code. Inserts that bypass SalesTable.insert() (for example doInsert()) do not call inserted() 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 fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaIdSalesTable.DataAreaIdCompany/legal entity of the return order.
salesOrderIdSales Order IDSalesIdSalesTable.SalesIdThe return order's order number (SalesId); the RMA number (SalesTable.ReturnItemNum) is not included.
customerAccountCustomer AccountCustAccountSalesTable.CustAccountAccount of the customer returning goods.
returnReasonCodeIdReturn Reason CodeReturnReasonCodeIdSalesTable.ReturnReasonCodeIdReason 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).
crossReferencesCross referencesList of MGCLatticeCrossReferenceEventContractMGCLatticeCrossReferenceEventHelper::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.