From de039d75f45293568ed12fef87f26affd3263024 Mon Sep 17 00:00:00 2001 From: Roberto Fichera Date: Tue, 10 Dec 2019 16:28:10 +0100 Subject: [PATCH 01/24] [10.0] ADD fiscal_epos_print --- fiscal_epos_print/README.rst | 29 + fiscal_epos_print/__init__.py | 3 + fiscal_epos_print/__manifest__.py | 38 + fiscal_epos_print/i18n/it.po | 347 ++++ fiscal_epos_print/models/__init__.py | 7 + fiscal_epos_print/models/account.py | 12 + fiscal_epos_print/models/account_journal.py | 25 + fiscal_epos_print/models/point_of_sale.py | 21 + fiscal_epos_print/models/pos_order.py | 33 + fiscal_epos_print/models/product.py | 15 + .../static/lib/fiscalprint/fiscalprint.js | 1435 +++++++++++++++++ .../static/lib/pikaday/pikaday.min.css | 5 + .../static/lib/pikaday/pikaday.min.js | 1 + fiscal_epos_print/static/src/css/pos.css | 5 + fiscal_epos_print/static/src/img/ade-logo.png | Bin 0 -> 1323 bytes fiscal_epos_print/static/src/js/fp90iii.js | 658 ++++++++ fiscal_epos_print/static/src/js/models.js | 8 + fiscal_epos_print/static/src/xml/pos.xml | 74 + .../views/account_statement_view.xml | 31 + fiscal_epos_print/views/assets.xml | 15 + fiscal_epos_print/views/point_of_sale.xml | 42 + oca_dependencies.txt | 1 + 22 files changed, 2805 insertions(+) create mode 100644 fiscal_epos_print/README.rst create mode 100644 fiscal_epos_print/__init__.py create mode 100644 fiscal_epos_print/__manifest__.py create mode 100644 fiscal_epos_print/i18n/it.po create mode 100644 fiscal_epos_print/models/__init__.py create mode 100644 fiscal_epos_print/models/account.py create mode 100644 fiscal_epos_print/models/account_journal.py create mode 100644 fiscal_epos_print/models/point_of_sale.py create mode 100644 fiscal_epos_print/models/pos_order.py create mode 100644 fiscal_epos_print/models/product.py create mode 100644 fiscal_epos_print/static/lib/fiscalprint/fiscalprint.js create mode 100644 fiscal_epos_print/static/lib/pikaday/pikaday.min.css create mode 100644 fiscal_epos_print/static/lib/pikaday/pikaday.min.js create mode 100644 fiscal_epos_print/static/src/css/pos.css create mode 100644 fiscal_epos_print/static/src/img/ade-logo.png create mode 100644 fiscal_epos_print/static/src/js/fp90iii.js create mode 100644 fiscal_epos_print/static/src/js/models.js create mode 100644 fiscal_epos_print/static/src/xml/pos.xml create mode 100644 fiscal_epos_print/views/account_statement_view.xml create mode 100644 fiscal_epos_print/views/assets.xml create mode 100644 fiscal_epos_print/views/point_of_sale.xml diff --git a/fiscal_epos_print/README.rst b/fiscal_epos_print/README.rst new file mode 100644 index 000000000000..1ac3fc6d05e1 --- /dev/null +++ b/fiscal_epos_print/README.rst @@ -0,0 +1,29 @@ +=================== +EPoS Fiscal Printer +=================== + +This module allow to print receipt of point_of_sale, +on fiscal printer Epson via EPos protocol. + +Configuration +============= + +- print list departments of your fiscal printer +- mapping odoo sale taxes with group taxes - departments of fiscal printer, for each sale tax on odoo, using field "Department group tax on fiscal printer 1~99" +- In odoo, use taxes included in price +- connect your fiscal printer on network and find IP +- open point_of_sale configuration and fill Printer IP Address field, with printer IP +- that's all, at validation of payment on POS session system print fiscal receipt. + + +Credits +======= + +Contributors +------------ + +* Leonardo Donelli +* Lorenzo Battistini +* Alessio Gerace + +Do not contact contributors directly about support or help with technical issues. diff --git a/fiscal_epos_print/__init__.py b/fiscal_epos_print/__init__.py new file mode 100644 index 000000000000..23ac4f955b7d --- /dev/null +++ b/fiscal_epos_print/__init__.py @@ -0,0 +1,3 @@ +# coding=utf-8 + +from . import models diff --git a/fiscal_epos_print/__manifest__.py b/fiscal_epos_print/__manifest__.py new file mode 100644 index 000000000000..21cb7e113e0f --- /dev/null +++ b/fiscal_epos_print/__manifest__.py @@ -0,0 +1,38 @@ +# coding=utf-8 +# Leonardo Donelli - Creativi Quadrati +# © 2016 Alessio Gerace - Agile Business Group +# © 2018-2019 Lorenzo Battistini +# © 2019 Roberto Fichera - Level Prime Srl +# License GPL-3.0 or later (http://www.gnu.org/licenses/gpl.html). + +{ + 'name': 'Driver for ePOS-Print XML compatible fiscal printers', + 'version': '10.0.1.0.0', + 'category': 'POS, Fiscal, Hardware, Driver', + 'summary': 'ePOS-Print XML Fiscal Printer Driver', + 'author': ( + 'Agile Business Group, ' + 'Leonardo Donelli @ Creativi Quadrati, TAKOBI, ' + 'Level Prime Srl' + ), + 'website': 'https://takobi.online', + 'depends': [ + 'point_of_sale', + 'pos_order_mgmt', + ], + 'data': [ + 'views/account_statement_view.xml', + 'views/point_of_sale.xml', + 'views/assets.xml', + ], + 'js': [ + 'static/src/js/models.js', + 'static/src/js/fp90iii.js', + 'static/lib/fiscalprint/fiscalprint.js' + ], + 'qweb': [ + 'static/src/xml/pos.xml' + ], + 'installable': True, + 'auto_install': False, +} diff --git a/fiscal_epos_print/i18n/it.po b/fiscal_epos_print/i18n/it.po new file mode 100644 index 000000000000..4104f62d5e97 --- /dev/null +++ b/fiscal_epos_print/i18n/it.po @@ -0,0 +1,347 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * fiscal_epos_print +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-12-11 14:47+0000\n" +"PO-Revision-Date: 2019-12-11 14:47+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:264 +#, python-format +msgid "\n" +"Old files: " +msgstr "\n" +"Vecchi files: " + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:264 +#, python-format +msgid "\n" +"Rejected files: " +msgstr "\n" +"Files respinti: " + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:630 +#, python-format +msgid "ADE files status" +msgstr "ADE files status" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:6 +#, python-format +msgid "ADE status" +msgstr "ADE status" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:59 +#, python-format +msgid "Apply" +msgstr "Applica" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:62 +#, python-format +msgid "Cancel" +msgstr "Cancella" + +#. module: fiscal_epos_print +#: selection:account.journal,fiscalprinter_payment_type:0 +msgid "Cash" +msgstr "Contanti" + +#. module: fiscal_epos_print +#: selection:account.journal,fiscalprinter_payment_type:0 +msgid "Cheque" +msgstr "Cheque" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:606 +#, python-format +msgid "Connecting to the fiscal printer" +msgstr "Collegamento con la stampante fiscale" + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_account_journal_fiscalprinter_payment_index +msgid "Credit Card/Ticket Index" +msgstr "Carta di Credito/Ticket Index" + +#. module: fiscal_epos_print +#: selection:account.journal,fiscalprinter_payment_type:0 +msgid "Credit/Credit Card" +msgstr "Credito/Carta di Credito" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:50 +#, python-format +msgid "DDMMYYYY" +msgstr "DDMMYYYY" + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_account_tax_fpdeptax +msgid "Department group tax on fiscal printer 1~99" +msgstr "Reparto sulla stampante fiscale 1~99" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:399 +#, python-format +msgid "Discount" +msgstr "Sconto" + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_pos_order_refund_doc_num +msgid "Document Number" +msgstr "Numero Documento" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:256 +#, python-format +msgid "Error missing paper." +msgstr "Errore Manca La carta." + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:264 +#, python-format +msgid "Files waiting to be sent: " +msgstr "File in attesa di essere inviati: " + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:442 +#, python-format +msgid "Fiscal Closing" +msgstr "Fiscal Closing" + +#. module: fiscal_epos_print +#: model:ir.ui.view,arch_db:fiscal_epos_print.view_pos_config_printer_form +msgid "Fiscal printer" +msgstr "Stampante fiscale" + +#. module: fiscal_epos_print +#: model:ir.model,name:fiscal_epos_print.model_account_journal +msgid "Journal" +msgstr "Registro" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:40 +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:45 +#, python-format +msgid "Max 4 numbers" +msgstr "Max 4 numeri" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:271 +#, python-format +msgid "Network error. Printer can not be reached" +msgstr "Errore di rete. La stampante non può essere raggiunta" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:472 +#, python-format +msgid "No taxes found" +msgstr "Nessuna imposta trovata" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:337 +#, python-format +msgid "Payment" +msgstr "Pagamento" + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_account_journal_fiscalprinter_payment_type +msgid "Payment type" +msgstr "Tipo pagamento" + +#. module: fiscal_epos_print +#: model:ir.model,name:fiscal_epos_print.model_pos_order +msgid "Point of Sale Orders" +msgstr "Ordini del Punto Vendita" + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_pos_config_printer_ip +msgid "Printer IP Address" +msgstr "Indirizzo IP Stampante" + +#. module: fiscal_epos_print +#: code:addons/fiscal_epos_print/models/product.py:15 +#, python-format +msgid "Product %s must have 1 tax" +msgstr "Il prodotto %s deve avere una aliquota iva" + +#. module: fiscal_epos_print +#: model:ir.model,name:fiscal_epos_print.model_product_template +msgid "Product Template" +msgstr "Template del Prodotto" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:53 +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:55 +#, python-format +msgid "RT Serial" +msgstr "Seriale RT" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:48 +#, python-format +msgid "Receipt Date" +msgstr "Data Scontrino" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:43 +#, python-format +msgid "Receipt Num." +msgstr "Num. Scontrino" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:12 +#, python-format +msgid "Receipt sent to the printer" +msgstr "Scontrino spedito alla stampante" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:411 +#, python-format +msgid "Refund >>> " +msgstr "Reso >>> " + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_pos_order_refund_cash_fiscal_serial +msgid "Refund Cash Serial" +msgstr "Refund Cash Serial" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:25 +#, python-format +msgid "Refund Data" +msgstr "Dati Reso" + +#. module: fiscal_epos_print +#: model:ir.ui.view,arch_db:fiscal_epos_print.view_pos_pos_form_refund_info +msgid "Refund Info" +msgstr "Informazioni Reso" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:113 +#, python-format +msgid "Refund Information Details" +msgstr "Dettagli Reso" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:34 +#, python-format +msgid "Refund Information Not Present" +msgstr "Dettagli Reso non presenti" + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_pos_order_refund_date +msgid "Refund date reference" +msgstr "Data riferimento Reso" + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_pos_order_refund_report +msgid "Report reference" +msgstr "Report reference" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:38 +#, python-format +msgid "Seq. Closing" +msgstr "Seq. Chiusura" + +#. module: fiscal_epos_print +#: model:ir.model.fields,help:fiscal_epos_print.field_account_journal_fiscalprinter_payment_index +msgid "Set the index of the given payment type to specify the detail. Such index of the payment type must programmed on the fiscal printer" +msgstr "Imposta l'indice del tipo pagamento indicato. L'indice del pagamento deve essere programmato nella stampante fiscale" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:66 +#, python-format +msgid "Some fields are empty." +msgstr "Alcuni campi sono vuoti." + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:6 +#, python-format +msgid "Status of files to be sent to ADE" +msgstr "Stato del file da spedire all'ADE" + +#. module: fiscal_epos_print +#: model:ir.model,name:fiscal_epos_print.model_account_tax +msgid "Tax" +msgstr "Imposta" + +#. module: fiscal_epos_print +#: model:ir.model.fields,help:fiscal_epos_print.field_pos_config_printer_ip +msgid "The hostname or ip address of the hardware printer, please fill this field if you want use you receipts printer" +msgstr "Hostname o indirizzo IP della stampante fisica, riempi il campo se vuoi usare la stampate degli scontrini" + +#. module: fiscal_epos_print +#: model:ir.model.fields,help:fiscal_epos_print.field_account_journal_fiscalprinter_payment_type +msgid "The payment type to send to the Fiscal Printer." +msgstr "Tipo di pagamento da spedire alla Stampante Fiscale." + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/js/fp90iii.js:35 +#, python-format +msgid "The refund information aren't present. Please insert them before printing the receipt" +msgstr "Le informazioni del reso non sono presenti. Si prega di inserirle prima di stampare lo scontrino" + +#. module: fiscal_epos_print +#: selection:account.journal,fiscalprinter_payment_type:0 +msgid "Ticket" +msgstr "Ticket" + +#. module: fiscal_epos_print +#: model:ir.model.fields,field_description:fiscal_epos_print.field_pos_config_use_https +msgid "Use https" +msgstr "Usa https" + +#. module: fiscal_epos_print +#. openerp-web +#: code:addons/fiscal_epos_print/static/src/xml/pos.xml:19 +#, python-format +msgid "display:none" +msgstr "display:none" + +#. module: fiscal_epos_print +#: model:ir.model,name:fiscal_epos_print.model_pos_config +msgid "pos.config" +msgstr "pos.config" + diff --git a/fiscal_epos_print/models/__init__.py b/fiscal_epos_print/models/__init__.py new file mode 100644 index 000000000000..35aabec125f2 --- /dev/null +++ b/fiscal_epos_print/models/__init__.py @@ -0,0 +1,7 @@ +# coding=utf-8 + +from . import account_journal +from . import point_of_sale +from . import account +from . import product +from . import pos_order diff --git a/fiscal_epos_print/models/account.py b/fiscal_epos_print/models/account.py new file mode 100644 index 000000000000..767476ad5146 --- /dev/null +++ b/fiscal_epos_print/models/account.py @@ -0,0 +1,12 @@ +# coding=utf-8 + +from odoo import fields, models + + +class AccountTax(models.Model): + _inherit = 'account.tax' + + fpdeptax = fields.Char( + 'Department group tax on fiscal printer 1~99', + size=1, default="1" + ) diff --git a/fiscal_epos_print/models/account_journal.py b/fiscal_epos_print/models/account_journal.py new file mode 100644 index 000000000000..24459cc89648 --- /dev/null +++ b/fiscal_epos_print/models/account_journal.py @@ -0,0 +1,25 @@ +# coding=utf-8 + +from odoo import fields, models + + +class AccountJournal(models.Model): + _inherit = 'account.journal' + + fiscalprinter_payment_type = fields.Selection( + [ + ('0', 'Cash'), + ('1', 'Cheque'), + ('2', 'Credit/Credit Card'), + ('3', 'Ticket') + ], + 'Payment type', + help='The payment type to send to the Fiscal Printer.', + default='0' + ) + + fiscalprinter_payment_index = fields.Integer( + string='Credit Card/Ticket Index', + help='Set the index of the given payment type to specify the detail. ' + 'Such index of the payment type must programmed on the fiscal ' + 'printer') diff --git a/fiscal_epos_print/models/point_of_sale.py b/fiscal_epos_print/models/point_of_sale.py new file mode 100644 index 000000000000..13f7b13e8b17 --- /dev/null +++ b/fiscal_epos_print/models/point_of_sale.py @@ -0,0 +1,21 @@ +# coding=utf-8 + +from odoo import fields, models + + +class PosConfig(models.Model): + _inherit = 'pos.config' + + printer_ip = fields.Char( + 'Printer IP Address', + help='The hostname or ip address of the hardware printer, ' + 'please fill this field if you want use you receipts printer', + size=45 + ) + use_https = fields.Boolean( + string='Use https', + default=False, + ) + + show_receipt_when_printing = fields.Boolean( + string='Show receipt on screen when printing', default=True) diff --git a/fiscal_epos_print/models/pos_order.py b/fiscal_epos_print/models/pos_order.py new file mode 100644 index 000000000000..88939f963209 --- /dev/null +++ b/fiscal_epos_print/models/pos_order.py @@ -0,0 +1,33 @@ +# coding=utf-8 + +from odoo import fields, models, api + + +class PosOrder(models.Model): + _inherit = 'pos.order' + + refund_date = fields.Date(string='Refund date reference') + refund_report = fields.Integer(string='Report reference', digits=(4, 0)) + refund_doc_num = fields.Integer(string='Document Number', digits=(4, 0)) + refund_cash_fiscal_serial = fields.Char(string='Refund Cash Serial') + + @api.model + def _order_fields(self, ui_order): + res = super(PosOrder, self)._order_fields(ui_order) + res['refund_date'] = ui_order['refund_date'] or False + res['refund_report'] = ui_order['refund_report'] or False + res['refund_doc_num'] = ui_order['refund_doc_num'] or False + res['refund_cash_fiscal_serial'] = \ + ui_order['refund_cash_fiscal_serial'] or False + return res + + # This is on pos_order_mgmt to send back the fields of already existing + # pos.order + @api.multi + def _prepare_done_order_for_pos(self): + res = super(PosOrder, self)._prepare_done_order_for_pos() + res['refund_date'] = self.refund_date + res['refund_report'] = self.refund_report + res['refund_doc_num'] = self.refund_doc_num + res['refund_cash_fiscal_serial'] = self.refund_cash_fiscal_serial + return res diff --git a/fiscal_epos_print/models/product.py b/fiscal_epos_print/models/product.py new file mode 100644 index 000000000000..7a256523ba75 --- /dev/null +++ b/fiscal_epos_print/models/product.py @@ -0,0 +1,15 @@ +# coding=utf-8 + +from odoo import models, api, _ +from odoo.exceptions import ValidationError + + +class Product(models.Model): + _inherit = 'product.template' + + @api.constrains('available_in_pos', 'taxes_id') + def _check_pos_prod_taxes(self): + if self.available_in_pos: + if len(self.taxes_id) != 1: + raise ValidationError( + _("Product %s must have 1 tax") % self.display_name) diff --git a/fiscal_epos_print/static/lib/fiscalprint/fiscalprint.js b/fiscal_epos_print/static/lib/fiscalprint/fiscalprint.js new file mode 100644 index 000000000000..5fc128e5ca6b --- /dev/null +++ b/fiscal_epos_print/static/lib/fiscalprint/fiscalprint.js @@ -0,0 +1,1435 @@ +// +// ePOS-Print and Fiscal Print API +// +// Version 1.0.0 +// +// Copyright (C) SEIKO EPSON CORPORATION 2012. All rights reserved. +// + +(function (window) +{ + // + // Function: ePOSBuilder constructor + // Description: initialize an ePOS-Print XML Builder object + // Parameters: none + // Return: none + // + function ePOSBuilder() { + // properties + this.message = ''; + // constants + this.FONT_A = 'font_a'; + this.FONT_B = 'font_b'; + this.FONT_C = 'font_c'; + this.FONT_SPECIAL_A = 'special_a'; + this.FONT_SPECIAL_B = 'special_b'; + this.ALIGN_LEFT = 'left'; + this.ALIGN_CENTER = 'center'; + this.ALIGN_RIGHT = 'right'; + this.COLOR_NONE = 'none'; + this.COLOR_1 = 'color_1'; + this.COLOR_2 = 'color_2'; + this.COLOR_3 = 'color_3'; + this.COLOR_4 = 'color_4'; + this.BARCODE_UPC_A = 'upc_a'; + this.BARCODE_UPC_E = 'upc_e'; + this.BARCODE_EAN13 = 'ean13'; + this.BARCODE_JAN13 = 'jan13'; + this.BARCODE_EAN8 = 'ean8'; + this.BARCODE_JAN8 = 'jan8'; + this.BARCODE_CODE39 = 'code39'; + this.BARCODE_ITF = 'itf'; + this.BARCODE_CODABAR = 'codabar'; + this.BARCODE_CODE93 = 'code93'; + this.BARCODE_CODE128 = 'code128'; + this.BARCODE_GS1_128 = 'gs1_128'; + this.BARCODE_GS1_DATABAR_OMNIDIRECTIONAL = 'gs1_databar_omnidirectional'; + this.BARCODE_GS1_DATABAR_TRUNCATED = 'gs1_databar_truncated'; + this.BARCODE_GS1_DATABAR_LIMITED = 'gs1_databar_limited'; + this.BARCODE_GS1_DATABAR_EXPANDED = 'gs1_databar_expanded'; + this.HRI_NONE = 'none'; + this.HRI_ABOVE = 'above'; + this.HRI_BELOW = 'below'; + this.HRI_BOTH = 'both'; + this.SYMBOL_PDF417_STANDARD = 'pdf417_standard'; + this.SYMBOL_PDF417_TRUNCATED = 'pdf417_truncated'; + this.SYMBOL_QRCODE_MODEL_1 = 'qrcode_model_1'; + this.SYMBOL_QRCODE_MODEL_2 = 'qrcode_model_2'; + this.SYMBOL_MAXICODE_MODE_2 = 'maxicode_mode_2'; + this.SYMBOL_MAXICODE_MODE_3 = 'maxicode_mode_3'; + this.SYMBOL_MAXICODE_MODE_4 = 'maxicode_mode_4'; + this.SYMBOL_MAXICODE_MODE_5 = 'maxicode_mode_5'; + this.SYMBOL_MAXICODE_MODE_6 = 'maxicode_mode_6'; + this.SYMBOL_GS1_DATABAR_STACKED = 'gs1_databar_stacked'; + this.SYMBOL_GS1_DATABAR_STACKED_OMNIDIRECTIONAL = 'gs1_databar_stacked_omnidirectional'; + this.SYMBOL_GS1_DATABAR_EXPANDED_STACKED = 'gs1_databar_expanded_stacked'; + this.LEVEL_0 = 'level_0'; + this.LEVEL_1 = 'level_1'; + this.LEVEL_2 = 'level_2'; + this.LEVEL_3 = 'level_3'; + this.LEVEL_4 = 'level_4'; + this.LEVEL_5 = 'level_5'; + this.LEVEL_6 = 'level_6'; + this.LEVEL_7 = 'level_7'; + this.LEVEL_8 = 'level_8'; + this.LEVEL_L = 'level_l'; + this.LEVEL_M = 'level_m'; + this.LEVEL_Q = 'level_q'; + this.LEVEL_H = 'level_h'; + this.LEVEL_DEFAULT = 'default'; + this.LINE_THIN = 'thin'; + this.LINE_MEDIUM = 'medium'; + this.LINE_THICK = 'thick'; + this.LINE_THIN_DOUBLE = 'thin_double'; + this.LINE_MEDIUM_DOUBLE = 'medium_double'; + this.LINE_THICK_DOUBLE = 'thick_double'; + this.DIRECTION_LEFT_TO_RIGHT = 'left_to_right'; + this.DIRECTION_BOTTOM_TO_TOP = 'bottom_to_top'; + this.DIRECTION_RIGHT_TO_LEFT = 'right_to_left'; + this.DIRECTION_TOP_TO_BOTTOM = 'top_to_bottom'; + this.CUT_NO_FEED = 'no_feed'; + this.CUT_FEED = 'feed'; + this.CUT_RESERVE = 'reserve'; + this.DRAWER_1 = 'drawer_1'; + this.DRAWER_2 = 'drawer_2'; + this.PULSE_100 = 'pulse_100'; + this.PULSE_200 = 'pulse_200'; + this.PULSE_300 = 'pulse_300'; + this.PULSE_400 = 'pulse_400'; + this.PULSE_500 = 'pulse_500'; + this.PATTERN_NONE = 'none'; + this.PATTERN_A = 'pattern_a'; + this.PATTERN_B = 'pattern_b'; + this.PATTERN_C = 'pattern_c'; + this.PATTERN_D = 'pattern_d'; + this.PATTERN_E = 'pattern_e'; + this.PATTERN_ERROR = 'error'; + this.PATTERN_PAPER_END = 'paper_end'; + } + + // + // Function: addFeedUnit method + // Description: append the XML element to print and feed paper + // Parameters: + // unit unsignedbyte paper feed amount (units) + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addFeedUnit = function (unit) { + // create empty string + var s = ''; + // check parameter + s += getUByteAttr('unit', unit); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addFeedLine method + // Description: append the XML element to print and feed n lines + // Parameters: + // line unsignedbyte paper feed amount (lines) + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addFeedLine = function (line) { + // create empty string + var s = ''; + // check parameter + s += getUByteAttr('line', line); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addText method + // Description: append the XML element to print characters + // Parameters: + // data string characters + // Return: object ePOSBuilder object + // + ePOSBuilder.prototype.addText = function (data) { + // append element + this.message += '' + encodeXmlEntity(data) + ''; + // return builder object + return this; + } + + // + // Function: addTextLang method + // Description: append the XML element to select language + // Parameters: + // lang string language code and country code (en, en-US, ja, ja-JP, etc.) + // Return: object ePOSBuilder object + // + ePOSBuilder.prototype.addTextLang = function (lang) { + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextAlign method + // Description: append the XML element to set alignment + // Parameters: + // align string alignment (ALIGN_* constants) + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextAlign = function (align) { + // create empty string + var s = ''; + // check parameter + s += getEnumAttr('align', align, regexAlign); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextRotate method + // Description: append the XML element to turn upside-down print mode on/off + // Parameters: + // rotate boolean when true, upside-down print mode is turned on + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextRotate = function (rotate) { + // create empty string + var s = ''; + // check parameter + s += getBoolAttr('rotate', rotate); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextLineSpace method + // Description: append the XML element to set line spacing + // Parameters: + // linespc unsignedByte the amount of line spacing + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextLineSpace = function (linespc) { + // create empty string + var s = ''; + // check parameter + s += getUByteAttr('linespc', linespc); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextFont method + // Description: append the XML element to select character font + // Parameters: + // font string font (FONT_* constants) + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextFont = function (font) { + // create empty string + var s = ''; + // check parameter + s += getEnumAttr('font', font, regexFont); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextSmooth method + // Description: append the XML element to turn smoothing mode on/off + // Parameters: + // smooth boolean when true, smoothing mode is turned on + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextSmooth = function (smooth) { + // create empty string + var s = ''; + // check parameter + s += getBoolAttr('smooth', smooth); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextDouble method + // Description: append the XML element to turn double-wide/double-high mode on/off + // Parameters: + // dw boolean when true, double-wide mode is turned on [option] + // dh boolean when true, double-high mode is turned on [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextDouble = function (dw, dh) { + // create empty string + var s = ''; + // check parameter (option) + if (dw !== undefined) { + s += getBoolAttr('dw', dw); + } + // check parameter (option) + if (dh !== undefined) { + s += getBoolAttr('dh', dh); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextSize method + // Description: append the XML element to select character size + // Parameters: + // width unsignedByte character width (1 to 8) [option] + // height unsignedByte character height (1 to 8) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextSize = function (width, height) { + // create empty string + var s = ''; + // check parameter (option) + if (width !== undefined) { + s += getIntAttr('width', width, 1, 8); + } + // check parameter (option) + if (height !== undefined) { + s += getIntAttr('height', height, 1, 8); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextStyle method + // Description: append the XML element to select character style + // Parameters: + // reverse boolean when true, black/white reverse print mode is turned on [option] + // ul boolean when true, underline mode is turned on [option] + // em boolean when true, emphasized mode is turned on [option] + // color string color (COLOR_* constants) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextStyle = function (reverse, ul, em, color) { + // create empty string + var s = ''; + // check parameter (option) + if (reverse !== undefined) { + s += getBoolAttr('reverse', reverse); + } + // check parameter (option) + if (ul !== undefined) { + s += getBoolAttr('ul', ul); + } + // check parameter (option) + if (em !== undefined) { + s += getBoolAttr('em', em); + } + // check parameter (option) + if (color !== undefined) { + s += getEnumAttr('color', color, regexColor); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addTextPosition method + // Description: append the XML element to set absolute print position + // Parameters: + // x unsignedShort X start position + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addTextPosition = function (x) { + // create empty string + var s = ''; + // check parameter + s += getUShortAttr('x', x); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addImage method + // Description: append the XML element to print the graphics data (raster format) + // Parameters: + // context object the 2-D context of HTML 5 Canvas + // x unsignedShort X start position + // y unsignedShort Y start position + // width unsignedShort horizontal size + // height unsignedShort vertical size + // color string color (COLOR_* constants) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addImage = function (context, x, y, width, height, color) { + // create empty string + var s = ''; + // check parameter + getUShortAttr('x', x); + // check parameter + getUShortAttr('y', y); + // check parameter + s += getUShortAttr('width', width); + // check parameter + s += getUShortAttr('height', height); + // check parameter (option) + if (color !== undefined) { + s += getEnumAttr('color', color, regexColor); + } + // create image data + var image = encodeRasterImage(context.getImageData(x, y, width, height).data, width, height); + // append element + this.message += '' + encodeBase64Binary(image) + ''; + // return builder object + return this; + } + + // + // Function: addLogo method + // Description: append the XML element to print specified NV graphics data + // Parameters: + // key1 unsignedShort key code 1 + // key2 unsignedShort key code 2 + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addLogo = function (key1, key2) { + // create empty string + var s = ''; + // check parameter + s += getUByteAttr('key1', key1); + // check parameter + s += getUByteAttr('key2', key2); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addBarcode method + // Description: append the XML element to print bar code + // Parameters: + // data object bar code data (characters, escape sequences '\xnn', '\\') + // type string bar code type (BARCODE_* constants) + // hri string print position of HRI characters (HRI_* constants) [option] + // font string font for HRI characters (FONT_* constants) [option] + // width unsignedByte bar code module width [option] + // height unsignedByte bar code module height [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addBarcode = function (data, type, hri, font, width, height) { + // create empty string + var s = ''; + // check parameter + s += getEnumAttr('type', type, regexBarcode); + // check parameter (option) + if (hri !== undefined) { + s += getEnumAttr('hri', hri, regexHri); + } + // check parameter (option) + if (font !== undefined) { + s += getEnumAttr('font', font, regexFont); + } + // check parameter (option) + if (width !== undefined) { + s += getUByteAttr('width', width); + } + // check parameter (option) + if (height !== undefined) { + s += getUByteAttr('height', height); + } + // append element + this.message += '' + escapeText(encodeXmlEntity(data)) + ''; + // return builder object + return this; + } + + // + // Function: addSymbol method + // Description: append the XML element to print two dimension code + // Parameters: + // data object symbol data (characters, escape sequences '\xnn', '\\') + // type string symbol type (SYMBOL_* constants) + // level string error correction level (LEVEL_* constants) [option] + // width unsignedByte module width (PDF417, QR Code, GS1 DataBar) [option] + // height unsignedByte module height (PDF417) [option] + // size unsignedShort the number of columns (PDF417), maximum width (GS1 DataBar) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addSymbol = function (data, type, level, width, height, size) { + // create empty string + var s = ''; + // check parameter + s += getEnumAttr('type', type, regexSymbol); + // check parameter (option) + if (level !== undefined) { + s += getEnumAttr('level', level, regexLevel); + } + // check parameter (option) + if (width !== undefined) { + s += getUByteAttr('width', width); + } + // check parameter (option) + if (height !== undefined) { + s += getUByteAttr('height', height); + } + // check parameter (option) + if (size !== undefined) { + s += getUShortAttr('size', size); + } + // append element + this.message += '' + escapeText(encodeXmlEntity(data)) + ''; + // return builder object + return this; + } + + // + // Function: addCommand method + // Description: append the XML element to send commands + // Parameters: + // data string commands + // Return: object ePOSBuilder object + // + ePOSBuilder.prototype.addCommand = function (data) { + // append element + this.message += '' + encodeHexBinary(data) + ''; + // return builder object + return this; + } + + // + // Function: addHLine method + // Description: append the XML element to draw horizontal line + // Parameters: + // x1 unsignedShort X start position + // x2 unsignedShort X end position + // style string the style of line (LINE_* constants) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addHLine = function (x1, x2, style) { + // create empty string + var s = ''; + // check parameter + s += getUShortAttr('x1', x1); + // check parameter + s += getUShortAttr('x2', x2); + // check parameter (option) + if (style !== undefined) { + s += getEnumAttr('style', style, regexLine); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addVLineBegin method + // Description: append the XML element to draw vertical line + // Parameters: + // x unsignedShort X start position + // style string the style of line (LINE_* constants) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addVLineBegin = function (x, style) { + // create empty string + var s = ''; + // check parameter + s += getUShortAttr('x', x); + // check parameter (option) + if (style !== undefined) { + s += getEnumAttr('style', style, regexLine); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addVLineEnd method + // Description: append the XML element to draw vertical line + // Parameters: + // x unsignedShort X end position + // style string the style of line (LINE_* constants) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addVLineEnd = function (x, style) { + // create empty string + var s = ''; + // check parameter + s += getUShortAttr('x', x); + // check parameter (option) + if (style !== undefined) { + s += getEnumAttr('style', style, regexLine); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addPageBegin method + // Description: append the XML element to select page mode + // Parameters: none + // Return: object ePOSBuilder object + // + ePOSBuilder.prototype.addPageBegin = function () { + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addPageEnd method + // Description: append the XML element to print and return to standard mode (in page mode) + // Parameters: none + // Return: object ePOSBuilder object + // + ePOSBuilder.prototype.addPageEnd = function () { + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addPageArea method + // Description: append the XML element to set print area in page mode + // Parameters: + // x unsignedShort horizontal logical origin + // y unsignedShort vertical logical origin + // width unsignedShort print area width + // height unsignedShort print area height + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addPageArea = function (x, y, width, height) { + // create empty string + var s = ''; + // check parameter + s += getUShortAttr('x', x); + // check parameter + s += getUShortAttr('y', y); + // check parameter + s += getUShortAttr('width', width); + // check parameter + s += getUShortAttr('height', height); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addPageDirection method + // Description: append the XML element to select print direction in page mode + // Parameters: + // dir string direction (DIRECTION_* constants) + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addPageDirection = function (dir) { + // create empty string + var s = ''; + // check parameter + s += getEnumAttr('dir', dir, regexDirection); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addPagePosition method + // Description: append the XML element to set absolute print position in page mode + // Parameters: + // x unsignedShort horizontal position + // y unsignedShort vertical position + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addPagePosition = function (x, y) { + // create empty string + var s = ''; + // check parameter + s += getUShortAttr('x', x); + // check parameter + s += getUShortAttr('y', y); + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addPageLine method + // Description: append the XML element to draw line in page mode + // Parameters: + // x1 unsignedShort X start position + // y1 unsignedShort Y start position + // x2 unsignedShort X end position + // y2 unsignedShort Y end position + // style string the style of line (LINE_* constants) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addPageLine = function (x1, y1, x2, y2, style) { + // create empty string + var s = ''; + // check parameter + s += getUShortAttr('x1', x1); + // check parameter + s += getUShortAttr('y1', y1); + // check parameter + s += getUShortAttr('x2', x2); + // check parameter + s += getUShortAttr('y2', y2); + // check parameter (option) + if (style !== undefined) { + s += getEnumAttr('style', style, regexLine); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addPageRectangle method + // Description: append the XML element to draw rectangle in page mode + // Parameters: + // x1 unsignedShort X start position + // y1 unsignedShort Y start position + // x2 unsignedShort X end position + // y2 unsignedShort Y end position + // style string the style of line (LINE_* constants) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addPageRectangle = function (x1, y1, x2, y2, style) { + // create empty string + var s = ''; + // check parameter + s += getUShortAttr('x1', x1); + // check parameter + s += getUShortAttr('y1', y1); + // check parameter + s += getUShortAttr('x2', x2); + // check parameter + s += getUShortAttr('y2', y2); + // check parameter (option) + if (style !== undefined) { + s += getEnumAttr('style', style, regexLine); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addCut method + // Description: append the XML element to cut paper + // Parameters: + // type string cut mode (CUT_* constants) [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addCut = function (type) { + // create empty string + var s = ''; + // check parameter (option) + if (type !== undefined) { + s += getEnumAttr('type', type, regexCut); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addPulse method + // Description: append the XML element to generate pulse + // Parameters: + // drawer string drawer kick-out connector pin (DRAWER_* constants) [option] + // time string the pulse on/off time [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addPulse = function (drawer, time) { + // create empty string + var s = ''; + // check parameter (option) + if (drawer !== undefined) { + s += getEnumAttr('drawer', drawer, regexDrawer); + } + // check parameter (option) + if (time !== undefined) { + s += getEnumAttr('time', time, regexPulse); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Function: addSound method + // Description: append the XML element to sound buzzer + // Parameters: + // pattern string a pattern (PATTERN_* constants) [option] + // repeat unsignedByte the number of times [option] + // Return: object ePOSBuilder object + // Throws: object invalid parameter + // + ePOSBuilder.prototype.addSound = function (pattern, repeat) { + // create empty string + var s = ''; + // check parameter (option) + if (pattern !== undefined) { + s += getEnumAttr('pattern', pattern, regexPattern); + } + // check parameter (option) + if (repeat !== undefined) { + s += getUByteAttr('repeat', repeat); + } + // append element + this.message += ''; + // return builder object + return this; + } + + // + // Method: toString + // Description: get the ePOS-Print XML message + // Parameters: none + // Return: string XML message + // + ePOSBuilder.prototype.toString = function () { + // append root element + var epos = '' + + this.message + ''; + // return message + return epos; + } + + // + // Function: encodeHexBinary method + // Description: encode binary data to hex binary data + // Parameters: + // s string binary data + // Return: string hex binary data + // + function encodeHexBinary(s) { + var r = ''; + for (i = 0; i < s.length; i++) { + r += ('0' + s.charCodeAt(i).toString(16)).slice(-2); + } + return r; + } + + // + // Function: encodeBase64Binary method + // Description: encode binary data to base64 binary data + // Parameters: + // s string binary data + // Return: string base64 binary data + // + function encodeBase64Binary(s) { + var r = ''; + var l = s.length; + var t = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + s += '\x00\x00'; + for (var i = 0; i < l; i += 3) { + var n = (s.charCodeAt(i) << 16) | (s.charCodeAt(i + 1) << 8) | s.charCodeAt(i + 2); + r += t.charAt((n >> 18) & 63) + t.charAt((n >> 12) & 63) + t.charAt((n >> 6) & 63) + t.charAt(n & 63); + } + var p = (3 - l % 3) % 3; + return r.slice(0, r.length - p) + '=='.slice(0, p); + } + + // + // Function: encodeRasterImage method + // Description: encode image data to raster bit image data + // Parameters: + // data byte[] RGBA image data + // w int image width + // h int image height + // Return: string raster bit image data + // + function encodeRasterImage(data, w, h) { + var d8 = [ + [0, 32, 8, 40, 2, 34, 10, 42], + [48, 16, 56, 24, 50, 18, 58, 26], + [12, 44, 4, 36, 14, 46, 6, 38], + [60, 28, 52, 20, 62, 30, 54, 22], + [3, 35, 11, 43, 1, 33, 9, 41], + [51, 19, 59, 27, 49, 17, 57, 25], + [15, 47, 7, 39, 13, 45, 5, 37], + [63, 31, 55, 23, 61, 29, 53, 21] + ]; + var s = '', n = 0, p = 0; + for (var y = 0; y < h; y++) { + for (var x = 0; x < w; x++) { + var r = data[p++], g = data[p++], b = data[p++], a = data[p++]; + var v = 255 - a + ((r * 29891 + g * 58661 + b * 11448) * a + 12750000) / 25500000; + var d = (d8[y & 7][x & 7] << 2) + 2; + if (v < d) { + n |= 0x80 >> (x & 7); + } + if ((x & 7) == 7 || x == w - 1) { + s += String.fromCharCode(n == 16 ? 32 : n); + n = 0; + } + } + } + return s; + } + + // + // Function: encodeXmlEntity method + // Description: encode markup character to XML entity + // Parameters: + // s string text data + // Return: string text data with XML entity + // + function encodeXmlEntity(s) { + var markup = /[<>&'"\t\n\r]/g; + if (markup.test(s)) { + s = s.replace(markup, function (c) { + var r = ''; + switch (c) { + case '<': + r = '<'; + break; + case '>': + r = '>'; + break; + case '&': + r = '&'; + break; + case "'": + r = '''; + break; + case '"': + r = '"'; + break; + case '\t': + r = ' '; + break; + case '\n': + r = ' '; + break; + case '\r': + r = ' '; + break; + default: + break; + } + return r; + }); + } + return s; + } + + // + // Function: escapeText method + // Description: escape sequence for bar code and symbol + // Parameters: + // s string text data + // Return: string text data with escape sequence + // + function escapeText(s) { + var escape = /[\\\x00-\x1f\x7f-\xff]/g; + if (escape.test(s)) { + s = s.replace(escape, function (c) { + return (c == '\\') ? '\\\\' : '\\x' + ('0' + c.charCodeAt(0).toString(16)).slice(-2); + }); + } + return s; + } + + // + // Function: regular expressions + // Description: enumeration check pattern + // + var regexFont = /^(font_[abc]|special_[ab])$/; + var regexAlign = /^(left|center|right)$/; + var regexColor = /^(none|color_[1-4])$/; + var regexBarcode = /^(upc_[ae]|[ej]an13|[ej]an8|code(39|93|128)|itf|codabar|gs1_128|gs1_databar_(omnidirectional|truncated|limited|expanded))$/; + var regexHri = /^(none|above|below|both)$/; + var regexSymbol = /^(pdf417_(standard|truncated)|qrcode_model_[12]|maxicode_mode_[2-6]|gs1_databar_(stacked(_omnidirectional)?|expanded_stacked))$/; + var regexLevel = /^(level_[0-8lmqh]|default)$/; + var regexLine = /^(thin|medium|thick)(_double)?$/; + var regexDirection = /^(left_to_right|bottom_to_top|right_to_left|top_to_bottom)$/; + var regexCut = /^(no_feed|feed|reserve)$/; + var regexDrawer = /^(drawer_1|drawer_2)$/; + var regexPulse = /^pulse_[1-5]00$/; + var regexPattern = /^(none|pattern_[a-e]|error|paper_end)$/; + + // + // Function: getEnumAttr method + // Description: get a XML attribute from a parameter (enumration) + // Parameters: + // name string parameter name + // value string parameter value + // regex regex check pattern + // Return: string XML attribute (' name="value"') + // Throws: object invalid parameter + // + function getEnumAttr(name, value, regex) { + if (!regex.test(value)) { + throw new Error('Parameter "' + name + '" is invalid'); + } + return ' ' + name + '="' + value + '"'; + } + + // + // Function: getBoolAttr method + // Description: get a XML attribute from a parameter (boolean) + // Parameters: + // name string parameter name + // value boolean parameter value + // Return: string XML attribute (' name="value"') + // + function getBoolAttr(name, value) { + return ' ' + name + '="' + !!value + '"'; + } + + // + // Function: getIntAttr method + // Description: get a XML attribute from a parameter (integer) + // Parameters: + // name string parameter name + // value integer parameter value + // min integer minumum value + // max integer maximum value + // Return: string XML attribute (' name="value"') + // Throws: object invalid parameter + // + function getIntAttr(name, value, min, max) { + if (isNaN(value) || value < min || value > max) { + throw new Error('Parameter "' + name + '" is invalid'); + } + return ' ' + name + '="' + value + '"'; + } + + // + // Function: getUByteAttr method + // Description: get a XML attribute from a parameter (unsigned byte) + // Parameters: + // name string parameter name + // value integer parameter value + // Return: string XML attribute (' name="value"') + // Throws: object invalid parameter + // + function getUByteAttr(name, value) { + return getIntAttr(name, value, 0, 255); + } + + // + // Function: getUShortAttr method + // Description: get a XML attribute from a parameter (unsigned short) + // Parameters: + // name string parameter name + // value integer parameter value + // Return: string XML attribute (' name="value"') + // Throws: object invalid parameter + // + function getUShortAttr(name, value) { + return getIntAttr(name, value, 0, 65535); + } + + // + // Function: ePOSPrint constructor + // Description: initialize an ePOS-Print object + // Parameters: none + // Return: none + // + function ePOSPrint() { + // events + this.onreceive = null; + this.onerror = null; + // constants + this.ASB_NO_RESPONSE = 0x00000001; + this.ASB_PRINT_SUCCESS = 0x00000002; + this.ASB_DRAWER_KICK = 0x00000004; + this.ASB_OFF_LINE = 0x00000008; + this.ASB_COVER_OPEN = 0x00000020; + this.ASB_PAPER_FEED = 0x00000040; + this.ASB_WAIT_ON_LINE = 0x00000100; + this.ASB_PANEL_SWITCH = 0x00000200; + this.ASB_MECHANICAL_ERR = 0x00000400; + this.ASB_AUTOCUTTER_ERR = 0x00000800; + this.ASB_UNRECOVER_ERR = 0x00002000; + this.ASB_AUTORECOVER_ERR = 0x00004000; + this.ASB_RECEIPT_NEAR_END = 0x00020000; + this.ASB_RECEIPT_END = 0x00080000; + this.ASB_BUZZER = 0x01000000; + this.ASB_SPOOLER_IS_STOPPED = 0x80000000; + } + + // + // Function: ePOSprint send method + // Description: send the ePOS-Print XML message + // Parameters: + // address string the address of ePOS-Print service + // request string request message + // Return: none + // Throws: object the browser does not equip XMLHttpRequest + // + ePOSPrint.prototype.send = function (address, request) { + // create SOAP envelope + var soap = '' + + '' + + request + ''; + // create XMLHttpRequest object + var xhr = createXMLHttpRequest(); + xhr.open('POST', address, true); + // set headers + xhr.setRequestHeader('Content-Type', 'text/xml; charset=UTF-8'); + xhr.setRequestHeader('If-Modified-Since', 'Thu, 01 Jan 1970 00:00:00 GMT'); + xhr.setRequestHeader('SOAPAction', '""'); + // receive event + var epos = this; + xhr.onreadystatechange = function () { + // receive response message + if (xhr.readyState == 4) { + if (xhr.status == 200) { + fireReceiveEvent(epos, xhr); + } + else { + fireErrorEvent(epos, xhr); + } + } + } + // send request message + xhr.send(soap); + } + + + /* + Function: createXMLHttpRequest method + Description: create an XMLHttpRequest object + Parameters: none + Return: object XMLHttpRequest object + Throws: object the browser does not equip XMLHttpRequest + */ + + function createXMLHttpRequest() + { + var xhr = null; + if (window.XMLHttpRequest) + { + xhr = new XMLHttpRequest(); + } + else if (window.ActiveXObject) + { + xhr = new ActiveXObject('Msxml2.XMLHTTP'); + } + else + { + throw new Error('XMLHttpRequest is not supported'); + } + return xhr; + } + + + // + // Function: fireReceiveEvent method + // Description: generate the onreceive event + // Parameters: + // epos object ePOSPrint object + // xhr object XMLHttpRequest object + // Return: none + // + function fireReceiveEvent(epos, xhr) { + if (epos.onreceive) { + var res = xhr.responseXML.getElementsByTagName('response'); + if (res.length > 0) { + // fire onreceive event + epos.onreceive({ + success: /^(1|true)$/.test(res[0].getAttribute('success')), + code: res[0].getAttribute('code'), + status: parseInt(res[0].getAttribute('status')) + }); + } + else { + fireErrorEvent(epos, xhr); + } + } + } + + // + // Function: fireErrorEvent method + // Description: generate the onerror event + // Parameters: + // epos object ePOSPrint object + // xhr object XMLHttpRequest object + // Return: none + // + function fireErrorEvent(epos, xhr) { + // fire onerror event + if (epos.onerror) { + epos.onerror({ + status: xhr.status, + responseText: xhr.responseText + }); + } + } + + +// F I S C A L --- F I S C A L --- F I S C A L --- F I S C A L --- F I S C A L + + /* + Function: fiscalPrint constructor + Description: initialize a fiscalPrint object + Parameters: none + Return: none + */ + + function fiscalPrint() + { + // events + this.onreceive = null; + this.onerror = null; + + // constants + this.ASB_NO_RESPONSE = 0x00000001; + this.ASB_PRINT_SUCCESS = 0x00000002; + this.ASB_DRAWER_KICK = 0x00000004; + this.ASB_OFF_LINE = 0x00000008; + this.ASB_COVER_OPEN = 0x00000020; + this.ASB_PAPER_FEED = 0x00000040; + this.ASB_WAIT_ON_LINE = 0x00000100; + this.ASB_PANEL_SWITCH = 0x00000200; + this.ASB_MECHANICAL_ERR = 0x00000400; + this.ASB_AUTOCUTTER_ERR = 0x00000800; + this.ASB_UNRECOVER_ERR = 0x00002000; + this.ASB_AUTORECOVER_ERR = 0x00004000; + this.ASB_RECEIPT_NEAR_END = 0x00020000; + this.ASB_RECEIPT_END = 0x00080000; + this.ASB_BUZZER = 0x01000000; + this.ASB_SPOOLER_IS_STOPPED = 0x80000000; + } + + + /* + Function: fiscalPrint send method + Description: send the fiscal ePOS-Print XML message + Parameters: + address string The address where fpmate.cgi resides + request string Request message + Return: none + Throws: object The browser does not equip XMLHttpRequest + */ + + fiscalPrint.prototype.send = function (address, request) + { + // create SOAP envelope + var soap = '\n' + + '\n' + + '\n' + + request + + '\n' + + '\n'; + // create XMLHttpRequest object + var xhr = createXMLHttpRequest(); + xhr.open('POST', address, true); + // set headers + xhr.setRequestHeader('Content-Type', 'text/xml; charset=UTF-8'); + xhr.setRequestHeader('If-Modified-Since', 'Thu, 01 Jan 1970 00:00:00 GMT'); + xhr.setRequestHeader('SOAPAction', '""'); + // receive event + var epos = this; + xhr.onreadystatechange = function () + { + // receive response message + // alert("xhr.readyState = " + xhr.readyState + "\n" + "xhr.status = " + xhr.status); + if (xhr.readyState == 4) + { + if (xhr.status == 200) + { + fireFiscalReceiveEvent(epos, xhr); + } + else + { + fireFiscalErrorEvent(epos, xhr); + } + } + } + // send request message + xhr.send(soap); + } + + + /* + Function: fireFiscalReceiveEvent method + Description: generate the onreceive event + Parameters: + epos object ePOSPrint object + xhr object XMLHttpRequest object + Return: none + */ + + function fireFiscalReceiveEvent(epos, xhr) + { + if (epos.onreceive) + { + var res = xhr.responseXML.getElementsByTagName('response'); + // alert (xhr.responseXML.xml); + // document.write(xhr.responseXML.xml); + + if (res.length > 0) + { + // fire onreceive event + var result = + { + success: /^(1|true)$/.test(res[0].getAttribute('success')), + code: res[0].getAttribute('code'), + status: parseInt(res[0].getAttribute('status')) + }; + + // look for additional info + var res_add = res[0].getElementsByTagName('addInfo'); + if (res_add.length > 0) + { + var list = res_add[0].getElementsByTagName('elementList'); + var list_len = list.length; + var tag_names_list = list[0].childNodes[0].nodeValue; + var tag_names_array = tag_names_list.split(','); + var add_info = {}; + for (var i = 0; i < tag_names_array.length; i++) + { + var node = res_add[0].getElementsByTagName(tag_names_array[i])[0]; + var node_child = node.childNodes[0]; + var node_val = node_child.nodeValue; + add_info[tag_names_array[i]] = node_val; + } + } + epos.onreceive(result, tag_names_array, add_info) + } + else // res.length <= 0 + { + // alert ("res.length = " + res.length); + fireFiscalErrorEvent(epos, xhr); + } // end if (res.length > 0) + } // end if (epos.onreceive) + } // end function fireFiscalReceiveEvent(epos, xhr) + + + /* + Function: fireFiscalErrorEvent method + Description: generate the onerror event + Parameters: + epos object ePOSPrint object + xhr object XMLHttpRequest object + Return: none + */ + + function fireFiscalErrorEvent(epos, xhr) + { + // fire onerror event + // alert("Error event called"); + if (epos.onerror) + { + epos.onerror({ + status: xhr.status, + responseText: xhr.responseText + }); + } + } + + + // + // Function: CanvasPrint constructor + // Description: initialize a Canvas-Print object + // Parameters: none + // Return: none + // + + function CanvasPrint() { + } + // inherit from ePOSPrint object + CanvasPrint.prototype = new ePOSPrint(); + CanvasPrint.prototype.constructor = CanvasPrint; + + // + // Function: print method + // Description: print the HTML 5 Canvas + // Parameters: + // address string the address of ePOS-Print service + // canvas object HTML 5 Canvas object + // cut boolean when true, cut paper [option] + // Return: none + // Throws: object the browser does not equip Canvas + // + CanvasPrint.prototype.print = function (address, canvas, cut) { + // check parameter + if (!canvas.getContext) { + throw new Error('Canvas is not supported'); + } + // get HTML 5 Canvas + var context = canvas.getContext('2d'); + var width = canvas.getAttribute('width'); + var height = canvas.getAttribute('height'); + // create ePOS-Print XML message + var builder = new ePOSBuilder(); + builder.addImage(context, 0, 0, width, height); + if (cut) { + builder.addCut(builder.CUT_FEED); + } + // send request message + this.send(address, builder.toString()); + }; + + + /* + Function: epson object + Description: append constructors to window object + */ + window.epson = { + ePOSBuilder: ePOSBuilder, + ePOSPrint: ePOSPrint, + fiscalPrint: fiscalPrint, + CanvasPrint: CanvasPrint + }; + +})(window); diff --git a/fiscal_epos_print/static/lib/pikaday/pikaday.min.css b/fiscal_epos_print/static/lib/pikaday/pikaday.min.css new file mode 100644 index 000000000000..92f41e33c90b --- /dev/null +++ b/fiscal_epos_print/static/lib/pikaday/pikaday.min.css @@ -0,0 +1,5 @@ +@charset "UTF-8";/*! + * Pikaday + * Copyright © 2014 David Bushell | BSD & MIT license | https://dbushell.com/ + */.pika-single{z-index:9999;display:block;position:relative;color:#333;background:#fff;border:1px solid #ccc;border-bottom-color:#bbb;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.pika-single:after,.pika-single:before{content:" ";display:table}.pika-single:after{clear:both}.pika-single.is-hidden{display:none}.pika-single.is-bound{position:absolute;box-shadow:0 5px 15px -5px rgba(0,0,0,.5)}.pika-lendar{float:left;width:240px;margin:8px}.pika-title{position:relative;text-align:center}.pika-label{display:inline-block;position:relative;z-index:9999;overflow:hidden;margin:0;padding:5px 3px;font-size:14px;line-height:20px;font-weight:700;background-color:#fff}.pika-title select{cursor:pointer;position:absolute;z-index:9998;margin:0;left:0;top:5px;opacity:0}.pika-next,.pika-prev{display:block;cursor:pointer;position:relative;outline:0;border:0;padding:0;width:20px;height:30px;text-indent:20px;white-space:nowrap;overflow:hidden;background-color:transparent;background-position:center center;background-repeat:no-repeat;background-size:75% 75%;opacity:.5}.pika-next:hover,.pika-prev:hover{opacity:1}.is-rtl .pika-next,.pika-prev{float:left;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg==)}.is-rtl .pika-prev,.pika-next{float:right;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII=)}.pika-next.is-disabled,.pika-prev.is-disabled{cursor:default;opacity:.2}.pika-select{display:inline-block}.pika-table{width:100%;border-collapse:collapse;border-spacing:0;border:0}.pika-table td,.pika-table th{width:14.285714285714286%;padding:0}.pika-table th{color:#999;font-size:12px;line-height:25px;font-weight:700;text-align:center}.pika-button{cursor:pointer;display:block;box-sizing:border-box;-moz-box-sizing:border-box;outline:0;border:0;margin:0;width:100%;padding:5px;color:#666;font-size:12px;line-height:15px;text-align:right;background:#f5f5f5}.pika-week{font-size:11px;color:#999}.is-today .pika-button{color:#3af;font-weight:700}.has-event .pika-button,.is-selected .pika-button{color:#fff;font-weight:700;background:#3af;box-shadow:inset 0 1px 3px #178fe5;border-radius:3px}.has-event .pika-button{background:#005da9;box-shadow:inset 0 1px 3px #0076c9}.is-disabled .pika-button,.is-inrange .pika-button{background:#d5e9f7}.is-startrange .pika-button{color:#fff;background:#6cb31d;box-shadow:none;border-radius:3px}.is-endrange .pika-button{color:#fff;background:#3af;box-shadow:none;border-radius:3px}.is-disabled .pika-button{pointer-events:none;cursor:default;color:#999;opacity:.3}.is-outside-current-month .pika-button{color:#999;opacity:.3}.is-selection-disabled{pointer-events:none;cursor:default}.pika-button:hover,.pika-row.pick-whole-week:hover .pika-button{color:#fff;background:#ff8000;box-shadow:none;border-radius:3px}.pika-table abbr{border-bottom:none;cursor:help} +/*# sourceMappingURL=pikaday.min.css.map */ \ No newline at end of file diff --git a/fiscal_epos_print/static/lib/pikaday/pikaday.min.js b/fiscal_epos_print/static/lib/pikaday/pikaday.min.js new file mode 100644 index 000000000000..078c1b5d6238 --- /dev/null +++ b/fiscal_epos_print/static/lib/pikaday/pikaday.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";var n;if("object"==typeof exports){try{n=require("moment")}catch(e){}module.exports=t(n)}else"function"==typeof define&&define.amd?define(function(e){try{n=e("moment")}catch(e){}return t(n)}):e.Pikaday=t(e.moment)}(this,function(n){"use strict";var s="function"==typeof n,o=!!window.addEventListener,c=window.document,h=window.setTimeout,r=function(e,t,n,a){o?e.addEventListener(t,n,!!a):e.attachEvent("on"+t,n)},t=function(e,t,n,a){o?e.removeEventListener(t,n,!!a):e.detachEvent("on"+t,n)},l=function(e,t){return-1!==(" "+e.className+" ").indexOf(" "+t+" ")},f=function(e,t){l(e,t)||(e.className=""===e.className?t:e.className+" "+t)},g=function(e,t){var n;e.className=(n=(" "+e.className+" ").replace(" "+t+" "," ")).trim?n.trim():n.replace(/^\s+|\s+$/g,"")},y=function(e){return/Array/.test(Object.prototype.toString.call(e))},F=function(e){return/Date/.test(Object.prototype.toString.call(e))&&!isNaN(e.getTime())},L=function(e,t){return[31,(n=e,n%4==0&&n%100!=0||n%400==0?29:28),31,30,31,30,31,31,30,31,30,31][t];var n},P=function(e){F(e)&&e.setHours(0,0,0,0)},B=function(e,t){return e.getTime()===t.getTime()},d=function(e,t,n){var a,i;for(a in t)(i=void 0!==e[a])&&"object"==typeof t[a]&&null!==t[a]&&void 0===t[a].nodeName?F(t[a])?n&&(e[a]=new Date(t[a].getTime())):y(t[a])?n&&(e[a]=t[a].slice(0)):e[a]=d({},t[a],n):!n&&i||(e[a]=t[a]);return e},i=function(e,t,n){var a;c.createEvent?((a=c.createEvent("HTMLEvents")).initEvent(t,!0,!1),a=d(a,n),e.dispatchEvent(a)):c.createEventObject&&(a=c.createEventObject(),a=d(a,n),e.fireEvent("on"+t,a))},a=function(e){return e.month<0&&(e.year-=Math.ceil(Math.abs(e.month)/12),e.month+=12),11';t.push("is-outside-current-month"),e.enableSelectionDaysInNextAndPreviousMonths||t.push("is-selection-disabled")}return e.isDisabled&&t.push("is-disabled"),e.isToday&&t.push("is-today"),e.isSelected&&(t.push("is-selected"),n="true"),e.hasEvent&&t.push("has-event"),e.isInRange&&t.push("is-inrange"),e.isStartRange&&t.push("is-startrange"),e.isEndRange&&t.push("is-endrange"),'"},p=function(e,t,n,a,i,s){var o,r,l,h,d,u=e._o,c=n===u.minYear,f=n===u.maxYear,g='
',m=!0,p=!0;for(l=[],o=0;o<12;o++)l.push('");for(h='
'+u.i18n.months[a]+'
",y(u.yearRange)?(o=u.yearRange[0],r=u.yearRange[1]+1):(o=n-u.yearRange,r=1+n+u.yearRange),l=[];o=u.minYear&&l.push('");return d='
'+n+u.yearSuffix+'
",u.showMonthAfterYear?g+=d+h:g+=h+d,c&&(0===a||u.minMonth>=a)&&(m=!1),f&&(11===a||u.maxMonth<=a)&&(p=!1),0===t&&(g+='"),t===e._o.numberOfMonths-1&&(g+='"),g+"
"},V=function(e,t,n){return''+function(e){var t,n=[];for(e.showWeekNumber&&n.push(""),t=0;t<7;t++)n.push('");return""+(e.isRTL?n.reverse():n).join("")+""}(e)+(""+t.join("")+"")+"
'+m(e,t,!0)+"
"},e=function(e){var a=this,i=a.config(e);a._onMouseDown=function(e){if(a._v){var t=(e=e||window.event).target||e.srcElement;if(t)if(l(t,"is-disabled")||(!l(t,"pika-button")||l(t,"is-empty")||l(t.parentNode,"is-disabled")?l(t,"pika-prev")?a.prevMonth():l(t,"pika-next")&&a.nextMonth():(a.setDate(new Date(t.getAttribute("data-pika-year"),t.getAttribute("data-pika-month"),t.getAttribute("data-pika-day"))),i.bound&&h(function(){a.hide(),i.blurFieldOnSelect&&i.field&&i.field.blur()},100))),l(t,"pika-select"))a._c=!0;else{if(!e.preventDefault)return e.returnValue=!1;e.preventDefault()}}},a._onChange=function(e){var t=(e=e||window.event).target||e.srcElement;t&&(l(t,"pika-select-month")?a.gotoMonth(t.value):l(t,"pika-select-year")&&a.gotoYear(t.value))},a._onKeyChange=function(e){if(e=e||window.event,a.isVisible())switch(e.keyCode){case 13:case 27:i.field&&i.field.blur();break;case 37:e.preventDefault(),a.adjustDate("subtract",1);break;case 38:a.adjustDate("subtract",7);break;case 39:a.adjustDate("add",1);break;case 40:a.adjustDate("add",7)}},a._onInputChange=function(e){var t;e.firedBy!==a&&(t=i.parse?i.parse(i.field.value,i.format):s?(t=n(i.field.value,i.format,i.formatStrict))&&t.isValid()?t.toDate():null:new Date(Date.parse(i.field.value)),F(t)&&a.setDate(t),a._v||a.show())},a._onInputFocus=function(){a.show()},a._onInputClick=function(){a.show()},a._onInputBlur=function(){var e=c.activeElement;do{if(l(e,"pika-single"))return}while(e=e.parentNode);a._c||(a._b=h(function(){a.hide()},50)),a._c=!1},a._onClick=function(e){var t=(e=e||window.event).target||e.srcElement,n=t;if(t){!o&&l(t,"pika-select")&&(t.onchange||(t.setAttribute("onchange","return;"),r(t,"change",a._onChange)));do{if(l(n,"pika-single")||n===i.trigger)return}while(n=n.parentNode);a._v&&t!==i.trigger&&n!==i.trigger&&a.hide()}},a.el=c.createElement("div"),a.el.className="pika-single"+(i.isRTL?" is-rtl":"")+(i.theme?" "+i.theme:""),r(a.el,"mousedown",a._onMouseDown,!0),r(a.el,"touchend",a._onMouseDown,!0),r(a.el,"change",a._onChange),i.keyboardInput&&r(c,"keydown",a._onKeyChange),i.field&&(i.container?i.container.appendChild(a.el):i.bound?c.body.appendChild(a.el):i.field.parentNode.insertBefore(a.el,i.field.nextSibling),r(i.field,"change",a._onInputChange),i.defaultDate||(s&&i.field.value?i.defaultDate=n(i.field.value,i.format).toDate():i.defaultDate=new Date(Date.parse(i.field.value)),i.setDefaultDate=!0));var t=i.defaultDate;F(t)?i.setDefaultDate?a.setDate(t,!0):a.gotoDate(t):a.gotoDate(new Date),i.bound?(this.hide(),a.el.className+=" is-bound",r(i.trigger,"click",a._onInputClick),r(i.trigger,"focus",a._onInputFocus),r(i.trigger,"blur",a._onInputBlur)):this.show()};return e.prototype={config:function(e){this._o||(this._o=d({},u,!0));var t=d(this._o,e,!0);t.isRTL=!!t.isRTL,t.field=t.field&&t.field.nodeName?t.field:null,t.theme="string"==typeof t.theme&&t.theme?t.theme:null,t.bound=!!(void 0!==t.bound?t.field&&t.bound:t.field),t.trigger=t.trigger&&t.trigger.nodeName?t.trigger:t.field,t.disableWeekends=!!t.disableWeekends,t.disableDayFn="function"==typeof t.disableDayFn?t.disableDayFn:null;var n=parseInt(t.numberOfMonths,10)||1;if(t.numberOfMonths=4=i&&(this._y=i,!isNaN(o)&&this._m>o&&(this._m=o)),t="pika-title-"+Math.random().toString(36).replace(/[^a-z]+/g,"").substr(0,2);for(var l=0;l'+p(this,l,this.calendars[l].year,this.calendars[l].month,this.calendars[0].year,t)+this.render(this.calendars[l].year,this.calendars[l].month,t)+"";this.el.innerHTML=r,n.bound&&"hidden"!==n.field.type&&h(function(){n.trigger.focus()},1),"function"==typeof this._o.onDraw&&this._o.onDraw(this),n.bound&&n.field.setAttribute("aria-label",n.ariaLabel)}},adjustPosition:function(){var e,t,n,a,i,s,o,r,l,h,d,u;if(!this._o.container){if(this.el.style.position="absolute",t=e=this._o.trigger,n=this.el.offsetWidth,a=this.el.offsetHeight,i=window.innerWidth||c.documentElement.clientWidth,s=window.innerHeight||c.documentElement.clientHeight,o=window.pageYOffset||c.body.scrollTop||c.documentElement.scrollTop,u=d=!0,"function"==typeof e.getBoundingClientRect)r=(h=e.getBoundingClientRect()).left+window.pageXOffset,l=h.bottom+window.pageYOffset;else for(r=t.offsetLeft,l=t.offsetTop+t.offsetHeight;t=t.offsetParent;)r+=t.offsetLeft,l+=t.offsetTop;(this._o.reposition&&ia.maxDate||a.disableWeekends&&(void 0,0===(w=R.getDay())||6===w)||a.disableDayFn&&a.disableDayFn(R),isEmpty:I,isStartRange:O,isEndRange:j,isInRange:W,showDaysInNextAndPreviousMonths:a.showDaysInNextAndPreviousMonths,enableSelectionDaysInNextAndPreviousMonths:a.enableSelectionDaysInNextAndPreviousMonths};a.pickWholeWeek&&N&&(M=!0),l.push(H(A)),7==++x&&(a.showWeekNumber&&l.unshift((D=k-o,v=t,b=e,_=void 0,_=new Date(b,0,1),''+Math.ceil(((new Date(b,v,D)-_)/864e5+_.getDay()+1)/7)+"")),r.push((p=l,y=a.isRTL,''+(y?p.reverse():p).join("")+"")),x=0,M=!(l=[]))}return V(a,r,n)},isVisible:function(){return this._v},show:function(){this.isVisible()||(this._v=!0,this.draw(),g(this.el,"is-hidden"),this._o.bound&&(r(c,"click",this._onClick),this.adjustPosition()),"function"==typeof this._o.onOpen&&this._o.onOpen.call(this))},hide:function(){var e=this._v;!1!==e&&(this._o.bound&&t(c,"click",this._onClick),this.el.style.position="static",this.el.style.left="auto",this.el.style.top="auto",f(this.el,"is-hidden"),this._v=!1,void 0!==e&&"function"==typeof this._o.onClose&&this._o.onClose.call(this))},destroy:function(){var e=this._o;this.hide(),t(this.el,"mousedown",this._onMouseDown,!0),t(this.el,"touchend",this._onMouseDown,!0),t(this.el,"change",this._onChange),e.keyboardInput&&t(c,"keydown",this._onKeyChange),e.field&&(t(e.field,"change",this._onInputChange),e.bound&&(t(e.trigger,"click",this._onInputClick),t(e.trigger,"focus",this._onInputFocus),t(e.trigger,"blur",this._onInputBlur))),this.el.parentNode&&this.el.parentNode.removeChild(this.el)}},e}); \ No newline at end of file diff --git a/fiscal_epos_print/static/src/css/pos.css b/fiscal_epos_print/static/src/css/pos.css new file mode 100644 index 000000000000..7ade28c334e5 --- /dev/null +++ b/fiscal_epos_print/static/src/css/pos.css @@ -0,0 +1,5 @@ +/* Disabilitato finchè non gestiamo i resi */ + +.orderlist-screen .order-line .order-list-return { + display:none; +} diff --git a/fiscal_epos_print/static/src/img/ade-logo.png b/fiscal_epos_print/static/src/img/ade-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2a01e0fa97518955eaba3ac142c1f70a4b4f95ba GIT binary patch literal 1323 zcmV+`1=RY9P)Al>qT9o?9-vL^tlJA=}BQ4BNyRyss`K~91S0b_xCfjpouurL-+ zZ0I$BG{kfeGZsHpw{F{k{@QLH;dy>xYtkWU+n3L|*|pnN&b)N8V))$}V?`{Uc%s(; zzW(JD$4{IwN=piN*^c*s<+wSP?Wphe9mcUeCXFqn)pEqLUCXkZJv-iiWk%)F#Vo5@ zf6F-lK%a5X0$?@&^X`O^gMGtLk10hIP+AM$|9phK2aln(q&K6Y%21C#GJlQ!vOd2O zAUyi%TL*BDZGn_~X_}a{L7rIk5&oBF+@b8AkivbB7<;UPVi*jpew$<9JO;$1yD1CF!_WmV;%xVmU6B?P58OSeA$7 zI3#UXw^~ktWjTFq*QNG!Jz8rM7!#N^(tf>gCn7_szz>Ff@!oQ@zIybBwa5SwK|~NO zXsr z;i=tv$%`{|C}hxkrYOjZHU+6vr`t5#d9cOeIWs=D9q)zq#V;beMToR1dre-sP9{NT zB7hRDlxP%M6e^T;n7XgDSy7g`@;d`$Iz7*?5|P>0BvUMUvwB%3Q47>pTyX*##lVD_NG-}R+Kfx;)$X&7h2BQt~VrU zxorPtA8V?&5Q=2I8kjYep;$RLJKZw2^SQBd(#ny65pVzfg;#QHZA=8RWATJ@6`;K& zW<}Xh;4JV~w7Tw{z^B9vUUEDHczBmQh@p6=lW1381LMVLr@TzP~u-`3HSJz_wkIjzfJz z6H8WY#Pw1=&BVV>PCfKsN>p9u)dh?ZYVw`aCY9y~fnF(s3xc7#U7}Zj4Fa*m hw1cMwUhDYe_!p8yX-584&fow5002ovPDHLkV1f+'; + return tag; + }, + + /* + Prints a sale refund item line. + */ + printRecRefund: function(args) { + var message = 'REFUND ' + + addPadding(args.refund_report) + ' ' + + addPadding(args.refund_doc_num) + ' ' + + args.refund_date + ' ' + + args.refund_cash_fiscal_serial; + + var tag = '\n' + + ''; + return tag; + }, + + /* + Adds a discount to the last line. + */ + printRecItemAdjustment: function(args) { + var tag = ''; + return tag; + }, + + /* + Prints a payment. + */ + printRecTotal: function(args) { + var tag = ''; + return tag; + }, + + // Remember that the header goes after + // but before otherwise it will not be printed + // as additional header messageType=1 + printFiscalReceiptHeader: function(receipt){ + var msg = ''; + if (receipt.header != '' && receipt.header.length > 0) { + var hdr = receipt.header.split(/\r\n|\r|\n/); + _.each(hdr, function(m, i) { + msg += '' + }); + } + return msg; + }, + + // Remember that the footer goes within + // as PROMO code messageType=3 + printFiscalReceiptFooter: function(receipt){ + var msg = ''; + if (receipt.footer != '' && receipt.footer.length > 0) { + var hdr = receipt.footer.split(/\r\n|\r|\n/); + _.each(hdr, function(m, i) { + msg += '' + }); + } + return msg; + }, + + /* + Prints a receipt + */ + printFiscalReceipt: function(receipt) { + var self = this; + var xml = ''; + // header must be printed before beginning a fiscal receipt + xml += this.printFiscalReceiptHeader(receipt); + xml += ''; + // footer can go only as promo code so within a fiscal receipt body + xml += this.printFiscalReceiptFooter(receipt); + _.each(receipt.orderlines, function(l, i, list) { + if (l.price >= 0) { + if(l.quantity>=0) { + xml += self.printRecItem({ + description: l.product_name, + quantity: l.quantity, + unitPrice: l.price, + department: l.tax_department.code + }); + if (l.discount) { + xml += self.printRecItemAdjustment({ + adjustmentType: 0, + description: _t('Discount') + ' ' + l.discount + '%', + amount: round_pr(l.quantity * l.price - l.price_display, self.sender.pos.currency.rounding), + }); + } + } + else + { + xml += self.printRecRefund({ + refund_date: receipt.refund_date, + refund_report: receipt.refund_report, + refund_doc_num: receipt.refund_doc_num, + refund_cash_fiscal_serial: receipt.refund_cash_fiscal_serial, + description: _t('Refund >>> ') + l.product_name, + quantity: l.quantity * -1.0, + unitPrice: l.price, + department: l.tax_department.code + }); + } + } + else { + xml += self.printRecItemAdjustment({ + adjustmentType: 3, + description: l.product_name, + department: l.tax_department.code, + amount: -l.price, + }); + } + }); + _.each(receipt.paymentlines, function(l, i, list) { + xml += self.printRecTotal({ + payment: l.amount, + paymentType: l.type, + paymentIndex: l.type_index, + description: l.journal, + }); + }); + xml += ''; + this.fiscalPrinter.send(this.url, xml); + console.log(xml); + }, + + printFiscalReport: function() { + var xml = ''; + xml += ''; + xml += ''; + xml += ''; + this.fiscalPrinter.send(this.url, xml); + }, + + getStatusOfFilesForADE: function() { + var xml = ''; + xml += ''; + xml += ''; + this.fiscalPrinter.send(this.url, xml); + }, + + }); + + var _orderline_super = models.Orderline.prototype; + models.Orderline = models.Orderline.extend({ + export_for_printing: function(){ + var res = _orderline_super.export_for_printing.call(this, arguments); + res['tax_department'] = this.get_tax_details_r(); + return res; + }, + get_tax_details_r: function(){ + var details = this.get_all_prices(); + for (var i in details.taxDetails){ + return { + code: this.pos.taxes_by_id[i].fpdeptax, + taxname: this.pos.taxes_by_id[i].name, + } + } + alert(_t("No taxes found")); + }, + compute_all: function(taxes, price_unit, quantity, currency_rounding, no_map_tax) { + var res = _orderline_super.compute_all.call(this, taxes, price_unit, quantity, currency_rounding, no_map_tax); + var self = this; + + var total_excluded = round_pr(price_unit * quantity, currency_rounding); + var total_included = total_excluded; + var base = total_excluded; + var list_taxes = res.taxes; + // amount_type 'group' not handled (used only for purchases, in Italy) + _(taxes).each(function(tax) { + if (!no_map_tax){ + tax = self._map_tax_fiscal_position(tax); + } + if (!tax){ + return; + } + var tax_amount = self._compute_all(tax, base, quantity); + tax_amount = round_pr(tax_amount, currency_rounding); + if (!tax_amount){ + // Intervene here: also add taxes with 0 amount + if (tax.price_include) { + total_excluded -= tax_amount; + base -= tax_amount; + } + else { + total_included += tax_amount; + } + if (tax.include_base_amount) { + base += tax_amount; + } + var data = { + id: tax.id, + amount: tax_amount, + name: tax.name, + }; + list_taxes.push(data); + } + }); + res.taxes = list_taxes; + + return res; + }, + }); + + /* + Overwrite Paymentline.export_for_printing() in order + to make it export the payment type that must be passed + to the fiscal printer. + */ + var original = models.Paymentline.prototype.export_for_printing; + models.Paymentline = models.Paymentline.extend({ + export_for_printing: function() { + var res = original.apply(this, arguments); + res.type = this.cashregister.journal.fiscalprinter_payment_type; + res.type_index = this.cashregister.journal.fiscalprinter_payment_index; + return res; + } + }); + + // when print order i validate call print receipt + screens.PaymentScreenWidget.include({ + getPrinterOptions: function (){ + var protocol = ((this.pos.config.use_https) ? 'https://' : 'http://'); + var printer_url = protocol + this.pos.config.printer_ip + '/cgi-bin/fpmate.cgi'; + return {url: printer_url}; + }, + sendToFP90Printer: function(receipt, printer_options) { + var fp90 = new eposDriver(printer_options, this); + fp90.printFiscalReceipt(receipt); + }, + finalize_validation: function() { + // we need to get currentOrder before calling the _super() + // otherwise we will likely get a empty order when we want to skip + // the receipt preview + var currentOrder = this.pos.get_order(); + this._super.apply(this, arguments); + if (this.pos.config.printer_ip && !currentOrder.is_to_invoice()) { + var printer_options = this.getPrinterOptions(); + var receipt = currentOrder.export_for_printing(); + this.sendToFP90Printer(receipt, printer_options); + currentOrder._printed = true; + } + } + + }); + + var _super_posmodel = models.PosModel.prototype; + models.PosModel = models.PosModel.extend({ + initialize: function (session, attributes) { + var tax_model = _.find(this.models, function(model){ return model.model === 'account.tax'; }); + tax_model.fields.push('fpdeptax'); + return _super_posmodel.initialize.call(this, session, attributes); + }, + }); + + OrderListScreenWidget.include({ + _prepare_order_from_order_data: function (order_data, action) { + var order = this._super(order_data, action); + order.refund_report = order_data.refund_report; + order.refund_date = order_data.refund_date ? order_data.refund_date.substr(8, 2) + // day + order_data.refund_date.substr(5, 2) + // month + order_data.refund_date.substr(0, 4) // year + : null; + order.refund_doc_num = order_data.refund_doc_num; + order.refund_cash_fiscal_serial = order_data.refund_cash_fiscal_serial; + + return order; + }, + // copiato da screens.PaymentScreenWidget + getPrinterOptions: function (){ + var protocol = ((this.pos.config.use_https) ? 'https://' : 'http://'); + var printer_url = protocol + this.pos.config.printer_ip + '/cgi-bin/fpmate.cgi'; + return [{url: printer_url}]; + }, + // copiato da screens.PaymentScreenWidget + sendToFP90Printer: function(receipt, printer_options) { + for (var i = 0; i < printer_options.length; i++){ + var printer_option = printer_options[i]; + var fp90 = new eposDriver(printer_option, this); + fp90.printFiscalReceipt(receipt); + } + }, + action_print: function (order_data, order) { + if (this.pos.config.printer_ip) { + var receipt = order.export_for_printing(); + var printer_options = this.getPrinterOptions(); + this.sendToFP90Printer(receipt, printer_options); + } + return this._super(order_data, order); + }, + }); + + var FiscalPrinterADEFilesButtonWidget = PosBaseWidget.extend({ + template: 'FiscalPrinterADEFilesButtonWidget', + + button_click: function () { + this.chrome.loading_show(); + this.chrome.loading_message(_t('Connecting to the fiscal printer')); + var protocol = ((this.pos.config.use_https) ? 'https://' : 'http://'); + var printer_url = protocol + this.pos.config.printer_ip + '/cgi-bin/fpmate.cgi'; + var printer_options = {url: printer_url}; + var fp90 = new eposDriver(printer_options, this); + fp90.getStatusOfFilesForADE(); + }, + + renderElement: function () { + var self = this; + this._super(); + this.$el.click(function () { + self.button_click(); + }); + }, + + }); + + var widgets = chrome.Chrome.prototype.widgets; + widgets.push({ + 'name': 'ADE files status', + 'widget': FiscalPrinterADEFilesButtonWidget, + 'append': '.pos-rightheader', + 'args': { + 'label': _t('ADE files status'), + }, + }); + + return { + eposDriver: eposDriver, + FiscalPrinterADEFilesButtonWidget: FiscalPrinterADEFilesButtonWidget, + RefundInfoButtonActionWidget: set_refund_info_button + }; + +}); diff --git a/fiscal_epos_print/static/src/js/models.js b/fiscal_epos_print/static/src/js/models.js new file mode 100644 index 000000000000..cde2df08ea8e --- /dev/null +++ b/fiscal_epos_print/static/src/js/models.js @@ -0,0 +1,8 @@ +odoo.define('fiscal_epos_print.fiscalcode_field', function (require) { + "use strict"; + + var pos_models = require('point_of_sale.models'); + pos_models.load_fields("account.journal", + ["fiscalprinter_payment_type", "fiscalprinter_payment_index"]); + +}); diff --git a/fiscal_epos_print/static/src/xml/pos.xml b/fiscal_epos_print/static/src/xml/pos.xml new file mode 100644 index 000000000000..c3492ec57baf --- /dev/null +++ b/fiscal_epos_print/static/src/xml/pos.xml @@ -0,0 +1,74 @@ + + + + +
+ ADE status +
+
+ + + +
+ Receipt sent to the printer +
+
+
+ + + display:none + + + + +
+ Refund Data +
+
+ + + + + +
diff --git a/fiscal_epos_print/views/account_statement_view.xml b/fiscal_epos_print/views/account_statement_view.xml new file mode 100644 index 000000000000..6cd577040091 --- /dev/null +++ b/fiscal_epos_print/views/account_statement_view.xml @@ -0,0 +1,31 @@ + + + + + + POS Journal - Fiscal Printer field + account.journal + + + + + + + + + + + account.tax.printer.form.view + account.tax + + + + + + + + + + diff --git a/fiscal_epos_print/views/assets.xml b/fiscal_epos_print/views/assets.xml new file mode 100644 index 000000000000..d7c458a6bdc3 --- /dev/null +++ b/fiscal_epos_print/views/assets.xml @@ -0,0 +1,15 @@ + + + +