Skip to main content

Lattice - Process Customizations

What Lattice changes about the standard Dynamics 365 Finance and Operations processes you already run.

The other reference docs are organized by artifact - Page reference by page, API reference by class, Event catalog by business event. This one is organized by process: you pick the business process you care about - confirming a sales order, posting a journal, releasing a product - and read exactly where Lattice attaches to it and what changes as a result.

Use it when you are asking "we already do this in D365. What is different now that Lattice is installed?" - during an implementation review, a change-impact assessment, an upgrade regression plan, or a support call where a standard process behaved unexpectedly.

Scope. This document covers the existing D365 processes Lattice attaches to. It does not describe the pages and services Lattice adds alongside them - those are entirely new surface area and have their own docs.


The short answer​

Lattice attaches to standard processes and pages at 225 points, but almost all of them belong to two additive features. The business event triggers are read-only observers: they let the standard process run untouched and then publish a business event describing what happened. The cross-reference keys add a button, a FactBox and a settings tab to standard pages and delete a record's keys together with the record. Neither can change a posting, block a save of a standard record, or alter a document.

CountWhat it means for you
Observe only73 classesThe standard process is byte-for-byte unchanged. Lattice reads the result and publishes an event.
Observe and change2 classesPublishes an event and writes something of its own: the e-invoice handlers stamp a Lattice UTC time on the standard submission log row, and the assortment hook records what it published.
Cross-reference keys9 classesShows the Cross references button and FactBox on the covered pages, runs the Cross references tab of the module parameters pages, and deletes a record's keys when the record is deleted (only in a legal entity that holds keys of that kind of record; batches are not covered, so their set-based deletion stays set-based). The standard process is unchanged.
Changes behavior5 classesGenuinely alters what the standard process does. All are listed below and all are off by default or additive.
Infrastructure4 classesLicensing, query range functions, a method that sets the options of the standard pending price activation for the inventory cost service, and a method that runs the production journal page's pre-posting step for the journal posting service. No effect on business logic.

If you read only one section, read Processes whose behavior actually changes. Everything else in this document is observation.

Attachment points by mechanism​

MechanismCountNotes
Chain of Command ([ExtensionOf])72Classes that wrap a standard class or table method (49 classes, 23 tables); always call next. (SysQueryRangeUtil only gains new functions, InventItemPriceActivationJob only a method that sets its options when the inventory cost service runs it without its dialog, and ProdJournalCheckPost only a method that lets the journal posting service run the step the production journal page runs before it posts.)
Event handler (delegate, data event, form event, post-handler)109Handler methods on a standard class, table or page: 22 for business events, guardrails, stamping and startup, and 87 for cross-reference keys (page opened, record deleted, and the Cross references tab and its buttons on the module parameters pages). The button handlers on Lattice's own pages are not counted.
Table extension4RetailAssortmentTable and RetailAssortmentStaging (the MGCLatticeCustAccount and MGCLatticeCustDataAreaId fields), CustomerParametersStaging, BusinessDocumentSubmission (the MGCLatticeSubmittedDateTimeUtc field).
Data entity extension2CustomerParametersEntity, RetailAssortmentEntity.
Form extension35DMFEntity - adds three buttons to the standard Data entities page; DataManagementWorkspace - adds two tiles to the Data management workspace; RetailAssortmentDetails - adds the customer account and customer legal entity fields; 25 record pages that get the cross-reference button and FactBox (AssetTable, BOMConsistOf, BOMTable, CustFreeInvoice, CustTable, EcoResProductDetailsExtended, EcoResProductVariantsPerCompany, InventBatch, InventTransferOrders, LedgerJournalTable, LedgerJournalTransDaily, ProdTable, ProdTableListPage, ProjInvoiceTable, ProjTable, PurchAgreement, PurchReqTable, PurchTable, ReturnTable, RouteInventProd, RouteTable, SalesAgreement, SalesQuotationTable, SalesTable, VendTable); 7 module parameters pages that get the Cross references tab (AssetParameters, CustParameters, InventParameters, LedgerParameters, ProdParameters, ProjParameters, SrmParameters).
Menu extension1SystemAdministration - adds the Lattice menu.

Processes whose behavior actually changes​

These are the only places where a standard D365 process does something different because Lattice is installed. Each one is gated - read the Gate row before assuming it is active in your environment.

1. Inbound sales order guardrails​

Two handlers evaluate sales orders that arrive through an integration and can put them on hold or lock them against editing; an order hold extension releases an order when its price hold is cleared.

Standard processSales order creation and line maintenance (SalesTable, SalesLine), and clearing order holds (MCRHoldCodeTrans).
Attaches atMGCLatticeInboundOrderPolicy_SalesTable_EventHandler (Inserted and Deleted data events on SalesTable), MGCLatticeInboundOrderPolicy_SalesLine_EventHandler (ValidatingWrite / ValidatingDelete on SalesLine), and MGCLatticeMCRHoldCodeTrans_Table_Extension (chain of command on MCRHoldCodeTrans update and delete, the standard order hold rows).
What changesOn creation the order is flagged as pending policy evaluation: a lightweight state row only, removed again when the order is deleted. The heavy tolerance / hold / auto-confirm work runs separately. Once an order has been confirmed, a configurable edit-lock window makes validation of a line write or delete fail, so a user editing the order in the standard form is blocked. When the standard price hold the policy placed is cleared or removed, the order's Lattice status changes to Released in the same transaction; the standard hold processing itself is unchanged.
Who noticesA salesperson editing a recently confirmed integrated order sees a validation error instead of a successful save. An order can sit On hold without a user putting it there.
GateMaster switch on System administration > Setup > Lattice > Inbound order policy parameters. Self-gating: with the policy off, both order handlers do nothing. They only read the switch, so creating an order never creates the parameters row, and a legal entity without one has the policy off. The hold extension is not gated, so an order held before the policy was switched off is still released when its hold is cleared; when any other hold is cleared or removed it only reads the order's policy state. The creation handler runs inside the order's own transaction and is written with guards rather than a catch, so it cannot fail the order; only the edit lock blocks a line change, on purpose.
Where to lookPage Inbound order policy state shows the evaluation of every inbound order, including holds and edit locks. The Inbound orders on hold tile on the Integration operations workspace counts them.

2. Sales-origin financial dimension stamping​

Standard processSales order creation (SalesTable.insert).
Attaches atMGCLatticeSalesOriginDimension_SalesTable_EventHandler, Inserting data event.
What changesWrites the mapped financial dimensions onto the new order, based on its sales origin: every dimension mapped to the origin is stamped. It uses the Inserting event so the dimensions are written with the order rather than as a follow-up update, and so it does not depend on the SalesTable.insert() signature. A mapping whose dimension or value no longer exists is skipped, and the order is created without that dimension.
Who noticesNew orders carry financial dimensions nobody typed. Downstream ledger postings inherit them.
GateA stamping switch plus the mapping rows on System administration > Setup > Lattice > Sales-origin financial dimension mapping. The switch (Sales-origin dimension stamping enabled, above the grid on the same page) is off by default and set per legal entity; opening the page creates the legal entity's parameters row. Creating an order only reads the switch and never creates the row, so a legal entity without one has stamping off. With no mapping row for an origin, nothing is stamped; deleting a sales origin deletes its mapping rows.

3. Customer-specific retail assortments​

Standard processRetail assortment maintenance (RetailAssortmentTable), assortment publishing (RetailAssortmentLookupTask).
Attaches atMGCLatticeRetailAssortmentTable_Table_Extension (modifiedField, insert, update), plus a table extension adding the MGCLatticeCustAccount field and its legal entity MGCLatticeCustDataAreaId.
What changesAdds an optional customer account field to the assortment. When it is set, the assortment name is defaulted to the customer name so the published assortment is recognizable.
Who noticesA merchandiser who sets the customer field sees the name change under them.
GateAdditive - only fires when the optional field is populated. Leave it blank and the standard behavior is unchanged.

4. Outbound business event logging​

Standard processBusiness event publication (BusinessEventsPublisher.publish).
Attaches atMGCLatticeBusinessEventsPublisher_Class_Extension, Chain of Command.
What changesDurably logs every outbound business event that opts in via IMGCLatticeBusinessEventLoggable to MGCLatticeBusinessEventLog: a Success row with the serialized payload for each publish that reaches the business events commit log, and an Error row when the publish fails outside a database transaction. That failure is recorded, raises the Business event publish failed event, and is not passed on to the calling process. A failure inside a transaction is not caught (X++ runs no catch there): it propagates and rolls back the caller's transaction, and nothing is logged. This is what makes the Business event log page and the reconciliation sweep possible, with no per-event wiring.
Who noticesExtra rows in a Lattice table; a small write on every published opted-in event. Events that do not implement the interface pass straight through with the platform's own behavior: if one fails to publish, the process that raised it gets the error.
GateOpt-in per event class via the interface. In this release two events opt in: Retail assortment published, and Business event publish failed (which never alerts on itself).

Also additive, no behavior change: MGCLatticeSysQueryRangeUtil_Class_Extension adds hour-granular relative-time query range functions (mgcLatticeAfterHoursAgo, mgcLatticeBeforeHoursAgo) that the standard SysQueryRangeUtil only offers at day granularity. It adds new functions; it changes none of the existing ones. Lattice's own workspace count tiles use them, and so can your queries.

Also additive, no behavior change: MGCLatticeProdJournalCheckPost_Class_Extension adds one method that runs the step the production journal page's Post runs before the posting (for a report as finished journal, creating the quality orders that quality associations require), so the journal posting service posts an existing production journal as the page does. It wraps no standard method.

Also additive: MGCLatticeEInvoiceSubmissionStatusChangedEventHandlers stamps the new MGCLatticeSubmittedDateTimeUtc field (Submitted (UTC)) on the standard BusinessDocumentSubmission row when a submission is logged and when a re-submission records a new submitted time. No standard field changes. Because it subscribes to the table's data events, set-based statements on that table run row by row unless the caller skips data events.


Changes you can see on standard pages​

Standard pageWhat Lattice adds
Data management > Data entities (DMFEntity)A Lattice button group with three buttons: OData metadata (opens the Lattice explorer against the selected entity), Export data entity template and Export entity data to Excel (wide).
Data management workspace (DataManagementWorkspace)Two tiles, Export data entity template and OData entity metadata explorer, opened without a selected entity.
Retail assortment details (RetailAssortmentDetails), entity and staging (RetailAssortmentEntity, RetailAssortmentStaging)The optional customer account field (see §3 above).
The 25 record pages covered by cross-reference keys - customers, vendors, sales, purchase, transfer and production orders, products, assets, projects, journals and moreA Cross references button and FactBox (and a Line cross references button and FactBox on pages with lines), shown only when an external system is set up as visible on forms for that record kind.
The 7 module parameters pages (accounts receivable, procurement and sourcing, inventory and warehouse management, fixed assets, project management and accounting, general ledger, production control)A Cross references tab with the per-system settings for that module's record kinds.
Customer parameters entity and staging (CustomerParametersEntity, CustomerParametersStaging)Additional fields exposed for data migration, prefixed so they cannot collide with a later Microsoft field: MGCLatticeMandatoryVATNum, MGCLatticeAdvanceInvoiceCreditCorrection_W, MGCLatticeAdvanceInvoiceReversalCorrection_W, MGCLatticeInvoiceIdEditing_W, MGCLatticePercentCustomersPerBatchTask (the CustParameters fields of the same names without the prefix).
System administration menuThe whole Lattice menu - Setup, Inquiries, Periodic tasks and the two workspace tiles. See Page reference.

Processes Lattice observes​

Everything below leaves the standard process untouched - apart from the submission time the e-invoice handlers stamp (see Finance) - and publishes a business event. The pattern is always the same: wrap the process method that causes the change (not the table insert() / update(), except where noted), call next, compare before-and-after state, and publish only on a genuine transition.

Read this section as "if I do X in D365, Lattice will emit an event". For each event's payload, exact hook and guard, see its page in Event catalog.

Sales​

Standard processHookEvent raised
Confirm a sales orderSalesConfirmJournalPost.postJournalPostSales order confirmed
Post a packing slipSalesPackingSlipJournalPost.postJournalPostSales packing slip posted (not for a cancellation or a return order receipt)
Post a sales invoice or credit noteSalesInvoiceJournalPost.postJournalPostSales order invoice posted
Invoice a return order (post its credit note)SalesInvoiceJournalPost.postJournalPostReturn credit note posted, after Sales order invoice posted
Confirm a sales quotationSalesQuotationEditLinesForm_Sales_Confir.createJournalSales quotation confirmed
Cancel remaining quantitySalesUpdateRemain.cancelOpenOrderLinesDeliveryRemainder; call-center and Commerce-payments orders through MCRSalesOrderCancellation::cancelOrder / cancelOrderFTC; under the Cancel action (cancelMultipleOrdersDeliveryRemainder) the event waits until the cancellation is finalSales order canceled
Create a sales return orderSalesTableType_ReturnItem.insertedSales return order created
Change a sales order lineSalesLine Updated data eventSales order line changed
Register an arrived return order lineSalesLine.returnLineRegisterUpdate() / SalesReturnNonStockedRegistrationHelper.updateOnRegistration() (ReturnStatus moves to Registered)Return order received
Confirm a sales agreementAgreementConfirm_Sales.createHeaderHistorySales agreement confirmed

Pro forma documents raise nothing. A pro forma confirmation, packing slip or invoice runs through the same posting classes but does not raise Sales order confirmed, Sales packing slip posted or Sales order invoice posted. The same applies to free text and project invoices (see Finance).

Purchasing​

Standard processHookEvent raised
Approve a purchase requisitionPurchReqWFStatusTransitionHelper::setPurchReqTable2ApprovedPurchase requisition approved
Create a purchase return orderPurchTableType_ReturnItem.insertedPurchase return order created
Confirm a purchase agreementAgreementConfirm_Purch.createHeaderHistoryPurchase agreement confirmed
Vendor submits an ASNWHSASNItem.insert / update (purchase ASN lines only)Vendor ASN line changed, once per new line and again when a line's quantity changes

Inventory and warehouse​

Standard processHookEvent raised
Any on-hand updateInventUpdateOnhand.insertInventSum + onOnHandUpdated delegate; the events are sent after the transaction commitsOn-hand changed; Item back in stock on a zero-to-positive transition
Ship a transfer orderInventTransferUpdShip.runTransfer order shipped
Receive a transfer orderInventTransferUpdReceive.runTransfer order received
Pick a transfer orderInventTransferUpdPick.runTransfer order picking list created
Run inventory closing or recalculationInventCostLedgerPostingTask.updateLedgerPostingInventory closing completed, once the close or recalculation has finished
Validate a quality orderInventQualityOrderValidate.runQuality order passed / failed
Confirm a warehouse shipment, or ship-confirm a transport loadWHSShipConfirm.shipConfirm; WHSShipConfirmationActionTransportLoad.shipConfirm for transport loadsWarehouse load shipped, once per load that moves to Shipped
Complete warehouse workWHSWorkTable.update, and insert for work created already closedWarehouse work completed; Warehouse picking completed for picking work
Cancel a picking list, or a single picking lineWMSPickingRoute.cancel; post-handler on WMSOrderTransType_Output_OrderPick.cancelPicking list canceled

Production​

Standard processHookEvent raised
Schedule a production orderProdUpdScheduling.runProduction order scheduled
Firm a planned production orderReqTransPoMarkFirm.insertMovementProduction order scheduled (firming creates the order as Scheduled)
Estimate a production orderProdUpdCostEstimation.runProduction order estimated
Start a production orderProdUpdStartUp.runProduction order started
Report as finishedProdUpdReportFinished.runProduction order reported as finished
Post a report-as-finished journalProdJournalCheckPostProd.runProduction order reported as finished
End a production orderProdUpdHistoricalCost.runProduction order ended
Post a pick listProdJournalCheckPostBOM.runPick list posted
Post a route cardProdJournalCheckPostRoute.runRoute card posted
Calculate a BOMBomCalcItem.insertBOMCalcTableBOM calculation completed
Approve a BOM versionBomVersionApprove.runBOM version approved
Run MRPReqCalc.run (the main thread of a master planning run only)MRP run completed (not for a canceled run)

Master data​

Standard processHookEvent raised
Create or edit a customerCustTable.insert / updateCustomer created / updated; customer hold status changed
Create or edit a vendorVendTable.insert / update; VendTable Updated data eventVendor created / updated; vendor hold status changed (also for a vendor created on hold)
Release a productEcoResProductReleaseManager.createInventTable, EcoResProductReleaseManagerItem.releaseReleased product created
Change an external item numberhandler on CustVendExternalItemExternal item changed

Documented exception. Customer and vendor master data have no single orchestrating process method - creation and edit flow through the form data source, the DMF entity and several service paths - so these two hook the table methods deliberately. The class-level comment on each records the exception. They are not the only table-level triggers: where no process method carries the change, other events also hook a table method or a data event, as the Hook columns show.

Finance​

Standard processHookEvent raised
Post a general journalLedgerJournalCheckPost.runInternalPostJournalTransactionEnded delegateGeneral journal posted
Post a vendor payment journalsame delegateVendor payment posted, once per vendor posting on the journal's lines
Post a free text invoiceCustInvoiceJour.insertFree text invoice posted (not for a pro forma invoice)
Post a project invoiceProjInvoiceJour.insertProject invoice posted (not for a pro forma invoice)
Acquire or dispose a fixed assetAssetTrans.insertFixed asset acquisition / disposal posted
Reverse an asset transaction, or reclassify an assetTransactionReversal_Asset.createAssetTrans, AssetReclassification.run (they mark the rows they write)Fixed asset acquisition / disposal posted, flagged isReversal / isReclassification
Complete a bank reconciliationBankAccountReconcile.updateBankAccountStatementToReconciledBank reconciliation completed
Mark an Advanced bank reconciliation worksheet as reconciledBankReconciliationHeader::reconcile / reconcileInBatchAdvanced bank reconciliation completed, after the reconcile transaction commits
Issue a vendor checkBankChequeTable.updateVendor check issued
Exceed a customer credit limitCustCreditLimit.checkCustomer credit limit exceeded
Open or close a collections caseCustCollectionsCaseDetail::createCase / closeCaseCollection case changed
Post collection lettersCustCollectionLetterPost.writeCustCollectionLetterJourCollection letter posted, when the letter is posted (creating a letter does not raise it)
A collection letter changes the level of open transactions (normally when it is posted)CustCollectionLetterJour.updateCollectionLetterCodeCustTransDunning level changed
Submit an electronic invoiceBusinessDocumentSubmission Inserted / Updated data events; Inserting / Updating handlers stamp the new MGCLatticeSubmittedDateTimeUtc field on the submission log rowE-invoice submission status changed, when a submission is logged and each time its status changes

Pricing and trade agreements​

Standard processHookEvent raised
Post a trade agreement journalPriceDiscAdmCheckPost.initJournalNum, createOrUpdatePriceDiscTableRecordsSales price agreement created / modified / superseded
Post a trade agreement journal with lines marked for deletionPriceDiscAdmTable::deleteMarkedSales price agreement deleted
Delete a sales price agreement (by hand, through an entity or in code)PriceDiscTable.deleteSales price agreement deleted
Insert or update any sales price agreement rowPriceDiscTable Inserted / Updated data eventsSales price trade agreement changed (for journal postings, only when the "Skip price agreement insert alerts" / "Skip price agreement update alerts" parameters are No)
A price becomes effective or expiresbatch sweep, not a hookSales price agreement effective / expired

A record-based trigger only fires when a PriceDiscTable row is written. It cannot observe a price simply becoming effective as the clock crosses its FromDate. That gap is closed by a batch sweep - Sales price agreement effectivity (effective/expired) events - which advances a watermark, kept per company and sweep in the new MGCLatticeTradeAgreementPriceEffectivityCursor table, and emits the effective/expired events. The first run with an active event only records its starting position; there is no historical backfill.

Platform and integration​

Standard processHookEvent raised
A batch job changes statusBatchJob.updateBatch job status changed (filterable - see Batch job event filters)
A DMF import/export finishesDMFDefinitionGroupExecution.update; DMFEntityDbExporter::generateEntityDBDataV2 for bring-your-own-database exportsDMF execution completed (an import run without batch is mostly not reported)
An aggregate measurement refreshesBIMeasurementProcessingStatisticsFull.updateAggregate measurement refresh completed
A workflow action is recordedWorkflowTrackingCommentTable.insertWorkflow lifecycle action
A workflow faults, or a work item waits past the thresholdscheduled scan (Workflow stalled/failed alert scan), not a hookWorkflow stalled or failed, once per condition until it changes (tracked in the new MGCLatticeWorkflowAlertState table)
Publish a retail assortmentRetailAssortmentLookupTask.runRetail assortment published, on first publish in a legal entity or when its effective item list changes (tracked in the new MGCLatticeRetailAssortmentPublishState table, whose rows are deleted with the assortment)
A retail info code is answeredRetailTransactionInfocodeTrans.insertRetail info-code response captured
Assign resources to a project task (save a published plan's task resources, or publish a draft plan)ProjTask::reserveResourceActivity; ProjActivityAssignment Inserted / Updated data events for rows written by customizations and importsProject task assigned, once per resource that holds hours on the task
Create a maintenance work orderEntAssetWorkOrderTable Inserted data event; the event is raised when the creating transaction commits (SysTransactionScope.ttsCommitting)Maintenance work order created
A maintenance work order moves to another lifecycle stateEntAssetLifecycleStateUpdate_WorkOrderTable.updateStateRecord()Maintenance work order scheduled / started / completed

Documented exception. The workflow framework records every action - assignment, approval, rejection, delegation, escalation, completion, fault - as a tracking row followed by its comment row (WorkflowTrackingCommentTable), so there is no single process method to wrap. The hook is on the comment row because it is written last, after the new assignee is recorded. The batch job hook is a documented exception for the same reason.


How to verify what is active in your environment​

  1. Business events - open Business event catalog. An event that is not activated in the standard Business events catalog is never published, whatever the trigger does. Nothing is published until you activate and endpoint it.
  2. Guardrails - open Setup > Lattice > Inbound order policy parameters. With the master switch off, the hold and edit-lock behavior in §1 does not run.
  3. Dimension stamping - open Setup > Lattice > Sales-origin financial dimension mapping. With no rows, nothing is stamped. Rows stamp nothing until Sales-origin dimension stamping enabled, above the grid, is selected.
  4. What was actually emitted - Business event log records every outbound event that opts in to logging with its payload and outcome. In this release that is Retail assortment published and Business event publish failed; other events are not logged.
  5. What a process did - Service call log for service-driven work; Inbound message inquiry for file-driven work.

How to turn a customization off​

CustomizationHow to disable
Any business eventDeactivate it in the standard business events catalog. The trigger still runs but publishes nothing.
Inbound order guardrailsMaster switch on the inbound order policy parameters page.
Sales-origin dimension stampingLeave the stamping switch off (the default), or remove the mapping rows.
Retail customer assortmentsLeave the optional customer account field blank.
Outbound event loggingPer-event, by whether the event class implements IMGCLatticeBusinessEventLoggable.

See also​