Отчёты для NORD POS. Часть 2

в 13:28, , рубрики: jasperreports, java, nord pos, open source, reports

Берём jrxml шаблон и устанавливаем в приложение

В первой части я рассказал о том, как подготовить в iReport шаблон отчёта для библиотеки JasperReports. А эта статья посвящена тому, как получившийся шаблон интегрировать непосредственно в приложение NORD POS. И если в первой части программа нужна была только, как источник данных для построения примера отчёта по справочнику товаров, то в данной статье она будет необходима для интеграции отчёта в интерфейс приложения, а также для демонстрации возможностей взаимодействия бизнес логики приложения и элементов шаблона библиотеки JasperReports.

Отчёты для NORD POS. Часть 2 - 1

Кроме этого, пришлось разделить статью на две части из-за того, что при подготовки материала я обнаружил ошибку печати отчёта в версии 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 локализации текстовых полей шаблона.

Отчёты для NORD POS. Часть 2 - 2

Пишем скрипт

Код скрипта должен инициализировать наш шаблон отчёта в программе и передать значения из базы данных приложения в поля формы. И так в первой строке скрипта делаем инициализацию класса 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.

Отчёты для NORD POS. Часть 2 - 3

Тег параметров в XML-шаблоне

<parameter name="TAXESLOGIC" class="com.openbravo.pos.sales.TaxesLogic" isForPrompting="false"/>

Который вызывается при расчёте цены и получает ставку налогу непосредственно на дату составления отчёта, что позволяет использовать возможности NORD POS для расчёта НДС в случае изменения её ставки после определённой даты.

Отчёты для NORD POS. Часть 2 - 4

Поле цены с налогом на дату отчёта

<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 успешно завершена.

Отчёты для NORD POS. Часть 2 - 5

Кроме создания отчётов с помощью средств JasperReports в NORD POS можно формировать этикетки, заполнять таблицы, строить графики и диаграммы, но о заложенных для этого основах я постарался рассказать читателям Хабра в этой статье. А в дальнейшем, если это будет интересно, то я хочу продолжить рассказ о других возможностях NORD POS, которые появились благодаря использованию сторонних библиотек. Но прежде хотел бы сделать небольшой опрос среди тех читателей, кто обе части дочитал до конца.

Автор: Svininykh

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js