barcode scanning fixes
[odoo/odoo.git] / addons / point_of_sale / static / src / js / pos_screens.js
1
2 // this file contains the screens definitions. Screens are the
3 // content of the right pane of the pos, containing the main functionalities. 
4 // screens are contained in the PosWidget, in pos_widget.js
5 // all screens are present in the dom at all time, but only one is shown at the
6 // same time. 
7 //
8 // transition between screens is made possible by the use of the screen_selector,
9 // which is responsible of hiding and showing the screens, as well as maintaining
10 // the state of the screens between different orders.
11 //
12 // all screens inherit from ScreenWidget. the only addition from the base widgets
13 // are show() and hide() which shows and hides the screen but are also used to 
14 // bind and unbind actions on widgets and devices. The screen_selector guarantees
15 // that only one screen is shown at the same time and that show() is called after all
16 // hide()s
17
18 function openerp_pos_screens(module, instance){ //module is instance.point_of_sale
19     var QWeb = instance.web.qweb;
20
21     var qweb_template = function(template,pos){
22         return function(ctx){
23             if(!pos){  //this is a huge hack that needs to be removed ... TODO
24                 var HackPosModel = Backbone.Model.extend({
25                     initialize:function(){
26                         this.set({
27                             'currency': {symbol: '$', position: 'after'},
28                         });
29                     },
30                 });
31                 pos = new HackPosModel();
32             }
33             return QWeb.render(template, _.extend({}, ctx,{
34                 'currency': pos.get('currency'),
35                 'format_amount': function(amount) {
36                     if (pos.get('currency').position == 'after') {
37                         return amount + ' ' + pos.get('currency').symbol;
38                     } else {
39                         return pos.get('currency').symbol + ' ' + amount;
40                     }
41                 },
42                 }));
43         };
44     };
45
46     module.ScreenSelector = instance.web.Class.extend({
47         init: function(options){
48             this.pos = options.pos;
49
50             this.screen_set = options.screen_set || {};
51
52             this.popup_set = options.popup_set || {};
53
54             this.default_client_screen = options.default_client_screen;
55             this.default_cashier_screen = options.default_cashier_screen;
56
57             this.current_client_screen = this.screen_set[this.default_client_screen];
58             
59             this.current_cashier_screen = this.screen_set[this.default_client_screen];
60
61             this.current_popup = null;
62
63             this.current_mode = options.default_mode || 'client';
64
65             this.current_screen = this.current_mode === 'client' ? 
66                 this.current_client_screen:
67                 this.current_cashier_screen;
68             
69             var current = null;
70             for(screen_name in this.screen_set){
71                 var screen = this.screen_set[screen_name];
72                 if(screen === this.current_screen){
73                     current = screen;
74                 }else{
75                     screen.hide();
76                 }
77             }
78             
79             for(popup_name in this.popup_set){
80                 this.popup_set[popup_name].hide();
81             }
82
83             if(current){
84                 current.show();
85             }
86
87             this.selected_order = this.pos.get('selectedOrder');
88             this.selected_order.set({ 
89                 user_mode : this.current_mode,
90                 client_screen: this.default_client_screen,
91                 cashier_screen: this.default_cashier_screen,
92             });
93
94             this.pos.bind('change:selectedOrder', this.load_saved_screen, this);
95         },
96         add_screen: function(screen_name, screen){
97             screen.hide();
98             this.screen_set[screen_name] = screen;
99             return this;
100         },
101         show_popup: function(name){
102             if(this.current_popup){
103                 this.close_popup();
104             }
105             this.current_popup = this.popup_set[name];
106             this.current_popup.show();
107         },
108         close_popup: function(){
109             if(this.current_popup){
110                 this.current_popup.hide();
111                 this.current_popup = null;
112             }
113         },
114         load_saved_screen:  function(){
115             this.close_popup();
116
117             var selectedOrder = this.pos.get('selectedOrder');
118             
119             if(this.current_mode === 'client'){
120                 this.set_current_screen(selectedOrder.get('client_screen') || this.default_client_screen);
121             }else if(this.current_mode === 'cashier'){
122                 console.log('default_cashier_screen:',this.default_cashier_screen);
123                 this.set_current_screen(selectedOrder.get('cashier_screen') || this.default_cashier_screen);
124             }
125             this.selected_order = selectedOrder;
126         },
127         set_user_mode: function(user_mode){
128             if(user_mode !== this.current_mode){
129                 this.close_popup();
130                 this.current_mode = user_mode;
131                 this.load_saved_screen();
132             }
133         },
134         get_user_mode: function(){
135             return this.current_mode;
136         },
137         set_current_screen: function(screen_name){
138             var screen = this.screen_set[screen_name];
139
140             this.close_popup();
141             var selectedOrder = this.pos.get('selectedOrder');
142             if(this.current_mode === 'client'){
143                 selectedOrder.set({'client_screen': screen_name});
144             }else{
145                 selectedOrder.set({'cashier_screen': screen_name});
146             }
147
148             if(screen && screen !== this.current_screen){
149                 if(this.current_screen){
150                     this.current_screen.hide();
151                 }
152                 this.current_screen = screen;
153                 this.current_screen.show();
154             }
155         },
156     });
157
158     module.ScreenWidget = instance.web.Widget.extend({
159         init: function(parent, options){
160             this._super(parent, options);
161             options = options || {};
162             this.pos = options.pos;
163             this.pos_widget = options.pos_widget;
164         },
165         show: function(){
166             if(this.$element){
167                 this.$element.show();
168             }
169         },
170         hide: function(){
171             if(this.$element){
172                 this.$element.hide();
173             }
174             if(this.pos.barcode_reader){
175                 this.pos.barcode_reader.reset_action_callbacks();
176             }
177             if(this.pos_widget.action_bar){
178                 this.pos_widget.action_bar.destroy_buttons();
179             }
180         },
181     });
182
183     module.PopUpWidget = module.ScreenWidget.extend({
184         hide: function(){
185             if(this.$element){
186                 this.$element.hide();
187             }
188         },
189     });
190
191     module.HelpPopupWidget = module.PopUpWidget.extend({
192         template:'HelpPopupWidget',
193         show: function(){
194             this._super();
195             this.pos.proxy.help_needed();
196             var self = this;
197             
198             this.$element.find('.button').off('click').click(function(){
199                 self.pos.screen_selector.close_popup();
200                 self.pos.proxy.help_canceled();
201             });
202         },
203     });
204
205     module.ReceiptPopupWidget = module.PopUpWidget.extend({
206         template:'ReceiptPopupWidget',
207         show: function(){
208             this._super();
209             var self = this;
210             this.$element.find('.receipt').off('click').click(function(){
211                 console.log('receipt!');     //TODO
212                 self.pos.screen_selector.set_current_screen('scan');
213             });
214             this.$element.find('.invoice').off('click').click(function(){
215                 console.log('invoice!');     //TODO
216                 self.pos.screen_selector.set_current_screen('scan');
217             });
218         },
219     });
220
221     module.ErrorPopupWidget = module.PopUpWidget.extend({
222         template:'ErrorPopupWidget',
223         show: function(){
224             this._super();
225             this.pos.proxy.help_needed();
226             var self = this;
227             
228             this.$element.find('.button').off('click').click(function(){
229                 self.pos.screen_selector.close_popup();
230                 self.pos.proxy.help_canceled();
231             });
232         },
233         hide:function(){
234             this._super();
235             this.pos.proxy.help_canceled();
236         },
237     });
238
239     module.ScaleInviteScreenWidget = module.ScreenWidget.extend({
240         template:'ScaleInviteScreenWidget',
241         show: function(){
242             this._super();
243             var self = this;
244
245             this.pos_widget.set_numpad_visible(false);
246             this.pos_widget.set_leftpane_visible(true);
247             this.pos_widget.set_cashier_controls_visible(false);
248             this.pos_widget.action_bar.set_total_visible(true);
249             this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
250             this.pos_widget.action_bar.set_logout_visible(false);
251
252             self.pos.proxy.weighting_start();
253
254             this.intervalID = setInterval(function(){
255                 var weight = self.pos.proxy.weighting_read_kg();
256                 if(weight > 0.001){
257                     clearInterval(this.intervalID);
258                     self.pos.screen_selector.set_current_screen('scale_product');
259                 }
260             },500);
261
262             this.pos_widget.action_bar.add_new_button(
263                 {
264                     label: 'back',
265                     icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
266                     click: function(){  
267                         clearInterval(this.intervalID);
268                         self.pos.proxy.weighting_end();
269                         self.pos.screen_selector.set_current_screen('scan');
270                     }
271                 }
272             );
273         },
274         hide: function(){
275             this._super();
276             clearInterval(this.intervalID);
277         },
278     });
279
280     module.ScaleProductScreenWidget = module.ScreenWidget.extend({
281         template:'ScaleProductSelectionScreenWidget',
282         start: function(){
283             this.product_categories_widget = new module.ProductCategoriesWidget(null,{
284                 pos:this.pos,
285             });
286             this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget'));
287
288             this.product_list_widget = new module.ProductListWidget(null,{
289                 pos:this.pos,
290                 weight: this.pos.proxy.weighting_read_kg(),
291             });
292             this.product_list_widget.replace($('.placeholder-ProductListWidget'));
293         },
294         show: function(){
295             this._super();
296             var self = this;
297             if(this.pos.screen_selector.get_user_mode() === 'client'){
298                 this.pos_widget.set_numpad_visible(false);
299                 this.pos_widget.set_leftpane_visible(true);
300                 this.pos_widget.set_cashier_controls_visible(false);
301                 this.pos_widget.action_bar.set_total_visible(true);
302                 this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
303                 this.pos_widget.action_bar.set_logout_visible(false);
304
305                 this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state);
306                 this.pos_widget.action_bar.add_new_button(
307                     {
308                         label: 'back',
309                         icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
310                         click: function(){
311                             self.pos.screen_selector.set_current_screen('scan');
312                         }
313                     }
314                 );
315                 this.pos.barcode_reader.set_action_callbacks({
316                     'cashier': function(ean){
317                         self.proxy.cashier_mode_activated();
318                     },
319                 });
320                 this.product_list_widget.set_next_screen('scan');
321             }else{  // user_mode === 'cashier'
322                 this.pos_widget.set_numpad_visible(true);
323                 this.pos_widget.set_leftpane_visible(true);
324                 this.pos_widget.set_cashier_controls_visible(true);
325                 this.pos_widget.action_bar.set_total_visible(true);
326                 this.pos_widget.action_bar.set_help_visible(false);
327                 
328                 this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state);
329                 this.pos_widget.action_bar.add_new_button(
330                     {
331                         label: 'back',
332                         icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
333                         click: function(){
334                             self.pos.screen_selector.set_current_screen('products');
335                         }
336                     }
337                 );
338                 this.product_list_widget.set_next_screen('undefined');
339             }
340
341             this.pos.proxy.weighting_start();
342             this.last_weight = this.product_list_widget.weight;
343             this.intervalID = setInterval(function(){
344                 var weight = self.pos.proxy.weighting_read_kg();
345                 if(weight != self.last_weight){
346                     self.product_list_widget.set_weight(weight);
347                     self.last_weight = weight;
348                 }
349             },500);
350         },
351         hide: function(){
352             this._super();
353             this.pos_widget.orderView.setNumpadState(null);
354             this.pos_widget.payment_screen.setNumpadState(null);
355             clearInterval(this.intervalID);
356             this.pos.proxy.weighting_end();
357         },
358     });
359
360     module.ClientPaymentScreenWidget =  module.ScreenWidget.extend({
361         template:'ClientPaymentScreenWidget',
362         show: function(){
363             this._super();
364             var self = this;
365
366             this.pos_widget.set_numpad_visible(false);
367             this.pos_widget.set_leftpane_visible(true);
368             this.pos_widget.set_cashier_controls_visible(false);
369             this.pos_widget.action_bar.set_total_visible(true);
370             this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
371             this.pos_widget.action_bar.set_logout_visible(false);
372
373             this.pos.proxy.payment_request(0,'card','info');    //TODO TOTAL
374
375             this.intervalID = setInterval(function(){
376                 var payment = self.pos.proxy.is_payment_accepted();
377                 if(payment === 'payment_accepted'){
378                     clearInterval(this.intervalID);
379                     //TODO process the payment stuff
380                     self.pos.proxy.transaction_end();
381                     self.pos.screen_selector.set_current_screen('welcome');
382                 }else if(payment === 'payment_rejected'){
383                     clearInterval(this.intervalID);
384                     //TODO show a tryagain thingie ? 
385                 }
386             },500);
387
388             this.pos_widget.action_bar.add_new_button(
389                 {
390                     label: 'back',
391                     icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
392                     click: function(){  //TODO Go to ask for weighting screen
393                         clearInterval(this.intervalID);
394                         self.pos.proxy.payment_canceled();
395                         self.pos.screen_selector.set_current_screen('scan');
396                     }
397                 }
398             );
399
400             this.pos.barcode_reader.set_action_callbacks({
401                 'cashier': function(ean){
402                     //TODO 'switch to cashier mode'
403                     clearInterval(this.intervalID);
404                     self.proxy.cashier_mode_activated();
405                     self.pos.screen_selector.set_current_screen('products');
406                 },
407             });
408         },
409         hide: function(){
410             this._super();
411             clearInterval(this.intervalID);
412         },
413     });
414
415     module.WelcomeScreenWidget = module.ScreenWidget.extend({
416         template:'WelcomeScreenWidget',
417         show: function(){
418             this._super();
419             var self = this;
420
421             this.pos_widget.set_numpad_visible(false);
422             this.pos_widget.set_leftpane_visible(false);
423             this.pos_widget.set_cashier_controls_visible(false);
424             this.pos_widget.action_bar.set_total_visible(false);
425             this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
426             this.pos_widget.action_bar.set_logout_visible(false);
427
428             this.pos_widget.action_bar.add_new_button(
429                 {
430                     label:'scan',
431                     click: function(){
432                         self.pos.screen_selector.set_current_screen('scan');
433                     }
434                 },{
435                     label: 'weight',
436                     icon: '/point_of_sale/static/src/img/icons/png48/scale.png',
437                     click: function(){  //TODO Go to ask for weighting screen
438                         self.pos.screen_selector.set_current_screen('scale_invite');
439                     }
440                 }
441             );
442             this.pos.barcode_reader.set_action_callbacks({
443                 'product': function(ean){
444                     console.log('product!');
445                     self.pos.proxy.transaction_start(); 
446                     self.pos.barcode_reader.scan_product_callback(ean);
447                     self.pos.screen_selector.set_current_screen('products');
448                 },
449                 'cashier': function(ean){
450                     //TODO 'switch to cashier mode'
451                     self.pos.proxy.cashier_mode_activated();
452                     self.pos.screen_selector.set_current_screen('products');
453                 },
454                 'client': function(ean){
455                     self.pos.proxy.transaction_start(); 
456                     //TODO 'log the client'
457                     self.pos.screen_selector.show_popup('receipt');
458                 },
459                 'discount': function(ean){
460                     // TODO : what to do in this case ????
461                 },
462             });
463         },
464         hide: function(){
465             this._super();
466             this.pos.barcode_reader.reset_action_callbacks();
467             this.pos_widget.action_bar.destroy_buttons();
468         },
469     });
470
471     module.ScanProductScreenWidget = module.ScreenWidget.extend({
472         template:'ScanProductScreenWidget',
473         show: function(){
474             this._super();
475             var self = this;
476
477             this.pos_widget.set_numpad_visible(false);
478             this.pos_widget.set_leftpane_visible(true);
479             this.pos_widget.set_cashier_controls_visible(false);
480             this.pos_widget.action_bar.set_total_visible(true);
481             this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
482             this.pos_widget.action_bar.set_logout_visible(false);
483
484             this.pos_widget.action_bar.add_new_button(
485                 {
486                     label: 'weight',
487                     icon: '/point_of_sale/static/src/img/icons/png48/scale.png',
488                     click: function(){  //TODO Go to ask for weighting screen
489                         self.pos.screen_selector.set_current_screen('scale_invite');
490                     }
491                 },{
492                     label: 'pay',
493                     icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
494                     click: function(){
495                         self.pos.screen_selector.set_current_screen('client_payment'); //TODO what stuff ?
496                     }
497                 }
498             );
499             this.pos.barcode_reader.set_action_callbacks({
500                 'product': function(ean){
501                     var success = self.pos.barcode_reader.scan_product_callback(ean);
502                     if(success){
503                         self.proxy.scan_item_success();
504                     }else{
505                         self.proxy.scan_item_error_unrecognized();
506                     }
507                 },
508                 'cashier': function(ean){
509                     //TODO 'switch to cashier mode'
510                     self.proxy.cashier_mode_activated();
511                 },
512                 'discount': function(ean){
513                     // TODO : handle the discount
514                 },
515             });
516         },
517     });
518     
519     module.SearchProductScreenWidget = module.ScreenWidget.extend({
520         template:'SearchProductScreenWidget',
521         start: function(){
522             this.product_categories_widget = new module.ProductCategoriesWidget(null,{
523                 pos:this.pos,
524             });
525             this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget'));
526
527             this.product_list_widget = new module.ProductListWidget(null,{
528                 pos:this.pos,
529             });
530             this.product_list_widget.replace($('.placeholder-ProductListWidget'));
531         },
532         show: function(){
533             this._super();
534             var self = this;
535
536             this.pos_widget.set_numpad_visible(true);
537             this.pos_widget.set_leftpane_visible(true);
538             this.pos_widget.set_cashier_controls_visible(true);
539             this.pos_widget.action_bar.set_total_visible(true);
540             this.pos_widget.action_bar.set_help_visible(false);
541             this.pos_widget.action_bar.set_logout_visible(true, function(){ 
542                 self.pos.screen_selector.set_user_mode('client');
543             });
544
545             this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state);
546             this.pos_widget.action_bar.add_new_button(
547                 {
548                     label: 'weight',
549                     icon: '/point_of_sale/static/src/img/icons/png48/scale.png',
550                     click: function(){  
551                         self.pos.screen_selector.set_current_screen('scale_product');
552                     }
553                 }
554             );
555             this.pos.barcode_reader.set_action_callbacks({
556                 'product': function(ean){
557                     var success = self.pos.barcode_reader.scan_product_callback(ean);
558                     if(success){
559                         self.proxy.scan_item_success();
560                     }else{
561                         self.proxy.scan_item_error_unrecognized();
562                     }
563                 },
564                 'cashier': function(ean){
565                     self.proxy.cashier_mode_activated();
566                 },
567                 'discount': function(ean){
568                     // TODO : handle the discount
569                 },
570             });
571         },
572         hide: function(){
573             this._super();
574             this.pos_widget.orderView.setNumpadState(null);
575             this.pos_widget.payment_screen.setNumpadState(null);
576         },
577
578     });
579
580     module.ReceiptScreenWidget = module.ScreenWidget.extend({
581         template: 'ReceiptScreenWidget',
582         init: function(parent, options) {
583             this._super(parent,options);
584             this.model = options.model;
585             this.user = this.pos.get('user');
586             this.company = this.pos.get('company');
587             this.shop_obj = this.pos.get('shop');
588         },
589         start: function() {
590             this.pos.bind('change:selectedOrder', this.changeSelectedOrder, this);
591             this.changeSelectedOrder();
592             $('button#pos-finish-order', this.$element).click(_.bind(this.finishOrder, this));
593             $('button#print-the-ticket', this.$element).click(_.bind(this.print, this));
594         },
595         show: function(){
596             this._super();
597             var self = this;
598
599             this.pos_widget.set_numpad_visible(true);
600             this.pos_widget.set_leftpane_visible(true);
601             this.pos_widget.set_cashier_controls_visible(true);
602             this.pos_widget.action_bar.set_total_visible(true);
603             this.pos_widget.action_bar.set_help_visible(false);
604             this.pos_widget.action_bar.set_logout_visible(true, function(){ 
605                 self.pos.screen_selector.set_user_mode('client');
606             });
607         },
608         print: function() {
609             window.print();
610         },
611         finishOrder: function() {
612             this.pos.get('selectedOrder').destroy();
613         },
614         changeSelectedOrder: function() {
615             if (this.currentOrderLines)
616                 this.currentOrderLines.unbind();
617             this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines');
618             this.currentOrderLines.bind('add', this.refresh, this);
619             this.currentOrderLines.bind('change', this.refresh, this);
620             this.currentOrderLines.bind('remove', this.refresh, this);
621             if (this.currentPaymentLines)
622                 this.currentPaymentLines.unbind();
623             this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines');
624             this.currentPaymentLines.bind('all', this.refresh, this);
625             this.refresh();
626         },
627         refresh: function() {
628             this.currentOrder = this.pos.get('selectedOrder');
629             $('.pos-receipt-container', this.$element).html(qweb_template('pos-ticket')({widget:this}));
630         },
631     });
632
633     module.PaymentScreenWidget = module.ScreenWidget.extend({
634         template_fct: qweb_template('PaymentScreenWidget'),
635         init: function(parent, options) {
636             this._super(parent,options);
637             this.model = options.model;
638             this.pos.bind('change:selectedOrder', this.changeSelectedOrder, this);
639             this.bindPaymentLineEvents();
640             this.bindOrderLineEvents();
641         },
642         show: function(){
643             this._super();
644             var self = this;
645
646             this.pos_widget.set_numpad_visible(true);
647             this.pos_widget.set_leftpane_visible(true);
648             this.pos_widget.set_cashier_controls_visible(true);
649             this.pos_widget.action_bar.set_total_visible(true);
650             this.pos_widget.action_bar.set_help_visible(false);
651             this.pos_widget.action_bar.set_logout_visible(true, function(){ 
652                 self.pos.screen_selector.set_user_mode('client');
653             });
654
655             this.setNumpadState(this.pos_widget.numpadView.state);
656         },
657         hide: function(){
658             this._super();
659             this.pos_widget.orderView.setNumpadState(null);
660             this.pos_widget.payment_screen.setNumpadState(null);
661         },
662         paymentLineList: function() {
663             return this.$element.find('#paymentlines');
664         },
665         back: function() {
666             console.log('back');
667             this.pos.screen_selector.set_current_screen('products');
668         },
669         validateCurrentOrder: function() {
670             var callback, currentOrder;
671             currentOrder = this.pos.get('selectedOrder');
672             $('button#validate-order', this.$element).attr('disabled', 'disabled');
673             this.pos.push_order(currentOrder.exportAsJSON()).then(_.bind(function() {
674                 $('button#validate-order', this.$element).removeAttr('disabled');
675                 return currentOrder.set({
676                     validated: true
677                 });
678             }, this));
679         },
680         bindPaymentLineEvents: function() {
681             this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines');
682             this.currentPaymentLines.bind('add', this.addPaymentLine, this);
683             this.currentPaymentLines.bind('remove', this.renderElement, this);
684             this.currentPaymentLines.bind('all', this.updatePaymentSummary, this);
685         },
686         bindOrderLineEvents: function() {
687             this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines');
688             this.currentOrderLines.bind('all', this.updatePaymentSummary, this);
689         },
690         changeSelectedOrder: function() {
691             this.currentPaymentLines.unbind();
692             this.bindPaymentLineEvents();
693             this.currentOrderLines.unbind();
694             this.bindOrderLineEvents();
695             this.renderElement();
696         },
697         addPaymentLine: function(newPaymentLine) {
698             var x = new module.PaymentlineWidget(null, {
699                     model: newPaymentLine
700                 });
701             x.on_delete.add(_.bind(this.deleteLine, this, x));
702             x.appendTo(this.paymentLineList());
703         },
704         renderElement: function() {
705             this._super();
706             this.$element.html(this.template_fct());
707             this.paymentLineList().empty();
708             this.currentPaymentLines.each(_.bind( function(paymentLine) {
709                 this.addPaymentLine(paymentLine);
710             }, this));
711             this.updatePaymentSummary();
712             $('button#validate-order', this.$element).click(_.bind(this.validateCurrentOrder, this));
713             $('.oe-back-to-products', this.$element).click(_.bind(this.back, this));
714         },
715         deleteLine: function(lineWidget) {
716                 this.currentPaymentLines.remove([lineWidget.model]);
717         },
718         updatePaymentSummary: function() {
719             var currentOrder, dueTotal, paidTotal, remaining, remainingAmount;
720             currentOrder = this.pos.get('selectedOrder');
721             paidTotal = currentOrder.getPaidTotal();
722             dueTotal = currentOrder.getTotal();
723             this.$element.find('#payment-due-total').html(dueTotal.toFixed(2));
724             this.$element.find('#payment-paid-total').html(paidTotal.toFixed(2));
725             remainingAmount = dueTotal - paidTotal;
726             remaining = remainingAmount > 0 ? 0 : (-remainingAmount).toFixed(2);
727             $('#payment-remaining').html(remaining);
728         },
729         setNumpadState: function(numpadState) {
730                 if (this.numpadState) {
731                         this.numpadState.unbind('setValue', this.setValue);
732                         this.numpadState.unbind('change:mode', this.setNumpadMode);
733                 }
734                 this.numpadState = numpadState;
735                 if (this.numpadState) {
736                         this.numpadState.bind('setValue', this.setValue, this);
737                         this.numpadState.bind('change:mode', this.setNumpadMode, this);
738                         this.numpadState.reset();
739                         this.setNumpadMode();
740                 }
741         },
742         setNumpadMode: function() {
743                 this.numpadState.set({mode: 'payment'});
744         },
745         setValue: function(val) {
746                 this.currentPaymentLines.last().set({amount: val});
747         },
748     });
749
750 }