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 class | MGCLatticeQualityOrderFailedBusinessEvent |
| Contract class | MGCLatticeQualityOrderFailedBusinessEventContract |
| Category | Inventory management |
| Module | ModuleAxapta::Inventory |
| Label IDs | QualityOrderFailedBusinessEventName / QualityOrderFailedBusinessEventDescription |
| Trigger | InventQualityOrderValidate.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 inupdateInventQualityOrder()insiderun()'s ownttsbegin/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()).OrderStatusbefore callingnext run(), and the committed record is re-read (InventQualityOrderTable::find(qualityOrderId)) afterward. The event fires only on a genuine transition (origStatus != qo.OrderStatus) intoInventTestOrderStatus::Fail, preventing re-fires on no-ops, re-runs, and already-in-state calls. This samerun()wrapper also fires the siblingMGCLatticeQualityOrderPassedBusinessEventon a transition toInventTestOrderStatus::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 field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | _inventQualityOrderTable.DataAreaId | Company of the quality order |
qualityOrderId | Quality Order ID | InventQualityOrderId | _inventQualityOrderTable.QualityOrderId | |
itemId | Item ID | ItemId | _inventQualityOrderTable.ItemId | |
itemSearchName | Item Search Name | str | InventTable::find(_inventQualityOrderTable.ItemId).NameAlias | Cross-table lookup to InventTable.NameAlias (search name) |
orderStatus | Order Status | int | enum2int(_inventQualityOrderTable.OrderStatus) | Integer value of InventTestOrderStatus; 1 (Fail) for this event |
orderStatusName | Order Status Name | str | enum2Symbol(enumNum(InventTestOrderStatus), enum2int(_inventQualityOrderTable.OrderStatus)) | Symbol name of InventTestOrderStatus; Fail for this event |
quantity | Quantity | InventQualityOrderQty | _inventQualityOrderTable.Qty | Inspected quantity |
blockedQuantity | Blocked Quantity | InventQty | _inventQualityOrderTable.BlockingQty | Quantity blocked/held back |
referenceType | Reference Type | int | enum2int(_inventQualityOrderTable.ReferenceType) | Integer value of InventTestReferenceType: 0 = Inventory, 1 = Sales, 2 = Purch, 3 = Production, 4 = Quarantine, 5 = RouteOpr |
referenceTypeName | Reference Type Name | str | enum2Symbol(enumNum(InventTestReferenceType), enum2int(_inventQualityOrderTable.ReferenceType)) | Symbol name of InventTestReferenceType |
referenceId | Reference ID | InventRefId | _inventQualityOrderTable.InventRefId | Source document (e.g. production/purchase order) |
routeId | Route ID | RouteId | _inventQualityOrderTable.RouteId | |
operationNumber | Operation Number | OprNum | _inventQualityOrderTable.OprNum | |
workCenterId | Work Center ID | WrkCtrIdBase | _inventQualityOrderTable.WrkCtrId | |
inventTransId | Inventory Transaction ID | InventTransId | _inventQualityOrderTable.InventTransId | |
failedDispositionCode | Failed Disposition Code | PdsFailedQualityDispositionCode | _inventQualityOrderTable.PdsFailedQualityDispositionCode | Disposition applied on failure |
validatedByPersonnelNumber | Validated By Personnel Number | HcmPersonnelNumberId | HcmWorker::find(_inventQualityOrderTable.ValidatedByWorker).PersonnelNumber | Personnel number of the validating worker; empty when none is recorded |
validatedDateTime | Validated Date Time | TransDateTime | _inventQualityOrderTable.ValidatedDateTime | Sent in the "\/Date(milliseconds)\/" form |
testGroupId | Test Group ID | InventTestGroupId | _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).
Related Events
- Quality order passed - fired by the same
MGCLatticeInventQualityOrderValidate_Class_Extension.run()wrapper on a transition toInventTestOrderStatus::Pass(the passing counterpart to this failing event).