[REF] [IMP] mail_alias improvement
authorThibault Delavallée <tde@openerp.com>
Tue, 9 Apr 2013 11:11:58 +0000 (13:11 +0200)
committerThibault Delavallée <tde@openerp.com>
Tue, 9 Apr 2013 11:11:58 +0000 (13:11 +0200)
alias_name is not required anymore
crm, hr_job, project, mail_group, res_users: alias creation is now different
and done more like other inherits, except an alias_model_name that is given
to the context to find the alias alias_model_id.
crm, jr_job, project, mail_group, res_users: updated form views using
aliases
mail_alias: added a filter on 'inactive' aliases (alias_name False) and
added a button to redirect to the related document if any

bzr revid: tde@openerp.com-20130409111158-bv04n5o01z9l3c17

15 files changed:
addons/crm/crm.py
addons/crm/crm_case_section_view.xml
addons/hr_recruitment/hr_recruitment.py
addons/hr_recruitment/hr_recruitment_view.xml
addons/mail/mail_alias.py
addons/mail/mail_alias_view.xml
addons/mail/mail_group.py
addons/mail/mail_group_view.xml
addons/mail/res_users.py
addons/mail/res_users_view.xml
addons/mail/tests/test_mail_base.py
addons/mail/tests/test_mail_features.py
addons/project/project.py
addons/project/project_view.xml
addons/project_issue/project_issue_view.xml

index 7b6fe02..2b8004e 100644 (file)
@@ -175,17 +175,13 @@ class crm_case_section(osv.osv):
         return res
 
     def create(self, cr, uid, vals, context=None):
-        mail_alias = self.pool.get('mail.alias')
-        if not vals.get('alias_id'):
-            alias_name = vals.pop('alias_name', None) or vals.get('name')  # prevent errors during copy()
-            alias_id = mail_alias.create_unique_alias(cr, uid,
-                    {'alias_name': alias_name},
-                    model_name="crm.lead",
-                    context=context)
-            vals['alias_id'] = alias_id
-        res = super(crm_case_section, self).create(cr, uid, vals, context)
-        mail_alias.write(cr, uid, [vals['alias_id']], {'alias_defaults': {'section_id': res, 'type': 'lead'}}, context)
-        return res
+        if context is None:
+            context = {}
+        create_context = dict(context, alias_model_name=self._name)
+        section_id = super(crm_case_section, self).create(cr, uid, vals, context=create_context)
+        section = self.browse(cr, uid, section_id, context=context)
+        self.pool.get('mail.alias').write(cr, uid, [section.alias_id.id], {'alias_defaults': {'section_id': section_id, 'type': 'lead'}}, context=context)
+        return section_id
 
     def unlink(self, cr, uid, ids, context=None):
         # Cascade-delete mail aliases as well, as they should not exist without the sales team.
index c788872..35b868f 100644 (file)
@@ -94,8 +94,8 @@
                                 </div>
                                 <div class="oe_kanban_content">
                                     <h4><field name="name"/></h4>
-                                    <div class="oe_kanban_alias" t-if="record.use_leads.raw_value and record.alias_id.value">
-                                        <span class="oe_e">%%</span><small><field name="alias_id"/></small>
+                                    <div class="oe_kanban_alias" t-if="record.alias_id.value">
+                                        <span class="oe_e oe_e_alias">%%</span><small><field name="alias_id"/></small>
                                     </div>
                                     <div class="oe_items_list">
                                         <a t-if="record.use_leads.raw_value" name="%(crm_case_form_view_salesteams_lead)d" type="action">
                             </h1>
                             <div name="group_alias"
                                     attrs="{'invisible': [('alias_domain', '=', False)]}">
-                                <label for="alias_id" string="Email Alias"/>
-                                <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
+                                <span name="read_alias" class="oe_read_only" attrs="{'invisible': [('alias_name', '=', False)]}">
+                                    <span class="oe_e oe_e_alias">%%</span>
+                                    <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
+                                </span>
                                 <span name="edit_alias" class="oe_edit_only">
-                                    <field name="alias_name" class="oe_inline"
-                                            attrs="{'required': [('use_leads', '=', True), ('alias_id', '!=', False)]}"/>
-                                    @
-                                    <field name="alias_domain" class="oe_inline" readonly="1"/>
+                                    <span class="oe_e oe_e_alias">%%</span>
+                                    <field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
                                 </span>
                             </div>
                             <div name="options_active">
index b0b60db..b734895 100644 (file)
@@ -504,29 +504,18 @@ class hr_job(osv.osv):
                                     help="Email alias for this job position. New emails will automatically "
                                          "create new applicants for this job position."),
     }
-    _defaults = {
-        'alias_domain': False, # always hide alias during creation
-    }
 
     def _auto_init(self, cr, context=None):
         """Installation hook to create aliases for all jobs and avoid constraint errors."""
-        self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(hr_job,self)._auto_init,
+        self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(hr_job, self)._auto_init,
             self._columns['alias_id'], 'name', alias_prefix='job+', alias_defaults={'job_id': 'id'}, context=context)
 
     def create(self, cr, uid, vals, context=None):
-        mail_alias = self.pool.get('mail.alias')
-        if not vals.get('alias_id'):
-            vals.pop('alias_name', None) # prevent errors during copy()
-            alias_id = mail_alias.create_unique_alias(cr, uid,
-                          # Using '+' allows using subaddressing for those who don't
-                          # have a catchall domain setup.
-                          {'alias_name': 'jobs+'+vals['name']},
-                          model_name="hr.applicant",
-                          context=context)
-            vals['alias_id'] = alias_id
-        res = super(hr_job, self).create(cr, uid, vals, context)
-        mail_alias.write(cr, uid, [vals['alias_id']], {"alias_defaults": {'job_id': res}}, context)
-        return res
+        create_context = dict(context, alias_model_name=self._name)
+        job_id = super(hr_job, self).create(cr, uid, vals, context=create_context)
+        job = self.browse(cr, uid, job_id, context=context)
+        self.pool.get('mail.alias').write(cr, uid, [job.alias_id.id], {"alias_defaults": {'job_id': job_id}}, context)
+        return job_id
 
     def unlink(self, cr, uid, ids, context=None):
         # Cascade-delete mail aliases as well, as they should not exist without the job position.
@@ -544,15 +533,16 @@ class hr_job(osv.osv):
         if record.survey_id:
             datas['ids'] = [record.survey_id.id]
         datas['model'] = 'survey.print'
-        context.update({'response_id': [0], 'response_no': 0,})
+        context.update({'response_id': [0], 'response_no': 0})
         return {
             'type': 'ir.actions.report.xml',
             'report_name': 'survey.form',
             'datas': datas,
-            'context' : context,
-            'nodestroy':True,
+            'context': context,
+            'nodestroy': True,
         }
 
+
 class applicant_category(osv.osv):
     """ Category of applicant """
     _name = "hr.applicant_category"
index b531677..10c4263 100644 (file)
             <xpath expr="//div[@class='oe_title']//h1" position="after">
                 <div name="group_alias"
                         attrs="{'invisible': [('alias_domain', '=', False)]}">
-                    <label for="alias_id" string="Email Alias"/>
-                    <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
+                    <span name="read_alias" class="oe_read_only" attrs="{'invisible': [('alias_name', '=', False)]}">
+                        <span class="oe_e oe_e_alias">%%</span>
+                        <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
+                    </span>
                     <span name="edit_alias" class="oe_edit_only">
-                        <field name="alias_name" class="oe_inline"
-                                attrs="{'required': [('alias_id', '!=', False)]}"/>
-                        @
-                        <field name="alias_domain" class="oe_inline" readonly="1"/>
+                        <span class="oe_e oe_e_alias">%%</span>
+                        <field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
                     </span>
                 </div>
             </xpath>
index dad69fd..51f9d36 100644 (file)
@@ -39,6 +39,7 @@ def remove_accents(input_str):
     nkfd_form = unicodedata.normalize('NFKD', input_str)
     return u''.join([c for c in nkfd_form if not unicodedata.combining(c)])
 
+
 class mail_alias(osv.Model):
     """A Mail Alias is a mapping of an email address with a given OpenERP Document
        model. It is used by OpenERP's mail gateway when processing incoming emails
@@ -47,7 +48,7 @@ class mail_alias(osv.Model):
        of that alias. If the message is a reply it will be attached to the
        existing discussion on the corresponding record, otherwise a new
        record of the corresponding model will be created.
-       
+
        This is meant to be used in combination with a catch-all email configuration
        on the company's mail server, so that as soon as a new mail.alias is
        created, it becomes immediately usable and OpenERP will accept email for it.
@@ -63,7 +64,7 @@ class mail_alias(osv.Model):
         return dict.fromkeys(ids, domain or "")
 
     _columns = {
-        'alias_name': fields.char('Alias', required=True,
+        'alias_name': fields.char('Alias',
                             help="The name of the email alias, e.g. 'jobs' "
                                  "if you want to catch emails for <jobs@example.my.openerp.com>",),
         'alias_model_id': fields.many2one('ir.model', 'Aliased Model', required=True, ondelete="cascade",
@@ -147,7 +148,8 @@ class mail_alias(osv.Model):
         return new_name
 
     def migrate_to_alias(self, cr, child_model_name, child_table_name, child_model_auto_init_fct,
-        alias_id_column, alias_key, alias_prefix = '', alias_force_key = '', alias_defaults = {}, context=None):
+        alias_id_column, alias_key, alias_prefix='', alias_force_key='', alias_defaults={},
+        alias_generate_name=False, context=None):
         """ Installation hook to create aliases for all users and avoid constraint errors.
 
             :param child_model_name: model name of the child class (i.e. res.users)
@@ -156,14 +158,12 @@ class mail_alias(osv.Model):
                 (i.e. super(res_users,self)._auto_init(cr, context=context))
             :param alias_id_column: alias_id column (i.e. self._columns['alias_id'])
             :param alias_key: name of the column used for the unique name (i.e. 'login')
-            :param alias_prefix: prefix for the unique name (i.e. 'jobs' + ...)
             :param alias_force_key': name of the column for force_thread_id;
                 if empty string, not taken into account
             :param alias_defaults: dict, keys = mail.alias columns, values = child
                 model column name used for default values (i.e. {'job_id': 'id'})
         """
-
-        # disable the unique alias_id not null constraint, to avoid spurious warning during 
+        # disable the unique alias_id not null constraint, to avoid spurious warning during
         # super.auto_init. We'll reinstall it afterwards.
         alias_id_column.required = False
 
@@ -173,16 +173,18 @@ class mail_alias(osv.Model):
         registry = RegistryManager.get(cr.dbname)
         mail_alias = registry.get('mail.alias')
         child_class_model = registry.get(child_model_name)
-        no_alias_ids = child_class_model.search(cr, SUPERUSER_ID, [('alias_id', '=', False)], context={'active_test':False})
+        no_alias_ids = child_class_model.search(cr, SUPERUSER_ID, [('alias_id', '=', False)], context={'active_test': False})
         # Use read() not browse(), to avoid prefetching uninitialized inherited fields
         for obj_data in child_class_model.read(cr, SUPERUSER_ID, no_alias_ids, [alias_key]):
-            alias_vals = {'alias_name': '%s%s' % (alias_prefix, obj_data[alias_key]) }
+            alias_vals = {'alias_name': False}
+            if alias_generate_name:
+                alias_vals['alias_name'] = '%s%s' % (alias_prefix, obj_data[alias_key])
             if alias_force_key:
                 alias_vals['alias_force_thread_id'] = obj_data[alias_force_key]
-            alias_vals['alias_defaults'] = dict( (k, obj_data[v]) for k, v in alias_defaults.iteritems())
-            alias_id = mail_alias.create_unique_alias(cr, SUPERUSER_ID, alias_vals, model_name=child_model_name)
+            alias_vals['alias_defaults'] = dict((k, obj_data[v]) for k, v in alias_defaults.iteritems())
+            alias_id = mail_alias.create(cr, SUPERUSER_ID, alias_vals, {'alias_model_name': child_model_name})
             child_class_model.write(cr, SUPERUSER_ID, obj_data['id'], {'alias_id': alias_id})
-            _logger.info('Mail alias created for %s %s (uid %s)', child_model_name, obj_data[alias_key], obj_data['id'])
+            _logger.info('Mail alias created for %s %s (id %s)', child_model_name, obj_data[alias_key], obj_data['id'])
 
         # Finally attempt to reinstate the missing constraint
         try:
@@ -196,19 +198,36 @@ class mail_alias(osv.Model):
         # set back the unique alias_id constraint
         alias_id_column.required = True
 
-    def create_unique_alias(self, cr, uid, vals, model_name=None, context=None):
-        """Creates an email.alias record according to the values provided in ``vals``,
-        with 2 alterations: the ``alias_name`` value may be suffixed in order to
-        make it unique (and certain unsafe characters replaced), and 
-        he ``alias_model_id`` value will set to the model ID of the ``model_name``
-        value, if provided, 
+    def create(self, cr, uid, vals, context=None):
+        """ Creates an email.alias record according to the values provided in ``vals``,
+            with 2 alterations: the ``alias_name`` value may be suffixed in order to
+            make it unique (and certain unsafe characters replaced), and
+            he ``alias_model_id`` value will set to the model ID of the ``model_name``
+            context value, if provided.
         """
+        if context is None:
+            context = {}
+        model_name = context.get('alias_model_name')
         # when an alias name appears to already be an email, we keep the local part only
-        alias_name = remove_accents(vals['alias_name']).lower().split('@')[0]
-        alias_name = re.sub(r'[^\w+.]+', '-', alias_name)
-        alias_name = self._find_unique(cr, uid, alias_name, context=context)
-        vals['alias_name'] = alias_name
+        if vals.get('alias_name'):
+            alias_name = remove_accents(vals['alias_name']).lower().split('@')[0]
+            alias_name = re.sub(r'[^\w+.]+', '-', alias_name)
+            alias_name = self._find_unique(cr, uid, alias_name, context=context)
+            vals['alias_name'] = alias_name
         if model_name:
             model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model_name)], context=context)[0]
             vals['alias_model_id'] = model_id
-        return self.create(cr, uid, vals, context=context)
+        res = super(mail_alias, self).create(cr, uid, vals, context=context)
+        return res
+
+    def open_document(self, cr, uid, ids, context=None):
+        alias = self.browse(cr, uid, ids, context=context)[0]
+        if not alias.alias_model_id or not alias.alias_force_thread_id:
+            return False
+        return {
+            'view_type': 'form',
+            'view_mode': 'form',
+            'res_model': alias.alias_model_id.model,
+            'res_id': alias.alias_force_thread_id,
+            'type': 'ir.actions.act_window',
+        }
index e0d8e17..53b673b 100644 (file)
@@ -9,7 +9,6 @@
             <field name="arch" type="xml">
                 <form string="Alias" version="7.0">
                     <sheet>
-                        <label for="alias_name" class="oe_edit_only"/>
                         <h2><field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline"/></h2>
                         <group>
                             <field name="alias_model_id"/>
@@ -17,6 +16,8 @@
                             <field name="alias_force_thread_id"/>
                             <field name="alias_defaults"/>
                         </group>
+                        <button name="open_document" string="Open Document" type="object"
+                                attrs="{'invisible': ['|', ('alias_model_id', '=', False), ('alias_force_thread_id', '=', False)]}"/>
                     </sheet>
                 </form>
             </field>
                 <search string="Search Alias">
                     <field name="alias_name"/>
                     <field name="alias_model_id"/>
+                    <separator/>
+                    <filter string="Active" name="active" domain="[('alias_name', '!=', False)]"/>
                     <group expand="0" string="Group By...">
-                        <filter string="User" name="User" icon="terp-personal" context="{'group_by':'alias_user_id'}"/>
+                        <filter string="User" name="User" context="{'group_by':'alias_user_id'}"/>
                         <filter string="Model" name="Model" context="{'group_by':'alias_model_id'}"/>
                     </group>
                 </search>
         <record id="action_view_mail_alias" model="ir.actions.act_window">
             <field name="name">Aliases</field>
             <field name="res_model">mail.alias</field>
+            <field name="context">{
+                    'search_default_active': True,
+                }
+            </field>
         </record>
 
         <menuitem id="mail_alias_menu"
index 977608f..28cc7be 100644 (file)
@@ -100,10 +100,10 @@ class mail_group(osv.Model):
         header = ''
         if group.description:
             header = '%s' % group.description
-        if group.alias_id and group.alias_id.alias_name and group.alias_id.alias_domain:
+        if group.alias_id and group.alias_name and group.alias_domain:
             if header:
                 header = '%s<br/>' % header
-            return '%sGroup email gateway: %s@%s' % (header, group.alias_id.alias_name, group.alias_id.alias_domain)
+            return '%sGroup email gateway: %s@%s' % (header, group.alias_name, group.alias_domain)
         return header
 
     def _subscribe_users(self, cr, uid, ids, context=None):
@@ -114,15 +114,8 @@ class mail_group(osv.Model):
             self.message_subscribe(cr, uid, ids, partner_ids, context=context)
 
     def create(self, cr, uid, vals, context=None):
-        mail_alias = self.pool.get('mail.alias')
-        if not vals.get('alias_id'):
-            vals.pop('alias_name', None)  # prevent errors during copy()
-            alias_id = mail_alias.create_unique_alias(cr, uid,
-                          # Using '+' allows using subaddressing for those who don't
-                          # have a catchall domain setup.
-                          {'alias_name': "group+" + vals['name']},
-                          model_name=self._name, context=context)
-            vals['alias_id'] = alias_id
+        if context is None:
+            context = {}
 
         # get parent menu
         menu_parent = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'mail_group_root')
@@ -134,8 +127,10 @@ class mail_group(osv.Model):
         vals['menu_id'] = menu_id
 
         # Create group and alias
-        mail_group_id = super(mail_group, self).create(cr, uid, vals, context=context)
-        mail_alias.write(cr, uid, [vals['alias_id']], {"alias_force_thread_id": mail_group_id}, context)
+        create_context = dict(context, alias_model_name=self._name)
+        mail_group_id = super(mail_group, self).create(cr, uid, vals, context=create_context)
+        group = self.browse(cr, uid, mail_group_id, context=context)
+        self.pool.get('mail.alias').write(cr, uid, [group.alias_id.id], {"alias_force_thread_id": mail_group_id}, context)
         group = self.browse(cr, uid, mail_group_id, context=context)
 
         # Create client action for this group and link the menu to it
index 04212b2..96f5aa7 100644 (file)
@@ -44,7 +44,7 @@
                                 <div class="oe_group_details">
                                     <h4><a type="open"><field name="name"/></a></h4>
                                     <div class="oe_kanban_alias" t-if="record.alias_id.value">
-                                        <span class="oe_e">%%</span><small><field name="alias_id"/></small>
+                                        <span class="oe_e oe_e_alias">%%</span><small><field name="alias_id"/></small>
                                     </div>
                                     <div class="oe_grey">
                                         <field name="description"/>
                             <h1><field name="name" readonly="0"/></h1>
                             <div name="group_alias"
                                     attrs="{'invisible': [('alias_domain', '=', False)]}">
-                                <label for="alias_id" string="Email Alias"/>
-                                <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
+                                <span name="read_alias" class="oe_read_only" attrs="{'invisible': [('alias_name', '=', False)]}">
+                                    <span class="oe_e oe_e_alias">%%</span>
+                                    <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
+                                </span>
                                 <span name="edit_alias" class="oe_edit_only">
-                                    <field name="alias_name" class="oe_inline"
-                                            attrs="{'required': [('alias_id', '!=', False)]}"/>
-                                    @
-                                    <field name="alias_domain" class="oe_inline" readonly="1"/>
+                                    <span class="oe_e oe_e_alias">%%</span>
+                                    <field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
                                 </span>
                             </div>
                         </div>
index f7c9193..0f4e5af 100644 (file)
@@ -23,6 +23,7 @@ from openerp.osv import fields, osv
 from openerp import SUPERUSER_ID
 from openerp.tools.translate import _
 
+
 class res_users(osv.Model):
     """ Update of res.users class
         - add a preference about sending emails about notifications
@@ -64,20 +65,16 @@ class res_users(osv.Model):
             self._columns['alias_id'], 'login', alias_force_key='id', context=context)
 
     def create(self, cr, uid, data, context=None):
-        # create default alias same as the login
         if not data.get('login', False):
             raise osv.except_osv(_('Invalid Action!'), _('You may not create a user. To create new users, you should use the "Settings > Users" menu.'))
+        if context is None:
+            context = {}
 
-        mail_alias = self.pool.get('mail.alias')
-        alias_id = mail_alias.create_unique_alias(cr, uid, {'alias_name': data['login']}, model_name=self._name, context=context)
-        data['alias_id'] = alias_id
-        data.pop('alias_name', None)  # prevent errors during copy()
-
-        # create user
-        user_id = super(res_users, self).create(cr, uid, data, context=context)
+        create_context = dict(context, alias_model_name=self._name)
+        user_id = super(res_users, self).create(cr, uid, data, context=create_context)
         user = self.browse(cr, uid, user_id, context=context)
-        # alias
-        mail_alias.write(cr, SUPERUSER_ID, [alias_id], {"alias_force_thread_id": user_id}, context)
+        self.pool.get('mail.alias').write(cr, SUPERUSER_ID, [user.alias_id.id], {"alias_force_thread_id": user_id}, context)
+
         # create a welcome message
         self._create_welcome_message(cr, uid, user, context=context)
         return user_id
@@ -91,12 +88,6 @@ class res_users(osv.Model):
         return self.pool.get('res.partner').message_post(cr, SUPERUSER_ID, [user.partner_id.id],
             body=body, context=context)
 
-    def write(self, cr, uid, ids, vals, context=None):
-        # User alias is sync'ed with login
-        if vals.get('login'):
-            vals['alias_name'] = vals['login']
-        return super(res_users, self).write(cr, uid, ids, vals, context=context)
-
     def unlink(self, cr, uid, ids, context=None):
         # Cascade-delete mail aliases as well, as they should not exist without the user.
         alias_pool = self.pool.get('mail.alias')
index f49ff72..b6a5ac3 100644 (file)
                     <field name="notification_email_send"/>
                 </field>
                 <field name="email" position="after">
-                    <field name="alias_domain" invisible="1"/>
-                    <field name="alias_id" readonly="1" required="0" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
+                    <label for="alias_id" string="Alias"/>
+                    <div name="group_alias"
+                                    attrs="{'invisible': [('alias_domain', '=', False)]}">
+                        <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
+                        <div name="edit_alias" class="oe_edit_only">
+                            <field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
+                        </div>
+                    </div>
                 </field>
             </data>
             </field>
index a3b9028..0de2dc3 100644 (file)
@@ -70,9 +70,9 @@ class TestMailBase(common.TransactionCase):
 
         # Test users to use through the various tests
         self.user_raoul_id = self.res_users.create(cr, uid,
-            {'name': 'Raoul Grosbedon', 'signature': 'SignRaoul', 'email': 'raoul@raoul.fr', 'login': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]})
+            {'name': 'Raoul Grosbedon', 'signature': 'SignRaoul', 'email': 'raoul@raoul.fr', 'login': 'raoul', 'alias_name': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]})
         self.user_bert_id = self.res_users.create(cr, uid,
-            {'name': 'Bert Tartignole', 'signature': 'SignBert', 'email': 'bert@bert.fr', 'login': 'bert', 'groups_id': [(6, 0, [])]})
+            {'name': 'Bert Tartignole', 'signature': 'SignBert', 'email': 'bert@bert.fr', 'login': 'bert', 'alias_name': 'bert', 'groups_id': [(6, 0, [])]})
         self.user_raoul = self.res_users.browse(cr, uid, self.user_raoul_id)
         self.user_bert = self.res_users.browse(cr, uid, self.user_bert_id)
         self.user_admin = self.res_users.browse(cr, uid, uid)
@@ -82,7 +82,7 @@ class TestMailBase(common.TransactionCase):
 
         # Test 'pigs' group to use through the various tests
         self.group_pigs_id = self.mail_group.create(cr, uid,
-            {'name': 'Pigs', 'description': 'Fans of Pigs, unite !'},
+            {'name': 'Pigs', 'description': 'Fans of Pigs, unite !', 'alias_name': 'group+pigs'},
             {'mail_create_nolog': True})
         self.group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
 
index 7eea66b..f23440d 100644 (file)
@@ -24,26 +24,25 @@ from openerp.tools.mail import html_sanitize
 
 
 class test_mail(TestMailBase):
-    
+
     def test_000_alias_setup(self):
         """ Test basic mail.alias setup works, before trying to use them for routing """
         cr, uid = self.cr, self.uid
         self.user_valentin_id = self.res_users.create(cr, uid,
-            {'name': 'Valentin Cognito', 'email': 'valentin.cognito@gmail.com', 'login': 'valentin.cognito'})
+            {'name': 'Valentin Cognito', 'email': 'valentin.cognito@gmail.com', 'login': 'valentin.cognito', 'alias_name': 'valentin.cognito'})
         self.user_valentin = self.res_users.browse(cr, uid, self.user_valentin_id)
         self.assertEquals(self.user_valentin.alias_name, self.user_valentin.login, "Login should be used as alias")
 
         self.user_pagan_id = self.res_users.create(cr, uid,
-            {'name': 'Pagan Le Marchant', 'email': 'plmarchant@gmail.com', 'login': 'plmarchant@gmail.com'})
+            {'name': 'Pagan Le Marchant', 'email': 'plmarchant@gmail.com', 'login': 'plmarchant@gmail.com', 'alias_name': 'plmarchant@gmail.com'})
         self.user_pagan = self.res_users.browse(cr, uid, self.user_pagan_id)
         self.assertEquals(self.user_pagan.alias_name, 'plmarchant', "If login is an email, the alias should keep only the local part")
 
         self.user_barty_id = self.res_users.create(cr, uid,
-            {'name': 'Bartholomew Ironside', 'email': 'barty@gmail.com', 'login': 'b4r+_#_R3wl$$'})
+            {'name': 'Bartholomew Ironside', 'email': 'barty@gmail.com', 'login': 'b4r+_#_R3wl$$', 'alias_name': 'b4r+_#_R3wl$$'})
         self.user_barty = self.res_users.browse(cr, uid, self.user_barty_id)
         self.assertEquals(self.user_barty.alias_name, 'b4r+_-_r3wl-', 'Disallowed chars should be replaced by hyphens')
 
-
     def test_00_followers_function_field(self):
         """ Tests designed for the many2many function field 'follower_ids'.
             We will test to perform writes using the many2many commands 0, 3, 4,
index eb32800..b580965 100644 (file)
@@ -348,13 +348,11 @@ class project(osv.osv):
         default['state'] = 'open'
         default['line_ids'] = []
         default['tasks'] = []
-        default.pop('alias_name', None)
-        default.pop('alias_id', None)
         proj = self.browse(cr, uid, id, context=context)
         if not default.get('name', False):
             default.update(name=_("%s (copy)") % (proj.name))
         res = super(project, self).copy(cr, uid, id, default, context)
-        self.map_tasks(cr,uid,id,res,context)
+        self.map_tasks(cr, uid, id, res, context=context)
         return res
 
     def duplicate_template(self, cr, uid, ids, context=None):
@@ -505,7 +503,7 @@ def Project():
         for project in projects:
             project_gantt = getattr(projects_gantt, 'Project_%d' % (project.id,))
             for task in project.tasks:
-                if task.state in ('done','cancelled'):
+                if task.state in ('done', 'cancelled'):
                     continue
 
                 p = getattr(project_gantt, 'Task_%d' % (task.id,))
@@ -525,23 +523,17 @@ def Project():
     # ------------------------------------------------
 
     def create(self, cr, uid, vals, context=None):
-        if context is None: context = {}
-        # Prevent double project creation when 'use_tasks' is checked!
-        context = dict(context, project_creation_in_progress=True)
-        mail_alias = self.pool.get('mail.alias')
-        if not vals.get('alias_id') and vals.get('name', False):
-            alias_name = vals.pop('alias_name', None) # prevent errors during copy()
-            alias_id = mail_alias.create_unique_alias(cr, uid,
-                          # Using '+' allows using subaddressing for those who don't
-                          # have a catchall domain setup.
-                          {'alias_name': alias_name or "project+"+short_name(vals['name'])},
-                          model_name=vals.get('alias_model', 'project.task'),
-                          context=context)
-            vals['alias_id'] = alias_id
-        if vals.get('type', False) not in ('template','contract'):
+        if context is None:
+            context = {}
+        # Prevent double project creation when 'use_tasks' is checked + alias management
+        create_context = dict(context, project_creation_in_progress=True, alias_model_name=self._name)
+
+        if vals.get('type', False) not in ('template', 'contract'):
             vals['type'] = 'contract'
-        project_id = super(project, self).create(cr, uid, vals, context)
-        mail_alias.write(cr, uid, [vals['alias_id']], {'alias_defaults': {'project_id': project_id} }, context)
+
+        project_id = super(project, self).create(cr, uid, vals, context=create_context)
+        project_rec = self.browse(cr, uid, project_id, context=context)
+        self.pool.get('mail.alias').write(cr, uid, [project_rec.alias_id.id], {'alias_defaults': {'project_id': project_id}}, context)
         return project_id
 
     def write(self, cr, uid, ids, vals, context=None):
index a016c46..5a1f038 100644 (file)
                             <field name="name" string="Project Name"/>
                         </h1>
                         <div name="group_alias"
-                            attrs="{'invisible': [('alias_domain', '=', False)]}">
-                        <label for="alias_id" string="Email Alias"/>
-                        <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
-                        <span name="edit_alias" class="oe_edit_only">
-                            <field name="alias_name" class="oe_inline"
-                                    attrs="{'required': [('alias_id', '!=', False)]}"/>
-                            @
-                            <field name="alias_domain" class="oe_inline" readonly="1"/>
-                        </span>
-                    </div>
+                                attrs="{'invisible': [('alias_domain', '=', False)]}">
+                            <span name="read_alias" class="oe_read_only" attrs="{'invisible': [('alias_name', '=', False)]}">
+                                <span class="oe_e oe_e_alias">%%</span>
+                                <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
+                            </span>
+                            <span name="edit_alias" class="oe_edit_only">
+                                <span class="oe_e oe_e_alias">%%</span>
+                                <field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
+                            </span>
+                        </div>
                         <div name="options_active">
                             <field name="use_tasks" class="oe_inline"/>
                             <label for="use_tasks"/>
                                 <div class="oe_kanban_content">
                                     <h4><field name="name"/></h4>
                                     <div class="oe_kanban_alias" t-if="record.alias_id.value">
-                                        <span class="oe_e">%%</span><small><field name="alias_id"/></small>
+                                        <span class="oe_e oe_e_alias">%%</span><small><field name="alias_id"/></small>
                                     </div>
                                     <div class="oe_kanban_project_list">
                                         <a t-if="record.use_tasks.raw_value" name="%(act_project_project_2_project_task_all)d" type="action" style="margin-right: 10px"> 
index f888ff9..8114108 100644 (file)
                 <field name="priority" position="before">
                     <field name="project_escalation_id"/>
                 </field>
-                <xpath expr='//span[@name="edit_alias"]' position='replace'>
+                <xpath expr='//span[@name="edit_alias"]' position='after'>
+                    <label for="alias_model" string="creates" style="vertical-align: middle;"/>
+                    <field name="alias_model" class="oe_inline"/>
+                </xpath>
+<!--                 <xpath expr='//span[@name="edit_alias"]' position='replace'>
                     <span class="oe_edit_only" name="edit_alias">
                         <field name="alias_name" class="oe_inline" attrs="{'required': [('alias_id', '!=', False)]}"/>
                         @
                             <field name="alias_model" class="oe_inline"/>
                         </span>
                     </span>
-                </xpath>
+                </xpath> -->
             </field>
        </record>