[WIP] started to reduce code
authorFabien Pinckaers <fp@tinyerp.com>
Sat, 12 Apr 2014 15:33:39 +0000 (17:33 +0200)
committerFabien Pinckaers <fp@tinyerp.com>
Sat, 12 Apr 2014 15:33:39 +0000 (17:33 +0200)
bzr revid: fp@tinyerp.com-20140412153339-rr3b1r4cmdeigp0v

1  2 
addons/mass_mailing/__openerp__.py
addons/mass_mailing/models/__init__.py
addons/mass_mailing/models/mass_mailing.py
addons/mass_mailing/views/mass_mailing.xml
addons/mass_mailing/wizard/__init__.py
addons/mass_mailing/wizard/mailing_list_confirm.py
addons/mass_mailing/wizard/mailing_list_confirm.xml

@@@ -44,7 -44,7 +44,6 @@@ professional emails and reuse template
          'data/mass_mailing_data.xml',
          'wizard/mail_compose_message_view.xml',
          'wizard/test_mailing.xml',
--        'wizard/mailing_list_confirm.xml',
          'views/mass_mailing_report.xml',
          'views/mass_mailing.xml',
          'views/res_config.xml',
@@@ -1,6 -1,6 +1,7 @@@
  # -*- coding: utf-8 -*-
  
  import mass_mailing
++import mass_mailing_stats
  import mail_mail
  import mail_thread
  import email_template
  from datetime import datetime
  from dateutil import relativedelta
  import random
--try:
--    import simplejson as json
--except ImportError:
--    import json
++import json
  import urllib
  import urlparse
  
@@@ -59,160 -59,69 +56,28 @@@ class MassMailingContact(osv.Model)
          'email': fields.char('Email', required=True),
          'list_id': fields.many2one(
              'mail.mass_mailing.list', string='Mailing List',
-             domain=[('model', '=', 'mail.mass_mailing.contact')],
              ondelete='cascade',
          ),
-         'opt_out': fields.boolean('Opt Out', help='The contact has chosen not to receive news anymore from this mailing list'),
+         'opt_out': fields.boolean('Opt Out', help='The contact has chosen not to receive mails anymore from this list'),
      }
  
-     def name_create(self, cr, uid, name, context=None):
-         name, email = self.pool['res.partner']._parse_partner_name(name, context=context)
-         if name and not email:
-             email = name
-         if email and not name:
-             name = email
-         rec_id = self.create(cr, uid, {'name': name, 'email': email}, context=context)
-         return self.name_get(cr, uid, [rec_id], context)[0]
++    def _get_latest_list(self, cr, uid, context={}):
++        lid = self.pool.get('mail.mass_mailing.list').search(cr, uid, [], limit=1, order='id desc', context=context)
++        return lid and lid[0] or False
++    _defaults = {
++        'list_id': _get_latest_list
++    }
 +
  
  class MassMailingList(osv.Model):
      """Model of a contact list. """
      _name = 'mail.mass_mailing.list'
-     _description = 'Contact List'
-     def default_get(self, cr, uid, fields, context=None):
-         """Override default_get to handle active_domain coming from the list view. """
-         res = super(MassMailingList, self).default_get(cr, uid, fields, context=context)
-         if 'domain' in fields:
-             if not 'model' in res and context.get('active_model'):
-                 res['model'] = context['active_model']
-             if 'active_domain' in context:
-                 res['domain'] = '%s' % context['active_domain']
-             elif 'active_ids' in context:
-                 res['domain'] = '%s' % [('id', 'in', context['active_ids'])]
-             else:
-                 res['domain'] = False
-         return res
-     def _get_contact_nbr(self, cr, uid, ids, name, arg, context=None):
-         """Compute the number of contacts linked to the mailing list. """
-         results = dict.fromkeys(ids, 0)
-         for contact_list in self.browse(cr, uid, ids, context=context):
-             results[contact_list.id] = self.pool[contact_list.model].search(
-                 cr, uid,
-                 self._get_domain(cr, uid, [contact_list.id], context=context)[contact_list.id],
-                 count=True, context=context
-             )
-         return results
-     def _get_model_list(self, cr, uid, context=None):
-         return self.pool['mail.mass_mailing']._get_mailing_model(cr, uid, context=context)
-     # indirections for inheritance
-     _model_list = lambda self, *args, **kwargs: self._get_model_list(*args, **kwargs)
+     _order = 'name'
+     _description = 'Mailing List'
 -
 -    def _get_contact_nbr(self, cr, uid, ids, name, arg, context=None):
 -        """Compute the number of contacts linked to the mailing list. """
 -        results = dict.fromkeys(ids, 0)
 -        mlc = self.pool.get('mail.mass_mailing.contact').
 -        result = dict(lambda x: (x,0), ids)
 -        for m in mlc.read_group(cr, uid, [('list_id','in',ids)], ['list_id'], ['list_id'], context=context):
 -            result[m['list_id']] = m['__count']
 -        return results
 -
      _columns = {
-         'name': fields.char('Name', required=True),
-         'contact_nbr': fields.function(
-             _get_contact_nbr, type='integer',
-             string='Contact Number',
-         ),
-         'model': fields.selection(
-             _model_list, type='char', required=True,
-             string='Applies To'
-         ),
-         'filter_id': fields.many2one(
-             'ir.filters', string='Custom Filter',
-             domain="[('model_id.model', '=', model)]",
-         ),
-         'domain': fields.text('Domain'),
+         'name': fields.char('Mailing List', required=True),
 -        'contact_nbr': fields.function(
 -            _get_contact_nbr, type='integer',
 -            string='Contact Number',
 -        ),
      }
  
-     def on_change_model(self, cr, uid, ids, model, context=None):
-         return {'value': {'filter_id': False}}
-     def on_change_filter_id(self, cr, uid, ids, filter_id, context=None):
-         values = {}
-         if filter_id:
-             ir_filter = self.pool['ir.filters'].browse(cr, uid, filter_id, context=context)
-             values['domain'] = ir_filter.domain
-         return {'value': values}
-     def on_change_domain(self, cr, uid, ids, domain, model, context=None):
-         if domain is False:
-             return {'value': {'contact_nbr': 0}}
-         else:
-             domain = eval(domain)
-             return {'value': {'contact_nbr': self.pool[model].search(cr, uid, domain, context=context, count=True)}}
-     def create(self, cr, uid, values, context=None):
-         new_id = super(MassMailingList, self).create(cr, uid, values, context=context)
-         if values.get('model') == 'mail.mass_mailing.contact' and (not context or not context.get('no_contact_to_list')):
-             domain = values.get('domain')
-             if domain is None or domain is False:
-                 return new_id
-             contact_ids = self.pool['mail.mass_mailing.contact'].search(cr, uid, eval(domain), context=context)
-             self.pool['mail.mass_mailing.contact'].write(cr, uid, contact_ids, {'list_id': new_id}, context=context)
-             self.pool['mail.mass_mailing.list'].write(cr, uid, [new_id], {'domain': [('list_id', '=', new_id)]}, context=context)
-         return new_id
-     def action_see_records(self, cr, uid, ids, context=None):
-         contact_list = self.browse(cr, uid, ids[0], context=context)
-         ctx = dict(context)
-         ctx['search_default_not_opt_out'] = True
-         return {
-             'name': _('See Contact List'),
-             'type': 'ir.actions.act_window',
-             'view_type': 'form',
-             'view_mode': 'tree,form',
-             'res_model': contact_list.model,
-             'views': [(False, 'tree'), (False, 'form')],
-             'view_id': False,
-             'target': 'current',
-             'context': ctx,
-             'domain': contact_list.domain,
-         }
-     def action_add_to_mailing(self, cr, uid, ids, context=None):
-         mass_mailing_id = context.get('default_mass_mailing_id')
-         if not mass_mailing_id:
-             return False
-         self.pool['mail.mass_mailing'].write(cr, uid, [mass_mailing_id], {'contact_list_ids': [(4, list_id) for list_id in ids]}, context=context)
-         return {
-             'name': _('Mass Mailing'),
-             'type': 'ir.actions.act_window',
-             'view_type': 'form',
-             'view_mode': 'form',
-             'res_model': 'mail.mass_mailing',
-             'res_id': mass_mailing_id,
-             'context': context,
-         }
-     def _get_domain(self, cr, uid, ids, context=None):
-         domains = {}
-         for contact_list in self.browse(cr, uid, ids, context=context):
-             if contact_list.domain is False or contact_list.domain is None:  # domain is a string like False or None -> void list
-                 domain = [('id', '=', '0')]
-             else:
-                 domain = eval(contact_list.domain)
-             domains[contact_list.id] = domain
-         return domains
-     def get_global_domain(self, cr, uid, ids, context=None):
-         model_to_domains = dict((mailing_model[0], list())
-                                 for mailing_model in self.pool['mail.mass_mailing']._get_mailing_model(cr, uid, context=context))
-         for contact_list in self.browse(cr, uid, ids, context=context):
-             domain = self._get_domain(cr, uid, [contact_list.id], context=context)[contact_list.id]
-             if domain is not False:
-                 model_to_domains[contact_list.model].append(domain)
-         for model, domains in model_to_domains.iteritems():
-             if domains:
-                 final_domain = ['|'] * (len(domains) - 1) + [leaf for dom in domains for leaf in dom]
-             else:
-                 final_domain = [('id', '=', '0')]
-             model_to_domains[model] = final_domain
-         return model_to_domains
 -    # TODO: remove this?
 -    def action_see_records(self, cr, uid, ids, context=None):
 -        contact_list = self.browse(cr, uid, ids[0], context=context)
 -        ctx = dict(context)
 -        ctx['search_default_not_opt_out'] = True
 -        return {
 -            'name': _('See Contact List'),
 -            'type': 'ir.actions.act_window',
 -            'view_type': 'form',
 -            'view_mode': 'tree,form',
 -            'res_model': contact_list.model,
 -            'views': [(False, 'tree'), (False, 'form')],
 -            'view_id': False,
 -            'target': 'current',
 -            'context': ctx,
 -            'domain': contact_list.domain,
 -        }
 -
 -    # TODO: remove this?
 -    def action_add_to_mailing(self, cr, uid, ids, context=None):
 -        mass_mailing_id = context.get('default_mass_mailing_id')
 -        if not mass_mailing_id:
 -            return False
 -        self.pool['mail.mass_mailing'].write(cr, uid, [mass_mailing_id], {'contact_list_ids': [(4, list_id) for list_id in ids]}, context=context)
 -        return {
 -            'name': _('Mass Mailing'),
 -            'type': 'ir.actions.act_window',
 -            'view_type': 'form',
 -            'view_mode': 'form',
 -            'res_model': 'mail.mass_mailing',
 -            'res_id': mass_mailing_id,
 -            'context': context,
 -        }
 -
  
  class MassMailingStage(osv.Model):
      """Stage for mass mailing campaigns. """
@@@ -234,29 -141,29 +97,6 @@@ class MassMailingCampaign(osv.Model)
      """Model of mass mailing campaigns. """
      _name = "mail.mass_mailing.campaign"
      _description = 'Mass Mailing Campaign'
--
--    def _get_statistics(self, cr, uid, ids, name, arg, context=None):
--        """ Compute statistics of the mass mailing campaign """
--        Statistics = self.pool['mail.mail.statistics']
--        results = dict.fromkeys(ids, False)
--        for cid in ids:
--            stat_ids = Statistics.search(cr, uid, [('mass_mailing_campaign_id', '=', cid)], context=context)
--            stats = Statistics.browse(cr, uid, stat_ids, context=context)
--            results[cid] = {
--                'total': len(stats),
--                'failed': len([s for s in stats if not s.scheduled is False and s.sent is False and not s.exception is False]),
--                'scheduled': len([s for s in stats if not s.scheduled is False and s.sent is False and s.exception is False]),
--                'sent': len([s for s in stats if not s.sent is False]),
--                'opened': len([s for s in stats if not s.opened is False]),
--                'replied': len([s for s in stats if not s.replied is False]),
--                'bounced': len([s for s in stats if not s.bounced is False]),
--            }
--            results[cid]['delivered'] = results[cid]['sent'] - results[cid]['bounced']
--            results[cid]['received_ratio'] = 100.0 * results[cid]['delivered'] / (results[cid]['sent'] or 1)
--            results[cid]['opened_ratio'] = 100.0 * results[cid]['opened'] / (results[cid]['sent'] or 1)
--            results[cid]['replied_ratio'] = 100.0 * results[cid]['replied'] / (results[cid]['sent'] or 1)
--        return results
--
      _columns = {
          'name': fields.char('Name', required=True),
          'stage_id': fields.many2one('mail.mass_mailing.stage', 'Stage', required=True),
              'mail.mass_mailing', 'mass_mailing_campaign_id',
              'Mass Mailings',
          ),
-         'ab_testing': fields.boolean(
-             'AB Testing',
-             help='If checked, recipients will be mailed only once, allowing to send'
-                  'various mailings in a single campaign to test the effectiveness'
-                  'of the mailings.'),
          'color': fields.integer('Color Index'),
--        # stat fields
--        'total': fields.function(
--            _get_statistics, string='Total',
--            type='integer', multi='_get_statistics'
--        ),
--        'scheduled': fields.function(
--            _get_statistics, string='Scheduled',
--            type='integer', multi='_get_statistics'
--        ),
--        'failed': fields.function(
--            _get_statistics, string='Failed',
--            type='integer', multi='_get_statistics'
--        ),
--        'sent': fields.function(
--            _get_statistics, string='Sent Emails',
--            type='integer', multi='_get_statistics'
--        ),
--        'delivered': fields.function(
--            _get_statistics, string='Delivered',
--            type='integer', multi='_get_statistics',
--        ),
--        'opened': fields.function(
--            _get_statistics, string='Opened',
--            type='integer', multi='_get_statistics',
--        ),
--        'replied': fields.function(
--            _get_statistics, string='Replied',
--            type='integer', multi='_get_statistics'
--        ),
--        'bounced': fields.function(
--            _get_statistics, string='Bounced',
--            type='integer', multi='_get_statistics'
--        ),
--        'received_ratio': fields.function(
--            _get_statistics, string='Received Ratio',
--            type='integer', multi='_get_statistics',
--        ),
--        'opened_ratio': fields.function(
--            _get_statistics, string='Opened Ratio',
--            type='integer', multi='_get_statistics',
--        ),
--        'replied_ratio': fields.function(
--            _get_statistics, string='Replied Ratio',
--            type='integer', multi='_get_statistics',
--        ),
      }
  
      def _get_default_stage_id(self, cr, uid, context=None):
  
      _defaults = {
          'user_id': lambda self, cr, uid, ctx=None: uid,
--        'stage_id': lambda self, cr, uid, ctx=None: self._get_default_stage_id(cr, uid, context=ctx),
++        'stage_id': lambda self, *args: self._get_default_stage_id(*args),
      }
  
--    #------------------------------------------------------
-     # Actions
-     #------------------------------------------------------
-     def action_new_mailing(self, cr, uid, ids, context=None):
-         return {
-             'name': _('Create a Mass Mailing for the Campaign'),
-             'type': 'ir.actions.act_window',
-             'view_type': 'form',
-             'view_mode': 'form',
-             'res_model': 'mail.mass_mailing',
-             'views': [(False, 'form')],
-             'context': dict(context, default_mass_mailing_campaign_id=ids[0]),
-         }
-     #------------------------------------------------------
--    # API
--    #------------------------------------------------------
-     def get_recipients(self, cr, uid, ids, model=None, context=None):
-         """Return the recipints of a mailing campaign. This is based on the statistics
-         build for each mailing. """
-         Statistics = self.pool['mail.mail.statistics']
-         res = dict.fromkeys(ids, False)
-         for cid in ids:
-             domain = [('mass_mailing_campaign_id', '=', cid)]
-             if model:
-                 domain += [('model', '=', model)]
-             stat_ids = Statistics.search(cr, uid, domain, context=context)
-             res[cid] = set(stat.res_id for stat in Statistics.browse(cr, uid, stat_ids, context=context))
-         return res
 -    # def get_recipients(self, cr, uid, ids, model=None, context=None):
 -    #     """Return the recipints of a mailing campaign. This is based on the statistics
 -    #     build for each mailing. """
 -    #     Statistics = self.pool['mail.mail.statistics']
 -    #     res = dict.fromkeys(ids, False)
 -    #     for cid in ids:
 -    #         domain = [('mass_mailing_campaign_id', '=', cid)]
 -    #         if model:
 -    #             domain += [('model', '=', model)]
 -    #         stat_ids = Statistics.search(cr, uid, domain, context=context)
 -    #         res[cid] = set(stat.res_id for stat in Statistics.browse(cr, uid, stat_ids, context=context))
 -    #     return res
 -
  
  class MassMailing(osv.Model):
      """ MassMailing models a wave of emails for a mass mailign campaign.
      A mass mailing is an occurence of sending emails. """
--
      _name = 'mail.mass_mailing'
      _description = 'Mass Mailing'
--    # number of periods for tracking mail_mail statistics
--    _period_number = 6
-     _order = 'date DESC'
-     def __get_bar_values(self, cr, uid, id, obj, domain, read_fields, value_field, groupby_field, context=None):
-         """ Generic method to generate data for bar chart values using SparklineBarWidget.
-             This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field).
-             :param obj: the target model (i.e. crm_lead)
-             :param domain: the domain applied to the read_group
-             :param list read_fields: the list of fields to read in the read_group
-             :param str value_field: the field used to compute the value of the bar slice
-             :param str groupby_field: the fields used to group
-             :return list section_result: a list of dicts: [
-                                                 {   'value': (int) bar_column_value,
-                                                     'tootip': (str) bar_column_tooltip,
-                                                 }
-                                             ]
-         """
-         date_begin = datetime.strptime(self.browse(cr, uid, id, context=context).date, tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
-         section_result = [{'value': 0,
-                            'tooltip': (date_begin + relativedelta.relativedelta(days=i)).strftime('%d %B %Y'),
-                            } for i in range(0, self._period_number)]
-         group_obj = obj.read_group(cr, uid, domain, read_fields, groupby_field, context=context)
-         field_col_info = obj._all_columns.get(groupby_field.split(':')[0])
-         pattern = tools.DEFAULT_SERVER_DATE_FORMAT if field_col_info.column._type == 'date' else tools.DEFAULT_SERVER_DATETIME_FORMAT
-         for group in group_obj:
-             group_begin_date = datetime.strptime(group['__domain'][0][2], pattern).date()
-             timedelta = relativedelta.relativedelta(group_begin_date, date_begin)
-             section_result[timedelta.days] = {'value': group.get(value_field, 0), 'tooltip': group.get(groupby_field)}
-         return section_result
-     def _get_daily_statistics(self, cr, uid, ids, field_name, arg, context=None):
-         """ Get the daily statistics of the mass mailing. This is done by a grouping
-         on opened and replied fields. Using custom format in context, we obtain
-         results for the next 6 days following the mass mailing date. """
-         obj = self.pool['mail.mail.statistics']
-         res = {}
-         for id in ids:
-             res[id] = {}
-             date_begin = datetime.strptime(self.browse(cr, uid, id, context=context).date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
-             date_end = date_begin + relativedelta.relativedelta(days=self._period_number - 1)
-             date_begin_str = date_begin.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
-             date_end_str = date_end.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
-             domain = [('mass_mailing_id', '=', id), ('opened', '>=', date_begin_str), ('opened', '<=', date_end_str)]
-             res[id]['opened_dayly'] = json.dumps(self.__get_bar_values(cr, uid, id, obj, domain, ['opened'], 'opened_count', 'opened:day', context=context))
-             domain = [('mass_mailing_id', '=', id), ('replied', '>=', date_begin_str), ('replied', '<=', date_end_str)]
-             res[id]['replied_dayly'] = json.dumps(self.__get_bar_values(cr, uid, id, obj, domain, ['replied'], 'replied_count', 'replied:day', context=context))
-         return res
-     def _get_statistics(self, cr, uid, ids, name, arg, context=None):
-         """ Compute statistics of the mass mailing campaign """
-         Statistics = self.pool['mail.mail.statistics']
-         results = dict.fromkeys(ids, False)
-         for mid in ids:
-             stat_ids = Statistics.search(cr, uid, [('mass_mailing_id', '=', mid)], context=context)
-             stats = Statistics.browse(cr, uid, stat_ids, context=context)
-             results[mid] = {
-                 'total': len(stats),
-                 'failed': len([s for s in stats if not s.scheduled is False and s.sent is False and not s.exception is False]),
-                 'scheduled': len([s for s in stats if not s.scheduled is False and s.sent is False and s.exception is False]),
-                 'sent': len([s for s in stats if not s.sent is False]),
-                 'opened': len([s for s in stats if not s.opened is False]),
-                 'replied': len([s for s in stats if not s.replied is False]),
-                 'bounced': len([s for s in stats if not s.bounced is False]),
-             }
-             results[mid]['delivered'] = results[mid]['sent'] - results[mid]['bounced']
-             results[mid]['received_ratio'] = 100.0 * results[mid]['delivered'] / (results[mid]['sent'] or 1)
-             results[mid]['opened_ratio'] = 100.0 * results[mid]['opened'] / (results[mid]['sent'] or 1)
-             results[mid]['replied_ratio'] = 100.0 * results[mid]['replied'] / (results[mid]['sent'] or 1)
-         return results
-     def _get_contact_nbr(self, cr, uid, ids, name, arg, context=None):
-         res = dict.fromkeys(ids, False)
-         for mailing in self.browse(cr, uid, ids, context=context):
-             val = {'contact_nbr': 0, 'contact_ab_nbr': 0, 'contact_ab_done': 0}
-             val['contact_nbr'] = self.pool[mailing.mailing_model].search(
-                 cr, uid,
-                 self.pool['mail.mass_mailing.list'].get_global_domain(cr, uid, [c.id for c in mailing.contact_list_ids], context=context)[mailing.mailing_model],
-                 count=True, context=context
-             )
-             val['contact_ab_nbr'] = int(val['contact_nbr'] * mailing.contact_ab_pc / 100.0)
-             if mailing.mass_mailing_campaign_id and mailing.ab_testing:
-                 val['contact_ab_done'] = len(self.pool['mail.mass_mailing.campaign'].get_recipients(cr, uid, [mailing.mass_mailing_campaign_id.id], context=context)[mailing.mass_mailing_campaign_id.id])
-             res[mailing.id] = val
-         return res
+     _order = 'id DESC'
  
 -    def __get_bar_values(self, cr, uid, id, obj, domain, read_fields, value_field, groupby_field, context=None):
 -        """ Generic method to generate data for bar chart values using SparklineBarWidget.
 -            This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field).
 -
 -            :param obj: the target model (i.e. crm_lead)
 -            :param domain: the domain applied to the read_group
 -            :param list read_fields: the list of fields to read in the read_group
 -            :param str value_field: the field used to compute the value of the bar slice
 -            :param str groupby_field: the fields used to group
 -
 -            :return list section_result: a list of dicts: [
 -                                                {   'value': (int) bar_column_value,
 -                                                    'tootip': (str) bar_column_tooltip,
 -                                                }
 -                                            ]
 -        """
 -        date_begin = datetime.strptime(self.browse(cr, uid, id, context=context).date, tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
 -        section_result = [{'value': 0,
 -                           'tooltip': (date_begin + relativedelta.relativedelta(days=i)).strftime('%d %B %Y'),
 -                           } for i in range(0, self._period_number)]
 -        group_obj = obj.read_group(cr, uid, domain, read_fields, groupby_field, context=context)
 -        field_col_info = obj._all_columns.get(groupby_field.split(':')[0])
 -        pattern = tools.DEFAULT_SERVER_DATE_FORMAT if field_col_info.column._type == 'date' else tools.DEFAULT_SERVER_DATETIME_FORMAT
 -        for group in group_obj:
 -            group_begin_date = datetime.strptime(group['__domain'][0][2], pattern).date()
 -            timedelta = relativedelta.relativedelta(group_begin_date, date_begin)
 -            section_result[timedelta.days] = {'value': group.get(value_field, 0), 'tooltip': group.get(groupby_field)}
 -        return section_result
 -
 -    def _get_daily_statistics(self, cr, uid, ids, field_name, arg, context=None):
 -        """ Get the daily statistics of the mass mailing. This is done by a grouping
 -        on opened and replied fields. Using custom format in context, we obtain
 -        results for the next 6 days following the mass mailing date. """
 -        obj = self.pool['mail.mail.statistics']
 -        res = {}
 -        for id in ids:
 -            res[id] = {}
 -            date_begin = datetime.strptime(self.browse(cr, uid, id, context=context).date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
 -            date_end = date_begin + relativedelta.relativedelta(days=self._period_number - 1)
 -            date_begin_str = date_begin.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
 -            date_end_str = date_end.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
 -            domain = [('mass_mailing_id', '=', id), ('opened', '>=', date_begin_str), ('opened', '<=', date_end_str)]
 -            res[id]['opened_dayly'] = json.dumps(self.__get_bar_values(cr, uid, id, obj, domain, ['opened'], 'opened_count', 'opened:day', context=context))
 -            domain = [('mass_mailing_id', '=', id), ('replied', '>=', date_begin_str), ('replied', '<=', date_end_str)]
 -            res[id]['replied_dayly'] = json.dumps(self.__get_bar_values(cr, uid, id, obj, domain, ['replied'], 'replied_count', 'replied:day', context=context))
 -        return res
 -
 -    def _get_statistics(self, cr, uid, ids, name, arg, context=None):
 -        """ Compute statistics of the mass mailing campaign """
 -        Statistics = self.pool['mail.mail.statistics']
 -        results = dict.fromkeys(ids, False)
 -        for mid in ids:
 -            stat_ids = Statistics.search(cr, uid, [('mass_mailing_id', '=', mid)], context=context)
 -            stats = Statistics.browse(cr, uid, stat_ids, context=context)
 -            results[mid] = {
 -                'total': len(stats),
 -                'failed': len([s for s in stats if not s.scheduled is False and s.sent is False and not s.exception is False]),
 -                'scheduled': len([s for s in stats if not s.scheduled is False and s.sent is False and s.exception is False]),
 -                'sent': len([s for s in stats if not s.sent is False]),
 -                'opened': len([s for s in stats if not s.opened is False]),
 -                'replied': len([s for s in stats if not s.replied is False]),
 -                'bounced': len([s for s in stats if not s.bounced is False]),
 -            }
 -            results[mid]['delivered'] = results[mid]['sent'] - results[mid]['bounced']
 -            results[mid]['received_ratio'] = 100.0 * results[mid]['delivered'] / (results[mid]['sent'] or 1)
 -            results[mid]['opened_ratio'] = 100.0 * results[mid]['opened'] / (results[mid]['sent'] or 1)
 -            results[mid]['replied_ratio'] = 100.0 * results[mid]['replied'] / (results[mid]['sent'] or 1)
 -        return results
 -
 -    # To improve
 -    def _get_contact_nbr(self, cr, uid, ids, name, arg, context=None):
 -        res = dict.fromkeys(ids, False)
 -        for mailing in self.browse(cr, uid, ids, context=context):
 -            val = {'contact_nbr': 0, 'contact_ab_nbr': 0, 'contact_ab_done': 0}
 -            val['contact_nbr'] = self.pool[mailing.mailing_model].search(
 -                cr, uid,
 -                self.pool['mail.mass_mailing.list'].get_global_domain(cr, uid, [c.id for c in mailing.contact_list_ids], context=context)[mailing.mailing_model],
 -                count=True, context=context
 -            )
 -            val['contact_ab_nbr'] = int(val['contact_nbr'] * mailing.contact_ab_pc / 100.0)
 -            if mailing.mass_mailing_campaign_id and mailing.ab_testing:
 -                val['contact_ab_done'] = len(self.pool['mail.mass_mailing.campaign'].get_recipients(cr, uid, [mailing.mass_mailing_campaign_id.id], context=context)[mailing.mass_mailing_campaign_id.id])
 -            res[mailing.id] = val
 -        return res
 -
      def _get_private_models(self, context=None):
          return ['res.partner', 'mail.mass_mailing.contact']
  
              ('mail.mass_mailing.contact', 'Contacts')
          ]
  
-     def _get_state_list(self, cr, uid, context=None):
-         return [('draft', 'Schedule'), ('test', 'Tested'), ('done', 'Sent')]
-     # indirections for inheritance
-     _mailing_model = lambda self, *args, **kwargs: self._get_mailing_model(*args, **kwargs)
-     _state = lambda self, *args, **kwargs: self._get_state_list(*args, **kwargs)
      _columns = {
          'name': fields.char('Subject', required=True),
+         'email_from': fields.char('From'),
          'date': fields.datetime('Date'),
-         'state': fields.selection(
-             _state, string='Status', required=True,
-         ),
-         'template_id': fields.many2one(
-             'email.template', 'Email Template',
-             domain="[('use_in_mass_mailing', '=', True), ('model', '=', mailing_model)]",
-         ),
 -
 -        'state': fields.selection(
 -            [('draft', 'Schedule'), ('test', 'Tested'), ('done', 'Sent')], string='Status', required=True,
 -        ),
 -        # 'template_id': fields.many2one(
 -        #     'email.template', 'Email Template',
 -        #     domain="[('use_in_mass_mailing', '=', True), ('model', '=', mailing_model)]",
 -        # ),
          'body_html': fields.html('Body'),
++
          'mass_mailing_campaign_id': fields.many2one(
              'mail.mass_mailing.campaign', 'Mass Mailing Campaign',
              ondelete='set null',
          ),
-         'ab_testing': fields.related(
-             'mass_mailing_campaign_id', 'ab_testing',
-             type='boolean', string='AB Testing'
 -
 -
 -        # TODO: to remove
 -        'ab_testing': fields.related(
 -            'mass_mailing_campaign_id', 'ab_testing',
 -            type='boolean', string='AB Testing'
 -        ),
 -        'contact_ab_pc': fields.integer(
 -            'AB Testing percentage',
 -            help='Percentage of the contacts that will be mailed. Recipients will be taken randomly.'
 -        ),
 -        'contact_ab_nbr': fields.function(
 -            _get_contact_nbr, type='integer', multi='_get_contact_nbr',
 -            string='Contact Number in AB Testing'
 -        ),
 -        'contact_ab_done': fields.function(
 -            _get_contact_nbr, type='integer', multi='_get_contact_nbr',
 -            string='Number of already mailed contacts'
++        'state': fields.selection(
++            [('draft', 'Schedule'), ('test', 'Tested'), ('done', 'Sent')], string='Status', required=True,
          ),
 -
 -
          'color': fields.related(
              'mass_mailing_campaign_id', 'color',
              type='integer', string='Color Index',
          ),
          # mailing options
-         'email_from': fields.char('From'),
++        # TODO: simplify these 4 fields
          'reply_in_thread': fields.boolean('Reply in thread'),
          'reply_specified': fields.boolean('Specific Reply-To'),
          'auto_reply_to_available': fields.function(
              _get_auto_reply_to_available,
              type='boolean', string='Reply in thread available'
          ),
 -
          'reply_to': fields.char('Reply To'),
-         'mailing_model': fields.selection(_mailing_model, string='Type', required=True),
++        # Target Emails
+         'mailing_model': fields.selection(_get_mailing_model, string='Model', required=True),
 -
++        'mailing_domain': fields.char('Domain', required=True),
          'contact_list_ids': fields.many2many(
              'mail.mass_mailing.list', 'mail_mass_mailing_list_rel',
              string='Mailing Lists',
--            domain="[('model', '=', mailing_model)]",
--        ),
--        'contact_nbr': fields.function(
--            _get_contact_nbr, type='integer', multi='_get_contact_nbr',
--            string='Contact Number'
 -        ),
 -        # statistics data
 -        'statistics_ids': fields.one2many(
 -            'mail.mail.statistics', 'mass_mailing_id',
 -            'Emails Statistics',
 -        ),
 -        'total': fields.function(
 -            _get_statistics, string='Total',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'scheduled': fields.function(
 -            _get_statistics, string='Scheduled',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'failed': fields.function(
 -            _get_statistics, string='Failed',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'sent': fields.function(
 -            _get_statistics, string='Sent',
 -            type='integer', multi='_get_statistics',
          ),
 -        'delivered': fields.function(
 -            _get_statistics, string='Delivered',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'opened': fields.function(
 -            _get_statistics, string='Opened',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'replied': fields.function(
 -            _get_statistics, string='Replied',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'bounced': fields.function(
 -            _get_statistics, string='Bounced',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'received_ratio': fields.function(
 -            _get_statistics, string='Received Ratio',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'opened_ratio': fields.function(
 -            _get_statistics, string='Opened Ratio',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        'replied_ratio': fields.function(
 -            _get_statistics, string='Replied Ratio',
 -            type='integer', multi='_get_statistics',
 -        ),
 -        # dayly ratio
 -        'opened_dayly': fields.function(
 -            _get_daily_statistics, string='Opened',
 -            type='char', multi='_get_daily_statistics',
 -            oldname='opened_monthly',
 -        ),
 -        'replied_dayly': fields.function(
 -            _get_daily_statistics, string='Replied',
 -            type='char', multi='_get_daily_statistics',
 -            oldname='replied_monthly',
 +        'contact_ab_pc': fields.integer(
 +            'AB Testing percentage',
 +            help='Percentage of the contacts that will be mailed. Recipients will be taken randomly.'
          ),
-         'contact_ab_nbr': fields.function(
-             _get_contact_nbr, type='integer', multi='_get_contact_nbr',
-             string='Contact Number in AB Testing'
-         ),
-         'contact_ab_done': fields.function(
-             _get_contact_nbr, type='integer', multi='_get_contact_nbr',
-             string='Number of already mailed contacts'
-         ),
-         # statistics data
-         'statistics_ids': fields.one2many(
-             'mail.mail.statistics', 'mass_mailing_id',
-             'Emails Statistics',
-         ),
-         'total': fields.function(
-             _get_statistics, string='Total',
-             type='integer', multi='_get_statistics',
-         ),
-         'scheduled': fields.function(
-             _get_statistics, string='Scheduled',
-             type='integer', multi='_get_statistics',
-         ),
-         'failed': fields.function(
-             _get_statistics, string='Failed',
-             type='integer', multi='_get_statistics',
-         ),
-         'sent': fields.function(
-             _get_statistics, string='Sent',
-             type='integer', multi='_get_statistics',
-         ),
-         'delivered': fields.function(
-             _get_statistics, string='Delivered',
-             type='integer', multi='_get_statistics',
-         ),
-         'opened': fields.function(
-             _get_statistics, string='Opened',
-             type='integer', multi='_get_statistics',
-         ),
-         'replied': fields.function(
-             _get_statistics, string='Replied',
-             type='integer', multi='_get_statistics',
-         ),
-         'bounced': fields.function(
-             _get_statistics, string='Bounced',
-             type='integer', multi='_get_statistics',
-         ),
-         'received_ratio': fields.function(
-             _get_statistics, string='Received Ratio',
-             type='integer', multi='_get_statistics',
-         ),
-         'opened_ratio': fields.function(
-             _get_statistics, string='Opened Ratio',
-             type='integer', multi='_get_statistics',
-         ),
-         'replied_ratio': fields.function(
-             _get_statistics, string='Replied Ratio',
-             type='integer', multi='_get_statistics',
-         ),
-         # dayly ratio
-         'opened_dayly': fields.function(
-             _get_daily_statistics, string='Opened',
-             type='char', multi='_get_daily_statistics',
-             oldname='opened_monthly',
-         ),
-         'replied_dayly': fields.function(
-             _get_daily_statistics, string='Replied',
-             type='char', multi='_get_daily_statistics',
-             oldname='replied_monthly',
-         ),
      }
  
      _defaults = {
      #------------------------------------------------------
  
      def copy_data(self, cr, uid, id, default=None, context=None):
--        if default is None:
--            default = {}
++        default = default or {}
          mailing = self.browse(cr, uid, id, context=context)
          default.update({
              'state': 'draft',
          return True
  
  
- class MailMailStats(osv.Model):
-     """ MailMailStats models the statistics collected about emails. Those statistics
-     are stored in a separated model and table to avoid bloating the mail_mail table
-     with statistics values. This also allows to delete emails send with mass mailing
-     without loosing the statistics about them. """
-     _name = 'mail.mail.statistics'
-     _description = 'Email Statistics'
-     _rec_name = 'message_id'
-     _order = 'message_id'
-     _columns = {
-         'mail_mail_id': fields.integer(
-             'Mail ID',
-             help='ID of the related mail_mail. This field is an integer field because'
-                  'the related mail_mail can be deleted separately from its statistics.'
-         ),
-         'message_id': fields.char('Message-ID'),
-         'model': fields.char('Document model'),
-         'res_id': fields.integer('Document ID'),
-         # campaign / wave data
-         'mass_mailing_id': fields.many2one(
-             'mail.mass_mailing', 'Mass Mailing',
-             ondelete='set null',
-         ),
-         'mass_mailing_campaign_id': fields.related(
-             'mass_mailing_id', 'mass_mailing_campaign_id',
-             type='many2one', ondelete='set null',
-             relation='mail.mass_mailing.campaign',
-             string='Mass Mailing Campaign',
-             store=True, readonly=True,
-         ),
-         'template_id': fields.related(
-             'mass_mailing_id', 'template_id',
-             type='many2one', ondelete='set null',
-             relation='email.template',
-             string='Email Template',
-             store=True, readonly=True,
-         ),
-         # Bounce and tracking
-         'scheduled': fields.datetime('Scheduled', help='Date when the email has been created'),
-         'sent': fields.datetime('Sent', help='Date when the email has been sent'),
-         'exception': fields.datetime('Exception', help='Date of technical error leading to the email not being sent'),
-         'opened': fields.datetime('Opened', help='Date when the email has been opened the first time'),
-         'replied': fields.datetime('Replied', help='Date when this email has been replied for the first time.'),
-         'bounced': fields.datetime('Bounced', help='Date when this email has bounced.'),
-     }
-     _defaults = {
-         'scheduled': fields.datetime.now,
-     }
-     def _get_ids(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, domain=None, context=None):
-         if not ids and mail_mail_ids:
-             base_domain = [('mail_mail_id', 'in', mail_mail_ids)]
-         elif not ids and mail_message_ids:
-             base_domain = [('message_id', 'in', mail_message_ids)]
-         else:
-             base_domain = [('id', 'in', ids or [])]
-         if domain:
-             base_domain = ['&'] + domain + base_domain
-         return self.search(cr, uid, base_domain, context=context)
-     def set_opened(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, context=None):
-         stat_ids = self._get_ids(cr, uid, ids, mail_mail_ids, mail_message_ids, [('opened', '=', False)], context)
-         self.write(cr, uid, stat_ids, {'opened': fields.datetime.now()}, context=context)
-         return stat_ids
-     def set_replied(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, context=None):
-         stat_ids = self._get_ids(cr, uid, ids, mail_mail_ids, mail_message_ids, [('replied', '=', False)], context)
-         self.write(cr, uid, stat_ids, {'replied': fields.datetime.now()}, context=context)
-         return stat_ids
-     def set_bounced(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, context=None):
-         stat_ids = self._get_ids(cr, uid, ids, mail_mail_ids, mail_message_ids, [('bounced', '=', False)], context)
-         self.write(cr, uid, stat_ids, {'bounced': fields.datetime.now()}, context=context)
-         return stat_ids
 -# Merge this on emails
 -class MailMailStats(osv.Model):
 -    """ MailMailStats models the statistics collected about emails. Those statistics
 -    are stored in a separated model and table to avoid bloating the mail_mail table
 -    with statistics values. This also allows to delete emails send with mass mailing
 -    without loosing the statistics about them. """
 -
 -    _name = 'mail.mail.statistics'
 -    _description = 'Email Statistics'
 -    _rec_name = 'message_id'
 -    _order = 'message_id'
 -
 -    _columns = {
 -        'mail_mail_id': fields.integer(
 -            'Mail ID',
 -            help='ID of the related mail_mail. This field is an integer field because'
 -                 'the related mail_mail can be deleted separately from its statistics.'
 -        ),
 -        'message_id': fields.char('Message-ID'),
 -        'model': fields.char('Document model'),
 -        'res_id': fields.integer('Document ID'),
 -        # campaign / wave data
 -        'mass_mailing_id': fields.many2one(
 -            'mail.mass_mailing', 'Mass Mailing',
 -            ondelete='set null',
 -        ),
 -        'mass_mailing_campaign_id': fields.related(
 -            'mass_mailing_id', 'mass_mailing_campaign_id',
 -            type='many2one', ondelete='set null',
 -            relation='mail.mass_mailing.campaign',
 -            string='Mass Mailing Campaign',
 -            store=True, readonly=True,
 -        ),
 -        'template_id': fields.related(
 -            'mass_mailing_id', 'template_id',
 -            type='many2one', ondelete='set null',
 -            relation='email.template',
 -            string='Email Template',
 -            store=True, readonly=True,
 -        ),
 -        # Bounce and tracking
 -        'scheduled': fields.datetime('Scheduled', help='Date when the email has been created'),
 -        'sent': fields.datetime('Sent', help='Date when the email has been sent'),
 -        'exception': fields.datetime('Exception', help='Date of technical error leading to the email not being sent'),
 -        'opened': fields.datetime('Opened', help='Date when the email has been opened the first time'),
 -        'replied': fields.datetime('Replied', help='Date when this email has been replied for the first time.'),
 -        'bounced': fields.datetime('Bounced', help='Date when this email has bounced.'),
 -    }
 -
 -    _defaults = {
 -        'scheduled': fields.datetime.now,
 -    }
 -
 -    def _get_ids(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, domain=None, context=None):
 -        if not ids and mail_mail_ids:
 -            base_domain = [('mail_mail_id', 'in', mail_mail_ids)]
 -        elif not ids and mail_message_ids:
 -            base_domain = [('message_id', 'in', mail_message_ids)]
 -        else:
 -            base_domain = [('id', 'in', ids or [])]
 -        if domain:
 -            base_domain = ['&'] + domain + base_domain
 -        return self.search(cr, uid, base_domain, context=context)
 -
 -    def set_opened(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, context=None):
 -        stat_ids = self._get_ids(cr, uid, ids, mail_mail_ids, mail_message_ids, [('opened', '=', False)], context)
 -        self.write(cr, uid, stat_ids, {'opened': fields.datetime.now()}, context=context)
 -        return stat_ids
 -
 -    def set_replied(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, context=None):
 -        stat_ids = self._get_ids(cr, uid, ids, mail_mail_ids, mail_message_ids, [('replied', '=', False)], context)
 -        self.write(cr, uid, stat_ids, {'replied': fields.datetime.now()}, context=context)
 -        return stat_ids
 -
 -    def set_bounced(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, context=None):
 -        stat_ids = self._get_ids(cr, uid, ids, mail_mail_ids, mail_message_ids, [('bounced', '=', False)], context)
 -        self.write(cr, uid, stat_ids, {'bounced': fields.datetime.now()}, context=context)
 -        return stat_ids
          <menuitem name="Configuration" id="marketing_configuration"
              parent="base.marketing_menu" sequence="99"/>
  
--        <!--  MASS MAILING CONTACT !-->
++        <!--  MASS MAILING CONTACT -->
          <record model="ir.ui.view" id="view_mail_mass_mailing_contact_search">
              <field name="name">mail.mass_mailing.contact.search</field>
              <field name="model">mail.mass_mailing.contact</field>
              <field name="arch" type="xml">
--               <search string="Mass Mailings">
++               <search string="Mailing Lists Subscribers">
                      <field name="name"/>
                      <field name="email"/>
                      <field name="list_id"/>
                      <separator/>
--                    <filter string="Available for Mass Mailing" name="not_opt_out" domain="[('opt_out', '=', False)]"
++                    <filter string="Exclude Opt Out" name="not_opt_out" domain="[('opt_out', '=', False)]"
                          help="Contact is not opt-out"/>
                      <group expand="0" string="Group By...">
                          <filter string="Mailing Lists" name="group_list_id"
@@@ -37,7 -37,7 +37,7 @@@
              <field name="model">mail.mass_mailing.contact</field>
              <field name="priority">10</field>
              <field name="arch" type="xml">
--                <tree string="Mass Mailings">
++                <tree string="Mailing Lists Subscribers" editable="top">
                      <field name="name"/>
                      <field name="email"/>
                      <field name="list_id"/>
              </field>
          </record>
  
--        <record model="ir.ui.view" id="view_mail_mass_mailing_contact_form">
--            <field name="name">mail.mass_mailing.contact.form</field>
--            <field name="model">mail.mass_mailing.contact</field>
--            <field name="arch" type="xml">
--                <form string="Mass Mailing" version="7.0">
--                    <sheet>
--                        <group>
--                            <field name="name"/>
--                            <field name="email"/>
--                            <field name="list_id"/>
--                            <field name="opt_out"/>
--                        </group>
--                    </sheet>
--                </form>
--            </field>
--        </record>
--
          <record id="action_view_mass_mailing_contacts" model="ir.actions.act_window">
--            <field name="name">Mass Mailing Contacts</field>
++            <field name="name">Mailing List Subscribers</field>
              <field name="res_model">mail.mass_mailing.contact</field>
              <field name="view_type">form</field>
--            <field name="view_mode">tree,form</field>
++            <field name="view_mode">tree</field>
              <field name="context">{'search_default_not_opt_out': 1}</field>
          </record>
  
--        <menuitem name="Contacts" id="menu_email_mass_mailing_contacts" groups="base.group_no_one"
++        <menuitem name="Contacts" id="menu_email_mass_mailing_contacts"
              parent="mass_mailing_list" sequence="50"
              action="action_view_mass_mailing_contacts"/>
  
--        <!-- Create a Mailing List from Contacts -->
--        <act_window name="Create Mailing List"
--            res_model="mail.mass_mailing.list.confirm"
--            src_model="mail.mass_mailing.contact"
--            view_mode="form"
--            multi="True"
--            target="new"
--            key2="client_action_multi"
--            id="action_contact_to_mailing_list"
--            context="{
--'default_mass_mailing_id': context.get('default_mass_mailing_id'),
--'default_model': context.get('default_model', 'mail.mass_mailing.contact'),
--'default_name': context.get('default_name', False)}"/>
--
--        <!--  MASS MAILING LIST !-->
++        <!--  MASS MAILING LIST -->
          <record model="ir.ui.view" id="view_mail_mass_mailing_list_search">
              <field name="name">mail.mass_mailing.list.search</field>
              <field name="model">mail.mass_mailing.list</field>
              <field name="arch" type="xml">
--               <search string="Mass Mailings">
--                    <field name="name"/>
--                    <separator/>
--                </search>
++               <search string="Mailing Lists">
++                   <field name="name"/>
++               </search>
              </field>
          </record>
  
              <field name="model">mail.mass_mailing.list</field>
              <field name="priority">10</field>
              <field name="arch" type="xml">
--                <tree string="Contact Lists">
++                <tree string="Mailing Lists">
                      <field name="name"/>
--                    <field name="model"/>
                      <field name="contact_nbr"/>
                  </tree>
              </field>
          </record>
  
++        <record id="mass_mailing_list_open_contacts" model="ir.actions.act_window">
++            <field name="name">Recipients</field>
++            <field name="res_model">mail.mass_mailing.contact</field>
++            <field name="view_type">form</field>
++            <field name="view_mode">tree</field>
++            <field name="context">{'search_default_list_id': active_id}</field>
++            <field name="help" type="html">
++              <p class="oe_view_nocontent_create">
++                Click to create a recipient.
++              </p>
++            </field>
++        </record>
++
          <record model="ir.ui.view" id="view_mail_mass_mailing_list_form">
              <field name="name">mail.mass_mailing.list.form</field>
              <field name="model">mail.mass_mailing.list</field>
              <field name="arch" type="xml">
                  <form string="Contact List" version="7.0">
--                    <header>
--                        <button name="action_add_to_mailing" type="object"
--                            class="oe_highlight" string="Continue to Mailing"
--                            invisible="not context.get('default_mass_mailing_id')"/>
--                    </header>
                      <sheet>
++                        <!-- TODO: stat_get button and relate link -->
++                        <div class="oe_button_box" nname="buttons">
++                            <button name="%(mass_mailing.mass_mailing_list_open_contacts)d" type="action"
++                                string="Recipients"/>
++                        </div>
                          <group>
--                            <field name="name" string="Mailing List Name"/>
--                            <label for="contact_nbr"/>
--                            <div>
--                                <field name="contact_nbr" nolabel="1" class="oe_inline"/>
--                                <field name="model" class="oe_inline"
--                                    on_change="on_change_model(model, context)" nolabel="1"/>
--                                <button string="See Recipients" class="oe_inline oe_link" style="margin-left: 8px;"
--                                    name="action_see_records" type="object"/>
--                            </div>
--                            <field name="filter_id" groups="base.group_no_one"
--                                on_change="on_change_filter_id(filter_id, context)"/>
--                            <field name="domain" groups="base.group_no_one"
--                                on_change="on_change_domain(domain, model, context)"/>
++                            <field name="name"/>
++                            <field for="contact_nbr"/>
                          </group>
                      </sheet>
                  </form>
              <field name="res_model">mail.mass_mailing.list</field>
              <field name="view_type">form</field>
              <field name="view_mode">tree,form</field>
--<field name="help" type="html">
--<p class="oe_view_nocontent_create">
--    Click here to create a new mailing list.
--</p><p>
--    Mailing lists allows you to to manage customers and contacts easily and to send to mailings in a single click.
--</p></field>
++            <field name="help" type="html">
++                <p class="oe_view_nocontent_create">
++                    Click here to create a new mailing list.
++                </p><p>
++                    Mailing lists allows you to to manage customers and
++                    contacts easily and to send to mailings in a single click.
++                </p>
++            </field>
          </record>
  
--        <menuitem name="Contact Lists" id="menu_email_mass_mailing_lists"
++        <menuitem name="Mailing Lists" id="menu_email_mass_mailing_lists"
              parent="mass_mailing_list" sequence="40"
              action="action_view_mass_mailing_lists"/>
  
                 <search string="Mass Mailings">
                      <field name="name" string="Mailings"/>
                      <field name="mass_mailing_campaign_id"/>
--                    <field name="template_id"/>
                      <group expand="0" string="Group By...">
                          <filter string="State" name="group_state"
                              context="{'group_by': 'state'}"/>
                          <filter string="Campaign" name="group_mass_mailing_campaign_id"
                              groups="mass_mailing.group_mass_mailing_campaign"
                              context="{'group_by': 'mass_mailing_campaign_id'}"/>
--                        <filter string="Template" name="group_template_id"
--                            context="{'group_by': 'template_id'}"/>
                      </group>
                  </search>
              </field>
                      <field name="replied"/>
                      <field name="mass_mailing_campaign_id"
                          groups="mass_mailing.group_mass_mailing_campaign"/>
--                    <field name="template_id" invisible="1"/>
                  </tree>
              </field>
          </record>
              <field name="arch" type="xml">
                  <form string="Mass Mailing" version="7.0">
                      <header>
++                        <field name="state" widget="statusbar" clickable="True"/>
                          <button name="action_test_mailing" type="object"
                              class="oe_highlight" string="Test Mailing"/>
                          <button name="send_mail" type="object"
                              class="oe_highlight" string="Send to All"/>
--                        <field name="state" widget="statusbar" clickable="True"/>
                      </header>
                      <sheet>
--                        <div colspan="2" class="oe_form_box_info oe_text_center"
++                        <div class="oe_form_box_info oe_text_center"
                                  attrs="{'invisible': [('scheduled', '=', 0)]}">
                              <p>
                                  <strong><field name="scheduled" class="oe_inline"/>emails are in queue
                                  and will be sent soon.</strong>
                              </p>
                          </div>
++
                          <group>
                              <group>
                                  <field name="email_from"/>
@@@ -2,4 -2,4 +2,3 @@@
  
  import test_mailing
  import mail_compose_message
--import mailing_list_confirm
diff --cc addons/mass_mailing/wizard/mailing_list_confirm.py
index de9fa10,de9fa10..0000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,57 -1,57 +1,0 @@@
--# -*- coding: utf-8 -*-
--
--from openerp.osv import osv, fields
--from openerp.tools.translate import _
--
--
--class MailingListConfirm(osv.TransientModel):
--    """A wizard that acts as a confirmation when creating a new mailing list coming
--    from a list view. This allows to have a lightweight flow to create mailing
--    lists without having to go through multiple screens."""
--
--    _inherit = 'mail.mass_mailing.list'
--    _name = 'mail.mass_mailing.list.confirm'
--
--    _columns = {
--        'mass_mailing_id': fields.many2one('mail.mass_mailing', 'Mailing'),
--    }
--
--    def create(self, cr, uid, values, context=None):
--        if context is None:
--            context = {}
--        context.update(no_contact_to_list=True)
--        return super(MailingListConfirm, self).create(cr, uid, values, context=context)
--
--    def action_confirm(self, cr, uid, ids, context=None):
--        wizard = self.browse(cr, uid, ids[0], context=context)
--        mailing_list_id = self.pool['mail.mass_mailing.list'].create(
--            cr, uid, {'name': wizard.name, 'model': wizard.model}, context=context)
--        res = self.pool['mail.mass_mailing.list'].action_add_to_mailing(cr, uid, [mailing_list_id], context=context)
--        if not res:
--            return {
--                'type': 'ir.actions.act_window',
--                'view_type': 'form',
--                'view_mode': 'form',
--                'res_model': 'mail.mass_mailing.list',
--                'res_id': mailing_list_id,
--                'context': context,
--            }
--        return res
--
--    def action_new_list(self, cr, uid, ids, context=None):
--        wizard = self.browse(cr, uid, ids[0], context=context)
--        action_id = self.pool['mail.mass_mailing']._get_model_to_list_action_id(cr, uid, wizard.model, context=context)
--        if wizard.model == 'mail.mass_mailing.contact':
--            domain = [('list_id', '=', False)]
--        else:
--            domain = []
--        ctx = dict(context, search_default_not_opt_out=True, view_manager_highlight=[action_id], default_name=wizard.name, default_model=wizard.model)
--        return {
--            'name': _('Choose Recipients'),
--            'type': 'ir.actions.act_window',
--            'view_type': 'form',
--            'view_mode': 'tree,form',
--            'res_model': wizard.model,
--            'context': ctx,
--            'domain': domain,
--        }
diff --cc addons/mass_mailing/wizard/mailing_list_confirm.xml
index 1713fe0,1713fe0..0000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,67 -1,67 +1,0 @@@
--<?xml version="1.0"?>
--<openerp>
--    <data>
--
--        <record model="ir.ui.view" id="view_mail_mass_mailing_list_confirm_form">
--            <field name="name">mail.mass_mailing.list.confirm.form</field>
--            <field name="model">mail.mass_mailing.list.confirm</field>
--            <field name="arch" type="xml">
--                <form string="Confirm Mailing List" version="7.0">
--                    <group>
--                        <field name="model" invisible="1"/>
--                        <field name="domain" invisible="1"
--                            on_change="on_change_domain(domain, model, context)"/>
--                        <div attrs="{'invisible': [('mass_mailing_id', '=', False)]}" colspan="2">
--                            Adding <field name="contact_nbr" class="oe_inline"/> contacts
--                            to the mailing  <field name="mass_mailing_id" class="oe_inline" readonly="1"/>.
--                        </div>
--                        <field name="name" attrs="{'invisible': [('mass_mailing_id', '!=', False)]}"/>
--                    </group>
--                    <footer>
--                        <button string="Confirm" name="action_confirm" type="object" class="oe_highlight"/>
--                        or
--                        <button string="Cancel" class="oe_link" special="cancel" />
--                    </footer>
--                </form>
--            </field>
--        </record>
--
--        <record model="ir.ui.view" id="view_mail_mass_mailing_list_create_form">
--            <field name="name">mail.mass_mailing.list.confirm.form</field>
--            <field name="model">mail.mass_mailing.list.confirm</field>
--            <field name="priority">32</field>
--            <field name="arch" type="xml">
--                <form string="Create a Mailing List" version="7.0">
--                    <header>
--                        <button string='Create a New List' class="oe_highlight"
--                            type='object' name='action_new_list'/>
--                    </header>
--                    <sheet>
--                        <group>
--                            <field name="name"/>
--                            <field name="model" widget="radio"/>
--                        </group>
--                    </sheet>
--                </form>
--            </field>
--        </record>
--
--        <record id="action_mail_mass_mailing_list_confirm" model="ir.actions.act_window">
--            <field name="name">Create a Mailing List</field>
--            <field name="res_model">mail.mass_mailing.list.confirm</field>
--            <field name="view_type">form</field>
--            <field name="view_mode">form</field>
--            <field name="target">new</field>
--        </record>
--
--        <record id="action_mail_mass_mailing_create" model="ir.actions.act_window">
--            <field name="name">Create a Mailing List</field>
--            <field name="res_model">mail.mass_mailing.list.confirm</field>
--            <field name="view_type">form</field>
--            <field name="view_mode">form</field>
--            <field name="view_id" ref="view_mail_mass_mailing_list_create_form"/>
--            <field name="target">new</field>
--        </record>
--
--    </data>
--</openerp>