diff options
| author | ryv-odoo <ryv@odoo.com> | 2019-12-02 16:02:42 +0000 |
|---|---|---|
| committer | ryv-odoo <ryv@odoo.com> | 2019-12-10 14:51:33 +0000 |
| commit | b5e24e9760a0d6a53730bebfc4bd76fadf971b3a (patch) | |
| tree | 87064da678a12521d1f552ad650f472c20369e32 /addons | |
| parent | 68518afe33040ff6e000a15acd3a7080b2485e38 (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.py | 48 | ||||
| -rw-r--r-- | addons/stock/tests/test_inventory.py | 101 | ||||
| -rw-r--r-- | addons/stock/views/stock_inventory_views.xml | 1 |
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}"/> |
