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

How to create a Module that Overrides Accounting

Contents

About this document

This document is part of the Localization Guide for Openbravo and describes the process of creating a module that overrides the default accounting behaviour implemented in Core, allowing the developer to modify the way entries are generated when posting documents.


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.

During the development of this module it will be necessary to create a dataset that includes the accounting template configuration. 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 forward.

From the functional side you should have a general idea about accounting configuration in Openbravo, specially the role of the General Ledger Configuration, and how the configuration defined at the Active Tables and Documents tabs affects the accounting engine.

The development is based on the concept of Accounting Templates, so it would be recommended to read its project documentation.

As you can imagine, the logic for overriding the default accounting entries must be implemented using Java. It is required to have good level in Java for developing this module.

Finally it is highly recommended to use Eclipse IDE. Please refer to the How to setup Eclipse IDE article if you haven't done it yet.

Estimated effort

The Openbravo accounting engine provides an infrastructure that easily allows the implementation of code that overrides its behaviour. The effort for developing this kind of modules highly depends on the complexity required for implementing the logic that generates the new accounting entries.

The flow for developing this logic usually consists on copying the original code in charge of creating the entries, which is distributed inside Core under the Openbravo Public License, and adapting it to the particular requirements.

As a rough estimation, the whole process of creating the module, testing and publishing in the Forge shouldn't take more than 4 days for an average developer.

Introduction

The accounting entries generated by Openbravo are usually fine in most scenarios, however there could be the case where these entries don't fulfill the legal requirements for a concrete country, making it necessary to generate them in a different way.

To support this kind of requirements, Openbravo allows to override the code that generates the accounting entries through what is called Accounting Templates. Each time a document is posted, the accounting engine checks whether there is defined any Accounting Template for the associated table or for the concrete document and execute it instead of the default Core's code.

This is a powerful feature that must be used with caution. The code that generates the accounting entries must be deeply tested before deploying it in a real instance.

Creating the module definition

Each time we plan to develop a new module, the first step must always be to create the module's definition and to register it in the Central Repository.

These are the special considerations for our module:

Now you should export the database to generate the file structure inside the module folder

ant export.database

Finally, inside the modules/<accounting template java package> directory create the src folder, where we will store the Java class that implements the logic for generating the new accounting entries.

LocGuide AcctTemplate 20.png

Setting up Eclipse

In case you are using Eclipse, you must now add the modules' src directory in the Openbravo project Build path. Right click on the openbravo project and select Build Path > Configure Build Path

LocGuide Remittance 50.png

Now, inside the Source tab, press Add Folder... button and select your module src directory.

LocGuide AcctTemplate 40.png

In case the src directory is not shown, you may first need to refresh the openbravo project in Eclipse.

Creating the Accounting Template Configuration

The Java class that implements the generation of the new accounting entries is defined into the Accounting Templates window. The definition is quite simple and only requires a name, the Java class name, which must be obviously inside the java package of our module, and the table for which we want to override its accounting entries (for example, C_Invoice for Invoices, M_InOut for goods shipments/receipts, etc.)

LocGuide AcctTemplate 50.png

This Accounting Template will be later on associated to the Active Tables or a Document. So in this step is important to define as many Java classes as Active Tables or Document to override their accounting behavior.

For example, we can define an unique java class for overriding the accounting behavior of all the invoices (sales invoices, purchase invoices, purchase/sales credit memo, etc.), or alternatively define a class for overriding only the accounting entries for Purchase Invoices (AP Invoice) and keep the default behavior to the rest of the invoices.

In this how to we are going to create just one template to override the Invoice table, but it's up to you to create as many templates as necessary inside the same module.

Dataset definition

Dataset definition is a 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 AcctTemplate 60.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 several 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 select our new dummy accounting template dataset.

LocGuide AcctTemplate 70.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 Accounting Templates window and check our record is there.

Implementing the accounting logic

Up to now we have just created the module definition and the required configuration that is included into a dataset. It is time now to develop the logic for creating the new accounting entries.

Dummy accounting entries example

As an example for this article we are going to create an accounting template for Invoices that generates exactly the same accounting entries but multiplied by 2.

Example: we have registered a sales invoice that originally generates this accounting entries:

LocGuide AcctTemplate 80.png

If we now unpost and post the same invoice using our dummy accounting template, all the entries will have a double amount.

LocGuide AcctTemplate 90.png

Creating the Java Package

Inside the Creating Accounting Template Configuration we set org.openbravo.localizationguide.accountingtemplate.DummyAccountingTemplate as the Java Class Name that will implement the new logic for the accounting entries.

Let's first create the org.openbravo.localizationguide.accountingtemplate package inside our module src directory. If you are using Eclipse you can easily create (Ctrl-N) the new package inside the modules/<your module>/src folder

LocGuide AcctTemplate 100.png

LocGuide AcctTemplate 110.png

Creating the Java Class

A bit of theory

At the org.openbravo.erpCommon.ad_forms package there is a set of classes which start by Doc and that implement the default accounting behaviour in Core. Examples of this classes are DocInvoice.java, DocAmortization.java or DocInOut.java that implement the accounting logic for Invoices, Amortizations and Goods shipments/receipts respectively. As you can see, all these classes extend from the Accounting Server class, which means they implement accounting logic.

You have probably noticed that, apart from these classes, we have other classes with the same name pattern but ending in Template, like DocInvoiceTemplate.java. This kind of classes are the ones that allow overriding the accounting behaviour of a concrete class. Let's see how they look like:

 
public abstract class DocInvoiceTemplate { 
  private static final long serialVersionUID = 1L; 
  public DocInvoiceTemplate() {} 
 
  public abstract Fact createFact(DocInvoice docInvoice, AcctSchema as, ConnectionProvider conn, Connection con, VariablesSecureApp vars) throws ServletException; 
}

The above code belongs to the DocInvoiceTemplate.java file, but it can be extrapolated to the rest of the Doc*Template classes. You can see it is an abstract class that just defines the abstract method createFact(), which is the one in charge of creating the accounting entries.

As you are probably imaging, the Java class that will override the default accounting behaviour must extend from this kind of Doc*Template classes. All the logic for creating the entries, which at the end is just inserting the records in the Fact_Acct table, must be developed inside the createFact() method.

Notice that the signature of this createFact() method is almost the same as the defined into the Accounting Server's createFact() abstract method; the only difference is that it has the new parameter DocInvoice docInvoice. This object is the instance of the original DocInvoice object, which already contains all necessary information for implementing our accounting logic (document type, lines, amounts...).

Implementing the createFact() method is for sure the most difficult part in the creation of this module. The good news for the developer is that he can take as a base the original code and adapt it inside the new class with just a few considerations:

String strClassname = AcctServerData
        .selectTemplateDoc(conn, as.m_C_AcctSchema_ID, DocumentType);
if (strClassname.equals(""))
  strClassname = AcctServerData.selectTemplate(conn, as.m_C_AcctSchema_ID, AD_Table_ID);
if (!strClassname.equals("")) {
  try {
    DocInvoiceTemplate newTemplate = (DocInvoiceTemplate) Class.forName(strClassname)
            .newInstance();
    return newTemplate.createFact(this, as, conn, con, vars);
  } catch (Exception e) {
    log4j.error("Error while creating new instance for DocInvoiceTemplate - " + e);
  }
}
Fact fact = new Fact(this, as, Fact.POST_Actual);

will be transformed to:

Fact fact = new Fact(docInvoice, as, Fact.POST_Actual);
getConvertedAmt(m_debt_payments[i].Amount, m_debt_payments[i].C_Currency_ID_From,
                    this.C_Currency_ID, DateAcct, "", AD_Client_ID, AD_Org_ID, conn)

will be transformed to:

docInvoice.getConvertedAmt(docInvoice.m_debt_payments[i].getAmount(),
                  docInvoice.m_debt_payments[i].getC_Currency_ID_From(), docInvoice.C_Currency_ID,
                  docInvoice.DateAcct, "", docInvoice.AD_Client_ID, docInvoice.AD_Org_ID, conn)

A bit of Java knowledge background and the help provided by Eclipse should be enough to properly implement your own createFact() method.


After this theoretical explanation, let's now continue with our dummy example for Invoices...

Implementing the logic

Inside the recently created package, we must now create the Java Class that will be in charge of generating the new accounting entries. This class, that in our example is called DummyAccountingTemplate, must extend from the org.openbravo.erpCommon.ad_forms.DocInvoiceTemplate class:

LocGuide AcctTemplate 120.png

Extending from the DocInvoiceTemplate class implies we must implement the createFact(DocInvoice docInvoice, AcctSchema as, ConnectionProvider conn, Connection con, VariablesSecureApp vars) method.

package org.openbravo.localizationguide.accountingtemplate;
 
import java.sql.Connection;
import javax.servlet.ServletException;
 
import org.openbravo.base.secureApp.VariablesSecureApp;
import org.openbravo.database.ConnectionProvider;
import org.openbravo.erpCommon.ad_forms.AcctSchema;
import org.openbravo.erpCommon.ad_forms.DocInvoice;
import org.openbravo.erpCommon.ad_forms.DocInvoiceTemplate;
import org.openbravo.erpCommon.ad_forms.Fact;
 
public class DummyAccountingTemplate extends DocInvoiceTemplate {
  @Override
  public Fact createFact(DocInvoice docInvoice, AcctSchema as, ConnectionProvider conn,
      Connection con, VariablesSecureApp vars) throws ServletException {
  }
}

As we have seen in the previous chapter, we can get the original createFact method from the DocInvoice class as a base and adapt it to our needs.

If you remember, the objective of our DummyAccountingTemplate was to multiply by 2 the accounting entries amounts. Let's see an example of how to do it:

public class DummyAccountingTemplate extends DocInvoiceTemplate {
  @Override
  public Fact createFact(DocInvoice docInvoice, AcctSchema as, ConnectionProvider conn,
      Connection con, VariablesSecureApp vars) throws ServletException {
         // create Fact Header
    Fact fact = new Fact(docInvoice, as, Fact.POST_Actual);
    String Fact_Acct_Group_ID = SequenceIdData.getUUID();
 
    // <some stuff hidden for simplicity>
 
    // accounting entry
    fact.createLine(docInvoice.p_lines[i], 
                    ((DocLine_Invoice) docInvoice.p_lines[i]).getAccount(ProductInfo.ACCTTYPE_P_Revenue, as, conn),
                      docInvoice.C_Currency_ID, "", 
                      new BigDecimal(docInvoice.p_lines[i].getAmount()).multiply(new BigDecimal("2")).toString(), // Notice that the amount is multiplied by 2
                      Fact_Acct_Group_ID,
                      docInvoice.nextSeqNo(docInvoice.getSeqNo()),
                      docInvoice.DocumentType,
                      conn);
 
   // <more stuff hidden for simplicity>
 
   return fact;
  }
}

The fact.createLine() method is in charge of creating the entry that will be later on inserted into the Fact_Acct table. For our development we have used the original code found in the createFact() method of the DocInvoice class, adapting it to our needs. Apart from the usual required changes explained in the previous chapter, we have just multiplied by 2 the accounting entry amount.

The same logic should be applied for the rest of the createLine() occurrences to complete our DummyAccountingTemplate class.


Remember to compile and to restart tomcat after finishing the code development.

General Ledger configuration

The final step to override the default accounting behavior is manually done in the General Ledger Configuration window. The end-user must specify the General Ledgers(s) for which he wants to use the new Accounting Template. This configuration can be done either at Active Tables or at Documents level.

In our example we want to override the accounting behavior for all the Invoices, that's why we will define the template at Active Table level.

We will use the F&B sample client distributed with Openbravo, because it already contains documents ready to be posted. Remember to apply our configuration dataset to this client in case your Accounting Template is not available.

LocGuide AcctTemplate 130.png

Important: Take into account that the end-user must manually perform this configuration in his instance. You should probably include this critical step into the manual configuration for your module. Alternatively, to make your end-user's life easier, you can develop a module script that transparently configures all the General Ledgers available in the instance.

Testing the code

After updating the General Ledger configuration everything is ready, so it's time to test it.

The test is quite simple. First of all we should check the accounting entry of any Invoice that we have previously posted using the original accounting logic. We can get them by pressing the Unpost button without checking the Delete accounting entry option.

LocGuide AcctTemplate 140.png

LocGuide AcctTemplate 80.png

Once we have written down the amounts, we move back to the same invoice and we unpost it, but this time checking the Delete accounting entry option. After that we post it again (now the system will use our Accounting Template), and we check the new amounts. If everything is OK, all the amounts are multiplied by 2

LocGuide AcctTemplate 90.png

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=<accounting template module java package>

Retrieved from "http://wiki.openbravo.com/wiki/How_to_create_a_Module_that_Overrides_Accounting"

This page has been accessed 11,498 times. This page was last modified on 13 February 2013, at 09:32. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.