[WIP] point_of_sale: more perf improvement, this time on the receipt and payment screen + lots of usability improvements and cleanups

bzr revid: fva@openerp.com-20131204172122-mzl4wg4uw51uzdfv
This commit is contained in:
Frédéric van der Essen 2013-12-04 18:21:22 +01:00
parent 7d062a0b45
commit d4e7b6eb96
8 changed files with 378 additions and 379 deletions

View File

@ -89,13 +89,11 @@ Main Features
'installable': True,
'application': True,
'js': [
'static/lib/mousewheel/jquery.mousewheel-3.0.6.js',
'static/lib/fastclick.js',
'static/src/js/db.js',
'static/src/js/models.js',
'static/src/js/widget_base.js',
'static/src/js/widget_keyboard.js',
'static/src/js/widget_scrollbar.js',
'static/src/js/widgets.js',
'static/src/js/devices.js',
'static/src/js/screens.js',

View File

@ -1,84 +0,0 @@
/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
* Licensed under the MIT License (LICENSE.txt).
*
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
* Thanks to: Seamus Leahy for adding deltaX and deltaY
*
* Version: 3.0.6
*
* Requires: 1.2.2+
*/
(function($) {
var types = ['DOMMouseScroll', 'mousewheel'];
if ($.event.fixHooks) {
for ( var i=types.length; i; ) {
$.event.fixHooks[ types[--i] ] = $.event.mouseHooks;
}
}
$.event.special.mousewheel = {
setup: function() {
if ( this.addEventListener ) {
for ( var i=types.length; i; ) {
this.addEventListener( types[--i], handler, false );
}
} else {
this.onmousewheel = handler;
}
},
teardown: function() {
if ( this.removeEventListener ) {
for ( var i=types.length; i; ) {
this.removeEventListener( types[--i], handler, false );
}
} else {
this.onmousewheel = null;
}
}
};
$.fn.extend({
mousewheel: function(fn) {
return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
},
unmousewheel: function(fn) {
return this.unbind("mousewheel", fn);
}
});
function handler(event) {
var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
event = $.event.fix(orgEvent);
event.type = "mousewheel";
// Old school scrollwheel delta
if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; }
if ( orgEvent.detail ) { delta = -orgEvent.detail/3; }
// New school multidimensional scroll (touchpads) deltas
deltaY = delta;
// Gecko
if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
deltaY = 0;
deltaX = -1*delta;
}
// Webkit
if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }
if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }
// Add event and delta to the front of the arguments
args.unshift(event, delta, deltaX, deltaY);
return ($.event.dispatch || $.event.handle).apply(this, args);
}
})(jQuery);

View File

@ -705,37 +705,60 @@
/* b) The payment screen */
.pos .pos-step-container {
display: inline-block;
font-size: 1.5em;
}
.pos .greyed-out{
color: #AAA;
}
.pos .pos-step-container input{
font-size: 1em;
outline: none;
border: none;
padding: 0px 8px;
padding-top: 8px;
margin-left: 16px;
background: white;
color: #4c4c4c;
box-shadow: 0px 2px rgba(143, 143, 143, 0.3) inset;
-webkit-animation: all 250ms linear;
}
.pos .pos-step-container input:focus{
color: rgb(130, 124, 255);
box-shadow: 0px 2px rgba(130, 124, 255, 0.3) inset;
-webkit-animation: all 250ms linear;
}
.pos .pos-payment-container {
display: inline-block;
font-size: 16px;
text-align: left;
min-width: 320px;
margin-top: 40px;
width: 360px;
}
.pos .payment-due-total {
text-align: center;
font-weight: bold;
font-size: 48px;
margin: 27px;
text-shadow: 0px 2px rgb(202, 202, 202);
}
.pos .paymentline{
position: relative;
padding: 8px;
border-box: 3px;
box-sizing: border-box;
border-radius: 3px;
}
.pos .paymentline-input{
font-size: 20px;
font-family: Lato;
display: block;
width: 100%;
box-sizing: border-box;
outline: none;
border: none;
padding: 6px 8px;
background: white;
color: #484848;
text-align: right;
box-shadow: 0px 2px rgba(143, 143, 143, 0.3) inset;
}
.pos .paymentline-input:focus{
color: rgb(130, 124, 255);
box-shadow: 0px 2px rgba(219, 219, 219, 0.3) inset;
-webkit-animation: all 250ms linear;
}
.paymentline-delete {
width: 32px;
height: 32px;
padding: 5px;
text-align: center;
box-sizing: border-box;
position: absolute;
bottom: 10px;
left: 8px;
cursor: pointer;
}
.pos .pos-payment-container .left-block{
display: inline-block;
width:49%;
@ -743,14 +766,15 @@
padding:0;
text-align:left;
}
.pos .pos-payment-container .header{
margin-top: 0px;
margin-bottom:20px;
font-weight: bold;
}
.pos .pos-payment-container .infoline{
margin-top:5px;
margin-bottom:5px;
padding: 0px 8px;
opacity: 0.5;
}
.pos .pos-payment-container .infoline.bigger{
opacity: 1;
font-size: 20px;
}
.pos .pos-payment-container .right-block{
display: inline-block;
@ -759,17 +783,8 @@
padding:0;
text-align:right;
}
.pos .pos-payment-container table {
width: 100%;
margin-bottom: 20px;
}
.pos .pos-payment-container td {
vertical-align: middle;
}
.pos .pos-payment-container .paymentline-type {
font-size: 1em;
font-weight: bold;
margin-right:10px;
.pos .paymentline.selected{
background: rgb(220,220,220);
}
/* c) The receipt screen */
@ -784,6 +799,7 @@
background-color: white;
margin: 20px;
padding: 15px;
font-size: 14px;
padding-bottom:30px;
display: inline-block;
font-family: "Inconsolata";

View File

@ -13,8 +13,6 @@ openerp.point_of_sale = function(instance) {
openerp_pos_keyboard(instance,module); // import pos_keyboard_widget.js
openerp_pos_scrollbar(instance,module); // import pos_scrollbar_widget.js
openerp_pos_screens(instance,module); // import pos_screens.js
openerp_pos_devices(instance,module); // import pos_devices.js

View File

@ -669,25 +669,30 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
model: module.Orderline,
});
// Every PaymentLine contains a cashregister and an amount of money.
// Every Paymentline contains a cashregister and an amount of money.
module.Paymentline = Backbone.Model.extend({
initialize: function(attributes, options) {
this.amount = 0;
this.cashregister = options.cashRegister;
this.name = this.cashregister.get('journal_id')[1];
this.selected = false;
},
//sets the amount of money on this payment line
set_amount: function(value){
this.amount = parseFloat(value) || 0;
this.trigger('change');
this.amount = round_di(parseFloat(value) || 0, 2);
this.trigger('change:amount',this);
},
// returns the amount of money on this paymentline
get_amount: function(){
return this.amount;
},
// returns the associated cashRegister
get_cashregister: function(){
return this.cashregister;
set_selected: function(selected){
if(this.selected !== selected){
this.selected = selected;
this.trigger('change:selected',this);
}
},
// returns the associated cashRegister
//exports as JSON for server communication
export_as_JSON: function(){
return {
@ -713,7 +718,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
// An order more or less represents the content of a client's shopping cart (the OrderLines)
// plus the associated payment information (the PaymentLines)
// plus the associated payment information (the Paymentlines)
// there is always an active ('selected') order in the Pos, a new one is created
// automaticaly once an order is completed and sent to the server.
module.Order = Backbone.Model.extend({
@ -727,8 +732,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
name: "Order " + this.uid,
client: null,
});
this.pos = attributes.pos;
this.selected_orderline = undefined;
this.pos = attributes.pos;
this.selected_orderline = undefined;
this.selected_paymentline = undefined;
this.screen_data = {}; // see ScreenSelector
this.receipt_type = 'receipt'; // 'receipt' || 'invoice'
return this;
@ -765,13 +771,21 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
getLastOrderline: function(){
return this.get('orderLines').at(this.get('orderLines').length -1);
},
addPaymentLine: function(cashRegister) {
addPaymentline: function(cashRegister) {
var paymentLines = this.get('paymentLines');
var newPaymentline = new module.Paymentline({},{cashRegister:cashRegister});
if(cashRegister.get('journal').type !== 'cash'){
newPaymentline.set_amount( this.getDueLeft() );
newPaymentline.set_amount( Math.max(this.getDueLeft(),0) );
}
paymentLines.add(newPaymentline);
this.selectPaymentline(newPaymentline);
},
removePaymentline: function(line){
if(this.selected_paymentline === line){
this.selectPaymentline(undefined);
}
this.get('paymentLines').remove(line);
},
getName: function() {
return this.get('name');
@ -946,6 +960,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
this.selected_orderline = undefined;
}
},
selectPaymentline: function(line){
console.log("SELECT_PAYMENTLINE",line);
if(line !== this.selected_paymentline){
if(this.selected_paymentline){
this.selected_paymentline.set_selected(false);
}
this.selected_paymentline = line;
if(this.selected_paymentline){
this.selected_paymentline.set_selected(true);
}
this.trigger('change:selected_paymentline',this.selected_paymentline);
}
},
});
module.OrderCollection = Backbone.Collection.extend({

View File

@ -157,6 +157,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
barcode_product_screen: 'products', //if defined, this screen will be loaded when a product is scanned
barcode_product_error_popup: 'error-product', //if defined, this popup will be loaded when there's an error in the popup
hotkeys_handlers: {},
// 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.
@ -634,7 +636,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
}
var cashregister = selfCheckoutRegisters[0] || self.pos.get('cashRegisters').models[0];
currentOrder.add_payment_line(cashregister);
currentOrder.addPaymentline(cashregister);
self.pos.push_order(currentOrder)
currentOrder.destroy();
self.pos.proxy.transaction_end();
@ -802,15 +804,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
init: function(parent, options) {
this._super(parent,options);
this.model = options.model;
this.user = this.pos.get('user');
this.company = this.pos.get('company');
this.shop_obj = this.pos.get('shop');
},
renderElement: function() {
this._super();
this.pos.bind('change:selectedOrder', this.change_selected_order, this);
this.change_selected_order();
},
show: function(){
this._super();
@ -828,6 +827,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
click: function() { self.finishOrder(); },
});
this.refresh();
this.print();
// THIS IS THE HACK OF THE CENTURY
@ -859,22 +859,14 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
finishOrder: function() {
this.pos.get('selectedOrder').destroy();
},
change_selected_order: function() {
if (this.currentOrderLines)
this.currentOrderLines.unbind();
this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines');
this.currentOrderLines.bind('add', this.refresh, this);
this.currentOrderLines.bind('change', this.refresh, this);
this.currentOrderLines.bind('remove', this.refresh, this);
if (this.currentPaymentLines)
this.currentPaymentLines.unbind();
this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines');
this.currentPaymentLines.bind('all', this.refresh, this);
this.refresh();
},
refresh: function() {
this.currentOrder = this.pos.get('selectedOrder');
$('.pos-receipt-container', this.$el).html(QWeb.render('PosTicket',{widget:this}));
var order = this.pos.get('selectedOrder');
$('.pos-receipt-container', this.$el).html(QWeb.render('PosTicket',{
widget:this,
order: order,
orderlines: order.get('orderLines').models,
paymentlines: order.get('paymentLines').models,
}));
},
close: function(){
this._super();
@ -886,17 +878,68 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
back_screen: 'products',
next_screen: 'receipt',
init: function(parent, options) {
var self = this;
this._super(parent,options);
this.model = options.model;
this.pos.bind('change:selectedOrder', this.change_selected_order, this);
this.bind_payment_line_events();
this.bind_orderline_events();
this.paymentlinewidgets = [];
this.focusedLine = null;
this.pos.bind('change:selectedOrder',function(){
this.bind_events();
this.renderElement();
},this);
this.bind_events();
this.line_delete_handler = function(event){
var node = this;
while(node && !node.classList.contains('paymentline')){
node = node.parentNode;
}
if(node){
self.pos.get('selectedOrder').removePaymentline(node.line)
}
event.stopPropagation();
};
this.line_change_handler = function(event){
var node = this;
while(node && !node.classList.contains('paymentline')){
node = node.parentNode;
}
if(node){
node.line.set_amount(this.value);
}
};
this.line_click_handler = function(event){
console.log('click');
var node = this;
while(node && !node.classList.contains('paymentline')){
node = node.parentNode;
}
if(node){
self.pos.get('selectedOrder').selectPaymentline(node.line);
}
};
},
show: function(){
this._super();
var self = this;
this.enable_numpad();
this.update_payment_summary();
this.focus_selected_line();
window.removeall = function(){
self.remove_empty_lines();
};
window.listlines = function(){
var lines = self.pos.get('selectedOrder').get('paymentLines').models;
for(var i = 0; i < lines.length; i++){
console.log('LINE:',lines[i]);
}
};
/*
this.hotkey_handler = function(event){
if(event.which === 13){
@ -907,13 +950,16 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
};
$('body').on('keyup',this.hotkey_handler);
*/
if( this.pos.iface_cashdrawer && this.pos.get('selectedOrder').get('paymentLines').find( function(pl){ return pl.cashregister.get('journal').type === 'cash'; })){
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.enable_numpad();
this.add_action_button({
label: _t('Back'),
@ -928,17 +974,17 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
name: 'validation',
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
click: function(){
self.validate();
self.validate_order();
},
});
if(this.pos.iface_invoicing){
if( this.pos.iface_invoicing ){
this.add_action_button({
label: 'Invoice',
name: 'invoice',
icon: '/point_of_sale/static/src/img/icons/png48/invoice.png',
click: function(){
self.validate({invoice: true});
self.validate_order({invoice: true});
},
});
}
@ -954,23 +1000,163 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
});
}
this.update_payment_summary();
this.line_refocus();
},
close: function(){
this._super();
this.disable_numpad();
$('body').off('keyup',this.hotkey_handler);
//$('body').off('keyup',this.hotkey_handler);
},
remove_empty_lines: function(){
var order = this.pos.get('selectedOrder');
var lines = order.get('paymentLines').models.slice(0);
for(var i = 0; i < lines.length; i++){
var line = lines[i];
if(line.get_amount() === 0){
order.removePaymentline(line);
}
}
},
back: function() {
_.each(this.paymentlinewidgets, function(widget){
if( widget.payment_line.get_amount() === 0 ){
widget.payment_line.destroy();
}
});
this.remove_empty_lines();
this.pos_widget.screen_selector.set_current_screen(this.back_screen);
},
validate: function(options) {
bind_events: function() {
if(this.old_order){
this.old_order.unbind(null,null,this);
}
var order = this.pos.get('selectedOrder');
order.bind('change:selected_paymentline',this.focus_selected_line,this);
this.old_order = order;
if(this.old_paymentlines){
this.old_paymentlines.unbind(null,null,this);
}
var paymentlines = order.get('paymentLines');
paymentlines.bind('add', this.add_paymentline, this);
paymentlines.bind('change:selected', this.rerender_paymentline, this);
paymentlines.bind('change:amount', function(line){
if(!line.selected && line.node){
line.node.value = line.amount.toFixed(2);
}
this.update_payment_summary();
},this);
paymentlines.bind('remove', this.remove_paymentline, this);
paymentlines.bind('all', this.update_payment_summary, this);
this.old_paymentlines = paymentlines;
if(this.old_orderlines){
this.old_orderlines.unbind(null,null,this);
}
var orderlines = order.get('orderLines');
orderlines.bind('all', this.update_payment_summary, this);
this.old_orderlines = orderlines;
},
focus_selected_line: function(){
var line = this.pos.get('selectedOrder').selected_paymentline;
if(line){
debugger;
if(!line.node){
debugger;
}
var input = line.node.querySelector('input');
if(!input){
return;
}
var value = input.value;
input.focus();
if(this.numpad_state){
this.numpad_state.reset();
}
if(Number(value) === 0){
input.value = '';
}else{
input.value = value;
input.select();
}
}
},
add_paymentline: function(line) {
var list_container = this.el.querySelector('.payment-lines');
list_container.appendChild(this.render_paymentline(line));
if(this.numpad_state){
this.numpad_state.reset();
}
},
render_paymentline: function(line){
var el_html = openerp.qweb.render('Paymentline',{widget: this, line: line});
el_html = _.str.trim(el_html);
var el_node = document.createElement('tbody');
el_node.innerHTML = el_html;
el_node = el_node.childNodes[0];
el_node.line = line;
el_node.querySelector('.paymentline-delete')
.addEventListener('click', this.line_delete_handler);
el_node.addEventListener('click', this.line_click_handler);
el_node.querySelector('input')
.addEventListener('keyup', this.line_change_handler);
line.node = el_node;
return el_node;
},
rerender_paymentline: function(line){
var old_node = line.node;
var new_node = this.render_paymentline(line);
old_node.parentNode.replaceChild(new_node,old_node);
console.log('RERENDER',line);
},
remove_paymentline: function(line){
console.log('Removing line from DOM:',line);
line.node.parentNode.removeChild(line.node);
line.node = undefined;
},
renderElement: function(){
this._super();
var paymentlines = this.pos.get('selectedOrder').get('paymentLines').models;
var list_container = this.el.querySelector('.payment-lines');
for(var i = 0; i < paymentlines.length; i++){
list_container.appendChild(this.render_paymentline(paymentlines[i]));
}
//this.update_payment_summary();
},
update_payment_summary: function() {
var currentOrder = this.pos.get('selectedOrder');
var paidTotal = currentOrder.getPaidTotal();
var dueTotal = currentOrder.getTotalTaxIncluded();
var remaining = dueTotal > paidTotal ? dueTotal - paidTotal : 0;
var change = paidTotal > dueTotal ? paidTotal - dueTotal : 0;
this.$('.payment-due-total').html(this.format_currency(dueTotal));
this.$('.payment-paid-total').html(this.format_currency(paidTotal));
this.$('.payment-remaining').html(this.format_currency(remaining));
this.$('.payment-change').html(this.format_currency(change));
if(currentOrder.selected_orderline === undefined){
remaining = 1; // What is this ?
}
if(this.pos_widget.action_bar){
this.pos_widget.action_bar.set_button_disabled('validation', !this.is_paid());
this.pos_widget.action_bar.set_button_disabled('invoice', !this.is_paid());
}
},
is_paid: function(){
var currentOrder = this.pos.get('selectedOrder');
return (currentOrder.getTotalTaxIncluded() >= 0.000001
&& currentOrder.getPaidTotal() + 0.000001 >= currentOrder.getTotalTaxIncluded());
},
validate_order: function(options) {
var self = this;
options = options || {};
@ -1012,97 +1198,13 @@ 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);
},
bind_payment_line_events: function() {
this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines');
this.currentPaymentLines.bind('add', this.add_payment_line, this);
this.currentPaymentLines.bind('remove', this.renderElement, this);
this.currentPaymentLines.bind('all', this.update_payment_summary, this);
},
bind_orderline_events: function() {
this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines');
this.currentOrderLines.bind('all', this.update_payment_summary, this);
},
change_selected_order: function() {
this.currentPaymentLines.unbind();
this.bind_payment_line_events();
this.currentOrderLines.unbind();
this.bind_orderline_events();
this.renderElement();
},
line_refocus: function(lineWidget){
if(lineWidget){
if(this.focusedLine !== lineWidget){
this.focusedLine = lineWidget;
}
}
if(this.focusedLine){
this.focusedLine.focus();
}
},
add_payment_line: function(newPaymentLine) {
var self = this;
var l = new module.PaymentlineWidget(this, {
payment_line: newPaymentLine,
});
l.on('delete_payment_line', self, function(r) {
self.deleteLine(r);
});
l.appendTo(this.$('.paymentlines'));
this.paymentlinewidgets.push(l);
if(this.numpadState){
this.numpadState.resetValue();
}
this.line_refocus(l);
},
renderElement: function() {
this._super();
this.$('.paymentlines').empty();
for(var i = 0, len = this.paymentlinewidgets.length; i < len; i++){
this.paymentlinewidgets[i].destroy();
}
this.paymentlinewidgets = [];
this.currentPaymentLines.each(_.bind( function(paymentLine) {
this.add_payment_line(paymentLine);
}, this));
this.update_payment_summary();
},
deleteLine: function(lineWidget) {
this.currentPaymentLines.remove([lineWidget.payment_line]);
lineWidget.destroy();
},
is_paid: function(){
var currentOrder = this.pos.get('selectedOrder');
return (currentOrder.getTotalTaxIncluded() >= 0.000001
&& currentOrder.getPaidTotal() + 0.000001 >= currentOrder.getTotalTaxIncluded());
},
update_payment_summary: function() {
var currentOrder = this.pos.get('selectedOrder');
var paidTotal = currentOrder.getPaidTotal();
var dueTotal = currentOrder.getTotalTaxIncluded();
var remaining = dueTotal > paidTotal ? dueTotal - paidTotal : 0;
var change = paidTotal > dueTotal ? paidTotal - dueTotal : 0;
this.$('.payment-due-total').html(this.format_currency(dueTotal));
this.$('.payment-paid-total').html(this.format_currency(paidTotal));
this.$('.payment-remaining').html(this.format_currency(remaining));
this.$('.payment-change').html(this.format_currency(change));
if(currentOrder.selected_orderline === undefined){
remaining = 1; // What is this ?
}
if(this.pos_widget.action_bar){
this.pos_widget.action_bar.set_button_disabled('validation', !this.is_paid());
this.pos_widget.action_bar.set_button_disabled('invoice', !this.is_paid());
}
},
enable_numpad: function(){
this.disable_numpad(); //ensure we don't register the callbacks twice
this.numpad_state = this.pos_widget.numpad.state;
@ -1124,7 +1226,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
this.numpad_state.set({mode: 'payment'});
},
set_value: function(val) {
this.currentPaymentLines.last().set_amount(val);
var selected_line =this.pos.get('selectedOrder').selected_paymentline;
if(selected_line){
selected_line.set_amount(val);
selected_line.node.querySelector('input').value = selected_line.amount.toFixed(2);
}
},
});
}

View File

@ -60,9 +60,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.state = new module.NumpadState();
window.numpadstate = this.state;
var self = this;
this.state.bind('change:buffer',function(){
console.log('BUFFER:',self.state.get('buffer'));
})
},
start: function() {
this.state.bind('change:mode', this.changedMode, this);
@ -128,7 +125,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
console.warn('TODO should not get there...?');
return;
}
self.pos.get('selectedOrder').addPaymentLine(self.cashRegister);
self.pos.get('selectedOrder').addPaymentline(self.cashRegister);
self.pos_widget.screen_selector.set_current_screen('payment');
});
},
@ -208,11 +205,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
this.update_summary();
},this);
},
update_numpad: function() {
this.selected_line = this.pos.get('selectedOrder').getSelectedLine();
if (this.numpadState)
this.numpadState.reset();
},
render_orderline: function(orderline){
var el_str = openerp.qweb.render('Orderline',{widget:this, line:orderline});
var el_node = document.createElement('div');
@ -236,6 +228,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
var replacement_line = this.render_orderline(order_line);
node.parentNode.replaceChild(replacement_line,node);
},
// overriding the openerp framework replace method for performance reasons
replace: function($target){
this.renderElement();
var target = $target[0];
@ -278,58 +271,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
},
});
module.PaymentlineWidget = module.PosBaseWidget.extend({
template: 'PaymentlineWidget',
init: function(parent, options) {
this._super(parent,options);
this.payment_line = options.payment_line;
this.payment_line.bind('change', this.changedAmount, this);
},
changeAmount: function(event) {
var newAmount = event.currentTarget.value;
var amount = parseFloat(newAmount);
if(!isNaN(amount)){
this.amount = amount;
this.payment_line.set_amount(amount);
}
},
checkAmount: function(e){
if (e.which !== 0 && e.charCode !== 0) {
if(isNaN(String.fromCharCode(e.charCode))){
return (String.fromCharCode(e.charCode) === "." && e.currentTarget.value.toString().split(".").length < 2)?true:false;
}
}
return true
},
changedAmount: function() {
if (this.amount !== this.payment_line.get_amount()){
this.renderElement();
}
},
renderElement: function() {
var self = this;
this.name = this.payment_line.get_cashregister().get('journal_id')[1];
this._super();
this.$('input').keypress(_.bind(this.checkAmount, this))
.keyup(function(event){
self.changeAmount(event);
});
this.$('.delete-payment-line').click(function() {
self.trigger('delete_payment_line', self);
});
},
focus: function(){
var val = this.$('input')[0].value;
this.$('input')[0].focus();
if(Number(val) === 0){
this.$('input')[0].value = '';
}else{
this.$('input')[0].value = val;
this.$('input')[0].select();
}
},
});
module.OrderButtonWidget = module.PosBaseWidget.extend({
template:'OrderButtonWidget',
init: function(parent, options) {
@ -918,12 +859,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
self.pos.delete_current_order();
});
$('body').on('keyup',function(event){
if(event.which === 13){
self.set_fullscreen();
}
});
//when a new order is created, add an order button widget
self.pos.get('orders').bind('add', function(new_order){
var new_order_button = new module.OrderButtonWidget(null, {

View File

@ -246,41 +246,32 @@
<t t-name="PaymentScreenWidget">
<div class="payment-screen screen">
<header><h2>Payment</h2></header>
<div class="pos-step-container">
<div class="pos-payment-container">
<br />
<div class="header">
<span class="left-block">
Total:
<div class="pos-payment-container">
<div class='payment-due-total'></div>
<div class='payment-lines'></div>
<div class='payment-info'>
<div class="infoline">
<span class='left-block'>
Paid:
</span>
<span class="right-block payment-due-total"></span>
<span class="right-block payment-paid-total"></span>
</div>
<table class="paymentlines">
</table>
<div class="footer">
<div class="infoline">
<span class='left-block'>
Paid:
</span>
<span class="right-block payment-paid-total"></span>
</div>
<div class="infoline">
<span class='left-block'>
Remaining:
</span>
<span class="right-block payment-remaining"></span>
</div>
<div class="infoline" >
<span class='left-block'>
Change:
</span>
<span class="right-block payment-change"></span>
</div>
<div class="infoline">
<span class='left-block'>
Remaining:
</span>
<span class="right-block payment-remaining"></span>
</div>
<div class="infoline bigger" >
<span class='left-block'>
Change:
</span>
<span class="right-block payment-change"></span>
</div>
</div>
</div>
</div>
</t> <!-- pos-payment-screen -->
</t>
<t t-name="ReceiptScreenWidget">
<div class="receipt-screen screen" >
@ -556,14 +547,26 @@
</li>
</t>
<t t-name="PaymentlineWidget">
<tr class="paymentline">
<t t-name="Paymentline">
<div t-attf-class="paymentline #{line.selected ? 'selected' : ''}">
<div class='paymentline-name'>
<t t-esc="line.name"/>
</div>
<input class='paymentline-input' type="number" step="0.01" t-att-value="line.get_amount().toFixed(2)" />
<span class='paymentline-delete'>
<img src="/point_of_sale/static/src/img/search_reset.gif" />
</span>
</div>
</t>
<t t-name="PaymentlineOld">
<tr t-attf-class="paymentline #{line.selected ? 'selected' : ''}">
<td class="paymentline-type">
<t t-esc="widget.name"/>
<t t-esc="line.name"/>
</td>
<td class="paymentline-amount pos-right-align">
<input type="number" step="0.01" t-att-value="widget.payment_line.get_amount().toFixed(2)" />
<a href='javascript:void(0)' class='delete-payment-line'><img src="/point_of_sale/static/src/img/search_reset.gif" /></a>
<input type="number" step="0.01" t-att-value="line.get_amount().toFixed(2)" />
<span class='delete-payment-line'><img src="/point_of_sale/static/src/img/search_reset.gif" /></span>
</td>
</tr>
</t>
@ -590,7 +593,7 @@
<div class="pos-sale-ticket">
<div class="pos-center-align"><t t-esc="new Date().toString(Date.CultureInfo.formatPatterns.shortDate + ' ' +
Date.CultureInfo.formatPatterns.longTime)"/> <t t-esc="widget.currentOrder.attributes.name"/></div>
Date.CultureInfo.formatPatterns.longTime)"/> <t t-esc="order.get('name')"/></div>
<br />
<t t-esc="widget.company.name"/><br />
Phone: <t t-esc="widget.company.phone || ''"/><br />
@ -603,7 +606,7 @@
<col width='25%' />
<col width='25%' />
</colgroup>
<tr t-foreach="widget.currentOrderLines.toArray()" t-as="orderline">
<tr t-foreach="orderlines" t-as="orderline">
<td>
<t t-esc="orderline.get_product().name"/>
<t t-if="orderline.get_discount() > 0">
@ -623,33 +626,33 @@
<br />
<table>
<tr><td>Subtotal:</td><td class="pos-right-align">
<t t-esc="widget.format_currency(widget.currentOrder.getSubtotal())"/>
<t t-esc="widget.format_currency(order.getSubtotal())"/>
</td></tr>
<tr><td>Tax:</td><td class="pos-right-align">
<t t-esc="widget.format_currency(widget.currentOrder.getTax())"/>
<t t-esc="widget.format_currency(order.getTax())"/>
</td></tr>
<tr><td>Discount:</td><td class="pos-right-align">
<t t-esc="widget.format_currency(widget.currentOrder.getDiscountTotal())"/>
<t t-esc="widget.format_currency(order.getDiscountTotal())"/>
</td></tr>
<tr class="emph"><td>Total:</td><td class="pos-right-align">
<t t-esc="widget.format_currency(widget.currentOrder.getTotalTaxIncluded())"/>
<t t-esc="widget.format_currency(order.getTotalTaxIncluded())"/>
</td></tr>
</table>
<br />
<table>
<tr t-foreach="widget.currentPaymentLines.toArray()" t-as="pline">
<tr t-foreach="paymentlines" t-as="line">
<td>
<t t-esc="pline.get_cashregister().get('journal_id')[1]"/>
<t t-esc="line.name"/>
</td>
<td class="pos-right-align">
<t t-esc="widget.format_currency(pline.get_amount())"/>
<t t-esc="widget.format_currency(line.get_amount())"/>
</td>
</tr>
</table>
<br />
<table>
<tr><td>Change:</td><td class="pos-right-align">
<t t-esc="widget.format_currency(widget.currentOrder.getPaidTotal() - widget.currentOrder.getTotalTaxIncluded())"/>
<t t-esc="widget.format_currency(order.getPaidTotal() - order.getTotalTaxIncluded())"/>
</td></tr>
</table>
</div>