Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/odoo/documentation/llms.txt

Use this file to discover all available pages before exploring further.

An accounting localization module (l10n_XX) packages a country-specific Chart of Accounts, tax definitions, fiscal positions, and tax reports for Odoo’s accounting module. When the account module is installed, Odoo automatically installs the localization corresponding to the company’s country code. This guide walks through building a complete l10n_XX module.
This guide requires knowledge of Odoo module development. Complete the Server Framework 101 tutorial before proceeding.

Installation Behavior

When account is installed, Odoo’s post-install hook reads the company’s country code and installs the matching l10n_XX module. If no matching localization is found, l10n_generic_coa (US) is installed as the default. For example: if the company’s country is Switzerland, l10n_ch is automatically installed.

Module Structure

A minimal l10n_XX module follows this layout:
l10n_xx/
├── data/
│   ├── template/
│   │   ├── account.account-xx.csv        # Chart of Accounts
│   │   ├── account.group-xx.csv          # Account groups
│   │   └── account.tax.group-xx.csv      # Tax groups
│   └── other_data.xml
├── views/
│   └── xxxmodel_views.xml
├── demo/
│   └── demo_company.xml
├── models/
│   ├── template_xx.py
│   └── __init__.py
├── __init__.py
└── __manifest__.py

Manifest

{
    "name": "COUNTRY - Accounting",
    "version": "1.0.0",
    "category": "Accounting/Localizations/Account Charts",
    "license": "LGPL-3",
    "depends": [
        "account",
    ],
    "data": [
        "data/other_data.xml",
        "views/xxxmodel_views.xml",
    ],
    "demo": [
        "demo/demo_company.xml",
    ],
}

Chart Template

In models/template_xx.py, define the chart of accounts template with the country identifier:
from odoo import models, fields

class AccountChartTemplate(models.AbstractModel):
    _inherit = "account.chart.template"

    def _get_xx_template_data(self):
        return {
            "code_digits": 6,
            "currency_id": "base.XX",  # replace XX with ISO currency code
            "bank_account_code_prefix": "1001",
            "cash_account_code_prefix": "1000",
            "transfer_account_code_prefix": "1002",
            "property_account_receivable_id": "ch_coa_1100",
            "property_account_payable_id": "ch_coa_2000",
        }

Chart of Accounts

Account Tags

Tags allow grouping accounts for financial reports when code-based rules are insufficient. Define them in data/account_account_tag_data.xml.

Accounts

Accounts are defined in data/template/account.account-xx.csv. Each row represents one account:
id,name,code,account_type,reconcile
ch_coa_1000,Cash,1000,asset_cash,FALSE
ch_coa_1100,Accounts Receivable,1100,asset_receivable,TRUE
ch_coa_2000,Accounts Payable,2000,liability_payable,TRUE
ch_coa_1171,Tax Receivable,1171,asset_current,FALSE
Avoid using asset_cash for account type — bank and cash accounts are created directly during localization installation and linked to account.journal. Keep the number of accounts manageable: 200–300 accounts is a good target for most localization packages.

Account Groups

Account groups define the hierarchical structure visible when expanding reports. They match accounts by code prefix range:
id,name,code_prefix_start,code_prefix_end,parent_id
il_account_group_10,Fixed Assets,10,19,
il_account_group_1000,Tangible Fixed Assets,100,109,il_account_group_10

Taxes

Tax Groups

Tax groups organize taxes in reports. Create one group per distinct tax rate (except 0%, which may need separate groups for exempt/0%/not-subject):
id,name,country_id
uk_tax_group_vat_20,VAT 20%,base.uk
uk_tax_group_vat_5,VAT 5%,base.uk
uk_tax_group_vat_0,VAT 0%,base.uk

Tax Definitions

Define taxes in data/template/account.tax-xx.csv. The first purchase/sale tax defined becomes the default for products:
<!-- data/template/account.tax-ae.csv (XML format example) -->
<record id="uae_sale_tax_5" model="account.tax">
  <field name="name">VAT 5%</field>
  <field name="type_tax_use">sale</field>
  <field name="amount">5.0</field>
  <field name="amount_type">percent</field>
  <field name="tax_group_id" ref="ae_tax_group_vat_5"/>
</record>

Tax Report (Enterprise)

The tax report is an Enterprise feature (account_accountant module). It is declared in account but only accessible when the full accounting module is installed.
Create data/account_tax_report_data.xml with a root account.report record:
<odoo>
  <record id="tax_report" model="account.report">
    <field name="name">Tax Report</field>
    <field name="root_report_id" ref="account.generic_tax_report"/>
    <field name="country_id" ref="base.XX"/>
  </record>

  <!-- Report lines follow as account.report.line records -->
  <record id="tax_report_line_base" model="account.report.line">
    <field name="name">Taxable Sales</field>
    <field name="report_id" ref="tax_report"/>
    <field name="sequence">10</field>
  </record>
</odoo>
Tax repartition lines (invoice_repartition_line_ids, refund_repartition_line_ids) link tax amounts to specific report lines via minus_report_line_ids and plus_report_line_ids.

Fiscal Positions

Fiscal positions map taxes and accounts when selling to specific customer categories (e.g., EU intra-community, export). The first fiscal position matching the company’s country is treated as the domestic position. Define in data/template/account.fiscal.position-xx.csv:
id,name,auto_apply,country_id,vat_required
l10n_es_fp_reg,Régimen General,True,base.es,False
l10n_es_fp_ec,Intracomunitario,True,base.es,True

Final Steps: Demo Company

Add a demo company so the localization can be tested in demo mode:
<!-- demo/demo_company.xml -->
<odoo>
  <record id="demo_company_ch" model="res.company">
    <field name="name">Agrolait</field>
    <field name="currency_id" ref="base.CHF"/>
    <field name="country_id" ref="base.ch"/>
    <field name="chart_template" ref="l10n_ch.l10n_ch_chart_template"/>
  </record>
</odoo>

Accounting Reports Module

Accounting reports are added in a separate l10n_XX_reports module that belongs to the enterprise repository. Basic manifest:
{
    "name": "COUNTRY - Accounting Reports",
    "category": "Accounting/Localizations/Reporting",
    "version": "1.0.0",
    "author": "Odoo S.A.",
    "license": "OEEL-1",
    "depends": [
        "l10n_xx",
        "account_reports",
    ],
    "data": [
        "data/balance_sheet.xml",
        "data/profit_and_loss.xml",
    ],
    "auto_install": True,
}
The reports use account.report and account.report.line records to define Balance Sheet, Profit & Loss, and other statutory reports.

Localization Module Checklist

1

Create the module skeleton

Set up __manifest__.py, __init__.py, and the directory structure described above.
2

Define the chart of accounts

Create account.account-xx.csv with 200–300 accounts covering all standard account types.
3

Add account groups

Define hierarchical groups in account.group-xx.csv using code prefix ranges.
4

Create tax groups and taxes

Define tax groups first, then tax templates with proper repartition lines and report line links.
5

Define fiscal positions

Create fiscal positions for domestic, intra-EU, and export scenarios as applicable.
6

Add a demo company

Provide a demo_company.xml that uses your chart template for easy testing.
7

Create the reports module (Enterprise)

In a separate l10n_XX_reports module in the enterprise repo, add statutory financial reports.

Build docs developers (and LLMs) love