diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css
index b03633e181c..07838e0f209 100644
--- a/addons/point_of_sale/static/src/css/pos.css
+++ b/addons/point_of_sale/static/src/css/pos.css
@@ -658,8 +658,16 @@
display: inline-block;
font-size: 1.5em;
}
+.point-of-sale .greyed-out{
+ color: #AAA;
+}
+.point-of-sale .pos-step-container input{
+ font-size: 1em;
+}
+
.point-of-sale .pos-payment-container {
text-align: left;
+ min-width: 500px;
}
.point-of-sale .pos-payment-container .left-block{
display: inline-block;
@@ -821,6 +829,28 @@
font-family: "Inconsolata";
}
+/* e) The Welcome Screen */
+.point-of-sale .goodbye-message{
+ position: absolute;
+ left:50%;
+ top:30%;
+ width:500px;
+ height:400px;
+ margin-left: -250px;
+ margin-top: -200px;
+ padding:10px;
+ padding-top:20px;
+ text-align:center;
+ font-size:20px;
+ font-weight:bold;
+ background-color: #F0EEEE;
+ border: 1px solid #E0DDDD;
+ -webkit-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
+ -moz-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
+ -ms-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
+ z-index:1150;
+}
+
/* ********* The OrderWidget ********* */
.point-of-sale .order-container{
@@ -1017,6 +1047,23 @@
-webkit-transition-timing-function: ease-out;
}
+.point-of-sale .pos-actionbar .button.disabled{
+ color:#AAA;
+}
+.point-of-sale .pos-actionbar .button.disabled:hover{
+ border: 1px solid #cacaca;
+ border-radius: 4px;
+
+ background: #e2e2e2;
+ background: -webkit-linear-gradient(#f0f0f0, #e2e2e2);
+ background: -moz-linear-gradient(#f0f0f0, #e2e2e2);
+ background: -ms-linear-gradient(#f0f0f0, #e2e2e2);
+ background: linear-gradient(#f0f0f0, #e2e2e2);
+ -webkit-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
+ -moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
+ box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
+}
+
.point-of-sale .pos-actionbar .button.rightalign{
float:right;
}
diff --git a/addons/point_of_sale/static/src/js/TODO.txt b/addons/point_of_sale/static/src/js/TODO.txt
index 2742a0ffa49..74148ce4e80 100644
--- a/addons/point_of_sale/static/src/js/TODO.txt
+++ b/addons/point_of_sale/static/src/js/TODO.txt
@@ -1,35 +1,30 @@
-- Affichage Catégories doivent respecter le poids
-- Affichage Catégories par poids doivent avoir une hiérarchie plate
-- Le Onscreen keyboard ne fonctionne plus
-- Scrolling dans la sélection produit et dans
+v Affichage Catégories doivent respecter le poids
+v Affichage Catégories par poids doivent avoir une hiérarchie plate
+v Le Onscreen keyboard ne fonctionne plus
+v Scrolling dans la sélection produit et dans
la liste de courses
-- Réductions
-- Redesign liste de courses
+v Réductions
+v Redesign liste de courses
- Redesign du receipt
-- générer les données de printing
-- popups d'erreur certainement buggés
-- bugs scans produits par prix par poids
-- si pas photo photo par defaut
+x générer les données de printing
+x popups d'erreur certainement buggés
+v bugs scans produits par prix par poids
+v si pas photo photo par defaut
- WebSQL
-- Redesign header, bouton retour aux backend en mode caissière
-- bouton exit en mode caissière doit retourner au backend.
+v Redesign header, bouton retour aux backend en mode caissière
+v bouton exit en mode caissière doit retourner au backend.
- user preferences : désactiver la balance etc.
- posting orders
- login alternatif
-- bug ajout ligne payment à zero + curseur dedans + suppression + design plus grand
-- si case print via proxy cochée, alors on skip l'ecran receipt
-- bouton exit self checkout
-- demarrage en mode self-checkout si self-checkout
-- produits poid code barre non reconnus
-- activer popup client aux écrans self-checkout
-- discount pas plus grand que 100
+v bug ajout ligne payment à zero + curseur dedans + suppression + design plus grand
+v si case print via proxy cochée, alors on skip l'ecran receipt
+v bouton exit self checkout
+v demarrage en mode self-checkout si self-checkout
+v produits poid code barre non reconnus
+v activer popup client aux écrans self-checkout
+v discount pas plus grand que 100
- numpad state parfois sans state
- numpad state en mode pesée ?? le cacher ?
-- numpad dans l'écran payment pour pouvoir entrer le montant
+v numpad dans l'écran payment pour pouvoir entrer le montant
- différence de total. Methode d'arrondis
-Bellevue Kriek
-Chaufontaine pétillante 33
-Boon Framboise
-Chaufontaine pétillante 50 avec discount 50%
-- mettre toutes les lignes de payement dans l'order
diff --git a/addons/point_of_sale/static/src/js/pos_devices.js b/addons/point_of_sale/static/src/js/pos_devices.js
index 39a977fdfea..c7d96eccffc 100644
--- a/addons/point_of_sale/static/src/js/pos_devices.js
+++ b/addons/point_of_sale/static/src/js/pos_devices.js
@@ -17,7 +17,9 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
delay_payment: function(){ this.activate(); this.payment_status = 'waiting_for_payment'; },
}))();
- //window.debug_devices = debug_devices;
+ if(jQuery.deparam(jQuery.param.querystring()).debug !== undefined){
+ window.debug_devices = debug_devices;
+ }
// this object interfaces with the local proxy to communicate to the various hardware devices
// connected to the Point of Sale. As the communication only goes from the POS to the proxy,
@@ -42,21 +44,26 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
success_callback = success_callback || function(){};
error_callback = error_callback || function(){};
- if(debug_devices && debug_devices.active){
+
+ if(jQuery.deparam(jQuery.param.querystring()).debug !== undefined){
console.log('PROXY:',name,params);
- }else{
+ }
+
+ if(!(debug_devices && debug_devices.active)){
this.connection.rpc('/pos/'+name, params || {}, success_callback, error_callback);
}
},
//a product has been scanned and recognized with success
- scan_item_success: function(){
- this.message('scan_item_success');
+ // ean is a parsed ean object
+ scan_item_success: function(ean){
+ this.message('scan_item_success',ean);
},
- //a product has been scanned but not recognized
- scan_item_error_unrecognized: function(){
- this.message('scan_item_error_unrecognized');
+ // a product has been scanned but not recognized
+ // ean is a parsed ean object
+ scan_item_error_unrecognized: function(ean){
+ this.message('scan_item_error_unrecognized',ean);
},
//the client is asking for help
@@ -331,6 +338,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
value: 0,
unit: 'none',
};
+ console.log('ean',ean);
function match_prefix(prefix_set, type){
for(prefix in prefix_set){
@@ -402,7 +410,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
var parse_result = self.parse_ean(codeNumbers.join(''));
if (parse_result.type === 'error') { //most likely a checksum error, raise warning
- console.error('ERROR: barcode checksum error:',parse_result);
+ console.warn('WARNING: barcode checksum error:',parse_result);
}else if(parse_result.type in {'unit':'', 'weight':'', 'price':''}){ //ean is associated to a product
if(self.action_callback['product']){
self.action_callback['product'](parse_result);
diff --git a/addons/point_of_sale/static/src/js/pos_models.js b/addons/point_of_sale/static/src/js/pos_models.js
index fd1e3fb384f..548b6b749f9 100644
--- a/addons/point_of_sale/static/src/js/pos_models.js
+++ b/addons/point_of_sale/static/src/js/pos_models.js
@@ -608,15 +608,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
return false;
}else if(this.get_discount() > 0){ // we don't merge discounted orderlines
return false;
- }else if(this.get_product_type() === 'unit'){
- return true;
- }else if(this.get_product_type() === 'weight'){
- return true;
- }else if(this.get_product_type() === 'price'){
- return this.get_product().get('list_price') === orderline.get_product().get('list_price');
- }else{
- console.error('point_of_sale/pos_models.js/Orderline.can_be_merged_with() : unknown product type:',this.get('product_type'));
+ }else if(this.price !== orderline.price){
return false;
+ }else{
+ return true;
}
},
merge: function(orderline){
diff --git a/addons/point_of_sale/static/src/js/pos_screens.js b/addons/point_of_sale/static/src/js/pos_screens.js
index 93e25ab21dc..f79b60052c0 100644
--- a/addons/point_of_sale/static/src/js/pos_screens.js
+++ b/addons/point_of_sale/static/src/js/pos_screens.js
@@ -160,12 +160,13 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
// there's an error.
barcode_product_action: function(ean){
if(this.pos_widget.scan_product(ean)){
- this.pos.proxy.scan_item_success();
+ this.pos.proxy.scan_item_success(ean);
if(this.barcode_product_screen){
this.pos_widget.screen_selector.set_current_screen(this.barcode_product_screen);
}
}else{
- if(this.barcode_product_error_popup){
+ this.pos.proxy.scan_item_error_unrecognized(ean);
+ if(this.barcode_product_error_popup && this.pos_widget.screen_selector.get_user_mode() !== 'cashier'){
this.pos_widget.screen_selector.show_popup(this.barcode_product_error_popup);
}
}
@@ -186,6 +187,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
return true;
}
}
+ this.pos.proxy.scan_item_unrecognized(ean);
return false;
},
@@ -199,9 +201,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
if(users[i].ean13 === ean.ean){
this.pos.get('selectedOrder').set_client(users[i]);
this.pos_widget.username.refresh();
+ this.pos.proxy.scan_item_success(ean);
return true;
}
}
+ this.pos.proxy.scan_item_unrecognized(ean);
return false;
//TODO start the transaction
},
@@ -209,6 +213,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
// 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);
var last_orderline = this.pos.get('selectedOrder').getLastOrderline();
if(last_orderline){
last_orderline.set_discount(ean.value)
@@ -241,6 +246,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
// this method shows the screen and sets up all the widget related to this screen. Extend this method
// if you want to alter the behavior of the screen.
show: function(){
+ var self = this;
+
this.hidden = false;
if(this.$element){
this.$element.show();
@@ -251,14 +258,22 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
}else{
this.hide_action_bar();
}
+
+ // we add the help button by default. we do this because the buttons are cleared on each refresh so that
+ // the button stay local to each screen
+ this.pos_widget.left_action_bar.add_new_button({
+ label: 'help',
+ icon: '/point_of_sale/static/src/img/icons/png48/help.png',
+ click: function(){ self.help_button_action(); },
+ });
var self = this;
var cashier_mode = this.pos_widget.screen_selector.get_user_mode() === 'cashier';
this.pos_widget.set_numpad_visible(this.show_numpad && cashier_mode);
this.pos_widget.set_leftpane_visible(this.show_leftpane);
+ this.pos_widget.set_left_action_bar_visible(this.show_leftpane && !cashier_mode);
this.pos_widget.set_cashier_controls_visible(cashier_mode);
- /*this.pos_widget.action_bar.set_element_visible('help-button', !cashier_mode, function(){ self.help_button_action(); });*/
if(cashier_mode && this.pos.use_selfcheckout){
this.pos_widget.client_button.show();
@@ -287,9 +302,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
if(this.pos.barcode_reader){
this.pos.barcode_reader.reset_action_callbacks();
}
- if(this.pos_widget.action_bar){
- this.pos_widget.action_bar.destroy_buttons();
- }
+ this.pos_widget.action_bar.destroy_buttons();
+ this.pos_widget.left_action_bar.destroy_buttons();
},
// this methods hides the screen. It's not a good place to put your cleanup stuff as it is called on the
@@ -559,12 +573,17 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
barcode_client_action: function(ean){
this._super(ean);
- this.pos_widget.screen_selector.set_current_screen(self.next_screen);
+ this.pos_widget.screen_selector.set_current_screen(this.next_screen);
},
show: function(){
this._super();
var self = this;
+ $('.goodbye-message').css({opacity:1}).show();
+ setTimeout(function(){
+ console.log('kill');
+ $('.goodbye-message').animate({opacity:0},500,'swing',function(){$('.goodbye-message').hide();});
+ },3000);
},
});
@@ -731,18 +750,23 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
validateCurrentOrder: function() {
var self = this;
var currentOrder = this.pos.get('selectedOrder');
-
- this.validate_button.$element.attr('disabled','disabled'); //FIXME is the css actually using this attr ?
+ if(this.busy){
+ return;
+ }else{
+ this.busy = true;
+ }
+ this.validate_button.$element.addClass('disabled');
this.pos.push_order(currentOrder.exportAsJSON())
.then(function() {
- self.validate_button.$element.removeAttr('disabled');
if(self.pos.use_proxy_printer){
self.pos.proxy.print_receipt(currentOrder.export_for_printing());
self.pos.get('selectedOrder').destroy(); //finish order and go back to scan screen
}else{
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
}
+ self.validate_button.$element.removeClass('disabled');
+ self.busy = false;
});
},
bindPaymentLineEvents: function() {
diff --git a/addons/point_of_sale/static/src/js/pos_widgets.js b/addons/point_of_sale/static/src/js/pos_widgets.js
index a8948437f2c..b41ccbfcc9a 100644
--- a/addons/point_of_sale/static/src/js/pos_widgets.js
+++ b/addons/point_of_sale/static/src/js/pos_widgets.js
@@ -112,7 +112,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
template:'OrderWidget',
init: function(parent, options) {
this._super(parent,options);
- this.compact = options.compact !== undefined ? options.compact : true;
+ this.display_mode = options.display_mode || 'numpad'; // 'maximized' | 'actionbar' | 'numpad'
this.set_numpad_state(options.numpadState);
this.pos.bind('change:selectedOrder', this.change_selected_order, this);
this.bind_orderline_events();
@@ -165,9 +165,12 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
var self = this;
this._super();
- if(!this.compact){
- console.log('not compact');
+ if(this.display_mode === 'maximized'){
$('.point-of-sale .order-container').css({'bottom':'0px'});
+ }else if(this.display_mode === 'actionbar'){
+ $('.point-of-sale .order-container').css({'bottom':'105px'});
+ }else if(this.display_mode !== 'numpad'){
+ console.error('ERROR: OrderWidget renderElement(): wrong display_mode:',this.display_mode);
}
var $content = this.$('.orderlines');
@@ -212,10 +215,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
var total = order ? order.getTotal() : 0;
this.$('.summary .value.total').html(this.format_currency(total));
},
- set_compact: function(compact){
- console.log('set_compact',compact);
- if(this.compact !== compact){
- this.compact = compact;
+ set_display_mode: function(mode){
+ if(this.display_mode !== mode){
+ this.display_mode = mode;
this.renderElement();
}
},
@@ -368,7 +370,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
add_new_button: function(button_options){
var button = new module.ActionButtonWidget(this,button_options);
this.button_list.push(button);
- button.appendTo($('.pos-actionbar-button-list'));
+ button.appendTo(this.$('.pos-actionbar-button-list'));
return button;
},
show:function(){
@@ -671,14 +673,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.pos_widget = this; //So that pos_widget's childs have pos_widget set automatically
this.numpad_visible = true;
+ this.left_action_bar_visible = true;
this.leftpane_visible = true;
this.leftpane_width = '440px';
this.cashier_controls_visible = true;
- var degree = 0;
+
/*
//Epileptic mode
setInterval(function(){
- $('body').css({'-webkit-filter':'sepia('+Math.round(Math.random())+') hue-rotate('+Math.random()*360+'deg) blur('+Math.random()*5+'px)' });
+ $('body').css({'-webkit-filter':'hue-rotate('+Math.random()*360+'deg)' });
},100);
*/
@@ -718,9 +721,14 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
self.screen_selector.show_popup('error', 'Sorry, we could not find any PoS Configuration for this session');
}
- self.$('.loader').animate({opacity:0},3000,'swing',function(){$('.loader').hide();});
+ self.$('.loader').animate({opacity:0},3000,'swing',function(){self.$('.loader').hide();});
self.$('.loader img').hide();
+ if(jQuery.deparam(jQuery.param.querystring()).debug !== undefined){
+ window.pos = self.pos;
+ window.pos_widget = self.pos_widget;
+ }
+
},function(){ // error when loading models data from the backend
self.$('.loader img').hide();
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_pos_session_opening']], ['res_id'])
@@ -733,7 +741,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
}, self));
});
},
-
// This method instantiates all the screens, widgets, etc. If you want to add new screens change the
// startup screen, etc, override this method.
@@ -788,6 +795,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.action_bar = new module.ActionBarWidget(this);
this.action_bar.appendTo($(".point-of-sale #rightpane"));
+ this.left_action_bar = new module.ActionBarWidget(this);
+ this.left_action_bar.appendTo($(".point-of-sale #leftpane"));
+
this.paypad = new module.PaypadWidget(this, {});
this.paypad.replace($('#placeholder-PaypadWidget'));
@@ -895,16 +905,35 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
if(visible !== this.numpad_visible){
this.numpad_visible = visible;
if(visible){
+ this.set_left_action_bar_visible(false);
this.numpad.show();
this.paypad.show();
- this.order_widget.set_compact(true);
+ this.order_widget.set_display_mode('numpad');
}else{
this.numpad.hide();
this.paypad.hide();
- this.order_widget.set_compact(false);
+ if(this.order_widget.display_mode === 'numpad'){
+ this.order_widget.set_display_mode('maximized');
+ }
}
}
},
+ set_left_action_bar_visible: function(visible){
+ if(visible !== this.left_action_bar_visible){
+ this.left_action_bar_visible = visible;
+ if(visible){
+ this.set_numpad_visible(false);
+ this.left_action_bar.show();
+ this.order_widget.set_display_mode('actionbar');
+ }else{
+ this.left_action_bar.hide();
+ if(this.order_widget.display_mode === 'actionbar'){
+ this.order_widget.set_display_mode('maximized');
+ }
+ }
+ }
+ },
+
//shows or hide the leftpane (contains the list of orderlines, the numpad, the paypad, etc.)
set_leftpane_visible: function(visible){
if(visible !== this.leftpane_visible){
diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml
index b690f6ebe6b..30875eb0fe5 100644
--- a/addons/point_of_sale/static/src/xml/pos.xml
+++ b/addons/point_of_sale/static/src/xml/pos.xml
@@ -237,7 +237,7 @@