From 40edae15b88f392174b9e50804fa67e025b6c687 Mon Sep 17 00:00:00 2001 From: davidmonterocrespo24 Date: Tue, 12 May 2026 23:28:57 +0200 Subject: [PATCH] fix(odoo-mail): forward velxio_user_id on password-reset payload Adds velxio_user_id to the send_password_reset payload (mirroring send_welcome). The Odoo side's res_partner.velxio_user_id is unique, so when Odoo eventually upserts on this endpoint the constraint serializes concurrent register-then-immediately-forgot upserts and prevents the duplicate-partner record the previous wire format risked. --- backend/app/api/routes/auth.py | 1 + backend/app/services/odoo_mail.py | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/backend/app/api/routes/auth.py b/backend/app/api/routes/auth.py index a6e7131f..84ecec31 100644 --- a/backend/app/api/routes/auth.py +++ b/backend/app/api/routes/auth.py @@ -216,6 +216,7 @@ async def forgot_password( reset_url=reset_url, expires_in_minutes=settings.PASSWORD_RESET_TOKEN_TTL_MINUTES, user_name=user.username, + velxio_user_id=user.id, ) ) logger.info("[forgot-password] token minted user=%s", user.id) diff --git a/backend/app/services/odoo_mail.py b/backend/app/services/odoo_mail.py index 5459cc7d..8abc0859 100644 --- a/backend/app/services/odoo_mail.py +++ b/backend/app/services/odoo_mail.py @@ -112,11 +112,18 @@ async def send_password_reset( reset_url: str, expires_in_minutes: int = 60, user_name: Optional[str] = None, + velxio_user_id: Optional[str] = None, ) -> bool: """Ask Odoo to deliver a password-reset mail with the given URL. The caller (Velxio backend) is the source of truth for the one-time token; Odoo only renders the email. + + `velxio_user_id` is forwarded so the Odoo side can upsert/match the + partner by stable user id (mirroring the send-welcome payload). This + removes the register-then-immediately-forgot race: with the id in + hand, send-password-reset can upsert the partner before delivering + the mail, so it no longer matters which endpoint reaches Odoo first. """ params: dict = { "email": email, @@ -125,6 +132,8 @@ async def send_password_reset( } if user_name: params["user_name"] = user_name + if velxio_user_id: + params["velxio_user_id"] = velxio_user_id result = await _post("/velxio/api/send-password-reset", params) return bool(result and result.get("sent"))