Add Filters to Accounting Reports in Odoo 18
By Braincuber Team
Published on January 13, 2026
Your CFO wants a Profit & Loss report showing only expense accounts 6000-6999. Your auditor needs the Balance Sheet filtered to show only bank and cash accounts. The standard Odoo reports include all accounts by default, and manually excluding entries isn't practical when you have hundreds of transactions. You need custom filters that let users select exactly which accounts appear in each report.
Odoo 18 allows you to add custom filters to accounting reports through module development. By extending the account.report model and adding QWeb templates, you can create dropdown filters that let users select specific accounts, partners, journals, or any other criteria. When the report generates, it applies your filter domain and shows only matching data. This tutorial walks through the complete implementation: model changes, view XML, Python filter logic, QWeb UI templates, and manifest configuration.
What You'll Build: A custom Account Filter for accounting reports. Users can enable the filter per report, then select specific accounts from a dropdown. The report automatically shows only transactions for selected accounts. Same pattern works for any custom filter.
Implementation Overview
Model Extension
Add filter_account Boolean field to account.report model to enable/disable the filter per report.
View XML
Inherit the report form view and add the filter field to the UI so admins can enable it.
Filter Logic
Python methods to initialize options and build the domain that filters report data.
QWeb Template
Frontend template for the account dropdown in the report's filter bar.
Module Structure
account_filter/
βββ __init__.py
βββ __manifest__.py
βββ models/
β βββ __init__.py
β βββ account_report.py
βββ views/
β βββ account_report_views.xml
βββ static/
βββ src/
βββ components/
βββ account_filter_templates.xml
Step 1: Extend the Model
First, add a Boolean field to the account.report model. This field controls whether the Account filter is available for each report. Create models/account_report.py:
from odoo import api, fields, models
class AccountReport(models.Model):
_inherit = 'account.report'
filter_account = fields.Boolean(
string="Accounts",
compute=lambda x: x._compute_report_option_filter('filter_account'),
readonly=False,
store=True,
depends=['root_report_id', 'section_main_report_ids'],
)
def _init_options_account(self, options, previous_options):
"""Initialize account filter options from previous selection."""
if not self.filter_account:
return
options['account'] = True
# Get previously selected accounts
previous_account_ids = previous_options.get('account_ids') or []
selected_account_ids = [int(acc) for acc in previous_account_ids]
# Search with access rules applied
selected_accounts = (
selected_account_ids and
self.env['account.account'].with_context(active_test=False).search(
[('id', 'in', selected_account_ids)]
) or self.env['account.account']
)
options['selected_account_ids'] = selected_accounts.mapped('name')
options['account_ids'] = selected_accounts.ids
@api.model
def _get_options_accounts_domain(self, options):
"""Build domain to filter by selected accounts."""
domain = []
if options.get('account_ids'):
account_ids = [int(acc) for acc in options['account_ids']]
domain.append(('account_id', 'in', account_ids))
return domain
def _get_options_domain(self, options, date_scope):
"""Extend the report domain with account filter."""
self.ensure_one()
domain = super()._get_options_domain(options, date_scope)
domain += self._get_options_accounts_domain(options)
return domain
Key Methods:
filter_account- Boolean to enable/disable filter per report_init_options_account()- Loads previously selected accounts into options_get_options_accounts_domain()- Builds domain from selected account IDs_get_options_domain()- Combines account filter with other report filters
Step 2: Module Init Files
Create the __init__.py files to properly import your model:
from . import account_report
from . import models
Step 3: Add Field to View
Create the XML view to add the filter_account field to the report configuration form:
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_report_form_inherit_filter_account"
model="ir.ui.view">
<field name="name">account.report.form.inherit.account.filter</field>
<field name="model">account.report</field>
<field name="inherit_id" ref="account_reports.account_report_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='filter_partner']" position="after">
<field name="filter_account"/>
</xpath>
</field>
</record>
</odoo>
Step 4: QWeb Filter Template
Create the QWeb template that adds the account dropdown to the report's filter bar. This goes in static/src/components/:
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<!-- Extend the report filter bar to add account filter -->
<t t-name="account_filter.accountingReportAccountFilter"
t-inherit="account_reports.AccountReportFiltersCustomizable"
t-inherit-mode="extension">
<xpath expr="//t[@t-if='controller.filters.show_period_comparison']"
position="after">
<t t-if="'account' in controller.options">
<div id="filter_account" class="filter_account">
<t t-call="account_reports.AccountReportFilterAccounts"/>
</div>
</t>
</xpath>
</t>
<!-- Define the account dropdown component -->
<t t-name="account_reports.AccountReportFilterAccounts">
<Dropdown menuClass="'account_report_filter account'">
<button class="btn btn-secondary">
<i class="fa fa-folder-open me-1"/>Accounts
</button>
<t t-set-slot="content">
<div class="dropdown-item gap-2 align-items-center">
<label>Accounts</label>
<MultiRecordSelector
t-props="getMultiRecordSelectorProps(
'account.account',
'account_ids'
)"/>
</div>
</t>
</Dropdown>
</t>
</templates>
QWeb Template Components:
The template uses Odoo's built-in Dropdown component and MultiRecordSelector for the account picker. The getMultiRecordSelectorProps function connects the selector to the account.account model and stores selections in account_ids.
Step 5: Module Manifest
Create the __manifest__.py file to register your module, views, and assets:
{
'name': 'Account Filter in Financial Reports',
'version': '18.0.1.0.0',
'category': 'Accounting',
'summary': 'Add custom account filter to accounting reports',
'description': """
This module adds an Account filter to Odoo accounting reports.
Users can enable the filter per report and select specific
accounts to include in the report output.
""",
'author': 'Your Company',
'website': 'https://www.yourcompany.com',
'license': 'LGPL-3',
'depends': [
'account',
'account_reports',
],
'data': [
'views/account_report_views.xml',
],
'assets': {
'web.assets_backend': [
'account_filter/static/src/components/**/*',
],
},
'installable': True,
'application': False,
'auto_install': False,
}
Using the Account Filter
Install the Module
- Place module in addons folder
- Update app list: Apps β Update Apps List
- Search for "Account Filter" and install
Enable Filter on Report
- Go to Accounting β Configuration β Accounting Reports
- Open a report (e.g., Profit and Loss, Balance Sheet)
- Check the Accounts checkbox in the filter options
- Save the report
Use the Filter
- Open the report from Accounting β Reporting
- Click the Accounts dropdown in the filter bar
- Select one or more accounts
- Report updates to show only selected accounts
Extending for Other Filters
CUSTOM FILTER IMPLEMENTATION PATTERN
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
STEP 1: ADD BOOLEAN FIELD TO account.report
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
filter_journal = fields.Boolean(
string="Journals",
compute=lambda x: x._compute_report_option_filter('filter_journal'),
readonly=False, store=True,
depends=['root_report_id', 'section_main_report_ids'],
)
STEP 2: INITIALIZE OPTIONS METHOD
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def _init_options_journal(self, options, previous_options):
if not self.filter_journal:
return
options['journal'] = True
# Load previous selections...
STEP 3: BUILD DOMAIN METHOD
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@api.model
def _get_options_journals_domain(self, options):
domain = []
if options.get('journal_ids'):
journal_ids = [int(j) for j in options['journal_ids']]
domain.append(('journal_id', 'in', journal_ids))
return domain
STEP 4: EXTEND _get_options_domain
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def _get_options_domain(self, options, date_scope):
domain = super()._get_options_domain(options, date_scope)
domain += self._get_options_journals_domain(options)
return domain
STEP 5: ADD VIEW XML FIELD
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
<field name="filter_journal"/>
STEP 6: CREATE QWEB DROPDOWN TEMPLATE
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
<t t-if="'journal' in controller.options">
<Dropdown>...filter UI...</Dropdown>
</t>
COMMON FILTERS YOU CAN ADD
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β’ Journal filter (filter by sales, purchase, bank journals)
β’ Product filter (for specific inventory reports)
β’ Analytic Account filter
β’ Currency filter
β’ Department filter (custom field)
β’ Project filter (custom field)
Best Practices
β Report Filter Development Best Practices:
- Use compute with _compute_report_option_filter: This ensures proper initialization and inheritance behavior
- Apply access rules: Use
search()instead ofbrowse()to respect user permissions - Handle empty selections: Check if filter IDs exist before building domain
- Use MultiRecordSelector: Odoo's built-in component handles the UI complexity
- Test with multiple reports: Verify filter works on Balance Sheet, P&L, General Ledger, etc.
- Consider performance: Adding too many filters can slow report generation
- Document for users: Create help text explaining what each filter does
- Version your module: Use proper versioning for updates and migrations
Conclusion
Adding custom filters to Odoo 18 accounting reports requires four components working together: a Boolean field on the account.report model, Python methods to initialize options and build domains, an XML view to expose the field in report configuration, and a QWeb template for the filter dropdown in the report UI. Once implemented, users can enable the filter per report and select specific accounts (or other records) to narrow down report data. This same pattern extends to any custom filter you needβjournals, products, analytic accounts, or custom fields.
π― Key Takeaway: Boolean field on model β Python init/domain methods β XML view field β QWeb dropdown template β Manifest assets. Same pattern for any custom filter. Users enable per report, select values, report filters automatically.
