From 6c9ea0c244c3cc4f627e6c0e5a09a5dc89eeadf7 Mon Sep 17 00:00:00 2001 From: ArnauCForgeFlow Date: Tue, 16 Jul 2024 10:23:51 +0200 Subject: [PATCH] [IMP] partner_multi_company: prevent inconsistencies between user and partner companies --- partner_multi_company/__manifest__.py | 2 +- partner_multi_company/hooks.py | 13 ++++++++ .../migrations/16.0.1.1.0/post-migration.py | 9 +++++ partner_multi_company/models/res_partner.py | 33 ++++++++++++++++++- partner_multi_company/models/res_users.py | 22 ++++++++++--- .../static/description/index.html | 11 ++++--- 6 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 partner_multi_company/migrations/16.0.1.1.0/post-migration.py diff --git a/partner_multi_company/__manifest__.py b/partner_multi_company/__manifest__.py index 776f8355be5..3d1a367acef 100644 --- a/partner_multi_company/__manifest__.py +++ b/partner_multi_company/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Partner multi-company", "summary": "Select individually the partner visibility on each company", - "version": "16.0.1.0.1", + "version": "16.0.1.1.0", "license": "AGPL-3", "depends": ["base_multi_company"], "author": "Tecnativa, " "Odoo Community Association (OCA)", diff --git a/partner_multi_company/hooks.py b/partner_multi_company/hooks.py index dd8c145fb14..cbe5ff33942 100644 --- a/partner_multi_company/hooks.py +++ b/partner_multi_company/hooks.py @@ -31,6 +31,19 @@ def post_init_hook(cr, registry): WHERE company_id IS NOT NULL """ ) + fix_user_partner_companies(cr) + + +def fix_user_partner_companies(cr): + env = api.Environment(cr, SUPERUSER_ID, {}) + for user in env["res.users"].search([]): + user_company_ids = set(user.company_ids.ids) + partner_company_ids = set(user.partner_id.company_ids.ids) + if not user_company_ids.issubset(partner_company_ids) and partner_company_ids: + missing_company_ids = list(user_company_ids - partner_company_ids) + user.partner_id.write( + {"company_ids": [(4, company_id) for company_id in missing_company_ids]} + ) def uninstall_hook(cr, registry): diff --git a/partner_multi_company/migrations/16.0.1.1.0/post-migration.py b/partner_multi_company/migrations/16.0.1.1.0/post-migration.py new file mode 100644 index 00000000000..b3139fa25f4 --- /dev/null +++ b/partner_multi_company/migrations/16.0.1.1.0/post-migration.py @@ -0,0 +1,9 @@ +# Copyright 2024 ForgeFlow S.L. (http://www.forgeflow.com) +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +# pylint: disable=W8150 +from odoo.addons.partner_multi_company import hooks + + +def migrate(cr, version): + hooks.fix_user_partner_companies(cr) diff --git a/partner_multi_company/models/res_partner.py b/partner_multi_company/models/res_partner.py index 7ff0039236e..694be3a10ef 100644 --- a/partner_multi_company/models/res_partner.py +++ b/partner_multi_company/models/res_partner.py @@ -2,7 +2,8 @@ # Copyright 2015-2019 Pedro M. Baeza # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html.html -from odoo import api, fields, models +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class ResPartner(models.Model): @@ -59,3 +60,33 @@ def _amend_company_id(self, vals): elif "company_id" not in vals: vals["company_ids"] = False return vals + + @api.constrains("company_ids") + def _check_company_id(self): + for rec in self: + if rec.user_ids: + user_company_ids = set(rec.user_ids.mapped("company_ids").ids) + partner_company_ids = set(rec.company_ids.ids) + + if ( + not user_company_ids.issubset(partner_company_ids) + and partner_company_ids + ): + raise ValidationError( + _( + "The partner must have at least all the companies " + "associated with the user." + ) + ) + + def _inverse_company_id(self): + if self.env.context.get("from_res_users"): + # don't delete all partner company_ids when + # the user's related company_id is modified. + for record in self: + company = record.company_id + if company: + record.company_ids = [(4, company.id)] + return + else: + return super()._inverse_company_id() diff --git a/partner_multi_company/models/res_users.py b/partner_multi_company/models/res_users.py index e4d942f976e..589819ff32c 100644 --- a/partner_multi_company/models/res_users.py +++ b/partner_multi_company/models/res_users.py @@ -12,16 +12,28 @@ def create(self, vals): res = super(ResUsers, self).create(vals) if "company_ids" in vals: res.partner_id.company_ids = vals["company_ids"] - if "company_id" in vals and res.partner_id.company_ids: - res.partner_id.company_id = vals["company_id"] return res def write(self, vals): - res = super(ResUsers, self).write(vals) + res = super(ResUsers, self.with_context(from_res_users=True)).write(vals) if "company_ids" in vals: for user in self.sudo(): - if user.partner_id.company_ids: - user.partner_id.company_ids = vals["company_ids"] + new_company_ids = [] + company_ids_data = vals["company_ids"] + if isinstance(company_ids_data, list) and user.partner_id.company_ids: + for item in company_ids_data: + if isinstance(item, tuple): + if item[0] == 4: + new_company_ids.append(item[1]) + elif item[0] == 6: + new_company_ids.extend(item[2]) + elif isinstance(item, list): + new_company_ids = item[2] + else: + new_company_ids.append(item) + user.partner_id.company_ids = [ + (4, company_id) for company_id in new_company_ids + ] if "company_id" in vals: for user in self.sudo(): if user.partner_id.company_ids: diff --git a/partner_multi_company/static/description/index.html b/partner_multi_company/static/description/index.html index 3ae1522d1c5..5fb9afe2dde 100644 --- a/partner_multi_company/static/description/index.html +++ b/partner_multi_company/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -437,7 +438,9 @@

Contributors

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

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.