Enable Dark Mode!
how-to-create-localization-in-odoo-17.jpg
By: Jumana Haseen

How to Create Localization in Odoo 17

Technical

Localization in Odoo involves implementing specific customizations to make the application suitable and compliant with the requirements of a particular country. The initial step in creating a localization module for Odoo is to configure the Chart of Accounts tailored to that country, along with its related dependencies such as account types, taxes, and other relevant financial settings.

When developing a localization module in Odoo, it's crucial to adhere to a specific naming convention. The format for the module name should be l10n_XX, where XX is the country code. For instance, if the aim is to create a localization module for Latvia, the module should be named l10n_LV. Following this convention ensures clarity and consistency in module naming across different countries. Within the localization module, one can then define various elements such as the chart of accounts, taxes, and other necessary configurations tailored to the requirements of that specific country.

Your worktree should look like this

How to Create Localization in Odoo 17-cybrosys

Initially, include an XML file in the localization module to facilitate testing in demo mode by incorporating a demo company. This allows for easy validation of the localization settings and configurations within a simulated environment. The fields set for this partner include the company's name ("LV Company"), street address, city, country(Latvia), postal code, phone number, email address, and website. This setup is part of the localization process, which tailors the Odoo system to specific regional settings and requirements, in this case for a company based in Latvia. Add these files under the file demo/demo_company.xml,

<?xml version="1.0" encoding="utf-8"?>
<odoo>
   <record id="partner_demo_company_lv" model="res.partner">
       <field name="name">LV Company</field>
       <field name="street">Mana iela</field>
       <field name="city">Riga</field>
       <field name="country_id" ref="base.lv"/>
      
       <field name="zip">LV-1010</field>
       <field name="phone">+371 20 00 00 00</field>
       <field name="email">info@uznemums.lv</field>
       <field name="website">www.uznemums.lv</field>
   </record>

And the company details and bank details given as

   <record id="demo_company_lv" model="res.company">
       <field name="name">LV Company</field>
       <field name="partner_id" ref="partner_demo_company_lv"/>
   </record>
<record id="demo_bank_lv" model="res.partner.bank">
       <field name="acc_number">LV97HABA0012345678910</field>
       <field name="partner_id" ref="partner_demo_company_lv"/>
       <field name="company_id" ref="demo_company_lv"/>
   </record>

The setup is used to execute the _onchange_country_id function for the specified company record, ensuring that any related changes or updates dependent on the country ID are applied to the demo_company_lv company record. 

<function model="res.company" name="_onchange_country_id">
   <value eval="[ref('demo_company_lv')]"/>
</function>

These function calls are part of the localization process, ensuring specific users are associated with a Latvian company and attempting to load the Latvian accounting chart template for that company.

    <function model="res.users" name="write">
       <value eval="[ref('base.user_root'), ref('base.user_admin'), ref('base.user_demo')]"/>
       <value eval="{'company_ids': [(4, ref('l10n_lv.demo_company_lv'))]}"/>
   </function>
   <function model="account.chart.template" name="try_loading">
       <value eval="[]"/>
       <value>lv</value>
       <value model="res.company" eval="obj().env.ref('l10n_lv.demo_company_lv')"/>
   </function>
</odoo>

Configure Chart of Accounts:

Account tags

Tags serve as a mechanism for categorizing accounts, particularly useful when generating complex financial reports with multiple lines. In scenarios where it's challenging to segregate accounts based solely on their codes, tags offer a solution by providing a means to filter accounts according to specific criteria. Each report line can be associated with a distinct tag, allowing for more precise organization and analysis of financial data. To implement this, tags can be incorporated into a CSV file under data/template/account.account-xx.csv, ensuring accounts are appropriately labeled and grouped for reporting purposes.

"id","name","code","account_type","tag_ids","reconcile","name@lv"
"a1110","Research and company development costs","1110","asset_non_current","","False","Petniecibas un uznemuma attistibas izmaksas"
"a1120","Concessions, patents, licenses, trademarks and similar rights","1120","asset_non_current","","False","Koncesijas, patenti, licences, precu zimes un tamlidzigas tiesibas"
"a1130","Other intangible assets","1130","asset_non_current","","False","Citi nematerialie ieguldijumi"
"a1140","Goodwill","1140","asset_non_current","","False","Nemateriala vertiba"
"a1180","Advance payments for intangible assets","1150","asset_prepayments","","False","Avansa maksajumi par nematerialajiem ieguldijumiem"
"a1191","Accumulated depreciation on portion of development costs","1191","asset_non_current","","False","Attistibas izmaksu norakstita dala (pasiva)"
"a1192","Write-down portion of concessions, patents, licenses, trademarks and similar rights","1192","asset_non_current","","False","Koncesiju, patentu, licencu, precu zimju un tamlidzigu tiesibu norakstita dala (pasiva)"
"a1193","Accumulated depreciation on part of the value of other intangible investments","1193","asset_non_current","","False","Citu nematerialo ieguldijumu vertibas norakstita dala (pasiva)"
"a1210","Land, buildings, perennial plantings","1210","asset_fixed","","False","Nekustama ipašuma objekti: Zemes gabali, ekas un buves"
"a1220","Technological equipment and machinery","1220","asset_fixed","","False","Tehnologiskas iekartas un mašinas"
"a1230","Other fixed assets and inventory","1230","asset_fixed","","False","Parejie pamatlidzekli un inventars"

Certainly, a Chart of Accounts relies on the existence of individual accounts. These accounts must be explicitly defined in a separate CSV file to ensure their inclusion and proper categorization within the overall accounting structure.

Account groups

Account groups serve to outline the hierarchical arrangement within the chart of accounts. Enabling the filter in the report activates the functionality, revealing parent accounts when delving into journal entries. This feature operates through the utilization of prefixes 'start' and 'end'; any account with a code falling within this range is assigned to the specified account group as its parent. Additionally, account groups can themselves have parent account groups, facilitating the establishment of a comprehensive hierarchical structure within the chart of accounts. To implement this, account groups can be incorporated into a CSV file under data/template/account.group-xx.csv,

"id","code_prefix_start","name","name@lv"
"l10n_lv_group_1","1","Long-term investments","Ilgtermina ieguldijumi"
"l10n_lv_group_11","11","Intangible assets","Nematerialie ieguldijumi"
"l10n_lv_group_12","12","Fixed assets (property, plant and equipment, investment property and biological assets)","Pamatlidzekli (pamatlidzekli, ieguldijuma ipašumi un biologiskie aktivi)"
"l10n_lv_group_13","13","Investment properties","Ieguldijuma ipašumi"
"l10n_lv_group_14","14","Biological assets (Animals and plants)","Biologiskie aktivi (Dzivnieki un augi)"
"l10n_lv_group_15","15","Long-term financial investments","Ilgtermina finanšu ieguldijumi"

Taxes

Before adding taxes to the system, it's essential to define tax groups. Typically, you'll require a single tax group for each tax rate, except for the 0% rate where it's common to distinguish between exempt, 0%, and not subject taxes. This model mandates just two fields: name and country. To establish tax groups, create a file named data/template/account.tax.group-xx.csv and enumerate the respective groups within it. This approach ensures clarity and organization in categorizing taxes according to their rates and exemptions.To implement this, account tax can be incorporated into a CSV file under  data/template/account.tax.group-xx.csv,

"id","name","country_id","name@lv"
"tax_group_vat_0","VAT 0%","base.lv","PVN 0%"
"tax_group_vat_exempt","W/O VAT","base.lv","BEZ PVN"
"tax_group_vat_5","VAT 5%","base.lv","PVN 5%"
"tax_group_vat_12","VAT 12%","base.lv","PVN 12%"
"tax_group_vat_21","VAT 21%","base.lv",""

Now, taxes can be incorporated using the data/template/account.tax-xx.csv file. Notably, the initial tax defined, whether for purchase or sale, automatically assumes the role of the default tax for corresponding transactions involving products. This streamlined process simplifies tax setup and ensures that the first tax specified serves as the default option for purchase or sale transactions, enhancing efficiency in tax management within the system.

"id","description","name","type_tax_use","amount","sequence","tax_group_id","amount_type","price_include","repartition_line_ids/factor_percent","repartition_line_ids/repartition_type","repartition_line_ids/document_type","repartition_line_ids/tag_ids","repartition_line_ids/account_id","name@lv"
"tax_sale_vat_21","21%","21%","sale","21.0","100","tax_group_vat_21","percent","","100","base","invoice","+41","","21%"
"","","","","","","","","","100","tax","invoice","+52","a5721",""
"","","","","","","","","","100","base","refund","-41","",""
"","","","","","","","","","100","tax","refund","-52","a5721",""
"tax_sale_vat_reverse","0%","Reverse charge VAT","sale","0.0","110","tax_group_vat_exempt","percent","False","100","base","invoice","+411","","Pardošana reversa"
"","","","","","","","","","100","tax","invoice","","",""
"","","","","","","","","","100","base","refund","-411","",""
"","","","","","","","","","100","tax","refund","","",""

In the first file models/template_xx.py, we set the name for the chart of accounts along with some basic fields.

The Python code extends the `account.chart.template` model in Odoo to include Latvian-specific accounting configurations. The `_get_lv_template_data` method, decorated with `@template('lv')`, returns a dictionary with default account properties for the Latvian chart of accounts, specifying account codes for receivable, payable, expense, and income categories, and setting the number of digits for account codes to 4. This customizes the accounting setup for Latvian companies in Odoo.

from odoo import models
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
   _inherit = 'account.chart.template'
   @template('lv')
   def _get_lv_template_data(self):
       return {
           'property_account_receivable_id': 'a2310',
           'property_account_payable_id': 'a5310',
           'property_account_expense_categ_id': 'a7550',
           'property_account_income_categ_id': 'a6110',
           'code_digits': '4',
       }

The Python code defines a method `_get_lv_res_company` for the Latvian localization in Odoo. It sets various accounting configurations for the current company, including enabling Anglo-Saxon accounting, setting Latvia as the fiscal country, and specifying default account codes and prefixes for bank, cash, transfer, currency exchange, and tax accounts. This customizes the company's accounting setup to meet Latvian standards.

@template('lv', 'res.company')
def _get_lv_res_company(self):
   return {
       self.env.company.id: {
           'anglo_saxon_accounting': True,
           'account_fiscal_country_id': 'base.lv',
           'bank_account_code_prefix': '2620',
           'cash_account_code_prefix': '2610',
           'transfer_account_code_prefix': '2699',
           'account_default_pos_receivable_account_id': 'a2613',
           'income_currency_exchange_account_id': 'a8150',
           'expense_currency_exchange_account_id': 'a8250',
           'account_journal_suspense_account_id': 'a26291',
           'account_journal_early_pay_discount_loss_account_id': 'a8299',
           'account_journal_early_pay_discount_gain_account_id': 'a8199',
           'account_journal_payment_debit_account_id': 'a26292',
           'account_journal_payment_credit_account_id': 'a26293',
           'default_cash_difference_income_account_id': 'a8199',
           'default_cash_difference_expense_account_id': 'a8299',
           'account_sale_tax_id': 'tax_sale_vat_21',
           'account_purchase_tax_id': 'tax_purchase_vat_21',
       },
   }

In this way, one can build a localization module for a specific country.

To read more about An Overview of Fiscal Localization in Odoo 17 Accounting, refer to our blog An Overview of Fiscal Localization in Odoo 17 Accounting.


If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message