[FIX]barcode interface: take into account location filter when scanning a product
authorCedric Snauwaert <csn@openerp.com>
Mon, 24 Mar 2014 10:46:21 +0000 (11:46 +0100)
committerCedric Snauwaert <csn@openerp.com>
Mon, 24 Mar 2014 10:46:21 +0000 (11:46 +0100)
bzr revid: csn@openerp.com-20140324104621-xfah53qqwg06qcqe

addons/stock/controllers/main.py
addons/stock/static/src/js/widgets.js
addons/stock/static/src/xml/picking.xml
addons/stock/stock.py

index 56a2fba..e140c60 100644 (file)
@@ -50,7 +50,7 @@ html_template = """<!DOCTYPE html>
 class BarcodeController(http.Controller):
 
     @http.route(['/barcode/web/','/barcode/web/<int:picking_type_id>','/barcode/web/<int:picking_type_id>/<int:picking_id>'], type='http', auth='user')
-    def a(self, debug=False, **k):
+    def a(self, debug=True, **k):
         if not request.session.uid:
             return http.local_redirect('/web/login?redirect=/barcode/web')
 
index c450a10..5e40748 100644 (file)
@@ -53,7 +53,10 @@ function openerp_picking_widgets(instance){
             var pack_created = [];
             _.each( model.packoplines, function(packopline){
                     var pack = undefined;
+                    var color = "";
                     if (packopline.product_id[1] !== undefined){ pack = packopline.package_id[1];}
+                    if (packopline.product_qty == packopline.qty_done){ color = "success "; }
+                    if (packopline.product_qty < packopline.qty_done){ color = "danger "; }
                     //also check that we don't have a line already existing for that package
                     if (packopline.result_package_id[1] !== undefined && $.inArray(packopline.result_package_id[0], pack_created) === -1){
                         self.rows.push({
@@ -94,7 +97,7 @@ function openerp_picking_widgets(instance){
                                 head_container: false,
                                 processed: packopline.processed,
                         },
-                        classes: ((packopline.product_qty <= packopline.qty_done) ? 'success ' : '') + (packopline.result_package_id[1] !== undefined ? 'in_container_hidden ' : '') + (packopline.processed === "true" ? 'processed hidden ':''),
+                        classes: color + (packopline.result_package_id[1] !== undefined ? 'in_container_hidden ' : '') + (packopline.processed === "true" ? 'processed hidden ':''),
                     });
             });
             //sort element by things to do, then things done, then grouped by packages
@@ -153,11 +156,13 @@ function openerp_picking_widgets(instance){
             });
             this.$('.js_plus').click(function(){
                 var id = $(this).data('product-id');
-                self.getParent().scan_product_id(id,true);
+                var op_id = $(this).parents("[data-id]:first").data('id');
+                self.getParent().scan_product_id(id,true,op_id);
             });
             this.$('.js_minus').click(function(){
                 var id = $(this).data('product-id');
-                self.getParent().scan_product_id(id,false);
+                var op_id = $(this).parents("[data-id]:first").data('id');
+                self.getParent().scan_product_id(id,false,op_id);
             });
             this.$('.js_unfold').click(function(){
                 var op_id = $(this).parent().data('id');
@@ -329,7 +334,18 @@ function openerp_picking_widgets(instance){
                 }
             });
             return done;
-        }
+        },
+        get_visible_ids: function(){
+            var self = this;
+            var visible_op_ids = []
+            var op_ids = this.$('.js_pack_op_line:not(.processed):not(.hidden):not(.container_head):not(.in_container):not(.in_container_hidden)').map(function(){
+                return $(this).data('id');
+            });
+            $.each(op_ids, function(key, op_id){
+                visible_op_ids.push(parseInt(op_id));
+            });
+            return visible_op_ids;
+        },
     });
 
     module.PickingMenuWidget = module.MobileWidget.extend({
@@ -643,9 +659,9 @@ function openerp_picking_widgets(instance){
         // (if no picking_id is provided, gets the first picking in the db)
         refresh_ui: function(picking_id){
             var self = this;
-            var remove_search_filter = true;
+            var remove_search_filter = "";
             if (self.picking.id === picking_id){
-                remove_search_filter = false;
+                remove_search_filter = self.$('.oe_searchbox').val();
             }
             return this.load(picking_id)
                 .then(function(){
@@ -663,12 +679,13 @@ function openerp_picking_widgets(instance){
                     }else{
                         self.$('.js_pick_next').removeClass('disabled');
                     }
-                    if (remove_search_filter){
+                    if (remove_search_filter === ""){
                         self.$('.oe_searchbox').val('');
                         self.on_searchbox('');
                     }
                     else{
-                        self.on_searchbox(self.$('.oe_searchbox').val());
+                        self.$('.oe_searchbox').val(remove_search_filter);
+                        self.on_searchbox(remove_search_filter);
                     }
                 });
         },
@@ -691,8 +708,9 @@ function openerp_picking_widgets(instance){
         },
         scan: function(ean){ //scans a barcode, sends it to the server, then reload the ui
             var self = this;
+            var product_visible_ids = this.picking_editor.get_visible_ids();
             new instance.web.Model('stock.picking')
-                .call('process_barcode_from_ui', [self.picking.id, ean])
+                .call('process_barcode_from_ui', [self.picking.id, ean, product_visible_ids])
                 .then(function(result){
                     if (result.filter_loc !== false){
                         //check if we have receive a location as answer
@@ -714,10 +732,10 @@ function openerp_picking_widgets(instance){
                     }
                 });
         },
-        scan_product_id: function(product_id,increment){ //performs the same operation as a scan, but with product id instead
+        scan_product_id: function(product_id,increment,op_id){ //performs the same operation as a scan, but with product id instead
             var self = this;
             new instance.web.Model('stock.picking')
-                .call('process_product_id_from_ui', [self.picking.id, product_id, increment])
+                .call('process_product_id_from_ui', [self.picking.id, product_id, op_id, increment])
                 .then(function(result){
                     return self.refresh_ui(self.picking.id);
                 });
index ac2eaca..cb58236 100644 (file)
                                 <t t-esc="row.cols.product" /> 
                             </td>
                             <td class='text-center js_row_qty'>
-                                <t t-if="row.cols.qty &amp;&amp; row.cols.processed == 'false' &amp;&amp; !row.cols.container">
+                                <t t-if="row.cols.processed == 'false' &amp;&amp; !row.cols.container">
                                     <div class="input-group">
                                         <span class="input-group-addon js_minus" t-att-data-product-id='row.cols.product_id'><a href="#"><i class="fa fa-minus"></i></a></span>
                                         <form class="js_submit_value">
                                         <span class="input-group-addon js_plus" t-att-data-product-id='row.cols.product_id'><a href="#"><i class="fa fa-plus"></i></a></span>
                                     </div>
                                 </t>
-                                <t t-if="row.cols.qty &amp;&amp; (row.cols.processed == 'true' || row.cols.container)">
+                                <t t-if="(row.cols.processed == 'true' || row.cols.container)">
                                     <t t-esc="row.cols.rem" />
                                 </t>
                             </td>
index 255bdca..a6470f6 100644 (file)
@@ -1257,10 +1257,10 @@ class stock_picking(osv.osv):
                 stock_operation_obj.write(cr, uid, pack_operation_ids, {'result_package_id': package_id}, context=context)
         return True
 
-    def process_product_id_from_ui(self, cr, uid, picking_id, product_id, increment=True, context=None):
-        return self.pool.get('stock.pack.operation')._search_and_increment(cr, uid, picking_id, [('product_id', '=', product_id)], increment=increment, context=context)
+    def process_product_id_from_ui(self, cr, uid, picking_id, product_id, op_id, increment=True, context=None):
+        return self.pool.get('stock.pack.operation')._search_and_increment(cr, uid, picking_id, [('product_id', '=', product_id),('id', '=', op_id)], increment=increment, context=context)
 
-    def process_barcode_from_ui(self, cr, uid, picking_id, barcode_str, context=None):
+    def process_barcode_from_ui(self, cr, uid, picking_id, barcode_str, visible_op_ids, context=None):
         '''This function is called each time there barcode scanner reads an input'''
         lot_obj = self.pool.get('stock.production.lot')
         package_obj = self.pool.get('stock.quant.package')
@@ -1279,20 +1279,20 @@ class stock_picking(osv.osv):
         #check if the barcode correspond to a product
         matching_product_ids = product_obj.search(cr, uid, ['|', ('ean13', '=', barcode_str), ('default_code', '=', barcode_str)], context=context)
         if matching_product_ids:
-            op_id = self.process_product_id_from_ui(cr, uid, picking_id, matching_product_ids[0], context=context)
+            op_id = stock_operation_obj._search_and_increment(cr, uid, picking_id, [('product_id', '=', matching_product_ids[0])], filter_visible=True, visible_op_ids=visible_op_ids, increment=True, context=context)
             answer['operation_id'] = op_id
             return answer
         #check if the barcode correspond to a lot
         matching_lot_ids = lot_obj.search(cr, uid, [('name', '=', barcode_str)], context=context)
         if matching_lot_ids:
             lot = lot_obj.browse(cr, uid, matching_lot_ids[0], context=context)
-            op_id = stock_operation_obj._search_and_increment(cr, uid, picking_id, [('product_id', '=', lot.product_id.id), ('lot_id', '=', lot.id)], increment=True, context=context)
+            op_id = stock_operation_obj._search_and_increment(cr, uid, picking_id, [('product_id', '=', lot.product_id.id), ('lot_id', '=', lot.id)], filter_visible=True, visible_op_ids=visible_op_ids, increment=True, context=context)
             answer['operation_id'] = op_id
             return answer
         #check if the barcode correspond to a package
         matching_package_ids = package_obj.search(cr, uid, [('name', '=', barcode_str)], context=context)
         if matching_package_ids:
-            op_id = stock_operation_obj._search_and_increment(cr, uid, picking_id, [('package_id', '=', matching_package_ids[0])], increment=True, context=context)
+            op_id = stock_operation_obj._search_and_increment(cr, uid, picking_id, [('package_id', '=', matching_package_ids[0])], filter_visible=True, visible_op_ids=visible_op_ids, increment=True, context=context)
             answer['operation_id'] = op_id
             return answer
         return answer
@@ -3668,7 +3668,7 @@ class stock_pack_operation(osv.osv):
 
 
     #TODO: this function can be refactored
-    def _search_and_increment(self, cr, uid, picking_id, domain, increment=True, context=None):
+    def _search_and_increment(self, cr, uid, picking_id, domain, filter_visible=False ,visible_op_ids=False, increment=True, context=None):
         '''Search for an operation with given 'domain' in a picking, if it exists increment the qty (+1) otherwise create it
 
         :param domain: list of tuple directly reusable as a domain
@@ -3686,20 +3686,31 @@ class stock_pack_operation(osv.osv):
         #if current_package_id is given in the context, we increase the number of items in this package
         package_clause = [('result_package_id', '=', context.get('current_package_id', False))]
         existing_operation_ids = self.search(cr, uid, [('picking_id', '=', picking_id)] + domain + package_clause, context=context)
+        todo_operation_ids = []
         if existing_operation_ids:
+            if filter_visible:
+                todo_operation_ids = [val for val in existing_operation_ids if val in visible_op_ids]
+            else:
+                todo_operation_ids = existing_operation_ids
+        if todo_operation_ids:
             #existing operation found for the given domain and picking => increment its quantity
-            operation_id = existing_operation_ids[0]
-            qty = self.browse(cr, uid, operation_id, context=context).qty_done
+            operation_id = todo_operation_ids[0]
+            op_obj = self.browse(cr, uid, operation_id, context=context)
+            qty = op_obj.qty_done
             if increment:
                 qty += 1
             else:
                 qty -= 1 if qty >= 1 else 0
+                if qty == 0 and op_obj.product_qty == 0:
+                    #we have a line with 0 qty set, so delete it
+                    self.unlink(cr, uid, [operation_id], context=context)
+                    return False
             self.write(cr, uid, [operation_id], {'qty_done': qty}, context=context)
         else:
             #no existing operation found for the given domain and picking => create a new one
             values = {
                 'picking_id': picking_id,
-                'product_qty': 1,
+                'product_qty': 0,
                 'qty_done': 1,
             }
             for key in domain: