Creating Charts in Openbravo Reports

Reporting is a decisive factor that determines the reach of an ERP among the Users. OpenbravoERP in particular have laid a lot of emphasis on the reporting structures. iReport is the tool officially supported by Openbravo for generating reports within Openbravo.

iReport is an opensource java based reporting tool. iReport provides lots of features like sub-reports,crosstab references, and various presentation gadgets like charts, bar graph, plotted line, etc. I have provided the steps for creating charts in reports in Openbravo.For basic on developing reports in iReport, refer here. You can download iReport here.

Lets see an example. I have 10 product categories and 500 products. I want to see which products fall under which category and how much is the stock available. Lets see how this could look.

 If you have not worked in iReports before, you can take a look at this. You can download iReport here. To add a chart to a window, use the chart tool icon in the interface. A screen shot of where it is located is provided below:

Once you have added the chart, you can access the chart properties as provided in the below screen shot.

In the chart properties, go to chart data -> details. Here you can add the categories based upon which you want the data. Here I have added the category as product Category and the series values in terms of the products in that particular category. Here the following key points to be noted are:

1. Series Expression:

This represents the bars that appears on the chart. Here we want all the products with the count. so we choose the products here

2. Category Expression:

This represents the  x-axis. Here the product category is our base and we provide that here.

3. Value Expression:

Value is nothing but the quantity that determines the height of the bars in the report. Here we are providing the count of each product.

4. Label Expression (optional) :

This provides the additional information about the bars in the chart that is provided under the chart. If its left empty, the name from the value expression will be pulled up.

Once all this is done, refer to the steps to import the same in the Openbravo Application and if you run the report, you will get the following output.

Having presented all this, generating reports in this format is really helpful. However Openbravo has now become the agile, tamed ERP…:). There is a new and powerful feature widgets.

Understanding OBDal in Openbravo

OBDal is an extensively used class in Openbravo. If offers lots of useful functions to enable external access to the Data Access Layer. OBDal provides the basic functions like insert,save,remove, etc. OBDal forms the base for the Data Access Layer(DAL) in Openbravo.

DAL Architecture

Though there are lots of useful functions in OBDal, we often use only few basic functions like save, remove, etc. Lets see the use of  the methods in OBDal and its usage.

1. void commitAndClose():

This function commits the transaction and closes the transaction. It will not only commit the current transaction but all the pending transactions. However, having more than one open transactions at a time is not advisable. There are few reasons why we should not have more than one open transactions. One of the reason is, if one of the open transactions failed to commit, all the pending transactions will be rolled back. This can be used in the code as follows.

OBDal.getInstance().commitAndClose();

There may be situations where we still need the transaction but just commit it. But when we use this method, it will not only commit but also closes the transaction. In this scenario, we can make use of the class SessionHandler( This class is exclusively for maintaining hibernate session for transactions). This class has a method commitAndStart(). This method will commit the transaction and starts a new session. This can be used in the code as follows.

SessionHandler.getInstance().commitAndStart();

2. void rollbackAndClose()

This method is used to rollback the transaction. Similar to commitAndClose() Method, this method will rollback all the open transactions.

OBDal.getInstance().rollbackAndClose();

The SessionHandler has a method rollback() which can be used when we don’t want to close the session but rollback the transaction.

SessionHandler.getInstance().rollback();

The SessionHandler class has two other methods that enables us to mark the transactions that needs to be rolled back. This can be done using the method, void setDoRollback(boolean). If the argument is true, then the transaction will be marked for rollback and if it is false, the transaction will not be marked for rollback. The other method is boolean getDoRollback() which will return whether the transaction is marked for rollback or not.

 SessionHandler.getInstance().setDoRollback(true);
 SessionHandler.getInstance().getDoRollback();

3. void disableActiveFilter() and void enableActiveFilter()

By default, the active filters will be enabled. Consider the line below.

Client clientList = OBDal.getInstance().get(Client.class,null); //Client is the class which we are referring and null denotes there is no filter

This will return all the records in ad_client  table that are active. We can disable this by using the method disableActiveFilter(). After disabling, the above line will return all the records irrespective of either the record is active or not. enableActiveFilter() is used to enable the filter. This methods can be used as follows.

OBDal.getInstance().disableActiveFilter();
 OBQuery<Client> clientList = OBDal.getInstance().createQuery(Client.class,null);
 for(Client client : clientList.list()) {
 //Processing
 }
 OBDal.getIstance().enableActiveFilter();

4. boolean isActiveFilterEnabled()

This method is used to verify whether the active filter is enabled or not. At any point of time, the active filter can be enabled and disabled and this method is useful to verify the status.

if(OBDal.getInstance().isActiveFilterEnabled()) {
 OBDal.getInstance().disableActiveFilter();
 }

5. boolean exists(String entityName, Object id)

This method is used to check whether a particular record exists in the database.

 OBDal.getInstance().exists(ADClient.ENTITY_NAME,"0");//ADClient is the entity name for Client Class and "0" refers to ad_client_id

To understand the use of this method, consider the code below.

Client clientList = OBDal.getInstance().get(Client.class,"45");
 try {
 String name = clientList.getName();
 } catch(Exception e) {
 log.info(e.getMessage());
 }

In the above code, if the record with ad_client_id = “45″ doesn’t exists, it will throw java.lang.NullPointerException since we are trying to access the value(clientList.getName()). To avoid this, we can use exists() method as follows.

Client clientList = OBDal.getInstance().get(Client.class,"45");
 if(clientList.getInstance().exists(ADClient,"45"))  {
 try {
 String name = clientList.getName();
 } catch(Exception e) {
 log.info(e.getMessage());
 }

The above code will be executed only if the record is present in the database.

6. String getReadableClientsInClause() & String getReadableOrganizationsInClause()

This method returns an in-clause string of the clients that are readable by the current user. The In-Clause String looks like (“0″,”1000000″). This method is useful in many scenarios. Below is one such scenario.

While retrieving the records using OBDal, it will automatically take care of the security. However, when we use HQL Queries, we need to take care of the security. In order to retrieve the client and organization readable by the user, we can use this method.

For example,

String hql = "SELECT name  "
 +"FROM ADRole r"
 +"WHERE r.organization IN "+OBDal.getInstance().getReadableOrganizationsInClause()
 +" AND r.client IN "+OBDal.getInstance().getReadableClientsInClause()
 +" AND r.active=true ";
 Query query = OBDal.getInstance().getSession().createQuery(hql);

This query will return the name of the roles that are readable for the current user.

These are few methods that I felt important in OBDal that would ease development using DAL. For details on how to write DAL code, refer ([1] and  [2]).

Resolving runtime model error in Openbravo

Whenever we refer columns in Openbravo using foreign key  references, the Application reference for the same will be  mapped as TableDir by default. This will be set when we provide create columns from DB. This is a small but effective value-add provided by Openbravo for developers. It reduces our work by a fair share. But as with all systems, there is a small downside to it. First let us see how they map the reference ‘TableDir’ to the column. When we run the Create Columns from DB process, the process checks for the column name, if the column name ends with ‘id’, it will map that as ‘TableDir’. For more information on references, refer here.  For eg, if a column name is ad_client_id, it would be mapped to TableDir by default. But the downside is, even if my column is ‘paid’, it sets it as TableDir.

We will not realize this, until we compile. When we compile, we get the following error, “Reference column for paid not found in runtime model“.  To resolve this issue, we have to change the reference type of the Column from TableDir to the corresponding reference (String or Number) and recompile.

One more issue that we face commonly while compiling is, “Referenced property is null for tablename.field“, where tablename is the name of the particular table and the field is the name of the field. The problem with this columns is, in Tables and Columns in Application Dictionary, for this particular column ‘Link to Parent Column’ will be checked. But as in our example, the column paid is a String field and not linked to any table or column that is already present, that is the reason why the error shows, referenced property is null. To resolve this, deselect the ‘Link to parent Column’ check box in the Column Window. I have attached a screen shot below to show where to deselect ‘Link to parent column’ property and also how reference are mapped.

Tree Structure for Custom Windows in Openbravo

Generating Tree Structure is a great innovative feature that is present in OpenbravoERP. If you are wondering what it looks like, refer to Organization window in the Client Mode or the Menu Window in System Admin mode. There will be an icon called Tree in the Toolbar. Click on that and you will see something similar to the screen shot below.For more information, refer here.

This functionality will find its use in most places where there is a hierarchy to be shown and segregations are to be visualized. One more appreciable feature is that you can drag and drop the items and rearrange it. Doesn’t it sound really cool to you? I was really excited to test this out for the custom windows and with the help of Wiki, Forge and of course my colleague, I was able to create a tree similar to the one shown above for a custom window called ‘Department’. I have attached a screen shot of my tree below.

This feature is really helpful in lot of cases. I have shared the sequence of steps that I followed that enabled me to create such a structure. We have categorized the steps that we performed into 3 sections:

1. Database changes

2. Changes to be done in the Application

3. Changes to be done in code

1. Database Changes

  • Create a new table for the department. Eg: XYZ_department.

The following are the key fields in the table.

        "value" character varying(40) NOT NULL,
        "name" character varying(60) NOT NULL,
        description character varying(255),
        issummary character(1) NOT NULL DEFAULT 'N'::bpchar,
  •  Create a new table for storing the tree nodes. Eg: XYZ_treenodedp (Structure similar to ad_treenode table)
  • Add logic in the Department Table Trigger to insert values in XYZ_treenodedp and the corresponding delete logic also. Refer Organisation table trigger for more information.
  • Add a new column in ad_clientinfo. Eg: em_XYZ_tree_department

2. Changes to be done in the Application

  • Create Window for the Department. Set the field ‘Tree Included’ to Yes in Fields Tab. Eg: In Department window
  • Import the  corresponding column created in ad_clientinfo table into the Application.
  • Add a new entry in the list reference ad_treetype. Eg: Search key: XYZ_DP Name: Department
  • Create a new entry in Tree and Node Image window both in System administrator and desired client admin. Eg. Name: Primary Department Tree type: Department in System Administrator and Name: F&B International Admin Department Tree Type: Department in F&B International Admin.

  • Update and set the value for the em_XYZ_tree_department field as the client’s tree entry. Eg: In F&B International Admin, Set the value as ‘F&B International Admin Department.

PrimaryDepartment

3. Changes to be done in code

  • In WindowTreeUtility.java, add the following lines in checkSpecificChanges() Method.
else if (TreeType.equals("XYZ_DP")) { //Department
 result = "";
 }

  • In WindowTreeUtility.java, add the following lines in getTreeType() Method.

else if (keyColumnName.equals("XYZ_Department_ID"))
 TreeType = "XYZ_DP";

  •  In WindowTreeUtility.java, add the following lines in getTree() Method.

else if (TreeType.equals("XYZ_DP"))
 data = WindowTreeData.selectDepartment(conn, vars.getUser(), strEditable, strParentID,  strNodeId, TreeID);

1

else if (TreeType.equals("XYZ_DP"))
 WindowTreeData.updateDP(conn, vars.getUser(), strParentID, strSeqNo, TreeID, strLink);

  •  In WindowTree_data.xsql, add two new sql methods to select and update the tree nodes.

<SqlMethod name="updateDP" type="preparedStatement" return="rowCount">
 <SqlMethodComment></SqlMethodComment>
 <Sql>
 UPDATE XYZ_TREENODEDP SET UPDATED=now(), UPDATEDBY = ?,                 PARENT_id = ?, SEQNO=TO_NUMBER(?)   WHERE AD_TREE_ID = ?
 AND NODE_ID = ?
 </Sql>
 <Parameter name="updatedby"/>
 <Parameter name="parentId"/>
 <Parameter name="seqno"/>
 <Parameter name="adTreeId"/>
 <Parameter name="nodeId"/>
 </SqlMethod>

<SqlMethod name="selectDepartment" type="preparedStatement" return="multiple">
 <SqlMethodComment></SqlMethodComment>
 <Sql>
 SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,                             m.XYZ_Department_ID AS ID, m.Name,m.Description,m.IsSummary
 FROM XYZ_TreeNodedp tn,
 XYZ_Department m
 WHERE tn.Node_ID = m.XYZ_Department_ID
 AND tn.AD_Tree_ID = ?
 ORDER BY COALESCE(tn.Parent_ID, '-1'), tn.SeqNo
 </Sql>
 <Parameter name="editable" optional="true" type="none" after="WHERE "                 text="tn.IsActive='Y' AND m.isActive='Y' AND "/>
 <Parameter name="parentId" optional="true" after="WHERE " text="tn.Parent_ID = ?             AND "/>
 <Parameter name="nodeId" optional="true" after="WHERE " text="tn.Node_ID = ?             AND "/>
 <Parameter name="adTreeId"/>
 </SqlMethod>

Import Loader Process For Custom Modules

Hi All,

The import loader process is used to load data into the openbravo windows from input files. Openbravo has provided the options to load product, business partner, etc., Now we have the option of creating import process for our own modules with a simple java file (Refer here). Right now this process reads data from csv file(The Input format is parsed using the file IdlServiceJava.java file). This can also be extended to read input from other formats by creating a service file similar to IdlServiceJava. The only catch here is that to try this out you need the Professional Subscription, after all not everything comes free in life…:).  I installed the modules, Initial Data Load and Initial Data Load Extension for Java. I used the sample import process that comes along with initial data load extension module and created a new import process for the window frequency.

Here are the steps which I followed.

1. Creating the Java Process file

 package com.fugoconsulting.xyzz.module.template.erpCommon.ad_process;

import org.openbravo.idl.proc.Parameter;
 import org.openbravo.idl.proc.Validator;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.text.ParseException;
 import java.math.BigDecimal;
 import java.util.Date;
 import org.apache.log4j.*;

import org.openbravo.base.exception.OBException;
 import org.openbravo.base.provider.OBProvider;
 import org.openbravo.base.structure.BaseOBObject;
 import org.openbravo.dal.service.OBDal;
 import org.openbravo.erpCommon.utility.Utility;
 import org.openbravo.idl.proc.Value;
 import org.openbravo.module.idljava.proc.IdlServiceJava;
 import com.fugoconsulting.xyzz.module.template.XYZZFrequency;

/**
 *
 * @author Pandeeswari
 */
 public class ImportFrequency extends IdlServiceJava {

private static Logger log=Logger.getLogger(ImportFrequency.class);
 DateFormat df = new SimpleDateFormat("dd-MM-yyyy");

@Override
 public String getEntityName() {
 return "Simple Frequency";
 }

@Override
 public Parameter[] getParameters() {
 return new Parameter[] {
 new Parameter("Organization", Parameter.STRING),
 new Parameter("SearchKey", Parameter.STRING),
 new Parameter("Name", Parameter.STRING),
 new Parameter("Description", Parameter.STRING),
 new Parameter("Factor", Parameter.STRING),
 new Parameter("Date", Parameter.STRING) };
 }

@Override
 protected Object[] validateProcess(Validator validator, String... values) throws Exception {
 validator.checkOrganization(values[0]);
 validator.checkNotNull(validator.checkString(values[1], 40), "SearchKey");
 validator.checkNotNull(validator.checkString(values[2], 60), "Name");
 validator.checkString(values[3], 255);
 validator.checkBigDecimal(values[4]);
 validator.checkDate(values[5]);
 return values;
 }

@Override
 public BaseOBObject internalProcess(Object... values) throws Exception {

return createFrequency((String) values[0], (String) values[1], (String) values[2],
 (String) values[3], (String) values[4], (String) values[5]);
 }

public BaseOBObject createFrequency(final String Organization, final String searchkey,
 final String name, final String description, final String factor,
 final String aDate)
 throws Exception {

// Frequency
 XYZZFrequency frequencyExist = findDALInstance(false, XYZZFrequency.class, new Value("searchKey", searchkey));
 if (frequencyExist != null) {
 throw new OBException(Utility.messageBD(conn, "XYZZ_FREQ_EXISTS", vars.getLanguage())
 + searchkey);
 }
 XYZZFrequency frequency = OBProvider.getInstance().get(XYZZFrequency.class);

try {
 frequency.setActive(true);
 frequency.setOrganization(rowOrganization);
 frequency.setSearchKey(searchkey);
 frequency.setName(name);
 frequency.setDescription(description);
 frequency.setFactor(new BigDecimal(factor));
 // Date date = df.parse(aDate);
 Date  date = new Date();
 frequency.setDate(date);

OBDal.getInstance().save(frequency);
 OBDal.getInstance().flush();
 } catch (Exception e) {
 e.printStackTrace();
 }

// End process
 OBDal.getInstance().commitAndClose();

return frequency;
 }
 }

I have created the Java File inside modules/mymodule/erpCommon/ad_process. You can place it where ever you want but just be careful to provide the proper Java package name.

Inside the getParameters() method, we provide the columns in the same order as it is in the input file. But the parameter names used in the method need not be the same.

The createFrequency() just inserts the value into the table using OBProvider.  The internalProcess(Object… values) Method which is inherited from IdlServiceJava class is used to call the appropriate method with appropriate parameters.

2. Register the file in entity default value

Register the Entity in Master Data Management -> Initial Data Load  -> Setup  -> Entity Default Value

Make Special note on the class name while adding the entity default value.

3. Import the data using import window

  • Go to Master Data Management -> Initial Data Load -> Process -> Import
  • Choose the input file
  • Choose the entity as Frequency

  • Give Validate
  • Once the input values are validated, the data can be loaded into the actual table by giving process.

  • If there occurs any problem with the input data, it will be logged in the boxes provided in the import screen.

Database Development Perspective in Eclipse for Openbravo,Postgres

Eclipse IDE is a great tool for Development and specially for development for an ERP like Openbravo. For setting up Openbravo in Eclipse refer here. Also Eclipse Provides many plug ins that could make the development even easier. There are many perspectives provided in Eclipse. (Refer Screen shot below)

Lets see about the Database Development Perspective in this Blog. Database Development Perspective allows us to connect to database directly, export data as files, import data, query, etc…

To connect your Openbravo postgresql database, these are the steps to be performed.

1. Choose Database Development from the available list of perspectives.

2. Create a new Connection and connect the driver to database. Refer the following screen shots.

3. In the Driver definition, choose your host and database name, the database field can be anything (column1), it does not matter. Its just the name that will show in Eclipse.

4. Once this is done, your eclipse will be as below.

Under Schemas, you will have public that will have the tables and functions.

Now you are connected to your database and you can query, or use the other options as I have shown in the screen shot below.

Happy Working..:)

Radio Button Reference for Openbravo

Last month I happened to see this issue, https://forge.openbravo.com/plugins/espforum/view.php?group_id=100&forumid=549512&topicid=7022038 accidentally, and I was more inclined about the solution model. Radio buttons are very common and are quite useful, but its surprising to note that it has not found its place in Openbravo. I felt Radio Button can be used in many places and that it should be part of the standard Reference Types. I could not get more in to it at that time, but couple of days ago got some time out of work and got a chance to give it a shot. I took the Yes/No Reference type as the base and remodelled the html file (WADYesNo.html) alone and then I was able to create a radio buttons out of it. I thought to contribute it to the community as a small dedication to the great work that is being in progress.

Feel free to buzz me at shankar@fugoconsulting.com. I would be glad to help the community and contribute in a small way that I can. I have also been trying to write some blogs about the basic issues that we face in Openbravo ERP. You can look at those at http://fugoconsulting.wordpress.com/category/openbravo/.

Solution Model:

The following are the sequence of files that I changed for the solution. All these are not needed to bring out a basic Radio Button especially  the skin images. But I have provided it as reference to the sequence of files to be added for a new reference type.

In src-wad/src/org/openbravo/wad/controls add the following files:

  • WADRadioButton.java
/*
 @author: Shankar Balachandran
*/
package org.openbravo.wad.controls;

import java.util.Properties;

import org.openbravo.xmlEngine.XmlDocument;

public class WADRadioButton extends WADControl {

 public WADRadioButton() {
 }

 public WADRadioButton(Properties prop) {
 setInfo(prop);
 initialize();
 }

 public void initialize() {
 generateJSCode();
 }

 private void generateJSCode() {
 setValidation("");
 setCalloutJS();
 }

 public String getType() {
 return "Radio_Check";
 }

 public String editMode() {
 XmlDocument xmlDocument = getReportEngine().readXmlTemplate(
 "org/openbravo/wad/controls/WADRadioButton").createXmlDocument();

 xmlDocument.setParameter("columnName", getData("ColumnName"));
 xmlDocument.setParameter("columnNameInp", getData("ColumnNameInp"));

 if (getData("IsReadOnly").equals("Y") || getData("IsReadOnlyTab").equals("Y")
 || getData("IsUpdateable").equals("N")) {
 xmlDocument.setParameter("disabled", "Y");
 xmlDocument.setParameter("logChanges", "");
 xmlDocument.setParameter("disabledFalse", "return false;");
 } else {
 xmlDocument.setParameter("disabled", "N");
 xmlDocument.setParameter("callout", getOnChangeCode());
 }
 if (getData("IsMandatory").equals("Y"))
 xmlDocument.setParameter("required", "true");
 else
 xmlDocument.setParameter("required", "false");

 return replaceHTML(xmlDocument.print());
 }

 public String newMode() {
 XmlDocument xmlDocument = getReportEngine().readXmlTemplate(
 "org/openbravo/wad/controls/WADRadioButton").createXmlDocument();

 xmlDocument.setParameter("columnName", getData("ColumnName"));
 xmlDocument.setParameter("columnNameInp", getData("ColumnNameInp"));

 if (getData("IsReadOnly").equals("Y") || getData("IsReadOnlyTab").equals("Y")) {
 xmlDocument.setParameter("disabled", "Y");
 xmlDocument.setParameter("logChanges", "");
 xmlDocument.setParameter("disabledFalse", "return false;");
 } else {
 xmlDocument.setParameter("disabled", "N");
 xmlDocument.setParameter("callout", getOnChangeCode());
 }
 if (getData("IsMandatory").equals("Y"))
 xmlDocument.setParameter("required", "true");
 else
 xmlDocument.setParameter("required", "false");

 return replaceHTML(xmlDocument.print());
 }

 public String toXml() {
 StringBuffer text = new StringBuffer();
 if (getData("IsParameter").equals("Y")) {
 if (getData("IsDisplayed").equals("N")) {
 text.append("<PARAMETER id=\"").append(getData("ColumnName")).append("\" name=\"").append(
 getData("ColumnName")).append("\" attribute=\"value\"/>");
 } else {
 text.append("<PARAMETER id=\"").append(getData("ColumnName")).append("\" name=\"").append(
 getData("ColumnName")).append("\" boolean=\"checked\" withId=\"paramCheck\"/>");
 }
 } else {
 if (getData("IsDisplayed").equals("N")) {
 text.append("<FIELD id=\"").append(getData("ColumnName")).append("\" attribute=\"value\">");
 text.append(getData("ColumnName")).append("</FIELD>");
 } else {
 text.append("<FIELD id=\"").append(getData("ColumnName")).append(
 "\" boolean=\"checked\" withId=\"paramCheck\">");
 text.append(getData("ColumnName")).append("</FIELD>");
 }
 }
 return text.toString();
 }

 public String toJava() {
 return "";
 }

 public String getDefaultValue() {
 return "N";
 }

 public boolean isText() {
 return true;
 }
}
  • WADRadioButton.html

<?xml version="1.0" encoding="UTF-8" ?>

<FIELD_TMP>
 <div id="xx_inp">
 <span><input type="radio" name="inpxx" id="xx" value="Y" onchange="return true;" onclick="changeToEditingMode('force');logChanges(this);xx();return true;" required="false"/></span>
 </div>
</FIELD_TMP>

  • WADRadioButton.xml

<?xml version="1.0" encoding="UTF-8"?>

<REPORT>
 <template file="WADRadioButton.html"/>
 <PARAMETER id="paramChecked" name="checked" default="Y"/>

 <PARAMETER id="xx_inp" name="columnName" attribute="id" replace="xx"/>
 <PARAMETER id="xx" name="columnName" attribute="id" replace="xx"/>
 <PARAMETER id="xx" name="columnNameInp" attribute="name" replace="xx"/>
 <PARAMETER id="xx" name="callout" attribute="onclick" replace="xx();" default=""/>
 <PARAMETER id="xx" name="required" attribute="required"/>
 <PARAMETER id="xx" name="disabled" boolean=" onclick='return false;' readonly=true" withId="paramChecked"/>
 <PARAMETER id="xx" name="logChanges" attribute="onclick" replace="logChanges(this);" default="logChanges(this);"/>
 <PARAMETER id="xx" name="disabledFalse" attribute="onclick" replace="return true;" default="return true;"/>

 <DISCARD id="discard"/>
</REPORT>

In src/org/openbravo/reference/ui add the following files

  • UIRadioButton.java

/*
 @author: Shankar Balachandran
*/
package org.openbravo.reference.ui;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Vector;

import javax.servlet.ServletException;

import org.openbravo.base.secureApp.VariablesSecureApp;
import org.openbravo.erpCommon.businessUtility.BuscadorData;

public class UIRadioButton extends UIReference {
 public UIRadioButton(String reference, String subreference) {
 super(reference, subreference);
 }

 public void generateFilterHtml(StringBuffer strHtml, VariablesSecureApp vars,
 BuscadorData fields, String strTab, String strWindow, ArrayList<String> vecScript, Vector<Object> vecKeys) throws IOException, ServletException {
 UIList list = new UIList("17", "47209D76F3EE4B6D84222C5BDF170AA2");
 list.generateFilterHtml(strHtml, vars, fields, strTab, strWindow, vecScript, null);
 }

 public void generateFilterAcceptScript(BuscadorData field, StringBuffer params,
 StringBuffer paramsData) {
 UITableDir tableDir = new UITableDir(reference, subReference);
 tableDir.generateFilterAcceptScript(field, params, paramsData);
 }
}

In web/skins/Default/Common

  • Add the Radio Button Folder with images

In web/skins/Default, in Openbravo_ERP_250.css add the following Code.

 


/*Custom Code Developed by Shankar 	Balachandran*/
/*
*************************
* Radio Button
*************************
*/
.dojoHtmlRadioButton {
border: 0px;
width: 16px;
height: 16px;
margin: 2px;
vertical-align: middle;
}
.dojoHtmlRadioButtonOn {
background-image: 	url(Common/RadioButton/Enabled.png) ;
}
.dojoHtmlRadioButtonOff {
background-image: 	url(Common/RadioButton/Simple.png) ;
}
.dojoHtmlRadioButtonDisabledOn {
background-image: 	url(Common/RadioButton/Disabled.png) ;
}
.dojoHtmlRadioButtonDisabledOff {
background-image: 	url(Common/RadioButton/Enabled.png) ;
}
.dojoHtmlRadioButtonOnHover {
background-image: 	url(Common/RadioButton/Simple.png) ;
}
.dojoHtmlRadioButtonOffHover {
background-image: 	url(Common/RadioButton/Simple.png) ;
}
.RadioButton_NOT_focused, 	.Radio_NOT_focused {
}
.RadioButton_container_NOT_focused, 	.Radio_container_NOT_focused {
padding: 0px;
margin: 0px;
width: 0px;
height: 0px;
border-style: solid;
border-width: 2px;
border-color: transparent;
}
.RadioButton_focused, 	.Radio_focused {
border: 2px solid #4D98CA;
outline-style: solid;
outline-width: 2px;
outline-color: #4D98CA;
}
.RadioButton_container_focused, 	.Radio_container_focused {
border-style: solid;
border-width: 2px;
border-color: transparent;
}

Then you have to create a base reference in the Application for the Radio Button. Below is a screen shot for reference.

You can assign the reference to any column that you want. I assigned it to the ”Default” field in the Module Window. Attached below is the screen shot of the field mapping.

Then you can “compile.complete.deploy” and then check the Module Window for the change. Attached below is the Screen shot with the Radio Button in Disabled and Enabled states.

Radio Button Disabled:

Radio Button Enabled:

Note:

 

  1. Option buttons are best utilised with the Button Group and they are least useful when used as individual items.
  2. I tried creating the same in RC4. And in the new UI, all I got was a text box with default value ‘False’. Not sure what piece I missed. But when I viewed it through the classic mode option, (URL/?mode=classic), I was able to view the Radio Button correctly.
For more external reference examples, refer here.
Follow

Get every new post delivered to your Inbox.