add partner_email_sync_portal_login

This commit is contained in:
Luis 2026-10-06 12:10:26 +02:00
parent 3c5809774f
commit 3be3de173e
11 changed files with 388 additions and 0 deletions

View file

@ -0,0 +1 @@
from . import res_partner

View file

@ -0,0 +1,102 @@
# Copyright 2026 Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging
from markupsafe import Markup
from odoo import _, models
from odoo.exceptions import UserError
from odoo.tools import email_normalize
_logger = logging.getLogger(__name__)
class ResPartner(models.Model):
_inherit = "res.partner"
def write(self, vals):
res = super().write(vals)
if "email" in vals and not self.env.context.get("skip_portal_login_sync"):
self._sync_portal_user_login()
return res
def _get_portal_users_to_sync(self):
self.ensure_one()
group_portal = self.env.ref("base.group_portal")
return self.sudo().user_ids.filtered(lambda u: group_portal in u.groups_id)
def _sync_portal_user_login(self):
"""Set the partner email as login of its portal users and send them
a password reset email."""
Users = self.env["res.users"].sudo().with_context(active_test=False)
for partner in self:
users = partner._get_portal_users_to_sync()
if not users:
continue
new_login = email_normalize(partner.email)
if not new_login:
_logger.info(
"Portal login not synced for partner %s: invalid email %r",
partner.id,
partner.email,
)
continue
for user in users:
if email_normalize(user.login) == new_login:
continue
if Users.search_count(
[("login", "=", new_login), ("id", "!=", user.id)]
):
raise UserError(
_(
"Cannot change the email of %(partner)s: there is "
"already a user with login %(login)s.",
partner=partner.display_name,
login=new_login,
)
)
old_login = user.login
user.write({"login": new_login})
_logger.info(
"Portal user %s login changed from %s to %s",
user.id,
old_login,
new_login,
)
if self.env.context.get("portal_login_sync_no_mail"):
body = _(
"Portal user login changed from %(old)s to %(new)s.",
old=old_login,
new=new_login,
)
else:
body = partner._send_portal_login_reset_password(
user, old_login, new_login
)
partner.sudo().message_post(body=Markup("<p>%s</p>") % body)
def _send_portal_login_reset_password(self, user, old_login, new_login):
try:
with self.env.cr.savepoint():
user.action_reset_password()
except Exception as e:
# Do not block the email change if the reset email cannot be sent
_logger.warning(
"Password reset email for portal user %s could not be sent: %s",
user.id,
e,
)
return _(
"Portal user login changed from %(old)s to %(new)s, but the "
"password reset email could not be sent: %(error)s",
old=old_login,
new=new_login,
error=str(e),
)
return _(
"Portal user login changed from %(old)s to %(new)s and a password "
"reset email has been sent.",
old=old_login,
new=new_login,
)