Jairo Llopis
10 years ago
committed by
Jordi Ballester
11 changed files with 869 additions and 0 deletions
-
72partner_second_lastname/README.rst
-
5partner_second_lastname/__init__.py
-
21partner_second_lastname/__openerp__.py
-
68partner_second_lastname/i18n/es.po
-
63partner_second_lastname/i18n/partner_second_lastname.pot
-
97partner_second_lastname/models.py
-
6partner_second_lastname/tests/__init__.py
-
177partner_second_lastname/tests/test_name.py
-
213partner_second_lastname/tests/test_onchange.py
-
105partner_second_lastname/views/res_partner.xml
-
42partner_second_lastname/views/res_user.xml
@ -0,0 +1,72 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:alt: License: AGPL-3 |
|||
|
|||
Partner second lastname |
|||
======================= |
|||
|
|||
This module was written to extend the functionality of ``partner_firstname`` to |
|||
support having a second lastname for contact partners. |
|||
|
|||
In some countries, it's important to have a second last name for contacts. |
|||
|
|||
Contact partners will need to fulfill at least one of the name fields |
|||
(*First name*, *First last name* or *Second last name*). |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
To use this module, you need to: |
|||
|
|||
* Edit any partner's form. |
|||
* Make sure the partner is not a company. |
|||
* Enter firstname and lastnames. |
|||
|
|||
If you directly enter the full name instead of entering the other fields |
|||
separately (maybe from other form), this module will try to guess the best |
|||
match for your input and split it between firstname, lastname and second |
|||
lastname. |
|||
|
|||
If the name you enter is in the form *Firstname Lastname1 Lastname2*, it will |
|||
be split as such. If you use a comma, it will understand it as *Lastname1 |
|||
Lastname2, Firstname*. |
|||
|
|||
If you can, always enter it manually please. Automatic guessing could fail for |
|||
you easily in some corner cases. |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/134/8.0 |
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues |
|||
<https://github.com/OCA/partner-contact/issues>`_. In case of trouble, please |
|||
check there if your issue has already been reported. If you spotted it first, |
|||
help us smashing it by providing a detailed and welcomed feedback `here |
|||
<https://github.com/OCA/partner-contact/issues/new?body=module:%20partner_second_lastname%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. |
|||
|
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* `Grupo ESOC <http://grupoesoc.es>`_: |
|||
* `Jairo Llopis <mailto:j.llopis@grupoesoc.es>`_. |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
OCA, or the Odoo Community Association, is a nonprofit organization whose |
|||
mission is to support the collaborative development of Odoo features and |
|||
promote its widespread use. |
|||
|
|||
To contribute to this module, please visit http://odoo-community.org. |
@ -0,0 +1,5 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
# © 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. |
|||
|
|||
from . import models |
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
# © 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. |
|||
|
|||
{ |
|||
"name": "Partner second last name", |
|||
"version": "8.0.4.0.0", |
|||
"author": "Grupo ESOC, Odoo Community Association (OCA)", |
|||
"license": "AGPL-3", |
|||
"maintainer": "Odoo Community Association (OCA)", |
|||
"category": "Extra Tools", |
|||
"website": "http://www.grupoesoc.es", |
|||
"depends": [ |
|||
"partner_firstname" |
|||
], |
|||
"data": [ |
|||
"views/res_partner.xml", |
|||
"views/res_user.xml", |
|||
], |
|||
"installable": True, |
|||
} |
@ -0,0 +1,68 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * partner_lastname2 |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0-20150327\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2015-08-13 11:16+0100\n" |
|||
"PO-Revision-Date: 2015-08-13 11:16+0100\n" |
|||
"Last-Translator: Jairo Llopis <j.llopis@grupoesoc.es>\n" |
|||
"Language-Team: \n" |
|||
"Language: es_ES\n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: 8bit\n" |
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
|||
"X-Generator: Poedit 1.8.1\n" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: model:ir.model,name:partner_second_lastname.model_res_partner |
|||
msgid "Partner" |
|||
msgstr "Empresa" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: field:res.partner,lastname2:0 |
|||
msgid "Second last name" |
|||
msgstr "Segundo apellido" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: view:res.partner:partner_second_lastname.partner_form |
|||
#: view:res.partner:partner_second_lastname.partner_simple_form |
|||
msgid "" |
|||
"{\n" |
|||
" 'required': [('firstname', '=', False),\n" |
|||
" ('lastname2', '=', False),\n" |
|||
" ('is_company', '=', False)]\n" |
|||
" }" |
|||
msgstr "" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: view:res.users:partner_second_lastname.users_form |
|||
msgid "" |
|||
"{\n" |
|||
" 'required': [('firstname', '=', False),\n" |
|||
" ('lastname2', '=', False)]\n" |
|||
" }" |
|||
msgstr "" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: view:res.partner:partner_second_lastname.partner_form |
|||
#: view:res.partner:partner_second_lastname.partner_simple_form |
|||
msgid "" |
|||
"{\n" |
|||
" 'required': [('lastname', '=', False),\n" |
|||
" ('lastname2', '=', False),\n" |
|||
" ('is_company', '=', False)]\n" |
|||
" }" |
|||
msgstr "" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: view:res.users:partner_second_lastname.users_form |
|||
msgid "" |
|||
"{\n" |
|||
" 'required': [('lastname', '=', False),\n" |
|||
" ('lastname2', '=', False)]\n" |
|||
" }" |
|||
msgstr "" |
@ -0,0 +1,63 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * partner_second_lastname |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 8.0-20150811\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2015-08-13 09:15+0000\n" |
|||
"PO-Revision-Date: 2015-08-13 09:15+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: model:ir.model,name:partner_second_lastname.model_res_partner |
|||
msgid "Partner" |
|||
msgstr "" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: field:res.partner,lastname2:0 |
|||
msgid "Second last name" |
|||
msgstr "" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: view:res.partner:partner_second_lastname.partner_form |
|||
#: view:res.partner:partner_second_lastname.partner_simple_form |
|||
msgid "{\n" |
|||
" 'required': [('firstname', '=', False),\n" |
|||
" ('lastname2', '=', False),\n" |
|||
" ('is_company', '=', False)]\n" |
|||
" }" |
|||
msgstr "" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: view:res.users:partner_second_lastname.users_form |
|||
msgid "{\n" |
|||
" 'required': [('firstname', '=', False),\n" |
|||
" ('lastname2', '=', False)]\n" |
|||
" }" |
|||
msgstr "" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: view:res.partner:partner_second_lastname.partner_form |
|||
#: view:res.partner:partner_second_lastname.partner_simple_form |
|||
msgid "{\n" |
|||
" 'required': [('lastname', '=', False),\n" |
|||
" ('lastname2', '=', False),\n" |
|||
" ('is_company', '=', False)]\n" |
|||
" }" |
|||
msgstr "" |
|||
|
|||
#. module: partner_second_lastname |
|||
#: view:res.users:partner_second_lastname.users_form |
|||
msgid "{\n" |
|||
" 'required': [('lastname', '=', False),\n" |
|||
" ('lastname2', '=', False)]\n" |
|||
" }" |
|||
msgstr "" |
|||
|
@ -0,0 +1,97 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
# © 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. |
|||
|
|||
from openerp import api, fields, models |
|||
from openerp.addons.partner_firstname import exceptions |
|||
|
|||
|
|||
class ResPartner(models.Model): |
|||
"""Adds a second last name.""" |
|||
|
|||
_inherit = "res.partner" |
|||
|
|||
lastname2 = fields.Char("Second last name") |
|||
|
|||
@api.model |
|||
def _get_computed_name(self, lastname, firstname, lastname2=None): |
|||
"""Compute the name combined with the second lastname too. |
|||
|
|||
We have 2 lastnames, so lastnames and firstname will be separated by a |
|||
comma. |
|||
""" |
|||
names = list() |
|||
|
|||
if lastname: |
|||
names.append(lastname) |
|||
if lastname2: |
|||
names.append(lastname2) |
|||
if names and firstname: |
|||
names[-1] = names[-1] + "," |
|||
if firstname: |
|||
names.append(firstname) |
|||
|
|||
return u" ".join(names) |
|||
|
|||
@api.one |
|||
@api.depends("firstname", "lastname", "lastname2") |
|||
def _compute_name(self): |
|||
"""Write :attr:`~.name` according to splitted data.""" |
|||
self.name = self._get_computed_name(self.lastname, |
|||
self.firstname, |
|||
self.lastname2) |
|||
|
|||
@api.one |
|||
def _inverse_name(self): |
|||
"""Try to revert the effect of :meth:`._compute_name`.""" |
|||
parts = self._get_inverse_name(self.name, self.is_company) |
|||
|
|||
# Avoid to hit :meth:`~._check_name` with all 3 fields being ``False`` |
|||
before, after = dict(), dict() |
|||
for key, value in parts.iteritems(): |
|||
(before if value else after)[key] = value |
|||
self.update(before) |
|||
self.update(after) |
|||
|
|||
@api.model |
|||
def _get_inverse_name(self, name, is_company=False): |
|||
"""Compute the inverted name. |
|||
|
|||
- If the partner is a company, save it in the lastname. |
|||
- Otherwise, make a guess. |
|||
""" |
|||
# Company name goes to the lastname |
|||
if is_company or not name: |
|||
parts = [False, name or False, False] |
|||
|
|||
# The comma separates the firstname |
|||
elif "," in name: |
|||
lastnames, firstname = name.split(",", 1) |
|||
parts = [firstname.strip()] + lastnames.split(" ", 1) |
|||
|
|||
# Without comma, the user wrote the firstname first |
|||
else: |
|||
parts = name.split(" ", 2) |
|||
|
|||
while len(parts) < 3: |
|||
parts.append(False) |
|||
|
|||
return {"firstname": parts[0], |
|||
"lastname": parts[1], |
|||
"lastname2": parts[2]} |
|||
|
|||
@api.one |
|||
@api.constrains("firstname", "lastname", "lastname2") |
|||
def _check_name(self): |
|||
"""Ensure at least one name is set.""" |
|||
try: |
|||
super(ResPartner, self)._check_name() |
|||
except exceptions.EmptyNamesError as error: |
|||
if not self.lastname2: |
|||
raise error |
|||
|
|||
@api.one |
|||
@api.onchange("firstname", "lastname", "lastname2") |
|||
def _onchange_subnames(self): |
|||
"""Trigger onchange with :attr:`~.lastname2` too.""" |
|||
super(ResPartner, self)._onchange_subnames() |
@ -0,0 +1,6 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
# © 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. |
|||
|
|||
from . import test_name, test_onchange |
|||
from openerp.addons.partner_firstname.tests import test_empty |
@ -0,0 +1,177 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
# © 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. |
|||
|
|||
from openerp.tests.common import TransactionCase |
|||
from openerp.addons.partner_firstname.tests.base import MailInstalled |
|||
|
|||
|
|||
class CompanyCase(TransactionCase): |
|||
"""Test ``res.partner`` when it is a company.""" |
|||
def tearDown(self): |
|||
try: |
|||
new = self.env["res.partner"].create({ |
|||
"is_company": True, |
|||
"name": self.name, |
|||
}) |
|||
|
|||
# Name should be cleaned of unneeded whitespace |
|||
clean_name = u" ".join(self.name.split(None)) |
|||
|
|||
# Check it's saved OK |
|||
self.assertEqual( |
|||
new.name, |
|||
clean_name, |
|||
"Saved company name is wrong.") |
|||
|
|||
# Check it's saved in the lastname |
|||
self.assertEqual( |
|||
new.lastname, |
|||
clean_name, |
|||
"Company name should be saved in the lastname field.") |
|||
|
|||
# Check that other fields are empty |
|||
self.assertEqual( |
|||
new.firstname, |
|||
False, |
|||
"Company first name must always be empty.") |
|||
self.assertEqual( |
|||
new.lastname2, |
|||
False, |
|||
"Company last name 2 must always be empty.") |
|||
|
|||
finally: |
|||
super(CompanyCase, self).tearDown() |
|||
|
|||
def test_long_name(self): |
|||
"""Create a company with a long name.""" |
|||
self.name = u"Söme very lóng nâme" |
|||
|
|||
def test_short_name(self): |
|||
"""Create a company with a short name.""" |
|||
self.name = u"Shoŕt" |
|||
|
|||
def test_whitespace_before(self): |
|||
"""Create a company with name prefixed with whitespace.""" |
|||
self.name = u" Wĥitespace befòre" |
|||
|
|||
def test_whitespace_after(self): |
|||
"""Create a company with name suffixed with whitespace.""" |
|||
self.name = u"Whitespâce aftér " |
|||
|
|||
def test_whitespace_inside(self): |
|||
"""Create a company with whitespace inside the name.""" |
|||
self.name = u"Whitespacé ïnside" |
|||
|
|||
def test_whitespace_everywhere(self): |
|||
"""Create a company with whitespace everywhere in the name.""" |
|||
self.name = u" A lot öf whitespace " |
|||
|
|||
|
|||
class PersonCase(TransactionCase): |
|||
"""Test ``res.partner`` when it is a person.""" |
|||
model = "res.partner" |
|||
context = dict() |
|||
|
|||
def setUp(self): |
|||
super(PersonCase, self).setUp() |
|||
|
|||
self.firstname = u"Fírstname" |
|||
self.lastname = u"Làstname1" |
|||
self.lastname2 = u"Lâstname2" |
|||
self.template = u"%(last1)s %(last2)s, %(first)s" |
|||
|
|||
def tearDown(self): |
|||
try: |
|||
new = (self.env[self.model].with_context(self.context) |
|||
.create(self.params)) |
|||
|
|||
# Check that each individual field matches |
|||
self.assertEqual( |
|||
self.firstname, |
|||
new.firstname, |
|||
"First name saved badly.") |
|||
self.assertEqual( |
|||
self.lastname, |
|||
new.lastname, |
|||
"Last name 1 saved badly.") |
|||
self.assertEqual( |
|||
self.lastname2, |
|||
new.lastname2, |
|||
"Last name 2 saved badly.") |
|||
|
|||
# Check that name gets saved fine |
|||
self.assertEqual( |
|||
self.template % ({"last1": self.lastname, |
|||
"last2": self.lastname2, |
|||
"first": self.firstname}), |
|||
new.name, |
|||
"Name saved badly.") |
|||
|
|||
finally: |
|||
super(PersonCase, self).tearDown() |
|||
|
|||
def test_firstname_first(self): |
|||
"""Create a person setting his first name first.""" |
|||
self.params = { |
|||
"is_company": False, |
|||
"name": "%s %s %s" % (self.firstname, |
|||
self.lastname, |
|||
self.lastname2), |
|||
} |
|||
|
|||
def test_firstname_last(self): |
|||
"""Create a persong setting his first name last.""" |
|||
self.params = { |
|||
"is_company": False, |
|||
"name": "%s %s, %s" % (self.lastname, |
|||
self.lastname2, |
|||
self.firstname), |
|||
} |
|||
|
|||
def test_firstname_only(self): |
|||
"""Create a persong setting his first name only.""" |
|||
self.lastname = self.lastname2 = False |
|||
self.template = "%(first)s" |
|||
self.params = { |
|||
"is_company": False, |
|||
"name": self.firstname, |
|||
} |
|||
|
|||
def test_firstname_lastname_only(self): |
|||
"""Create a persong setting his first name and last name 1 only.""" |
|||
self.lastname2 = False |
|||
self.template = "%(last1)s, %(first)s" |
|||
self.params = { |
|||
"is_company": False, |
|||
"name": "%s %s" % (self.firstname, self.lastname), |
|||
} |
|||
|
|||
def test_lastname_firstname_only(self): |
|||
"""Create a persong setting his last name 1 and first name only.""" |
|||
self.lastname2 = False |
|||
self.template = "%(last1)s, %(first)s" |
|||
self.params = { |
|||
"is_company": False, |
|||
"name": "%s, %s" % (self.lastname, self.firstname), |
|||
} |
|||
|
|||
def test_separately(self): |
|||
"""Create a person setting separately all fields.""" |
|||
self.params = { |
|||
"is_company": False, |
|||
"firstname": self.firstname, |
|||
"lastname": self.lastname, |
|||
"lastname2": self.lastname2, |
|||
} |
|||
|
|||
|
|||
class UserCase(PersonCase, MailInstalled): |
|||
"""Test ``res.users``.""" |
|||
model = "res.users" |
|||
context = {"default_login": "user@example.com"} |
|||
|
|||
def tearDown(self): |
|||
# Skip if ``mail`` is installed |
|||
if not self.mail_installed(): |
|||
super(UserCase, self).tearDown() |
@ -0,0 +1,213 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
# © 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. |
|||
"""These tests try to mimic the behavior of the UI form. |
|||
|
|||
The form operates in onchange mode, with its limitations. |
|||
""" |
|||
|
|||
from openerp.tests.common import TransactionCase |
|||
|
|||
|
|||
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 |
|||
|
|||
|
|||
class PartnerCompanyCase(OnChangeCase): |
|||
is_company = True |
|||
|
|||
def tearDown(self): |
|||
"""Companies never have ``firstname`` nor ``lastname2``.""" |
|||
self.assertEqual(self.partner.firstname, False) |
|||
self.assertEqual(self.partner.lastname2, False) |
|||
|
|||
def set_name(self, value): |
|||
self.partner.name = value |
|||
|
|||
# It triggers onchange |
|||
self.partner._onchange_name() |
|||
|
|||
# Ensure it's properly set |
|||
self.assertEqual(self.partner.name, value) |
|||
|
|||
def test_create_from_form(self): |
|||
"""A user creates a company from the form.""" |
|||
name = u"Sôme company" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_name(name) |
|||
|
|||
self.assertEqual(self.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`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_name(u"Fóo") |
|||
self.set_name(u"") |
|||
|
|||
self.assertEqual(self.partner.lastname, False) |
|||
|
|||
|
|||
class PartnerContactCase(OnChangeCase): |
|||
def set_field(self, field, value): |
|||
# Changes the field |
|||
setattr(self.partner, field, value) |
|||
|
|||
if field in ("firstname", "lastname", "lastname2"): |
|||
# Trigger onchanges |
|||
self.partner._onchange_subnames() |
|||
self.partner._onchange_name() |
|||
|
|||
# Check it's set OK |
|||
self.assertEqual(getattr(self.partner, field), value) |
|||
|
|||
def test_create_from_form_empty(self): |
|||
"""A user creates a contact from the form. |
|||
|
|||
All subfields must be false, or the ``required`` attr will not work as |
|||
expected. |
|||
""" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# Odoo tries to compute the name |
|||
self.partner._compute_name() |
|||
|
|||
# This is then triggered |
|||
self.partner._onchange_name() |
|||
|
|||
# Subnames must start as False to make the UI work fine |
|||
self.assertEqual(self.partner.firstname, False) |
|||
self.assertEqual(self.partner.lastname, False) |
|||
self.assertEqual(self.partner.lastname2, False) |
|||
|
|||
# ``name`` cannot be False, or upstream Odoo will fail |
|||
self.assertEqual(self.partner.name, u"") |
|||
|
|||
def test_create_from_form_only_firstname(self): |
|||
"""A user creates a contact with only the firstname from the form.""" |
|||
firstname = u"Fïrst" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_field("firstname", firstname) |
|||
|
|||
self.assertEqual(self.partner.lastname, False) |
|||
self.assertEqual(self.partner.lastname2, False) |
|||
self.assertEqual(self.partner.name, firstname) |
|||
|
|||
def test_create_from_form_only_lastname(self): |
|||
"""A user creates a contact with only the lastname from the form.""" |
|||
lastname = u"Läst" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_field("lastname", lastname) |
|||
|
|||
self.assertEqual(self.partner.firstname, False) |
|||
self.assertEqual(self.partner.lastname2, False) |
|||
self.assertEqual(self.partner.name, lastname) |
|||
|
|||
def test_create_from_form_only_lastname2(self): |
|||
"""A user creates a contact with only the lastname2 from the form.""" |
|||
lastname2 = u"Läst2" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_field("lastname2", lastname2) |
|||
|
|||
self.assertEqual(self.partner.firstname, False) |
|||
self.assertEqual(self.partner.lastname, False) |
|||
self.assertEqual(self.partner.name, lastname2) |
|||
|
|||
def test_create_from_without_firstname(self): |
|||
"""A user creates a contact without firstname from the form.""" |
|||
lastname = u"Läst" |
|||
lastname2 = u"Läst2" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_field("lastname", lastname) |
|||
self.set_field("lastname2", lastname2) |
|||
|
|||
self.assertEqual(self.partner.firstname, False) |
|||
self.assertEqual( |
|||
self.partner.name, |
|||
u"%s %s" % (lastname, lastname2)) |
|||
|
|||
def test_create_from_without_lastname(self): |
|||
"""A user creates a contact without lastname from the form.""" |
|||
firstname = u"Fïrst" |
|||
lastname2 = u"Läst2" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_field("firstname", firstname) |
|||
self.set_field("lastname2", lastname2) |
|||
|
|||
self.assertEqual(self.partner.lastname, False) |
|||
self.assertEqual( |
|||
self.partner.name, |
|||
u"%s, %s" % (lastname2, firstname)) |
|||
|
|||
def test_create_from_without_lastname2(self): |
|||
"""A user creates a contact without lastname2 from the form.""" |
|||
firstname = u"Fïrst" |
|||
lastname = u"Läst" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_field("firstname", firstname) |
|||
self.set_field("lastname", lastname) |
|||
|
|||
self.assertEqual(self.partner.lastname2, False) |
|||
self.assertEqual( |
|||
self.partner.name, |
|||
u"%s, %s" % (lastname, firstname)) |
|||
|
|||
def test_create_from_form_all(self): |
|||
"""A user creates a contact with all names from the form.""" |
|||
firstname = u"Fïrst" |
|||
lastname = u"Läst" |
|||
lastname2 = u"Läst2" |
|||
with self.env.do_in_onchange(): |
|||
# User presses ``new`` |
|||
self.partner = self.new_partner() |
|||
|
|||
# User changes fields |
|||
self.set_field("firstname", firstname) |
|||
self.set_field("lastname", lastname) |
|||
self.set_field("lastname2", lastname2) |
|||
|
|||
self.assertEqual( |
|||
self.partner.name, |
|||
u"%s %s, %s" % (lastname, lastname2, firstname)) |
@ -0,0 +1,105 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
© 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. --> |
|||
|
|||
<openerp> |
|||
<data> |
|||
<record id="partner_simple_form" model="ir.ui.view"> |
|||
<field name="name">Add second last name</field> |
|||
<field name="model">res.partner</field> |
|||
<field name="inherit_id" |
|||
ref="partner_firstname.view_partner_simple_form_firstname"/> |
|||
<field name="arch" type="xml"> |
|||
<data> |
|||
<xpath expr="//field[@name='firstname']" position="attributes"> |
|||
<attribute name="attrs">{ |
|||
'required': [('lastname', '=', False), |
|||
('lastname2', '=', False), |
|||
('is_company', '=', False)] |
|||
}</attribute> |
|||
</xpath> |
|||
|
|||
<xpath expr="//field[@name='lastname']" position="attributes"> |
|||
<attribute name="attrs">{ |
|||
'required': [('firstname', '=', False), |
|||
('lastname2', '=', False), |
|||
('is_company', '=', False)] |
|||
}</attribute> |
|||
</xpath> |
|||
|
|||
<xpath expr="//field[@name='lastname']" position="after"> |
|||
<field name="lastname2" |
|||
attrs="{'required': [('firstname', '=', False), |
|||
('lastname', '=', False), |
|||
('is_company', '=', False)]}"/> |
|||
</xpath> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="partner_form" model="ir.ui.view"> |
|||
<field name="name">Add second last name</field> |
|||
<field name="model">res.partner</field> |
|||
<field name="inherit_id" |
|||
ref="partner_firstname.view_partner_form_firstname"/> |
|||
<field name="arch" type="xml"> |
|||
<data> |
|||
<!-- Main form --> |
|||
<xpath expr="//field[@name='firstname']" position="attributes"> |
|||
<attribute name="attrs">{ |
|||
'required': [('lastname', '=', False), |
|||
('lastname2', '=', False), |
|||
('is_company', '=', False)] |
|||
}</attribute> |
|||
</xpath> |
|||
|
|||
<xpath expr="//field[@name='lastname']" position="attributes"> |
|||
<attribute name="attrs">{ |
|||
'required': [('firstname', '=', False), |
|||
('lastname2', '=', False), |
|||
('is_company', '=', False)] |
|||
}</attribute> |
|||
</xpath> |
|||
|
|||
<xpath expr="//field[@name='lastname']" position="after"> |
|||
<field name="lastname2" |
|||
attrs="{'required': [('firstname', '=', False), |
|||
('lastname', '=', False), |
|||
('is_company', '=', False)]}"/> |
|||
</xpath> |
|||
|
|||
<!-- Inner contact form of child_ids --> |
|||
<xpath expr="//field[@name='child_ids']/form |
|||
//field[@name='firstname']" |
|||
position="attributes"> |
|||
<attribute name="attrs">{ |
|||
'required': [('lastname', '=', False), |
|||
('lastname2', '=', False), |
|||
('is_company', '=', False)] |
|||
}</attribute> |
|||
</xpath> |
|||
|
|||
<xpath expr="//field[@name='child_ids']/form |
|||
//field[@name='lastname']" |
|||
position="attributes"> |
|||
<attribute name="attrs">{ |
|||
'required': [('firstname', '=', False), |
|||
('lastname2', '=', False), |
|||
('is_company', '=', False)] |
|||
}</attribute> |
|||
</xpath> |
|||
|
|||
<xpath expr="//field[@name='child_ids']/form |
|||
//field[@name='lastname']" |
|||
position="after"> |
|||
<field name="lastname2" |
|||
attrs="{'required': [('firstname', '=', False), |
|||
('lastname', '=', False), |
|||
('is_company', '=', False)]}"/> |
|||
</xpath> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,42 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
© 2015 Grupo ESOC Ingeniería de Servicios, S.L.U. --> |
|||
|
|||
<openerp> |
|||
<data> |
|||
|
|||
<!-- Required before modifying `base.vew_users_form`. |
|||
https://github.com/odoo/odoo/issues/6324#issuecomment-93534579 --> |
|||
<function model="res.groups" name="update_user_groups_view" /> |
|||
|
|||
<record id="users_form" model="ir.ui.view"> |
|||
<field name="name">Add second last name</field> |
|||
<field name="model">res.users</field> |
|||
<field name="inherit_id" ref="partner_firstname.view_users_form"/> |
|||
<field name="arch" type="xml"> |
|||
<data> |
|||
<xpath expr="//field[@name='firstname']" position="attributes"> |
|||
<attribute name="attrs">{ |
|||
'required': [('lastname', '=', False), |
|||
('lastname2', '=', False)] |
|||
}</attribute> |
|||
</xpath> |
|||
|
|||
<xpath expr="//field[@name='lastname']" position="attributes"> |
|||
<attribute name="attrs">{ |
|||
'required': [('firstname', '=', False), |
|||
('lastname2', '=', False)] |
|||
}</attribute> |
|||
</xpath> |
|||
|
|||
<xpath expr="//field[@name='lastname']" position="after"> |
|||
<field name="lastname2" |
|||
attrs="{'required': [('firstname', '=', False), |
|||
('lastname', '=', False)]}"/> |
|||
</xpath> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue