diff --git a/stock_inventory_exclude_sublocation/README.rst b/stock_inventory_exclude_sublocation/README.rst index 38d75ff58..8b5f687e5 100644 --- a/stock_inventory_exclude_sublocation/README.rst +++ b/stock_inventory_exclude_sublocation/README.rst @@ -1,11 +1,27 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html - :alt: License: AGPL-3 - =================================== Stock Inventory Exclude Sublocation =================================== +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png + :target: https://odoo-community.org/page/development-status + :alt: Mature +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-warehouse/tree/11.0/stock_inventory_exclude_sublocation + :alt: OCA/stock-logistics-warehouse +.. |badge4| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/153/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| + This module extends the functionality of Inventory Adjustment to allow you to exclude all the sublocations when doing an inventory adjustment for a given location. @@ -16,6 +32,10 @@ do inventories of smaller locations contained in our stock, so we don't want to count them again when doing an inventory adjustment of the parent location. E.g. if we apply a cycle count strategy. +**Table of contents** + +.. contents:: + :local: Usage ===== @@ -26,44 +46,41 @@ To use this module, you simply need to: #. Select the option inventory of all products. #. Check the box "Exclude Sublocations". -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/153/10.0 - - Bug Tracker =========== -Bugs are tracked on `GitHub Issues -`_. In case of trouble, please -check there if your issue has already been reported. If you spotted it first, -help us smash it by providing detailed and welcomed feedback. +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback. + +Do not contact contributors directly about support or help with technical issues. Credits ======= -Images ------- +Authors +~~~~~~~ -* Odoo Community Association: `Icon `_. +* Eficent Contributors ------------- +~~~~~~~~~~~~ * Lois Rilo Antelo +Maintainers +~~~~~~~~~~~ -Maintainer ----------- +This module is maintained by the OCA. .. image:: https://odoo-community.org/logo.png :alt: Odoo Community Association :target: https://odoo-community.org -This module is maintained by the OCA. - OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit https://odoo-community.org. +This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_inventory_exclude_sublocation/__init__.py b/stock_inventory_exclude_sublocation/__init__.py index 289aba0fe..0650744f6 100644 --- a/stock_inventory_exclude_sublocation/__init__.py +++ b/stock_inventory_exclude_sublocation/__init__.py @@ -1,7 +1 @@ -# -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. -# (http://www.eficent.com) -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). - from . import models -from . import tests diff --git a/stock_inventory_exclude_sublocation/__manifest__.py b/stock_inventory_exclude_sublocation/__manifest__.py index 1d7ee88d3..8fbb5a94c 100644 --- a/stock_inventory_exclude_sublocation/__manifest__.py +++ b/stock_inventory_exclude_sublocation/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Eficent Business and IT Consulting Services S.L. # (http://www.eficent.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). @@ -6,14 +5,15 @@ "name": "Stock Inventory Exclude Sublocation", "summary": "Allow to perform inventories of a location without including " "its child locations.", - "version": "10.0.1.0.0", - "author": "Eficent," + "version": "11.0.1.0.0", + "development_status": "Mature", + "author": "Eficent, " "Odoo Community Association (OCA)", "website": "https://github.com/OCA/stock-logistics-warehouse", "category": "Warehouse Management", "depends": ["stock", "stock_inventory_chatter"], "data": [ - 'views/stock_inventory_view.xml' + 'views/stock_inventory_view.xml', ], "license": "AGPL-3", 'installable': True, diff --git a/stock_inventory_exclude_sublocation/models/__init__.py b/stock_inventory_exclude_sublocation/models/__init__.py index eff36f793..35536816e 100644 --- a/stock_inventory_exclude_sublocation/models/__init__.py +++ b/stock_inventory_exclude_sublocation/models/__init__.py @@ -1,6 +1 @@ -# -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. -# (http://www.eficent.com) -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). - from . import stock_inventory diff --git a/stock_inventory_exclude_sublocation/models/stock_inventory.py b/stock_inventory_exclude_sublocation/models/stock_inventory.py index 9d3492467..918addddb 100644 --- a/stock_inventory_exclude_sublocation/models/stock_inventory.py +++ b/stock_inventory_exclude_sublocation/models/stock_inventory.py @@ -1,9 +1,8 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Eficent Business and IT Consulting Services S.L. # (http://www.eficent.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models +from odoo import fields, models class Inventory(models.Model): @@ -14,68 +13,78 @@ class Inventory(models.Model): track_visibility='onchange', readonly=True, states={'draft': [('readonly', False)]}) - @api.multi def _get_inventory_lines_values(self): - if self.exclude_sublocation: - domain = ' location_id = %s' - args = (tuple(self.location_id.ids),) + """This method is a copy of standard one but considering only the + current location. + WARNING: In case of excluding sublocations standard method + is overridden by this one.""" + if not self.exclude_sublocation: + # Early return if exclude_sublocation is not set + return super()._get_inventory_lines_values() - vals = [] - product_obj = self.env['product.product'] - # Empty recordset of products available in stock_quants - quant_products = self.env['product.product'] - # Empty recordset of products to filter - products_to_filter = self.env['product.product'] + # STAR OF MODIFIED CODE: + domain = ' location_id in %s' + args = (tuple(self.location_id.ids),) + # END OF MODIFIED CODE. - if self.company_id.id: - domain += ' AND company_id = %s' - args += (self.company_id.id,) - if self.partner_id: - domain += ' AND owner_id = %s' - args += (self.partner_id.id,) - if self.lot_id: - domain += ' AND lot_id = %s' - args += (self.lot_id.id,) - if self.product_id: - domain += ' AND product_id = %s' - args += (self.product_id.id,) - products_to_filter |= self.product_id - if self.package_id: - domain += ' AND package_id = %s' - args += (self.package_id.id,) - if self.category_id: - categ_products = product_obj.search( - [('categ_id', '=', self.category_id.id)]) - domain += ' AND product_id = ANY (%s)' - args += (categ_products.ids,) - products_to_filter |= categ_products + vals = [] + Product = self.env['product.product'] + # Empty recordset of products available in stock_quants + quant_products = self.env['product.product'] + # Empty recordset of products to filter + products_to_filter = self.env['product.product'] - # disable error about SQL injection as the code here is generating - # a vulnerability - # pylint: disable = E8103 - self.env.cr.execute( - "SELECT product_id, SUM(qty) AS product_qty, location_id, " - " lot_id AS prod_lot_id, package_id, owner_id AS partner_id " - "FROM stock_quant " - "WHERE " + domain + " " + - "GROUP BY product_id, location_id, lot_id, package_id, " - "partner_id """, args) + # case 0: Filter on company + if self.company_id: + domain += ' AND company_id = %s' + args += (self.company_id.id,) - for product_data in self.env.cr.dictfetchall(): - for void_field in [item[0] for item in product_data.items() if - item[1] is None]: - product_data[void_field] = False - product_data['theoretical_qty'] = product_data['product_qty'] - if product_data['product_id']: - product_data['product_uom_id'] = product_obj.browse( - product_data['product_id']).uom_id.id - quant_products |= product_obj.browse( - product_data['product_id']) - vals.append(product_data) - if self.exhausted: - exhausted_vals = self._get_exhausted_inventory_line( - products_to_filter, quant_products) - vals.extend(exhausted_vals) - return vals - else: - return super(Inventory, self)._get_inventory_lines_values() + # case 1: Filter on One owner only or One product for a specific owner + if self.partner_id: + domain += ' AND owner_id = %s' + args += (self.partner_id.id,) + # case 2: Filter on One Lot/Serial Number + if self.lot_id: + domain += ' AND lot_id = %s' + args += (self.lot_id.id,) + # case 3: Filter on One product + if self.product_id: + domain += ' AND product_id = %s' + args += (self.product_id.id,) + products_to_filter |= self.product_id + # case 4: Filter on A Pack + if self.package_id: + domain += ' AND package_id = %s' + args += (self.package_id.id,) + # case 5: Filter on One product category + Exahausted Products + if self.category_id: + categ_products = Product.search( + [('categ_id', '=', self.category_id.id)]) + domain += ' AND product_id = ANY (%s)' + args += (categ_products.ids,) + products_to_filter |= categ_products + + self.env.cr.execute(""" + SELECT product_id, sum(quantity) as product_qty, + location_id, lot_id as prod_lot_id, package_id, + owner_id as partner_id + FROM stock_quant + WHERE %s + GROUP BY product_id, location_id, lot_id, + package_id, partner_id """ % domain, args) + + for product_data in self.env.cr.dictfetchall(): + for void_field in [item[0] for item in product_data.items() if + item[1] is None]: + product_data[void_field] = False + product_data['theoretical_qty'] = product_data['product_qty'] + if product_data['product_id']: + product_data['product_uom_id'] = Product.browse( + product_data['product_id']).uom_id.id + quant_products |= Product.browse(product_data['product_id']) + vals.append(product_data) + if self.exhausted: + exhausted_vals = self._get_exhausted_inventory_line( + products_to_filter, quant_products) + vals.extend(exhausted_vals) + return vals diff --git a/stock_inventory_exclude_sublocation/readme/CONTRIBUTORS.rst b/stock_inventory_exclude_sublocation/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..7e28360de --- /dev/null +++ b/stock_inventory_exclude_sublocation/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Lois Rilo Antelo diff --git a/stock_inventory_exclude_sublocation/readme/DESCRIPTION.rst b/stock_inventory_exclude_sublocation/readme/DESCRIPTION.rst new file mode 100644 index 000000000..1175e27f7 --- /dev/null +++ b/stock_inventory_exclude_sublocation/readme/DESCRIPTION.rst @@ -0,0 +1,9 @@ +This module extends the functionality of Inventory Adjustment to allow you to +exclude all the sublocations when doing an inventory adjustment for a +given location. + +Sometimes we just want to make an inventory adjustment of just one shelf, or +space and forget about extra subdivisions in the location. In other cases we +do inventories of smaller locations contained in our stock, so we don't want +to count them again when doing an inventory adjustment of the parent location. +E.g. if we apply a cycle count strategy. diff --git a/stock_inventory_exclude_sublocation/readme/USAGE.rst b/stock_inventory_exclude_sublocation/readme/USAGE.rst new file mode 100644 index 000000000..b1c26759c --- /dev/null +++ b/stock_inventory_exclude_sublocation/readme/USAGE.rst @@ -0,0 +1,5 @@ +To use this module, you simply need to: + +#. Create a new inventory adjustment. +#. Select the option inventory of all products. +#. Check the box "Exclude Sublocations". diff --git a/stock_inventory_exclude_sublocation/tests/__init__.py b/stock_inventory_exclude_sublocation/tests/__init__.py index f2e05e912..2d88b76aa 100644 --- a/stock_inventory_exclude_sublocation/tests/__init__.py +++ b/stock_inventory_exclude_sublocation/tests/__init__.py @@ -1,6 +1 @@ -# -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. -# (http://www.eficent.com) -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). - from . import test_exclude_sublocation diff --git a/stock_inventory_exclude_sublocation/tests/test_exclude_sublocation.py b/stock_inventory_exclude_sublocation/tests/test_exclude_sublocation.py index 0fe5afbc2..2f3548240 100644 --- a/stock_inventory_exclude_sublocation/tests/test_exclude_sublocation.py +++ b/stock_inventory_exclude_sublocation/tests/test_exclude_sublocation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Eficent Business and IT Consulting Services S.L. # (http://www.eficent.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). @@ -104,7 +103,7 @@ class TestStockInventoryExcludeSublocation(TransactionCase): if the excluding sublocations option is disabled.""" inventory_location = self._create_inventory_all_products( 'location inventory', self.location, False) - inventory_location.prepare_inventory() + inventory_location.action_start() inventory_location.action_done() lines = inventory_location.line_ids self.assertEqual(len(lines), 2, 'Not all expected products are ' @@ -117,9 +116,9 @@ class TestStockInventoryExcludeSublocation(TransactionCase): 'location inventory', self.location, True) inventory_sublocation = self._create_inventory_all_products( 'sublocation inventory', self.sublocation, True) - inventory_location.prepare_inventory() + inventory_location.action_start() inventory_location.action_done() - inventory_sublocation.prepare_inventory() + inventory_sublocation.action_start() inventory_sublocation.action_done() lines_location = inventory_location.line_ids lines_sublocation = inventory_sublocation.line_ids @@ -137,7 +136,7 @@ class TestStockInventoryExcludeSublocation(TransactionCase): 'lot_id': self.lot_a.id, 'exclude_sublocation': True }) - inventory.prepare_inventory() + inventory.action_start() inventory.action_done() lines = inventory.line_ids self.assertEqual(len(lines), 1, 'The products in the sublocations are ' @@ -149,7 +148,7 @@ class TestStockInventoryExcludeSublocation(TransactionCase): self.quant_model.create({ 'product_id': self.product1.id, 'location_id': self.location.id, - 'qty': 1, + 'quantity': 1, 'owner_id': self.partner, }) inventory = self.inventory_model.sudo(self.user.id).create({ @@ -160,7 +159,7 @@ class TestStockInventoryExcludeSublocation(TransactionCase): 'partner_id': self.partner, 'exclude_sublocation': True }) - inventory.prepare_inventory() + inventory.action_start() lines = inventory.line_ids self.assertEqual(len(lines), 1, 'The products in the sublocations are ' @@ -171,7 +170,7 @@ class TestStockInventoryExcludeSublocation(TransactionCase): self.quant_model.create({ 'product_id': self.product1.id, 'location_id': self.location.id, - 'qty': 1, + 'quantity': 1, 'package_id': self.package.id }) inventory = self.inventory_model.sudo(self.user.id).create({ @@ -181,7 +180,7 @@ class TestStockInventoryExcludeSublocation(TransactionCase): 'package_id': self.package.id, 'exclude_sublocation': True }) - inventory.prepare_inventory() + inventory.action_start() lines = inventory.line_ids self.assertEqual(len(lines), 1, 'The products in the sublocations are ' 'not excluded with package filter.') diff --git a/stock_inventory_exclude_sublocation/views/stock_inventory_view.xml b/stock_inventory_exclude_sublocation/views/stock_inventory_view.xml index c51b076b2..a0fb1b83e 100644 --- a/stock_inventory_exclude_sublocation/views/stock_inventory_view.xml +++ b/stock_inventory_exclude_sublocation/views/stock_inventory_view.xml @@ -5,7 +5,7 @@ - Inventory form view - cycle count extension + Inventory form view - stock_inventory_exclude_sublocation extension stock.inventory