1 function openerp_picking_widgets(instance){
3 var module = instance.stock;
4 var _t = instance.web._t;
5 var QWeb = instance.web.qweb;
7 // This widget makes sure that the scaling is disabled on mobile devices.
8 // Widgets that want to display fullscreen on mobile phone need to extend this
11 module.MobileWidget = instance.web.Widget.extend({
13 if(!$('#oe-mobilewidget-viewport').length){
14 $('head').append('<meta id="oe-mobilewidget-viewport" name="viewport" content="initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">');
19 $('#oe-mobilewidget-viewport').remove();
24 module.PickingEditorWidget = instance.web.Widget.extend({
25 template: 'PickingEditorWidget',
26 init: function(parent,options){
27 this._super(parent,options);
30 this.search_filter = "";
32 get_header: function(){
33 return this.getParent().get_header();
35 get_location: function(){
36 var model = this.getParent();
39 _.each(model.locations, function(loc){
40 locations.push({name: loc.complete_name, id: loc.id,});
44 get_logisticunit: function(){
45 var model = this.getParent();
48 _.each(model.uls, function(ulog){
49 ul.push({name: ulog.name, id: ulog.id,});
54 var model = this.getParent();
57 var pack_created = [];
58 _.each( model.packoplines, function(packopline){
61 if (packopline.product_id[1] !== undefined){ pack = packopline.package_id[1];}
62 if (packopline.product_qty == packopline.qty_done){ color = "success "; }
63 if (packopline.product_qty < packopline.qty_done){ color = "danger "; }
64 //also check that we don't have a line already existing for that package
65 if (packopline.result_package_id[1] !== undefined && $.inArray(packopline.result_package_id[0], pack_created) === -1){
66 var myPackage = $.grep(model.packages, function(e){ return e.id == packopline.result_package_id[0]; })[0];
68 cols: { product: packopline.result_package_id[1],
74 container: packopline.result_package_id[1],
75 container_id: undefined,
76 loc: packopline.location_id[1],
77 dest: packopline.location_dest_id[1],
78 id: packopline.result_package_id[0],
79 product_id: undefined,
82 processed: packopline.processed,
83 package_id: myPackage.id,
84 ul_id: myPackage.ul_id[0],
86 classes: ('success container_head ') + (packopline.processed === "true" ? 'processed hidden ':''),
88 pack_created.push(packopline.result_package_id[0]);
91 cols: { product: packopline.product_id[1] || packopline.package_id[1],
92 qty: packopline.product_qty,
93 rem: packopline.qty_done,
94 uom: packopline.product_uom_id[1],
95 lot: packopline.lot_id[1],
97 container: packopline.result_package_id[1],
98 container_id: packopline.result_package_id[0],
99 loc: packopline.location_id[1],
100 dest: packopline.location_dest_id[1],
102 product_id: packopline.product_id[0],
103 can_scan: packopline.result_package_id[1] === undefined ? true : false,
104 head_container: false,
105 processed: packopline.processed,
106 package_id: undefined,
109 classes: color + (packopline.result_package_id[1] !== undefined ? 'in_container_hidden ' : '') + (packopline.processed === "true" ? 'processed hidden ':''),
112 //sort element by things to do, then things done, then grouped by packages
113 group_by_container = _.groupBy(self.rows, function(row){
114 return row.cols.container;
117 if (group_by_container.undefined !== undefined){
118 group_by_container.undefined.sort(function(a,b){return (b.classes === '') - (a.classes === '');});
119 $.each(group_by_container.undefined, function(key, value){
120 sorted_row.push(value);
124 $.each(group_by_container, function(key, value){
125 if (key !== 'undefined'){
126 $.each(value, function(k,v){
134 renderElement: function(){
137 this.check_content_screen();
138 this.$('.js_pick_done').click(function(){ self.getParent().done(); });
139 this.$('.js_pick_print').click(function(){ self.getParent().print_picking(); });
140 this.$('.oe_pick_app_header').text(self.get_header());
141 this.$('.oe_searchbox').keyup(function(event){
142 self.on_searchbox($(this).val());
144 this.$('.js_putinpack').click(function(){ self.getParent().pack(); });
145 this.$('.js_drop_down').click(function(){ self.getParent().drop_down();});
146 this.$('.js_clear_search').click(function(){
147 self.on_searchbox('');
148 self.$('.oe_searchbox').val('');
150 this.$('.oe_searchbox').focus(function(){
151 self.getParent().barcode_scanner.disconnect();
153 this.$('.oe_searchbox').blur(function(){
154 self.getParent().barcode_scanner.connect(function(ean){
155 self.get_Parent().scan(ean);
158 this.$('#js_select').change(function(){
159 var selection = self.$('#js_select option:selected').attr('value');
160 if (selection === "ToDo"){
161 self.getParent().$('.js_pick_pack').removeClass('hidden')
162 self.getParent().$('.js_drop_down').removeClass('hidden')
163 self.$('.js_pack_op_line.processed').addClass('hidden')
164 self.$('.js_pack_op_line:not(.processed)').removeClass('hidden')
167 self.getParent().$('.js_pick_pack').addClass('hidden')
168 self.getParent().$('.js_drop_down').addClass('hidden')
169 self.$('.js_pack_op_line.processed').removeClass('hidden')
170 self.$('.js_pack_op_line:not(.processed)').addClass('hidden')
172 self.on_searchbox(self.search_filter);
174 this.$('.js_plus').click(function(){
175 var id = $(this).data('product-id');
176 var op_id = $(this).parents("[data-id]:first").data('id');
177 self.getParent().scan_product_id(id,true,op_id);
179 this.$('.js_minus').click(function(){
180 var id = $(this).data('product-id');
181 var op_id = $(this).parents("[data-id]:first").data('id');
182 self.getParent().scan_product_id(id,false,op_id);
184 this.$('.js_unfold').click(function(){
185 var op_id = $(this).parent().data('id');
186 var line = $(this).parent();
187 //select all js_pack_op_line with class in_container_hidden and correct container-id
188 select = self.$('.js_pack_op_line.in_container_hidden[data-container-id='+op_id+']')
189 if (select.length > 0){
191 line.addClass('warning');
192 select.removeClass('in_container_hidden');
193 select.addClass('in_container');
197 line.removeClass('warning');
198 select = self.$('.js_pack_op_line.in_container[data-container-id='+op_id+']')
199 select.removeClass('in_container');
200 select.addClass('in_container_hidden');
203 this.$('.js_create_lot').click(function(){
204 var op_id = $(this).parents("[data-id]:first").data('id');
205 var lot_name = false;
206 self.$('.js_lot_scan').val('');
207 var $lot_modal = self.$el.siblings('#js_LotChooseModal');
208 //disconnect scanner to prevent scanning a product in the back while dialog is open
209 self.getParent().barcode_scanner.disconnect();
212 $lot_modal.on('shown.bs.modal', function(){
213 self.$('.js_lot_scan').focus();
215 //reactivate scanner when dialog close
216 $lot_modal.on('hidden.bs.modal', function(){
217 self.getParent().barcode_scanner.connect(function(ean){
218 self.getParent().scan(ean);
221 self.$('.js_lot_scan').focus();
223 self.$('.js_validate_lot').click(function(){
224 //get content of input
225 var name = self.$('.js_lot_scan').val();
226 if (name.length !== 0){
229 $lot_modal.modal('hide');
230 //we need this here since it is not sure the hide event
231 //will be catch because we refresh the view after the create_lot call
232 self.getParent().barcode_scanner.connect(function(ean){
233 self.getParent().scan(ean);
235 self.getParent().create_lot(op_id, lot_name);
238 this.$('.js_delete_pack').click(function(){
239 var pack_id = $(this).parents("[data-id]:first").data('id');
240 self.getParent().delete_package_op(pack_id);
242 this.$('.js_print_pack').click(function(){
243 var pack_id = $(this).parents("[data-id]:first").data('id');
244 // $(this).parents("[data-id]:first").data('id')
245 self.getParent().print_package(pack_id);
247 this.$('.js_submit_value').submit(function(event){
248 var op_id = $(this).parents("[data-id]:first").data('id');
249 var value = parseFloat($("input", this).val());
251 self.getParent().set_operation_quantity(value, op_id);
253 $("input", this).val("");
256 this.$('.js_qty').focus(function(){
257 self.getParent().barcode_scanner.disconnect();
259 this.$('.js_qty').blur(function(){
260 var op_id = $(this).parents("[data-id]:first").data('id');
261 var value = parseFloat($(this).val());
263 self.getParent().set_operation_quantity(value, op_id);
266 self.getParent().barcode_scanner.connect(function(ean){
267 self.getParent().scan(ean);
270 this.$('.js_change_src').click(function(){
271 var op_id = $(this).parents("[data-id]:first").data('id');//data('op_id');
272 self.$('#js_loc_select').addClass('source');
273 self.$('#js_loc_select').data('op-id',op_id);
274 self.$el.siblings('#js_LocationChooseModal').modal();
276 this.$('.js_change_dst').click(function(){
277 var op_id = $(this).parents("[data-id]:first").data('id');
278 self.$('#js_loc_select').data('op-id',op_id);
279 self.$el.siblings('#js_LocationChooseModal').modal();
281 this.$('.js_pack_change_dst').click(function(){
282 var op_id = $(this).parents("[data-id]:first").data('id');
283 self.$('#js_loc_select').addClass('pack');
284 self.$('#js_loc_select').data('op-id',op_id);
285 self.$el.siblings('#js_LocationChooseModal').modal();
287 this.$('.js_validate_location').click(function(){
288 //get current selection
289 var select_dom_element = self.$('#js_loc_select');
290 var loc_id = self.$('#js_loc_select option:selected').data('loc-id');
292 var op_id = select_dom_element.data('op-id');
293 if (select_dom_element.hasClass('pack')){
294 select_dom_element.removeClass('source');
296 self.$('.js_pack_op_line[data-container-id='+op_id+']').each(function(){
297 op_ids.push($(this).data('id'));
301 else if (select_dom_element.hasClass('source')){
303 select_dom_element.removeClass('source');
305 if (loc_id === false){
307 self.$el.siblings('#js_LocationChooseModal').modal('hide');
310 self.$el.siblings('#js_LocationChooseModal').modal('hide');
311 self.getParent().change_location(op_id, parseInt(loc_id), src_dst);
315 this.$('.js_pack_configure').click(function(){
316 var pack_id = $(this).parents(".js_pack_op_line:first").data('package-id');
317 var ul_id = $(this).parents(".js_pack_op_line:first").data('ulid');
318 self.$('#js_packconf_select').val(ul_id);
319 self.$('#js_packconf_select').data('pack-id',pack_id);
320 self.$el.siblings('#js_PackConfModal').modal();
322 this.$('.js_validate_pack').click(function(){
323 //get current selection
324 var select_dom_element = self.$('#js_packconf_select');
325 var ul_id = self.$('#js_packconf_select option:selected').data('ul-id');
326 var pack_id = select_dom_element.data('pack-id');
327 self.$el.siblings('#js_PackConfModal').modal('hide');
329 self.getParent().set_package_pack(pack_id, ul_id);
330 $('.container_head[data-package-id="'+pack_id+'"]').data('ulid', ul_id);
334 //remove navigtion bar from default openerp GUI
335 $('td.navbar').html('<div></div>');
337 on_searchbox: function(query){
338 //hide line that has no location matching the query and highlight location that match the query
339 this.search_filter = query;
340 var processed = ".processed";
341 if (this.$('#js_select option:selected').attr('value') == "ToDo"){
342 processed = ":not(.processed)";
345 this.$('.js_loc:not(.js_loc:Contains('+query+'))').removeClass('info');
346 this.$('.js_loc:Contains('+query+')').addClass('info');
347 this.$('.js_pack_op_line'+processed+':not(.js_pack_op_line:has(.js_loc:Contains('+query+')))').addClass('hidden');
348 this.$('.js_pack_op_line'+processed+':has(.js_loc:Contains('+query+'))').removeClass('hidden');
350 //if no query specified, then show everything
352 this.$('.js_loc').removeClass('info');
353 this.$('.js_pack_op_line'+processed+'.hidden').removeClass('hidden');
355 this.check_content_screen();
357 check_content_screen: function(){
358 //get all visible element and if none has positive qty, disable put in pack and process button
360 var processed = this.$('.js_pack_op_line.processed');
361 var qties = this.$('.js_pack_op_line:not(.processed):not(.hidden) .js_qty').map(function(){return $(this).val()});
362 var container = this.$('.js_pack_op_line.container_head:not(.processed):not(.hidden)')
364 $.each(qties,function(index, value){
365 if (parseInt(value)>0){
371 if (container.length===0){
372 self.$('.js_drop_down').addClass('disabled');
375 self.$('.js_drop_down').removeClass('disabled');
377 self.$('.js_pick_pack').addClass('disabled');
378 if (processed.length === 0){
379 self.$('.js_pick_done').addClass('disabled');
382 self.$('.js_pick_done').removeClass('disabled');
386 self.$('.js_drop_down').removeClass('disabled');
387 self.$('.js_pick_pack').removeClass('disabled');
388 self.$('.js_pick_done').removeClass('disabled');
391 get_current_op_selection: function(ignore_container){
392 //get ids of visible on the screen
394 this.$('.js_pack_op_line:not(.processed):not(.js_pack_op_line.hidden):not(.container_head)').each(function(){
395 cur_id = $(this).data('id');
396 pack_op_ids.push(parseInt(cur_id));
398 //get list of element in this.rows where rem > 0 and container is empty is specified
400 _.each(this.rows, function(row){
401 if (row.cols.rem > 0 && (ignore_container || row.cols.container === undefined)){
402 list.push(row.cols.id);
405 //return only those visible with rem qty > 0 and container empty
406 return _.intersection(pack_op_ids, list);
408 remove_blink: function(){
409 this.$('.js_pack_op_line.blink_me').removeClass('blink_me');
411 blink: function(op_id){
412 this.$('.js_pack_op_line[data-id="'+op_id+'"]').addClass('blink_me');
414 check_done: function(){
415 var model = this.getParent();
418 _.each( model.packoplines, function(packopline){
419 if (packopline.processed === "false"){
426 get_visible_ids: function(){
428 var visible_op_ids = []
429 var op_ids = this.$('.js_pack_op_line:not(.processed):not(.hidden):not(.container_head):not(.in_container):not(.in_container_hidden)').map(function(){
430 return $(this).data('id');
432 $.each(op_ids, function(key, op_id){
433 visible_op_ids.push(parseInt(op_id));
435 return visible_op_ids;
439 module.PickingMenuWidget = module.MobileWidget.extend({
440 template: 'PickingMenuWidget',
441 init: function(parent, params){
442 this._super(parent,params);
444 $(window).bind('hashchange', function(){
445 var states = $.bbq.getState();
446 if (states.action === "stock.ui"){
448 type: 'ir.actions.client',
452 clear_breadcrumbs: true,
456 this.picking_types = [];
457 this.loaded = this.load();
458 this.scanning_type = 0;
459 this.barcode_scanner = new module.BarcodeScanner();
460 this.pickings_by_type = {};
461 this.pickings_by_id = {};
462 this.picking_search_string = "";
466 return new instance.web.Model('stock.picking.type').get_func('search_read')([],[])
467 .then(function(types){
468 self.picking_types = types;
469 for(var i = 0; i < types.length; i++){
470 self.pickings_by_type[types[i].id] = [];
472 self.pickings_by_type[0] = [];
474 return new instance.web.Model('stock.picking').call('search_read',[ [['state','in', ['assigned', 'partially_available']]], [] ], {context: new instance.web.CompoundContext()});
476 }).then(function(pickings){
477 self.pickings = pickings;
478 for(var i = 0; i < pickings.length; i++){
479 var picking = pickings[i];
480 self.pickings_by_type[picking.picking_type_id[0]].push(picking);
481 self.pickings_by_id[picking.id] = picking;
482 self.picking_search_string += '' + picking.id + ':' + (picking.name ? picking.name.toUpperCase(): '') + '\n';
487 renderElement: function(){
490 this.$('.js_pick_quit').click(function(){ self.quit(); });
491 this.$('.js_pick_scan').click(function(){ self.scan_picking($(this).data('id')); });
492 this.$('.js_pick_last').click(function(){ self.goto_last_picking_of_type($(this).data('id')); });
493 this.$('.oe_searchbox').keyup(function(event){
494 self.on_searchbox($(this).val());
496 //remove navigtion bar from default openerp GUI
497 $('td.navbar').html('<div></div>');
502 instance.webclient.set_content_full_screen(true);
503 this.barcode_scanner.connect(function(barcode){
504 self.on_scan(barcode);
506 this.loaded.then(function(){
507 self.renderElement();
510 goto_picking: function(picking_id){
511 $.bbq.pushState('#action=stock.ui&picking_id='+picking_id);
512 $(window).trigger('hashchange');
514 goto_last_picking_of_type: function(type_id){
515 $.bbq.pushState('#action=stock.ui&picking_type_id='+type_id);
516 $(window).trigger('hashchange');
518 search_picking: function(barcode){
520 var re = RegExp("([0-9]+):.*?"+barcode.toUpperCase(),"gi");
523 //avoid crash if a not supported char is given (like '\' or ')')
528 for(var i = 0; i < 100; i++){
529 r = re.exec(this.picking_search_string);
531 var picking = this.pickings_by_id[Number(r[1])];
533 results.push(picking);
541 on_scan: function(barcode){
543 for(var i = 0, len = this.pickings.length; i < len; i++){
544 var picking = this.pickings[i];
545 if(picking.name.toUpperCase() === $.trim(barcode.toUpperCase())){
546 this.goto_picking(picking.id);
550 this.$('.js_picking_not_found').removeClass('hidden');
552 clearTimeout(this.picking_not_found_timeout);
553 this.picking_not_found_timeout = setTimeout(function(){
554 self.$('.js_picking_not_found').addClass('hidden');
558 on_searchbox: function(query){
561 clearTimeout(this.searchbox_timeout);
562 this.searchbox_timout = setTimeout(function(){
564 self.$('.js_picking_not_found').addClass('hidden');
565 self.$('.js_picking_categories').addClass('hidden');
566 self.$('.js_picking_search_results').html(
567 QWeb.render('PickingSearchResults',{results:self.search_picking(query)})
569 self.$('.js_picking_search_results .oe_picking').click(function(){
570 self.goto_picking($(this).data('id'));
572 self.$('.js_picking_search_results').removeClass('hidden');
574 self.$('.js_title_label').removeClass('hidden');
575 self.$('.js_picking_categories').removeClass('hidden');
576 self.$('.js_picking_search_results').addClass('hidden');
581 return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_picking_type_form']], ['res_id']).pipe(function(res) {
582 window.location = '/web#action=' + res[0]['res_id'];
587 this.barcode_scanner.disconnect();
588 instance.webclient.set_content_full_screen(false);
591 openerp.web.client_actions.add('stock.menu', 'instance.stock.PickingMenuWidget');
593 module.PickingMainWidget = module.MobileWidget.extend({
594 template: 'PickingMainWidget',
595 init: function(parent,params){
596 this._super(parent,params);
598 $(window).bind('hashchange', function(){
599 var states = $.bbq.getState();
600 if (states.action === "stock.menu"){
602 type: 'ir.actions.client',
606 clear_breadcrumbs: true,
610 init_hash = $.bbq.getState();
611 this.picking_type_id = init_hash.picking_type_id ? init_hash.picking_type_id:0;
612 this.picking_id = init_hash.picking_id ? init_hash.picking_id:undefined;
615 this.packoplines = null;
616 this.selected_operation = { id: null, picking_id: null};
617 this.packages = null;
618 this.barcode_scanner = new module.BarcodeScanner();
622 this.loaded = this.load(this.picking_id);
624 this.loaded = this.load();
629 // load the picking data from the server. If picking_id is undefined, it will take the first picking
630 // belonging to the category
631 load: function(picking_id){
635 function load_picking_list(type_id){
636 var pickings = new $.Deferred();
637 new instance.web.Model('stock.picking')
638 .call('get_next_picking_for_ui',[{'default_picking_type_id':parseInt(type_id)}])
639 .then(function(picking_ids){
640 if(!picking_ids || picking_ids.length === 0){
641 (new instance.web.Dialog(self,{
642 title: _t('No Picking Available'),
649 }, _t('<p>We could not find a picking to display.</p>'))).open();
653 self.pickings = picking_ids;
654 pickings.resolve(picking_ids);
661 // if we have a specified picking id, we load that one, and we load the picking of the same type as the active list
663 var loaded_picking = new instance.web.Model('stock.picking')
664 .call('read',[[parseInt(picking_id)], [], new instance.web.CompoundContext()])
665 .then(function(picking){
666 self.picking = picking[0];
667 self.picking_type_id = picking[0].picking_type_id[0];
668 return load_picking_list(self.picking.picking_type_id[0]);
671 // if we don't have a specified picking id, we load the pickings belong to the specified type, and then we take
672 // the first one of that list as the active picking
673 var loaded_picking = new $.Deferred();
674 load_picking_list(self.picking_type_id)
676 return new instance.web.Model('stock.picking').call('read',[self.pickings[0],[], new instance.web.CompoundContext()]);
678 .then(function(picking){
679 self.picking = picking;
680 self.picking_type_id = picking.picking_type_id[0];
681 loaded_picking.resolve();
685 return loaded_picking.then(function(){
686 return new instance.web.Model('stock.location').call('search',[[['usage','=','internal']]]).then(function(locations_ids){
687 return new instance.web.Model('stock.location').call('read',[locations_ids, []]).then(function(locations){
688 self.locations = locations;
692 return new instance.web.Model('stock.picking').call('check_group_pack').then(function(result){
693 return self.show_pack = result;
696 return new instance.web.Model('stock.picking').call('check_group_lot').then(function(result){
697 return self.show_lot = result;
700 if (self.picking.pack_operation_exist === false){
701 self.picking.recompute_pack_op = false;
702 return new instance.web.Model('stock.picking').call('do_prepare_partial',[[self.picking.id]]);
705 return new instance.web.Model('stock.pack.operation').call('search',[[['picking_id','=',self.picking.id]]])
706 }).then(function(pack_op_ids){
707 return new instance.web.Model('stock.pack.operation').call('read',[pack_op_ids, [], new instance.web.CompoundContext()])
708 }).then(function(operations){
709 self.packoplines = operations;
710 var package_ids = [];
712 for(var i = 0; i < operations.length; i++){
713 if(!_.contains(package_ids,operations[i].result_package_id[0])){
714 if (operations[i].result_package_id[0]){
715 package_ids.push(operations[i].result_package_id[0]);
719 return new instance.web.Model('stock.quant.package').call('read',[package_ids, [], new instance.web.CompoundContext()])
720 }).then(function(packages){
721 self.packages = packages;
723 return new instance.web.Model('product.ul').call('search',[[]])
724 }).then(function(uls_ids){
725 return new instance.web.Model('product.ul').call('read',[uls_ids, []])
726 }).then(function(uls){
733 instance.webclient.set_content_full_screen(true);
734 this.barcode_scanner.connect(function(ean){
738 this.$('.js_pick_quit').click(function(){ self.quit(); });
739 this.$('.js_pick_prev').click(function(){ self.picking_prev(); });
740 this.$('.js_pick_next').click(function(){ self.picking_next(); });
741 this.$('.js_pick_menu').click(function(){ self.menu(); });
742 this.$('.js_reload_op').click(function(){ self.reload_pack_operation();});
744 $.when(this.loaded).done(function(){
745 self.picking_editor = new module.PickingEditorWidget(self);
746 self.picking_editor.replace(self.$('.oe_placeholder_picking_editor'));
748 if( self.picking.id === self.pickings[0]){
749 self.$('.js_pick_prev').addClass('disabled');
751 self.$('.js_pick_prev').removeClass('disabled');
754 if( self.picking.id === self.pickings[self.pickings.length-1] ){
755 self.$('.js_pick_next').addClass('disabled');
757 self.$('.js_pick_next').removeClass('disabled');
759 if (self.picking.recompute_pack_op){
760 self.$('.oe_reload_op').removeClass('hidden');
763 self.$('.oe_reload_op').addClass('hidden');
765 if (!self.show_pack){
766 self.$('.js_pick_pack').addClass('hidden');
769 self.$('.js_create_lot').addClass('hidden');
772 }).fail(function(error) {console.log(error);});
775 on_searchbox: function(query){
777 self.picking_editor.on_searchbox(query.toUpperCase());
779 // reloads the data from the provided picking and refresh the ui.
780 // (if no picking_id is provided, gets the first picking in the db)
781 refresh_ui: function(picking_id){
783 var remove_search_filter = "";
784 if (self.picking.id === picking_id){
785 remove_search_filter = self.$('.oe_searchbox').val();
787 return this.load(picking_id)
789 self.picking_editor.remove_blink();
790 self.picking_editor.renderElement();
791 if (!self.show_pack){
792 self.$('.js_pick_pack').addClass('hidden');
795 self.$('.js_create_lot').addClass('hidden');
797 if (self.picking.recompute_pack_op){
798 self.$('.oe_reload_op').removeClass('hidden');
801 self.$('.oe_reload_op').addClass('hidden');
804 if( self.picking.id === self.pickings[0]){
805 self.$('.js_pick_prev').addClass('disabled');
807 self.$('.js_pick_prev').removeClass('disabled');
810 if( self.picking.id === self.pickings[self.pickings.length-1] ){
811 self.$('.js_pick_next').addClass('disabled');
813 self.$('.js_pick_next').removeClass('disabled');
815 if (remove_search_filter === ""){
816 self.$('.oe_searchbox').val('');
817 self.on_searchbox('');
820 self.$('.oe_searchbox').val(remove_search_filter);
821 self.on_searchbox(remove_search_filter);
825 get_header: function(){
827 return this.picking.name;
833 $.bbq.pushState('#action=stock.menu');
834 $(window).trigger('hashchange');
836 scan: function(ean){ //scans a barcode, sends it to the server, then reload the ui
838 var product_visible_ids = this.picking_editor.get_visible_ids();
839 return new instance.web.Model('stock.picking')
840 .call('process_barcode_from_ui', [self.picking.id, ean, product_visible_ids])
841 .then(function(result){
842 if (result.filter_loc !== false){
843 //check if we have receive a location as answer
844 if (result.filter_loc !== undefined){
845 var modal_loc_hidden = self.$('#js_LocationChooseModal').attr('aria-hidden');
846 if (modal_loc_hidden === "false"){
847 var line = self.$('#js_LocationChooseModal .js_loc_option[data-loc-id='+result.filter_loc_id+']').attr('selected','selected');
850 self.$('.oe_searchbox').val(result.filter_loc);
851 self.on_searchbox(result.filter_loc);
855 if (result.operation_id !== false){
856 self.refresh_ui(self.picking.id).then(function(){
857 return self.picking_editor.blink(result.operation_id);
862 scan_product_id: function(product_id,increment,op_id){ //performs the same operation as a scan, but with product id instead
864 return new instance.web.Model('stock.picking')
865 .call('process_product_id_from_ui', [self.picking.id, product_id, op_id, increment])
866 .then(function(result){
867 return self.refresh_ui(self.picking.id);
872 var pack_op_ids = self.picking_editor.get_current_op_selection(false);
873 if (pack_op_ids.length !== 0){
874 return new instance.web.Model('stock.picking')
875 .call('action_pack',[[[self.picking.id]], pack_op_ids])
877 instance.session.user_context.current_package_id = false;
878 return self.refresh_ui(self.picking.id);
882 drop_down: function(){
884 var pack_op_ids = self.picking_editor.get_current_op_selection(true);
885 if (pack_op_ids.length !== 0){
886 return new instance.web.Model('stock.pack.operation')
887 .call('action_drop_down', [pack_op_ids])
889 return self.refresh_ui(self.picking.id).then(function(){
890 if (self.picking_editor.check_done()){
899 return new instance.web.Model('stock.picking')
900 .call('action_done_from_ui',[self.picking.id, {'default_picking_type_id': self.picking_type_id}])
901 .then(function(new_picking_ids){
902 if (new_picking_ids){
903 return self.refresh_ui(new_picking_ids[0]);
910 create_lot: function(op_id, lot_name){
912 return new instance.web.Model('stock.pack.operation')
913 .call('create_and_assign_lot',[parseInt(op_id), lot_name])
915 return self.refresh_ui(self.picking.id);
918 change_location: function(op_id, loc_id, is_src_dst){
920 var vals = {'location_dest_id': loc_id};
922 vals = {'location_id': loc_id};
924 return new instance.web.Model('stock.pack.operation')
925 .call('write',[op_id, vals])
927 return self.refresh_ui(self.picking.id);
930 print_package: function(package_id){
932 return new instance.web.Model('stock.quant.package')
933 .call('action_print',[[package_id]])
934 .then(function(action){
935 return self.do_action(action);
938 print_picking: function(){
940 return new instance.web.Model('stock.picking.type').call('read', [[self.picking_type_id], ['code'], new instance.web.CompoundContext()])
941 .then(function(pick_type){
942 return new instance.web.Model('stock.picking').call('do_print_picking',[[self.picking.id]])
943 .then(function(action){
944 return self.do_action(action);
948 picking_next: function(){
949 for(var i = 0; i < this.pickings.length; i++){
950 if(this.pickings[i] === this.picking.id){
951 if(i < this.pickings.length -1){
952 $.bbq.pushState('picking_id='+this.pickings[i+1]);
953 this.refresh_ui(this.pickings[i+1]);
959 picking_prev: function(){
960 for(var i = 0; i < this.pickings.length; i++){
961 if(this.pickings[i] === this.picking.id){
963 $.bbq.pushState('picking_id='+this.pickings[i-1]);
964 this.refresh_ui(this.pickings[i-1]);
970 delete_package_op: function(pack_id){
972 return new instance.web.Model('stock.pack.operation').call('search', [[['result_package_id', '=', pack_id]]])
973 .then(function(op_ids) {
974 return new instance.web.Model('stock.pack.operation').call('write', [op_ids, {'result_package_id':false}])
976 return self.refresh_ui(self.picking.id);
980 set_operation_quantity: function(quantity, op_id){
983 return new instance.web.Model('stock.pack.operation')
984 .call('write',[[op_id],{'qty_done': quantity }])
986 self.refresh_ui(self.picking.id);
991 set_package_pack: function(package_id, pack){
993 return new instance.web.Model('stock.quant.package')
994 .call('write',[[package_id],{'ul_id': pack }]);
997 reload_pack_operation: function(){
999 return new instance.web.Model('stock.picking')
1000 .call('do_prepare_partial',[[self.picking.id]])
1002 self.refresh_ui(self.picking.id);
1007 return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_picking_type_form']], ['res_id']).pipe(function(res) {
1008 window.location = '/web#action=' + res[0]['res_id'];
1011 destroy: function(){
1013 // this.disconnect_numpad();
1014 this.barcode_scanner.disconnect();
1015 instance.webclient.set_content_full_screen(false);
1018 openerp.web.client_actions.add('stock.ui', 'instance.stock.PickingMainWidget');
1020 module.BarcodeScanner = instance.web.Class.extend({
1021 connect: function(callback){
1026 this.handler = function(e){
1027 if(e.which === 13){ //ignore returns
1031 if(timeStamp + 50 < new Date().getTime()){
1035 timeStamp = new Date().getTime();
1036 clearTimeout(timeout);
1038 code += String.fromCharCode(e.which);
1040 timeout = setTimeout(function(){
1041 if(code.length >= 3){
1048 $('body').on('keypress', this.handler);
1051 disconnect: function(){
1052 $('body').off('keypress', this.handler);
1058 openerp.stock = function(openerp) {
1059 openerp.stock = openerp.stock || {};
1060 openerp_picking_widgets(openerp);