1 function openerp_pos_widgets(instance, module){ //module is instance.point_of_sale
2 var QWeb = instance.web.qweb;
4 module.NumpadWidget = module.PosBaseWidget.extend({
5 template:'NumpadWidget',
6 init: function(parent, options) {
8 this.state = new module.NumpadState();
11 this.state.bind('change:mode', this.changedMode, this);
13 this.$element.find('button#numpad-backspace').click(_.bind(this.clickDeleteLastChar, this));
14 this.$element.find('button#numpad-minus').click(_.bind(this.clickSwitchSign, this));
15 this.$element.find('button.number-char').click(_.bind(this.clickAppendNewChar, this));
16 this.$element.find('button.mode-button').click(_.bind(this.clickChangeMode, this));
18 clickDeleteLastChar: function() {
19 return this.state.deleteLastChar();
21 clickSwitchSign: function() {
22 return this.state.switchSign();
24 clickAppendNewChar: function(event) {
26 newChar = event.currentTarget.innerText || event.currentTarget.textContent;
27 return this.state.appendNewChar(newChar);
29 clickChangeMode: function(event) {
30 var newMode = event.currentTarget.attributes['data-mode'].nodeValue;
31 return this.state.changeMode(newMode);
33 changedMode: function() {
34 var mode = this.state.get('mode');
35 $('.selected-mode').removeClass('selected-mode');
36 $(_.str.sprintf('.mode-button[data-mode="%s"]', mode), this.$element).addClass('selected-mode');
40 // The paypad allows to select the payment method (cashRegisters)
41 // used to pay the order.
42 module.PaypadWidget = module.PosBaseWidget.extend({
43 template: 'PaypadWidget',
44 renderElement: function() {
48 this.pos.get('cashRegisters').each(function(cashRegister) {
49 var button = new module.PaypadButtonWidget(self,{
51 pos_widget : self.pos_widget,
52 cashRegister: cashRegister,
54 button.appendTo(self.$element);
59 module.PaypadButtonWidget = module.PosBaseWidget.extend({
60 template: 'PaypadButtonWidget',
61 init: function(parent, options){
62 this._super(parent, options);
63 this.cashRegister = options.cashRegister;
65 renderElement: function() {
69 this.$element.click(function(){
70 if (self.pos.get('selectedOrder').get('screen') === 'receipt'){ //TODO Why ?
71 console.warn('TODO should not get there...?');
74 self.pos.get('selectedOrder').addPaymentLine(self.cashRegister);
75 self.pos_widget.screen_selector.set_current_screen('payment');
80 module.OrderlineWidget = module.PosBaseWidget.extend({
81 template: 'OrderlineWidget',
82 init: function(parent, options) {
83 this._super(parent,options);
85 this.model = options.model;
86 this.order = options.order;
88 this.model.bind('change', _.bind( function() {
92 click_handler: function() {
93 this.order.selectLine(this.model);
96 renderElement: function() {
98 this.$element.click(_.bind(this.click_handler, this));
99 if(this.model.is_selected()){
100 this.$element.addClass('selected');
104 this.renderElement();
107 on_selected: function() {},
108 on_refresh: function(){},
111 module.OrderWidget = module.PosBaseWidget.extend({
112 template:'OrderWidget',
113 init: function(parent, options) {
114 this._super(parent,options);
115 this.display_mode = options.display_mode || 'numpad'; // 'maximized' | 'actionbar' | 'numpad'
116 this.set_numpad_state(options.numpadState);
117 this.pos.bind('change:selectedOrder', this.change_selected_order, this);
118 this.bind_orderline_events();
120 set_numpad_state: function(numpadState) {
121 if (this.numpadState) {
122 this.numpadState.unbind('set_value', this.set_value);
124 this.numpadState = numpadState;
125 if (this.numpadState) {
126 this.numpadState.bind('set_value', this.set_value, this);
127 this.numpadState.reset();
130 set_value: function(val) {
131 var order = this.pos.get('selectedOrder');
132 if (order.get('orderLines').length !== 0) {
133 var mode = this.numpadState.get('mode');
134 if( mode === 'quantity'){
135 order.getSelectedLine().set_quantity(val);
136 }else if( mode === 'discount'){
137 order.getSelectedLine().set_discount(val);
138 }else if( mode === 'list_price'){
139 order.getSelectedLine().set_list_price(val);
142 this.pos.get('selectedOrder').destroy();
145 change_selected_order: function() {
146 this.currentOrderLines.unbind();
147 this.bind_orderline_events();
148 this.renderElement();
150 bind_orderline_events: function() {
151 this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines');
152 this.currentOrderLines.bind('add', this.renderElement, this);
153 this.currentOrderLines.bind('remove', this.renderElement, this);
155 update_numpad: function() {
157 if (this.selected_line !== this.pos.get('selectedOrder').getSelectedLine()) {
160 this.selected_line = this.pos.get('selectedOrder').getSelectedLine();
161 if (reset && this.numpadState)
162 this.numpadState.reset();
164 renderElement: function() {
168 if(this.display_mode === 'maximized'){
169 $('.point-of-sale .order-container').css({'bottom':'0px'});
170 }else if(this.display_mode === 'actionbar'){
171 $('.point-of-sale .order-container').css({'bottom':'105px'});
172 }else if(this.display_mode !== 'numpad'){
173 console.error('ERROR: OrderWidget renderElement(): wrong display_mode:',this.display_mode);
176 var $content = this.$('.orderlines');
177 this.currentOrderLines.each(_.bind( function(orderLine) {
178 var line = new module.OrderlineWidget(this, {
180 order: this.pos.get('selectedOrder'),
182 line.on_selected.add(_.bind(this.update_numpad, this));
183 line.on_refresh.add(_.bind(this.update_summary, this));
184 line.appendTo($content);
186 this.update_numpad();
187 this.update_summary();
189 var position = this.scrollbar ? this.scrollbar.get_position() : 0;
190 var at_bottom = this.scrollbar ? this.scrollbar.is_at_bottom() : false;
192 this.scrollbar = new module.ScrollbarWidget(this,{
194 target_selector: '.order-scroller',
198 self.$('.order-scroller').css({'width':'89%'},100);
201 self.$('.order-scroller').css({'width':'100%'},100);
205 this.scrollbar.replace(this.$('.placeholder-ScrollbarWidget'));
206 this.scrollbar.set_position(position);
209 this.scrollbar.set_position(Number.MAX_VALUE, false);
213 update_summary: function(){
214 var order = this.pos.get('selectedOrder');
215 var total = order ? order.getTotal() : 0;
216 this.$('.summary .value.total').html(this.format_currency(total));
218 set_display_mode: function(mode){
219 if(this.display_mode !== mode){
220 this.display_mode = mode;
221 this.renderElement();
226 module.ProductWidget = module.PosBaseWidget.extend({
227 template: 'ProductWidget',
228 init: function(parent, options) {
229 this._super(parent,options);
230 this.model = options.model;
231 this.model.attributes.weight = options.weight;
232 this.next_screen = options.next_screen;
233 this.click_product_action = options.click_product_action;
235 add_to_order: function(event) {
236 /* Preserve the category URL */
237 event.preventDefault();
238 return (this.pos.get('selectedOrder')).addProduct(this.model);
240 set_weight: function(weight){
241 this.model.attributes.weight = weight;
242 this.renderElement();
244 get_image_url: function() {
245 return 'web/binary/image?session_id='+instance.connection.session_id+'&model=product.product&field=image&id='+this.model.get('id')+'&cache=1800';
247 renderElement: function() {
250 $("a", this.$element).click(function(e){
251 if(self.click_product_action){
252 self.click_product_action(self.model);
258 module.PaymentlineWidget = module.PosBaseWidget.extend({
259 template: 'PaymentlineWidget',
260 init: function(parent, options) {
261 this._super(parent,options);
262 this.payment_line = options.payment_line;
263 this.payment_line.bind('change', this.changedAmount, this);
265 on_delete: function() {},
266 changeAmount: function(event) {
268 newAmount = event.currentTarget.value;
269 if (newAmount && !isNaN(newAmount)) {
270 this.amount = parseFloat(newAmount);
271 this.payment_line.set_amount(this.amount);
274 changedAmount: function() {
275 if (this.amount !== this.payment_line.get_amount())
276 this.renderElement();
278 renderElement: function() {
279 this.name = this.payment_line.get_cashregister().get('journal_id')[1];
281 this.$('input').keyup(_.bind(this.changeAmount, this));
282 this.$('.delete-payment-line').click(this.on_delete);
286 module.OrderButtonWidget = module.PosBaseWidget.extend({
287 template:'OrderButtonWidget',
288 init: function(parent, options) {
289 this._super(parent,options);
290 this.order = options.order;
291 this.order.bind('destroy', _.bind( function() {
294 this.pos.bind('change:selectedOrder', _.bind( function(pos) {
296 selectedOrder = pos.get('selectedOrder');
297 if (this.order === selectedOrder) {
298 this.setButtonSelected();
302 renderElement:function(){
304 this.$('button.select-order').click(_.bind(this.selectOrder, this));
305 this.$('button.close-order').click(_.bind(this.closeOrder, this));
307 selectOrder: function(event) {
309 selectedOrder: this.order
312 setButtonSelected: function() {
313 $('.selected-order').removeClass('selected-order');
314 this.$element.addClass('selected-order');
316 closeOrder: function(event) {
317 this.order.destroy();
321 module.ActionButtonWidget = instance.web.Widget.extend({
322 template:'ActionButtonWidget',
323 icon_template:'ActionButtonWidgetWithIcon',
324 init: function(parent, options){
325 this._super(parent, options);
326 this.label = options.label || 'button';
327 this.rightalign = options.rightalign || false;
328 this.click_action = options.click;
330 this.icon = options.icon;
331 this.template = this.icon_template;
334 renderElement: function(){
336 if(this.click_action){
337 this.$element.click(_.bind(this.click_action, this));
342 module.ActionBarWidget = instance.web.Widget.extend({
343 template:'ActionBarWidget',
344 init: function(parent, options){
345 this._super(parent,options);
346 this.button_list = [];
347 this.fake_buttons = {};
348 this.visibility = {};
350 set_element_visible: function(element, visible, action){
351 if(visible != this.visibility[element]){
352 this.visibility[element] = visible;
354 this.$('.'+element).show();
356 this.$('.'+element).hide();
359 if(visible && action){
360 this.$('.'+element).off('click').click(action);
363 destroy_buttons:function(){
364 for(var i = 0; i < this.button_list.length; i++){
365 this.button_list[i].destroy();
367 this.button_list = [];
370 get_button_count: function(){
371 return this.button_list.length;
373 add_new_button: function(button_options){
374 var button = new module.ActionButtonWidget(this,button_options);
375 this.button_list.push(button);
376 button.appendTo(this.$('.pos-actionbar-button-list'));
380 this.$element.show();
383 this.$element.hide();
387 module.ProductCategoriesWidget = module.PosBaseWidget.extend({
388 template: 'ProductCategoriesWidget',
389 init: function(parent, options){
391 this._super(parent,options);
392 this.product_type = options.product_type || 'all'; // 'all' | 'weightable'
393 this.onlyWeightable = options.onlyWeightable || false;
394 this.category = this.pos.root_category;
395 this.breadcrumb = [];
396 this.subcategories = [];
400 // changes the category. if undefined, sets to root category
401 set_category : function(category){
402 var db = this.pos.db;
404 this.category = db.get_category_by_id(db.root_category_id);
406 this.category = category;
408 this.breadcrumb = [];
409 var ancestors_ids = db.get_category_ancestors_ids(this.category.id);
410 for(var i = 1; i < ancestors_ids.length; i++){
411 this.breadcrumb.push(db.get_category_by_id(ancestors_ids[i]));
413 if(this.category.id !== db.root_category_id){
414 this.breadcrumb.push(this.category);
416 this.subcategories = db.get_category_by_id(db.get_category_childs_ids(this.category.id));
419 renderElement: function(){
423 var hasimages = false; //if none of the subcategories have images, we don't display buttons with icons
424 _.each(this.subcategories, function(category){
430 _.each(this.subcategories, function(category){
432 var button = QWeb.render('CategoryButton',{category:category});
434 var button = QWeb.render('CategorySimpleButton',{category:category});
436 button = _.str.trim(button); // we remove whitespace between buttons to fix spacing
438 $(button).appendTo(this.$('.category-list')).click(function(event){
439 var id = category.id;
440 var cat = self.pos.db.get_category_by_id(id);
441 self.set_category(cat);
442 self.renderElement();
443 self.search_and_categories(cat);
446 // breadcrumb click actions
447 this.$(".oe-pos-categories-list a").click(function(event){
448 var id = $(event.target).data("category-id");
449 var category = self.pos.db.get_category_by_id(id);
450 self.set_category(category);
451 self.renderElement();
452 self.search_and_categories(category);
454 this.search_and_categories();
457 set_product_type: function(type){ // 'all' | 'weightable'
458 this.product_type = type;
459 this.reset_category();
462 // resets the current category to the root category
463 reset_category: function(){
465 this.renderElement();
466 this.search_and_categories();
469 // filters the products, and sets up the search callbacks
470 search_and_categories: function(category){
473 // find all products belonging to the current category
474 var products = this.pos.db.get_product_by_category(this.category.id);
475 self.pos.get('products').reset(products);
477 // filter the products according to the search string
478 this.$('.searchbox input').keyup(function(){
479 query = $(this).val().toLowerCase();
481 var products = self.pos.db.search_product_in_category(self.category.id, ['name','ean13'], query);
482 self.pos.get('products').reset(products);
483 self.$('.search-clear').fadeIn();
485 var products = self.pos.db.get_product_by_category(self.category.id);
486 self.pos.get('products').reset(products);
487 self.$('.search-clear').fadeOut();
491 this.$('.searchbox input').click(function(){}); //Why ???
493 //reset the search when clicking on reset
494 this.$('.search-clear').click(function(){
495 var products = self.pos.db.get_product_by_category(self.category.id);
496 self.pos.get('products').reset(products);
497 self.$('.searchbox input').val('').focus();
498 self.$('.search-clear').fadeOut();
503 module.ProductListWidget = module.ScreenWidget.extend({
504 template:'ProductListWidget',
505 init: function(parent, options) {
507 this._super(parent,options);
508 this.model = options.model;
509 this.product_list = [];
510 this.weight = options.weight || 0;
511 this.show_scale = options.show_scale || false;
512 this.next_screen = options.next_screen || false;
513 this.click_product_action = options.click_product_action;
515 this.pos.get('products').bind('reset', function(){
516 self.renderElement();
519 set_weight: function(weight){
520 for(var i = 0; i < this.product_list.length; i++){
521 this.product_list[i].set_weight(weight);
524 renderElement: function() {
527 this.product_list = [];
528 this.pos.get('products')
530 .map(function(product) {
531 var product = new module.ProductWidget(self, {
534 click_product_action: self.click_product_action,
536 self.product_list.push(product);
539 .invoke('appendTo', this.$('.product-list'));
541 this.scrollbar = new module.ScrollbarWidget(this,{
543 target_selector: '.product-list-scroller',
545 self.$('.product-list-scroller').css({'padding-right':'62px'},100);
548 self.$('.product-list-scroller').css({'padding-right':'0px'},100);
552 this.scrollbar.replace(this.$('.placeholder-ScrollbarWidget'));
557 module.UsernameWidget = module.PosBaseWidget.extend({
558 template: 'UsernameWidget',
559 init: function(parent, options){
560 var options = options || {};
561 this._super(parent,options);
562 this.mode = options.mode || 'cashier';
564 set_user_mode: function(mode){
569 this.renderElement();
571 get_name: function(){
573 if(this.mode === 'cashier'){
574 user = this.pos.get('cashier') || this.pos.get('user');
576 user = this.pos.get('selectedOrder').get_client() || this.pos.get('user');
586 module.HeaderButtonWidget = module.PosBaseWidget.extend({
587 template: 'HeaderButtonWidget',
588 init: function(parent, options){
589 options = options || {};
590 this._super(parent, options);
591 this.action = options.action;
592 this.label = options.label;
594 renderElement: function(){
598 this.$element.click(function(){ self.action(); });
601 show: function(){ this.$element.show(); },
602 hide: function(){ this.$element.hide(); },
607 // ---------- Main Point of Sale Widget ----------
609 // this is used to notify the user that data is being synchronized on the network
610 module.SynchNotificationWidget = module.PosBaseWidget.extend({
611 template: "SynchNotificationWidget",
612 init: function(parent, options){
613 options = options || {};
614 this._super(parent, options);
616 renderElement: function() {
619 this.$('.oe_pos_synch-notification-button').click(function(){
625 this.pos.bind('change:nbr_pending_operations', function(){
626 self.renderElement();
629 get_nbr_pending: function(){
630 return this.pos.get('nbr_pending_operations');
634 // The PosWidget is the main widget that contains all other widgets in the PointOfSale.
635 // It is mainly composed of :
636 // - a header, containing the list of orders
637 // - a leftpane, containing the list of bought products (orderlines)
638 // - a rightpane, containing the screens (see pos_screens.js)
639 // - an actionbar on the bottom, containing various action buttons
641 // - an onscreen keyboard
642 // a screen_selector which controls the switching between screens and the showing/closing of popups
644 module.PosWidget = module.PosBaseWidget.extend({
645 template: 'PosWidget',
647 this._super(arguments[0],{});
649 this.pos = new module.PosModel(this.session);
650 this.pos_widget = this; //So that pos_widget's childs have pos_widget set automatically
652 this.numpad_visible = true;
653 this.left_action_bar_visible = true;
654 this.leftpane_visible = true;
655 this.leftpane_width = '440px';
656 this.cashier_controls_visible = true;
660 setInterval(function(){
661 $('body').css({'-webkit-filter':'hue-rotate('+Math.random()*360+'deg)' });
669 return self.pos.ready.then(function() {
670 self.build_currency_template();
671 self.renderElement();
673 self.$('.neworder-button').click(function(){
674 self.pos.add_new_order();
677 //when a new order is created, add an order button widget
678 self.pos.get('orders').bind('add', function(new_order){
679 var new_order_button = new module.OrderButtonWidget(null, {
683 new_order_button.appendTo($('#orders'));
684 new_order_button.selectOrder();
687 self.pos.get('orders').add(new module.Order({ pos: self.pos }));
689 self.build_widgets();
691 self.screen_selector.set_default_screen();
693 self.pos.barcode_reader.connect();
695 instance.webclient.set_content_full_screen(true);
697 if (!self.pos.get('pos_session')) {
698 self.screen_selector.show_popup('error', 'Sorry, we could not create a user session');
699 }else if(!self.pos.get('pos_config')){
700 self.screen_selector.show_popup('error', 'Sorry, we could not find any PoS Configuration for this session');
703 self.$('.loader').animate({opacity:0},1500,'swing',function(){self.$('.loader').hide();});
704 self.$('.loader img').hide();
706 if(jQuery.deparam(jQuery.param.querystring()).debug !== undefined){
707 window.pos = self.pos;
708 window.pos_widget = self.pos_widget;
711 },function(){ // error when loading models data from the backend
712 self.$('.loader img').hide();
713 return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_pos_session_opening']], ['res_id'])
714 .pipe( _.bind(function(res){
715 return instance.connection.rpc('/web/action/load', {'action_id': res[0]['res_id']})
716 .pipe(_.bind(function(result){
717 var action = result.result;
718 this.do_action(action);
724 // This method instantiates all the screens, widgets, etc. If you want to add new screens change the
725 // startup screen, etc, override this method.
726 build_widgets: function() {
729 // -------- Screens ---------
731 this.product_screen = new module.ProductScreenWidget(this,{});
732 this.product_screen.appendTo($('#rightpane'));
734 this.receipt_screen = new module.ReceiptScreenWidget(this, {});
735 this.receipt_screen.appendTo($('#rightpane'));
737 this.payment_screen = new module.PaymentScreenWidget(this, {});
738 this.payment_screen.appendTo($('#rightpane'));
740 this.welcome_screen = new module.WelcomeScreenWidget(this,{});
741 this.welcome_screen.appendTo($('#rightpane'));
743 this.client_payment_screen = new module.ClientPaymentScreenWidget(this, {});
744 this.client_payment_screen.appendTo($('#rightpane'));
746 this.scale_invite_screen = new module.ScaleInviteScreenWidget(this, {});
747 this.scale_invite_screen.appendTo($('#rightpane'));
749 this.scale_screen = new module.ScaleScreenWidget(this,{});
750 this.scale_screen.appendTo($('#rightpane'));
752 // -------- Popups ---------
754 this.help_popup = new module.HelpPopupWidget(this, {});
755 this.help_popup.appendTo($('.point-of-sale'));
757 this.error_popup = new module.ErrorPopupWidget(this, {});
758 this.error_popup.appendTo($('.point-of-sale'));
760 this.error_product_popup = new module.ErrorProductNotRecognizedPopupWidget(this, {});
761 this.error_product_popup.appendTo($('.point-of-sale'));
763 this.error_session_popup = new module.ErrorNoSessionPopupWidget(this, {});
764 this.error_session_popup.appendTo($('.point-of-sale'));
766 // -------- Misc ---------
768 this.notification = new module.SynchNotificationWidget(this,{});
769 this.notification.appendTo(this.$('#rightheader'));
771 this.username = new module.UsernameWidget(this,{});
772 this.username.replace(this.$('.placeholder-UsernameWidget'));
774 this.action_bar = new module.ActionBarWidget(this);
775 this.action_bar.appendTo($(".point-of-sale #rightpane"));
777 this.left_action_bar = new module.ActionBarWidget(this);
778 this.left_action_bar.appendTo($(".point-of-sale #leftpane"));
780 this.paypad = new module.PaypadWidget(this, {});
781 this.paypad.replace($('#placeholder-PaypadWidget'));
783 this.numpad = new module.NumpadWidget(this);
784 this.numpad.replace($('#placeholder-NumpadWidget'));
786 this.order_widget = new module.OrderWidget(this, {});
787 this.order_widget.replace($('#placeholder-OrderWidget'));
789 this.onscreen_keyboard = new module.OnscreenKeyboardWidget(this, {
790 'keyboard_model': 'simple'
792 this.onscreen_keyboard.appendTo($(".point-of-sale #content"));
794 this.close_button = new module.HeaderButtonWidget(this,{
796 action: function(){ self.try_close(); },
798 this.close_button.appendTo(this.$('#rightheader'));
800 this.client_button = new module.HeaderButtonWidget(this,{
801 label:'Self-Checkout',
802 action: function(){ self.screen_selector.set_user_mode('client'); },
804 this.client_button.appendTo(this.$('#rightheader'));
807 // -------- Screen Selector ---------
809 this.screen_selector = new module.ScreenSelector({
812 'products': this.product_screen,
813 'payment' : this.payment_screen,
814 'client_payment' : this.client_payment_screen,
815 'scale_invite' : this.scale_invite_screen,
816 'scale': this.scale_screen,
817 'receipt' : this.receipt_screen,
818 'welcome' : this.welcome_screen,
821 'help': this.help_popup,
822 'error': this.error_popup,
823 'error-product': this.error_product_popup,
824 'error-session': this.error_session_popup,
826 default_client_screen: 'welcome',
827 default_cashier_screen: 'products',
828 default_mode: this.pos.use_selfcheckout ? 'client' : 'cashier',
833 changed_pending_operations: function () {
835 this.synch_notification.on_change_nbr_pending(self.pos.get('nbr_pending_operations').length);
837 // shows or hide the numpad and related controls like the paypad.
838 set_numpad_visible: function(visible){
839 if(visible !== this.numpad_visible){
840 this.numpad_visible = visible;
842 this.set_left_action_bar_visible(false);
845 this.order_widget.set_display_mode('numpad');
849 if(this.order_widget.display_mode === 'numpad'){
850 this.order_widget.set_display_mode('maximized');
855 set_left_action_bar_visible: function(visible){
856 if(visible !== this.left_action_bar_visible){
857 this.left_action_bar_visible = visible;
859 this.set_numpad_visible(false);
860 this.left_action_bar.show();
861 this.order_widget.set_display_mode('actionbar');
863 this.left_action_bar.hide();
864 if(this.order_widget.display_mode === 'actionbar'){
865 this.order_widget.set_display_mode('maximized');
871 //shows or hide the leftpane (contains the list of orderlines, the numpad, the paypad, etc.)
872 set_leftpane_visible: function(visible){
873 if(visible !== this.leftpane_visible){
874 this.leftpane_visible = visible;
876 $('#leftpane').show().animate({'width':this.leftpane_width},500,'swing');
877 $('#rightpane').animate({'left':this.leftpane_width},500,'swing');
879 var leftpane = $('#leftpane');
880 $('#leftpane').animate({'width':'0px'},500,'swing', function(){ leftpane.hide(); });
881 $('#rightpane').animate({'left':'0px'},500,'swing');
885 //shows or hide the controls in the PosWidget that are specific to the cashier ( Orders, close button, etc. )
886 set_cashier_controls_visible: function(visible){
887 if(visible !== this.cashier_controls_visible){
888 this.cashier_controls_visible = visible;
890 $('#loggedas').show();
891 $('#rightheader').show();
893 $('#loggedas').hide();
894 $('#rightheader').hide();
898 try_close: function() {
900 self.pos.flush().then(function() {
906 this.pos.barcode_reader.disconnect();
907 return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_client_pos_menu']], ['res_id']).pipe(
908 _.bind(function(res) {
909 return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) {
910 var action = result.result;
911 action.context = _.extend(action.context || {}, {'cancel_action': {type: 'ir.actions.client', tag: 'reload'}});
913 this.do_action(action);
917 destroy: function() {
918 instance.webclient.set_content_full_screen(false);
919 self.pos = undefined;