# Odoo Bank Reconciliation: Matching Models and Review

- Author: PreciseBankFlow (https://www.precisebankflow.com)
- Published: 2026-04-10
- Updated: 2026-04-10
- Category: Reconciling in accounting software
- Canonical: https://www.precisebankflow.com/blog/odoo-bank-reconciliation

> Odoo bank reconciliation: reconciliation models, matching statement lines to invoices, partial payments and checking the result against the bank.
Odoo bank reconciliation happens in the Bank Matching view. Odoo pairs each bank transaction with invoices, bills or payments by reference and amount, and reconciliation models handle recurring items such as bank fees. You resolve the rest by hand, then group transactions into statements whose starting and ending balances must agree with the bank's.

## How Odoo bank reconciliation matches transactions by default

Odoo matches a bank transaction in two ways before any custom rule runs. Without a partner on the transaction, it compares the transaction's label with invoice, bill and payment references. With a partner set, it compares amounts: exact match first, then a discounted amount, then an amount written in the label.

Odoo's documentation on [bank reconciliation](https://www.odoo.com/documentation/19.0/applications/finance/accounting/bank/reconciliation.html) explains the mechanics for version 19. You open the Bank Matching view from the Accounting Dashboard by clicking the bank journal's name. Each transaction there is tied to a journal entry that posts to the journal's main account and its suspense account until it is fully reconciled. When you match it, the suspense side is replaced by the counterpart's account.

That suspense account is worth watching. Any balance left in it at month-end is money the bank moved that your books have not yet explained. A clean month ends with the suspense account at zero for that journal.

The label-matching rule depends on the bank sending a usable reference. A customer who pays invoice INV/2026/0412 and writes that number in the payment memo is easy. A customer who writes "September" is not. The more your customers quote invoice numbers, the more Odoo matches without help, so print the reference clearly on every invoice.

The partner-based rules depend on Odoo knowing who paid. Odoo's reconciliation models page notes that a model whose counterpart lines name a partner but no account can serve as partner mapping, so a known payer's transactions pick up the right partner.

## Matching an Odoo bank transaction to invoices by hand

A transaction with no automatic match shows action buttons in the Bank Matching view. Reconcile lets you pick existing invoices, bills or payments. Set Account writes the full amount to an account you choose. Receivable and Payable write it to the partner's account. Batches matches a batch payment.

Odoo's reconciliation page lists more options. Sales creates invoices from sales orders and reconciles them. A reconciliation model button applies that model's lines. Up to two suggested actions appear on the line, and the others sit under the ellipsis menu.

Pick the action by what the money really is:

- **A customer paying one invoice.** Use Reconcile and select the invoice.
- **A customer paying several invoices at once.** Use Reconcile and select each invoice the payment covers. Check the total against the bank amount before you confirm.
- **A deposit made of several cheques.** If your team registered the cheques as a batch payment, use Batches, which creates a counterpart for each payment in it.
- **A payment you cannot place yet.** Leave it unreconciled. Writing it to an account just to clear the screen moves the question somewhere harder to find.

Once reconciled, the line shows the matched counterparts or the account it was written to. To reverse a match, Odoo says to delete all counterpart items on the transaction with the trash icon. Removing a reconciled match is a careful job in any system, and the [guide to unreconciling in QuickBooks Online](/blog/how-to-unreconcile-in-quickbooks-online) shows the same caution in another product.

## How does Odoo handle a partial payment on a bank transaction?

Odoo treats a bank amount smaller than the invoice as a partial payment. The invoice stays open for the unpaid part. If the shortfall is a deduction you accept, such as a bank charge taken by the payer, you mark the invoice fully paid when editing the line and write the difference off.

Odoo's documentation gives the steps. To close an underpaid invoice, edit the line, click **fully paid**, and save. To reverse that choice, edit the line again and choose partial payment. If the bank amount is larger than the invoice, the transaction is only partly reconciled, and you reconcile the remaining balance like any other amount.

### A worked partial payment

The figures below are made up to show the method.

| Item | Amount |
| --- | --- |
| Invoice INV/2026/0412 | 2,400.00 |
| Bank transaction from the customer | 2,375.00 |
| Shortfall | 25.00 |

There are three honest outcomes for the 25.00:

1. **The customer still owes it.** Leave it as a partial payment. The invoice shows 25.00 open on the aging, and someone chases it.
2. **A bank or card fee was deducted.** Mark it fully paid and send 25.00 to a bank fees expense account.
3. **An early-payment discount was taken.** If the payment terms offer a discount, Odoo's discounted-match rule may already have caught it. If not, record it to the discount account.

The wrong outcome is marking it fully paid with no idea why 25.00 is missing. That is how small amounts become unexplained write-offs.

A shortfall of an amount divisible by 9 deserves a second look before any write-off. It can mean two digits were swapped when someone keyed the invoice or the payment, a pattern explained in [finding a transposition error in a bank reconciliation](/blog/transposition-error-in-bank-reconciliation).

## Setting up Odoo reconciliation models for fees and transfers

A reconciliation model is a rule that adds to Odoo's default matching. A manual model appears as an action button while you reconcile. An automated model applies on its own to any transaction that meets its conditions. Each model has matching conditions and counterpart lines, which say what journal items to create.

Odoo's documentation on [reconciliation models](https://www.odoo.com/documentation/19.0/applications/finance/accounting/bank/reconciliation_models.html) describes the parts:

- **Conditions** filter by journal, partner, amount and label. Labels can use Contains, Not Contains or Match Regex. A transaction must meet every condition for the model to apply. A model with no conditions applies to everything.
- **Counterpart lines** each create a journal item. The amount type can be Fixed, a percentage of the remaining balance, a percentage of the statement line, or a value read from the label with a regular expression.

Odoo ships defaults, including Internal Transfers and Bank Fees. The Bank Fees model sends the remaining balance to a bank fees account and only applies to transactions whose label contains "Bank Fees". The accounts behind the defaults depend on your fiscal localization.

### Three example models

These are examples to adapt, not Odoo's defaults.

| Model | Type | Conditions | Counterpart line |
| --- | --- | --- | --- |
| Monthly account fee | Automated | Bank journal; label contains "MONTHLY SERVICE FEE"; amount under 50.00 | 100% of balance to bank charges expense |
| Card processor deduction | Manual | Bank journal; partner is the card processor | 100% of balance to merchant fees expense |
| Transfer to savings | Manual | Label contains "TRANSFER TO SAV" | 100% of balance to the internal transfer account |

Keep the automated list short. An automated model posts without anyone looking. The monthly fee in the table is safe to automate because the label is exact and the amount cap stops it from catching anything large. The card deduction is better as a manual button: someone sees each one and confirms it before it posts.

Other small-business systems face the same setup questions: how narrow should a rule be, and who reviews what it does? The [Zoho Books reconciliation guide](/blog/zoho-books-reconciliation) works through them for that product.

## Which Odoo reconciliation model wins when several match?

When a transaction meets the conditions of more than one automated model, Odoo applies the first model in the sequence. You change the order by dragging models in the list. Put the narrowest rule at the top and the broadest at the bottom, so a specific rule always gets the first chance.

Here is how order goes wrong. Suppose a broad model says: label contains "FEE", write to bank charges. Below it sits a narrow model: label contains "WIRE FEE REFUND", write to other income. A wire fee refund contains "FEE", so the broad model takes it first and books a refund as a charge. Reverse the order and each lands where it belongs.

Review the sequence whenever you add a model. Test a new automated model on last month's transactions in a copy of the database if you have one, or set it up as manual for a month, watch what it would catch, then switch it to automated.

## Checking Odoo bank statements against the bank's ending balance

Grouping transactions into statements is optional in Odoo, but it is how you prove the month. Each statement records a starting and an ending balance. Odoo warns when the starting balance does not equal the previous statement's ending balance, or when the ending balance does not equal the starting balance plus the transactions.

Odoo's page on [bank transactions and statements](https://www.odoo.com/documentation/19.0/applications/finance/accounting/bank/transactions.html) explains how to create one. In the Bank Matching view, hover on the most recent transaction that belongs to the statement and click the **Statement** button on the separator line. Odoo creates a statement from that transaction down to the oldest one not yet in a statement. Fill in the reference, check the **Starting Balance** and **Ending Balance**, attach the bank's PDF, and save.

Treat the warning as a stop sign. Odoo lets you save without resolving it, for flexibility. A reviewer should not accept a statement saved that way. A mismatch means a transaction is missing from the import, appears twice, or has the wrong amount.

Duplicates are the usual cause after a bank sync hiccup. Odoo has a **Find Duplicate Transactions** action in the Bank Matching view. It flags likely duplicates by amount, date and account number, or by transaction ID for bank-synced lines, and lets you delete the ones you confirm.

Odoo's documentation also notes that you should create an opening transaction for the account's balance on the day you start importing. Without it, every statement's ending balance is off by the same amount forever.

## Mistake: an automated Odoo model that writes off real differences

An automated model with a wide condition and a percentage-of-balance counterpart will write off any amount it catches. That saves time on fees. On anything else, it turns errors into expenses with no human review. The fix is narrow conditions, amount caps and manual models for anything that needs judgment.

Signs that a model has gone too far:

- The bank fees account grows faster than the bank's fee schedule explains.
- Customer balances age while the bank shows payments arriving.
- A model has no amount cap, or a label condition one word long.

Open the journal items the model created last month. Read twenty of them. If more than one surprises you, narrow the conditions or switch the model to manual.

The same balance between speed and review applies in lighter systems. The guide to [FreshBooks bank reconciliation](/blog/freshbooks-bank-reconciliation) shows what an accountant adds when the software's own checks are thin. For firms reviewing client books from Odoo or elsewhere, PreciseBankFlow checks each bank statement foots and lists duplicate and unmatched lines with their evidence. It is opening to firms in small groups, and you can [request a place](/get-started).
