[IMP] stock: readd include exhausted product option
In the inventory adjustment form, readd (remove in 13.0) the option to include exhausted product. task-2115194 closes odoo/odoo#41239 Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
This commit is contained in:
@@ -58,6 +58,10 @@ class Inventory(models.Model):
|
||||
help="Allows to start with prefill counted quantity for each lines or "
|
||||
"with all counted quantity set to zero.", default='counted',
|
||||
selection=[('counted', 'Default to stock on hand'), ('zero', 'Default to zero')])
|
||||
exhausted = fields.Boolean(
|
||||
'Include Exhausted Products', readonly=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
help="Include also products with quantity of 0")
|
||||
|
||||
@api.onchange('company_id')
|
||||
def _onchange_company_id(self):
|
||||
@@ -206,8 +210,7 @@ class Inventory(models.Model):
|
||||
return action
|
||||
|
||||
def _get_quantities(self):
|
||||
"""
|
||||
Return quantities group by product_id, location_id, lot_id, package_id and owner_id
|
||||
"""Return quantities group by product_id, location_id, lot_id, package_id and owner_id
|
||||
|
||||
:return: a dict with keys as tuple of group by and quantity as value
|
||||
:rtype: dict
|
||||
@@ -240,9 +243,44 @@ class Inventory(models.Model):
|
||||
quant['quantity'] for quant in quants
|
||||
}
|
||||
|
||||
def _get_inventory_lines_values(self):
|
||||
def _get_exhausted_inventory_lines_vals(self, non_exhausted_set):
|
||||
"""Return the values of the inventory lines to create if the user
|
||||
wants to include exhausted products. Exhausted products are products
|
||||
without quantities or quantity equal to 0.
|
||||
|
||||
:param non_exhausted_set: set of tuple (product_id, location_id) of non exhausted product-location
|
||||
:return: a list containing the `stock.inventory.line` values to create
|
||||
:rtype: list
|
||||
"""
|
||||
Return the values of the inventory lines to create for this inventory.
|
||||
self.ensure_one()
|
||||
if self.product_ids:
|
||||
product_ids = self.product_ids.ids
|
||||
else:
|
||||
product_ids = self.env['product.product'].search_read([
|
||||
'|', ('company_id', '=', self.company_id.id), ('company_id', '=', False),
|
||||
('type', '=', 'product'),
|
||||
('active', '=', True)], ['id'])
|
||||
product_ids = [p['id'] for p in product_ids]
|
||||
|
||||
if self.location_ids:
|
||||
location_ids = self.location_ids.ids
|
||||
else:
|
||||
location_ids = self.env['stock.warehouse'].search([('company_id', '=', self.company_id.id)]).lot_stock_id.ids
|
||||
|
||||
vals = []
|
||||
for product_id in product_ids:
|
||||
for location_id in location_ids:
|
||||
if ((product_id, location_id) not in non_exhausted_set):
|
||||
vals.append({
|
||||
'inventory_id': self.id,
|
||||
'product_id': product_id,
|
||||
'location_id': location_id,
|
||||
'theoretical_qty': 0
|
||||
})
|
||||
return vals
|
||||
|
||||
def _get_inventory_lines_values(self):
|
||||
"""Return the values of the inventory lines to create for this inventory.
|
||||
|
||||
:return: a list containing the `stock.inventory.line` values to create
|
||||
:rtype: list
|
||||
@@ -263,6 +301,8 @@ class Inventory(models.Model):
|
||||
}
|
||||
line_values['product_uom_id'] = self.env['product.product'].browse(product_id).uom_id.id
|
||||
vals.append(line_values)
|
||||
if self.exhausted:
|
||||
vals += self._get_exhausted_inventory_lines_vals({(l['product_id'], l['location_id']) for l in vals})
|
||||
return vals
|
||||
|
||||
|
||||
|
||||
@@ -701,3 +701,104 @@ class TestInventory(SavepointCase):
|
||||
inventory_2.action_validate()
|
||||
# Expect line of inventory 1 is still up to date
|
||||
self.assertEqual(inventory_1.line_ids.outdated, False)
|
||||
|
||||
def test_inventory_include_exhausted_product(self):
|
||||
""" Checks that exhausted product (quant not set or == 0) is added
|
||||
to inventory line
|
||||
(only for location_ids selected or, if not set, for each main location
|
||||
(linked directly to the warehouse) of the current company)
|
||||
when the option is active """
|
||||
|
||||
# location_ids SET + product_ids SET
|
||||
inventory = self.env['stock.inventory'].create({
|
||||
'name': 'loc SET - pro SET',
|
||||
'exhausted': True,
|
||||
'location_ids': [(4, self.stock_location.id)],
|
||||
'product_ids': [(4, self.product1.id)],
|
||||
})
|
||||
inventory.action_start()
|
||||
|
||||
self.assertEqual(len(inventory.line_ids), 1)
|
||||
self.assertEqual(inventory.line_ids.product_id.id, self.product1.id)
|
||||
self.assertEqual(inventory.line_ids.theoretical_qty, 0)
|
||||
self.assertEqual(inventory.line_ids.location_id.id, self.stock_location.id)
|
||||
|
||||
# location_ids SET + product_ids UNSET
|
||||
inventory = self.env['stock.inventory'].create({
|
||||
'name': 'loc SET - pro UNSET',
|
||||
'exhausted': True,
|
||||
'location_ids': [(4, self.stock_location.id)]
|
||||
})
|
||||
inventory.action_start()
|
||||
line_ids_p1 = [l for l in inventory.line_ids if l['product_id']['id'] == self.product1.id]
|
||||
line_ids_p2 = [l for l in inventory.line_ids if l['product_id']['id'] == self.product2.id]
|
||||
self.assertEqual(len(line_ids_p1), 1)
|
||||
self.assertEqual(len(line_ids_p2), 1)
|
||||
self.assertEqual(line_ids_p1[0].location_id.id, self.stock_location.id)
|
||||
self.assertEqual(line_ids_p2[0].location_id.id, self.stock_location.id)
|
||||
|
||||
# location_ids UNSET + product_ids SET
|
||||
warehouse = self.env['stock.warehouse'].create({
|
||||
'name': 'Warhouse',
|
||||
'code': 'WAR'
|
||||
})
|
||||
child_loc = self.env['stock.location'].create({
|
||||
'name': "ChildLOC",
|
||||
'usage': 'internal',
|
||||
'location_id': warehouse.lot_stock_id.id
|
||||
})
|
||||
|
||||
inventory = self.env['stock.inventory'].create({
|
||||
'name': 'loc UNSET - pro SET',
|
||||
'exhausted': True,
|
||||
'product_ids': [(4, self.product1.id)],
|
||||
})
|
||||
inventory.action_start()
|
||||
|
||||
line_ids = [l for l in inventory.line_ids if l['location_id']['id'] == warehouse.lot_stock_id.id]
|
||||
self.assertEqual(len(line_ids), 1)
|
||||
self.assertEqual(line_ids[0].theoretical_qty, 0)
|
||||
self.assertEqual(line_ids[0].product_id.id, self.product1.id)
|
||||
|
||||
# Only the main location have a exhausted line
|
||||
line_ids = [l for l in inventory.line_ids if l['location_id']['id'] == child_loc.id]
|
||||
self.assertEqual(len(line_ids), 0)
|
||||
|
||||
# location_ids UNSET + product_ids UNSET
|
||||
inventory = self.env['stock.inventory'].create({
|
||||
'name': 'loc UNSET - pro UNSET',
|
||||
'exhausted': True
|
||||
})
|
||||
inventory.action_start()
|
||||
|
||||
# Product1 & Product2 line with warehouse location
|
||||
line_ids_p1 = [l for l in inventory.line_ids if l['product_id']['id'] == self.product1.id and l['location_id']['id'] == warehouse.lot_stock_id.id]
|
||||
line_ids_p2 = [l for l in inventory.line_ids if l['product_id']['id'] == self.product2.id and l['location_id']['id'] == warehouse.lot_stock_id.id]
|
||||
self.assertEqual(len(line_ids_p1), 1)
|
||||
self.assertEqual(len(line_ids_p2), 1)
|
||||
self.assertEqual(line_ids_p1[0].theoretical_qty, 0)
|
||||
self.assertEqual(line_ids_p2[0].theoretical_qty, 0)
|
||||
|
||||
# location_ids SET + product_ids SET but when product in one locations but no the other
|
||||
self.env['stock.quant'].create({
|
||||
'product_id': self.product1.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'quantity': 10,
|
||||
'reserved_quantity': 0,
|
||||
})
|
||||
inventory = self.env['stock.inventory'].create({
|
||||
'name': 'loc SET - pro SET',
|
||||
'exhausted': True,
|
||||
'location_ids': [(4, self.stock_location.id), (4, warehouse.lot_stock_id.id)],
|
||||
'product_ids': [(4, self.product1.id)],
|
||||
})
|
||||
inventory.action_start()
|
||||
|
||||
# need to have line for product1 for both location, one with quant the other not
|
||||
line_ids_loc1 = [l for l in inventory.line_ids if l['location_id']['id'] == self.stock_location.id]
|
||||
line_ids_loc2 = [l for l in inventory.line_ids if l['location_id']['id'] == warehouse.lot_stock_id.id]
|
||||
self.assertEqual(len(line_ids_loc1), 1)
|
||||
self.assertEqual(len(line_ids_loc2), 1)
|
||||
self.assertEqual(line_ids_loc1[0].theoretical_qty, 10)
|
||||
self.assertEqual(line_ids_loc2[0].theoretical_qty, 0)
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
groups="stock.group_stock_multi_locations"/>
|
||||
<field name="product_ids" options="{'no_create': True}"
|
||||
widget="many2many_tags"/>
|
||||
<field name="exhausted"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
|
||||
Reference in New Issue
Block a user