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 class | MGCLatticeBankReconciliationCompletedBusinessEvent |
| Contract class | MGCLatticeBankReconciliationCompletedBusinessEventContract |
| Category | Bank management |
| Module | ModuleAxapta::Bank |
| Label IDs | BankReconciliationCompletedBusinessEventName / BankReconciliationCompletedBusinessEventDescription |
| Trigger | BankAccountReconcile.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
ReconcileDateis captured beforenext; afterwards the event is sent when that date was empty, the statement now has aReconcileDate, and itsCancelDateis 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 transactionrun()marks each included bank transaction of the statement as reconciled and then callsupdateBankAccountStatementToReconciled(), which stampsReconcileDatewith today's date (in the user's time zone). No other standard code setsBankAccountStatement.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 (
BankAccountTranswith 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 oneBankAccountStatement. It never stampsBankAccountStatement.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
CancelDatewith a set-based update and leavesReconcileDatein 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 field | Display label | Type / EDT | Source | Notes |
|---|---|---|---|---|
legalEntity | Legal Entity | DataAreaId | BankAccountStatement.DataAreaId | Company of the bank account, in lower case (for example usmf). |
bankAccountId | Bank Account ID | CompanyBankAccountId | BankAccountStatement.AccountId | Bank account. |
statementNumber | Statement Number | BankAccountStatementNum | BankAccountStatement.AccountStatementNum | Bank statement number. |
statementDate | Statement Date | TransDate | BankAccountStatement.AccountStatementDate | Bank statement date (date, \/Date(milliseconds)\/ form). |
currencyCode | Currency Code | CurrencyCode | BankAccountStatement.CurrencyCode | Currency of the statement. |
endingBalance | Ending Balance | AmountCur | BankAccountStatement.EndingBalance | Statement ending balance, in currencyCode. |
reconciledDate | Reconciled Date | TransDate | BankAccountStatement.ReconcileDate | Date the statement was reconciled. |
matchedTransactionCount | Matched Transaction Count | int | count(RecId) of BankAccountTrans where AccountId, AccountStatement and AccountStatementDate are the statement's, Included = Yes and Reconciled = Yes | Number of bank transactions reconciled on the statement. |
matchedAmountMST | Matched Amount MST | AmountMST | sum(AmountMST) of the same transactions | Their 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.
Related Events
- Advanced bank reconciliation completed - the same moment for Advanced bank reconciliation worksheets.
- General journal posted - ledger postings, including bank-related journals.
- Vendor payment posted - vendor payments that later appear on bank statements.
- Vendor check issued - checks that clear through the bank account.