diff --git a/stock_helper/__init__.py b/stock_helper/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/stock_helper/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_helper/__manifest__.py b/stock_helper/__manifest__.py new file mode 100644 index 000000000..6473fbf35 --- /dev/null +++ b/stock_helper/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright 2020-2021 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +{ + "name": "Stock Move Helpers", + "summary": "Add methods shared between various stock modules", + "version": "13.0.1.1.0", + "author": "Camptocamp, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "category": "Hidden", + "depends": ["stock"], + "data": [], + "installable": True, + "license": "LGPL-3", +} diff --git a/stock_helper/models/__init__.py b/stock_helper/models/__init__.py new file mode 100644 index 000000000..88493e35d --- /dev/null +++ b/stock_helper/models/__init__.py @@ -0,0 +1 @@ +from . import stock_location diff --git a/stock_helper/models/stock_location.py b/stock_helper/models/stock_location.py new file mode 100644 index 000000000..cad6d288c --- /dev/null +++ b/stock_helper/models/stock_location.py @@ -0,0 +1,20 @@ +# Copyright 2020-2021 Camptocamp SA (http://www.camptocamp.com) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import models + + +class StockLocation(models.Model): + _inherit = "stock.location" + + def is_sublocation_of(self, others, func=any): + """Return True if self is a sublocation of others (or equal) + + By default, it return True if any other is a parent or equal. + ``all`` can be passed to ``func`` to require all the other locations + to be parent or equal to be True. + """ + self.ensure_one() + # Efficient way to verify that the current location is + # below one of the other location without using SQL. + return func(self.parent_path.startswith(other.parent_path) for other in others) diff --git a/stock_helper/readme/CONTRIBUTORS.rst b/stock_helper/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..48286263c --- /dev/null +++ b/stock_helper/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Guewen Baconnier diff --git a/stock_helper/readme/DESCRIPTION.rst b/stock_helper/readme/DESCRIPTION.rst new file mode 100644 index 000000000..198d259e3 --- /dev/null +++ b/stock_helper/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Add methods to be used by other modules. This is not a functional module. diff --git a/stock_helper/tests/__init__.py b/stock_helper/tests/__init__.py new file mode 100644 index 000000000..e67580e62 --- /dev/null +++ b/stock_helper/tests/__init__.py @@ -0,0 +1 @@ +from . import test_location_is_sublocation_of diff --git a/stock_helper/tests/common.py b/stock_helper/tests/common.py new file mode 100644 index 000000000..871a216ad --- /dev/null +++ b/stock_helper/tests/common.py @@ -0,0 +1,19 @@ +# Copyright 2020-2021 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo.tests import SavepointCase + + +class StockHelperCommonCase(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + + cls.wh = cls.env.ref("stock.warehouse0") + + cls.customer_loc = cls.env.ref("stock.stock_location_customers") + cls.supplier_loc = cls.env.ref("stock.stock_location_suppliers") + cls.stock_loc = cls.wh.lot_stock_id + cls.shelf1_loc = cls.env.ref("stock.stock_location_components") + cls.shelf2_loc = cls.env.ref("stock.stock_location_14") diff --git a/stock_helper/tests/test_location_is_sublocation_of.py b/stock_helper/tests/test_location_is_sublocation_of.py new file mode 100644 index 000000000..f88047727 --- /dev/null +++ b/stock_helper/tests/test_location_is_sublocation_of.py @@ -0,0 +1,48 @@ +# Copyright 2020-2021 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + + +from .common import StockHelperCommonCase + + +class TestStockLocationIsSublocationOf(StockHelperCommonCase): + def test_is_sublocation_of_equal(self): + self.assertTrue(self.shelf1_loc.is_sublocation_of(self.shelf1_loc)) + + def test_is_sublocation_of_equal_child_ko(self): + bin_loc = self.env["stock.location"].create( + {"name": "bin", "location_id": self.shelf1_loc.id} + ) + self.assertFalse(self.shelf1_loc.is_sublocation_of(bin_loc)) + + def test_is_sublocation_of_equal_child_sibling(self): + self.assertFalse(self.shelf1_loc.is_sublocation_of(self.shelf2_loc)) + + def test_is_sublocation_of_any_ok(self): + self.assertTrue( + self.shelf1_loc.is_sublocation_of(self.stock_loc | self.customer_loc) + ) + + def test_is_sublocation_of_any_ko(self): + self.assertFalse( + self.shelf1_loc.is_sublocation_of(self.supplier_loc | self.customer_loc) + ) + + def test_is_sublocation_of_all_ok(self): + self.assertTrue( + self.shelf1_loc.is_sublocation_of( + self.stock_loc | self.stock_loc.location_id, func=all + ) + ) + + def test_is_sublocation_of_all_ko(self): + self.assertFalse( + self.shelf1_loc.is_sublocation_of( + self.stock_loc | self.customer_loc, func=all + ) + ) + self.assertFalse( + self.shelf1_loc.is_sublocation_of( + self.supplier_loc | self.customer_loc, func=all + ) + )