E-invoice submission status changed
Fires when a document submission is logged by the Electronic invoicing integration - announcing its first status - and again each time the submission's status changes afterwards, for example from Scheduled to Completed, Failed or Pending service response. D365 tracks each submission on the Electronic document submission log (BusinessDocumentSubmission) and updates its status as the Electronic invoicing service processes the document and reports back (including responses from the tax authority or network the service submits to). Downstream systems can use the event to follow each document through submission and to alert on failures without polling the log.
| Event class | MGCLatticeEInvoiceSubmissionStatusChangedBusinessEvent |
| Contract class | MGCLatticeEInvoiceSubmissionStatusChangedBusinessEventContract |
| Category | Accounts receivable |
| Module | ModuleAxapta::Customer |
| Label IDs | EInvoiceSubmissionStatusChangedBusinessEventName / EInvoiceSubmissionStatusChangedBusinessEventDescription |
| Trigger | BusinessDocumentSubmission inserted (DataEventType::Inserted), or updated (DataEventType::Updated) with State different from orig().State |
Trigger / Hook
- Handler class:
MGCLatticeEInvoiceSubmissionStatusChangedEventHandlers, with four data event handlers onBusinessDocumentSubmission:BusinessDocumentSubmission_onInserted,[DataEventHandler(tableStr(BusinessDocumentSubmission), DataEventType::Inserted)]- sends the event with the first status of a newly logged submission.BusinessDocumentSubmission_onUpdated,[DataEventHandler(tableStr(BusinessDocumentSubmission), DataEventType::Updated)]- sends the event when the update changedState.BusinessDocumentSubmission_onInsertingandBusinessDocumentSubmission_onUpdating(Inserting/Updating) - send nothing; they stamp the UTC submission time on the row (seesubmittedDateTime).
- Method signatures:
public static void <handler>(Common _sender, DataEventArgs _e). - Firing condition: every newly logged submission; afterwards, every update whose
Statediffers fromorig().State. Updates that leave the status unchanged are ignored - including D365's periodic refresh of the pending-response timestamps. Temporary (in-memory) buffers of the table are ignored. - First status: D365 logs a new submission either directly with its first result (Scheduled, or Failed when the submission call itself fails) or - when its submission-locking behavior is switched on - first as Processing while it calls the service, updating the row to the result afterwards. Whichever status the row is inserted with is announced, followed by an event for each later change. If the service call fails without any response, D365 deletes the new Processing row again; its Processing event has already been sent and no further events follow for that row.
- Every status change qualifies, including intermediate processing states (for example Executing, Pending, Processing), not only final outcomes; filter on
submissionStatusNameif you only need some of them. - Not limited to customer invoices: every document type submitted through Electronic invoicing writes to the same log, and
sourceTableName/sourceRecIdidentify the source document. - Set-based statements: because Lattice subscribes to the table's data events, set-based inserts and updates of the log (such as the pending-response refresh) are carried out row by row unless they run with
skipEvents(true). Writes withdoInsert()/doUpdate(), or set-based statements run withskipEvents(true), raise nothing and are not stamped. - Timing:
send()writes to the business events commit log inside the transaction that writes the log row and delivery happens asynchronously after commit, so a write that is rolled back never delivers. - Enablement gate:
BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeEInvoiceSubmissionStatusChangedBusinessEvent)), checked after the status comparison. - Database: the UTC stamp is stored in a field that Lattice adds to the log table (
BusinessDocumentSubmission.MGCLatticeSubmittedDateTimeUtc), so installing Lattice includes a database synchronization for that table.
[DataEventHandler(tableStr(BusinessDocumentSubmission), DataEventType::Inserted)]
public static void BusinessDocumentSubmission_onInserted(Common _sender, DataEventArgs _e)
{
BusinessDocumentSubmission submission = _sender as BusinessDocumentSubmission;
if (!submission.isTmp()
&& BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeEInvoiceSubmissionStatusChangedBusinessEvent)))
{
MGCLatticeEInvoiceSubmissionStatusChangedBusinessEvent::newFromBusinessDocumentSubmission(submission).send();
}
}
[DataEventHandler(tableStr(BusinessDocumentSubmission), DataEventType::Updated)]
public static void BusinessDocumentSubmission_onUpdated(Common _sender, DataEventArgs _e)
{
BusinessDocumentSubmission submission = _sender as BusinessDocumentSubmission;
// Fire only on a genuine submission status transition, not on every update to the log row.
if (submission.isTmp()
|| !MGCLatticeEInvoiceSubmissionStatusChangedEventHandlers::isStatusChange(submission.orig().State, submission.State))
{
return;
}
if (BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeEInvoiceSubmissionStatusChangedBusinessEvent)))
{
MGCLatticeEInvoiceSubmissionStatusChangedBusinessEvent::newFromBusinessDocumentSubmission(submission).send();
}
}
Payload Contract
One row per [DataMember], in declaration order. All sources are fields on the inserted or updated BusinessDocumentSubmission row, mapped in initialize().
| JSON field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | BusinessDocumentSubmission.DataAreaId | Company of the submission log row, in lower case (for example usmf). |
documentReference | Document Reference | str | BusinessDocumentSubmission.UID | The submission's unique identifier (a GUID) as text. |
sourceTableName | Source Table Name | str | tableId2name(BusinessDocumentSubmission.RefTableId) | Table name of the submitted source document, for example CustInvoiceJour. |
sourceRecId | Source Rec Id | RefRecId | BusinessDocumentSubmission.RefRecId | Record ID of the source document in that table. |
submissionStatus | Submission Status | int | enum2int(BusinessDocumentSubmission.State) | The status now on the row - the first status when the submission is logged, the new status on a change - as a BusinessDocumentState integer: 0 = Scheduled, 1 = Canceled, 2 = Deleted, 3 = ValidationFailed, 4 = Executing, 5 = Completed, 6 = Failed, 7 = Pending, 8 = ExecutionFailed, 9 = PostProcessFailed, 10 = PendingResponse, 11 = PendingUpdateActionsExecution, 12 = Processing. The previous status is not included. |
submissionStatusName | Submission Status Name | str | enum2Symbol(enumNum(BusinessDocumentState), ...) | Symbol of that status, for example Completed or Failed. |
responseDetail | Response Detail | str | BusinessDocumentSubmission.ErrorMsg | Error message recorded on the log row; empty when there is none. |
submittedDateTime | Submitted Date Time | utcdatetime | BusinessDocumentSubmission.MGCLatticeSubmittedDateTimeUtc | When the submission was logged, or last re-submitted, in UTC (\/Date(milliseconds)\/ form). Lattice stamps it when the row is inserted and again whenever a re-submission records a new submitted time, because D365 itself keeps that time only as local-time text in the submitting user's format. Empty (the null date) for submissions logged before Lattice was installed. |
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, not 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; an event that joins no run carries Event: followed by a lower-case GUID unique to this emission) 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": "MGCLatticeEInvoiceSubmissionStatusChangedBusinessEvent",
"ControlNumber": 5637148841,
"EventId": "5B1E7C40-2D98-4A63-B0F5-9E4C6A2D8B17",
"EventTime": "\/Date(1790270772000)\/",
"EventTimeIso8601": "2026-09-24T17:26:12.2840727Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{0687AE1C-2598-6D19-FEEC-7C440C5DAAC3}",
"ParentContextRecordSubjects": [],
"eventSequence": 48349,
"correlationId": "Event:4f2a8d61-c07e-4b39-8e1d-6a5b3c9f0e24",
"schemaVersion": 1,
"legalEntity": "usmf",
"documentReference": "6e1b7c3a-2f48-4d9e-a5c1-7b3d9e0f2a64",
"sourceTableName": "CustInvoiceJour",
"sourceRecId": 5637168412,
"submissionStatus": 5,
"submissionStatusName": "Completed",
"responseDetail": "",
"submittedDateTime": "\/Date(1790242337000)\/"
}
Activation
In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("E-invoice submission status changed") or by filtering the Category column to Accounts receivable. 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). The event only fires where documents are submitted through the Electronic invoicing integration, since that is what writes the Electronic document submission log.
Related Events
- Free text invoice posted - free text invoices are typical e-invoice source documents.
- Sales order invoice posted - sales order invoices are typical e-invoice source documents.
- Project invoice posted - project invoices can also be submitted electronically.
- Return credit note posted - credit notes of return orders, which can also be submitted electronically.