summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorryv-odoo <ryv@odoo.com>2019-12-02 16:02:42 +0000
committerryv-odoo <ryv@odoo.com>2019-12-10 14:51:33 +0000
commitb5e24e9760a0d6a53730bebfc4bd76fadf971b3a (patch)
tree87064da678a12521d1f552ad650f472c20369e32 /addons
parent68518afe33040ff6e000a15acd3a7080b2485e38 (diff)
[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>
Diffstat (limited to 'addons')
-rw-r--r--addons/stock/models/stock_inventory.py48
-rw-r--r--addons/stock/tests/test_inventory.py101
-rw-r--r--addons/stock/views/stock_inventory_views.xml1
3 files changed, 146 insertions, 4 deletions
diff --git a/addons/stock/models/stock_inventory.py b/addons/stock/models/stock_inventory.py
index 9426593aaa0..01007292c5c 100644
--- a/addons/stock/models/stock_inventory.py
+++ b/addons/stock/models/stock_inventory.py
@@ -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
diff --git a/addons/stock/tests/test_inventory.py b/addons/stock/tests/test_inventory.py
index b787b21a423..3ef6e389e92 100644
--- a/addons/stock/tests/test_inventory.py
+++ b/addons/stock/tests/test_inventory.py
@@ -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)
diff --git a/addons/stock/views/stock_inventory_views.xml b/addons/stock/views/stock_inventory_views.xml
index cadbceaa87c..a6f8b9dd5fa 100644
--- a/addons/stock/views/stock_inventory_views.xml
+++ b/addons/stock/views/stock_inventory_views.xml
@@ -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}"/>