Skip to main content

Quality order failed

Fires when an inventory quality order is validated with a failing result - that is, the order's status transitions to Fail. This signals that inspected material did not meet the defined test specifications, capturing the failing quantity, the blocked quantity held back, the disposition code applied, and the worker and timestamp of the validation so downstream systems can trigger nonconformance handling, quarantine, supplier notification, or rework workflows.

Event classMGCLatticeQualityOrderFailedBusinessEvent
Contract classMGCLatticeQualityOrderFailedBusinessEventContract
CategoryInventory management
ModuleModuleAxapta::Inventory
Label IDsQualityOrderFailedBusinessEventName / QualityOrderFailedBusinessEventDescription
TriggerInventQualityOrderValidate.run() -> OrderStatus transitions to InventTestOrderStatus::Fail

Trigger / Hook​

  • Extension class: MGCLatticeInventQualityOrderValidate_Class_Extension
  • [ExtensionOf] target: classStr(InventQualityOrderValidate)
  • CoC method signature: void run() (no params)
  • Hooked on the process method, rather than the underlying InventQualityOrderTable.update(). The validation process method is the true business moment; the table write is only its side effect (and table hooks false-fire for entity/import writes and are skipped by set-based DML). The status write happens in updateInventQualityOrder() inside run()'s own ttsbegin/ttscommit, so the event is sent after that transaction commits. When validation runs inside a larger transaction, the event is written to the business events commit log inside it and is delivered only if that transaction commits.
  • Firing condition: The pre-validation status is captured via InventQualityOrderTable::find(this.parmQualityOrderId()).OrderStatus before calling next run(), and the committed record is re-read (InventQualityOrderTable::find(qualityOrderId)) afterward. The event fires only on a genuine transition (origStatus != qo.OrderStatus) into InventTestOrderStatus::Fail, preventing re-fires on no-ops, re-runs, and already-in-state calls. This same run() wrapper also fires the sibling MGCLatticeQualityOrderPassedBusinessEvent on a transition to InventTestOrderStatus::Pass (the branches are mutually exclusive - Pass XOR Fail).
  • Enablement gate: Guarded by BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeQualityOrderFailedBusinessEvent)), so the event is only built and sent when activated against an endpoint in the business events catalog.
void run()
{
// The activation checks are cached lookups and come first, so an environment that has activated neither
// event pays no database read. next run() is always called.
boolean passedEnabled = BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeQualityOrderPassedBusinessEvent));
boolean failedEnabled = BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeQualityOrderFailedBusinessEvent));
InventQualityOrderId qualityOrderId = this.parmQualityOrderId();
InventTestOrderStatus origStatus;

if (passedEnabled || failedEnabled)
{
origStatus = InventQualityOrderTable::find(qualityOrderId).OrderStatus;
}

next run();

if (passedEnabled || failedEnabled)
{
InventQualityOrderTable qo = InventQualityOrderTable::find(qualityOrderId);

if (origStatus != qo.OrderStatus)
{
if (qo.OrderStatus == InventTestOrderStatus::Pass && passedEnabled)
{
MGCLatticeQualityOrderPassedBusinessEvent::newFromInventQualityOrderTable(qo).send();
}
else if (qo.OrderStatus == InventTestOrderStatus::Fail && failedEnabled)
{
MGCLatticeQualityOrderFailedBusinessEvent::newFromInventQualityOrderTable(qo).send();
}
}
}
}

Payload Contract​

Source record: InventQualityOrderTable (passed to initialize()).

JSON fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaId_inventQualityOrderTable.DataAreaIdCompany of the quality order
qualityOrderIdQuality Order IDInventQualityOrderId_inventQualityOrderTable.QualityOrderId
itemIdItem IDItemId_inventQualityOrderTable.ItemId
itemSearchNameItem Search NamestrInventTable::find(_inventQualityOrderTable.ItemId).NameAliasCross-table lookup to InventTable.NameAlias (search name)
orderStatusOrder Statusintenum2int(_inventQualityOrderTable.OrderStatus)Integer value of InventTestOrderStatus; 1 (Fail) for this event
orderStatusNameOrder Status Namestrenum2Symbol(enumNum(InventTestOrderStatus), enum2int(_inventQualityOrderTable.OrderStatus))Symbol name of InventTestOrderStatus; Fail for this event
quantityQuantityInventQualityOrderQty_inventQualityOrderTable.QtyInspected quantity
blockedQuantityBlocked QuantityInventQty_inventQualityOrderTable.BlockingQtyQuantity blocked/held back
referenceTypeReference Typeintenum2int(_inventQualityOrderTable.ReferenceType)Integer value of InventTestReferenceType: 0 = Inventory, 1 = Sales, 2 = Purch, 3 = Production, 4 = Quarantine, 5 = RouteOpr
referenceTypeNameReference Type Namestrenum2Symbol(enumNum(InventTestReferenceType), enum2int(_inventQualityOrderTable.ReferenceType))Symbol name of InventTestReferenceType
referenceIdReference IDInventRefId_inventQualityOrderTable.InventRefIdSource document (e.g. production/purchase order)
routeIdRoute IDRouteId_inventQualityOrderTable.RouteId
operationNumberOperation NumberOprNum_inventQualityOrderTable.OprNum
workCenterIdWork Center IDWrkCtrIdBase_inventQualityOrderTable.WrkCtrId
inventTransIdInventory Transaction IDInventTransId_inventQualityOrderTable.InventTransId
failedDispositionCodeFailed Disposition CodePdsFailedQualityDispositionCode_inventQualityOrderTable.PdsFailedQualityDispositionCodeDisposition applied on failure
validatedByPersonnelNumberValidated By Personnel NumberHcmPersonnelNumberIdHcmWorker::find(_inventQualityOrderTable.ValidatedByWorker).PersonnelNumberPersonnel number of the validating worker; empty when none is recorded
validatedDateTimeValidated Date TimeTransDateTime_inventQualityOrderTable.ValidatedDateTimeSent in the "\/Date(milliseconds)\/" form
testGroupIdTest Group IDInventTestGroupId_inventQualityOrderTable.TestGroupId

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 raised inside the business transaction rather than when it commits; it orders the events of one business record, gaps are permanent and normal, and it must not be used to re-sequence the whole stream), correlationId (String, always Scope:Key - groups emissions that belong to one logical run; Event:<GUID> unique to this emission when the event belongs to no 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": "MGCLatticeQualityOrderFailedBusinessEvent",
"ControlNumber": 558210,
"EventId": "5F9C2B1E-4A3D-4F8A-9B2C-7E1D6A0F3C45",
"EventTime": "\/Date(1790273019000)\/",
"EventTimeIso8601": "2026-09-24T18:03:39.5173390Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{362B2FA5-EDB9-6A32-D8F3-71AA1D75A1D8}",
"ParentContextRecordSubjects": [],
"eventSequence": 48561,
"correlationId": "Event:9d96d25d-4b63-49bc-87c6-cdbc5f1fced0",
"schemaVersion": 1,
"legalEntity": "usmf",
"qualityOrderId": "QO000148",
"itemId": "M0001",
"itemSearchName": "Mid-range speaker",
"orderStatus": 1,
"orderStatusName": "Fail",
"quantity": 50.00,
"blockedQuantity": 12.00,
"referenceType": 3,
"referenceTypeName": "Production",
"referenceId": "P000231",
"routeId": "000156",
"operationNumber": 30,
"workCenterId": "1250",
"inventTransId": "0697234",
"failedDispositionCode": "REJECT",
"validatedByPersonnelNumber": "000117",
"validatedDateTime": "\/Date(1790273016000)\/",
"testGroupId": "TG-AUDIO"
}

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Quality order failed") or by filtering the Category column to Inventory management. Select it and use Activate to bind it to a configured endpoint (such as an Azure Service Bus queue, Event Grid topic, or HTTPS webhook).

  • Quality order passed - fired by the same MGCLatticeInventQualityOrderValidate_Class_Extension.run() wrapper on a transition to InventTestOrderStatus::Pass (the passing counterpart to this failing event).