f3a576a306dc86afc2f24dc17fed4a5a8a96d07b
[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                 this.set_current_screen(selectedOrder.get('cashier_screen') || this.default_cashier_screen);
123             }
124             this.selected_order = selectedOrder;
125         },
126         set_user_mode: function(user_mode){
127             if(user_mode !== this.current_mode){
128                 this.close_popup();
129                 this.current_mode = user_mode;
130                 this.load_saved_screen();
131             }
132         },
133         get_user_mode: function(){
134             return this.current_mode;
135         },
136         set_current_screen: function(screen_name){
137             var screen = this.screen_set[screen_name];
138
139             this.close_popup();
140             var selectedOrder = this.pos.get('selectedOrder');
141             if(this.current_mode === 'client'){
142                 selectedOrder.set({'client_screen': screen_name});
143             }else{
144                 selectedOrder.set({'cashier_screen': screen_name});
145             }
146
147             if(screen && screen !== this.current_screen){
148                 if(this.current_screen){
149                     this.current_screen.hide();
150                 }
151                 this.current_screen = screen;
152                 this.current_screen.show();
153             }
154         },
155     });
156
157     module.ScreenWidget = instance.web.Widget.extend({
158         init: function(parent, options){
159             this._super(parent, options);
160             options = options || {};
161             this.pos = options.pos;
162             this.pos_widget = options.pos_widget;
163         },
164         show: function(){
165             if(this.$element){
166                 this.$element.show();
167             }
168         },
169         hide: function(){
170             if(this.$element){
171                 this.$element.hide();
172             }
173             if(this.pos.barcode_reader){
174                 this.pos.barcode_reader.reset_action_callbacks();
175             }
176             if(this.pos_widget.action_bar){
177                 this.pos_widget.action_bar.destroy_buttons();
178             }
179         },
180     });
181
182     module.PopUpWidget = module.ScreenWidget.extend({
183         hide: function(){
184             if(this.$element){
185                 this.$element.hide();
186             }
187         },
188     });
189
190     module.HelpPopupWidget = module.PopUpWidget.extend({
191         template:'HelpPopupWidget',
192         show: function(){
193             this._super();
194             this.pos.proxy.help_needed();
195             var self = this;
196             
197             this.$element.find('.button').off('click').click(function(){
198                 self.pos.screen_selector.close_popup();
199                 self.pos.proxy.help_canceled();
200             });
201         },
202     });
203
204     module.ReceiptPopupWidget = module.PopUpWidget.extend({
205         template:'ReceiptPopupWidget',
206         show: function(){
207             this._super();
208             var self = this;
209             this.$element.find('.receipt').off('click').click(function(){
210                 console.log('receipt!');     //TODO
211                 self.pos.screen_selector.set_current_screen('scan');
212             });
213             this.$element.find('.invoice').off('click').click(function(){
214                 console.log('invoice!');     //TODO
215                 self.pos.screen_selector.set_current_screen('scan');
216             });
217         },
218     });
219
220     module.ErrorPopupWidget = module.PopUpWidget.extend({
221         template:'ErrorPopupWidget',
222         show: function(){
223             var self = this;
224             this._super();
225             this.pos.proxy.help_needed();
226             this.pos.proxy.scan_item_error_unrecognized();
227
228             this.pos.barcode_reader.save_callbacks();
229             this.pos.barcode_reader.reset_action_callbacks();
230             this.pos.barcode_reader.set_action_callbacks({
231                 'cashier': function(ean){
232                     clearInterval(this.intervalID);
233                     self.pos.proxy.cashier_mode_activated();
234                     self.pos.screen_selector.set_user_mode('cashier');
235                 },
236             });
237         },
238         hide:function(){
239             this._super();
240             this.pos.proxy.help_canceled();
241             this.pos.barcode_reader.restore_callbacks();
242         },
243     });
244
245     module.ScaleInviteScreenWidget = module.ScreenWidget.extend({
246         template:'ScaleInviteScreenWidget',
247         show: function(){
248             this._super();
249             var self = this;
250
251             this.pos_widget.set_numpad_visible(false);
252             this.pos_widget.set_leftpane_visible(true);
253             this.pos_widget.set_cashier_controls_visible(false);
254             this.pos_widget.action_bar.set_total_visible(true);
255             this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
256             this.pos_widget.action_bar.set_logout_visible(false);
257
258             self.pos.proxy.weighting_start();
259
260             this.intervalID = setInterval(function(){
261                 var weight = self.pos.proxy.weighting_read_kg();
262                 if(weight > 0.001){
263                     clearInterval(this.intervalID);
264                     self.pos.screen_selector.set_current_screen('scale_product');
265                 }
266             },500);
267
268             this.pos_widget.action_bar.add_new_button(
269                 {
270                     label: 'back',
271                     icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
272                     click: function(){  
273                         clearInterval(this.intervalID);
274                         self.pos.proxy.weighting_end();
275                         self.pos.screen_selector.set_current_screen('scan');
276                     }
277                 }
278             );
279
280             this.pos.barcode_reader.set_action_callbacks({
281                 'cashier': function(ean){
282                     self.pos.proxy.cashier_mode_activated();
283                     self.pos.screen_selector.set_user_mode('cashier');
284                 },
285                 'product': function(ean){
286                     if(self.pos_widget.scan_product(ean)){
287                         self.pos.proxy.scan_item_success();
288                         self.pos.screen_selector.set_current_screen('scan');
289                     }else{
290                         self.pos.screen_selector.show_popup('error');
291                     }
292                 },
293             });
294         },
295         hide: function(){
296             this._super();
297             clearInterval(this.intervalID);
298         },
299     });
300
301     module.ScaleProductScreenWidget = module.ScreenWidget.extend({
302         template:'ScaleProductSelectionScreenWidget',
303         start: function(){
304             this.product_categories_widget = new module.ProductCategoriesWidget(null,{
305                 pos:this.pos,
306             });
307             this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget'));
308
309             this.product_list_widget = new module.ProductListWidget(null,{
310                 pos:this.pos,
311                 weight: this.pos.proxy.weighting_read_kg(),
312             });
313             this.product_list_widget.replace($('.placeholder-ProductListWidget'));
314         },
315         show: function(){
316             this._super();
317             var self = this;
318             if(this.pos.screen_selector.get_user_mode() === 'client'){
319                 this.pos_widget.set_numpad_visible(false);
320                 this.pos_widget.set_leftpane_visible(true);
321                 this.pos_widget.set_cashier_controls_visible(false);
322                 this.pos_widget.action_bar.set_total_visible(true);
323                 this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
324                 this.pos_widget.action_bar.set_logout_visible(false);
325
326                 this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state);
327                 this.pos_widget.action_bar.add_new_button(
328                     {
329                         label: 'back',
330                         icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
331                         click: function(){
332                             self.pos.screen_selector.set_current_screen('scan');
333                         }
334                     }
335                 );
336                 this.pos.barcode_reader.set_action_callbacks({
337                     'cashier': function(ean){
338                         self.pos.proxy.cashier_mode_activated();
339                         self.pos.screen_selector.set_user_mode('cashier');
340                     },
341                     'product': function(ean){
342                         if(self.pos_widget.scan_product(ean)){
343                             self.pos.proxy.scan_item_success();
344                             self.pos.screen_selector.set_current_screen('scan');
345                         }else{
346                             self.pos.screen_selector.show_popup('error');
347                     }
348                 },
349                 });
350                 this.product_list_widget.set_next_screen('scan');
351             }else{  // user_mode === 'cashier'
352                 this.pos_widget.set_numpad_visible(true);
353                 this.pos_widget.set_leftpane_visible(true);
354                 this.pos_widget.set_cashier_controls_visible(true);
355                 this.pos_widget.action_bar.set_total_visible(true);
356                 this.pos_widget.action_bar.set_help_visible(false);
357                 
358                 this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state);
359                 this.pos_widget.action_bar.add_new_button(
360                     {
361                         label: 'back',
362                         icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
363                         click: function(){
364                             self.pos.screen_selector.set_current_screen('products');
365                         }
366                     }
367                 );
368                 this.product_list_widget.set_next_screen('undefined');
369             }
370
371             this.pos.proxy.weighting_start();
372             this.last_weight = this.product_list_widget.weight;
373             this.intervalID = setInterval(function(){
374                 var weight = self.pos.proxy.weighting_read_kg();
375                 if(weight != self.last_weight){
376                     self.product_list_widget.set_weight(weight);
377                     self.last_weight = weight;
378                 }
379             },500);
380         },
381         hide: function(){
382             this._super();
383             this.pos_widget.orderView.setNumpadState(null);
384             this.pos_widget.payment_screen.setNumpadState(null);
385             clearInterval(this.intervalID);
386             this.pos.proxy.weighting_end();
387         },
388     });
389
390     module.ClientPaymentScreenWidget =  module.ScreenWidget.extend({
391         template:'ClientPaymentScreenWidget',
392         show: function(){
393             this._super();
394             var self = this;
395
396             this.pos_widget.set_numpad_visible(false);
397             this.pos_widget.set_leftpane_visible(true);
398             this.pos_widget.set_cashier_controls_visible(false);
399             this.pos_widget.action_bar.set_total_visible(true);
400             this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
401             this.pos_widget.action_bar.set_logout_visible(false);
402
403             this.pos.proxy.payment_request(this.pos.get('selectedOrder').getTotal(),'card','info');    //TODO TOTAL
404
405             this.intervalID = setInterval(function(){
406                 var payment = self.pos.proxy.is_payment_accepted();
407                 if(payment === 'payment_accepted'){
408                     clearInterval(this.intervalID);
409                     var currentOrder = self.pos.get('selectedOrder');
410                     self.pos.push_order(currentOrder.exportAsJSON()).then(function() {
411                         currentOrder.destroy();
412                         self.pos.proxy.transaction_end();
413                         self.pos.screen_selector.set_current_screen('welcome');
414                     });
415                 }else if(payment === 'payment_rejected'){
416                     clearInterval(this.intervalID);
417                     //TODO show a tryagain thingie ? 
418                 }
419             },500);
420
421             this.pos_widget.action_bar.add_new_button(
422                 {
423                     label: 'back',
424                     icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
425                     click: function(){  //TODO Go to ask for weighting screen
426                         clearInterval(this.intervalID);
427                         self.pos.proxy.payment_canceled();
428                         self.pos.screen_selector.set_current_screen('scan');
429                     }
430                 }
431             );
432
433             this.pos.barcode_reader.set_action_callbacks({
434                 'cashier': function(ean){
435                     clearInterval(this.intervalID);
436                     self.pos.proxy.cashier_mode_activated();
437                     self.pos.screen_selector.set_user_mode('cashier');
438                 },
439             });
440         },
441         hide: function(){
442             this._super();
443             clearInterval(this.intervalID);
444         },
445     });
446
447     module.WelcomeScreenWidget = module.ScreenWidget.extend({
448         template:'WelcomeScreenWidget',
449         show: function(){
450             this._super();
451             var self = this;
452
453             this.pos_widget.set_numpad_visible(false);
454             this.pos_widget.set_leftpane_visible(false);
455             this.pos_widget.set_cashier_controls_visible(false);
456             this.pos_widget.action_bar.set_total_visible(false);
457             this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
458             this.pos_widget.action_bar.set_logout_visible(false);
459
460             this.pos_widget.action_bar.add_new_button(
461                 {
462                     label:'scan',
463                     click: function(){
464                         self.pos.screen_selector.set_current_screen('scan');
465                     }
466                 },{
467                     label: 'weight',
468                     icon: '/point_of_sale/static/src/img/icons/png48/scale.png',
469                     click: function(){  //TODO Go to ask for weighting screen
470                         self.pos.screen_selector.set_current_screen('scale_invite');
471                     }
472                 }
473             );
474             this.pos.barcode_reader.set_action_callbacks({
475                 'product': function(ean){
476                     self.pos.proxy.transaction_start(); 
477                     if(self.pos_widget.scan_product(ean)){
478                         self.pos.proxy.scan_item_success();
479                         self.pos.screen_selector.set_current_screen('scan');
480                     }else{
481                         self.pos.screen_selector.show_popup('error');
482                     }
483                 },
484                 'cashier': function(ean){
485                     //TODO 'switch to cashier mode'
486                     self.pos.proxy.cashier_mode_activated();
487                     self.pos.screen_selector.set_user_mode('cashier');
488                 },
489                 'client': function(ean){
490                     self.pos.proxy.transaction_start(); 
491                     //TODO 'log the client'
492                     self.pos.screen_selector.show_popup('receipt');
493                 },
494                 'discount': function(ean){
495                     // TODO : what to do in this case ????
496                 },
497             });
498         },
499         hide: function(){
500             this._super();
501             this.pos.barcode_reader.reset_action_callbacks();
502             this.pos_widget.action_bar.destroy_buttons();
503         },
504     });
505
506     module.ScanProductScreenWidget = module.ScreenWidget.extend({
507         template:'ScanProductScreenWidget',
508         show: function(){
509             this._super();
510             var self = this;
511
512             this.pos_widget.set_numpad_visible(false);
513             this.pos_widget.set_leftpane_visible(true);
514             this.pos_widget.set_cashier_controls_visible(false);
515             this.pos_widget.action_bar.set_total_visible(true);
516             this.pos_widget.action_bar.set_help_visible(true,function(){self.pos.screen_selector.show_popup('help');});
517             this.pos_widget.action_bar.set_logout_visible(false);
518
519             this.pos_widget.action_bar.add_new_button(
520                 {
521                     label: 'weight',
522                     icon: '/point_of_sale/static/src/img/icons/png48/scale.png',
523                     click: function(){  //TODO Go to ask for weighting screen
524                         self.pos.screen_selector.set_current_screen('scale_invite');
525                     }
526                 },{
527                     label: 'pay',
528                     icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
529                     click: function(){
530                         self.pos.screen_selector.set_current_screen('client_payment'); //TODO what stuff ?
531                     }
532                 }
533             );
534             this.pos.barcode_reader.set_action_callbacks({
535                 'product': function(ean){
536                     if(self.pos_widget.scan_product(ean)){
537                         self.pos.proxy.scan_item_success();
538                     }else{
539                         self.pos.screen_selector.show_popup('error');
540                     }
541                 },
542                 'cashier': function(ean){
543                     self.pos.proxy.cashier_mode_activated();
544                     self.pos.screen_selector.set_user_mode('cashier');
545                 },
546                 'discount': function(ean){
547                     // TODO : handle the discount
548                 },
549             });
550         },
551     });
552     
553     module.SearchProductScreenWidget = module.ScreenWidget.extend({
554         template:'SearchProductScreenWidget',
555         start: function(){
556             this.product_categories_widget = new module.ProductCategoriesWidget(null,{
557                 pos:this.pos,
558             });
559             this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget'));
560
561             this.product_list_widget = new module.ProductListWidget(null,{
562                 pos:this.pos,
563             });
564             this.product_list_widget.replace($('.placeholder-ProductListWidget'));
565         },
566         show: function(){
567             this._super();
568             var self = this;
569
570             this.pos_widget.set_numpad_visible(true);
571             this.pos_widget.set_leftpane_visible(true);
572             this.pos_widget.set_cashier_controls_visible(true);
573             this.pos_widget.action_bar.set_total_visible(true);
574             this.pos_widget.action_bar.set_help_visible(false);
575             this.pos_widget.action_bar.set_logout_visible(true, function(){ 
576                 self.pos.screen_selector.set_user_mode('client');
577             });
578
579             this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state);
580             this.pos_widget.action_bar.add_new_button(
581                 {
582                     label: 'weight',
583                     icon: '/point_of_sale/static/src/img/icons/png48/scale.png',
584                     click: function(){  
585                         self.pos.screen_selector.set_current_screen('scale_product');
586                     }
587                 }
588             );
589             this.pos.barcode_reader.set_action_callbacks({
590                 'product': function(ean){
591                     if(self.pos_widget.scan_product(ean)){
592                         self.pos.proxy.scan_item_success();
593                     }else{
594                         self.pos.screen_selector.show_popup('error');
595                     }
596                 },
597                 'cashier': function(ean){
598                     self.pos.proxy.cashier_mode_activated();
599                     self.pos.screen_selector.set_user_mode('cashier');
600                 },
601                 'discount': function(ean){
602                     // TODO : handle the discount
603                 },
604             });
605         },
606         hide: function(){
607             this._super();
608             this.pos_widget.orderView.setNumpadState(null);
609             this.pos_widget.payment_screen.setNumpadState(null);
610         },
611
612     });
613
614     module.ReceiptScreenWidget = module.ScreenWidget.extend({
615         template: 'ReceiptScreenWidget',
616         init: function(parent, options) {
617             this._super(parent,options);
618             this.model = options.model;
619             this.user = this.pos.get('user');
620             this.company = this.pos.get('company');
621             this.shop_obj = this.pos.get('shop');
622         },
623         start: function() {
624             this.pos.bind('change:selectedOrder', this.changeSelectedOrder, this);
625             this.changeSelectedOrder();
626             $('button#pos-finish-order', this.$element).click(_.bind(this.finishOrder, this));
627             $('button#print-the-ticket', this.$element).click(_.bind(this.print, this));
628         },
629         show: function(){
630             this._super();
631             var self = this;
632
633             this.pos_widget.set_numpad_visible(true);
634             this.pos_widget.set_leftpane_visible(true);
635             this.pos_widget.set_cashier_controls_visible(true);
636             this.pos_widget.action_bar.set_total_visible(true);
637             this.pos_widget.action_bar.set_help_visible(false);
638             this.pos_widget.action_bar.set_logout_visible(true, function(){ 
639                 self.pos.screen_selector.set_user_mode('client');
640             });
641         },
642         print: function() {
643             window.print();
644         },
645         finishOrder: function() {
646             this.pos.get('selectedOrder').destroy();
647         },
648         changeSelectedOrder: function() {
649             if (this.currentOrderLines)
650                 this.currentOrderLines.unbind();
651             this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines');
652             this.currentOrderLines.bind('add', this.refresh, this);
653             this.currentOrderLines.bind('change', this.refresh, this);
654             this.currentOrderLines.bind('remove', this.refresh, this);
655             if (this.currentPaymentLines)
656                 this.currentPaymentLines.unbind();
657             this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines');
658             this.currentPaymentLines.bind('all', this.refresh, this);
659             this.refresh();
660         },
661         refresh: function() {
662             this.currentOrder = this.pos.get('selectedOrder');
663             $('.pos-receipt-container', this.$element).html(qweb_template('pos-ticket')({widget:this}));
664         },
665     });
666
667     module.PaymentScreenWidget = module.ScreenWidget.extend({
668         template_fct: qweb_template('PaymentScreenWidget'),
669         init: function(parent, options) {
670             this._super(parent,options);
671             this.model = options.model;
672             this.pos.bind('change:selectedOrder', this.changeSelectedOrder, this);
673             this.bindPaymentLineEvents();
674             this.bindOrderLineEvents();
675         },
676         show: function(){
677             this._super();
678             var self = this;
679
680             this.pos_widget.set_numpad_visible(true);
681             this.pos_widget.set_leftpane_visible(true);
682             this.pos_widget.set_cashier_controls_visible(true);
683             this.pos_widget.action_bar.set_total_visible(true);
684             this.pos_widget.action_bar.set_help_visible(false);
685             this.pos_widget.action_bar.set_logout_visible(true, function(){ 
686                 self.pos.screen_selector.set_user_mode('client');
687             });
688
689             this.setNumpadState(this.pos_widget.numpadView.state);
690         },
691         hide: function(){
692             this._super();
693             this.pos_widget.orderView.setNumpadState(null);
694             this.pos_widget.payment_screen.setNumpadState(null);
695         },
696         paymentLineList: function() {
697             return this.$element.find('#paymentlines');
698         },
699         back: function() {
700             this.pos.screen_selector.set_current_screen('products');
701         },
702         validateCurrentOrder: function() {
703             var callback, currentOrder;
704             currentOrder = this.pos.get('selectedOrder');
705             $('button#validate-order', this.$element).attr('disabled', 'disabled');
706             this.pos.push_order(currentOrder.exportAsJSON()).then(_.bind(function() {
707                 $('button#validate-order', this.$element).removeAttr('disabled');
708                 return currentOrder.set({
709                     validated: true
710                 });
711             }, this));
712         },
713         bindPaymentLineEvents: function() {
714             this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines');
715             this.currentPaymentLines.bind('add', this.addPaymentLine, this);
716             this.currentPaymentLines.bind('remove', this.renderElement, this);
717             this.currentPaymentLines.bind('all', this.updatePaymentSummary, this);
718         },
719         bindOrderLineEvents: function() {
720             this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines');
721             this.currentOrderLines.bind('all', this.updatePaymentSummary, this);
722         },
723         changeSelectedOrder: function() {
724             this.currentPaymentLines.unbind();
725             this.bindPaymentLineEvents();
726             this.currentOrderLines.unbind();
727             this.bindOrderLineEvents();
728             this.renderElement();
729         },
730         addPaymentLine: function(newPaymentLine) {
731             var x = new module.PaymentlineWidget(null, {
732                     model: newPaymentLine
733                 });
734             x.on_delete.add(_.bind(this.deleteLine, this, x));
735             x.appendTo(this.paymentLineList());
736         },
737         renderElement: function() {
738             this._super();
739             this.$element.html(this.template_fct());
740             this.paymentLineList().empty();
741             this.currentPaymentLines.each(_.bind( function(paymentLine) {
742                 this.addPaymentLine(paymentLine);
743             }, this));
744             this.updatePaymentSummary();
745             $('button#validate-order', this.$element).click(_.bind(this.validateCurrentOrder, this));
746             $('.oe-back-to-products', this.$element).click(_.bind(this.back, this));
747         },
748         deleteLine: function(lineWidget) {
749                 this.currentPaymentLines.remove([lineWidget.model]);
750         },
751         updatePaymentSummary: function() {
752             var currentOrder, dueTotal, paidTotal, remaining, remainingAmount;
753             currentOrder = this.pos.get('selectedOrder');
754             paidTotal = currentOrder.getPaidTotal();
755             dueTotal = currentOrder.getTotal();
756             this.$element.find('#payment-due-total').html(dueTotal.toFixed(2));
757             this.$element.find('#payment-paid-total').html(paidTotal.toFixed(2));
758             remainingAmount = dueTotal - paidTotal;
759             remaining = remainingAmount > 0 ? 0 : (-remainingAmount).toFixed(2);
760             $('#payment-remaining').html(remaining);
761         },
762         setNumpadState: function(numpadState) {
763                 if (this.numpadState) {
764                         this.numpadState.unbind('setValue', this.setValue);
765                         this.numpadState.unbind('change:mode', this.setNumpadMode);
766                 }
767                 this.numpadState = numpadState;
768                 if (this.numpadState) {
769                         this.numpadState.bind('setValue', this.setValue, this);
770                         this.numpadState.bind('change:mode', this.setNumpadMode, this);
771                         this.numpadState.reset();
772                         this.setNumpadMode();
773                 }
774         },
775         setNumpadMode: function() {
776                 this.numpadState.set({mode: 'payment'});
777         },
778         setValue: function(val) {
779                 this.currentPaymentLines.last().set({amount: val});
780         },
781     });
782
783 }