← Back to team overview

openerp-community-reviewer team mailing list archive

[Merge] lp:~nemry/partner-contact-management/7.0-partner-firstname into lp:partner-contact-management

 

Jonathan Nemry (Acsone) has proposed merging lp:~nemry/partner-contact-management/7.0-partner-firstname into lp:partner-contact-management.

Requested reviews:
  Acsone OpenErp Team (acsone-openerp)

For more details, see:
https://code.launchpad.net/~nemry/partner-contact-management/7.0-partner-firstname/+merge/202713

For Partner:

1) Create always the SQL constraint on 'lastname'
2) Better implementation of "_write_name" allowing more intuitive update of the partner name when processing from another model (ex: res_user), i.e., try to keep the firstname if unchanged
3) When duplicating a partner, avoid to repeat the firstname in the name
4) Beautify the inner form for children contacts (placing fields as in the main form)
5) Allow edition of the field name in the inner form if child is a company

For User:

1) Reintegrate the name as "required"
2) When duplicating a user, avoid to repeat the firstname in the related partner name
-- 
https://code.launchpad.net/~nemry/partner-contact-management/7.0-partner-firstname/+merge/202713
Your team Partner and Contact Core Editors is subscribed to branch lp:partner-contact-management.
=== modified file 'partner_firstname/i18n/de.po'
--- partner_firstname/i18n/de.po	2013-02-04 13:37:23 +0000
+++ partner_firstname/i18n/de.po	2014-01-22 17:11:43 +0000
@@ -16,6 +16,18 @@
 "Plural-Forms: \n"
 
 #. module: partner_firstname
+#: code:addons/partner_firstname/partner.py:76
+#: code:addons/partner_firstname/res_user.py:35
+#, python-format
+msgid "%s (copy)"
+msgstr "%s (kopie)"
+
+#. module: partner_firstname
+#: model:ir.model,name:partner_firstname.model_res_users
+msgid "Users"
+msgstr "Benutzer"
+
+#. module: partner_firstname
 #: field:res.partner,lastname:0
 msgid "Lastname"
 msgstr "Name"
@@ -26,6 +38,11 @@
 msgstr "Vorname"
 
 #. module: partner_firstname
+#: view:res.partner:0
+msgid "Is a Company?"
+msgstr "Ist ein Unternehmen?"
+
+#. module: partner_firstname
 #: model:ir.model,name:partner_firstname.model_res_partner
 msgid "Partner"
 msgstr "Partner"

=== modified file 'partner_firstname/i18n/en.po'
--- partner_firstname/i18n/en.po	2013-02-04 13:37:23 +0000
+++ partner_firstname/i18n/en.po	2014-01-22 17:11:43 +0000
@@ -16,17 +16,33 @@
 "Plural-Forms: \n"
 
 #. module: partner_firstname
+#: code:addons/partner_firstname/partner.py:76
+#: code:addons/partner_firstname/res_user.py:35
+#, python-format
+msgid "%s (copy)"
+msgstr "%s (copy)"
+
+#. module: partner_firstname
+#: model:ir.model,name:partner_firstname.model_res_users
+msgid "Users"
+msgstr "Users"
+
+#. module: partner_firstname
+#: field:res.partner,firstname:0
+msgid "Firstname"
+msgstr "Firstname"
+
+#. module: partner_firstname
 #: field:res.partner,lastname:0
 msgid "Lastname"
 msgstr "Lastname"
 
 #. module: partner_firstname
-#: field:res.partner,firstname:0
-msgid "Firstname"
-msgstr "Firstname"
+#: view:res.partner:0
+msgid "Is a Company?"
+msgstr "Is a Company?"
 
 #. module: partner_firstname
 #: model:ir.model,name:partner_firstname.model_res_partner
 msgid "Partner"
 msgstr "Partner"
-

=== modified file 'partner_firstname/i18n/fr.po'
--- partner_firstname/i18n/fr.po	2013-02-04 13:37:23 +0000
+++ partner_firstname/i18n/fr.po	2014-01-22 17:11:43 +0000
@@ -16,6 +16,18 @@
 "Plural-Forms: \n"
 
 #. module: partner_firstname
+#: code:addons/partner_firstname/partner.py:76
+#: code:addons/partner_firstname/res_user.py:35
+#, python-format
+msgid "%s (copy)"
+msgstr "%s (copie)"
+
+#. module: partner_firstname
+#: model:ir.model,name:partner_firstname.model_res_users
+msgid "Users"
+msgstr "Utilisateur"
+
+#. module: partner_firstname
 #: field:res.partner,lastname:0
 msgid "Lastname"
 msgstr "Nom"
@@ -26,6 +38,11 @@
 msgstr "Prénom"
 
 #. module: partner_firstname
+#: view:res.partner:0
+msgid "Is a Company?"
+msgstr "Est une société?"
+
+#. module: partner_firstname
 #: model:ir.model,name:partner_firstname.model_res_partner
 msgid "Partner"
 msgstr "Partenaire"

=== modified file 'partner_firstname/i18n/nl.po'
--- partner_firstname/i18n/nl.po	2013-10-03 15:20:53 +0000
+++ partner_firstname/i18n/nl.po	2014-01-22 17:11:43 +0000
@@ -16,6 +16,18 @@
 "Plural-Forms: \n"
 
 #. module: partner_firstname
+#: code:addons/partner_firstname/partner.py:76
+#: code:addons/partner_firstname/res_user.py:35
+#, python-format
+msgid "%s (copy)"
+msgstr "%s (kopie)"
+
+#. module: partner_firstname
+#: model:ir.model,name:partner_firstname.model_res_users
+msgid "Users"
+msgstr "Gebruikers"
+
+#. module: partner_firstname
 #: field:res.partner,lastname:0
 msgid "Lastname"
 msgstr "Achternaam"
@@ -26,6 +38,11 @@
 msgstr "Voornaam"
 
 #. module: partner_firstname
+#: view:res.partner:0
+msgid "Is a Company?"
+msgstr "Is een bedrijf?"
+
+#. module: partner_firstname
 #: model:ir.model,name:partner_firstname.model_res_partner
 msgid "Partner"
 msgstr "Relatie"

=== modified file 'partner_firstname/i18n/partner_firstname.pot'
--- partner_firstname/i18n/partner_firstname.pot	2013-10-03 16:13:54 +0000
+++ partner_firstname/i18n/partner_firstname.pot	2014-01-22 17:11:43 +0000
@@ -6,8 +6,8 @@
 msgstr ""
 "Project-Id-Version: OpenERP Server 7.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-10-03 16:09+0000\n"
-"PO-Revision-Date: 2013-10-03 16:09+0000\n"
+"POT-Creation-Date: 2014-01-22 14:09+0000\n"
+"PO-Revision-Date: 2014-01-22 14:09+0000\n"
 "Last-Translator: <>\n"
 "Language-Team: \n"
 "MIME-Version: 1.0\n"
@@ -16,6 +16,18 @@
 "Plural-Forms: \n"
 
 #. module: partner_firstname
+#: code:addons/partner_firstname/partner.py:76
+#: code:addons/partner_firstname/res_user.py:35
+#, python-format
+msgid "%s (copy)"
+msgstr ""
+
+#. module: partner_firstname
+#: model:ir.model,name:partner_firstname.model_res_users
+msgid "Users"
+msgstr ""
+
+#. module: partner_firstname
 #: field:res.partner,firstname:0
 msgid "Firstname"
 msgstr ""
@@ -26,6 +38,11 @@
 msgstr ""
 
 #. module: partner_firstname
+#: view:res.partner:0
+msgid "Is a Company?"
+msgstr ""
+
+#. module: partner_firstname
 #: model:ir.model,name:partner_firstname.model_res_partner
 msgid "Partner"
 msgstr ""

=== modified file 'partner_firstname/partner.py'
--- partner_firstname/partner.py	2013-08-12 06:18:39 +0000
+++ partner_firstname/partner.py	2014-01-22 17:11:43 +0000
@@ -18,6 +18,7 @@
 #
 ##############################################################################
 from openerp.osv.orm import Model, fields
+from openerp.tools.translate import _
 
 
 class ResPartner(Model):
@@ -29,6 +30,10 @@
         cursor.execute('SELECT id FROM res_partner WHERE lastname IS NOT NULL Limit 1')
         if not cursor.fetchone():
             cursor.execute('UPDATE res_partner set lastname = name WHERE name IS NOT NULL')
+            # Create Sql constraint if table is not empty
+            cursor.execute('SELECT id FROM res_partner Limit 1')
+            if cursor.fetchone():
+                cursor.execute('ALTER TABLE res_partner ALTER COLUMN lastname SET NOT NULL')
 
     def _compute_name_custom(self, cursor, uid, ids, fname, arg, context=None):
         res = {}
@@ -41,13 +46,39 @@
         return res
 
     def _write_name(self, cursor, uid, partner_id, field_name, field_value, arg, context=None):
-        return self.write(cursor, uid, partner_id,
-                          {'lastname': field_value}, context=context)
+        """
+        # Try to reverse the effect of _compute_name_custom:
+        # * if is_company is True then lastname = name and firstname False
+        # * if firstname change in the new name: lastname is set to new name, firstname is reset
+        # * if only lastname change in the new name: lastname is updated accordingly, firstname remains untouched
+        """
+        vals = {'lastname': field_value, 'firstname': False}
+        fields = self.read(cursor, uid, [partner_id], ['firstname', 'is_company'], context=context)[0]
+        if not fields['is_company']:
+            to_check = ' %s' % fields['firstname']
+            if field_value.endswith(to_check):
+                vals['lastname'] = field_value[:-len(to_check)]
+                del(vals['firstname'])
+        return self.write(cursor, uid, partner_id, vals, context=context)
+
+    def copy_data(self, cr, uid, id, default=None, context=None):
+        """
+        # Avoid to replicate the firstname into the name when duplicating a partner
+        """
+        default = default or {}
+        if not default.get('lastname'):
+            default = default.copy()
+            default['lastname'] = _('%s (copy)') % self.read(cr, uid, [id], ['lastname'], context=context)[0]['lastname']
+            if default.get('name'):
+                del(default['name'])
+        return super(ResPartner, self).copy_data(cr, uid, id, default, context=context)
 
     def create(self, cursor, uid, vals, context=None):
-        """To support data backward compatibility we have to keep this overwrite even if we
-        use fnct_inv: otherwise we can't create entry because lastname is mandatory and module
-        will not install if there is demo data"""
+        """
+        # To support data backward compatibility we have to keep this overwrite even if we
+        # use fnct_inv: otherwise we can't create entry because lastname is mandatory and module
+        # will not install if there is demo data
+        """
         to_use = vals
         if vals.get('name'):
             corr_vals = vals.copy()

=== modified file 'partner_firstname/partner_view.xml'
--- partner_firstname/partner_view.xml	2013-11-13 16:18:13 +0000
+++ partner_firstname/partner_view.xml	2014-01-22 17:11:43 +0000
@@ -32,15 +32,26 @@
           </group>
         </field>
         <!-- Add firstname and last name in inner contact form of child_ids -->
-        <xpath expr="//form[@string='Contact']/sheet/div" position="after">
+        <xpath expr="//form[@string='Contact']/sheet//field[@name='category_id']" position="before">
            <group attrs="{'invisible': [('is_company', '=', True)]}">
             <field name="lastname" attrs="{'required': [('is_company', '=', False)]}"/>
             <field name="firstname"/>
            </group> 
         </xpath>
-        <xpath expr="//form[@string='Contact']/sheet/div/h1" position="after">
-           <field name="is_company" on_change="onchange_type(is_company)" class="oe_inline"/>
-           <label for="is_company" string="Is a Company?"/>)
+        <xpath expr="//form[@string='Contact']/sheet//field[@name='category_id']" position="attributes">
+            <attribute name="style"/>
+        </xpath>
+        <xpath expr="//form[@string='Contact']/sheet/div/label" position="replace">
+            <div class="oe_edit_only">
+                <label for="name"/> (
+                <field name="is_company" on_change="onchange_type(is_company)" class="oe_inline"/>
+                <label for="is_company" string="Is a Company?"/>)
+            </div>
+        </xpath>
+        <xpath expr="//form[@string='Contact']/sheet/div/h1/field[@name='name']" position="attributes">
+            <div class="oe_edit_only">
+                 <attribute name="attrs">{'readonly': [('is_company', '=', False)], 'required': [('is_company', '=', True)]}</attribute>
+            </div>
         </xpath>
 
 

=== modified file 'partner_firstname/res_user.py'
--- partner_firstname/res_user.py	2013-02-20 14:00:17 +0000
+++ partner_firstname/res_user.py	2014-01-22 17:11:43 +0000
@@ -18,15 +18,21 @@
 #
 ##############################################################################
 from openerp.osv import orm
+from openerp.tools.translate import _
 
 
 class ResUsers(orm.Model):
-    """Allows user creation from user form as
-    name is not in form"""
 
     _inherit = 'res.users'
 
-    def create(self, cursor, uid, vals, context=None):
-        if not vals.get('name'):
-            vals['name'] = vals['login']
-        return super(ResUsers, self).create(cursor, uid, vals, context=context)
+    def copy_data(self, cr, uid, id, default=None, context=None):
+        """
+        # Avoid to replicate the firstname into the name when duplicating a user
+        """
+        default = default or {}
+        if not default.get('lastname'):
+            default = default.copy()
+            default['lastname'] = _('%s (copy)') % self.read(cr, uid, [id], ['lastname'], context=context)[0]['lastname']
+            if default.get('name'):
+                del(default['name'])
+        return super(ResUsers, self).copy_data(cr, uid, id, default, context=context)

=== modified file 'partner_firstname/res_user_view.xml'
--- partner_firstname/res_user_view.xml	2013-02-20 12:43:45 +0000
+++ partner_firstname/res_user_view.xml	2014-01-22 17:11:43 +0000
@@ -8,6 +8,7 @@
       <field name="arch" type="xml">
         <field name="name" position="attributes">
           <attribute name="readonly">False</attribute>
+          <attribute name="required">True</attribute>
         </field>
       </field>
     </record>

=== added directory 'partner_firstname/tests'
=== added file 'partner_firstname/tests/__init__.py'
--- partner_firstname/tests/__init__.py	1970-01-01 00:00:00 +0000
+++ partner_firstname/tests/__init__.py	2014-01-22 17:11:43 +0000
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Authors: Nemry Jonathan
+# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
+# All Rights Reserved
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs.
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly advised to contact a Free Software
+# Service Company.
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+import test_partner_firstname
+
+checks = [
+    test_partner_firstname
+    ]
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'partner_firstname/tests/test_partner_firstname.py'
--- partner_firstname/tests/test_partner_firstname.py	1970-01-01 00:00:00 +0000
+++ partner_firstname/tests/test_partner_firstname.py	2014-01-22 17:11:43 +0000
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Authors: Nemry Jonathan
+# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu)
+# All Rights Reserved
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs.
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly advised to contact a Free Software
+# Service Company.
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+import openerp.tests.common as common
+
+
+class test_partner_firstname(common.TransactionCase):
+
+    def setUp(self):
+        super(test_partner_firstname, self).setUp()
+        self.registry('ir.model').clear_caches()
+        self.registry('ir.model.data').clear_caches()
+
+        self.user_model = self.registry("res.users")
+        self.partner_model = self.registry("res.partner")
+        self.fields_partner = {'lastname': 'lastname', 'firstname': 'firstname'}
+        self.fields_user = {'name': 'lastname', 'login': 'v5Ue4Tql0Pm67KX05g25A'}
+
+    def test_copy_partner(self):
+        cr, uid = self.cr, self.uid
+        res_id = self.partner_model.create(cr, uid, self.fields_partner, context={})
+        res_id = self.partner_model.copy(cr, uid, res_id, default={}, context={})
+        vals = self.partner_model.read(cr, uid, [res_id], ['name', 'lastname', 'firstname'], context={})[0]
+        self.assertEqual(vals['name'] == "lastname (copy) firstname" and
+                         vals['lastname'] == 'lastname (copy)' and
+                         vals['firstname'] == 'firstname', True, 'Copy of the partner failed with wrong values')
+
+    def test_copy_user(self):
+        cr, uid = self.cr, self.uid
+        # create a user
+        res_id = self.user_model.create(cr, uid, self.fields_user, context={})
+        # get the related partner id and add it a firstname
+        fields = self.user_model.read(cr, uid, [res_id], ['partner_id'], context={})[0]
+        self.partner_model.write(cr, uid, fields['partner_id'][0], {'firstname':'firstname'}, context={})
+        # copy the user and compare result
+        res_id = self.user_model.copy(cr, uid, res_id, default={}, context={})
+        vals = self.user_model.read(cr, uid, [res_id], ['name', 'lastname', 'firstname'], context={})[0]
+        self.assertEqual(vals['name'] == "lastname (copy) firstname" and
+                         vals['lastname'] == 'lastname (copy)' and
+                         vals['firstname'] == 'firstname', True, 'Copy of the user failed with wrong values')
+
+    def test_update_user_lastname(self):
+        cr, uid = self.cr, self.uid
+        # create a user
+        res_id = self.user_model.create(cr, uid, self.fields_user, context={})
+        # get the related partner id and add it a firstname
+        fields = self.user_model.read(cr, uid, [res_id], ['partner_id'], context={})[0]
+        self.partner_model.write(cr, uid, fields['partner_id'][0], {'firstname':'firstname'}, context={})
+        self.user_model.write(cr, uid, res_id, {'name': 'change firstname'}, context={})
+        vals = self.user_model.read(cr, uid, [res_id], ['name', 'lastname', 'firstname'], context={})[0]
+        self.assertEqual(vals['name'] == "change firstname" and
+                         vals['lastname'] == 'change' and
+                         vals['firstname'] == 'firstname', True, 'Update of the user lastname failed with wrong values')
+
+    def test_update_user_firstname(self):
+        cr, uid = self.cr, self.uid
+        # create a user
+        res_id = self.user_model.create(cr, uid, self.fields_user, context={})
+        # get the related partner id and add it a firstname
+        fields = self.user_model.read(cr, uid, [res_id], ['partner_id'], context={})[0]
+        self.partner_model.write(cr, uid, fields['partner_id'][0], {'firstname':'firstname'}, context={})
+        self.user_model.write(cr, uid, res_id, {'name': 'lastname other'}, context={})
+        vals = self.user_model.read(cr, uid, [res_id], ['name', 'lastname', 'firstname'], context={})[0]
+        self.assertEqual(vals['name'] == "lastname other" and
+                         vals['lastname'] == 'lastname other' and
+                         vals['firstname'] == False, True, 'Update of the user firstname failed with wrong values')
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:


Follow ups