summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorQuentin (OpenERP) <qdp-launchpad@openerp.com>2013-11-20 11:42:33 +0100
committerQuentin (OpenERP) <qdp-launchpad@openerp.com>2013-11-20 11:42:33 +0100
commitd9ebd0600a73f9949c274c170bab2aea67fdc019 (patch)
tree149bbc832d15a5ea2f281f925e4b250ed73d3fda /addons
parentad8bec7759c20406ebe0329701d2bbdcafcef162 (diff)
[FIX] stock: barcode scanner UI fixed
bzr revid: qdp-launchpad@openerp.com-20131120104233-5bis81r0ii1kumpw
Diffstat (limited to 'addons')
-rw-r--r--addons/stock/static/src/js/widgets.js8
-rw-r--r--addons/stock/stock.py128
2 files changed, 61 insertions, 75 deletions
diff --git a/addons/stock/static/src/js/widgets.js b/addons/stock/static/src/js/widgets.js
index 6fb68a6143c..c015bca7c00 100644
--- a/addons/stock/static/src/js/widgets.js
+++ b/addons/stock/static/src/js/widgets.js
@@ -314,7 +314,7 @@ function openerp_picking_widgets(instance){
var pickings = new $.Deferred();
new instance.web.Model('stock.picking')
- .call('get_picking_for_packing_ui',[{'default_picking_type_id':type_id}])
+ .call('get_next_picking_for_ui',[{'default_picking_type_id':type_id}])
.then(function(picking_ids){
if(!picking_ids || picking_ids.length === 0){
(new instance.web.Dialog(self,{
@@ -487,7 +487,7 @@ function openerp_picking_widgets(instance){
scan: function(ean){ //scans a barcode, sends it to the server, then reload the ui
var self = this;
new instance.web.Model('stock.picking')
- .call('get_barcode_and_return_todo_stuff', [self.picking.id, ean])
+ .call('process_barcode_from_ui', [self.picking.id, ean])
.then(function(){
self.reset_selected_operation();
return self.refresh_ui(self.picking.id);
@@ -496,7 +496,7 @@ function openerp_picking_widgets(instance){
scan_product_id: function(product_id){ //performs the same operation as a scan, but with product id instead
var self = this;
new instance.web.Model('stock.picking')
- .call('get_product_id_and_return_todo_stuff', [self.picking.id, product_id])
+ .call('process_product_id_from_ui', [self.picking.id, product_id])
.then(function(){
self.reset_selected_operation();
return self.refresh_ui(self.picking.id);
@@ -515,7 +515,7 @@ function openerp_picking_widgets(instance){
done: function(){
var self = this;
new instance.web.Model('stock.picking')
- .call('action_done_from_packing_ui',[self.picking.id])
+ .call('action_done_from_ui',[self.picking.id])
.then(function(new_picking_id){
return self.refresh_ui(new_picking_id);
});
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 2918fa57387..a872ef54415 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -797,13 +797,13 @@ class stock_picking(osv.osv):
self.pool.get('stock.move').force_assign(cr, uid, move_ids, context=context)
return True
- def cancel_assign(self, cr, uid, ids, *args):
+ def cancel_assign(self, cr, uid, ids, context=None):
""" Cancels picking and moves.
@return: True
"""
- for pick in self.browse(cr, uid, ids):
+ for pick in self.browse(cr, uid, ids, context=context):
move_ids = [x.id for x in pick.move_lines]
- self.pool.get('stock.move').cancel_assign(cr, uid, move_ids)
+ self.pool.get('stock.move').cancel_assign(cr, uid, move_ids, context=context)
return True
def action_cancel(self, cr, uid, ids, context=None):
@@ -832,23 +832,24 @@ class stock_picking(osv.osv):
return True
def unlink(self, cr, uid, ids, context=None):
+ #on picking deletion, cancel its move then unlink them too
move_obj = self.pool.get('stock.move')
context = context or {}
for pick in self.browse(cr, uid, ids, context=context):
- ids2 = [move.id for move in pick.move_lines]
- move_obj.action_cancel(cr, uid, ids2, context=context)
- move_obj.unlink(cr, uid, ids2, context=context)
+ move_ids = [move.id for move in pick.move_lines]
+ move_obj.action_cancel(cr, uid, move_ids, context=context)
+ move_obj.unlink(cr, uid, move_ids, context=context)
return super(stock_picking, self).unlink(cr, uid, ids, context=context)
def write(self, cr, uid, ids, vals, context=None):
res = super(stock_picking, self).write(cr, uid, ids, vals, context=context)
+ #if we changed the move lines or the pack operations, we need to recompute the remaining quantities of both
if 'move_lines' in vals or 'pack_operation_ids' in vals:
self.do_recompute_remaining_quantities(cr, uid, ids, context=context)
return res
def _create_backorder(self, cr, uid, picking, backorder_moves=[], context=None):
- """
- Move all non-done lines into a new backorder picking. If the key 'do_only_split' is given in the context, then move all lines not in context.get('split', []) instead of all non-done lines.
+ """ Move all non-done lines into a new backorder picking. If the key 'do_only_split' is given in the context, then move all lines not in context.get('split', []) instead of all non-done lines.
"""
if not backorder_moves:
backorder_moves = picking.move_lines
@@ -874,6 +875,7 @@ class stock_picking(osv.osv):
return False
def do_prepare_partial(self, cr, uid, picking_ids, context=None):
+ #TODO refactore me
context = context or {}
pack_operation_obj = self.pool.get('stock.pack.operation')
pack_obj = self.pool.get("stock.quant.package")
@@ -979,7 +981,8 @@ class stock_picking(osv.osv):
_create_link_for_product(product_id, qty)
def _create_extra_moves(self, cr, uid, picking, context=None):
- '''This function creates move lines on a picking, at the time of do_transfer, based on unexpected product transfers (or exceeding quantities) found in the pack operations
+ '''This function creates move lines on a picking, at the time of do_transfer, based on
+ unexpected product transfers (or exceeding quantities) found in the pack operations.
'''
move_obj = self.pool.get('stock.move')
operation_obj = self.pool.get('stock.pack.operation')
@@ -1001,6 +1004,7 @@ class stock_picking(osv.osv):
self.do_recompute_remaining_quantities(cr, uid, [picking.id], context=context)
def rereserve_quants(self, cr, uid, picking, move_ids=[], context=None):
+ """ Unreserve quants then try to reassign quants."""
stock_move_obj = self.pool.get('stock.move')
if not move_ids:
self.do_unreserve(cr, uid, [picking.id], context=context)
@@ -1055,26 +1059,31 @@ class stock_picking(osv.osv):
return True
def do_split(self, cr, uid, picking_ids, context=None):
- """
- just split the picking without making it 'done'
- """
+ """ just split the picking (create a backorder) without making it 'done' """
if context is None:
context = {}
ctx = context.copy()
ctx['do_only_split'] = True
- self.do_transfer(cr, uid, picking_ids, context=ctx)
- return True
+ return self.do_transfer(cr, uid, picking_ids, context=ctx)
- # Methods for the barcode UI
- def get_picking_for_packing_ui(self, cr, uid, context=None):
- return self.search(cr, uid, [('state', 'in', ('confirmed', 'assigned')), ('picking_type_id', '=', context.get('default_picking_type_id'))], context=context)
-
- def action_done_from_packing_ui(self, cr, uid, picking_id, only_split_lines=False, context=None):
- self.do_transfer(cr, uid, picking_id, only_split_lines, context=context)
+ def get_next_picking_for_ui(self, cr, uid, context=None):
+ """ returns the next pickings to process. Used in the barcode scanner UI"""
+ if context is None:
+ context = {}
+ domain = [('state', 'in', ('confirmed', 'assigned'))]
+ if context.get('default_picking_type_id'):
+ domain.append(('picking_type_id', '=', context['default_picking_type_id']))
+ return self.search(cr, uid, domain, context=context)
+
+ def action_done_from_ui(self, cr, uid, picking_id, context=None):
+ """ called when button 'done' in pused in the barcode scanner UI """
+ self.do_transfer(cr, uid, [picking_id], context=context)
#return id of next picking to work on
- return self.get_picking_for_packing_ui(cr, uid, context=context)
+ return self.get_next_picking_for_ui(cr, uid, context=context)
def action_pack(self, cr, uid, picking_ids, context=None):
+ """ Create a package with the current pack_operation_ids of the picking that aren't yet in a pack.
+ Used in the barcode scanner UI and the normal interface as well. """
stock_operation_obj = self.pool.get('stock.pack.operation')
package_obj = self.pool.get('stock.quant.package')
for picking_id in picking_ids:
@@ -1084,51 +1093,30 @@ class stock_picking(osv.osv):
stock_operation_obj.write(cr, uid, operation_ids, {'result_package_id': package_id}, context=context)
return True
- #TODO: commented because quant_id has been removed from pack operation object
- #def _deal_with_quants(self, cr, uid, picking_id, quant_ids, context=None):
- # stock_operation_obj = self.pool.get('stock.pack.operation')
- # todo_on_moves = []
- # todo_on_operations = []
- # for quant in self.pool.get('stock.quant').browse(cr, uid, quant_ids, context=context):
- # tmp_moves, tmp_operations = stock_operation_obj._search_and_increment(cr, uid, picking_id, ('quant_id', '=', quant.id), context=context)
- # todo_on_moves += tmp_moves
- # todo_on_operations += tmp_operations
- # return todo_on_moves, todo_on_operations
-
- def get_barcode_and_return_todo_stuff(self, cr, uid, picking_id, barcode_str, context=None):
+ def process_product_id_from_ui(self, cr, uid, picking_id, product_id, context=None):
+ return self.pool.get('stock.pack.operation')._search_and_increment(cr, uid, picking_id, [('product_id', '=', product_id)], context=context)
+
+ def process_barcode_from_ui(self, cr, uid, picking_id, barcode_str, context=None):
'''This function is called each time there barcode scanner reads an input'''
- #TODO: better error messages handling => why not real raised errors
- quant_obj = self.pool.get('stock.quant')
+ lot_obj = self.pool.get('stock.production.lot')
package_obj = self.pool.get('stock.quant.package')
product_obj = self.pool.get('product.product')
stock_operation_obj = self.pool.get('stock.pack.operation')
- error_msg = ''
- todo_on_moves = []
- todo_on_operations = []
#check if the barcode correspond to a product
matching_product_ids = product_obj.search(cr, uid, [('ean13', '=', barcode_str)], context=context)
if matching_product_ids:
- todo_on_moves, todo_on_operations = stock_operation_obj._search_and_increment(cr, uid, picking_id, ('product_id', '=', matching_product_ids[0]), context=context)
+ self.process_product_id_from_ui(cr, uid, picking_id, matching_product_ids[0], context=context)
- #TODO: if barcode is a lot instead of a quant => replace next lines
- ##check if the barcode correspond to a quant
- #matching_quant_ids = quant_obj.search(cr, uid, [('name', '=', barcode_str)], context=context) # TODO need the location clause
- #if matching_quant_ids:
- # todo_on_moves, todo_on_operations = self._deal_with_quants(cr, uid, picking_id, [matching_quant_ids[0]], context=context)
+ #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)
+ stock_operation_obj._search_and_increment(cr, uid, picking_id, [('product_id', '=', lot.product_id.id), ('lot_id', '=', lot.id)], context=context)
#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:
- included_package_ids = package_obj.search(cr, uid, [('parent_id', 'child_of', matching_package_ids[0])], context=context)
- included_quant_ids = quant_obj.search(cr, uid, [('package_id', 'in', included_package_ids)], context=context)
- todo_on_moves, todo_on_operations = self._deal_with_quants(cr, uid, picking_id, included_quant_ids, context=context)
- #write remaining qty on stock.move, to ease the treatment server side
- for todo in todo_on_moves:
- if todo[0] == 1:
- self.pool.get('stock.move').write(cr, uid, todo[1], todo[2], context=context)
- elif todo[0] == 0:
- self.pool.get('stock.move').create(cr, uid, todo[2], context=context)
- return {'warnings': error_msg, 'moves_to_update': todo_on_moves, 'operations_to_update': todo_on_operations}
+ stock_operation_obj._search_and_increment(cr, uid, picking_id, [('package_id', '=', matching_package_ids[0])], context=context)
class stock_production_lot(osv.osv):
@@ -3179,10 +3167,10 @@ class stock_pack_operation(osv.osv):
#TODO: this function can be refactored
- def _search_and_increment(self, cr, uid, picking_id, key, context=None):
- '''Search for an operation on an existing key in a picking, if it exists increment the qty (+1) otherwise create it
+ def _search_and_increment(self, cr, uid, picking_id, domain, context=None):
+ '''Search for an operation with given 'domain' in a picking, if it exists increment the qty (+1) otherwise create it
- :param key: tuple directly reusable in a domain
+ :param domain: list of tuple directly reusable as a domain
context can receive a key 'current_package_id' with the package to consider for this operation
returns True
@@ -3191,35 +3179,33 @@ class stock_pack_operation(osv.osv):
(1, ID, { values }) update the linked record with id = ID (write *values* on it)
(2, ID) remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well)
'''
- quant_obj = self.pool.get('stock.quant')
if context is None:
context = {}
#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), key] + package_clause, context=context)
+ existing_operation_ids = self.search(cr, uid, [('picking_id', '=', picking_id)] + domain + package_clause, context=context)
if existing_operation_ids:
- #existing operation found for the given key and picking => increment its quantity
+ #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).product_qty + 1
self.write(cr, uid, operation_id, {'product_qty': qty}, context=context)
else:
- #no existing operation found for the given key and picking => create a new one
- var_name, dummy, value = key
- uom_id = False
- if var_name == 'product_id':
- uom_id = self.pool.get('product.product').browse(cr, uid, value, context=context).uom_id.id
- elif var_name == 'quant_id':
- quant = quant_obj.browse(cr, uid, value, context=context)
- uom_id = quant.product_id.uom_id.id
+ #no existing operation found for the given domain and picking => create a new one
values = {
'picking_id': picking_id,
- var_name: value,
'product_qty': 1,
- 'product_uom_id': uom_id,
}
+ for key in domain:
+ var_name, dummy, value = key
+ uom_id = False
+ if var_name == 'product_id':
+ uom_id = self.pool.get('product.product').browse(cr, uid, value, context=context).uom_id.id
+ update_dict = {var_name: value}
+ if uom_id:
+ update_dict['product_uom_id'] = uom_id
+ values.update(update_dict)
operation_id = self.create(cr, uid, values, context=context)
- values.update({'id': operation_id})
return True