diff --git a/addons/point_of_sale/controllers/main.py b/addons/point_of_sale/controllers/main.py index 2461fe90b79..76dd705cbfc 100644 --- a/addons/point_of_sale/controllers/main.py +++ b/addons/point_of_sale/controllers/main.py @@ -8,182 +8,73 @@ import random from openerp import http from openerp.http import request -from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template +from openerp.addons.web.controllers.main import manifest_list, module_boot _logger = logging.getLogger(__name__) -class PointOfSaleController(http.Controller): - def __init__(self): - self.scale = 'closed' - self.scale_weight = 0.0 +html_template = """ + + + OpenERP Point of Sale - @http.route('/pos/app', type='http', auth='admin') - def app(self): - js = "\n ".join('' % i for i in manifest_list('js',db=request.db)) - css = "\n ".join('' % i for i in manifest_list('css',db=request.db)) + + - cookie = request.httprequest.cookies.get("instance0|session_id") - session_id = cookie.replace("%22","") - template = html_template.replace(' + - r = template % { + + + + + + + + %(css)s + %(js)s + + + + + + +""" + +class PosController(http.Controller): + + @http.route('/pos/web', type='http', auth='none') + def a(self, debug=False, **k): + js_list = manifest_list('js',db=request.db, debug=debug) + css_list = manifest_list('css',db=request.db, debug=debug) + + print css_list + print js_list + + js = "\n".join('' % i for i in js_list) + css = "\n".join('' % i for i in css_list) + r = html_template % { 'js': js, 'css': css, - 'modules': simplejson.dumps(module_boot(request)), - 'init': 'var wc = new s.web.WebClient();wc.appendTo($(document.body));' + 'modules': simplejson.dumps(module_boot(request.db)), + 'init': """ + window.navigator.standalone = true; + var wc = new s.web.WebClient(); + wc.appendTo($(document.body)); + wc.show_application = function(){ + wc.action_manager.do_action("pos.ui"); + }; + wc.show_login = function(){ + window.location.href = '/'; + } + """ } return r - @http.route('/pos/manifest',type='http', auth='admin') - def manifest(self): - """ This generates a HTML5 cache manifest files that preloads the categories and products thumbnails - and other ressources necessary for the point of sale to work offline """ - - ml = ["CACHE MANIFEST"] - - # loading all the images in the static/src/img/* directories - def load_css_img(srcdir,dstdir): - for f in os.listdir(srcdir): - path = os.path.join(srcdir,f) - dstpath = os.path.join(dstdir,f) - if os.path.isdir(path) : - load_css_img(path,dstpath) - elif f.endswith(('.png','.PNG','.jpg','.JPG','.jpeg','.JPEG','.gif','.GIF')): - ml.append(dstpath) - - imgdir = openerp.modules.get_module_resource('point_of_sale','static/src/img'); - load_css_img(imgdir,'/point_of_sale/static/src/img') - - products = request.registry.get('product.product') - for p in products.search_read(request.cr, request.uid, [('pos_categ_id','!=',False)], ['name']): - product_id = p['id'] - url = "/web/binary/image?session_id=%s&model=product.product&field=image&id=%s" % (request.session_id, product_id) - ml.append(url) - - categories = request.registry.get('pos.category') - for c in categories.search_read(request.cr, request.uid, [], ['name']): - category_id = c['id'] - url = "/web/binary/image?session_id=%s&model=pos.category&field=image&id=%s" % (request.session_id, category_id) - ml.append(url) - - ml += ["NETWORK:","*"] - m = "\n".join(ml) - - return m - - @http.route('/pos/test_connection', type='json', auth='admin') - def test_connection(self): - _logger.info('Received Connection Test from the Point of Sale'); - - @http.route('/pos/scan_item_success', type='json', auth='admin') - def scan_item_success(self, ean): - """ - A product has been scanned with success - """ - print 'scan_item_success: ' + str(ean) - - @http.route('/pos/scan_item_error_unrecognized', type='json', auth='admin') - def scan_item_error_unrecognized(self, ean): - """ - A product has been scanned without success - """ - print 'scan_item_error_unrecognized: ' + str(ean) - - @http.route('/pos/help_needed', type='json', auth='admin') - def help_needed(self): - """ - The user wants an help (ex: light is on) - """ - print "help_needed" - - @http.route('/pos/help_canceled', type='json', auth='admin') - def help_canceled(self): - """ - The user stops the help request - """ - print "help_canceled" - - @http.route('/pos/weighting_start', type='json', auth='admin') - def weighting_start(self): - if self.scale == 'closed': - print "Opening (Fake) Connection to Scale..." - self.scale = 'open' - self.scale_weight = 0.0 - time.sleep(0.1) - print "... Scale Open." - else: - print "WARNING: Scale already Connected !!!" - - @http.route('/pos/weighting_read_kg', type='json', auth='admin') - def weighting_read_kg(self): - if self.scale == 'open': - print "Reading Scale..." - time.sleep(0.025) - self.scale_weight += 0.01 - print "... Done." - return self.scale_weight - else: - print "WARNING: Reading closed scale !!!" - return 0.0 - - @http.route('/pos/weighting_end', type='json', auth='admin') - def weighting_end(self): - if self.scale == 'open': - print "Closing Connection to Scale ..." - self.scale = 'closed' - self.scale_weight = 0.0 - time.sleep(0.1) - print "... Scale Closed." - else: - print "WARNING: Scale already Closed !!!" - - @http.route('/pos/payment_request', type='json', auth='admin') - def payment_request(self, price): - """ - The PoS will activate the method payment - """ - print "payment_request: price:"+str(price) - return 'ok' - - @http.route('/pos/payment_status', type='json', auth='admin') - def payment_status(self): - print "payment_status" - return { 'status':'waiting' } - - @http.route('/pos/payment_cancel', type='json', auth='admin') - def payment_cancel(self): - print "payment_cancel" - - @http.route('/pos/transaction_start', type='json', auth='admin') - def transaction_start(self): - print 'transaction_start' - - @http.route('/pos/transaction_end', type='json', auth='admin') - def transaction_end(self): - print 'transaction_end' - - @http.route('/pos/cashier_mode_activated', type='json', auth='admin') - def cashier_mode_activated(self): - print 'cashier_mode_activated' - - @http.route('/pos/cashier_mode_deactivated', type='json', auth='admin') - def cashier_mode_deactivated(self): - print 'cashier_mode_deactivated' - - @http.route('/pos/open_cashbox', type='json', auth='admin') - def open_cashbox(self): - print 'open_cashbox' - - @http.route('/pos/print_receipt', type='json', auth='admin') - def print_receipt(self, receipt): - print 'print_receipt' + str(receipt) - - @http.route('/pos/log', type='json', auth='admin') - def log(self, arguments): - _logger.info(' '.join(str(v) for v in arguments)) - - @http.route('/pos/print_pdf_invoice', type='json', auth='admin') - def print_pdf_invoice(self, pdfinvoice): - print 'print_pdf_invoice' + str(pdfinvoice) - - diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index 8e1fcb8c28e..8935e6d2dc5 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -30,6 +30,12 @@ -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } +.pos input::-webkit-outer-spin-button, +.pos input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + .pos button{ box-shadow: none; outline: none; diff --git a/addons/point_of_sale/static/src/img/touch-icon-ipad-retina.png b/addons/point_of_sale/static/src/img/touch-icon-ipad-retina.png new file mode 100644 index 00000000000..4f1e1db5c98 Binary files /dev/null and b/addons/point_of_sale/static/src/img/touch-icon-ipad-retina.png differ diff --git a/addons/point_of_sale/static/src/img/touch-icon-ipad.png b/addons/point_of_sale/static/src/img/touch-icon-ipad.png new file mode 100644 index 00000000000..8b8c111406f Binary files /dev/null and b/addons/point_of_sale/static/src/img/touch-icon-ipad.png differ diff --git a/addons/point_of_sale/static/src/img/touch-icon-iphone-retina.png b/addons/point_of_sale/static/src/img/touch-icon-iphone-retina.png new file mode 100644 index 00000000000..593c1506061 Binary files /dev/null and b/addons/point_of_sale/static/src/img/touch-icon-iphone-retina.png differ diff --git a/addons/point_of_sale/static/src/img/touch-icon-iphone.png b/addons/point_of_sale/static/src/img/touch-icon-iphone.png new file mode 100644 index 00000000000..4122e61f9c0 Binary files /dev/null and b/addons/point_of_sale/static/src/img/touch-icon-iphone.png differ diff --git a/addons/point_of_sale/static/src/img/touch-icon.svg b/addons/point_of_sale/static/src/img/touch-icon.svg new file mode 100644 index 00000000000..8ce5f30e13e --- /dev/null +++ b/addons/point_of_sale/static/src/img/touch-icon.svg @@ -0,0 +1,199 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 3de24b22fbb..68acd4b874e 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -378,7 +378,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal _flush_order: function(order_id, options){ var self = this; options = options || {}; - timeout = typeof options.timeout === 'number' ? options.timeout : 5000; + timeout = typeof options.timeout === 'number' ? options.timeout : 7500; var order = this.db.get_order(order_id); order.to_invoice = options.to_invoice || false; diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 4c5f2245e0d..88a83fc52e1 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -812,6 +812,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this._super(); var self = this; + this.pos_widget.set_numpad_visible(false); + var print_button = this.add_action_button({ label: _t('Print'), icon: '/point_of_sale/static/src/img/icons/png48/printer.png', @@ -872,6 +874,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.currentOrder = this.pos.get('selectedOrder'); $('.pos-receipt-container', this.$el).html(QWeb.render('PosTicket',{widget:this})); }, + close: function(){ + this._super(); + this.pos_widget.set_numpad_visible(true); + } }); module.PaymentScreenWidget = module.ScreenWidget.extend({ @@ -1006,6 +1012,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.pos_widget.screen_selector.set_current_screen(this.next_screen); } } + // hide onscreen (iOS) keyboard + setTimeout(function(){ + document.activeElement.blur(); + $("input").blur(); + },250); }, bindPaymentLineEvents: function() { this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines'); @@ -1068,8 +1079,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }, isPaymentPaid: function(){ var currentOrder = this.pos.get('selectedOrder'); - return (currentOrder.getTotalTaxIncluded < 0.000001 - && currentOrder.getPaidTotal() + 0.000001 < currentOrder.getTotalTaxIncluded()); + return (currentOrder.getTotalTaxIncluded() >= 0.000001 + && currentOrder.getPaidTotal() + 0.000001 >= currentOrder.getTotalTaxIncluded()); }, updatePaymentSummary: function() { @@ -1088,8 +1099,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa } if(this.pos_widget.action_bar){ - this.pos_widget.action_bar.set_button_disabled('validation', this.isPaymentPaid()); - this.pos_widget.action_bar.set_button_disabled('invoice', this.isPaymentPaid()); + this.pos_widget.action_bar.set_button_disabled('validation', !this.isPaymentPaid()); + this.pos_widget.action_bar.set_button_disabled('invoice', !this.isPaymentPaid()); } }, set_numpad_state: function(numpadState) { diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js index 6a222cd1ca4..2939eb39390 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -213,13 +213,13 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa var scroller = this.$('.order-scroller')[0]; var scrollbottom = true; var scrollTop = 0; - /*if(scroller){ + if(scroller){ var overflow_bottom = scroller.scrollHeight - scroller.clientHeight; scrollTop = scroller.scrollTop; if( !goto_bottom && scrollTop < 0.9 * overflow_bottom){ scrollbottom = false; } - }*/ + } this._super(); // freeing subwidgets @@ -244,14 +244,13 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.update_summary(); scroller = this.$('.order-scroller')[0]; + if(scroller){ - //scroller.scrollTop = 1000000; - /* if(scrollbottom){ scroller.scrollTop = scroller.scrollHeight - scroller.clientHeight; }else{ scroller.scrollTop = scrollTop; - }*/ + } } }, update_summary: function(){ @@ -313,8 +312,12 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa focus: function(){ var val = this.$('input')[0].value; this.$('input')[0].focus(); - this.$('input')[0].value = val; - this.$('input')[0].select(); + if(Number(val) === 0){ + this.$('input')[0].value = ''; + }else{ + this.$('input')[0].value = val; + this.$('input')[0].select(); + } }, }); @@ -863,16 +866,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa self.screen_selector.set_default_screen(); - self.pos.barcode_reader.connect(); - if(!$('#oe-fullscreenwidget-viewport').length){ - $('head').append(''); - $('head').append(''); - } - - $('.oe_leftbar').addClass('oe_hidden'); - instance.webclient.set_content_full_screen(true); if (!self.pos.get('pos_session')) { @@ -1104,7 +1099,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) { var action = result; action.context = _.extend(action.context || {}, {'cancel_action': {type: 'ir.actions.client', tag: 'reload'}}); - //self.destroy(); this.do_action(action); }, this)); }, self)); @@ -1124,9 +1118,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa destroy: function() { this.pos.destroy(); instance.webclient.set_content_full_screen(false); - $('.oe_leftbar').removeClass('oe_hidden'); - $('#oe-pos-viewport').remove(); - $('#oe-pos-apple-mobile').remove(); this._super(); } }); diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 42e5b7ef44d..4eaf9e53604 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -580,7 +580,7 @@ - +