[IMP] point_of_sale: various fixes and improvements

bzr revid: fva@openerp.com-20120730154143-kz57aldzo1yalfx9
This commit is contained in:
Frédéric van der Essen 2012-07-30 17:41:43 +02:00
parent b3f6c148c5
commit ccf07028cf
7 changed files with 168 additions and 67 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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){

View File

@ -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() {

View File

@ -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){

View File

@ -237,7 +237,7 @@
<t t-if="widget.currency.position == 'after'" t-esc="widget.currency.symbol"/>
</span>
</div>
<div class="infoline">
<div class="infoline" >
<span class='left-block'>
Change:
</span>
@ -269,6 +269,9 @@
<img src="/point_of_sale/static/src/img/scan.png" />
<p> Please scan an item or your member card </p>
</div>
<div class="goodbye-message">
<p>Thank you for shopping with us.</p>
</div>
</t>