From 0d247969154f43cadc6ccfcfb6d053b2d7f80669 Mon Sep 17 00:00:00 2001 From: Cedric Snauwaert Date: Mon, 24 Mar 2014 11:46:21 +0100 Subject: [PATCH] [FIX]barcode interface: take into account location filter when scanning a product bzr revid: csn@openerp.com-20140324104621-xfah53qqwg06qcqe --- addons/stock/controllers/main.py | 2 +- addons/stock/static/src/js/widgets.js | 40 ++++++++++++++++++------- addons/stock/static/src/xml/picking.xml | 4 +-- addons/stock/stock.py | 31 ++++++++++++------- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/addons/stock/controllers/main.py b/addons/stock/controllers/main.py index 56a2fbaf44f..e140c608a0f 100644 --- a/addons/stock/controllers/main.py +++ b/addons/stock/controllers/main.py @@ -50,7 +50,7 @@ html_template = """ class BarcodeController(http.Controller): @http.route(['/barcode/web/','/barcode/web/','/barcode/web//'], 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') diff --git a/addons/stock/static/src/js/widgets.js b/addons/stock/static/src/js/widgets.js index c450a100458..5e407489d41 100644 --- a/addons/stock/static/src/js/widgets.js +++ b/addons/stock/static/src/js/widgets.js @@ -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); }); diff --git a/addons/stock/static/src/xml/picking.xml b/addons/stock/static/src/xml/picking.xml index ac2eaca4a92..cb58236e49d 100644 --- a/addons/stock/static/src/xml/picking.xml +++ b/addons/stock/static/src/xml/picking.xml @@ -136,7 +136,7 @@ - +
@@ -146,7 +146,7 @@
- + diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 255bdca9e9a..a6470f6a9e4 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -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: