diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 4ad9658bf26900ce309c2880002aef3035713e81..59350e512be41a663ca2cb6fef5630bf37fdde0b 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2396,13 +2396,15 @@ class stock_move(osv.osv): lot_qty[pack_lot.lot_id.id] = uom_obj._compute_qty(cr, uid, ops.product_uom_id.id, pack_lot.qty, ops.product_id.uom_id.id) for record in ops.linked_move_operation_ids: move_qty = record.qty + move = record.move_id domain = main_domain[move.id] for lot in lot_qty: if float_compare(lot_qty[lot], 0, precision_rounding=rounding) > 0 and float_compare(move_qty, 0, precision_rounding=rounding) > 0: qty = min(lot_qty[lot], move_qty) quants = quant_obj.quants_get_preferred_domain(cr, uid, qty, move, ops=ops, lot_id=lot, domain=domain, preferred_domain_list=[], context=context) - quants_to_reserve = [x for x in quants if x[0] and x[0].lot_id] - quant_obj.quants_reserve(cr, uid, quants_to_reserve, move, record, context=context) + quant_obj.quants_reserve(cr, uid, quants, move, record, context=context) + lot_qty[lot] -= qty + move_qty -= qty for move in todo_moves: if move.linked_move_operation_ids: @@ -2489,62 +2491,62 @@ class stock_move(osv.osv): self.write(cr, uid, [move.id], vals, context=context) def _move_quants_by_lot(self, cr, uid, ops, lot_qty, quants_taken, false_quants, lot_move_qty, quant_dest_package_id, context=None): + """ + This function is used to process all the pack operation lots of a pack operation + For every move: + First, we check the quants with lot already reserved (and those are already subtracted from the lots to do) + Then go through all the lots to process: + Add reserved false lots lot by lot + Check if there are not reserved quants or reserved elsewhere with that lot or without lot (with the traditional method) + """ quant_obj = self.pool['stock.quant'] - move_quants_dict = {} - domain = [('qty', '>', 0)] fallback_domain = [('reservation_id', '=', False)] fallback_domain2 = ['&', ('reservation_id', 'not in', [x for x in lot_move_qty.keys()]), ('reservation_id', '!=', False)] preferred_domain_list = [fallback_domain] + [fallback_domain2] rounding = ops.product_id.uom_id.rounding - # Iterate for every move through the different lots taken - # Take the reserved quants with the correct lot first - # Afterwards take the not reserved quants (or reserved on another move) with the correct lot - # If nothing found, take first the quants reserved with False lots before taking others for move in lot_move_qty: - move_quants_dict[move] = {} + move_quants_dict = {} move_rec = self.pool['stock.move'].browse(cr, uid, move, context=context) - #Needs to be divided by lot still + # Assign quants already reserved with lot to the correct for quant in quants_taken: - move_quants_dict[move].setdefault(quant[0].lot_id.id, []) - move_quants_dict[move][quant[0].lot_id.id] += [quant] + move_quants_dict.setdefault(quant[0].lot_id.id, []) + move_quants_dict[quant[0].lot_id.id] += [quant] false_quants_move = [x for x in false_quants if x[0].reservation_id.id == move] for lot in lot_qty: - move_quants_dict[move].setdefault(lot, []) + move_quants_dict.setdefault(lot, []) + redo_false_quants = False + # Take remaining reserved quants with no lot first + # (This will be used mainly when incoming had no lot and you do outgoing with) + while false_quants_move and float_compare(lot_qty[lot], 0, precision_rounding=rounding) > 0 and float_compare(lot_move_qty[move], 0, precision_rounding=rounding) > 0: + qty_min = min(lot_qty[lot], lot_move_qty[move]) + if false_quants_move[0].qty > qty_min: + move_quants_dict[lot] += [(false_quants_move[0], qty_min)] + qty = qty_min + redo_false_quants = True + else: + move_quants_dict[lot] += [false_quants_move[0]] + qty = false_quants_move[0][1] + false_quants_move.pop(0) + lot_qty[lot] -= qty + lot_move_qty[move] -= qty + + # Search other with first matching lots and then without lots if float_compare(lot_move_qty[move], 0, precision_rounding=rounding) > 0 and float_compare(lot_qty[lot], 0, precision_rounding=rounding) > 0: # Search if we can find quants with that lot - quants = quant_obj.quants_get_preferred_domain(cr, uid, lot_move_qty[move], move_rec, ops=ops, lot_id=lot, domain=domain, + domain = [('qty', '>', 0)] + qty = min(lot_qty[lot], lot_move_qty[move]) + quants = quant_obj.quants_get_preferred_domain(cr, uid, qty, move_rec, ops=ops, lot_id=lot, domain=domain, preferred_domain_list=preferred_domain_list, context=context) - while quants and float_compare(lot_qty[lot], 0, precision_rounding=rounding) > 0 and float_compare(lot_move_qty[move], 0, precision_rounding=rounding) > 0: - quant = quants.pop(0) - if quant[0] and quant[0].lot_id: - qty = min (lot_qty[lot], lot_move_qty[move], quant[1]) - move_quants_dict[move][lot] += [(quant[0], qty)] - lot_qty[lot] -= qty - lot_move_qty[move] -= qty - else: - #Take reserved False quants first if no quants with lot anymore - while false_quants_move and float_compare(lot_qty[lot], 0, precision_rounding=rounding) > 0 and float_compare(lot_move_qty[move], 0, precision_rounding=rounding) > 0: - qty_min = min(lot_qty[lot], lot_move_qty[move]) - if false_quants_move[0][1] > qty_min: - false_quants_move[0][1] -= qty_min - move_quants_dict[move][lot] += [(false_quants_move[0][0], qty_min)] - qty = qty_min - else: - move_quants_dict[move][lot] += [false_quants_move[0]] - qty = false_quants_move[0][1] - false_quants_move.pop(0) - lot_qty[lot] -= qty - lot_move_qty[move] -= qty - if float_compare(lot_qty[lot], 0, precision_rounding=rounding) > 0 and float_compare(lot_move_qty[move], 0,precision_rounding=rounding) > 0: - qty = min (lot_qty[lot], lot_move_qty[move], quant[1]) - move_quants_dict[move][lot] += [(quant[0], qty)] - lot_qty[lot] -= qty - lot_move_qty[move] -= qty + move_quants_dict[lot] += quants #Move all the quants related to that lot/move - quant_obj.quants_move(cr, uid, move_quants_dict[move][lot], move_rec, ops.location_dest_id, location_from=ops.location_id, + if move_quants_dict[lot]: + quant_obj.quants_move(cr, uid, move_quants_dict[lot], move_rec, ops.location_dest_id, location_from=ops.location_id, lot_id=lot, owner_id=ops.owner_id.id, src_package_id=ops.package_id.id, dest_package_id=quant_dest_package_id, context=context) + if redo_false_quants: + move_rec = self.pool['stock.move'].browse(cr, uid, move, context=context) + false_quants_move = [(x, x.qty) for x in move_rec.reserved_quant_ids if not x.lot_id] def action_done(self, cr, uid, ids, context=None): """ Process completely the moves given as ids and if all moves are done, it will finish the picking.