diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index da8325cd046..89ab429c4f4 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -97,6 +97,9 @@ .point-of-sale .pos-right-align { text-align: right; } +.point-of-sale .pos-center-align { + text-align: center; +} .point-of-sale .pos-right-align input { text-align: right; border: 1px solid #cecbcb; @@ -815,6 +818,9 @@ } @media print { + .point-of-sale{ + background: white !important; + } .point-of-sale #topheader, .point-of-sale #leftpane { display: none !important; } @@ -834,9 +840,6 @@ .pos-actionbar { display: none !important; } - .pos-sale-ticket { - margin: 0; - } .debug-widget{ display: none !important; } @@ -846,9 +849,12 @@ background: transparent !important; } .point-of-sale .pos-sale-ticket{ + margin: 0; margin-left: auto !important; margin-right: auto !important; - border: solid 1px black !important; + border: none !important; + font-size: 13px !important; + width: 266px !important; } } diff --git a/addons/point_of_sale/static/src/img/open-cashbox.png b/addons/point_of_sale/static/src/img/open-cashbox.png new file mode 100644 index 00000000000..1e07b0a9282 Binary files /dev/null and b/addons/point_of_sale/static/src/img/open-cashbox.png differ diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index a5017d517b7..01ccd538d8c 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -160,29 +160,29 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa // what happens when a product is scanned : // it will add the product to the order and go to barcode_product_screen. Or show barcode_product_error_popup if // there's an error. - barcode_product_action: function(ean){ + barcode_product_action: function(code){ var self = this; - if(self.pos.scan_product(ean)){ - self.pos.proxy.scan_item_success(ean); + if(self.pos.scan_product(code)){ + self.pos.proxy.scan_item_success(code); if(self.barcode_product_screen){ self.pos_widget.screen_selector.set_current_screen(self.barcode_product_screen); } }else{ - self.pos.proxy.scan_item_error_unrecognized(ean); + self.pos.proxy.scan_item_error_unrecognized(code); if(self.barcode_product_error_popup && self.pos_widget.screen_selector.get_user_mode() !== 'cashier'){ self.pos_widget.screen_selector.show_popup(self.barcode_product_error_popup); } } }, - + // what happens when a cashier id barcode is scanned. // the default behavior is the following : // - if there's a user with a matching ean, put it as the active 'cashier', go to cashier mode, and return true // - else : do nothing and return false. You probably want to extend this to show and appropriate error popup... - barcode_cashier_action: function(ean){ + barcode_cashier_action: function(code){ var users = this.pos.get('user_list'); for(var i = 0, len = users.length; i < len; i++){ - if(users[i].ean13 === ean.ean){ + if(users[i].ean13 === code.code){ this.pos.set('cashier',users[i]); this.pos_widget.username.refresh(); this.pos.proxy.cashier_mode_activated(); @@ -190,7 +190,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa return true; } } - this.pos.proxy.scan_item_error_unrecognized(ean); + this.pos.proxy.scan_item_error_unrecognized(code); return false; }, @@ -198,28 +198,28 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa // the default behavior is the following : // - if there's a user with a matching ean, put it as the active 'client' and return true // - else : return false. - barcode_client_action: function(ean){ + barcode_client_action: function(code){ var partners = this.pos.get('partner_list'); for(var i = 0, len = partners.length; i < len; i++){ - if(partners[i].ean13 === ean.ean){ + if(partners[i].ean13 === code.code){ this.pos.get('selectedOrder').set_client(partners[i]); this.pos_widget.username.refresh(); - this.pos.proxy.scan_item_success(ean); + this.pos.proxy.scan_item_success(code); return true; } } - this.pos.proxy.scan_item_error_unrecognized(ean); + this.pos.proxy.scan_item_error_unrecognized(code); return false; //TODO start the transaction }, // what happens when a discount barcode is scanned : the default behavior // is to set the discount on the last order. - barcode_discount_action: function(ean){ - this.pos.proxy.scan_item_success(ean); + barcode_discount_action: function(code){ + this.pos.proxy.scan_item_success(code); var last_orderline = this.pos.get('selectedOrder').getLastOrderline(); if(last_orderline){ - last_orderline.set_discount(ean.value) + last_orderline.set_discount(code.value) } }, @@ -292,10 +292,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.pos_widget.username.set_user_mode(this.pos_widget.screen_selector.get_user_mode()); this.pos.barcode_reader.set_action_callback({ - 'cashier': self.barcode_cashier_action ? function(ean){ self.barcode_cashier_action(ean); } : undefined , - 'product': self.barcode_product_action ? function(ean){ self.barcode_product_action(ean); } : undefined , - 'client' : self.barcode_client_action ? function(ean){ self.barcode_client_action(ean); } : undefined , - 'discount': self.barcode_discount_action ? function(ean){ self.barcode_discount_action(ean); } : undefined, + 'cashier': self.barcode_cashier_action ? function(code){ self.barcode_cashier_action(code); } : undefined , + 'product': self.barcode_product_action ? function(code){ self.barcode_product_action(code); } : undefined , + 'client' : self.barcode_client_action ? function(code){ self.barcode_client_action(code); } : undefined , + 'discount': self.barcode_discount_action ? function(code){ self.barcode_discount_action(code); } : undefined, }); }, @@ -405,7 +405,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.pos.barcode_reader.save_callbacks(); this.pos.barcode_reader.reset_action_callbacks(); this.pos.barcode_reader.set_action_callback({ - 'cashier': function(ean){ + 'cashier': function(code){ clearInterval(this.intervalID); self.pos.proxy.cashier_mode_activated(); self.pos_widget.screen_selector.set_user_mode('cashier'); @@ -683,14 +683,14 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa show_numpad: false, show_leftpane: false, - barcode_product_action: function(ean){ + barcode_product_action: function(code){ this.pos.proxy.transaction_start(); - this._super(ean); + this._super(code); }, - barcode_client_action: function(ean){ + barcode_client_action: function(code){ this.pos.proxy.transaction_start(); - this._super(ean); + this._super(code); $('.goodbye-message').addClass('oe_hidden'); this.pos_widget.screen_selector.show_popup('choose-receipt'); }, @@ -873,8 +873,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this._super(); var self = this; - if(this.pos.iface_cashdrawer){ - this.pos.proxy.open_cashbox(); + if( this.pos.iface_cashdrawer && this.pos.get('selectedOrder').get('paymentLines').find( function(pl){ return pl.cashregister.get('journal').type === 'cash'; })){ + this.pos.proxy.open_cashbox(); } this.set_numpad_state(this.pos_widget.numpad.state); @@ -883,6 +883,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa label: _t('Back'), icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png', click: function(){ + _.each(self.paymentlinewidgets, function(widget){ + if( widget.payment_line.get_amount() === 0 ){ + widget.payment_line.destroy(); + } + }); self.pos_widget.screen_selector.set_current_screen(self.back_screen); }, }); @@ -907,6 +912,17 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }); } + if( this.pos.iface_cashdrawer ){ + this.add_action_button({ + label: _t('Cash'), + name: 'cashbox', + icon: '/point_of_sale/static/src/img/open-cashbox.png', + click: function(){ + self.pos.proxy.open_cashbox(); + }, + }); + } + this.updatePaymentSummary(); this.line_refocus(); }, diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js index cfec71be68d..866e3c7ba72 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -143,7 +143,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa var self = this; this._super(); this.$el.click(function(){ - self.order.selectLine(this.model); + self.order.selectLine(self.model); self.trigger('order_line_selected'); }); if(this.model.is_selected()){ @@ -516,7 +516,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa var cat = self.pos.db.get_category_by_id(id); self.set_category(cat); self.renderElement(); - self.search_and_categories(cat); }); }); // breadcrumb click actions @@ -525,12 +524,13 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa var category = self.pos.db.get_category_by_id(id); self.set_category(category); self.renderElement(); - self.search_and_categories(category); }); + + this.search_and_categories(); + if(this.pos.iface_vkeyboard && this.pos_widget.onscreen_keyboard){ this.pos_widget.onscreen_keyboard.connect(this.$('.searchbox input')); } - this.search_and_categories(); }, set_product_type: function(type){ // 'all' | 'weightable' @@ -542,7 +542,14 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa reset_category: function(){ this.set_category(); this.renderElement(); - this.search_and_categories(); + }, + + // empties the content of the search box + clear_search: function(){ + var products = this.pos.db.get_product_by_category(this.category.id); + this.pos.get('products').reset(products); + this.$('.searchbox input').val('').focus(); + this.$('.search-clear').fadeOut(); }, // filters the products, and sets up the search callbacks @@ -553,28 +560,37 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa var products = this.pos.db.get_product_by_category(this.category.id); self.pos.get('products').reset(products); - // filter the products according to the search string - this.$('.searchbox input').keyup(function(){ - query = $(this).val().toLowerCase(); - if(query){ - var products = self.pos.db.search_product_in_category(self.category.id, query); - self.pos.get('products').reset(products); - self.$('.search-clear').fadeIn(); - }else{ - var products = self.pos.db.get_product_by_category(self.category.id); - self.pos.get('products').reset(products); - self.$('.search-clear').fadeOut(); - } - }); - this.$('.searchbox input').click(function(){}); //Why ??? + var searchtimeout = null; + // filter the products according to the search string + this.$('.searchbox input').keyup(function(event){ + clearTimeout(searchtimeout); + + var query = $(this).val().toLowerCase(); + + searchtimeout = setTimeout(function(){ + if(query){ + if(event.which === 13){ + if( self.pos.get('products').size() === 1 ){ + self.pos.get('selectedOrder').addProduct(self.pos.get('products').at(0)); + self.clear_search(); + } + }else{ + var products = self.pos.db.search_product_in_category(self.category.id, query); + self.pos.get('products').reset(products); + self.$('.search-clear').fadeIn(); + } + }else{ + var products = self.pos.db.get_product_by_category(self.category.id); + self.pos.get('products').reset(products); + self.$('.search-clear').fadeOut(); + } + },200); + }); //reset the search when clicking on reset this.$('.search-clear').click(function(){ - var products = self.pos.db.get_product_by_category(self.category.id); - self.pos.get('products').reset(products); - self.$('.searchbox input').val('').focus(); - self.$('.search-clear').fadeOut(); + self.clear_search(); }); }, }); @@ -668,7 +684,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa var self = this; this._super(); if(this.action){ - this.$el.click(function(){ self.action(); }); + this.$el.click(function(){ + self.action(); + }); } }, show: function(){ this.$el.removeClass('oe_hidden'); }, @@ -732,12 +750,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.$('.button.custom_ean').click(function(){ var ean = self.pos.barcode_reader.sanitize_ean(self.$('input.ean').val() || '0'); self.$('input.ean').val(ean); - self.pos.barcode_reader.on_ean(ean); + self.pos.barcode_reader.scan('ean13',ean); + }); + this.$('.button.reference').click(function(){ + self.pos.barcode_reader.scan('reference',self.$('input.ean').val()); }); _.each(this.eans, function(ean, name){ self.$('.button.'+name).click(function(){ self.$('input.ean').val(ean); - self.pos.barcode_reader.on_ean(ean); + self.pos.barcode_reader.scan('ean13',ean); }); }); _.each(this.events, function(name){ @@ -1082,15 +1103,29 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }, close: function() { var self = this; - return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_client_pos_menu']], ['res_id']).pipe( - _.bind(function(res) { - 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)); - }, this)); + + function close(){ + return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_client_pos_menu']], ['res_id']).pipe( + _.bind(function(res) { + 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)); + } + + var draft_order = _.find( self.pos.get('orders').models, function(order){ + return order.get('orderLines').length !== 0 && order.get('paymentLines').length === 0; + }); + if(draft_order){ + if (confirm(_t("Pending orders will be lost.\nAre you sure you want to leave this session?"))) { + return close(); + } + }else{ + return close(); + } }, destroy: function() { this.pos.destroy(); diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 7456c29b9e5..742c823702e 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -12,8 +12,8 @@
- - + +
    @@ -494,6 +494,7 @@
  1. 1.54€ Lemon
  2. Unknown Product
  3. Invalid Ean
  4. +
  5. Reference
  6. Hardware Status

    @@ -584,7 +585,7 @@
    -