[FIX] stock: serial number

- Activate the option "Track Lots or Serial Numbers".
- Set the outgoing process as 3-step one.
- Create a stockable product for which the tracking is "By Unique Serial
  Number".
- Go to Sales > Sales > Sales Orders.
- Create a Quotation for the created product and confirm it. A picking
  is generated but it is waiting availability.
- You are sure to have this product in stock so you force the
  availability and assign the serial number (001) you want to transfer
  in the operation lot details.
- Validate the picking. By doing this, it creates a negative quant in
  the origin location (WH/Stock) and it creates a positive quant in the
  destination location (WH/Packing Zone). The two quants are linked to
  each other.
- Go to Inventory > Inventory Control > Inventory Adjustments.
- Create an inventory in WH/Stock  for all products and set it in
  progress.
- You want to correct the negative quantity you have so set the real
  quantity of product B to 0.
- Validate the inventory and you get the following warning: "The serial
  number 001 is already in stock.Otherwise make sure the right
  stock/owner is set".

We should allow a quantity larger than 1.0 temporary, so it allows the
system to reconcile the quants.

opw-685825
This commit is contained in:
Nicolas Martinelli
2016-09-01 11:06:37 +02:00
parent 24ca4396ef
commit 2d21795228
+22 -6
View File
@@ -411,10 +411,12 @@ class stock_quant(osv.osv):
quants_reconcile = []
to_move_quants = []
self._check_location(cr, uid, location_to, context=context)
check_lot = False
for quant, qty in quants:
if not quant:
#If quant is None, we will create a quant to move (and potentially a negative counterpart too)
quant = self._quant_create(cr, uid, qty, move, lot_id=lot_id, owner_id=owner_id, src_package_id=src_package_id, dest_package_id=dest_package_id, force_location_from=location_from, force_location_to=location_to, context=context)
check_lot = True
else:
self._quant_split(cr, uid, quant, qty, context=context)
to_move_quants.append(quant)
@@ -433,6 +435,26 @@ class stock_quant(osv.osv):
for quant in quants_reconcile:
self._quant_reconcile_negative(cr, uid, quant, move, context=context)
# In case of serial tracking, check if the product does not exist somewhere internally already
# Checking that a positive quant already exists in an internal location is too restrictive.
# Indeed, if a warehouse is configured with several steps (e.g. "Pick + Pack + Ship") and
# one step is forced (creates a quant of qty = -1.0), it is not possible afterwards to
# correct the inventory unless the product leaves the stock.
picking_type = move.picking_id and move.picking_id.picking_type_id or False
if check_lot and lot_id and move.product_id.tracking == 'serial' and (not picking_type or (picking_type.use_create_lots or picking_type.use_existing_lots)):
other_quants = self.search(cr, uid, [('product_id', '=', move.product_id.id), ('lot_id', '=', lot_id),
('location_id.usage', '=', 'internal')], context=context)
if other_quants:
# We raise an error if:
# - the total quantity is strictly larger than 1.0
# - there are more than one negative quant, to avoid situations where the user would
# force the quantity at several steps of the process
other_quants = self.browse(cr, uid, other_quants, context=context)
if sum(other_quants.mapped('qty')) > 1.0 or len([q for q in other_quants.mapped('qty') if q < 0]) > 1:
lot_name = self.pool['stock.production.lot'].browse(cr, uid, lot_id, context=context).name
raise UserError(_('The serial number %s is already in stock.') % lot_name + _("Otherwise make sure the right stock/owner is set."))
def move_quants_write(self, cr, uid, quants, move, location_dest_id, dest_package_id, lot_id = False, entire_pack=False, context=None):
context=context or {}
vals = {'location_id': location_dest_id.id,
@@ -566,16 +588,10 @@ class stock_quant(osv.osv):
negative_quant_id = self.create(cr, SUPERUSER_ID, negative_vals, context=context)
vals.update({'propagated_from_id': negative_quant_id})
# In case of serial tracking, check if the product does not exist somewhere internally already
picking_type = move.picking_id and move.picking_id.picking_type_id or False
if lot_id and move.product_id.tracking == 'serial' and (not picking_type or (picking_type.use_create_lots or picking_type.use_existing_lots)):
if qty != 1.0:
raise UserError(_('You should only receive by the piece with the same serial number'))
other_quants = self.search(cr, uid, [('product_id', '=', move.product_id.id), ('lot_id', '=', lot_id),
('qty', '>', 0.0), ('location_id.usage', '=', 'internal')], context=context)
if other_quants:
lot_name = self.pool['stock.production.lot'].browse(cr, uid, lot_id, context=context).name
raise UserError(_('The serial number %s is already in stock.') % lot_name + _("Otherwise make sure the right stock/owner is set."))
#create the quant as superuser, because we want to restrict the creation of quant manually: we should always use this method to create quants
quant_id = self.create(cr, SUPERUSER_ID, vals, context=context)