diff --git a/addons/hw_escpos/__init__.py b/addons/hw_escpos/__init__.py new file mode 100644 index 00000000000..a208bc1c551 --- /dev/null +++ b/addons/hw_escpos/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import controllers + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/hw_escpos/__openerp__.py b/addons/hw_escpos/__openerp__.py new file mode 100644 index 00000000000..a6412061600 --- /dev/null +++ b/addons/hw_escpos/__openerp__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'ESC/POS Hardware Driver', + 'version': '1.0', + 'category': 'Hardware Drivers', + 'sequence': 6, + 'summary': 'Hardware Driver for ESC/POS Printers and Cashdrawers', + 'description': """ +ESC/POS Hardware Driver +======================= + +This module allows openerp to print with ESC/POS compatible printers and +to open ESC/POS controlled cashdrawers in the point of sale and other modules +that would need such functionality. + +""", + 'author': 'OpenERP SA', + 'depends': [], + 'test': [ + ], + 'installable': True, + 'auto_install': False, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/hw_escpos/controllers/__init__.py b/addons/hw_escpos/controllers/__init__.py new file mode 100644 index 00000000000..b5f0bcc9ec6 --- /dev/null +++ b/addons/hw_escpos/controllers/__init__.py @@ -0,0 +1,3 @@ +import main +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/hw_escpos/controllers/logo_grayscale.png b/addons/hw_escpos/controllers/logo_grayscale.png new file mode 100644 index 00000000000..acc3fa43f77 Binary files /dev/null and b/addons/hw_escpos/controllers/logo_grayscale.png differ diff --git a/addons/hw_escpos/controllers/main.py b/addons/hw_escpos/controllers/main.py new file mode 100644 index 00000000000..ad343a511b5 --- /dev/null +++ b/addons/hw_escpos/controllers/main.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +import logging +import simplejson +import os +import openerp +import time +import random +import openerp.addons.hw_proxy.controllers.main as hw_proxy +import subprocess +import usb.core +import escpos +import escpos.printer + +from openerp import http +from openerp.http import request +from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template + +_logger = logging.getLogger(__name__) + +class EscposDriver(hw_proxy.Proxy): + + supported_printers = [ + { 'vendor' : 0x04b8, 'product' : 0x0e03, 'name' : 'Epson TM-T20' } + ] + + @http.route('/hw_proxy/open_cashbox', type='json', auth='admin') + def open_cashbox(self): + print 'ESC/POS: OPEN CASHBOX' + + @http.route('/hw_proxy/print_receipt', type='json', auth='admin') + def print_receipt(self, receipt): + print 'ESC/POS: PRINT RECEIPT ' + str(receipt) + + printers = self.connected_usb_devices(self.supported_printers) + + def check(string): + return string != True and bool(string) and string.strip() + + def price(amount): + return "{0:.2f}".format(amount) + + def printline(left, right='', width=40, ratio=0.5, indent=0): + lwidth = int(width * ratio) + rwidth = width - lwidth + lwidth = lwidth - indent + + left = left[:lwidth] + if len(left) != lwidth: + left = left + ' ' * (lwidth - len(left)) + + right = right[-rwidth:] + if len(right) != rwidth: + right = ' ' * (rwidth - len(right)) + right + + return ' ' * indent + left + right + '\n' + + + if len(printers) > 0: + printer = printers[0] + + eprint = escpos.printer.Usb(printer['vendor'], printer['product']) + #eprint.image(os.path.join(os.path.dirname(__file__),'logo_grayscale.png')) + + # Receipt Header + eprint.set(align='center',type='b',height=2,width=2) + eprint.text(receipt['shop']['name'] + '\n') + + eprint.set(align='center',type='b') + if check(receipt['company']['name']): + eprint.text(receipt['company']['name'] + '\n') + if check(receipt['company']['contact_address']): + eprint.text(receipt['company']['contact address'] + '\n') + if check(receipt['company']['phone']): + eprint.text('Tel:' + receipt['company']['phone'] + '\n') + if check(receipt['company']['vat']): + eprint.text('VAT:' + receipt['company']['vat'] + '\n') + if check(receipt['company']['email']): + eprint.text(receipt['company']['email'] + '\n') + if check(receipt['company']['website']): + eprint.text(receipt['company']['website'] + '\n') + + if check(receipt['cashier']): + eprint.text('-'*32+'\n') + eprint.text('Served by '+receipt['cashier']+'\n') + + # Orderlines + eprint.text('\n\n') + eprint.set(align='center') + for line in receipt['orderlines']: + pricestr = price(line['price_display']) + if line['discount'] == 0 and line['unit_name'] == 'Unit(s)' and line['quantity'] == 1: + eprint.text(printline(line['product_name'],pricestr,ratio=0.6)) + else: + eprint.text(printline(line['product_name'],ratio=0.6)) + if line['discount'] != 0: + eprint.text(printline('Discount: '+str(line['discount'])+'%', ratio=0.6, indent=2)) + if line['unit_name'] == 'Unit(s)': + eprint.text( printline( str(line['quantity']) + ' x ' + price(line['price']), pricestr, ratio=0.6, indent=2)) + else: + eprint.text( printline( str(line['quantity']) + line['unit_name'] + ' x ' + price(line['price']), pricestr, ratio=0.6, indent=2)) + + # Subtotal if the taxes are not included + taxincluded = True + if price(receipt['subtotal']) != price(receipt['total_with_tax']): + eprint.text(printline('','-------')); + eprint.text(printline('Subtotal',price(receipt['subtotal']),width=40, ratio=0.6)) + eprint.text(printline('Taxes',price(receipt['total_tax']),width=40, ratio=0.6)) + taxincluded = False + + + # Total + eprint.text(printline('','-------')); + eprint.set(align='center',height=2) + eprint.text(printline(' TOTAL',price(receipt['total_with_tax']),width=40, ratio=0.6)) + eprint.text('\n\n'); + + # Paymentlines + eprint.set(align='center') + for line in receipt['paymentlines']: + eprint.text(printline(line['journal'], price(line['amount']), ratio=0.6)) + + eprint.text('\n'); + eprint.set(align='center',height=2) + eprint.text(printline(' CHANGE',price(receipt['change']),width=40, ratio=0.6)) + eprint.set(align='center') + eprint.text('\n'); + + # Extra Payment info + if receipt['total_discount'] != 0: + eprint.text(printline('Discounts',price(receipt['total_discount']),width=40, ratio=0.6)) + if taxincluded: + eprint.text(printline('Taxes',price(receipt['total_tax']),width=40, ratio=0.6)) + + # Footer + eprint.text(receipt['name']+'\n') + eprint.text( str(receipt['date']['date']).zfill(2) + +'/'+ str(receipt['date']['month']+1).zfill(2) + +'/'+ str(receipt['date']['year']).zfill(4) + +' '+ str(receipt['date']['hour']).zfill(2) + +':'+ str(receipt['date']['minute']).zfill(2) ) + eprint.cut() + return + diff --git a/addons/hw_proxy/controllers/main.py b/addons/hw_proxy/controllers/main.py index 4df01372846..c3e01a34822 100644 --- a/addons/hw_proxy/controllers/main.py +++ b/addons/hw_proxy/controllers/main.py @@ -5,6 +5,10 @@ import os import openerp import time import random +import subprocess +import usb.core +import escpos +import escpos.printer from openerp import http from openerp.http import request @@ -12,12 +16,19 @@ from openerp.addons.web.controllers.main import manifest_list, module_boot, html _logger = logging.getLogger(__name__) -class ProxyController(http.Controller): +class Proxy(http.Controller): def __init__(self): self.scale = 'closed' self.scale_weight = 0.0 pass + def connected_usb_devices(self,devices): + connected = [] + for device in devices: + if usb.core.find(idVendor=device['vendor'], idProduct=device['product']) != None: + connected.append(device) + return connected + @http.route('/hw_proxy/test_connection', type='json', auth='admin') def test_connection(self): _logger.info('Received Connection Test from the Point of Sale'); diff --git a/addons/point_of_sale/static/src/js/devices.js b/addons/point_of_sale/static/src/js/devices.js index a1d8e19aacc..a443c824087 100644 --- a/addons/point_of_sale/static/src/js/devices.js +++ b/addons/point_of_sale/static/src/js/devices.js @@ -331,6 +331,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal * } */ print_receipt: function(receipt){ + console.log('PRINT RECEIPT:', receipt); return this.message('print_receipt',{receipt: receipt}); }, diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index f269c9be348..f8ddc7cb056 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -845,7 +845,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal date: date.getDate(), // day of the month day: date.getDay(), // day of the week hour: date.getHours(), - minute: date.getMinutes() + minute: date.getMinutes() , + isostring: date.toISOString(), }, company:{ email: company.email,