http://habrahabr.ru/post/248587/
Берём jrxml шаблон и устанавливаем в приложение
В
первой части я рассказал о том, как подготовить в iReport шаблон отчёта для библиотеки JasperReports. А эта статья посвящена тому, как получившийся шаблон интегрировать непосредственно в приложение
NORD POS. И если в первой части программа нужна была только, как источник данных для построения примера отчёта по справочнику товаров, то в данной статье она будет необходима для интеграции отчёта в интерфейс приложения, а также для демонстрации возможностей взаимодействия бизнес логики приложения и элементов шаблона библиотеки JasperReports.
Кроме этого, пришлось разделить статью на две части из-за того, что при подготовки материала я обнаружил ошибку печати отчёта в версии 3.0.1CE. Ошибка возникала из-за неправильного вызова диалога выбора принтера при использовании не стандартного оформления из Swing Look&Feel библиотеки
Insubstantial. Ошибка не возникала при использовании темы Metal или оформления в стиле операционной системы. Но, так как в NORD POS по-умолчанию используется нестандартная тема CremeSkin, то для написания этой части необходимо было устранить данный баг и выпустить обновлённую версию
NORD POS 3.0.2CE. И именно эту версию мы будем использовать во второй части статьи.
Размещаем шаблон
Чтобы установить шаблон отчёта не обязательно скачивать исходники всего приложения, достаточно сохранить файл из iRepot в папке
reports установленного приложения указав путь
./reports/io/example/reports/ для него. Кроме того, необходимо создать BeanShell скрипт для инициализации шаблона в NORD POS, а также ресурс Properties локализации текстовых полей шаблона.
Пишем скрипт
Код скрипта должен инициализировать наш шаблон отчёта в программе и передать значения из базы данных приложения в поля формы. И так в первой строке скрипта делаем инициализацию класса
PanelReportBean(), отвечающего за взаимодействие с библиотекой JasperReports:
report = new com.openbravo.pos.reports.PanelReportBean();
Задаём для него основные параметры:
report.setTitleKey("Menu.ExtProducts"); // Задаём название панели
report.setReport("/io/example/reports/productsext"); // Указываем на файл формирующего отчёт
report.setResourceBundle("io/example/reports/productsext_messages"); // и на файл локализации
И строку SQL-запроса для получения значения из базы данных:
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");
Здесь нужно обратить внимание на условие
WHERE ?(QBF_FILTER), оно позволяет вставить в запрос фильтр из интерфейса приложения. Например для справочника товаров это
ProductFilter() с следующими полями параметров:
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());
С помощью фильтра пользователь NORD POS сможете сделать выборку по цене товара, его категории или использую регулярное выражение SQL выбрать товар только с определённым названием. Например, выражение
А%, даст нам список товаров начинающихся только на букву «А» из любой категории.
В конце нашего скрипта обязательно нужно указать поля, которые будут использоваться в jrxml-шаблоне для построения отчёта:
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;
И вызвать средствами BeanShell скрипта созданный нами отчёт.
Полный готовый текст скриптаreport = new com.openbravo.pos.reports.PanelReportBean();
report.setTitleKey(«Menu.ProductList»); // Задаём название панели
report.setReport("/io/example/reports/productsext"); // Указываем на файл формирующего отчёт
report.setResourceBundle(«io/example/reports/productsext_messages»); // и на файл локализации
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");
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;
Локализуем поля
Для этого нам необходимо вернутся в iReport и заменить поля подписей на текстовые, чтобы в выражение указать переменную вида
$R{label.key} для локализации. Например для шапки отчёта задаём значение
$R{label.title} в в текстовом поле jrxml-шаблона.
После чего добавляем для этого ключа значение в файл
productsext_messages.properies.
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
В качества базового языка лучше использовать английский добавив затем к нему перевод на другом языке. Например для русского языка это будет
productsext_messages_ru.properies файл.
label.title=Список товаров
label.line.number=№
label.product.reference=Артикул
label.product.name=Название
label.product.price=Цена
label.product.vat=НДС
label.product.TaxPrice=Цена+Налог
label.report.summary=Всего позиций
Пересчитываем налоги
В первой части ставку налога мы брали непосредственно из базы данных, но формируя отчёт из приложения, лучше вести расчёт ставки и суммы налога использую специально для этого предназначенный метод
getTaxRate класса
TaxesLogic. Для этого в шаблоне надо создать параметр
TAXESLOGIC.
Тег параметров в XML-шаблоне<parameter name="TAXESLOGIC" class="com.openbravo.pos.sales.TaxesLogic" isForPrompting="false"/>
Который вызывается при расчёте цены и получает ставку налогу непосредственно на дату составления отчёта, что позволяет использовать возможности NORD POS для расчёта НДС в случае изменения её ставки после определённой даты.
Поле цены с налогом на дату отчёта<textField pattern="" isBlankWhenNull="false">
<reportElement uuid="1158eb51-5046-4b15-88f2-2456bac9eea1" x="425" y="2" width="84" height="32"/>
<textElement textAlignment="Right" verticalAlignment="Top"/>
<textFieldExpression><![CDATA[com.openbravo.format.Formats.CURRENCY.formatValue(
new Double(
$F{PRODUCT_PRICESELL}.doubleValue() *
(1.0 + $P{TAXESLOGIC}.getTaxRate($F{TAX_ID}, new Date()))
)
)
]]></textFieldExpression>
</textField>
Также в данном примере вместо паттерна самого шаблона для денежных значений используется паттерн приложения, чтобы обеспечить единообразие вывода всех значений.
Добавляем логотип и QR-код
Также с помощью вызова методов внешних классов в отчёт можно добавить различные ресурсы родительского приложения. Например в базе данных NORD POS хранится изображение логотипа. Вставить его в отчёт с помощью SQL-запроса не получится, но можно воспользоваться методом
getResourceAsImage класса
DataLogicSystem, вызвав его запросом из выражения поля изображения.
com.openbravo.pos.forms.DataLogicSystem.getResourceAsImage("Window.SupportBy")
Поле изображения логотипа <image scaleImage="Clip">
<reportElement uuid="5b7371fd-db3f-488e-80b2-1f2bc912703b" key="image-1" mode="Transparent" x="381" y="1" width="132" height="34"/>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<bottomPen lineWidth="0.0" lineColor="#000000"/>
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
<imageExpression><![CDATA[com.openbravo.pos.forms.DataLogicSystem.getResourceAsImage("Window.SupportBy")]]></imageExpression>
</image>
Или, например, в JasperReports среди поддерживаемых штрих-кодов нет QR-кода, а в NORD POS интегрирована библиотека
ZXing, с помощью неё можно сгенерировать QR-кода для отчёта например с ссылкой на сайт.
com.nordpos.device.util.BarcodeImage.getQRCode("http://nordpos.mobi")
Поле QR-кода ссылки на сайт <image scaleImage="RetainShape" hAlign="Center" vAlign="Middle">
<reportElement uuid="425a36a5-4937-4551-8b26-8ffe7245f9f0" key="barcode-1" x="449" y="13" width="64" height="64"/>
<box>
<topPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<leftPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
<bottomPen lineWidth="0.0" lineColor="#000000"/>
<rightPen lineWidth="0.0" lineStyle="Solid" lineColor="#000000"/>
</box>
<graphicElement fill="Solid">
<pen lineWidth="0.0" lineStyle="Solid"/>
</graphicElement>
<imageExpression><![CDATA[com.nordpos.device.util.BarcodeImage.getQRCode("http://nordpos.mobi")]]></imageExpression>
</image>
Настраиваем доступ
Теперь остался последний шаг, это открыть доступ к отчёту из NORD POS. С начала добавим кнопку нашего отчёт в интерфейс приложения. Открываем в
Настройки -> Ресурсы, находим BeanShell-скрипт
Menu.Root и добавляем в раздел
MenuSalesManagement панель отчёта.
submenu.addPanel("/com/openbravo/images/appointment.png", "Menu.ProductList", "/io/example/reports/productsext.bsh");
Второй шаг, это разрешить в профиле для группы пользователей доступ к отчёту. Переходим
Настройки -> Профили, выбираем роль из списка и добавляем в XML-документ разрешение доступа к нашему отчёту.
<class name="/io/example/reports/productsext.bsh"/>
Всё, перезагружаем NORD POS, открываем панель отчёта и формируем его. На этом задача по созданию отчёта для NORD POS успешно завершена.
Кроме создания отчётов с помощью средств JasperReports в NORD POS можно формировать этикетки, заполнять таблицы, строить графики и диаграммы, но о заложенных для этого основах я постарался рассказать читателям Хабра в этой статье. А в дальнейшем, если это будет интересно, то я хочу продолжить рассказ о других возможностях NORD POS, которые появились благодаря использованию сторонних библиотек. Но прежде хотел бы сделать небольшой опрос среди тех читателей, кто обе части дочитал до конца.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.