From bb8c1f2f3538d8988dca49cf559aae707eb3f594 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Tue, 9 Sep 2025 11:29:19 -0400 Subject: [PATCH] [MIG] bemade_partner_root_ancestor to 18.0 --- bemade_partner_root_ancestor/__init__.py | 1 + bemade_partner_root_ancestor/__manifest__.py | 32 +++++++++ .../models/__init__.py | 1 + .../models/res_partner.py | 18 +++++ .../tests/__init__.py | 1 + .../tests/test_root_ancestor.py | 71 +++++++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 bemade_partner_root_ancestor/__init__.py create mode 100644 bemade_partner_root_ancestor/__manifest__.py create mode 100644 bemade_partner_root_ancestor/models/__init__.py create mode 100644 bemade_partner_root_ancestor/models/res_partner.py create mode 100644 bemade_partner_root_ancestor/tests/__init__.py create mode 100644 bemade_partner_root_ancestor/tests/test_root_ancestor.py diff --git a/bemade_partner_root_ancestor/__init__.py b/bemade_partner_root_ancestor/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/bemade_partner_root_ancestor/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/bemade_partner_root_ancestor/__manifest__.py b/bemade_partner_root_ancestor/__manifest__.py new file mode 100644 index 0000000..64f6d65 --- /dev/null +++ b/bemade_partner_root_ancestor/__manifest__.py @@ -0,0 +1,32 @@ +# +# Bemade Inc. +# +# Copyright (C) June 2023 Bemade Inc. (). +# Author: mdurepos (Contact : it@bemade.org) +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +{ + "name": "Partner Root Ancestor", + "version": "18.0.1.0.0", + "summary": "Technical module to add the field root_ancestor to res.partner.", + "category": "Generic Modules/Base", + "author": "Bemade Inc.", + "website": "https://www.bemade.org", + "license": "OPL-1", + "depends": ["base"], + "data": [], + "demo": [], + "installable": True, + "auto_install": False, +} diff --git a/bemade_partner_root_ancestor/models/__init__.py b/bemade_partner_root_ancestor/models/__init__.py new file mode 100644 index 0000000..91fed54 --- /dev/null +++ b/bemade_partner_root_ancestor/models/__init__.py @@ -0,0 +1 @@ +from . import res_partner diff --git a/bemade_partner_root_ancestor/models/res_partner.py b/bemade_partner_root_ancestor/models/res_partner.py new file mode 100644 index 0000000..3cf4dbb --- /dev/null +++ b/bemade_partner_root_ancestor/models/res_partner.py @@ -0,0 +1,18 @@ +from odoo import models, fields, api, _, Command + + +class Partner(models.Model): + _inherit = 'res.partner' + + root_ancestor = fields.Many2one( + comodel_name='res.partner', + string='Root Ancestor', + compute='_compute_root_ancestor', + store=True, + recursive=True + ) + + @api.depends('parent_id', 'parent_id.root_ancestor') + def _compute_root_ancestor(self): + for rec in self: + rec.root_ancestor = rec.parent_id and rec.parent_id.root_ancestor or rec diff --git a/bemade_partner_root_ancestor/tests/__init__.py b/bemade_partner_root_ancestor/tests/__init__.py new file mode 100644 index 0000000..77fc5d6 --- /dev/null +++ b/bemade_partner_root_ancestor/tests/__init__.py @@ -0,0 +1 @@ +from . import test_root_ancestor diff --git a/bemade_partner_root_ancestor/tests/test_root_ancestor.py b/bemade_partner_root_ancestor/tests/test_root_ancestor.py new file mode 100644 index 0000000..b7b0935 --- /dev/null +++ b/bemade_partner_root_ancestor/tests/test_root_ancestor.py @@ -0,0 +1,71 @@ +from odoo.tests.common import TransactionCase + + +class TestPartnerRootAncestor(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + partner = cls.env["res.partner"] + cls.common_ancestor = partner.create( + { + "name": "Parnter name", + "company_type": "company", + } + ) + cls.first_child = partner.create( + { + "name": "Child name", + "company_type": "company", + "parent_id": cls.common_ancestor.id, + } + ) + cls.second_child = partner.create( + { + "name": "Child name", + "company_type": "company", + "parent_id": cls.common_ancestor.id, + } + ) + cls.first_grandchild = partner.create( + { + "name": "Grandchild name", + "company_type": "person", + "parent_id": cls.first_child.id, + } + ) + cls.second_grandchild = partner.create( + { + "name": "Grandchild name", + "company_type": "person", + "parent_id": cls.second_child.id, + } + ) + cls.unrelated_partner = partner.create( + { + "name": "Unrelated partner", + } + ) + cls.relatives = [ + cls.common_ancestor, + cls.first_child, + cls.second_child, + cls.first_grandchild, + cls.second_grandchild, + ] + + def test_base_case(self): + for r1 in self.relatives: + self.assertFalse(r1.root_ancestor == self.unrelated_partner) + for r2 in self.relatives: + self.assertTrue(r1.root_ancestor == r2.root_ancestor) + + def test_new_relative(self): + new_relative = self.env["res.partner"].create( + { + "name": "Whatever", + "company_type": "person", + "parent_id": self.second_grandchild.id, + } + ) + for r1 in self.relatives: + self.assertTrue(r1.root_ancestor == new_relative.root_ancestor)