add partner_email_sync_portal_login
This commit is contained in:
parent
3c5809774f
commit
3be3de173e
11 changed files with 388 additions and 0 deletions
1
partner_email_sync_portal_login/models/__init__.py
Normal file
1
partner_email_sync_portal_login/models/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from . import res_partner
|
||||
102
partner_email_sync_portal_login/models/res_partner.py
Normal file
102
partner_email_sync_portal_login/models/res_partner.py
Normal 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,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue