Retail info-code response captured
Fires when a retail info code (reason code) response row is inserted into RetailTransactionInfocodeTrans in headquarters through the table's insert method. The payload carries the info code and subcode, the response text and amount, the transaction ID and the transaction line the response belongs to, the store, terminal, and staff member that captured it, and the capture time in UTC. Downstream systems can use it to react to till-side signals such as return reasons, price-override reasons, or customer survey answers, for example for loss-prevention alerts or feedback analytics. Responses that stores upload to headquarters might not raise it; see Trigger / Hook.
| Event class | MGCLatticeRetailInfoCodeResponseBusinessEvent |
| Contract class | MGCLatticeRetailInfoCodeResponseBusinessEventContract |
| Category | Retail |
| Module | ModuleAxapta::RetailTerminal |
| Label IDs | RetailInfoCodeResponseBusinessEventName / RetailInfoCodeResponseBusinessEventDescription |
| Trigger | RetailTransactionInfocodeTrans.insert() -> after each record insert |
Trigger / Hook
- Extension class:
MGCLatticeRetailTransactionInfocodeTrans_Table_Extension, decorated with[ExtensionOf(tableStr(RetailTransactionInfocodeTrans))]. - CoC method signature:
void insert()(Chain of Command wrap of the table'sinsert()). - Firing condition: the event is sent after every
next insert(), gated only by activation. There's no filter on info code or type: responses of every info code transaction type (header, sales line, payment, income/expense, no sale, affiliation, fiscal) send an event. - Which writes raise it: only inserts that go through the table's
insert()method, for example a record created through theTransactionInfocodeTransorRetailTransactionInfoCodeLinedata entity, unless the import uses set-based processing. Set-based inserts (insert_recordset,RecordInsertList,doInsert) don't callinsert()and don't raise the event. - Limitation, store transactions: no standard X++ code in the application inserts these rows through
insert(). Store transactions normally reach headquarters through the Commerce Data Exchange upload (P-job), which isn't X++ code, and whether that upload writes rows throughinsert()can't be determined from the application source. If it doesn't, responses captured at the stores never raise this event. Test it in your environment before you rely on it for store traffic. - Capture time: the row's
transDateandtransTimeare the till's local date and time. They're converted to UTC with the time zone of the row's channel (found by its channel record, otherwise by its store); when the channel has no time zone, the legal entity's time zone is used. - Transaction: the event is sent inside the insert. When the insert is part of a larger transaction, the event is written to the business events commit log inside it and is delivered only if that transaction commits.
- Enablement gate: guarded by
BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeRetailInfoCodeResponseBusinessEvent)), checked before the contract is built.
void insert()
{
next insert();
if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeRetailInfoCodeResponseBusinessEvent)))
{
MGCLatticeRetailInfoCodeResponseBusinessEvent::newFromRetailTransactionInfocodeTrans(this).send();
}
}
Payload Contract
One row per [DataMember], in declaration order. All sources are fields on the inserted RetailTransactionInfocodeTrans record, mapped in initialize().
| JSON field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | RetailTransactionInfocodeTrans.dataAreaId | |
infoCodeId | Info Code ID | RetailInfocodeId | RetailTransactionInfocodeTrans.infocodeId | The info code (reason code) |
subInfoCodeId | Sub Info Code ID | RetailInformationSubcodeId | RetailTransactionInfocodeTrans.subInfocodeId | The selected subcode; blank when none was selected |
information | Response Text | RetailInfocodeInformation | RetailTransactionInfocodeTrans.information | Text entered at the till |
infoAmount | Response Amount | RetailInfocodeAmount | RetailTransactionInfocodeTrans.infoAmount | Amount captured with the response |
infoCodeTransactionType | Info Code Transaction Type | int | enum2int(RetailTransactionInfocodeTrans.type) | RetailInfocodeTransType value: 0 = Header, 1 = Sales, 2 = Payment, 3 = IncomeExpense, 4 = NoSale, 5 = Affiliation, 6 = Fiscal |
infoCodeTransactionTypeName | Info Code Transaction Type Name | str | enum2Symbol(enumNum(RetailInfocodeTransType), ...) | Symbol, for example Sales |
transactionId | Transaction ID | RetailTransactionId | RetailTransactionInfocodeTrans.transactionId | The store transaction the response belongs to |
lineNumber | Line Number | LineNum | RetailTransactionInfocodeTrans.lineNum | Line number of this info code row |
parentLineNumber | Parent Line Number | LineNum | RetailTransactionInfocodeTrans.parentLineNum | Number of the transaction line the response is attached to, for example the sales or payment line; 0 for a response to the transaction header |
storeId | Store ID | RetailStoreId | RetailTransactionInfocodeTrans.store | |
terminalId | Terminal ID | RetailTerminalId | RetailTransactionInfocodeTrans.terminal | |
staffId | Staff ID | RetailStaffId | RetailTransactionInfocodeTrans.staff | Operator who captured the response |
entryDateTime | Entry Date Time | utcdatetime | transDate and transTime, converted from the channel's time zone with DateTimeUtil::removeTimeZoneOffset() | The capture time in UTC; see Capture time above. When transDate is empty the value is the empty date and time, 1900-01-01, sent as "\/Date(-2208988800000)\/" |
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": "MGCLatticeRetailInfoCodeResponseBusinessEvent",
"ControlNumber": 5637146419,
"EventId": "8D3F1A6C-0E52-4B97-A4C1-7B2E9F5D0C38",
"EventTime": "\/Date(1790270405000)\/",
"EventTimeIso8601": "2026-09-24T17:20:05.1014750Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{CA409780-4280-A44C-95D9-82EE42648D89}",
"ParentContextRecordSubjects": [],
"eventSequence": 48547,
"correlationId": "Event:da03ba9a-80fd-4aa6-b1a9-53a4ab8cbf60",
"schemaVersion": 1,
"legalEntity": "usmf",
"infoCodeId": "RETURN",
"subInfoCodeId": "DAMAGED",
"information": "Box crushed in transit",
"infoAmount": 0.0,
"infoCodeTransactionType": 1,
"infoCodeTransactionTypeName": "Sales",
"transactionId": "HOUSTON-HOUSTON-3-1790270",
"lineNumber": 1.0,
"parentLineNumber": 1.0,
"storeId": "HOUSTON",
"terminalId": "HOUSTON-3",
"staffId": "000160",
"entryDateTime": "\/Date(1790270400000)\/"
}
Activation
In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Retail info-code response captured") or by filtering the Category column to Retail. 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 needed. Confirm that info code responses arriving from your stores actually raise the event before depending on it (see Trigger / Hook).