Skip to main content

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 classMGCLatticeRetailInfoCodeResponseBusinessEvent
Contract classMGCLatticeRetailInfoCodeResponseBusinessEventContract
CategoryRetail
ModuleModuleAxapta::RetailTerminal
Label IDsRetailInfoCodeResponseBusinessEventName / RetailInfoCodeResponseBusinessEventDescription
TriggerRetailTransactionInfocodeTrans.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's insert()).
  • 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 the TransactionInfocodeTrans or RetailTransactionInfoCodeLine data entity, unless the import uses set-based processing. Set-based inserts (insert_recordset, RecordInsertList, doInsert) don't call insert() 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 through insert() 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 transDate and transTime are 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 fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaIdRetailTransactionInfocodeTrans.dataAreaId
infoCodeIdInfo Code IDRetailInfocodeIdRetailTransactionInfocodeTrans.infocodeIdThe info code (reason code)
subInfoCodeIdSub Info Code IDRetailInformationSubcodeIdRetailTransactionInfocodeTrans.subInfocodeIdThe selected subcode; blank when none was selected
informationResponse TextRetailInfocodeInformationRetailTransactionInfocodeTrans.informationText entered at the till
infoAmountResponse AmountRetailInfocodeAmountRetailTransactionInfocodeTrans.infoAmountAmount captured with the response
infoCodeTransactionTypeInfo Code Transaction Typeintenum2int(RetailTransactionInfocodeTrans.type)RetailInfocodeTransType value: 0 = Header, 1 = Sales, 2 = Payment, 3 = IncomeExpense, 4 = NoSale, 5 = Affiliation, 6 = Fiscal
infoCodeTransactionTypeNameInfo Code Transaction Type Namestrenum2Symbol(enumNum(RetailInfocodeTransType), ...)Symbol, for example Sales
transactionIdTransaction IDRetailTransactionIdRetailTransactionInfocodeTrans.transactionIdThe store transaction the response belongs to
lineNumberLine NumberLineNumRetailTransactionInfocodeTrans.lineNumLine number of this info code row
parentLineNumberParent Line NumberLineNumRetailTransactionInfocodeTrans.parentLineNumNumber of the transaction line the response is attached to, for example the sales or payment line; 0 for a response to the transaction header
storeIdStore IDRetailStoreIdRetailTransactionInfocodeTrans.store
terminalIdTerminal IDRetailTerminalIdRetailTransactionInfocodeTrans.terminal
staffIdStaff IDRetailStaffIdRetailTransactionInfocodeTrans.staffOperator who captured the response
entryDateTimeEntry Date TimeutcdatetimetransDate 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).