eprint.text(receipt['company']['email'] + '\n')
if check(receipt['company']['website']):
eprint.text(receipt['company']['website'] + '\n')
-
+ if check(receipt['header']):
+ eprint.text(receipt['header']+'\n')
if check(receipt['cashier']):
eprint.text('-'*32+'\n')
eprint.text('Served by '+receipt['cashier']+'\n')
eprint.text(printline(_('Taxes'),money(receipt['total_tax']),width=40, ratio=0.6))
# Footer
+ if check(receipt['footer']):
+ eprint.text('\n'+receipt['footer']+'\n\n')
eprint.text(receipt['name']+'\n')
eprint.text( str(receipt['date']['date']).zfill(2)
+'/'+ str(receipt['date']['month']+1).zfill(2)
def print_receipt(self, receipt):
print 'print_receipt' + str(receipt)
+ @http.route('/hw_proxy/is_scanner_connected', type='json', auth='admin')
+ def print_receipt(self, receipt):
+ print 'is_scanner_connected?'
+ return False
+
+ @http.route('/hw_proxy/scanner', type='json', auth='admin')
+ def print_receipt(self, receipt):
+ print 'scanner'
+ time.sleep(10)
+ return ''
+
@http.route('/hw_proxy/log', type='json', auth='admin')
def log(self, arguments):
_logger.info(' '.join(str(v) for v in arguments))
--- /dev/null
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import controllers
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
--- /dev/null
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+{
+ 'name': 'Barcode Scanner Hardware Driver',
+ 'version': '1.0',
+ 'category': 'Hardware Drivers',
+ 'sequence': 6,
+ 'summary': 'Hardware Driver for Barcode Scanners',
+ 'description': """
+Barcode Scanner Hardware Driver
+================================
+
+This module allows the web client to access a remotely installed barcode
+scanner, and is used by the posbox to provide barcode scanner support to the
+point of sale module.
+
+""",
+ 'author': 'OpenERP SA',
+ 'depends': [],
+ 'test': [
+ ],
+ 'installable': True,
+ 'auto_install': False,
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
--- /dev/null
+import main
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
--- /dev/null
+# -*- coding: utf-8 -*-
+import logging
+import os
+from os import listdir
+from os.path import join
+import openerp
+import openerp.addons.hw_proxy.controllers.main as hw_proxy
+from openerp.tools.translate import _
+
+from openerp import http
+from openerp.http import request
+
+_logger = logging.getLogger(__name__)
+
+from evdev import InputDevice, ecodes, categorize, list_devices
+from select import select
+
+class ScannerDriver(hw_proxy.Proxy):
+ def __init__(self):
+ self.input_dir = '/dev/input/by-id/'
+ self.keymap = {
+ 2: ("1","!"),
+ 3: ("2","@"),
+ 4: ("3","#"),
+ 5: ("4","$"),
+ 6: ("5","%"),
+ 7: ("6","^"),
+ 8: ("7","&"),
+ 9: ("8","*"),
+ 10:("9","("),
+ 11:("0",")"),
+ 12:("-","_"),
+ 13:("=","+"),
+ # 14 BACKSPACE
+ # 15 TAB
+ 16:("q","Q"),
+ 17:("w","W"),
+ 18:("e","E"),
+ 19:("r","R"),
+ 20:("t","T"),
+ 21:("y","Y"),
+ 22:("u","U"),
+ 23:("i","I"),
+ 24:("o","O"),
+ 25:("p","P"),
+ 26:("[","{"),
+ 27:("]","}"),
+ # 28 ENTER
+ # 29 LEFT_CTRL
+ 30:("a","A"),
+ 31:("s","S"),
+ 32:("d","D"),
+ 33:("f","F"),
+ 34:("g","G"),
+ 35:("h","H"),
+ 36:("j","J"),
+ 37:("k","K"),
+ 38:("l","L"),
+ 39:(";",":"),
+ 40:("'","\""),
+ 41:("`","~"),
+ # 42 LEFT SHIFT
+ 43:("\\","|"),
+ 44:("z","Z"),
+ 45:("x","X"),
+ 46:("c","C"),
+ 47:("v","V"),
+ 48:("b","B"),
+ 49:("n","N"),
+ 50:("m","M"),
+ 51:(",","<"),
+ 52:(".",">"),
+ 53:("/","?"),
+ # 54 RIGHT SHIFT
+ 57:(" "," "),
+ }
+
+ def get_device(self):
+ devices = [ device for device in listdir(self.input_dir)]
+ keyboards = [ device for device in devices if 'kbd' in device ]
+ scanners = [ device for device in devices if ('barcode' in device.lower()) or ('scanner' in device.lower()) ]
+ if len(scanners) > 0:
+ return InputDevice(join(self.input_dir,scanners[0]))
+ elif len(keyboards) > 0:
+ return InputDevice(join(self.input_dir,keyboards[0]))
+ else:
+ return None
+
+ @http.route('/hw_proxy/is_scanner_connected', type='http', auth='admin')
+ def is_scanner_connected(self):
+ return self.get_device() != None
+
+ @http.route('/hw_proxy/scanner', type='http', auth='admin')
+ def scanner(self):
+ device = self.get_device()
+ barcode = []
+ shift = False
+ if not device:
+ return ''
+ else:
+ device.grab()
+ while True:
+ r,w,x = select([device],[],[],10)
+ if len(r) == 0: # timeout
+ device.ungrab()
+ return ''
+ for event in device.read():
+ if event.type == ecodes.EV_KEY:
+ if event.value == 1: # keydown events
+ print categorize(event)
+ if event.code in self.keymap:
+ if shift:
+ barcode.append(self.keymap[event.code][1])
+ else:
+ barcode.append(self.keymap[event.code][0])
+ elif event.code == 42 or event.code == 54: # SHIFT
+ shift = True
+ elif event.code == 28: # ENTER
+ device.ungrab()
+ return ''.join(barcode);
+ elif event.value == 0: #keyup events
+ if event.code == 42 or event.code == 54: # LEFT SHIFT
+ shift = False
+
+
help="Accounting journal used to post sales entries."),
'iface_self_checkout' : fields.boolean('Self Checkout Mode',
help="Check this if this point of sale should open by default in a self checkout mode. If unchecked, OpenERP uses the normal cashier mode by default."),
- 'iface_cashdrawer' : fields.boolean('Cashdrawer Interface'),
- 'iface_payment_terminal' : fields.boolean('Payment Terminal Interface'),
- 'iface_electronic_scale' : fields.boolean('Electronic Scale Interface'),
- 'iface_vkeyboard' : fields.boolean('Virtual KeyBoard Interface'),
- 'iface_print_via_proxy' : fields.boolean('Print via Proxy'),
+ 'iface_cashdrawer' : fields.boolean('Cashdrawer',help="Automatically open the cashdrawer"),
+ 'iface_payment_terminal' : fields.boolean('Payment Terminal', help="Enables Payment Terminal integration"),
+ 'iface_electronic_scale' : fields.boolean('Electronic Scale', help="Enables Electronic Scale integration"),
+ 'iface_vkeyboard' : fields.boolean('Virtual KeyBoard', help="Enables an integrated Virtual Keyboard"),
+ 'iface_print_via_proxy' : fields.boolean('Print via Proxy', help="Bypass browser printing and prints via the hardware proxy"),
'iface_invoicing': fields.boolean('Invoicing',help='Enables invoice generation from the Point of Sale'),
'iface_big_scrollbars': fields.boolean('Large Scrollbars',help='For imprecise industrial touchscreens'),
+ 'receipt_header': fields.text('Receipt Header',help="A short text that will be inserted as a header in the printed receipt"),
+ 'receipt_footer': fields.text('Receipt Footer',help="A short text that will be inserted as a footer in the printed receipt"),
'state' : fields.selection(POS_CONFIG_STATE, 'Status', required=True, readonly=True),
'sequence_id' : fields.many2one('ir.sequence', 'Order IDs Sequence', readonly=True,
<field name="cash_control" />
</tree>
</field>
- <group string="Material Interfaces" >
+ <group string="Settings" >
<group>
<field name="iface_self_checkout" />
<field name="iface_cashdrawer" />
<group>
<field name="iface_electronic_scale" />
<field name="iface_vkeyboard" />
- <field name="iface_print_via_proxy" />
<field name="iface_big_scrollbars" />
</group>
</group>
+ <group string="Receipt" >
+ <field name="iface_print_via_proxy" />
+ <field name="receipt_header" placeholder="A custom receipt header message"/>
+ <field name="receipt_footer" placeholder="A custom receipt header footage"/>
+ </group>
</sheet>
</form>
'iface_self_checkout', 'iface_led', 'iface_cashdrawer',
'iface_payment_terminal', 'iface_electronic_scale', 'iface_barscan', 'iface_vkeyboard',
'iface_print_via_proxy','iface_cashdrawer','iface_invoicing','iface_big_scrollbars',
+ 'receipt_header','receipt_footer',
'state','sequence_id','session_ids'],
[['id','=', self.pos_session.config_id[0]]]
);
client: client ? client.name : null ,
invoice_id: null, //TODO
cashier: cashier ? cashier.name : null,
+ header: this.pos.config.receipt_header || '',
+ footer: this.pos.config.receipt_footer || '',
precision: {
price: 2,
money: 2,