View source | Discuss this page | Page history | Printable version   

How to create a Taxes Module


About this document

This document is part of the Localization Guide for Openbravo and describes the process of creating a taxes module ready to be distributed through the Central Repository.

Recommended articles

Before reading this howto it is important to have a clear understanding about the Modularity Concepts, specially the process of creating and packing modules.

The main objective of a taxes module is to provide a dataset with the list of common taxes for a concrete country. In case you haven't created yet a dataset, it is recommended to firstly read the How to create a Dataset article to get a general idea before moving to the particular scenario about taxes.

From the functional perspective, it is mandatory to know the way taxes work in Openbravo. The User Guide includes a complete description about it. Reading the following articles is specially crucial for a successful taxes module development:

Finally, just in case your country is internally divided into regions which have special tax configurations, it is recommended to create first a regions module before developing the taxes one. Please read the How to create a regions module article for more information.

Estimated effort

The biggest difficulty in creating a taxes module is on the functional side. A concrete list of the taxes to be included into the module and the way to properly define them in Openbravo is mandatory before creating the taxes module.

A functional expert should spend less than two working days for defining and introducing in the ERP the set of taxes that will be part of the module. Once the taxes definition is ready, exporting the dataset and packaging the module is a straightforward process that should take few hours.


Along with the translation and the chart of account modules, the taxes module is one of the most important parts in the localization for any country.

Apart from the evident benefit of marking it easier for users to configure their taxes, the taxes module has a very important objective: it allows to develop other modules on top of it, like official tax and withholding reports ready to be sent to the Tax Authorities. The taxes defined in the module are used for creating transactions (invoices, orders...). The modules that depend on the tax module know the exact list of taxes defined in the taxes module and which one of them take into account for the report (for example, only take into account the withholding taxes, or the taxes related to imports, etc.).

Please read the How to create an official Fiscal Report based on the Tax Report Launcher article for more information.

Defining the tax configuration

Setting up the environment

The main objective of the taxes module is to include all the configuration related to taxes into a dataset. Depending on the particular scenario for your country, the taxes module could store a great number of tax rates. For example, the Taxes Module for Spain includes more than 100 different tax rates! That means the dataset will have a big size that makes it difficult to manage (review the XML file, check the differences in case of an update, etc.).

When creating a dataset, we need to be sure that only the required data is inserted in the dataset. To make the development of the taxes dataset easier, it is highly recommended to create a new empty client in which only define the configuration of taxes which will later on be included in the dataset. With this simple trick we reduce the risk of inserting wrong data in the dataset.

We can create a new client at the Initial Client Setup window when logged as the System Administrator role. In the example, the new client is called TAXES to make its purpose clear:

LocGuide Taxes 10.png

Now we should log out and log in again inside our TAXES client.

Entering the taxes configuration

Inside our recently created empty client, we must define the tax configuration for our country, which involves several windows and tabs:

Tax Category

Tax Category window provides the way for grouping and managing similar tax rates, for example Sales Taxes or VAT 18%. Every tax rate and product belongs to a tax category, so when a product is selected for an order or an invoice, a tax in this tax category is automatically chosen.

Defining the set of tax categories is the first step we must complete before moving forward. Think about useful tax categories for the users of your country, like for example: Exempt, VAT, VAT for services, reduced VAT, VAT for real estate, etc. and provide clear and concrete names and descriptions for them using the default language for your country.

LocGuide Taxes 20.png

Business Partner Tax Category

Business Partner Tax Category is used to define tax categories to be associated to business partners and tax rates. A business partner may or may not have an associated business partner tax category, and only one business partner tax category can be associated to a business partner (one as vendor and/or one as customer).

A tax rate associated with a business partner tax category will only be applied to partners within the same category. If the tax does not have a business partner tax category defined, the tax will be applied to any partner. That is how you create special taxes that will be applied to some specific partners.

Based on that explanation, you must define the list of business partner tax categories to be included into your module. This decision highly depends on the legal requirements for your country and the set of taxes rates you will later on define. Some examples, taken from the Taxes Module for Spain, are: Retention lease, Lease-hold, Services, Reduced Services, etc.

LocGuide Taxes 30.png

Tax Rate

Tax Rate window is used to define taxes which will be later on included into transactions. Openbravo allows complex tax rate configurations: from simple VAT tax rates to structures composed of various taxes (withholding and/or VAT) at the same time. Please take a look at the User's Documentation Tax Rate article that contains a detailed description about this topic, including several examples of simple and complex tax rates definition.

LocGuide Taxes 40.png

Tax Zone and Regions module

The tax rate may define the zones where this tax is applied, which can be countries or even regions inside countries. In the previous screenshot we have configured a Spanish tax rate called Adquisiciones a Canarias, Ceuta y Melilla to be used only for purchase transactions of goods coming from any of the following Spanish regions: Santa Cruz de Tenerife, Ceuta or Melilla. This was just an example of the Openbravo's powerful tax engine configuration that shows us another possible module to develop in our localization pack: the Regions module.

By default Openbravo includes the complete list of countries in the world, but not their regions. So if your country is internally divided into regions and, specially, when there are different tax rates configurations depending on the regions (like in Spain), it is mandatory to previously create a Regions module that will just include the list of regions for your country. In this case the Regions module will be defined as a dependency of our Taxes module (as we will see later on), that will allow us to include any region in the tax rate configuration.


In some countries with several official languages, it may be useful to include the taxes translation for all these languages. Openbravo defines a Translation tab inside the previous windows to create one translation record per language. In the following screenshot our original tax category is written in Spanish and we have declared an English translation:

LocGuide Taxes 50.png

Once we have created the translations for all the records involved in the taxes configuration we have two possibilities:

In the Dataset definition chapter we will see how to export these translations (and the rest of the taxes configuration).

Creating the Taxes Module

At this point our TAXES client should have all the required taxes configuration that we would want to include into our module. It is the time to create it.

Module definition

As you already know, a taxes module is like any other module that includes a dataset, so there are no special tricks for declaring it inside the Application Dictionary, but just some few considerations:

After the module's definition is ready, you should register the module in case you want to publish it in the Forge

Dataset definition

Dataset definition is the key step in this process. A wrong dataset definition can waste all our previous work, so it is important to follow all these considerations:

LocGuide Taxes 70.png

The dataset definition is ready, so we just need to export it to a file pressing the Export Reference Data button. This process queries the previous tables and gets all the records that fulfill the HQL/SQL Where clause, generating a XML file inside the module's referencedata/standard directory. As a fast check, you can open this file using any plain text editor and you can verify that it contains hundreds of lines.

In case the file is empty, you should double check the dataset definition, specially the HQL/SQL Where clause used for each table.

Testing the Dataset

The real test to ensure the taxes dataset is OK can be done inside our development instance. The test consists on creating a new client running the Initial Client Setup and selecting our taxes module dataset inside the Reference Data section.

LocGuide Taxes 80.png

If the data inside the dataset are consistent, the Initial Client Setup Process should be completed successfully, otherwise it will fail giving a description about the error.

After a successful Initial Client Setup, we just need to login into the new client, go to the Tax Rate, Tax Category and Business Partner Tax Category windows and check no records are missed for these windows and their tabs.

Packaging the Module

To generate the obx file we should follow the standard steps from the command line:

ant export.database
ant package.module -Dmodule=<taxes module java package>

Releasing new versions

Each time you want to release a new version of the taxes module, you must follow this steps:

ant export.database
ant package.module -Dmodule=<taxes module java package>

Considerations when releasing new versions of the Taxes module

During the life of the taxes module is very likely that you will need to release new versions which include some changes: bug fixing, new tax rates, etc. It is very important to ensure our users are able to successfully apply any taxes update.

Updating and Deleting records

When a user applies any dataset, the system remembers the records that belong to this dataset. In case a user applies an update for a dataset, the system will automatically inserts the new records included into the new version, and updates the existing ones in case it is necessary.

However, the system will not automatically delete a record belonging to a dataset even in the case this record is not included anymore into the new dataset version, unless the record is not reference by any other record in the system. This is the expected behaviour to avoid database inconsistencies.

Example: imagine we have included a tax rate into the first version of our dataset and in the second version we have deleted because it was wrong. If a user has previously applied the first dataset version and, for example, he has created an invoice line with this tax rate, the system will not delete the tax rate although it is not included anymore into the new dataset version.

In this kind of scenarios you should deactivate the record and inform the user about the existence of a wrong tax rate, for example through an Alert.

UUIDs management

Each record inside a dataset has associated an unique identifier (UUID) that is used by the system to keep track of the record. The first time we apply a dataset, the UUIDs included into the dataset are directly stored into the database. However, if we apply two or more times the same dataset (for example for several clients or organizations in the same instance) the UUIDs stored into the database will be different from the ones defined in the dataset. This behaviour doesn't create any conflict for the user, but it can be a serious problem for an inexperienced developer.

Example: imagine we apply our taxes module to the TAXES client, and after that we apply it again to the TAXES2 client. If we export the dataset from the TAXES client, the dataset's and database's UUIDs are synchronized, however if we export it from the TAXES2 client the UUID synchronization will be broken and the system will store new UUIDs for the previous records inside the dataset. If a user tries to update to the new version generated from the TAXES2 client, he will end up having duplicated records instead of updating the existing ones.

So the golden rule to use when developing new versions of any dataset is to work always with the first applied data.

Retrieved from ""

This page has been accessed 9,107 times. This page was last modified on 10 May 2013, at 12:53. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.