
Reports for NORD POS. Part 2
- Tutorial
We take the jrxml template and install it in the application
In the first part, I talked about how to prepare a report template for the JasperReports library in iReport. And this article is devoted to how to integrate the resulting template directly into the NORD POS application . And if in the first part the program was needed only as a data source for building an example of a report on the product directory, then in this article it will be necessary to integrate the report into the application interface, as well as to demonstrate the possibilities of interaction between the business logic of the application and the elements of the JasperReports library template.

In addition, I had to divide the article into two parts due to the fact that during the preparation of the material I found a report printing error in version 3.0.1CE. The error occurred due to an incorrect call to the printer selection dialog when using a non-standard design from the Swing Look & Feel library of the Insubstantial . The error did not occur when using the Metal theme or design in the style of the operating system. But, since NORD POS uses the non-standard CremeSkin theme by default, to write this part, it was necessary to fix this bug and release an updated version of NORD POS 3.0.2CE . And it is this version that we will use in the second part of the article.
Place the template
To install the report template, it is not necessary to download the source code of the entire application, just save the file from iRepot in the reports folder of the installed application by specifying the path ./reports/io/example/reports/ for it. In addition, you need to create a BeanShell script to initialize the template in NORD POS, as well as the Properties resource to localize the text fields of the template.

Writing a script
The script code should initialize our report template in the program and transfer the values from the application database to the form fields. And so in the first line of the script we initialize the PanelReportBean () class , which is responsible for interacting with the JasperReports library:
report = new com.openbravo.pos.reports.PanelReportBean();
We set the main parameters for it:
report.setTitleKey("Menu.ExtProducts"); // Задаём название панели
report.setReport("/io/example/reports/productsext"); // Указываем на файл формирующего отчёт
report.setResourceBundle("io/example/reports/productsext_messages"); // и на файл локализации
And the SQL query string to get the value from the database:
report.setSentence("SELECT"+
" PRODUCTS.NAME AS PRODUCT_NAME" +
", PRODUCTS.REFERENCE AS PRODUCT_REFERENCE" +
", PRODUCTS.PRICESELL AS PRODUCT_PRICESELL" +
", PRODUCTS.CATEGORY AS CATEGORY_ID" +
", CATEGORIES.NAME AS CATEGORY_NAME" +
", PRODUCTS.TAXCAT AS TAX_ID" +
" FROM PRODUCTS" +
" LEFT OUTER JOIN CATEGORIES ON PRODUCTS.CATEGORY = CATEGORIES.ID" +
" LEFT OUTER JOIN TAXCATEGORIES ON PRODUCTS.TAXCAT = TAXCATEGORIES.ID" +
" LEFT OUTER JOIN TAXES ON TAXCATEGORIES.ID = TAXES.CATEGORY" +
" WHERE ?(QBF_FILTER)" +
" ORDER BY CATEGORIES.NAME, PRODUCTS.NAME");
Here you need to pay attention to the WHERE? (QBF_FILTER) condition , it allows you to insert a filter from the application interface into the request. For example, for a product directory, this is ProductFilter () with the following parameter fields:
report.addParameter("PRODUCTS.NAME");
report.addParameter("PRODUCTS.PRICEBUY");
report.addParameter("PRODUCTS.PRICESELL");
report.addParameter("PRODUCTS.CATEGORY");
report.addParameter("PRODUCTS.CODE");
report.addQBFFilter(new com.openbravo.pos.ticket.ProductFilter());
Using the filter, the NORD POS user can select the price of the product, its category, or use the regular SQL expression to select a product with only a specific name. For example, the expression A% will give us a list of products starting only with the letter “A” from any category.
At the end of our script, you must specify the fields that will be used in the jrxml template for building the report:
report.addField("PRODUCT_NAME", com.openbravo.data.loader.Datas.STRING);
report.addField("PRODUCT_REFERENCE", com.openbravo.data.loader.Datas.STRING);
report.addField("PRODUCT_PRICESELL", com.openbravo.data.loader.Datas.DOUBLE);
report.addField("CATEGORY_ID", com.openbravo.data.loader.Datas.STRING);
report.addField("CATEGORY_NAME", com.openbravo.data.loader.Datas.STRING);
report.addField("TAX_ID", com.openbravo.data.loader.Datas.STRING);
report;
And call the BeanShell script using the report we created.
Full finished script text
report = new com.openbravo.pos.reports.PanelReportBean ();
report.setTitleKey ("Menu.ProductList"); // Set the name of the panel
report.setReport ("/ io / example / reports / productsext"); //
Point to the file generating the report report.setResourceBundle ("io / example / reports / productsext_messages"); // and to the localization file
report.setSentence ("SELECT" +
"PRODUCTS.NAME AS PRODUCT_NAME" +
", PRODUCTS.REFERENCE AS PRODUCT_REFERENCE" +
", PRODUCTS.PRICESELL AS PRODUCT_PRICESELL" +
", PRODUCTS.CATEGORY AS CATEGORY_ID" +
" , CATEGORIES.NAME AS CATEGORY_NAME "+
", PRODUCTS.TAXCAT AS TAX_ID "+
" FROM PRODUCTS "+
"
"LEFT OUTER JOIN TAXCATEGORIES ON PRODUCTS.TAXCAT = TAXCATEGORIES.ID" +
"LEFT OUTER JOIN TAXES ON TAXCATEGORIES.ID = TAXES.CATEGORY" +
WHERE? (QBF_FILTER) "+
" ORDER BY CATEGOR..) ;
report.addParameter ("PRODUCTS.NAME");
report.addParameter ("PRODUCTS.PRICEBUY");
report.addParameter ("PRODUCTS.PRICESELL");
report.addParameter ("PRODUCTS.CATEGORY");
report.addParameter ("PRODUCTS.CODE");
report.addQBFFilter (new com.openbravo.pos.ticket.ProductFilter ());
report.addField ("PRODUCT_NAME", com.openbravo.data.loader.Datas.STRING);
report.addField ("PRODUCT_REFERENCE", com.openbravo.data.loader.Datas.STRING);
report.addField ("PRODUCT_PRICESELL", com.openbravo.data.loader.Datas.DOUBLE);
report.addField ("CATEGORY_ID", com.openbravo.data.loader.Datas.STRING);
report.addField ("CATEGORY_NAME", com.openbravo.data.loader.Datas.STRING);
report.addField ("TAX_ID", com.openbravo.data.loader.Datas.STRING);
report;
report.setTitleKey ("Menu.ProductList"); // Set the name of the panel
report.setReport ("/ io / example / reports / productsext"); //
Point to the file generating the report report.setResourceBundle ("io / example / reports / productsext_messages"); // and to the localization file
report.setSentence ("SELECT" +
"PRODUCTS.NAME AS PRODUCT_NAME" +
", PRODUCTS.REFERENCE AS PRODUCT_REFERENCE" +
", PRODUCTS.PRICESELL AS PRODUCT_PRICESELL" +
", PRODUCTS.CATEGORY AS CATEGORY_ID" +
" , CATEGORIES.NAME AS CATEGORY_NAME "+
", PRODUCTS.TAXCAT AS TAX_ID "+
" FROM PRODUCTS "+
"
"LEFT OUTER JOIN TAXCATEGORIES ON PRODUCTS.TAXCAT = TAXCATEGORIES.ID" +
"LEFT OUTER JOIN TAXES ON TAXCATEGORIES.ID = TAXES.CATEGORY" +
WHERE? (QBF_FILTER) "+
" ORDER BY CATEGOR..) ;
report.addParameter ("PRODUCTS.NAME");
report.addParameter ("PRODUCTS.PRICEBUY");
report.addParameter ("PRODUCTS.PRICESELL");
report.addParameter ("PRODUCTS.CATEGORY");
report.addParameter ("PRODUCTS.CODE");
report.addQBFFilter (new com.openbravo.pos.ticket.ProductFilter ());
report.addField ("PRODUCT_NAME", com.openbravo.data.loader.Datas.STRING);
report.addField ("PRODUCT_REFERENCE", com.openbravo.data.loader.Datas.STRING);
report.addField ("PRODUCT_PRICESELL", com.openbravo.data.loader.Datas.DOUBLE);
report.addField ("CATEGORY_ID", com.openbravo.data.loader.Datas.STRING);
report.addField ("CATEGORY_NAME", com.openbravo.data.loader.Datas.STRING);
report.addField ("TAX_ID", com.openbravo.data.loader.Datas.STRING);
report;
We localize the fields
To do this, we need to return to iReport and replace the signature fields with text fields to indicate a variable of the form $ R {label.key} for localization in the expression . For example, for the report header, set the value $ R {label.title} in the jrxml template text field.
Then we add a value for this key to the productsext_messages.properies file .
label.title=List of Products
label.line.number=N
label.product.reference=Reference
label.product.name=Name
label.product.price=Price
label.product.vat=VAT
label.product.TaxPrice=Price+Tax
label.report.summary=Summary
It is better to use English as the base language, then add a translation in another language to it. For example, for the Russian language it will be the productsext_messages_ru.properies file.
label.title=Список товаров
label.line.number=№
label.product.reference=Артикул
label.product.name=Название
label.product.price=Цена
label.product.vat=НДС
label.product.TaxPrice=Цена+Налог
label.report.summary=Всего позиций
We recalculate taxes
The first part of the tax rate, we were taken directly from the database, but the report form from the application, it is better to conduct the calculation of rates and the tax amount is used specifically for the intended method getTaxRate class TaxesLogic . To do this, create the TAXESLOGIC parameter in the template .

Parameter tag in XML template
Which is called when calculating the price and receives the tax rate directly on the date of the report, which allows you to use the NORD POS capabilities for calculating VAT if its rate changes after a certain date.

Price field with tax at the reporting date
Also in this example, instead of the pattern of the template itself for monetary values, the application pattern is used to ensure uniform output of all values.
Add logo and QR code
Also, by calling methods of external classes in the report, you can add various resources of the parent application. For example, the NORD POS database stores a logo image. Insert it into the report using SQL-query does not work, but you can use the method getResourceAsImage class DataLogicSystem , calling it a request from the expression of the image field.
com.openbravo.pos.forms.DataLogicSystem.getResourceAsImage("Window.SupportBy")
Logo Image Box
![]()
Or, for example, among the supported barcodes in JasperReports, there is no QR code among the supported bar codes, and the ZXing library is integrated in NORD POS , using it you can generate a QR code for reporting, for example, with a link to the site.
com.nordpos.device.util.BarcodeImage.getQRCode("http://nordpos.mobi")
QR code field of the link to the site
![]()
Configure Access
Now the last step remains, is to open access to the report from NORD POS. From the beginning, add the button of our report to the application interface. Open in Settings -> Resources , find the BeanShell script Menu.Root and add a report panel to the MenuSalesManagement section .
submenu.addPanel("/com/openbravo/images/appointment.png", "Menu.ProductList", "/io/example/reports/productsext.bsh");
The second step is to allow access to the report in the profile for the user group. Go to Settings -> Profiles , select a role from the list and add permission to access our report in the XML document.
That's it, restart NORD POS, open the report panel and form it. This completes the task of creating a report for NORD POS.

In addition to creating reports using JasperReports tools in NORD POS, you can create labels, fill in tables, build graphs and charts, but I tried to tell the readers of Habr in this article about the foundations for this. And in the future, if it will be interesting, then I want to continue the story about other features of NORD POS, which appeared due to the use of third-party libraries. But first I would like to do a small survey among those readers who have read both parts to the end.
Only registered users can participate in the survey. Please come in.
Why were you interested in NORD POS and what would you like / could use it for?
- 35.1% to automate your own business 13
- 16.2% for customer business automation 6
- 10.8% as an example of developing a native application 4
- 8.1% to learn about using third-party libraries in Java 3
- 45.9% simply read for the general development about something new on Habré 17