Released product created
Fires when a product is released to a legal entity. The moment the product release process creates the released product (the InventTable record for that company), this event publishes the released product's identity, search name, item type, and lifecycle state so downstream systems can pick up the new released product for catalog sync, master-data distribution, or item enrichment workflows. The same event is also emitted in bulk by the item resync described below.
| Event class | MGCLatticeReleasedProductCreatedBusinessEvent |
| Contract class | MGCLatticeReleasedProductCreatedBusinessEventContract |
| Category | Inventory management |
| Module | ModuleAxapta::Inventory |
| Label IDs | ReleasedProductCreatedBusinessEventName / ReleasedProductCreatedBusinessEventDescription |
| Trigger | EcoResProductReleaseManager.createInventTable() (and the item-only EcoResProductReleaseManagerItem.release()) -> after the released product is inserted (RecId guard), plus the on-demand item resync |
Trigger / Hook
The event is raised from the product release process rather than from InventTable.insert(), so InventTable rows written any other way don't raise it. There are three send sites:
- Standard release: extension class
MGCLatticeEcoResProductReleaseManager_Class_Extension,[ExtensionOf(classStr(EcoResProductReleaseManager))], CoC methodprotected void createInventTable().EcoResProductReleaseManagerreleases distinct products and product masters (constraint-based product masters through the inheritingEcoResProductReleaseManagerDefaultConfig). It's used, for example, by Release products and by the released products data entities, which release throughEcoResProductReleaseManager::releaseProductWithLegalEntityData(). Afternext createInventTable(), the extension reads the newinventTablebuffer and sends the event when itsRecIdis set. - Item-only release: extension class
MGCLatticeEcoResProductReleaseManagerItem_Class_Extension,[ExtensionOf(classStr(EcoResProductReleaseManagerItem))], CoC methodpublic void release(boolean _isCreation, TaxItemGroup _purchTaxItemGroupId, TaxItemGroup _salesTaxItemGroupId). This subclass inserts theInventTablerecord itself without callingcreateInventTable(), so the two hooks never both fire for one release. Afternext release(), the extension reads the newinventTablebuffer and, when itsRecIdis set, sends the event in the released record's legal entity. - Bulk resync: the action menu item
MGCLatticeProcessAllItems("Publish all item business events (resync)") asks for confirmation and then runsMGCLatticeBulkEventPublisherfor theItementity type in a sandbox session (it isn't a batch job).MGCLatticeBulkEventSourceItem.publishAll()sends this event for every released product in the current legal entity, pausing for 250 ms after every 500 events. The payload doesn't say whether an event came from a real release or from the resync. Before reading any record, the resync checks that the event is published in the current legal entity (business events framework on, event activated). If not, it stops with "The business event MGCLatticeReleasedProductCreatedBusinessEvent is not activated in legal entity <company>, so no events were published. Activate it in the business events catalog and run the job again." The finish message counts only events actually published. The menu item is at System administration > Periodic tasks > Lattice business events > Publish all item business events (resync), and theMGCLatticeProcessAllItemsExecuteprivilege grants it to the integration administrator role through the batch maintenance duty (MGCLatticeBatchMaintenanceDuty).
Timing and gates:
- Standard release:
createInventTable()runs inside the release transaction (release()switches to the target legal entity and wraps the release inttsbegin/ttscommit), so the event is written to the business events commit log inside that transaction and is delivered only if the release commits. It's sent right after theInventTableinsert, before the rest of the release (inventory setup, default item location, and so on) has run. - Item-only release: the event is sent after
release()has committed its own transaction.release()switches to the target legal entity only inside its own processing, so the extension switches to the company of the released record (changecompany(inventTable.DataAreaId)) before checking activation and sending. Like the standard release, the event is therefore checked against the activation of the legal entity the product was released to, andBusinessEventLegalEntityis that legal entity, even when the release is started from another company. - Enablement gate: both release hooks check
BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeReleasedProductCreatedBusinessEvent))in the target legal entity before sending.
protected void createInventTable()
{
InventTable inventTableLocal;
next createInventTable();
inventTableLocal = this.inventTable;
if (inventTableLocal.RecId)
{
if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeReleasedProductCreatedBusinessEvent)))
{
MGCLatticeReleasedProductCreatedBusinessEvent::newFromInventTable(inventTableLocal).send();
}
}
}
Payload Contract
| JSON field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | _inventTable.dataAreaId | Company the product was released to. |
itemId | Item ID | ItemId | _inventTable.ItemId | Released product number. |
productRecId | Product Record ID | EcoResProductRecId | _inventTable.Product | RecId reference to the shared EcoResProduct. |
searchName | Search Name | ItemNameAlias | _inventTable.NameAlias | Item search name / alias. |
itemType | Item Type | int | enum2int(_inventTable.ItemType) | Enum stored as its integer value: 0 = Item, 2 = Service (1 is the retired BOM value). |
itemTypeName | Item Type Name | str | enum2Symbol(enumNum(ItemType), enum2int(_inventTable.ItemType)) | Symbolic name of the ItemType enum value. |
productLifecycleStateId | Product Lifecycle State ID | EcoResProductLifecycleStateId | _inventTable.ProductLifecycleStateId | Product lifecycle state identifier. |
crossReferences | Cross references | List of MGCLatticeCrossReferenceEventContract | MGCLatticeCrossReferenceEventHelper::listFor(InventTable) | Keys external systems hold for the released product: 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": "MGCLatticeReleasedProductCreatedBusinessEvent",
"ControlNumber": 5500123,
"EventId": "B2F8A1E4-7C3D-4F5A-9E21-0D4C8B6A1F37",
"EventTime": "\/Date(1790280614000)\/",
"EventTimeIso8601": "2026-09-24T20:10:14.8589460Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{202BA2B4-C2A8-A7CC-F94B-AA9C0B871635}",
"ParentContextRecordSubjects": [],
"eventSequence": 48588,
"correlationId": "Event:c4116818-2977-44df-8d4a-f78ba14f0f4f",
"schemaVersion": 1,
"legalEntity": "usmf",
"itemId": "V00042",
"productRecId": 22565423789,
"searchName": "Mid-range speaker",
"itemType": 0,
"itemTypeName": "Item",
"productLifecycleStateId": "Active",
"crossReferences": [
{
"externalSystem": "LEGACYERP",
"externalKey": "ITM-88213"
}
]
}
Activation
In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Released product created") or by filtering the Category column to Inventory management. 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 for releases. To seed a new subscriber with every existing released product, activate the event first and then have an integration administrator run the resync menu item MGCLatticeProcessAllItems in each legal entity; it sends one event per released product.
Related Events
- External Item Changed - customer and vendor item number cross-references for released products.
- Inventory Closing Completed - downstream inventory lifecycle event for the same module.
- Customer Created - sibling master-data "created" event in another domain.
- Vendor Created - sibling master-data "created" event in another domain.