Browse Source

[MIG] partner_fistname: Migration to 13.0

Remove kack on context and pseudo onchange methods and takes benefit on compute method with readonly=False
14.0
Laurent Mignon (ACSONE) 5 years ago
committed by Luis Torres
parent
commit
8fdc75a622
  1. 3
      partner_firstname/exceptions.py
  2. 31
      partner_firstname/models/res_partner.py
  3. 1
      partner_firstname/readme/CONTRIBUTORS.rst
  4. 4
      partner_firstname/tests/__init__.py
  5. 12
      partner_firstname/tests/base.py
  6. 2
      partner_firstname/tests/test_name.py
  7. 104
      partner_firstname/tests/test_onchange.py
  8. 103
      partner_firstname/tests/test_partner_form.py
  9. 59
      partner_firstname/tests/test_user_form.py
  10. 51
      partner_firstname/tests/test_user_onchange.py
  11. 4
      partner_firstname/views/base_config_view.xml

3
partner_firstname/exceptions.py

@ -4,7 +4,8 @@ from odoo import _, exceptions
class EmptyNamesError(exceptions.ValidationError):
def __init__(self, record, value=_("No name is set.")):
def __init__(self, record, value=None):
value = value or _("No name is set.")
self.record = record
self._value = value
self.name = _("Error(s) with partner %d's name.") % record.id

31
partner_firstname/models/res_partner.py

@ -23,6 +23,7 @@ class ResPartner(models.Model):
inverse="_inverse_name_after_cleaning_whitespace",
required=False,
store=True,
readonly=False,
)
@api.model
@ -117,14 +118,8 @@ class ResPartner(models.Model):
for record in self:
# Remove unneeded whitespace
clean = record._get_whitespace_cleaned_name(record.name)
# Clean name avoiding infinite recursion
if record.name != clean:
record.name = clean
# Save name in the real fields
else:
record._inverse_name()
record.name = clean
record._inverse_name()
@api.model
def _get_whitespace_cleaned_name(self, name, comma=False):
@ -202,26 +197,6 @@ class ResPartner(models.Model):
):
raise exceptions.EmptyNamesError(record)
@api.onchange("firstname", "lastname")
def _onchange_subnames(self):
"""Avoid recursion when the user changes one of these fields.
This forces to skip the :attr:`~.name` inversion when the user is
setting it in a not-inverted way.
"""
# Modify self's context without creating a new Environment.
# See https://github.com/odoo/odoo/issues/7472#issuecomment-119503916.
self.env.context = self.with_context(skip_onchange=True).env.context
@api.onchange("name")
def _onchange_name(self):
"""Ensure :attr:`~.name` is inverted in the UI."""
if self.env.context.get("skip_onchange"):
# Do not skip next onchange
self.env.context = self.with_context(skip_onchange=False).env.context
else:
self._inverse_name_after_cleaning_whitespace()
@api.model
def _install_partner_firstname(self):
"""Save names correctly in the database.

1
partner_firstname/readme/CONTRIBUTORS.rst

@ -16,3 +16,4 @@
* Pedro Baeza <pedro.baeza@serviciosbaeza.com>
* Dave Lasley <dave@laslabs.com>
* Graeme Gellatly <graeme@o4sb.com>
* Laurent Mignon <laurent.mignon@acsone.eu>

4
partner_firstname/tests/__init__.py

@ -4,8 +4,8 @@ from . import (
test_delete,
test_empty,
test_name,
test_onchange,
test_user_onchange,
test_partner_form,
test_user_form,
test_order,
test_copy,
)

12
partner_firstname/tests/base.py

@ -40,7 +40,7 @@ class BaseCase(TransactionCase, MailInstalled):
for field in ("name", "lastname", "firstname"):
self.assertEqual(
getattr(self.changed, field),
self.changed[field],
getattr(self, field),
"Test failed with wrong %s" % field,
)
@ -63,13 +63,3 @@ class BaseCase(TransactionCase, MailInstalled):
self.check_fields = False
with self.assertRaises(ex.EmptyNamesError):
self.original.firstname = self.original.lastname = False
class OnChangeCase(TransactionCase):
is_company = False
def new_partner(self):
"""Create an empty partner. Ensure it is (or not) a company."""
new = self.env["res.partner"].new()
new.is_company = self.is_company
return new

2
partner_firstname/tests/test_name.py

@ -48,7 +48,7 @@ class PartnerContactCase(BaseCase):
self.original.name = " newfïrstname newlästname "
# Need this to refresh the ``name`` field
self.original.invalidate_cache()
self.original.invalidate_cache(["name"])
class PartnerCompanyCase(BaseCase):

104
partner_firstname/tests/test_onchange.py

@ -1,104 +0,0 @@
# Copyright 2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
"""These tests try to mimic the behavior of the UI form.
The form operates in onchange mode, with its limitations.
"""
from .base import OnChangeCase
class PartnerCompanyCase(OnChangeCase):
is_company = True
def test_create_from_form(self):
"""A user creates a company from the form."""
name = "Sôme company"
with self.env.do_in_onchange():
# User presses ``new``
partner = self.new_partner()
# User sets a name, which triggers onchanges
partner.name = name
partner._onchange_name()
self.assertEqual(partner.name, name)
self.assertEqual(partner.firstname, False)
self.assertEqual(partner.lastname, name)
def test_empty_name_and_subnames(self):
"""If the user empties ``name``, subnames must be ``False``.
Otherwise, the ``required`` attr will not work as expected.
"""
with self.env.do_in_onchange():
# User presses ``new``
partner = self.new_partner()
# User sets a name, which triggers onchanges
partner.name = "Foó"
partner._onchange_name()
# User unsets name, which triggers onchanges
partner.name = ""
partner._onchange_name()
self.assertEqual(partner.firstname, False)
self.assertEqual(partner.lastname, False)
class PartnerContactCase(OnChangeCase):
def test_create_from_form_only_firstname(self):
"""A user creates a contact with only the firstname from the form."""
firstname = "Fïrst"
with self.env.do_in_onchange():
# User presses ``new``
partner = self.new_partner()
# Changes firstname, which triggers onchanges
partner.firstname = firstname
partner._onchange_subnames()
partner._onchange_name()
self.assertEqual(partner.lastname, False)
self.assertEqual(partner.firstname, firstname)
self.assertEqual(partner.name, firstname)
def test_create_from_form_only_lastname(self):
"""A user creates a contact with only the lastname from the form."""
lastname = "Läst"
with self.env.do_in_onchange():
# User presses ``new``
partner = self.new_partner()
# Changes lastname, which triggers onchanges
partner.lastname = lastname
partner._onchange_subnames()
partner._onchange_name()
self.assertEqual(partner.firstname, False)
self.assertEqual(partner.lastname, lastname)
self.assertEqual(partner.name, lastname)
def test_create_from_form_all(self):
"""A user creates a contact with all names from the form."""
firstname = "Fïrst"
lastname = "Läst"
with self.env.do_in_onchange():
# User presses ``new``
partner = self.new_partner()
# Changes firstname, which triggers onchanges
partner.firstname = firstname
partner._onchange_subnames()
partner._onchange_name()
# Changes lastname, which triggers onchanges
partner.lastname = lastname
partner._onchange_subnames()
partner._onchange_name()
self.assertEqual(partner.lastname, lastname)
self.assertEqual(partner.firstname, firstname)
self.assertEqual(partner.name, " ".join((firstname, lastname)))

103
partner_firstname/tests/test_partner_form.py

@ -0,0 +1,103 @@
# Copyright 2015 Grupo ESOC <www.grupoesoc.es>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
"""These tests try to mimic the behavior of the UI form.
The form operates in onchange mode, with its limitations.
"""
from odoo.tests.common import Form, TransactionCase
from ..exceptions import EmptyNamesError
class PartnerCompanyCase(TransactionCase):
is_company = True
def test_create_from_form(self):
name = "Sôme company"
with Form(self.env["res.partner"]) as partner_form:
partner_form.is_company = self.is_company
partner_form.name = name
self.assertEqual(partner_form.name, name)
self.assertEqual(partner_form.firstname, False)
self.assertEqual(partner_form.lastname, name)
def test_empty_name(self):
"""If we empty the name and save the form, EmptyNamesError must
be raised (firstname and lastname are reset...)
"""
with Form(
self.env["res.partner"], view="base.view_partner_simple_form"
) as partner_form:
partner_form.is_company = self.is_company
name = "Foó"
# User sets a name
partner_form.name = name
# call save to trigger the inverse
partner_form.save()
self.assertEqual(partner_form.name, name)
self.assertEqual(partner_form.firstname, False)
self.assertEqual(partner_form.lastname, name)
# User unsets name
partner_form.name = ""
# call save to trigger the inverse and therefore raise an exception
with self.assertRaises(EmptyNamesError), self.env.cr.savepoint():
partner_form.save()
name += " bis"
partner_form.name = name
partner_form.save()
self.assertEqual(partner_form.name, name)
self.assertEqual(partner_form.firstname, False)
self.assertEqual(partner_form.lastname, name)
class PartnerContactCase(TransactionCase):
is_company = False
def test_create_from_form_only_firstname(self):
"""A user creates a contact with only the firstname from the form."""
firstname = "Fïrst"
with Form(self.env["res.partner"]) as partner_form:
partner_form.is_company = self.is_company
# Changes firstname, which triggers compute
partner_form.firstname = firstname
self.assertEqual(partner_form.lastname, False)
self.assertEqual(partner_form.firstname, firstname)
self.assertEqual(partner_form.name, firstname)
def test_create_from_form_only_lastname(self):
"""A user creates a contact with only the lastname from the form."""
lastname = "Läst"
with Form(self.env["res.partner"]) as partner_form:
partner_form.is_company = self.is_company
# Changes lastname, which triggers compute
partner_form.lastname = lastname
self.assertEqual(partner_form.firstname, False)
self.assertEqual(partner_form.lastname, lastname)
self.assertEqual(partner_form.name, lastname)
def test_create_from_form_all(self):
"""A user creates a contact with all names from the form."""
firstname = "Fïrst"
lastname = "Läst"
with Form(self.env["res.partner"]) as partner_form:
partner_form.is_company = self.is_company
# Changes firstname, which triggers compute
partner_form.firstname = firstname
# Changes lastname, which triggers compute
partner_form.lastname = lastname
self.assertEqual(partner_form.lastname, lastname)
self.assertEqual(partner_form.firstname, firstname)
self.assertEqual(partner_form.name, " ".join((firstname, lastname)))

59
partner_firstname/tests/test_user_form.py

@ -0,0 +1,59 @@
# Copyright 2016 Yannick Vaucher (Camptocamp SA)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import Form, TransactionCase
class UserOnchangeCase(TransactionCase):
def test_create_from_form_only_firstname(self):
"""In a new users form, a user set only the firstname."""
login = "Zoë"
firstname = "Zoë"
with Form(
self.env["res.users"], view="partner_firstname.view_users_form"
) as user_form:
user_form.login = login
# Changes firstname, which triggers onchanges
user_form.firstname = firstname
self.assertEqual(user_form.lastname, False)
self.assertEqual(user_form.firstname, firstname)
self.assertEqual(user_form.name, firstname)
def test_create_from_form_only_lastname(self):
"""In a new user form, a user set only the lastname."""
login = "Żywioł"
lastname = "Żywioł"
with Form(
self.env["res.users"], view="partner_firstname.view_users_form"
) as user_form:
user_form.login = login
# Changes lastname, which triggers onchanges
user_form.lastname = lastname
self.assertEqual(user_form.firstname, False)
self.assertEqual(user_form.lastname, lastname)
self.assertEqual(user_form.name, lastname)
def test_create_from_form_all(self):
"""In a new user form, a user set all names."""
login = "Zoë.Żywioł"
firstname = "Zoë"
lastname = "Żywioł"
with Form(
self.env["res.users"], view="partner_firstname.view_users_form"
) as user_form:
user_form.login = login
# Changes firstname, which triggers onchanges
user_form.firstname = firstname
# Changes lastname, which triggers onchanges
user_form.lastname = lastname
self.assertEqual(user_form.lastname, lastname)
self.assertEqual(user_form.firstname, firstname)
self.assertEqual(user_form.name, " ".join((firstname, lastname)))
def setUp(self):
super(UserOnchangeCase, self).setUp()
self.user = self.env["res.users"].new()

51
partner_firstname/tests/test_user_onchange.py

@ -1,51 +0,0 @@
# Copyright 2016 Yannick Vaucher (Camptocamp SA)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
class UserOnchangeCase(TransactionCase):
def test_create_from_form_only_firstname(self):
"""In a new users form, a user set only the firstname."""
firstname = "Zoë"
with self.env.do_in_onchange():
# Changes firstname, which triggers onchanges
self.user.firstname = firstname
self.user._compute_name()
self.assertEqual(self.user.lastname, False)
self.assertEqual(self.user.firstname, firstname)
self.assertEqual(self.user.name, firstname)
def test_create_from_form_only_lastname(self):
"""In a new user form, a user set only the lastname."""
lastname = "Żywioł"
with self.env.do_in_onchange():
# Changes lastname, which triggers onchanges
self.user.lastname = lastname
self.user._compute_name()
self.assertEqual(self.user.firstname, False)
self.assertEqual(self.user.lastname, lastname)
self.assertEqual(self.user.name, lastname)
def test_create_from_form_all(self):
"""In a new user form, a user set all names."""
firstname = "Zoë"
lastname = "Żywioł"
with self.env.do_in_onchange():
# Changes firstname, which triggers onchanges
self.user.firstname = firstname
self.user._compute_name()
# Changes lastname, which triggers onchanges
self.user.lastname = lastname
self.user._compute_name()
self.assertEqual(self.user.lastname, lastname)
self.assertEqual(self.user.firstname, firstname)
self.assertEqual(self.user.name, " ".join((firstname, lastname)))
def setUp(self):
super(UserOnchangeCase, self).setUp()
self.user = self.env["res.users"].new()

4
partner_firstname/views/base_config_view.xml

@ -3,13 +3,13 @@
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo>
<record id="view_general_configuration" model="ir.ui.view">
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">Add partner_names_order config parameter</field>
<field name="model">res.config.settings</field>
<field name="inherit_id"
ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='multi_company']" position='after'>
<xpath expr="//div[@id='companies']" position='after'>
<h2>Partner Names Order</h2>
<div class="row mt16 o_settings_container"
name="partner_names_order">

Loading…
Cancel
Save