Return credit note posted
Fires when the credit note for a customer return is posted - that is, when a sales return order is invoiced, which is how D365 posts the credit note for returned goods. It is raised after the posting has written the credit note's totals, so refund, RMA and customer-service systems receive the credit note number, the return order and RMA number, the customer, the amount and its currency, and can close out the return. Pro forma credit notes do not raise it.
| Event class | MGCLatticeReturnCreditNotePostedBusinessEvent |
| Contract class | MGCLatticeReturnCreditNotePostedBusinessEventContract |
| Category | Sales orders |
| Module | ModuleAxapta::SalesOrder |
| Label IDs | ReturnCreditNotePostedBusinessEventName / ReturnCreditNotePostedBusinessEventDescription |
| Trigger | SalesInvoiceJournalPost.postJournalPost() -> a posted (not pro forma) invoice journal of a return order (SalesType = ReturnItem) |
Trigger / Hook
- Extension class:
MGCLatticeSalesInvoiceJournalPost_Class_Extension,[ExtensionOf(classStr(SalesInvoiceJournalPost))], wrappingpublic void postJournalPost()- the same post-completion hook that raises Sales order invoice posted. The event is sent byMGCLatticeReturnLifecycleEventHandlers::raiseReturnCreditNotePosted(). - When it runs: sales order invoicing calls
postJournalPost()once for every invoice journal it creates, after that journal has been posted and its totals written; the header is read again by record ID so the payload carries what was stored. - Firing condition (
MGCLatticeReturnLifecycleEventHandlers::isReturnOrderCreditNote()): the invoice journal exists, belongs to a sales order, is not pro forma, and its order type is Returned order (CustInvoiceJour.SalesType=SalesType::ReturnItem). The order type decides, not the sign of the amount: every posted invoice of a return order is its credit note, and a credit note posted from an ordinary sales order (negative lines on a sales order) is not a return and does not raise this event. For a summary invoice, the order type of the order the invoice is posted under counts. - The same journal also raises Sales order invoice posted, which covers every sales order invoice and credit note. If you subscribe to both, de-duplicate on the credit note number.
- Timing:
postJournalPost()runs inside the posting transaction;send()writes to the business events commit log inside it and delivery happens asynchronously after commit, so a posting that fails, or a simulated posting (which D365 rolls back), never delivers. - Enablement gate:
BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeReturnCreditNotePostedBusinessEvent)).
public static boolean isReturnOrderCreditNote(CustInvoiceJour _custInvoiceJour)
{
return _custInvoiceJour.RecId != 0
&& _custInvoiceJour.SalesId != ''
&& _custInvoiceJour.SalesType == SalesType::ReturnItem
&& !_custInvoiceJour.isProforma();
}
public static void raiseReturnCreditNotePosted(CustInvoiceJour _custInvoiceJour)
{
if (MGCLatticeReturnLifecycleEventHandlers::isReturnOrderCreditNote(_custInvoiceJour)
&& BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeReturnCreditNotePostedBusinessEvent)))
{
MGCLatticeReturnCreditNotePostedBusinessEvent::newFromCustInvoiceJour(_custInvoiceJour).send();
}
}
Payload Contract
One row per [DataMember], in declaration order. All sources are fields on the posted CustInvoiceJour header, read after the posting wrote its totals and mapped in initialize().
| JSON field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | CustInvoiceJour.DataAreaId | Company of the credit note, as stored (lowercase, for example usmf). |
invoiceId | Invoice ID | InvoiceId | CustInvoiceJour.InvoiceId | Credit note (invoice) number. |
salesOrderId | Sales Order ID | SalesId | CustInvoiceJour.SalesId | The return order. |
rmaNumber | RMA Number | ReturnItemNum | CustInvoiceJour.ReturnItemNum | Return merchandise authorization number of the return order; matches rmaNumber in Return order received. |
invoiceAccount | Invoice Account | CustAccount | CustInvoiceJour.InvoiceAccount | Invoice account credited. |
amount | Amount | AmountCur | CustInvoiceJour.InvoiceAmount | Credit note total including tax, in currencyCode. Normally negative; a return order with charges that outweigh the returned goods can produce a zero or positive total, which is reported as it is. |
currencyCode | Currency Code | CurrencyCode | CustInvoiceJour.CurrencyCode | Currency of amount. |
crossReferences | Cross references | List of MGCLatticeCrossReferenceEventContract | MGCLatticeCrossReferenceEventHelper::listForSalesOrder(CustInvoiceJour.SalesId, CustInvoiceJour.DataAreaId) | Keys external systems hold for the return order the credit note was posted for: one { externalSystem, externalKey } object per external system, ordered by external system, historical keys included; [] when it has none. See Cross-reference keys. The keys are the return order's, not the journal's. |
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": "MGCLatticeReturnCreditNotePostedBusinessEvent",
"ControlNumber": 5637148733,
"EventId": "E81C5A7D-2B94-4F30-A6D1-3C9F0E7B4A25",
"EventTime": "\/Date(1790323124000)\/",
"EventTimeIso8601": "2026-09-25T07:58:44.3293554Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{C86309B4-0DE4-E984-6D86-72FFA98CFAA1}",
"ParentContextRecordSubjects": [],
"eventSequence": 48377,
"correlationId": "Event:1cbfcd33-4f98-467b-829e-fc6b3438d0ba",
"schemaVersion": 1,
"legalEntity": "usmf",
"invoiceId": "CIV-000812",
"salesOrderId": "001207",
"rmaNumber": "RMA-000017",
"invoiceAccount": "US-001",
"amount": -1250.00,
"currencyCode": "USD",
"crossReferences": [
{
"externalSystem": "SHOP",
"externalKey": "RMA-20931"
}
]
}
Activation
In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Return credit note posted") or by filtering the Category column to Sales orders. 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
- Sales order invoice posted - fires for every sales order invoice and credit note, including this one.
- Return order received - returned goods registered at the warehouse, the step before the credit note.
- Sales return order created - the start of the return lifecycle.
- Free text invoice posted - also fires for free text credit notes (no sales order).