Skip to content

Commit

Permalink
Allow creation of partners from *Create and Edit*.
Browse files Browse the repository at this point in the history
This fixes OCA#78 and adds new tests for it.
  • Loading branch information
Jairo Llopis authored and rven committed Sep 30, 2019
1 parent 5267765 commit da49613
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 12 deletions.
4 changes: 2 additions & 2 deletions partner_firstname/__openerp__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
{
'name': 'Partner first name and last name',
'summary': "Split first name and last name for non company partners",
'version': '8.0.2.0.0',
'author': "Camptocamp, Odoo Community Association (OCA)",
'version': '8.0.2.0.1',
'author': "Camptocamp, Grupo ESOC, Odoo Community Association (OCA)",
"license": "AGPL-3",
'maintainer': 'Camptocamp, Acsone',
'category': 'Extra Tools',
Expand Down
42 changes: 34 additions & 8 deletions partner_firstname/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,45 @@ class ResPartner(models.Model):
@api.model
def create(self, vals):
"""Add inverted names at creation if unavailable."""
if "name" in vals:
context = dict(self.env.context)
name = vals.get("name", context.get("default_name"))

if name is not None:
# Calculate the splitted fields
inverted = self._get_inverse_name(
vals.get("name"),
self._get_whitespace_cleaned_name(name),
vals.get("is_company",
self.default_get(["is_company"])["is_company"]))

for key, value in inverted.iteritems():
if not vals.get(key):
if not vals.get(key) or context.get("copy"):
vals[key] = value

return super(ResPartner, self).create(vals)
# Remove the combined fields
if "name" in vals:
del vals["name"]
if "default_name" in context:
del context["default_name"]

return super(ResPartner, self.with_context(context)).create(vals)

@api.multi
def copy(self, default=None):
"""Ensure partners are copied right.
Odoo adds ``(copy)`` to the end of :attr:`~.name`, but that would get
ignored in :meth:`~.create` because it also copies explicitly firstname
and lastname fields.
"""
return super(ResPartner, self.with_context(copy=True)).copy(default)

@api.model
def default_get(self, fields_list):
"""Invert name when getting default values."""
result = super(ResPartner, self).default_get(fields_list)

inverted = self._get_inverse_name(
result.get("name", ""),
self._get_whitespace_cleaned_name(result.get("name", "")),
result.get("is_company", False))

for field in inverted.keys():
Expand All @@ -85,13 +105,11 @@ def _compute_name(self):
def _inverse_name_after_cleaning_whitespace(self):
"""Clean whitespace in :attr:`~.name` and split it.
Removes leading, trailing and duplicated whitespace.
The splitting logic is stored separately in :meth:`~._inverse_name`, so
submodules can extend that method and get whitespace cleaning for free.
"""
# Remove unneeded whitespace
clean = u" ".join(self.name.split(None)) if self.name else self.name
clean = self._get_whitespace_cleaned_name(self.name)

# Clean name avoiding infinite recursion
if self.name != clean:
Expand All @@ -101,6 +119,14 @@ def _inverse_name_after_cleaning_whitespace(self):
else:
self._inverse_name()

@api.model
def _get_whitespace_cleaned_name(self, name):
"""Remove redundant whitespace from :param:`name`.
Removes leading, trailing and duplicated whitespace.
"""
return u" ".join(name.split(None)) if name else name

@api.model
def _get_inverse_name(self, name, is_company=False):
"""Compute the inverted name.
Expand Down
3 changes: 2 additions & 1 deletion partner_firstname/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#
# Authors: Nemry Jonathan
# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
# 2015: Grupo ESOC <www.grupoesoc.es>
# All Rights Reserved
#
# WARNING: This program as such is intended to be used by professional
Expand All @@ -28,4 +29,4 @@
#
##############################################################################

from . import test_defaults, test_empty, test_name, test_onchange
from . import test_create, test_defaults, test_empty, test_name, test_onchange
2 changes: 1 addition & 1 deletion partner_firstname/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def tearDown(self):
def test_copy(self):
"""Copy the partner and compare the result."""
self.expect(self.lastname, u"%s (copy)" % self.firstname)
self.changed = self.original.with_context(lang="en_US").copy()
self.changed = self.original.with_context(copy=True, lang="en_US").copy()

def test_one_name(self):
"""Test what happens when only one name is given."""
Expand Down
81 changes: 81 additions & 0 deletions partner_firstname/tests/test_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# © 2015 Grupo ESOC Ingeniería de Servicios, S.L. - Jairo Llopis.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

"""Test default values for models."""

from openerp.tests.common import TransactionCase
from .base import MailInstalled


class PersonCase(TransactionCase):
"""Test ``res.partner`` when it is a person."""
context = {"default_is_company": False}
model = "res.partner"

def setUp(self):
super(PersonCase, self).setUp()
self.good_values = {
"firstname": u"Núñez",
"lastname": u"Fernán",
}
self.good_values["name"] = "%s %s" % (self.good_values["lastname"],
self.good_values["firstname"])
if "default_is_company" in self.context:
self.good_values["is_company"] = self.context["default_is_company"]
self.values = self.good_values.copy()

def tearDown(self):
self.record = (self.env[self.model]
.with_context(self.context)
.create(self.values))

for key, value in self.good_values.iteritems():
self.assertEqual(
self.record[key],
value,
"Checking key %s" % key)

super(PersonCase, self).tearDown()

def test_no_name(self):
"""Name is calculated."""
del self.values["name"]

def test_wrong_name_value(self):
"""Wrong name value is ignored, name is calculated."""
self.values["name"] = u"BÄD"

def test_wrong_name_context(self):
"""Wrong name context is ignored, name is calculated."""
del self.values["name"]
self.context["default_name"] = u"BÄD"

def test_wrong_name_value_and_context(self):
"""Wrong name value and context is ignored, name is calculated."""
self.values["name"] = u"BÄD1"
self.context["default_name"] = u"BÄD2"


class CompanyCase(PersonCase):
"""Test ``res.partner`` when it is a company."""
context = {"default_is_company": True}

def setUp(self):
return super(CompanyCase, self).setUp()
self.values.update(lastname=self.values["name"], firstname=False)


class UserCase(PersonCase, MailInstalled):
"""Test ``res.users``."""
model = "res.users"
context = {"default_login": "user@example.com"}

def tearDown(self):
# Cannot create users if ``mail`` is installed
if self.mail_installed():
# Skip tests
super(PersonCase, self).tearDown()
else:
# Run tests
super(UserCase, self).tearDown()

0 comments on commit da49613

Please sign in to comment.