diff --git a/addons/stock/models/stock_location.py b/addons/stock/models/stock_location.py
index b96421dfd34..3e7fccf5b5f 100644
--- a/addons/stock/models/stock_location.py
+++ b/addons/stock/models/stock_location.py
@@ -117,9 +117,9 @@ class Location(models.Model):
('view_location_id.parent_left', '<=', self.parent_left),
('view_location_id.parent_right', '>=', self.parent_left)], limit=1)
- def should_impact_quants(self):
+ def should_bypass_reservation(self):
self.ensure_one()
- return False if self.usage in ('supplier', 'inventory', 'production', 'customer') else True
+ return self.usage in ('supplier', 'customer', 'inventory', 'production') or self.scrap_location
class Route(models.Model):
diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py
index faab9a301e5..74fd5e67278 100644
--- a/addons/stock/models/stock_move_line.py
+++ b/addons/stock/models/stock_move_line.py
@@ -96,10 +96,10 @@ class StockMoveLine(models.Model):
vals['ordered_qty'] = vals.get('product_uom_qty')
ml = super(StockMoveLine, self).create(vals)
if ml.state == 'done':
- Quant = self.env['stock.quant']
- quantity = ml.product_uom_id._compute_quantity(ml.qty_done, ml.move_id.product_id.uom_id,rounding_method='HALF-UP')
- in_date = None
- if ml.location_id.should_impact_quants() and ml.product_id.type == 'product':
+ if ml.product_id.type == 'product':
+ Quant = self.env['stock.quant']
+ quantity = ml.product_uom_id._compute_quantity(ml.qty_done, ml.move_id.product_id.uom_id,rounding_method='HALF-UP')
+ in_date = None
available_qty, in_date = Quant._update_available_quantity(ml.product_id, ml.location_id, -quantity, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
if available_qty < 0 and ml.lot_id:
# see if we can compensate the negative quants with some untracked quants
@@ -108,7 +108,6 @@ class StockMoveLine(models.Model):
taken_from_untracked_qty = min(untracked_qty, abs(quantity))
Quant._update_available_quantity(ml.product_id, ml.location_id, -taken_from_untracked_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id)
Quant._update_available_quantity(ml.product_id, ml.location_id, taken_from_untracked_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
- if ml.location_dest_id.should_impact_quants() and ml.product_id.type == 'product':
Quant._update_available_quantity(ml.product_id, ml.location_dest_id, quantity, lot_id=ml.lot_id, package_id=ml.result_package_id, owner_id=ml.owner_id, in_date=in_date)
next_moves = ml.move_id.move_dest_ids.filtered(lambda move: move.state not in ('done', 'cancel'))
next_moves.do_unreserve()
@@ -125,12 +124,13 @@ class StockMoveLine(models.Model):
return super(StockMoveLine, self).write(vals)
Quant = self.env['stock.quant']
+ precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
# We forbid to change the reserved quantity in the interace, but it is needed in the
# case of stock.move's split.
# TODO Move me in the update
if 'product_uom_qty' in vals:
- for ml in self.filtered(lambda m: m.state in ('partially_available', 'assigned')):
- if ml.location_id.should_impact_quants() and ml.product_id.type == 'product':
+ for ml in self.filtered(lambda m: m.state in ('partially_available', 'assigned') and m.product_id.type == 'product'):
+ if not ml.location_id.should_bypass_reservation():
qty_to_decrease = ml.product_qty - ml.product_uom_id._compute_quantity(vals['product_uom_qty'], ml.product_id.uom_id, rounding_method='HALF-UP')
try:
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -qty_to_decrease, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
@@ -154,8 +154,8 @@ class StockMoveLine(models.Model):
updates[key] = self.env[model].browse(vals[key])
if updates:
- for ml in self.filtered(lambda ml: ml.state in ['partially_available', 'assigned']):
- if ml.location_id.should_impact_quants() and ml.product_id.type == 'product':
+ for ml in self.filtered(lambda ml: ml.state in ['partially_available', 'assigned'] and ml.product_id.type == 'product'):
+ if not ml.location_id.should_bypass_reservation():
try:
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
except UserError:
@@ -164,7 +164,7 @@ class StockMoveLine(models.Model):
else:
raise
- if updates.get('location_id', ml.location_id).should_impact_quants() and ml.product_id.type == 'product':
+ if not updates.get('location_id', ml.location_id).should_bypass_reservation():
new_product_qty = 0
try:
q = Quant._update_reserved_quantity(ml.product_id, updates.get('location_id', ml.location_id), ml.product_qty, lot_id=updates.get('lot_id', ml.lot_id),
@@ -186,18 +186,14 @@ class StockMoveLine(models.Model):
# When editing a done move line, the reserved availability of a potential chained move is impacted. Take care of running again `action_assign` on the concerned moves.
next_moves = self.env['stock.move']
if updates or 'qty_done' in vals:
- for ml in self.filtered(lambda ml: ml.move_id.state == 'done'):
+ for ml in self.filtered(lambda ml: ml.move_id.state == 'done' and ml.product_id.type == 'product'):
# undo the original move line
- in_date = None
- if ml.location_dest_id.should_impact_quants() and ml.product_id.type == 'product':
- in_date = Quant._update_available_quantity(ml.product_id, ml.location_dest_id, -ml.qty_done, lot_id=ml.lot_id,
+ in_date = Quant._update_available_quantity(ml.product_id, ml.location_dest_id, -ml.qty_done, lot_id=ml.lot_id,
package_id=ml.package_id, owner_id=ml.owner_id)[1]
- if ml.location_id.should_impact_quants() and ml.product_id.type == 'product':
- Quant._update_available_quantity(ml.product_id, ml.location_id, ml.qty_done, lot_id=ml.lot_id,
+ Quant._update_available_quantity(ml.product_id, ml.location_id, ml.qty_done, lot_id=ml.lot_id,
package_id=ml.package_id, owner_id=ml.owner_id, in_date=in_date)
# move what's been actually done
- in_date = None
product_id = ml.product_id
location_id = updates.get('location_id', ml.location_id)
location_dest_id = updates.get('location_dest_id', ml.location_dest_id)
@@ -207,8 +203,9 @@ class StockMoveLine(models.Model):
result_package_id = updates.get('result_package_id', ml.result_package_id)
owner_id = updates.get('owner_id', ml.owner_id)
quantity = ml.move_id.product_uom._compute_quantity(qty_done, ml.move_id.product_id.uom_id, rounding_method='HALF-UP')
- if location_id.should_impact_quants() and ml.product_id.type == 'product':
+ if not location_id.should_bypass_reservation():
ml._free_reservation(product_id, location_id, quantity, lot_id=lot_id, package_id=package_id, owner_id=owner_id)
+ if not float_is_zero(quantity, precision_digits=precision):
available_qty, in_date = Quant._update_available_quantity(product_id, location_id, -quantity, lot_id=lot_id, package_id=package_id, owner_id=owner_id)
if available_qty < 0 and lot_id:
# see if we can compensate the negative quants with some untracked quants
@@ -217,8 +214,8 @@ class StockMoveLine(models.Model):
taken_from_untracked_qty = min(untracked_qty, abs(available_qty))
Quant._update_available_quantity(product_id, location_id, -taken_from_untracked_qty, lot_id=False, package_id=package_id, owner_id=owner_id)
Quant._update_available_quantity(product_id, location_id, taken_from_untracked_qty, lot_id=lot_id, package_id=package_id, owner_id=owner_id)
- ml._free_reservation(ml.product_id, location_id, untracked_qty, lot_id=False, package_id=package_id, owner_id=owner_id)
- if location_dest_id.should_impact_quants() and ml.product_id.type == 'product' and qty_done:
+ if not location_id.should_bypass_reservation():
+ ml._free_reservation(ml.product_id, location_id, untracked_qty, lot_id=False, package_id=package_id, owner_id=owner_id)
Quant._update_available_quantity(product_id, location_dest_id, quantity, lot_id=lot_id, package_id=result_package_id, owner_id=owner_id, in_date=in_date)
# Unreserve and reserve following move in order to have the real reserved quantity on move_line.
next_moves |= ml.move_id.move_dest_ids.filtered(lambda move: move.state not in ('done', 'cancel'))
@@ -233,8 +230,8 @@ class StockMoveLine(models.Model):
for ml in self:
if ml.state in ('done', 'cancel'):
raise UserError(_('You can not delete pack operations of a done picking'))
- # Unlinking a pack operation should unreserve.
- if ml.location_id.should_impact_quants() and ml.product_id.type == 'product' and not float_is_zero(ml.product_qty, precision_digits=precision):
+ # Unlinking a move line should unreserve.
+ if ml.product_id.type == 'product' and not ml.location_id.should_bypass_reservation() and not float_is_zero(ml.product_qty, precision_digits=precision):
self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id,
package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
return super(StockMoveLine, self).unlink()
@@ -290,16 +287,16 @@ class StockMoveLine(models.Model):
# Now, we can actually move the quant.
for ml in self - ml_to_delete:
- if ml.product_id.type != 'consu':
+ if ml.product_id.type == 'product':
Quant = self.env['stock.quant']
rounding = ml.product_uom_id.rounding
# if this move line is force assigned, unreserve elsewhere if needed
- if ml.location_id.should_impact_quants() and float_compare(ml.qty_done, ml.product_qty, precision_rounding=rounding) > 0:
+ if not ml.location_id.should_bypass_reservation() and float_compare(ml.qty_done, ml.product_qty, precision_rounding=rounding) > 0:
extra_qty = ml.qty_done - ml.product_qty
ml._free_reservation(ml.product_id, ml.location_id, extra_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
# unreserve what's been reserved
- if ml.location_id.should_impact_quants() and ml.product_id.type == 'product' and ml.product_qty:
+ if not ml.location_id.should_bypass_reservation() and ml.product_id.type == 'product' and ml.product_qty:
try:
Quant._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
except UserError:
@@ -307,18 +304,15 @@ class StockMoveLine(models.Model):
# move what's been actually done
quantity = ml.product_uom_id._compute_quantity(ml.qty_done, ml.move_id.product_id.uom_id, rounding_method='HALF-UP')
- in_date = None
- if ml.location_id.should_impact_quants() and ml.product_id.type == 'product':
- available_qty, in_date = Quant._update_available_quantity(ml.product_id, ml.location_id, -quantity, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
- if available_qty < 0 and ml.lot_id:
- # see if we can compensate the negative quants with some untracked quants
- untracked_qty = Quant._get_available_quantity(ml.product_id, ml.location_id, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
- if untracked_qty:
- taken_from_untracked_qty = min(untracked_qty, abs(quantity))
- Quant._update_available_quantity(ml.product_id, ml.location_id, -taken_from_untracked_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id)
- Quant._update_available_quantity(ml.product_id, ml.location_id, taken_from_untracked_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
- if ml.location_dest_id.should_impact_quants() and ml.product_id.type == 'product':
- Quant._update_available_quantity(ml.product_id, ml.location_dest_id, quantity, lot_id=ml.lot_id, package_id=ml.result_package_id, owner_id=ml.owner_id, in_date=in_date)
+ available_qty, in_date = Quant._update_available_quantity(ml.product_id, ml.location_id, -quantity, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
+ if available_qty < 0 and ml.lot_id:
+ # see if we can compensate the negative quants with some untracked quants
+ untracked_qty = Quant._get_available_quantity(ml.product_id, ml.location_id, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
+ if untracked_qty:
+ taken_from_untracked_qty = min(untracked_qty, abs(quantity))
+ Quant._update_available_quantity(ml.product_id, ml.location_id, -taken_from_untracked_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id)
+ Quant._update_available_quantity(ml.product_id, ml.location_id, taken_from_untracked_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
+ Quant._update_available_quantity(ml.product_id, ml.location_dest_id, quantity, lot_id=ml.lot_id, package_id=ml.result_package_id, owner_id=ml.owner_id, in_date=in_date)
def _free_reservation(self, product_id, location_id, quantity, lot_id=None, package_id=None, owner_id=None):
""" When editing a done move line or validating one with some forced quantities, it is
diff --git a/addons/stock/models/stock_production_lot.py b/addons/stock/models/stock_production_lot.py
index d9197ad96ac..06cc2917502 100644
--- a/addons/stock/models/stock_production_lot.py
+++ b/addons/stock/models/stock_production_lot.py
@@ -39,7 +39,9 @@ class ProductionLot(models.Model):
@api.one
def _product_qty(self):
- self.product_qty = sum(self.quant_ids.mapped('quantity'))
+ # We only care for the quants in internal or transit locations.
+ quants = self.quant_ids.filtered(lambda q: q.location_id.usage in ['internal', 'transit'])
+ self.product_qty = sum(quants.mapped('quantity'))
@api.multi
def action_traceability(self):
diff --git a/addons/stock/models/stock_traceability.py b/addons/stock/models/stock_traceability.py
index bd2861e60a6..c40e7a76a47 100644
--- a/addons/stock/models/stock_traceability.py
+++ b/addons/stock/models/stock_traceability.py
@@ -90,6 +90,7 @@ class MrpStockReport(models.TransientModel):
quant_ids = self.env['stock.quant'].search([
('lot_id', '=', context.get('active_id')),
('quantity', '<', 0),
+ ('location_id.usage', '=', 'internal'),
])
res += self._lines(line_id, model_id=model_id, model='stock.quant', level=level,
parent_quant=parent_quant, stream=stream, obj_ids=quant_ids)
@@ -104,6 +105,7 @@ class MrpStockReport(models.TransientModel):
quant_ids = self.env['stock.quant'].search([
('lot_id', '=', context.get('active_id')),
('quantity', '>', 0),
+ ('location_id.usage', '=', 'internal'),
])
res += self._lines(line_id, model_id=model_id, model='stock.quant', level=level,
parent_quant=parent_quant, stream=stream, obj_ids=quant_ids)
diff --git a/addons/stock/test/packing.yml b/addons/stock/test/packing.yml
index b1c18b0d767..b84e38e5985 100644
--- a/addons/stock/test/packing.yml
+++ b/addons/stock/test/packing.yml
@@ -72,11 +72,12 @@
!python {model: stock.picking, id: pick1}: |
self.action_done()
-
- Check the system created 3 quants one with 120 pieces on pallet 1, one with 120 pieces on pallet 2 with lot A and 60 pieces on pallet 3
+ Check the system created 5 quants one with 120 pieces on pallet 1, one with 120 pieces on pallet 2 with lot A and 60 pieces on pallet 3 in stock
+ and 1 with -180 pieces and another with -120 piece lot A in supplier
-
!python {model: stock.quant, id: False}: |
quants = self.search([('product_id','=',ref('product1'))])
- assert len(quants.ids) == 3, "The number of quants created is not correct"
+ assert len(quants.ids) == 5, "The number of quants created is not correct"
for quant in quants:
if quant.package_id.name == 'Pallet 1':
assert quant.quantity == 120, "Should have 120 pieces on pallet 1"
@@ -137,7 +138,7 @@
elif rec.package_id.name == 'Pallet 3' and rec.location_id.id == ref('stock_location_stock'):
assert rec.quantity == 50, "Should have 50 pieces in stock on pallet 3"
else:
- assert False, "Unrecognized quant"
+ assert rec.location_id.id != ref('stock_location_stock'), "Unrecognized quant in stock"
-
Check a backorder was created and on that backorder, prepare partial and process backorder
-
diff --git a/addons/stock/test/packingneg.yml b/addons/stock/test/packingneg.yml
index 49931e0b1ca..ca3305dad0b 100644
--- a/addons/stock/test/packingneg.yml
+++ b/addons/stock/test/packingneg.yml
@@ -120,7 +120,7 @@
elif rec.package_id.name == 'Palneg 3' and rec.location_id.id == ref('stock_location_stock'):
pallet_3_stock_qty += rec.quantity
else:
- assert False, "Unrecognized quant"
+ assert rec.location_id.id != ref('stock_location_stock'), "Unrecognized quant in stock"
assert pallet_3_stock_qty == 50, "Should have 50 pieces in stock on pallet 3"
-
Create a picking for reconciling the negative quant
@@ -148,8 +148,9 @@
Check the negative quant was reconciled
-
!python {model: stock.quant, id: False}: |
- neg_quants = self.search([('product_id','=', ref('product_neg')), ('quantity', '<', 0)])
- assert len(neg_quants.ids) == 0, "Negative quants should have been reconciled"
+ neg_quants = self.search([('product_id','=', ref('product_neg')), ('quantity', '<', 0), ('location_id.id', '!=',
+ ref('stock_location_suppliers'))])
+ assert len(neg_quants) == 0, "Negative quants should have been reconciled"
pick = self.env['stock.picking'].browse(ref('delivery_reconcile'))
customer_quant = self.search([
('product_id', '=', ref('product_neg')),
diff --git a/addons/stock/test/wiseoperator.yml b/addons/stock/test/wiseoperator.yml
index b79072a9699..3814d744116 100644
--- a/addons/stock/test/wiseoperator.yml
+++ b/addons/stock/test/wiseoperator.yml
@@ -51,11 +51,11 @@
!python {model: stock.picking, id: pick1_wise}: |
self.do_transfer()
-
- Check the system created 2 quants
+ Check the system created 3 quants
-
!python {model: stock.quant, id: False}: |
records = self.search([('product_id','=',ref('product_wise'))])
- assert len(records.ids) == 2, "The number of quants created is not correct"
+ assert len(records.ids) == 3, "The number of quants created is not correct"
-
Make a delivery order of 5 pieces to the customer
-
@@ -138,7 +138,8 @@
Check there was no negative quant created by this picking
-
!python {model: stock.quant, id: False}: |
- records = self.search([('product_id','=',ref('product_wise')), ('quantity', '<', 0.0)])
+ records = self.search([('product_id','=',ref('product_wise')), ('quantity', '<', 0.0), ('location_id.id', '=',
+ ref('stock_location_stock'))])
assert len(records.ids) == 0, 'This should not have created a negative quant'
-
Check the other delivery order has changed its state back to partially available
@@ -149,10 +150,10 @@
Process the second picking
-
!python {model: stock.picking, id: delivery_order_wise2}: |
- self.do_transfer()
+ self.action_done()
-
Check all quants are in Customers and there are no negative quants anymore
-
!python {model: stock.quant, id: False}: |
- records = self.search([('product_id','=',ref('product_wise'))])
- assert all([x.location_id.id==ref('stock_location_customers') and x.qty > 0.0 for x in records]), "Negative quant or wrong location detected"
\ No newline at end of file
+ records = self.search([('product_id','=',ref('product_wise')), ('location_id', '!=', ref('stock_location_suppliers'))])
+ assert all([x.location_id.id==ref('stock_location_customers') and x.quantity > 0.0 for x in records]), "Negative quant or wrong location detected"
\ No newline at end of file
diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py
index a0902c455ce..23ff2a8b99d 100644
--- a/addons/stock/tests/test_move.py
+++ b/addons/stock/tests/test_move.py
@@ -70,9 +70,9 @@ class StockMove(TransactionCase):
move1.action_done()
self.assertEqual(move1.state, 'done')
# no quants are created in the supplier location
- self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.supplier_location), 0.0)
+ self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.supplier_location), -100.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.stock_location), 100.0)
- self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.supplier_location)), 0.0)
+ self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.supplier_location)), 1.0)
self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.stock_location)), 1.0)
def test_in_2(self):
@@ -111,9 +111,9 @@ class StockMove(TransactionCase):
self.assertEqual(move1.state, 'done')
# no quants are created in the supplier location
- self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product3, self.supplier_location), 0.0)
+ self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product3, self.supplier_location), -5.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product3, self.stock_location), 5.0)
- self.assertEqual(len(self.env['stock.quant']._gather(self.product3, self.supplier_location)), 0.0)
+ self.assertEqual(len(self.env['stock.quant']._gather(self.product3, self.supplier_location)), 1.0)
quants = self.env['stock.quant']._gather(self.product3, self.stock_location)
self.assertEqual(len(quants), 1.0)
for quant in quants:
@@ -160,11 +160,11 @@ class StockMove(TransactionCase):
self.assertEqual(move1.product_qty, 5) # don't change reservation
self.assertEqual(move1.state, 'done')
- # no quants are created in the supplier location
- self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.supplier_location), 0.0)
+ # Quant balance should result with 5 quant in supplier and stock
+ self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.supplier_location), -5.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location), 5.0)
- self.assertEqual(len(self.env['stock.quant']._gather(self.product2, self.supplier_location)), 0.0)
+ self.assertEqual(len(self.env['stock.quant']._gather(self.product2, self.supplier_location)), 5.0)
quants = self.env['stock.quant']._gather(self.product2, self.stock_location)
self.assertEqual(len(quants), 5.0)
for quant in quants:
@@ -211,9 +211,9 @@ class StockMove(TransactionCase):
# validation
move1.action_done()
self.assertEqual(move1.state, 'done')
- # # no quants are created in the customer location
- self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.customer_location), 0.0)
- self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.customer_location)), 0.0)
+ # Check there is one quant in customer location
+ self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.customer_location), 100.0)
+ self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.customer_location)), 1.0)
# there should be no quant amymore in the stock location
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.stock_location), 0.0)
self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.stock_location)), 0.0)
@@ -260,7 +260,7 @@ class StockMove(TransactionCase):
# validation
move1.action_done()
self.assertEqual(move1.state, 'done')
- # # no quants are created in the customer location
+ # no quants are created in the customer location since it's a consumable
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.customer_location), 0.0)
self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.customer_location)), 0.0)
# there should be no quant amymore in the stock location
@@ -2466,12 +2466,14 @@ class StockMove(TransactionCase):
move2.action_done()
initial_in_date_lot2 = self.env['stock.quant'].search([
+ ('location_id', '=', self.stock_location.id),
('product_id', '=', self.product3.id),
('lot_id', '=', lot2.id),
]).in_date
# Edit lot1's incoming date.
quant_lot1 = self.env['stock.quant'].search([
+ ('location_id', '=', self.stock_location.id),
('product_id', '=', self.product3.id),
('lot_id', '=', lot1.id),
])
@@ -2508,6 +2510,7 @@ class StockMove(TransactionCase):
# Check that lot1 correctly is back to stock with its right in_date
quant_lot1 = self.env['stock.quant'].search([
+ ('location_id.usage', '=', 'internal'),
('product_id', '=', self.product3.id),
('lot_id', '=', lot1.id),
])
@@ -2516,6 +2519,7 @@ class StockMove(TransactionCase):
# Check that lo2 is in pack with is right in_date
quant_lot2 = self.env['stock.quant'].search([
+ ('location_id.usage', '=', 'internal'),
('product_id', '=', self.product3.id),
('lot_id', '=', lot2.id),
])
@@ -2567,12 +2571,14 @@ class StockMove(TransactionCase):
move2.action_done()
initial_in_date_lot2 = self.env['stock.quant'].search([
+ ('location_id', '=', self.stock_location.id),
('product_id', '=', self.product3.id),
('lot_id', '=', lot2.id),
]).in_date
# Edit lot1's incoming date.
quant_lot1 = self.env['stock.quant'].search([
+ ('location_id.usage', '=', 'internal'),
('product_id', '=', self.product3.id),
('lot_id', '=', lot1.id),
])
@@ -2606,6 +2612,7 @@ class StockMove(TransactionCase):
})
quants = self.env['stock.quant'].search([
+ ('location_id.usage', '=', 'internal'),
('product_id', '=', self.product3.id),
])
self.assertEqual(len(quants), 2)
diff --git a/addons/stock/tests/test_stock_flow.py b/addons/stock/tests/test_stock_flow.py
index 07b958578d6..7e44febe1e9 100644
--- a/addons/stock/tests/test_stock_flow.py
+++ b/addons/stock/tests/test_stock_flow.py
@@ -1415,9 +1415,9 @@ class TestStockFlow(TestStockCommon):
# Check picking_in_package is in picking_pack_package
self.assertEqual(picking_in_package.id, picking_pack_package.id, 'The package created in the picking in is not in the one created in picking pack')
self.assertEqual(picking_pack_package.id, picking_out_package.id, 'The package created in the picking in is not in the one created in picking pack')
- # Check that we haven't quant in customer location.
- quant = self.StockQuantObj.search([('location_id', '=', self.customer_location)])
- self.assertEqual(len(quant), 0, 'There should be no package for customer location')
+ # Check that we have one quant in customer location.
+ quant = self.StockQuantObj.search([('product_id', '=', self.productA.id), ('location_id', '=', self.customer_location)])
+ self.assertEqual(len(quant), 1, 'There should be one quant with package for customer location')
# Check that the parent package of the quant is the picking_in_package
def test_50_create_in_out_with_product_pack_lines(self):
@@ -1471,9 +1471,11 @@ class TestStockFlow(TestStockCommon):
packout2.package_id = pack2
packout2.qty_done = 1
picking_out.action_done()
- # Check there are no negative quants
+ # Should be only 1 negative quant in supplier location
neg_quants = self.env['stock.quant'].search([('product_id', '=', self.productE.id), ('quantity', '<', 0.0)])
- self.assertEqual(len(neg_quants), 0, 'There are negative quants!')
+ self.assertEqual(len(neg_quants), 1, 'There should be 1 negative quants for supplier!')
+ self.assertEqual(neg_quants.location_id.id, self.supplier_location, 'There shoud be 1 negative quants for supplier!')
+
quants = self.env['stock.quant']._gather(self.productE, self.env['stock.location'].browse(self.stock_location))
self.assertEqual(len(quants), 2, 'We should have exactly 2 quants in the end')
@@ -1538,9 +1540,10 @@ class TestStockFlow(TestStockCommon):
'product_uom_id': self.productE.uom_id.id,
})
picking_out.action_done()
- # Check there are no negative quants
+ # Should be only 1 negative quant in supplier location
neg_quants = self.env['stock.quant'].search([('product_id', '=', self.productE.id), ('quantity', '<', 0.0)])
- self.assertEqual(len(neg_quants), 0, 'There are negative quants!')
+ self.assertEqual(len(neg_quants), 1, 'There should be 1 negative quants for supplier!')
+ self.assertEqual(neg_quants.location_id.id, self.supplier_location, 'There shoud be 1 negative quants for supplier!')
# We should also make sure that when matching stock moves with pack operations, it takes the correct
quants = self.env['stock.quant']._gather(self.productE, self.env['stock.location'].browse(self.stock_location))
self.assertEqual(len(quants), 0, 'We should have no quants in the end')
diff --git a/addons/stock/tests/test_warehouse.py b/addons/stock/tests/test_warehouse.py
index 039b90683cf..23a44df81c6 100644
--- a/addons/stock/tests/test_warehouse.py
+++ b/addons/stock/tests/test_warehouse.py
@@ -37,7 +37,7 @@ class TestWarehouse(TestStockCommon):
self.assertEqual(inventory.move_ids.location_dest_id, self.env.ref('stock.location_inventory')) # Inventory loss
self.assertEqual(inventory.move_ids.state, 'done')
quants = self.env['stock.quant']._gather(self.product_1, self.env.ref('stock.location_inventory'))
- self.assertEqual(len(quants), 0) # No quant created for inventory loss
+ self.assertEqual(len(quants), 1) # One quant created for inventory loss
# Check quantity of product in various locations: current, its parent, brother and other
self.assertEqual(self.env['stock.quant']._gather(self.product_1, self.warehouse_1.lot_stock_id).quantity, 35.0)
@@ -67,9 +67,9 @@ class TestWarehouse(TestStockCommon):
self.assertEqual(inventory.line_ids.product_id, self.product_1)
self.assertEqual(inventory.line_ids.product_qty, 50.0)
- # Check associated quants: 1 quant for the product and the quantity
+ # Check associated quants: 2 quants for the product and the quantity (1 in stock, 1 in inventory adjustment)
quant = self.env['stock.quant'].search([('id', 'not in', self.existing_quants.ids)])
- self.assertEqual(len(quant), 1)
+ self.assertEqual(len(quant), 2)
# print quant.name, quant.product_id, quant.location_id
# TDE TODO: expand this test
@@ -225,9 +225,9 @@ class TestWarehouse(TestStockCommon):
quants = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', stock_location.id)])
self.assertEqual(len(quants), 0)
- # There should be no quant in the inventory loss location
+ # There should be one quant in the inventory loss location
quant = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', location_loss.id)])
- self.assertEqual(len(quant), 0)
+ self.assertEqual(len(quant), 1)
class TestResupply(TestStockCommon):
diff --git a/addons/stock/views/stock_quant_views.xml b/addons/stock/views/stock_quant_views.xml
index 50625c85375..e92515f6037 100644
--- a/addons/stock/views/stock_quant_views.xml
+++ b/addons/stock/views/stock_quant_views.xml
@@ -48,7 +48,7 @@
-
+
@@ -68,7 +68,6 @@
-
@@ -91,6 +90,7 @@
stock.quant
form
tree,form,pivot
+ {'search_default_internal_loc': 1, 'search_default_transit_loc': 1}
This analysis gives you a fast overview on the current stock level of your products and their current inventory value.