Overview

ADempiere is a great Business Application. What make ADempeire different from others are not only its complete business features, but indeed its ability to extend its features. ADempeire Application Dictionary Framework is very flexible and powerful. ADempiere is great about openness. All the technique has been document and discussed openly in this Wiki. The only thing developer need to do is to find and get familiar with all the concept, and try to connect all the jigsaw together. Which is in a way, quite difficult.

In this tutorial, we will be using a real usable yet simple module that I developed from a requirement of ADempiere ERP Project in Thailand. I will walk you through techniques needed to build a new module. And along the way, I will be referring to the more completed source of documentation. As such, it is highly recommended that the reader dig into each of the technique and try to understand them along with the tutorial.

Business Requirement for this tutorial

We will call this new module - Billing. In some countries, at least for Thailand, there is a customary practice for companies to collect money from their customers only once in a month. For example, the customer has 3 payments due in a given month, the vendor or billing company should group all the due AR Invoices in a document call Billing Document and issue it with all the invoices consolidated to the customer on the Billing Day. The customer will be paying based on the payable amount shown in Billing Document in the following month.

For training purposes, download the source code (Billing_src.zip), PackIn package (Billing.zip) and a sample jasper form (Billing_Form.jrxml) from DOWNLOAD HERE (as ADempeire Wiki now do not accept zip file, so I have to host them at Bitbucket).

Sample Test Steps

Following are the use case of this new module. We will be testing them along with development steps.

A customer has made 3 orders during the month. Sales orders are completed, and the goods has been shipped. Now it is the process of invoicing.

User prepare 3 Invoice (Customer) issued to that customer. Let's give these invoices due date at the end of the working month.

It is the normal practice (at least in Thailand) that, customer will accept invoices from vendor only once a month. So, before that date, user create 1 Billing Document that summarize the 3 invoices

Printout the Billing forms and its associated Invoice forms. These forms will be printed out and issue to customer

Once money is paid from customers, user use the Payment window to do the AR Receipt process. Allocate the Receipt Line with the help of Billing Document

User complete the AR Receipt, information (AR Receipt's DocNo) will be referenced back to the underlining Billing Document

Development Steps

Step 1: Prepare Your Customization Environment

In this tutorial, we assume that we only have 1 project "ADempiere360LTS" setup and functional. We will be creating a new Eclipse Project called "BillingModule" as our custom project.

On your Eclipse, create a new Java Project called "BillingModule"

Add ADempiere360LTS to this project build path

Create Run Configuration for this new project

Run ADempeire from this Run Configuration

Note: At this step of tutorial, BillingModule project is an empty project. We will later on add the source code that we downloaded from the previous step.

Step 2: Create new Entity Type

This is one noteworthy step before we start any development. The Entity Type determines the ownership of Application Dictionary entries. Normally, entity (i.e., Window, Fields, Rules, etc...) are marked as "Dictionary" which means, ADempiere own entities. It is a good practice to always create a new Entity Type for your project. This will tell you which component belongs to your project.

It could be anything, but in this tutorial we will be using our Entity Type called, ECS_LCO (Ecosoft Thai Localization)

Run ADempiere from Eclipse

Login as System Administrator

Open Entity Type window

Click New

Entity Type: ECS_LCO

Name: Thai Localisation

ModelPackage: org.ecosoft.model (<--this will be used as default package later on when we run GenerateModel)

Click Save

From now on, when you create any new components, set Entity Type to "ECS_LCO" when ever applicable.

Step 3: Create Billing Tables and Window

In this step, we will be creating a new Window (Billing) with 2 tabs (Billing and Billing Line). In normal practice, you will be using Application Dictionary to create the window. But for this tutorial purpose, it will be using too much time to create windows and fields one by one. Instead, we will install the pre-built package, Billing.zip downloaded form previous step. The Billing.zip is a 2Pack Package that I have created (PackOut) from my previous implementing of Billing module. 2Pack is a very useful feature when come to migration and worth experimenting in detail.

Per say, we will use the ready to use Billing.zip to create,

Billing window with 2 tabs, Billing and Billing Line

2 database tables for the UI, C_Billing and C_BillingLine

Some other required component, i.e., Field Validator, etc.

To install Billing.zip

Login as System Administrator

Open window "PackIn - Import a package"

New

Package Source Type: File

Package Source: (Select the Billing.zip)

Package Directory: migration (<-- PackIn will copy and expand Billing.zip in this directory)

Update system maintained application dictionary: Not checked

Save and click to process "PackIn"

Note:

The brief steps if create new window manually are

Login as System Administator

Use Table and Column window to create new table, "C_Billing" and "C_BillingLine"

Once the Tables and Windows is created (from PackIn), please review and see how they are configured. Open "Window, Tab and Field" window and "Table and Column" and look for new Window / Tables. Some note on Columns / Fields here,

Step 4: Generate Model Class for Billing and Billing Line model

After previous step, we now have a new Billing window with its associate table. Though CRUD (Create/Read/Update/Delete) functionality is available, it is not yet very useful. Next step is to extend its functionality, we will have to create Model classes for them.

With Model class, we can make the control over the object (aka Window/Table) better. ADempiere provide a GenerateModel process to help generate Interface and PO Extension classes (I_ and X_ classes getter/setter).

On your Eclipse, create a new Run Configurator, call it Generate Model

Project: ADempiere360LTS

Main class: org.adempiere.util.GenerateModel

Tell what class to generate, by giving the Arguments

D:\temp\Billing --> where output class will be, also make sure that this folder is prepared. Adempiere will not auto create it.

org.ecosoft.model --> package

'ECS_LCO' --> Entity Type (our new tables have been marked as ECS_LCO)

'C_Billing' --> Table to lookup

Run the configuration and the classes will be created into D:\temp\Billing folder

Do the same to creates model classes for C_BillingLine

Go to D:\temp\Billing and you should see 4 java file generated, I_C_Billing.java, X_C_Billing.java, I_C_BillingLine.java, X_C_BillingLine.java

Note: for the new model classes, you will notice in the file that, its package is org.ecosoft.model. This is because we have specified it in Entity Type

I_ and X_ are interface and get/set classes generated by GenerateModel class, and hence should not be modified. There is no implementation logic in these classes yet. Next we have to create the real model-extension class where the logic reside. As a rule of thumb, the name of Model for C_Billing table will be "MCBilling" (prefix with "M" and takeout "_"). More information about extending model can be found here.

As such, we will be creating 2 new model extension classes.

org.ecosoft.MCBilling.java

org.ecosoft.MCBillingLine.java

Note that, these classes will extend the getter and setter classes (X_ classes) in previous steps. We can add more logic when a billing record is, i.e., saved, deleted, completed, etc. For training purpose we will be using the pre-written class provided in this tutorial.

Step 5: Making Billing a Document Type

If it is for window that simply keep master data, all implementation in previous steps is enough. But if the window will become a transaction data, or in the term of ERP system, become a "Document", this step is necessary. Becoming a Document will embed the following behavior 1) have document status 2) have period control 3) have document workflow and 4) can create accounting fact (optional).

In our example, Billing is a kind document, but it will not have to create accounting fact.

To register for new Document Base Type - "Billing", first, we will be registering the new type into References window.

Login as System, open References window

Lookup for C_DocType DocBaseType

Select the List Validation tab and add a new entry

Search Key: BIL

Name: Billing

Entity Type: Thai Localisation

Note: In our case, the Billing.zip already created it.

Extending C_DocType for new DocType

There is a class in ADempiere X_C_DocType.java (located in base/src org.compiere.model) which contains all constants of document types in the system. As we have new DocType, at first glance it would be easy to overwrite it to accommodate the new DocType, i.e., in this case to add a Constant into existing X_C_DocType.java

But overwriting the existing class is not a good practice, the BETTER way is --> in our BillingModule project directory create a new interface (I call it "Extension Interface"), I_C_DocType.java that extend the existing I_C_Doctype.java

Run process Role Access Update --> This ensure that, people are granted access right to execute the document process.

This tutorial will not go in-dept about the Java Code. But you can explore MCBilling.java and MCBillingLine.java and see what additional logic we try to achieve when some event occur with Billing document

Now, from eclipse, stop and rerun the Application and notice changes,

What are added?

In Billing Window

Create new Billing record

Document Type = Billing, now exists

Document No is now running

Clicking Complete button, DocAction is shown

In Workflow window

You will see new Document Process for Billing

In Calendar Year and Period window

You will see periods for new Billing Document Type

In Role window

In Document Action Access, you will see all DocAction for new Billing Document Type

Up to this point, the new window is functional. But according to the Business Requirement, we still miss some important pieces of code.

Callout --> To make UI more interactive as when a field is filled, information in other fields should be retrieved and filled automatically.

Process --> To make clicking of a button in Billing run some internal process for us.

Report --> To show the Jasper Form of Billing document when clicking on Billing window's Print Preview

ModelValidator --> To be more interactive with other existing processes (without modifying existing code)

Step 7: Create Java Process

Create billing lines based on the open invoice of the selected customers which their due date are not beyond due date on the billing.

Register the Process class

Login as System, open Report & Process

New process

Search Key: GenerateBillingLine

Name: Generate Billing Line

Data Access Level: Client + Organization

Classname: org.ecosoft.process.GenerateBillingLine

Save the record

No parameter required (RECORD_ID will be passed to the process by default)

Open Table and Column window

Look for C_Billing table, GenerateBillingLine column

You will notice that this column is of reference type "Button". Clicking of the button will trigger the process.

Make sure that process is GenerateBillingLine_Generate Billing Line

Create a class GenerateBillingLine in the package org.ecosoft.process

For training purpose, we will use the pre-written class. But please notice from the code to learn how it works.

Note: Up to this point, the general use of Billing window is ready. User can create new Billing record. Provided the Invoice DueDate and Business Partner, clicking on Generate Billing Line button will create Billing Line based on the invoices that meet the criteria.

Test: Create new Billing that summarize invoices (customer)

As the process will look up for the completed invoices that match the criteria on the Billing window, i.e., Business Partner, Billing Date, before running this test, make sure you created and completed Invoice (customer) for this Business Partner, i..e, C&W Construction (Invoice's Due Date + Payment Term < Billing Date).

Create Billing document for a specific customer

Login as Garden Admin, open Billing window

New Billing record, i.e.,

Document Type: Billing

Business Partner: C&W Construction

Due Date: End of Month (cover all the completed invoices that reach the due date)

Start from this step, we will be enhancing the existing Payment window to be able to interact with the Billing module. When doing the AR Receipt on Payment window, by clicking at a button, user should be able to allocate invoices based on the issued Billing Document.

Before we can do that, we need to have a new Button "Create lines from..." button and a new field "Billing Document". And like previous steps, we will be registering new Java Process to that button.

But again, for this tutorial, our Billing.zip package has created those necessary Application Dictionary elements for us. Please refer to Application Dictionary for table C_Payment (column - CreateForm and C_Billing_ID) and window Payment (field - Create lines form... and Billing Document) on how they are configured.

Step 8: Intercept other process with ModelValidator

ModelValidator is the good way to intercept existing process without overwrite the existing code.

This case, we want to intercept the process in AR Receipt document process

After COMPLETE the Payment (receipt) Document, update the Billing Document associate with it

Register the ModelValidator class

Login as System, open Model Validator window

New

Entity Type: Thai Localisation

Name: Model Validator for Billing Module

Model Validation Class: org.ecosoft.model.BillingValidator

Sequence: 2

Save the record

Note: ModelValidator can be registered in both System and Clint level. In this case, we are registering at System level.

Create a class BillingValidator in the package org.ecosoft.model

You can read the code in BillingValidator.java and notice how event is registered for C_Payment

Test: Complete the AR Receipt

Complete the AR Receipt

Restart Adempiere from Eclipse

Login as GardenAdmin

Open Receipt window, and look for AR Receipt record in previous step.

On Receipt tab, fill in receipt amount (i.e., 142.75 USD)

Complete the AR Receipt Document.

See the effect of AR Receipt document complete to the referenced Billing Document.

Open to the referred Billing Document

Now you will see document status changed to Closed

And Cheque Received Date is now updated

Step 9: Deploy Billing.jar Package

Now, we have all the functionalites we need for this new module. Meanwhile, we still run it directly from Eclipse. For development period, this is ok. But what if we want to use it on our production server?

So, next, let's deploy! The concept is easy, just make the Billing.jar file out of the Eclipse and deploy them in the server.

From Eclipse, right click on BillingModule project --> Export --> JAR File, name the file "Billing.jar" and click next to export it

Since this is a new package (work as separately as module), we can deploy them package folder. Deploy to ADEMPIERE_HOME\packages\Billing\lib\Billing.jar

RUN_silentsetup .sh/.bat to include this new package into the application.

Note:

Adempeiere Precedence of JAR

Customization.jar

Patches.jar

<Package>.jar (i.e., LiberoHR.jar, LiberoManu.jar, etc…)

Adempiere.jar

Deploying as a new JAR

Copy and Paste to Adempiere

As customization.jar in C:\Adempiere\lib

As <Package>.jar in C:\Adempiere\Packages\<Package>\lib\<Package>.jar

Execute Run_Setup.bat or RUN_SilentSetup.bat to include the new classes into the system runtime

Summary

As you will see now, ADempiere is a great tool to develop new Business Application. This sample module is utilizing most of the important techniques available in ADempiere and try to connect them together in a single tutorial. Yet, these are just the basic steps to understand ADempiere. I do highly recommended the reader to read though all the links provided in this tutorial.

If this tutorial has any typo error or is not clear enough, please do help me in suggesting any edits or by giving your feedback in the Discussion page. Thank you and have fun!