Skip to main content

Production order started

Fires when a production order is started for the first time and moves to the Started status (ProdStatus::StartedUp), signaling that production has begun on the shop floor. Downstream systems can use it to begin tracking actual material consumption, labor, and machine time against the order.

Event classMGCLatticeProdOrderStartedBusinessEvent
Contract classMGCLatticeProdOrderStartedBusinessEventContract
CategoryProduction control
ModuleModuleAxapta::ProductionControl
Label IDsProdOrderStartedBusinessEventName / ProdOrderStartedBusinessEventDescription
TriggerProdUpdStartUp.run() -> ProdStatus transitions into StartedUp

Trigger / Hook​

  • Extension class: MGCLatticeProdUpdStartUp_Class_Extension, decorated with [ExtensionOf(classStr(ProdUpdStartUp))].
  • CoC method signature: void run() (no parameters). This is the start update for one production order, not the ProdTable.update() table write.
  • Firing condition: before next run(), the production order ID is read from the update's parameter record (this.parmParmBuffer().Id) and the order's current status is read from the database. After next run(), the order is re-read and the event is sent only when the status changed into ProdStatus::StartedUp (origStatus != ProdStatus::StartedUp && prodTable.ProdStatus == ProdStatus::StartedUp).
  • When the status changes: the standard update (updateProduction()) sets Started only for an order that hasn't been started yet. Starting a further quantity on an order that is already Started doesn't change its status, so it doesn't raise the event again.
  • Coverage: raised for every start that runs through ProdUpdStartUp.run(). That includes the Start action and the start step that the production status framework runs automatically when a later status update is requested for an order that hasn't been started (for example, reporting it as finished).
  • Transaction: ProdUpdStartUp.run() performs the update inside its own ttsbegin/ttscommit, and the event is sent after it returns. BusinessEventsBase.send() only writes to the commit log inside the current transaction and delivery is asynchronous post-commit, so an event raised inside a larger transaction that rolls back is never delivered.
  • Enablement gate: guarded by BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeProdOrderStartedBusinessEvent)), so the event only sends when activated in the business events catalog.
void run()
{
// The activation check is a cached lookup and comes first, so an environment that has not activated the
// event pays no database read. next run() is always called.
boolean eventEnabled = BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeProdOrderStartedBusinessEvent));
ProdId prodId;
ProdStatus origStatus;

// Capture the pre-status from the database BEFORE next so the event fires only on a genuine transition.
// The base class initializes its prodTable buffer inside run(), so read the persisted status using the
// production order id from the parm buffer.
if (eventEnabled)
{
prodId = this.parmParmBuffer().Id;
origStatus = ProdTable::find(prodId).ProdStatus;
}

next run();

if (eventEnabled)
{
// Re-read the committed record after next for the freshest status.
ProdTable prodTable = ProdTable::find(prodId);

if (origStatus != ProdStatus::StartedUp
&& prodTable.ProdStatus == ProdStatus::StartedUp)
{
MGCLatticeProdOrderStartedBusinessEvent::newFromProdTable(prodTable).send();
}
}
}

Payload Contract​

One row per [DataMember], in declaration order. All sources are fields on the re-read ProdTable record, mapped in initialize().

JSON fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaIdProdTable.DataAreaIdCompany of the production order.
productionOrderIdProduction Order IDProdIdProdTable.ProdIdProduction order number.
itemIdItem NumberItemIdProdTable.ItemIdItem being produced.
itemSearchNameItem Search NamestrInventTable::find(ProdTable.ItemId).NameAliasThe item's search name, not its product name.
productionStatusProduction Statusintenum2int(ProdTable.ProdStatus)ProdStatus as an integer; always 4 (StartedUp) for this event.
productionStatusNameProduction Status Namestrenum2Symbol(enumNum(ProdStatus), enum2int(ProdTable.ProdStatus))ProdStatus symbol; always StartedUp for this event.
crossReferencesCross referencesList of MGCLatticeCrossReferenceEventContractMGCLatticeCrossReferenceEventHelper::listFor(ProdTable)Keys external systems hold for the production order: one { externalSystem, externalKey } object per external system, ordered by external system, historical keys included; [] when it has none. See Cross-reference keys.

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": "MGCLatticeProdOrderStartedBusinessEvent",
"ControlNumber": 5637151717,
"EventId": "9520A5C5-6E66-4BE8-B463-47AE9361B0E5",
"EventTime": "\/Date(1790063285000)\/",
"EventTimeIso8601": "2026-09-22T07:48:05.9197634Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{176858E1-CE98-2FF9-D703-671624D7FEF0}",
"ParentContextRecordSubjects": [],
"eventSequence": 48117,
"correlationId": "Event:5232776f-ec9a-415b-8c31-4d102d3c3f10",
"schemaVersion": 1,
"legalEntity": "usmf",
"productionOrderId": "P000108",
"itemId": "D0001",
"itemSearchName": "MidRangeSpeaker",
"productionStatus": 4,
"productionStatusName": "StartedUp",
"crossReferences": [
{
"externalSystem": "MES",
"externalKey": "WO-104522"
}
]
}

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Production order started") or by filtering the Category column to Production control. 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).