[FIX] stock: barcode scanner UI fixed
bzr revid: qdp-launchpad@openerp.com-20131120104233-5bis81r0ii1kumpw
This commit is contained in:
parent
ad8bec7759
commit
d9ebd0600a
|
@ -314,7 +314,7 @@ function openerp_picking_widgets(instance){
|
||||||
var pickings = new $.Deferred();
|
var pickings = new $.Deferred();
|
||||||
|
|
||||||
new instance.web.Model('stock.picking')
|
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){
|
.then(function(picking_ids){
|
||||||
if(!picking_ids || picking_ids.length === 0){
|
if(!picking_ids || picking_ids.length === 0){
|
||||||
(new instance.web.Dialog(self,{
|
(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
|
scan: function(ean){ //scans a barcode, sends it to the server, then reload the ui
|
||||||
var self = this;
|
var self = this;
|
||||||
new instance.web.Model('stock.picking')
|
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(){
|
.then(function(){
|
||||||
self.reset_selected_operation();
|
self.reset_selected_operation();
|
||||||
return self.refresh_ui(self.picking.id);
|
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
|
scan_product_id: function(product_id){ //performs the same operation as a scan, but with product id instead
|
||||||
var self = this;
|
var self = this;
|
||||||
new instance.web.Model('stock.picking')
|
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(){
|
.then(function(){
|
||||||
self.reset_selected_operation();
|
self.reset_selected_operation();
|
||||||
return self.refresh_ui(self.picking.id);
|
return self.refresh_ui(self.picking.id);
|
||||||
|
@ -515,7 +515,7 @@ function openerp_picking_widgets(instance){
|
||||||
done: function(){
|
done: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
new instance.web.Model('stock.picking')
|
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){
|
.then(function(new_picking_id){
|
||||||
return self.refresh_ui(new_picking_id);
|
return self.refresh_ui(new_picking_id);
|
||||||
});
|
});
|
||||||
|
|
|
@ -797,13 +797,13 @@ class stock_picking(osv.osv):
|
||||||
self.pool.get('stock.move').force_assign(cr, uid, move_ids, context=context)
|
self.pool.get('stock.move').force_assign(cr, uid, move_ids, context=context)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def cancel_assign(self, cr, uid, ids, *args):
|
def cancel_assign(self, cr, uid, ids, context=None):
|
||||||
""" Cancels picking and moves.
|
""" Cancels picking and moves.
|
||||||
@return: True
|
@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]
|
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
|
return True
|
||||||
|
|
||||||
def action_cancel(self, cr, uid, ids, context=None):
|
def action_cancel(self, cr, uid, ids, context=None):
|
||||||
|
@ -832,23 +832,24 @@ class stock_picking(osv.osv):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def unlink(self, cr, uid, ids, context=None):
|
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')
|
move_obj = self.pool.get('stock.move')
|
||||||
context = context or {}
|
context = context or {}
|
||||||
for pick in self.browse(cr, uid, ids, context=context):
|
for pick in self.browse(cr, uid, ids, context=context):
|
||||||
ids2 = [move.id for move in pick.move_lines]
|
move_ids = [move.id for move in pick.move_lines]
|
||||||
move_obj.action_cancel(cr, uid, ids2, context=context)
|
move_obj.action_cancel(cr, uid, move_ids, context=context)
|
||||||
move_obj.unlink(cr, uid, ids2, context=context)
|
move_obj.unlink(cr, uid, move_ids, context=context)
|
||||||
return super(stock_picking, self).unlink(cr, uid, ids, context=context)
|
return super(stock_picking, self).unlink(cr, uid, ids, context=context)
|
||||||
|
|
||||||
def write(self, cr, uid, ids, vals, context=None):
|
def write(self, cr, uid, ids, vals, context=None):
|
||||||
res = super(stock_picking, self).write(cr, uid, ids, vals, context=context)
|
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:
|
if 'move_lines' in vals or 'pack_operation_ids' in vals:
|
||||||
self.do_recompute_remaining_quantities(cr, uid, ids, context=context)
|
self.do_recompute_remaining_quantities(cr, uid, ids, context=context)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _create_backorder(self, cr, uid, picking, backorder_moves=[], context=None):
|
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:
|
if not backorder_moves:
|
||||||
backorder_moves = picking.move_lines
|
backorder_moves = picking.move_lines
|
||||||
|
@ -874,6 +875,7 @@ class stock_picking(osv.osv):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def do_prepare_partial(self, cr, uid, picking_ids, context=None):
|
def do_prepare_partial(self, cr, uid, picking_ids, context=None):
|
||||||
|
#TODO refactore me
|
||||||
context = context or {}
|
context = context or {}
|
||||||
pack_operation_obj = self.pool.get('stock.pack.operation')
|
pack_operation_obj = self.pool.get('stock.pack.operation')
|
||||||
pack_obj = self.pool.get("stock.quant.package")
|
pack_obj = self.pool.get("stock.quant.package")
|
||||||
|
@ -979,7 +981,8 @@ class stock_picking(osv.osv):
|
||||||
_create_link_for_product(product_id, qty)
|
_create_link_for_product(product_id, qty)
|
||||||
|
|
||||||
def _create_extra_moves(self, cr, uid, picking, context=None):
|
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')
|
move_obj = self.pool.get('stock.move')
|
||||||
operation_obj = self.pool.get('stock.pack.operation')
|
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)
|
self.do_recompute_remaining_quantities(cr, uid, [picking.id], context=context)
|
||||||
|
|
||||||
def rereserve_quants(self, cr, uid, picking, move_ids=[], context=None):
|
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')
|
stock_move_obj = self.pool.get('stock.move')
|
||||||
if not move_ids:
|
if not move_ids:
|
||||||
self.do_unreserve(cr, uid, [picking.id], context=context)
|
self.do_unreserve(cr, uid, [picking.id], context=context)
|
||||||
|
@ -1055,26 +1059,31 @@ class stock_picking(osv.osv):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def do_split(self, cr, uid, picking_ids, context=None):
|
def do_split(self, cr, uid, picking_ids, context=None):
|
||||||
"""
|
""" just split the picking (create a backorder) without making it 'done' """
|
||||||
just split the picking without making it 'done'
|
|
||||||
"""
|
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
ctx = context.copy()
|
ctx = context.copy()
|
||||||
ctx['do_only_split'] = True
|
ctx['do_only_split'] = True
|
||||||
self.do_transfer(cr, uid, picking_ids, context=ctx)
|
return self.do_transfer(cr, uid, picking_ids, context=ctx)
|
||||||
return True
|
|
||||||
|
|
||||||
# Methods for the barcode UI
|
def get_next_picking_for_ui(self, cr, uid, context=None):
|
||||||
def get_picking_for_packing_ui(self, cr, uid, context=None):
|
""" returns the next pickings to process. Used in the barcode scanner UI"""
|
||||||
return self.search(cr, uid, [('state', 'in', ('confirmed', 'assigned')), ('picking_type_id', '=', context.get('default_picking_type_id'))], context=context)
|
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_packing_ui(self, cr, uid, picking_id, only_split_lines=False, context=None):
|
def action_done_from_ui(self, cr, uid, picking_id, context=None):
|
||||||
self.do_transfer(cr, uid, picking_id, only_split_lines, context=context)
|
""" 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 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):
|
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')
|
stock_operation_obj = self.pool.get('stock.pack.operation')
|
||||||
package_obj = self.pool.get('stock.quant.package')
|
package_obj = self.pool.get('stock.quant.package')
|
||||||
for picking_id in picking_ids:
|
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)
|
stock_operation_obj.write(cr, uid, operation_ids, {'result_package_id': package_id}, context=context)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
#TODO: commented because quant_id has been removed from pack operation object
|
def process_product_id_from_ui(self, cr, uid, picking_id, product_id, context=None):
|
||||||
#def _deal_with_quants(self, cr, uid, picking_id, quant_ids, context=None):
|
return self.pool.get('stock.pack.operation')._search_and_increment(cr, uid, picking_id, [('product_id', '=', product_id)], context=context)
|
||||||
# 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_barcode_from_ui(self, cr, uid, picking_id, barcode_str, context=None):
|
||||||
'''This function is called each time there barcode scanner reads an input'''
|
'''This function is called each time there barcode scanner reads an input'''
|
||||||
#TODO: better error messages handling => why not real raised errors
|
lot_obj = self.pool.get('stock.production.lot')
|
||||||
quant_obj = self.pool.get('stock.quant')
|
|
||||||
package_obj = self.pool.get('stock.quant.package')
|
package_obj = self.pool.get('stock.quant.package')
|
||||||
product_obj = self.pool.get('product.product')
|
product_obj = self.pool.get('product.product')
|
||||||
stock_operation_obj = self.pool.get('stock.pack.operation')
|
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
|
#check if the barcode correspond to a product
|
||||||
matching_product_ids = product_obj.search(cr, uid, [('ean13', '=', barcode_str)], context=context)
|
matching_product_ids = product_obj.search(cr, uid, [('ean13', '=', barcode_str)], context=context)
|
||||||
if matching_product_ids:
|
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 lot
|
||||||
##check if the barcode correspond to a quant
|
matching_lot_ids = lot_obj.search(cr, uid, [('name', '=', barcode_str)], context=context)
|
||||||
#matching_quant_ids = quant_obj.search(cr, uid, [('name', '=', barcode_str)], context=context) # TODO need the location clause
|
if matching_lot_ids:
|
||||||
#if matching_quant_ids:
|
lot = lot_obj.browse(cr, uid, matching_lot_ids[0], context=context)
|
||||||
# todo_on_moves, todo_on_operations = self._deal_with_quants(cr, uid, picking_id, [matching_quant_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
|
#check if the barcode correspond to a package
|
||||||
matching_package_ids = package_obj.search(cr, uid, [('name', '=', barcode_str)], context=context)
|
matching_package_ids = package_obj.search(cr, uid, [('name', '=', barcode_str)], context=context)
|
||||||
if matching_package_ids:
|
if matching_package_ids:
|
||||||
included_package_ids = package_obj.search(cr, uid, [('parent_id', 'child_of', matching_package_ids[0])], context=context)
|
stock_operation_obj._search_and_increment(cr, uid, picking_id, [('package_id', '=', 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}
|
|
||||||
|
|
||||||
|
|
||||||
class stock_production_lot(osv.osv):
|
class stock_production_lot(osv.osv):
|
||||||
|
@ -3179,10 +3167,10 @@ class stock_pack_operation(osv.osv):
|
||||||
|
|
||||||
|
|
||||||
#TODO: this function can be refactored
|
#TODO: this function can be refactored
|
||||||
def _search_and_increment(self, cr, uid, picking_id, key, context=None):
|
def _search_and_increment(self, cr, uid, picking_id, domain, context=None):
|
||||||
'''Search for an operation on an existing key in a picking, if it exists increment the qty (+1) otherwise create it
|
'''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
|
context can receive a key 'current_package_id' with the package to consider for this operation
|
||||||
returns True
|
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)
|
(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)
|
(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:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
|
|
||||||
#if current_package_id is given in the context, we increase the number of items in this package
|
#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))]
|
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:
|
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]
|
operation_id = existing_operation_ids[0]
|
||||||
qty = self.browse(cr, uid, operation_id, context=context).product_qty + 1
|
qty = self.browse(cr, uid, operation_id, context=context).product_qty + 1
|
||||||
self.write(cr, uid, operation_id, {'product_qty': qty}, context=context)
|
self.write(cr, uid, operation_id, {'product_qty': qty}, context=context)
|
||||||
else:
|
else:
|
||||||
#no existing operation found for the given key and picking => create a new one
|
#no existing operation found for the given domain 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
|
|
||||||
values = {
|
values = {
|
||||||
'picking_id': picking_id,
|
'picking_id': picking_id,
|
||||||
var_name: value,
|
|
||||||
'product_qty': 1,
|
'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)
|
operation_id = self.create(cr, uid, values, context=context)
|
||||||
values.update({'id': operation_id})
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue