Skip to main content

Bank reconciliation completed

Fires when a bank account statement is reconciled with the Reconcile account action of the bank account reconciliation - the classic reconciliation, not Advanced bank reconciliation - at the moment D365 stamps the statement's Reconciled date. It carries the bank account, statement number and date, currency, ending balance and reconciliation date, plus the number of bank transactions reconciled on the statement and their total in accounting currency, giving treasury and cash-management systems a push signal that a statement period has been closed. Advanced bank reconciliation raises Advanced bank reconciliation completed instead.

Event classMGCLatticeBankReconciliationCompletedBusinessEvent
Contract classMGCLatticeBankReconciliationCompletedBusinessEventContract
CategoryBank management
ModuleModuleAxapta::Bank
Label IDsBankReconciliationCompletedBusinessEventName / BankReconciliationCompletedBusinessEventDescription
TriggerBankAccountReconcile.updateBankAccountStatementToReconciled() -> ReconcileDate goes from empty to set while CancelDate is empty

Trigger / Hook​

  • Extension class: MGCLatticeBankAccountReconcile_Class_Extension, [ExtensionOf(classStr(BankAccountReconcile))] - a process hook on the reconcile action, not a table hook.
  • CoC method signature: protected void updateBankAccountStatementToReconciled(BankAccountStatement _bankAccountStatement).
  • Firing condition: the statement's ReconcileDate is captured before next; afterwards the event is sent when that date was empty, the statement now has a ReconcileDate, and its CancelDate is empty - the first time a statement that has not been canceled is marked reconciled. It fires at most once per statement.
  • Process: BankAccountReconcile (menu item Reconcile account, run from the account reconciliation page of a bank statement). Inside one transaction run() marks each included bank transaction of the statement as reconciled and then calls updateBankAccountStatementToReconciled(), which stamps ReconcileDate with today's date (in the user's time zone). No other standard code sets BankAccountStatement.ReconcileDate.
  • Other writers: statements written by data entities, imports, migrations or code outside the reconcile action do not raise the event, even when they set ReconcileDate.
  • Matched totals: when the event is built, the transactions that step has just marked are counted and summed - the statement's bank transactions (BankAccountTrans with the statement's bank account, statement number and statement date) that are included and reconciled.
  • Advanced bank reconciliation is not covered. It reconciles through its own worksheet (BankReconciliationHeader, marked reconciled by the worksheet's Mark as reconciled action) over imported bank statements (BankStmtISOAccountStatement), which can span several statements per worksheet and match statement lines to bank documents rather than to one BankAccountStatement. It never stamps BankAccountStatement.ReconcileDate, so reconciliations done there do not raise this event; they raise Advanced bank reconciliation completed, which reports the worksheet's statements and its matched statement lines and bank transactions in bank currency.
  • Canceling a reconciliation sets CancelDate with a set-based update and leaves ReconcileDate in place; it raises no event, and a canceled statement cannot raise this event again.
  • Timing: send() writes to the business events commit log inside the reconcile transaction and delivery happens asynchronously after commit, so a reconciliation that fails and rolls back never delivers.
  • Enablement gate: BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeBankReconciliationCompletedBusinessEvent)), checked only after the date transition is detected.
protected void updateBankAccountStatementToReconciled(BankAccountStatement _bankAccountStatement)
{
TransDate previousReconcileDate = _bankAccountStatement.ReconcileDate;

next updateBankAccountStatementToReconciled(_bankAccountStatement);

if (previousReconcileDate == dateNull()
&& _bankAccountStatement.ReconcileDate != dateNull()
&& _bankAccountStatement.CancelDate == dateNull()
&& BusinessEventsConfigurationReader::isBusinessEventEnabled(classStr(MGCLatticeBankReconciliationCompletedBusinessEvent)))
{
MGCLatticeBankReconciliationCompletedBusinessEvent::newFromBankAccountStatement(_bankAccountStatement).send();
}
}

Payload Contract​

One row per [DataMember], in declaration order. initialize() reads the reconciled BankAccountStatement row, then counts and sums the statement's included, reconciled BankAccountTrans rows.

JSON fieldDisplay labelType / EDTSourceNotes
legalEntityLegal EntityDataAreaIdBankAccountStatement.DataAreaIdCompany of the bank account, in lower case (for example usmf).
bankAccountIdBank Account IDCompanyBankAccountIdBankAccountStatement.AccountIdBank account.
statementNumberStatement NumberBankAccountStatementNumBankAccountStatement.AccountStatementNumBank statement number.
statementDateStatement DateTransDateBankAccountStatement.AccountStatementDateBank statement date (date, \/Date(milliseconds)\/ form).
currencyCodeCurrency CodeCurrencyCodeBankAccountStatement.CurrencyCodeCurrency of the statement.
endingBalanceEnding BalanceAmountCurBankAccountStatement.EndingBalanceStatement ending balance, in currencyCode.
reconciledDateReconciled DateTransDateBankAccountStatement.ReconcileDateDate the statement was reconciled.
matchedTransactionCountMatched Transaction Countintcount(RecId) of BankAccountTrans where AccountId, AccountStatement and AccountStatementDate are the statement's, Included = Yes and Reconciled = YesNumber of bank transactions reconciled on the statement.
matchedAmountMSTMatched Amount MSTAmountMSTsum(AmountMST) of the same transactionsTheir total in the legal entity's accounting currency, as stored on the transactions (AmountMST).

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": "MGCLatticeBankReconciliationCompletedBusinessEvent",
"ControlNumber": 5637148856,
"EventId": "A93F0B26-5E71-4D8C-B4A2-C0E7D19F63B5",
"EventTime": "\/Date(1790239651000)\/",
"EventTimeIso8601": "2026-09-24T08:47:31.3101444Z",
"MajorVersion": 0,
"MinorVersion": 0,
"BusinessEventLegalEntity": "USMF",
"ContextRecordSubject": "",
"InitiatingUserAADObjectId": "{9E0E481C-DDF2-461E-F503-CA809B9A682C}",
"ParentContextRecordSubjects": [],
"eventSequence": 48195,
"correlationId": "Event:7c04e9b3-a8d2-4f16-9b5e-2d6a1c8f3e70",
"schemaVersion": 1,
"legalEntity": "usmf",
"bankAccountId": "USMF OPER",
"statementNumber": "STMT-2026-08",
"statementDate": "\/Date(1788134400000)\/",
"currencyCode": "USD",
"endingBalance": 1284517.36,
"reconciledDate": "\/Date(1790208000000)\/",
"matchedTransactionCount": 42,
"matchedAmountMST": 183406.12
}

Activation​

In the D365FO client, go to System administration > Setup > Business events > Business events catalog. Find this event by name ("Bank reconciliation completed") or by filtering the Category column to Bank 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). The event only covers bank accounts reconciled with the classic bank account reconciliation; bank accounts that use Advanced bank reconciliation do not raise it. To cover those, also activate Advanced bank reconciliation completed.