Skip to content

Commit

Permalink
[ADD]website_contact_lastname: New module to set lastname from portal
Browse files Browse the repository at this point in the history
  • Loading branch information
manuelregidor committed Sep 14, 2023
1 parent 1e6bec1 commit aee206b
Show file tree
Hide file tree
Showing 19 changed files with 449 additions and 0 deletions.
3 changes: 3 additions & 0 deletions oca_dependencies.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# See https://github.com/OCA/odoo-community.org/blob/master/website/Contribution/CONTRIBUTING.rst#oca_dependencies-txt
e-commerce
partner-contact
6 changes: 6 additions & 0 deletions setup/website_contact_lastname/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
5 changes: 5 additions & 0 deletions website_contact_lastname/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import controllers
from . import models
23 changes: 23 additions & 0 deletions website_contact_lastname/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

{
"name": "Website Contact Lastname",
"version": "15.0.1.0.0",
"category": "Website",
"website": "https://github.com/OCA/website",
"author": "Sygel Technology," "Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"auth_signup",
"website_account_fiscal_position_partner_type",
"partner_firstname",
],
"data": [
"views/templates.xml",
"views/auth_signup_login_templates.xml",
"views/portal_templates.xml",
],
}
5 changes: 5 additions & 0 deletions website_contact_lastname/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import main
from . import portal
159 changes: 159 additions & 0 deletions website_contact_lastname/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import _
from odoo.http import request

from odoo.addons.auth_signup.controllers.main import AuthSignupHome
from odoo.addons.website_sale.controllers.main import WebsiteSale


class WebsiteSale(WebsiteSale):
def _get_mandatory_fields_shipping(self, country_id=False):
req = super()._get_mandatory_fields_shipping(country_id)
req += ["firstname"]

Check warning on line 14 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L13-L14

Added lines #L13 - L14 were not covered by tests
if "name" in req:
req.remove("name")
return req

Check warning on line 17 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L16-L17

Added lines #L16 - L17 were not covered by tests

def _get_mandatory_fields_billing(self, country_id=False):
req = super()._get_mandatory_fields_billing(country_id)
req.append("firstname")

Check warning on line 21 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L20-L21

Added lines #L20 - L21 were not covered by tests
if request.env.context.get("fiscal_position_type") == "b2c":
req.append("lastname")

Check warning on line 23 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L23

Added line #L23 was not covered by tests
# Name is removed as this field cannot be explicitly edited
# It is edited in the backend through the fields first name
# and lastname
if "name" in req:
req.remove("name")
return req

Check warning on line 29 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L28-L29

Added lines #L28 - L29 were not covered by tests

def values_postprocess(self, order, mode, values, errors, error_msg):
new_values, errors, error_msg = super(WebsiteSale, self).values_postprocess(

Check warning on line 32 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L32

Added line #L32 was not covered by tests
order=order, mode=mode, values=values, errors=errors, error_msg=error_msg
)
new_values.update(

Check warning on line 35 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L35

Added line #L35 was not covered by tests
{
"firstname": values.get("firstname") or "",
"lastname": values.get("lastname") or "",
}
)
# Name is removed as this field cannot be explicitly edited
# It is edited in the backend through the fields first name
# and lastname
new_values.pop("name")
return new_values, errors, error_msg

Check warning on line 45 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L44-L45

Added lines #L44 - L45 were not covered by tests

def checkout_form_validate(self, mode, all_form_values, data):
required_fields = [
f for f in (all_form_values.get("field_required") or "").split(",") if f
]
# Name is removed as this field cannot be explicitly edited
# It is edited in the backend through the fields first name
# and lastname
if "name" in required_fields:
required_fields.remove("name")
all_form_values["field_required"] = ",".join(required_fields)
error, error_message = super().checkout_form_validate(

Check warning on line 57 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L55-L57

Added lines #L55 - L57 were not covered by tests
mode, all_form_values, data
)
if data.get("partner_id"):
partner_su = (

Check warning on line 61 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L61

Added line #L61 was not covered by tests
request.env["res.partner"]
.sudo()
.browse(int(data["partner_id"]))
.exists()
)
can_edit_vat = (

Check warning on line 67 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L67

Added line #L67 was not covered by tests
partner_su.parent_id.can_edit_vat()
if partner_su.parent_id
else partner_su.can_edit_vat()
)
firstname_change = (

Check warning on line 72 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L72

Added line #L72 was not covered by tests
partner_su
and "firstname" in data
and data["firstname"] != partner_su.firstname
)
if firstname_change and not can_edit_vat:
error["firstname"] = "error"
error_message.append(

Check warning on line 79 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L78-L79

Added lines #L78 - L79 were not covered by tests
_(
"Changing your name is not allowed once invoices have been"
" issued for your account. Please contact us directly for "
"this operation."
)
)
# When lastname field in form is empty, its values is False
# When lastname field in backend is empty, its values is ''
# In that case, if both are compared, they are considered to be
# different so data['lastname'] != partner_su.lastname would
# return True although no real change would have been applied.
lastname_change = (

Check warning on line 91 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L91

Added line #L91 was not covered by tests
partner_su
and "lastname" in data
and data["lastname"] != partner_su.lastname
and (data["lastname"] or partner_su.lastname not in ["", False])
)
if lastname_change and not can_edit_vat:
error["lastname"] = "error"
error_message.append(

Check warning on line 99 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L98-L99

Added lines #L98 - L99 were not covered by tests
_(
"Changing your last name is not allowed once invoices have"
" been issued for your account. Please contact us directly"
" for this operation."
)
)

# Prevent change the partner name, lastname if
# it is an internal user.
if (firstname_change or lastname_change) and not all(
partner_su.user_ids.mapped("share")
):
error.update(

Check warning on line 112 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L112

Added line #L112 was not covered by tests
{
"firstname": "error" if firstname_change else None,
"lastname": "error" if lastname_change else None,
}
)
error_message.append(

Check warning on line 118 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L118

Added line #L118 was not covered by tests
_(
"If you are ordering for an external person, please place "
"your order via the backend. If you wish to change your "
"name or last name, please do so in the account settings "
"or contact your administrator."
)
)
return error, error_message

Check warning on line 126 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L126

Added line #L126 was not covered by tests


class AuthSignupHome(AuthSignupHome):
def get_auth_signup_qcontext(self):
qcontext = super().get_auth_signup_qcontext()

Check warning on line 131 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L131

Added line #L131 was not covered by tests
qcontext.update(
{
k: v
for (k, v) in request.params.items()
if k
in {
"lastname",
}
}
)
if "name" in qcontext:
qcontext["firstname"] = qcontext["name"]

Check warning on line 143 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L143

Added line #L143 was not covered by tests
if (
"error" not in qcontext
and request.httprequest.method == "POST"
and qcontext.get("fiscal_position_type") == "b2c"
and not qcontext.get("lastname")
):
qcontext["error"] = _("Lastname is required for B2C users.")
return qcontext

Check warning on line 151 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L150-L151

Added lines #L150 - L151 were not covered by tests

def _prepare_signup_values(self, qcontext):
values = super()._prepare_signup_values(qcontext)

Check warning on line 154 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L154

Added line #L154 was not covered by tests
if "firstname" in qcontext:
values["firstname"] = qcontext["firstname"]

Check warning on line 156 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L156

Added line #L156 was not covered by tests
if "lastname" in qcontext:
values["lastname"] = qcontext["lastname"]
return values

Check warning on line 159 in website_contact_lastname/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/main.py#L158-L159

Added lines #L158 - L159 were not covered by tests
63 changes: 63 additions & 0 deletions website_contact_lastname/controllers/portal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo import _
from odoo.http import request

from odoo.addons.portal.controllers.portal import CustomerPortal


class CustomerPortal(CustomerPortal):

CustomerPortal.OPTIONAL_BILLING_FIELDS += [
"firstname",
"lastname",
]

def details_form_validate(self, data):
context = dict(request.env.context)

Check warning on line 18 in website_contact_lastname/controllers/portal.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/portal.py#L18

Added line #L18 was not covered by tests
# 'name' field cannont be updated as it would recompute fields
# firstname and lastname. That is why it is set in context
# that changes in field name need to be ignored.
context.update({"name_ignore": True})
request.env.context = context
error, error_message = super().details_form_validate(data)
partner = request.env.user.partner_id

Check warning on line 25 in website_contact_lastname/controllers/portal.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/portal.py#L22-L25

Added lines #L22 - L25 were not covered by tests
if partner.can_edit_vat():
if "firstname" in data and not data.get("Name"):
error["firstname"] = "error"
error_message.append(_("Firstname is mandatory."))

Check warning on line 29 in website_contact_lastname/controllers/portal.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/portal.py#L28-L29

Added lines #L28 - L29 were not covered by tests
if (
"lastname" in data
and not data.get("lastname")
and (
(data.get("fiscal_position_type") == "b2c")
or (
partner.fiscal_position_type == "b2c"
and not data.get("fiscal_position_type") == "b2b"
)
)
):
error["lastname"] = "error"
error["fiscal_position_type"] = "error"
error_message.append(_("Lastname is mandatory for B2C users."))

Check warning on line 43 in website_contact_lastname/controllers/portal.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/portal.py#L41-L43

Added lines #L41 - L43 were not covered by tests
else:
if "firstname" in data and data.get("firstname") != partner.firstname:
error["firstname"] = "error"
error_message.append(

Check warning on line 47 in website_contact_lastname/controllers/portal.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/portal.py#L46-L47

Added lines #L46 - L47 were not covered by tests
_(
"Changing Name is not allowed once document(s) have been "
"issued for your account. Please contact us directly for "
"this operation."
)
)
if "lastname" in data and data.get("lastname") != partner.lastname:
error["lastname"] = "error"
error_message.append(

Check warning on line 56 in website_contact_lastname/controllers/portal.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/portal.py#L55-L56

Added lines #L55 - L56 were not covered by tests
_(
"Changing Lastname is not allowed once document(s) have "
"been issued for your account. Please contact us directly "
"for this operation."
)
)
return error, error_message

Check warning on line 63 in website_contact_lastname/controllers/portal.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/controllers/portal.py#L63

Added line #L63 was not covered by tests
5 changes: 5 additions & 0 deletions website_contact_lastname/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2023 Manuel Regidor <manuelregidor@sygel.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import res_users
from . import res_partner
26 changes: 26 additions & 0 deletions website_contact_lastname/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3).

from odoo import api, models
from odoo.http import request


class Partner(models.Model):
_inherit = "res.partner"

@api.model
def signup_retrieve_info(self, token):
res = super().signup_retrieve_info(token)
partner = self._signup_retrieve_partner(token, raise_exception=True)
res.update(

Check warning on line 15 in website_contact_lastname/models/res_partner.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_partner.py#L13-L15

Added lines #L13 - L15 were not covered by tests
{
"name": partner.firstname,
"lastname": partner.lastname,
}
)
return res

Check warning on line 21 in website_contact_lastname/models/res_partner.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_partner.py#L21

Added line #L21 was not covered by tests

def write(self, vals):
if vals.get("name") and request.env.context.get("name_ignore"):
vals.pop("name")
return super().write(vals)

Check warning on line 26 in website_contact_lastname/models/res_partner.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_partner.py#L25-L26

Added lines #L25 - L26 were not covered by tests
37 changes: 37 additions & 0 deletions website_contact_lastname/models/res_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3).

from odoo import api, models


class ResUsers(models.Model):
_inherit = "res.users"

@api.model
def signup(self, values, token=None):
if token:
partner = self.env["res.partner"]._signup_retrieve_partner(

Check warning on line 13 in website_contact_lastname/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_users.py#L13

Added line #L13 was not covered by tests
token, check_validity=True, raise_exception=True
)
partner_user = partner.user_ids and partner.user_ids[0] or False

Check warning on line 16 in website_contact_lastname/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_users.py#L16

Added line #L16 was not covered by tests
# Don't update firstname and lastname if partner
# related to user exists (i.e. when resetting password)
if partner_user:
values.pop("firstname", None)
values.pop("lastname", None)
return super().signup(values, token)

Check warning on line 22 in website_contact_lastname/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_users.py#L20-L22

Added lines #L20 - L22 were not covered by tests

def _create_user_from_template(self, values):
user = super()._create_user_from_template(values)

Check warning on line 25 in website_contact_lastname/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_users.py#L25

Added line #L25 was not covered by tests
# Because of the way the name is computed, it is important to
# reset the values so the final name is correct.
# It cannot be done before (the way would be setting the value of name
# if param. values to '') as the funcion _create_user_from_template
# checks that values contains a value for 'name'
user.write(

Check warning on line 31 in website_contact_lastname/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_users.py#L31

Added line #L31 was not covered by tests
{
"firstname": values.get("firstname"),
"lastname": values.get("lastname"),
}
)
return user

Check warning on line 37 in website_contact_lastname/models/res_users.py

View check run for this annotation

Codecov / codecov/patch

website_contact_lastname/models/res_users.py#L37

Added line #L37 was not covered by tests
1 change: 1 addition & 0 deletions website_contact_lastname/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
No configuration needed.
3 changes: 3 additions & 0 deletions website_contact_lastname/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* `Sygel <https://www.sygel.es>`_:

* Manuel Regidor
2 changes: 2 additions & 0 deletions website_contact_lastname/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This module allows users to introduce and edit their lastname
from the portal.
2 changes: 2 additions & 0 deletions website_contact_lastname/readme/USAGE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Lastname field is mandatory for B2C users in portal.
It can be left blank when the user is B2B.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions website_contact_lastname/views/auth_signup_login_templates.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
Copyright 2023 Manuel Regidor <manuel.regidor@sygel.es>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<template id="website_contact_lastname_auth_signup" inherit_id="auth_signup.fields">
<xpath expr="//div[hasclass('field-name')]" position="after">
<div class="form-group field-lastname">
<label for="name">Last Name</label>
<input
type="text"
name="lastname"
t-att-value="lastname"
id="lastname"
class="form-control form-control-sm"
t-att-readonly="'readonly' if only_passwords else None"
t-att-autofocus="'autofocus' if login and not only_passwords else None"
/>
</div>
</xpath>
</template>
</odoo>
Loading

0 comments on commit aee206b

Please sign in to comment.