[IMP] [REF] mass_mailing: first draft for the saas-4 refactoring.
Improved mass mailing form view, that is used as a central point to create new mailings. Added concept of contact list (based on partner, or leads (to add)), as well as contact (a list of name / email to import). Mailings are done un contact list to simplify the way it works. Added a kanban view of templates, with a flag to filter only mass mailing templates (to avoid havign to deal with acknoledgments). Using campaigns is now an option (a group), mailings can be done without having to deal with campaigns. Mailings and campaigns now have a status, used to display their kanban view. bzr revid: tde@openerp.com-20140314165113-g4gvvifrhr2nfu15
This commit is contained in:
parent
676189cbf7
commit
08ab922468
|
@ -63,7 +63,7 @@ campaigns on any OpenERP document.
|
|||
'wizard/mail_compose_message_view.xml',
|
||||
'security/ir.model.access.csv'
|
||||
],
|
||||
'demo': ['res_partner_demo.yml'],
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': True,
|
||||
'images': ['images/1_email_account.jpeg','images/2_email_template.jpeg','images/3_emails.jpeg'],
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
-
|
||||
Set opt-out to True on all demo partners
|
||||
-
|
||||
!python {model: res.partner}: |
|
||||
partner_ids = self.search(cr, uid, [])
|
||||
# assume partners with an external ID come from demo data
|
||||
ext_ids = self._get_external_ids(cr, uid, partner_ids)
|
||||
ids_to_update = [k for (k,v) in ext_ids.iteritems() if v]
|
||||
self.write(cr, uid, ids_to_update, {'opt_out': True})
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2013-today OpenERP SA (<http://www.openerp.com>)
|
||||
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -22,5 +22,7 @@
|
|||
import mass_mailing
|
||||
import mail_mail
|
||||
import mail_thread
|
||||
import email_template
|
||||
import res_config
|
||||
import wizard
|
||||
import controllers
|
||||
import controllers
|
|
@ -33,14 +33,18 @@ professional emails and reuse templates in a few clicks.
|
|||
'depends': [
|
||||
'mail',
|
||||
'email_template',
|
||||
'marketing',
|
||||
'web_kanban_gauge',
|
||||
'web_kanban_sparkline',
|
||||
],
|
||||
'data': [
|
||||
'mail_data.xml',
|
||||
'mass_mailing_data.xml',
|
||||
'wizard/mail_compose_message_view.xml',
|
||||
'wizard/mail_mass_mailing_create_segment.xml',
|
||||
'mass_mailing_view.xml',
|
||||
'res_config_view.xml',
|
||||
'email_template.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'js': [
|
||||
|
@ -48,7 +52,8 @@ professional emails and reuse templates in a few clicks.
|
|||
],
|
||||
'qweb': [],
|
||||
'css': [
|
||||
'static/src/css/mass_mailing.css'
|
||||
'static/src/css/mass_mailing.css',
|
||||
'static/src/css/email_template.css'
|
||||
],
|
||||
'demo': [
|
||||
'mass_mailing_demo.xml',
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
|
||||
class EmailTemplate(osv.Model):
|
||||
"""Add the mass mailing campaign data to mail"""
|
||||
_name = 'email.template'
|
||||
_inherit = ['email.template']
|
||||
|
||||
_columns = {
|
||||
'use_in_mass_mailing': fields.boolean('Available for mass mailing campaigns'),
|
||||
}
|
||||
|
||||
def action_new_mailing(self, cr, uid, ids, context=None):
|
||||
ctx = dict(context)
|
||||
ctx.update({
|
||||
'default_template_id': ids[0],
|
||||
})
|
||||
return {
|
||||
'name': _('Create a Mass Mailing'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'mail.mass_mailing',
|
||||
'views': [(False, 'form')],
|
||||
'view_id': False,
|
||||
# 'target': 'new',
|
||||
'context': ctx,
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Email Templates -->
|
||||
<record id="view_marketing_settings_mass_mailing" model="ir.ui.view">
|
||||
<field name="name">email.template.form.mass.mailing</field>
|
||||
<field name="model">email.template</field>
|
||||
<field name="inherit_id" ref="email_template.email_template_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='model_id']" position="after">
|
||||
<br /><label for="use_in_mass_mailing"/><field name="use_in_mass_mailing"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_email_template_search_mass_mailing" model="ir.ui.view">
|
||||
<field name="name">email.template.search.mass.mailing</field>
|
||||
<field name="model">email.template</field>
|
||||
<field name="inherit_id" ref="email_template.view_email_template_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='model_id']" position="after">
|
||||
<separator/>
|
||||
<filter string="Available for Mass Mailing" name="use_in_mass_mailing" domain="[('use_in_mass_mailing', '=', 1)]"
|
||||
help="Available for use in mass mailing campaigns"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_email_template_kanban">
|
||||
<field name="name">email.template.kanban</field>
|
||||
<field name="model">email.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<field name="body_html"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_card oe_kanban_global_click oe_kanban_email_template">
|
||||
<div class="oe_dropdown_toggle oe_dropdown_kanban">
|
||||
<span class="oe_e">i</span>
|
||||
<ul class="oe_dropdown_menu">
|
||||
<t>
|
||||
<li><a name="action_new_mailing" type="object">New Mailing</a></li>
|
||||
</t>
|
||||
<t t-if="widget.view.is_action_enabled('edit')">
|
||||
<li><a type="edit">Edit</a></li>
|
||||
</t>
|
||||
<t t-if="widget.view.is_action_enabled('delete')">
|
||||
<li><a type="delete">Delete</a></li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="oe_kanban_content">
|
||||
<h3>
|
||||
<field name="name"/>
|
||||
</h3>
|
||||
<div class="html_preview">
|
||||
<t t-raw="record.body_html.raw_value"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_clear"></div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_email_template">
|
||||
<field name="name">Templates</field>
|
||||
<field name="res_model">email.template</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context">{'search_default_use_in_mass_mailing': 1}</field>
|
||||
</record>
|
||||
|
||||
<!-- Add Templates in Marketing / Mass mailing menu -->
|
||||
<menuitem name="Mail Templates" id="menu_email_template"
|
||||
parent="mass_mailing_campaign" sequence="3"
|
||||
action="action_email_template"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -23,10 +23,151 @@ from datetime import datetime
|
|||
from dateutil import relativedelta
|
||||
|
||||
from openerp import tools
|
||||
from openerp.tools.safe_eval import safe_eval as eval
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
|
||||
class MassMailingCategory(osv.Model):
|
||||
"""Model of categories of mass mailing, i.e. marketing, newsletter, ... """
|
||||
_name = 'mail.mass_mailing.category'
|
||||
_description = 'Mass Mailing Category'
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True),
|
||||
}
|
||||
|
||||
|
||||
class MassMailingContact(osv.Model):
|
||||
"""Model of a contact. This model is different from the partner model
|
||||
because it holds only some basic information: name, email. The purpose is to
|
||||
be able to deal with large contact list to email without bloating the partner
|
||||
database. """
|
||||
_name = 'mail.mass_mailing.contact'
|
||||
_description = 'Mass Mailing Contact'
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True),
|
||||
'email': fields.char('Email', required=True),
|
||||
'list_id': fields.many2one(
|
||||
'mail.mass_mailing.list', string='Mailing List',
|
||||
required=True, ondelete='cascade',
|
||||
),
|
||||
'opt_out': fields.boolean('Opt Out', help='The contact has chosen not to receive news anymore from this mailing 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 and 'active_domain' in context:
|
||||
res['domain'] = '%s' % context['active_domain']
|
||||
res['model'] = context.get('active_model', 'res.partner')
|
||||
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):
|
||||
if contact_list.model == 'mail.mass_mailing.contact':
|
||||
results[contact_list.id] = len(contact_list.contact_ids)
|
||||
else:
|
||||
domain = self.compute_domain(cr, uid, [contact_list.id], context=context)
|
||||
results[contact_list.id] = self.pool[contact_list.model].search(cr, uid, domain, count=True, context=context)
|
||||
return results
|
||||
|
||||
def _get_model_list(self, cr, uid, context=None):
|
||||
return [
|
||||
('res.partner', 'Customers'),
|
||||
('mail.mass_mailing.contact', 'Mailing Contacts')
|
||||
]
|
||||
|
||||
# indirections for inheritance
|
||||
_model_list = lambda self, *args, **kwargs: self._get_model_list(*args, **kwargs)
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True),
|
||||
'contact_nbr': fields.function(
|
||||
_get_contact_nbr, type='integer',
|
||||
string='Contact Number',
|
||||
),
|
||||
# contact-based list
|
||||
'contact_ids': fields.one2many(
|
||||
'mail.mass_mailing.contact', 'list_id', string='Contacts',
|
||||
domain=[('opt_out', '=', False)],
|
||||
),
|
||||
# filter-based list
|
||||
'model': fields.selection(
|
||||
_model_list, type='char', required=True,
|
||||
string='Applies To'
|
||||
),
|
||||
# 'model_id': fields.many2one(
|
||||
# 'ir.model', string='Related Model',
|
||||
# domain="[('model', '=', model')]",
|
||||
# ),
|
||||
'filter_id': fields.many2one(
|
||||
'ir.filters', string='Custom Filter',
|
||||
# domain="[('model_id', '=', model_id)]",
|
||||
),
|
||||
'domain': fields.text('Domain'),
|
||||
}
|
||||
|
||||
def on_change_model(self, cr, uid, ids, model, context=None):
|
||||
values = {}
|
||||
if model == 'mail.mass_mailing.contact':
|
||||
values.update(domain=False, filter_id=False)
|
||||
else:
|
||||
values.update(filter_id=False)
|
||||
return {'value': values}
|
||||
|
||||
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
|
||||
else:
|
||||
values['domain'] = False
|
||||
return {'value': values}
|
||||
|
||||
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 compute_domain(self, cr, uid, ids, context=None):
|
||||
domains = []
|
||||
for contact_list in self.browse(cr, uid, ids, context=context):
|
||||
domain = eval(contact_list.domain)
|
||||
if domain:
|
||||
domain = ['&', ('opt_out', '=', False)] + domain
|
||||
else:
|
||||
domain = [('opt_out', '=', False)]
|
||||
if domain is not False:
|
||||
domains.append(domain)
|
||||
if domains:
|
||||
final_domain = ['|'] * (len(domains) - 1) + [leaf for dom in domains for leaf in dom]
|
||||
else:
|
||||
final_domain = domains
|
||||
return final_domain
|
||||
|
||||
|
||||
class MassMailingCampaign(osv.Model):
|
||||
"""Model of mass mailing campaigns.
|
||||
"""
|
||||
|
@ -63,6 +204,12 @@ class MassMailingCampaign(osv.Model):
|
|||
results[campaign.id] = mass_mailing_results
|
||||
return results
|
||||
|
||||
def _get_state_list(self, cr, uid, context=None):
|
||||
return [('draft', 'Schedule'), ('design', 'Design'), ('done', 'Sent')]
|
||||
|
||||
# indirections for inheritance
|
||||
_state = lambda self, *args, **kwargs: self._get_state_list(*args, **kwargs)
|
||||
|
||||
_columns = {
|
||||
'name': fields.char(
|
||||
'Campaign Name', required=True,
|
||||
|
@ -71,6 +218,12 @@ class MassMailingCampaign(osv.Model):
|
|||
'res.users', 'Responsible',
|
||||
required=True,
|
||||
),
|
||||
'state': fields.selection(
|
||||
_state, string='Status', required=True,
|
||||
),
|
||||
'category_id': fields.many2one(
|
||||
'mail.mass_mailing.category', 'Category',
|
||||
help='Category'),
|
||||
'mass_mailing_ids': fields.one2many(
|
||||
'mail.mass_mailing', 'mass_mailing_campaign_id',
|
||||
'Mass Mailings',
|
||||
|
@ -117,8 +270,42 @@ class MassMailingCampaign(osv.Model):
|
|||
|
||||
_defaults = {
|
||||
'user_id': lambda self, cr, uid, ctx=None: uid,
|
||||
'state': 'draft',
|
||||
}
|
||||
|
||||
#------------------------------------------------------
|
||||
# Technical stuff
|
||||
#------------------------------------------------------
|
||||
|
||||
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
|
||||
""" Override read_group to always display all states. """
|
||||
if groupby and groupby[0] == "state":
|
||||
# Default result structure
|
||||
states = self._get_state_list(cr, uid, context=context)
|
||||
read_group_all_states = [{
|
||||
'__context': {'group_by': groupby[1:]},
|
||||
'__domain': domain + [('state', '=', state_value)],
|
||||
'state': state_value,
|
||||
'state_count': 0,
|
||||
} for state_value, state_name in states]
|
||||
# Get standard results
|
||||
read_group_res = super(MassMailingCampaign, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby)
|
||||
# Update standard results with default results
|
||||
result = []
|
||||
for state_value, state_name in states:
|
||||
res = filter(lambda x: x['state'] == state_value, read_group_res)
|
||||
if not res:
|
||||
res = filter(lambda x: x['state'] == state_value, read_group_all_states)
|
||||
res[0]['state'] = [state_value, state_name]
|
||||
result.append(res[0])
|
||||
return result
|
||||
else:
|
||||
return super(MassMailingCampaign, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby)
|
||||
|
||||
#------------------------------------------------------
|
||||
# Actions
|
||||
#------------------------------------------------------
|
||||
|
||||
def launch_mass_mailing_create_wizard(self, cr, uid, ids, context=None):
|
||||
ctx = dict(context)
|
||||
ctx.update({
|
||||
|
@ -142,7 +329,7 @@ class MassMailing(osv.Model):
|
|||
A mass mailing is an occurence of sending emails. """
|
||||
|
||||
_name = 'mail.mass_mailing'
|
||||
_description = 'Wave of sending emails'
|
||||
_description = 'Mass Mailing'
|
||||
# number of periods for tracking mail_mail statistics
|
||||
_period_number = 6
|
||||
_order = 'date DESC'
|
||||
|
@ -189,9 +376,9 @@ class MassMailing(osv.Model):
|
|||
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_monthly'] = self.__get_bar_values(cr, uid, id, obj, domain, ['opened'], 'opened_count', 'opened:day', context=context)
|
||||
res[id]['opened_dayly'] = 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_monthly'] = self.__get_bar_values(cr, uid, id, obj, domain, ['replied'], 'replied_count', 'replied:day', context=context)
|
||||
res[id]['replied_dayly'] = 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):
|
||||
|
@ -207,22 +394,54 @@ class MassMailing(osv.Model):
|
|||
}
|
||||
return results
|
||||
|
||||
def _get_mailing_type(self, cr, uid, context=None):
|
||||
return [
|
||||
('res.partner', 'Customers'),
|
||||
('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_type = lambda self, *args, **kwargs: self._get_mailing_type(*args, **kwargs)
|
||||
_state = lambda self, *args, **kwargs: self._get_state_list(*args, **kwargs)
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', required=True),
|
||||
'mass_mailing_campaign_id': fields.many2one(
|
||||
'mail.mass_mailing.campaign', 'Mass Mailing Campaign',
|
||||
ondelete='cascade', required=True,
|
||||
'name': fields.char('Subject', required=True),
|
||||
'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)],
|
||||
ondelete='set null',
|
||||
),
|
||||
'body_html': fields.related(
|
||||
'template_id', 'body_html', type='html',
|
||||
string='Body', readonly='True',
|
||||
help='Technical field: used only to display a view of the template in the form view',
|
||||
),
|
||||
'mass_mailing_campaign_id': fields.many2one(
|
||||
'mail.mass_mailing.campaign', 'Mass Mailing Campaign',
|
||||
ondelete='set null',
|
||||
),
|
||||
'domain': fields.char('Domain'),
|
||||
'date': fields.datetime('Date'),
|
||||
'color': fields.related(
|
||||
'mass_mailing_campaign_id', 'color',
|
||||
type='integer', string='Color Index',
|
||||
),
|
||||
# mailing options
|
||||
'email_from': fields.char('From'),
|
||||
'email_to': fields.char('Send to Emails'),
|
||||
'reply_to': fields.char('Reply To'),
|
||||
'mailing_type': fields.selection(_mailing_type, string='Type', required=True),
|
||||
'contact_list_ids': fields.many2many(
|
||||
'mail.mass_mailing.list', 'mail_mass_mailing_list_rel',
|
||||
string='Mailing Lists',
|
||||
domain="[('model', '=', mailing_type)]",
|
||||
),
|
||||
'contact_nbr': fields.integer('Contact Number'),
|
||||
# statistics data
|
||||
'statistics_ids': fields.one2many(
|
||||
'mail.mail.statistics', 'mass_mailing_id',
|
||||
|
@ -254,22 +473,159 @@ class MassMailing(osv.Model):
|
|||
type='integer', multi='_get_statistics'
|
||||
),
|
||||
# monthly ratio
|
||||
'opened_monthly': fields.function(
|
||||
'opened_dayly': fields.function(
|
||||
_get_daily_statistics,
|
||||
string='Opened',
|
||||
type='char', multi='_get_daily_statistics',
|
||||
oldname='opened_monthly',
|
||||
),
|
||||
'replied_monthly': fields.function(
|
||||
'replied_dayly': fields.function(
|
||||
_get_daily_statistics,
|
||||
string='Replied',
|
||||
type='char', multi='_get_daily_statistics',
|
||||
oldname='replied_monthly',
|
||||
),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'state': 'draft',
|
||||
'date': fields.datetime.now,
|
||||
'email_from': lambda self, cr, uid, ctx=None: self.pool['mail.message']._get_default_from(cr, uid, context=ctx),
|
||||
'mailing_type': 'res.partner',
|
||||
}
|
||||
|
||||
#------------------------------------------------------
|
||||
# Technical stuff
|
||||
#------------------------------------------------------
|
||||
|
||||
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
|
||||
""" Override read_group to always display all states. """
|
||||
if groupby and groupby[0] == "state":
|
||||
# Default result structure
|
||||
states = self._get_state_list(cr, uid, context=context)
|
||||
read_group_all_states = [{
|
||||
'__context': {'group_by': groupby[1:]},
|
||||
'__domain': domain + [('state', '=', state_value)],
|
||||
'state': state_value,
|
||||
'state_count': 0,
|
||||
} for state_value, state_name in states]
|
||||
# Get standard results
|
||||
read_group_res = super(MassMailing, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby)
|
||||
# Update standard results with default results
|
||||
result = []
|
||||
for state_value, state_name in states:
|
||||
res = filter(lambda x: x['state'] == state_value, read_group_res)
|
||||
if not res:
|
||||
res = filter(lambda x: x['state'] == state_value, read_group_all_states)
|
||||
res[0]['state'] = [state_value, state_name]
|
||||
result.append(res[0])
|
||||
return result
|
||||
else:
|
||||
return super(MassMailing, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby)
|
||||
|
||||
#------------------------------------------------------
|
||||
# Views & Actions
|
||||
#------------------------------------------------------
|
||||
|
||||
def on_change_mailing_type(self, cr, uid, ids, mailing_type, context=None):
|
||||
return {'value': {'contact_list_ids': []}}
|
||||
|
||||
def on_change_template_id(self, cr, uid, ids, template_id, context=None):
|
||||
values = {}
|
||||
if template_id:
|
||||
template = self.pool['email.template'].browse(cr, uid, template_id, context=context)
|
||||
if template.email_from:
|
||||
values['email_from'] = template.email_from
|
||||
if template.reply_to:
|
||||
values['reply_to'] = template.reply_to
|
||||
values['body_html'] = template.body_html
|
||||
else:
|
||||
values['email_from'] = self.pool['mail.message']._get_default_from(cr, uid, context=context)
|
||||
values['reply_to'] = False
|
||||
values['body_html'] = False
|
||||
return {'value': values}
|
||||
|
||||
def send_mail(self, cr, uid, ids, context=None):
|
||||
Mail = self.pool['mail.mail']
|
||||
for mailing in self.browse(cr, uid, ids, context=context):
|
||||
contact_list_ids = [contact_list.id for contact_list in mailing.contact_list_ids]
|
||||
|
||||
# contact-based list: aggregate all contacts
|
||||
if mailing.mailing_type == 'mail.mass_mailing.list':
|
||||
res_ids = [contact.id for contact in contact_list.contact_ids for contact_list in mailing.contact_list_ids]
|
||||
elif mailing.mailing_type == 'res.partner':
|
||||
domain = self.pool['mail.mass_mailing.list'].compute_domain(cr, uid, contact_list_ids, context=context)
|
||||
print domain
|
||||
res_ids = self.pool[contact_list.model].search(cr, uid, domain, context=context)
|
||||
|
||||
all_mail_values = self.pool['mail.compose.message'].generate_email_for_composer_batch(
|
||||
cr, uid, mailing.template_id.id, res_ids,
|
||||
context=context,
|
||||
fields=['body_html', 'attachment_ids', 'mail_server_id']
|
||||
)
|
||||
for res_id, mail_values in all_mail_values.iteritems():
|
||||
mail_values.update({
|
||||
'email_from': mailing.email_from,
|
||||
'reply_to': mailing.reply_to,
|
||||
'subject': mailing.name,
|
||||
'body_html': mail_values.get('body'),
|
||||
'auto_delete': True,
|
||||
'statistics_ids': [(0, 0, {
|
||||
'model': mailing.mailing_type,
|
||||
'res_id': res_id,
|
||||
'mass_mailing_id': mailing.id,
|
||||
})]
|
||||
})
|
||||
m2m_attachment_ids = self.pool['mail.thread']._message_preprocess_attachments(
|
||||
cr, uid, mail_values.pop('attachments', []),
|
||||
mail_values.pop('attachment_ids', []),
|
||||
'mail.message', 0,
|
||||
context=context)
|
||||
mail_values['attachment_ids'] = m2m_attachment_ids
|
||||
if mailing.mailing_type == 'mail.mass_mailing.list':
|
||||
contact = self.pool['mail.mass_mailing.contact'].browse(cr, uid, res_id, context=context)
|
||||
mail_values['email_to'] = '"%s" <%s>' % (contact.name, contact.email)
|
||||
elif mailing.mailing_type == 'res.partner':
|
||||
mail_values['recipient_ids'] = [(4, res_id)]
|
||||
Mail.create(cr, uid, mail_values, context=context)
|
||||
# todo: handle email_to
|
||||
return True
|
||||
|
||||
def send_mail_to_myself(self, cr, uid, ids, context=None):
|
||||
Mail = self.pool['mail.mail']
|
||||
for mailing in self.browse(cr, uid, ids, context=context):
|
||||
mail_values = {
|
||||
'email_from': mailing.email_from,
|
||||
'reply_to': mailing.reply_to,
|
||||
'email_to': self.pool['res.users'].browse(cr, uid, uid, context=context).email,
|
||||
'subject': mailing.name,
|
||||
'body_html': mailing.template_id.body_html,
|
||||
'auto_delete': True,
|
||||
}
|
||||
mail_id = Mail.create(cr, uid, mail_values, context=context)
|
||||
Mail.send(cr, uid, [mail_id], context=context)
|
||||
return True
|
||||
|
||||
def select_customers(self, cr, uid, ids, context=None):
|
||||
sid = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'base.view_res_partner_filter')
|
||||
|
||||
aid = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'mass_mailing.action_partner_to_mailing_list')
|
||||
print sid, aid
|
||||
ctx = dict(context)
|
||||
ctx['view_manager_highlight'] = [aid]
|
||||
return {
|
||||
'name': _('Choose Customers'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'res.partner',
|
||||
# 'views': [(False, 'tree'), (False, 'form')],
|
||||
'view_id': False,
|
||||
'search_view_id': sid,
|
||||
# 'target': 'new',
|
||||
'context': ctx,
|
||||
}
|
||||
|
||||
|
||||
class MailMailStats(osv.Model):
|
||||
""" MailMailStats models the statistics collected about emails. Those statistics
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- After installation of the module, open the related menu -->
|
||||
<record id="action_client_marketing_menu" model="ir.actions.client">
|
||||
<field name="name">Open Marketing Menu</field>
|
||||
<field name="tag">reload</field>
|
||||
<field name="params" eval="{'menu_id': ref('base.marketing_menu')}"/>
|
||||
</record>
|
||||
<record id="base.open_menu" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_client_marketing_menu"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
|
||||
<!-- Group to manage campaigns -->
|
||||
<record id="group_mass_mailing_campaign" model="res.groups">
|
||||
<field name="name">Manage Mass Mailing Campaigns</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -8,16 +8,153 @@
|
|||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="auto_delete" eval="False"/>
|
||||
<field name="partner_to">${object.id}</field>
|
||||
<field name="body_html"><![CDATA[<p>Hello</p>]]></field>
|
||||
<field name="reply_to"><![CDATA[Info <info@yourcompany.example.com>]]></field>
|
||||
<field name="use_in_mass_mailing" eval="True"/>
|
||||
<field name="body_html"><![CDATA[<div data-snippet-id="big-picture" style="padding:0px; margin:0px">
|
||||
<table cellpadding="0" cellspacing="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width:600px" valign="top">
|
||||
<h2 style="text-align: center; padding:0px 5px">A Punchy Headline</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:600px" valign="top"><img src="/website/static/src/img/big_picture.png" style="display:block;border:none;min-height:250px;margin:0 auto;" width="500"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:600px" valign="top">
|
||||
<p style="text-align: center; overflow:hidden"></p>
|
||||
|
||||
<h3 style="text-align: center; padding:0px 5px">A Small Subtitle for ${object.name}</h3>
|
||||
|
||||
<p></p>
|
||||
|
||||
<p style="text-align: center; overflow:hidden">Choose a vibrant image and write an inspiring paragraph about it. It does not have to be long, but it should reinforce your image.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div data-snippet-id="three-columns" style="padding:0px; margin:0px">
|
||||
<table cellpadding="0" cellspacing="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width:300px" valign="top"><img src="/website/static/src/img/desert_thumb.jpg" style="display:block;border:none;min-height:50px" width="275"></td>
|
||||
<td style="width:300px" valign="top"><img src="/website/static/src/img/deers_thumb.jpg" style="display:block;border:none;min-height:50px" width="275"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:300px" valign="top">
|
||||
<h3 style="text-align: center; padding:0px 5px">Feature One</h3>
|
||||
|
||||
<p style="overflow:hidden">Choose a vibrant image and write an inspiring paragraph about it. It does not have to be long, but it should reinforce your image.</p>
|
||||
</td>
|
||||
<td style="width:300px" valign="top">
|
||||
<h3 style="text-align: center; padding:0px 5px">Feature Two</h3>
|
||||
|
||||
<p style="overflow:hidden">Choose a vibrant image and write an inspiring paragraph about it. It does not have to be long, but it should reinforce your image.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>]]></field>
|
||||
</record>
|
||||
|
||||
<record id="mass_mail_template_2" model="email.template">
|
||||
<field name="name">Partner Newsletter 2</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="auto_delete" eval="False"/>
|
||||
<field name="partner_to">${object.id}</field>
|
||||
<field name="body_html"><![CDATA[<p>Hello</p>]]></field>
|
||||
<field name="reply_to"><![CDATA[Info <info@yourcompany.example.com>]]></field>
|
||||
<field name="use_in_mass_mailing" eval="True"/>
|
||||
<field name="body_html"><![CDATA[<div data-snippet-id="text-image" style="padding:0px; margin:0px">
|
||||
<table cellpadding="0" cellspacing="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px 5px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width:600px" valign="top">
|
||||
<div style="padding:0px 5px">
|
||||
<h1 style="text-align: center">Sell Online. Easily.</h1>
|
||||
|
||||
<p style="overflow:hidden">Write one sentence to convince visitor about your message.</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div data-snippet-id="hr" style="padding:0px; margin:0px">
|
||||
<table cellpadding="0" cellspacing="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width:600px" valign="top">
|
||||
<div style="padding:0px 5px">
|
||||
<hr style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0" width="100%" data-snippet-id="hr"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div data-snippet-id="three-columns" style="padding:0px; margin:0px">
|
||||
<table cellpadding="0" cellspacing="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width:200px" valign="top"><img src="/website/static/src/img/desert_thumb.jpg" style="display:block;border:none;min-height:50px" width="175"></td>
|
||||
<td style="width:200px" valign="top"><img src="/website/static/src/img/deers_thumb.jpg" style="display:block;border:none;min-height:50px" width="175"></td>
|
||||
<td style="width:200px" valign="top"><img src="/website/static/src/img/china_thumb.jpg" style="display:block;border:none;min-height:50px" width="175"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:200px" valign="top">
|
||||
<h3 style="text-align: center; padding:0px 5px">Feature One</h3>
|
||||
|
||||
<p style="overflow:hidden">Choose a vibrant image and write an inspiring paragraph about it. It does not have to be long, but it should reinforce your image.</p>
|
||||
</td>
|
||||
<td style="width:200px" valign="top">
|
||||
<h3 style="text-align: center; padding:0px 5px">Feature Two</h3>
|
||||
|
||||
<p style="overflow:hidden">Choose a vibrant image and write an inspiring paragraph about it. It does not have to be long, but it should reinforce your image.</p>
|
||||
</td>
|
||||
<td style="width:200px" valign="top">
|
||||
<h3 style="text-align: center; padding:0px 5px">Feature Three</h3>
|
||||
|
||||
<p style="overflow:hidden">Choose a vibrant image and write an inspiring paragraph about it. It does not have to be long, but it should reinforce your image.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>]]></field>
|
||||
</record>
|
||||
|
||||
<!-- Create mailing lists -->
|
||||
<record id="mass_mail_list_1" model="mail.mass_mailing.list">
|
||||
<field name="name">Imported Contacts</field>
|
||||
<field name="model">mail.mass_mailing.contact</field>
|
||||
</record>
|
||||
<record id="mass_mail_list_2" model="mail.mass_mailing.list">
|
||||
<field name="name">Customers</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="model_id" eval="ref('base.model_res_partner')"/>
|
||||
<field name="domain">[('customer', '=', True)]</field>
|
||||
</record>
|
||||
|
||||
<!-- Create Contacts -->
|
||||
<record id="mass_mail_contact_1" model="mail.mass_mailing.contact">
|
||||
<field name="name">Aristide Antario</field>
|
||||
<field name="email">aa@example.com</field>
|
||||
<field name="list_id" eval="ref('mass_mail_list_1')"/>
|
||||
</record>
|
||||
<record id="mass_mail_contact_2" model="mail.mass_mailing.contact">
|
||||
<field name="name">Beverly Bridge</field>
|
||||
<field name="email">bb@example.com</field>
|
||||
<field name="list_id" eval="ref('mass_mail_list_1')"/>
|
||||
</record>
|
||||
<record id="mass_mail_contact_3" model="mail.mass_mailing.contact">
|
||||
<field name="name">Carol Cartridge</field>
|
||||
<field name="email">cc@example.com</field>
|
||||
<field name="list_id" eval="ref('mass_mail_list_1')"/>
|
||||
<field name="opt_out" eval="True"/>
|
||||
</record>
|
||||
|
||||
<!-- Create campaign and mailings -->
|
||||
<record id="mass_mail_campaign_1" model="mail.mass_mailing.campaign">
|
||||
<field name="name">Partners Newsletter</field>
|
||||
<field name="user_id" eval="ref('base.user_root')"/>
|
||||
|
@ -25,12 +162,14 @@
|
|||
|
||||
<record id="mass_mail_1" model="mail.mass_mailing">
|
||||
<field name="name">First Newsletter</field>
|
||||
<field name="state">done</field>
|
||||
<field name="template_id" eval="ref('mass_mail_template_1')"/>
|
||||
<field name="date" eval="(DateTime.today() - relativedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="date" eval="(DateTime.today() - relativedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="mass_mailing_campaign_id" eval="ref('mass_mail_campaign_1')"/>
|
||||
</record>
|
||||
<record id="mass_mail_2" model="mail.mass_mailing">
|
||||
<field name="name">Second Newsletter</field>
|
||||
<field name="state">test</field>
|
||||
<field name="template_id" eval="ref('mass_mail_template_2')"/>
|
||||
<field name="date" eval="(DateTime.today() - relativedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
<field name="mass_mailing_campaign_id" eval="ref('mass_mail_campaign_1')"/>
|
||||
|
@ -63,20 +202,5 @@
|
|||
<field name="bounced" eval="(DateTime.today() - relativedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
|
||||
<record id="mass_mail_email_2_1" model="mail.mail.statistics">
|
||||
<field name="mass_mailing_id" eval="ref('mass_mail_2')"/>
|
||||
<field name="message_id">1111005@OpenERP.com</field>
|
||||
<field name="opened" eval="(DateTime.today() - relativedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
<record id="mass_mail_email_2_2" model="mail.mail.statistics">
|
||||
<field name="mass_mailing_id" eval="ref('mass_mail_2')"/>
|
||||
<field name="message_id">1111006@OpenERP.com</field>
|
||||
<field name="opened" eval="(DateTime.today() - relativedelta(days=2)).strftime('%Y-%m-%d %H:%M:%S')"/>
|
||||
</record>
|
||||
<record id="mass_mail_email_2_3" model="mail.mail.statistics">
|
||||
<field name="mass_mailing_id" eval="ref('mass_mail_2')"/>
|
||||
<field name="message_id">1111007@OpenERP.com</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -2,6 +2,147 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Marketing / Mass Mailing -->
|
||||
<menuitem name="Mass Mailing" id="mass_mailing_campaign"
|
||||
parent="base.marketing_menu" sequence="1"/>
|
||||
<!-- Marketing / Mailing Lists -->
|
||||
<menuitem name="Contacts" id="mass_mailing_list"
|
||||
parent="base.marketing_menu" sequence="2"/>
|
||||
|
||||
<!-- 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">
|
||||
<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)]"
|
||||
help="Contact is not opt-out"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Mailing Lists" name="group_list_id"
|
||||
context="{'group_by': 'list_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_mail_mass_mailing_contact_tree">
|
||||
<field name="name">mail.mass_mailing.contact.tree</field>
|
||||
<field name="model">mail.mass_mailing.contact</field>
|
||||
<field name="priority">10</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Mass Mailings">
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
<field name="list_id"/>
|
||||
<field name="opt_out"/>
|
||||
</tree>
|
||||
</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="res_model">mail.mass_mailing.contact</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_not_opt_out': 1}</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Mailing Contacts" id="menu_email_mass_mailing_contacts"
|
||||
parent="mass_mailing_list" sequence="50"
|
||||
action="action_view_mass_mailing_contacts"/>
|
||||
|
||||
<!-- 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>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_mail_mass_mailing_list_tree">
|
||||
<field name="name">mail.mass_mailing.list.tree</field>
|
||||
<field name="model">mail.mass_mailing.list</field>
|
||||
<field name="priority">10</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Contact Lists">
|
||||
<field name="name"/>
|
||||
<field name="model"/>
|
||||
<field name="contact_nbr"/>
|
||||
</tree>
|
||||
</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_see_records" type="object"
|
||||
class="oe_highlight" string="See Contacts"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<label for="contact_nbr"/>
|
||||
<div>
|
||||
<field name="contact_nbr" nolabel="1" class="oe_inline"/><span>contacts</span>
|
||||
</div>
|
||||
<field name="model" on_change="on_change_model(model, context)"/>
|
||||
<field name="contact_ids"
|
||||
attrs="{'invisible': [('model', '!=', 'mail.mass_mailing.contact')]}">
|
||||
<tree editable='bottom'>
|
||||
<field name="name"/>
|
||||
<field name="email"/>
|
||||
</tree>
|
||||
</field>
|
||||
<field name="filter_id"
|
||||
on_change="on_change_filter_id(filter_id, context)"
|
||||
attrs="{'invisible': [('model', '=', 'mail.mass_mailing.contact')]}"/>
|
||||
<field name="domain"
|
||||
attrs="{'invisible': ['|', ('model', '=', 'mail.mass_mailing.contact'), ('filter_id', '!=', False)]}"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_view_mass_mailing_lists" model="ir.actions.act_window">
|
||||
<field name="name">Contact Lists</field>
|
||||
<field name="res_model">mail.mass_mailing.list</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Contact Lists" id="menu_email_mass_mailing_lists"
|
||||
parent="mass_mailing_list" sequence="40"
|
||||
action="action_view_mass_mailing_lists"/>
|
||||
|
||||
<!-- MASS MAILING !-->
|
||||
<record model="ir.ui.view" id="view_mail_mass_mailing_search">
|
||||
<field name="name">mail.mass_mailing.search</field>
|
||||
|
@ -13,6 +154,7 @@
|
|||
<field name="template_id"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<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'}"/>
|
||||
|
@ -32,7 +174,8 @@
|
|||
<field name="delivered"/>
|
||||
<field name="opened"/>
|
||||
<field name="replied"/>
|
||||
<field name="mass_mailing_campaign_id" invisible="1"/>
|
||||
<field name="mass_mailing_campaign_id"
|
||||
groups="mass_mailing.group_mass_mailing_campaign"/>
|
||||
<field name="template_id" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
@ -43,19 +186,51 @@
|
|||
<field name="model">mail.mass_mailing</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Mass Mailing" version="7.0">
|
||||
<header>
|
||||
<button name="send_mail_to_myself" type="object"
|
||||
class="oe_highlight" string="Send to Myself"/>
|
||||
<button name="send_mail" type="object"
|
||||
class="oe_highlight" string="Send to All"/>
|
||||
<field name="state" widget="statusbar" clickable="True"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="mass_mailing_campaign_id" readonly="True"/>
|
||||
<field name="date" readonly="True"/>
|
||||
<field name="mass_mailing_campaign_id" groups="mass_mailing.group_mass_mailing_campaign"/>
|
||||
<label for="template_id"/>
|
||||
<div style="max-height: 200px; overflow: hidden !important;">
|
||||
<field name="template_id" string="Select Template" nolabel="1"
|
||||
on_change="on_change_template_id(template_id, context)"/>
|
||||
<field name="body_html" class="html_preview" nolabel="1"
|
||||
attrs="{'invisible': [('template_id', '=', False)]}"/>
|
||||
</div>
|
||||
<field name="email_from"/>
|
||||
<field name="reply_to"/>
|
||||
<field name="email_to"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="template_id"/>
|
||||
<field name="domain"/>
|
||||
<field name="date"/>
|
||||
<p>Here be some graphs</p>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Email Statistics">
|
||||
<group>
|
||||
<label for="contact_list_ids" string="Recipients"/>
|
||||
<div>
|
||||
<field name="contact_nbr" class="oe_inline" readonly="True"/>
|
||||
<field name="mailing_type" class="oe_inline"
|
||||
on_change='on_change_mailing_type(mailing_type, context)'/>
|
||||
<span>selected</span>
|
||||
<group>
|
||||
<label for="contact_list_ids" string="Selected Lists"/>
|
||||
<div>
|
||||
<field name="contact_list_ids" widget="many2many_tags" nolabel="1"/>
|
||||
<button string='Create a New List' class="oe_inline oe_link" type='object' name='select_customers'/>
|
||||
</div>
|
||||
</group>
|
||||
</div>
|
||||
</group>
|
||||
<!-- <group string="Email Statistics">
|
||||
<field name="statistics_ids" nolabel="1" colspan="2"/>
|
||||
<group>
|
||||
<field name="sent"/>
|
||||
|
@ -66,7 +241,7 @@
|
|||
<field name="delivered"/>
|
||||
<field name="replied"/>
|
||||
</group>
|
||||
</group>
|
||||
</group> -->
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -76,7 +251,7 @@
|
|||
<field name="name">mail.mass_mailing.kanban</field>
|
||||
<field name="model">mail.mass_mailing</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<kanban default_group_by='state'>
|
||||
<field name='color'/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
|
@ -87,8 +262,9 @@
|
|||
<field name="name"/>
|
||||
</h3>
|
||||
<p style="margin-left: 10px; margin-top: 8px;">
|
||||
Sent: <field name="date"/><br />
|
||||
Campaign: <field name="mass_mailing_campaign_id"/>
|
||||
<span>Sent:</span><field name="date"/><br />
|
||||
<span groups="mass_mailing.mass_mailing_campaign_id">Campaign:</span>
|
||||
<field name="mass_mailing_campaign_id" groups="mass_mailing.mass_mailing_campaign_id"/>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -112,11 +288,11 @@
|
|||
<div>
|
||||
<div class="oe_sparkline_container">
|
||||
<h4 class="oe_sparkline_bar_title">Opened</h4><br />
|
||||
<field name="opened_monthly" widget="sparkline_bar" options="{'height': '50px', 'barWidth': 10, 'barSpacing': 5}"/>
|
||||
<field name="opened_dayly" widget="sparkline_bar" options="{'height': '50px', 'barWidth': 10, 'barSpacing': 5}"/>
|
||||
</div>
|
||||
<div class="oe_sparkline_container">
|
||||
<h4 class="oe_sparkline_bar_title">Replied</h4><br />
|
||||
<field name="replied_monthly" widget="sparkline_bar" options="{'height': '50px', 'barWidth': 10, 'barSpacing': 5}"/>
|
||||
<field name="replied_dayly" widget="sparkline_bar" options="{'height': '50px', 'barWidth': 10, 'barSpacing': 5}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -147,6 +323,10 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Mass Mailings" id="menu_email_mass_mailings"
|
||||
parent="mass_mailing_campaign" sequence="2"
|
||||
action="action_view_mass_mailings"/>
|
||||
|
||||
<!-- MASS MAILING CAMPAIGNS !-->
|
||||
<record model="ir.ui.view" id="view_mail_mass_mailing_campaign_search">
|
||||
<field name="name">mail.mass_mailing.campaign.search</field>
|
||||
|
@ -154,10 +334,13 @@
|
|||
<field name="arch" type="xml">
|
||||
<search string="Mass Mailing Campaigns">
|
||||
<field name="name" string="Campaigns"/>
|
||||
<field name="category_id"/>
|
||||
<field name="user_id"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Responsibles" name="group_user_id"
|
||||
<filter string="Responsible" name="group_user_id"
|
||||
context="{'group_by': 'user_id'}"/>
|
||||
<filter string="Category" name="group_category_id"
|
||||
context="{'group_by': 'category_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
@ -171,6 +354,8 @@
|
|||
<tree string="Mass Mailing Campaigns">
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
<field name="state"/>
|
||||
<field name="category_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -182,14 +367,16 @@
|
|||
<form string="Mass Mailing Campaign" version="7.0">
|
||||
<header>
|
||||
<button name="launch_mass_mailing_create_wizard" type="object"
|
||||
class="oe_highlight" string="Create a New Mailing"/>
|
||||
class="oe_highlight" string="New Mailing"/>
|
||||
<field name="state" widget="statusbar" clickable="True"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
<field name="category_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<!-- <group>
|
||||
<group>
|
||||
<field name="sent"/>
|
||||
<field name="opened"/>
|
||||
|
@ -199,9 +386,20 @@
|
|||
<field name="delivered"/>
|
||||
<field name="replied"/>
|
||||
</group>
|
||||
</group>
|
||||
</group> -->
|
||||
<group>
|
||||
<field name="mass_mailing_ids" readonly="1"/>
|
||||
<field name="mass_mailing_ids" readonly="1" string="Related Mailing(s)">
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="date"/>
|
||||
<field name="state"/>
|
||||
<field name="delivered"/>
|
||||
<field name="opened"/>
|
||||
<field name="replied"/>
|
||||
<field name="bounced"/>
|
||||
<button name="duplicate_mailing" type="object" string="Duplicate"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
|
@ -212,7 +410,7 @@
|
|||
<field name="name">mail.mass_mailing.campaign.kanban</field>
|
||||
<field name="model">mail.mass_mailing.campaign</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<kanban default_group_by='state'>
|
||||
<field name="mass_mailing_kanban_ids"/>
|
||||
<field name='sent'/>
|
||||
<field name='color'/>
|
||||
|
@ -299,6 +497,11 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Campaigns" id="menu_email_campaigns"
|
||||
parent="mass_mailing_campaign" sequence="1"
|
||||
action="action_view_mass_mailing_campaigns"
|
||||
groups="mass_mailing.group_mass_mailing_campaign"/>
|
||||
|
||||
<!-- MAIL MAIL STATISTICS !-->
|
||||
<record model="ir.ui.view" id="view_mail_mail_statistics_search">
|
||||
<field name="name">mail.mail.statistics.search</field>
|
||||
|
@ -357,23 +560,25 @@
|
|||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<!-- Top menu item -->
|
||||
<menuitem name="Marketing" id="base.marketing_menu" sequence="85" groups="base.group_user"/>
|
||||
|
||||
<!-- Add in marketing -->
|
||||
<menuitem name="Mass Mailing" id="mass_mailing_campaign"
|
||||
parent="base.marketing_menu" sequence="1"/>
|
||||
<menuitem name="Campaigns" id="menu_email_campaigns"
|
||||
parent="mass_mailing_campaign" sequence="1"
|
||||
action="action_view_mass_mailing_campaigns"/>
|
||||
<menuitem name="Mass Mailings" id="menu_email_mass_mailings"
|
||||
parent="mass_mailing_campaign" sequence="2"
|
||||
action="action_view_mass_mailings"/>
|
||||
|
||||
<!-- Add in Technical/Email -->
|
||||
<menuitem name="Mail Statistics" id="menu_email_statistics"
|
||||
parent="base.menu_email" sequence="50"
|
||||
action="action_view_mail_mail_statistics"/>
|
||||
|
||||
|
||||
|
||||
<!-- Replace the default mass-mailing wizard in base with the composition wizard -->
|
||||
<act_window name="Partner to Mailing List"
|
||||
res_model="mail.mass_mailing.list"
|
||||
src_model="res.partner"
|
||||
view_mode="form"
|
||||
multi="True"
|
||||
target="current"
|
||||
key2="client_action_multi"
|
||||
id="action_partner_to_mailing_list"
|
||||
context="{
|
||||
'caca': 'prout',
|
||||
}"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
||||
class MassMailingConfiguration(osv.TransientModel):
|
||||
_name = 'marketing.config.settings'
|
||||
_inherit = 'marketing.config.settings'
|
||||
|
||||
_columns = {
|
||||
'group_mass_mailing_campaign': fields.boolean(
|
||||
'Manage Mass Mailing using Campaign',
|
||||
implied_group='mass_mailing.group_mass_mailing_campaign',
|
||||
help="""Manage mass mailign using Campaigns"""),
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_marketing_settings_mass_mailing" model="ir.ui.view">
|
||||
<field name="name">marketing.config.settings.mass.mailing</field>
|
||||
<field name="model">marketing.config.settings</field>
|
||||
<field name="inherit_id" ref="marketing.view_marketing_configuration"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='module_mass_mailing']" position="after">
|
||||
<div>
|
||||
<field name="group_mass_mailing_campaign" class="oe_inline"/>
|
||||
<label for="group_mass_mailing_campaign"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,4 +1,7 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_mass_mailing_category,mail.mass_mailing.category,model_mail_mass_mailing_category,base.group_user,1,1,1,1
|
||||
access_mass_mailing_contact,mail.mass_mailing.contact,model_mail_mass_mailing_contact,base.group_user,1,1,1,1
|
||||
access_mass_mailing_list,mail.mass_mailing.list,model_mail_mass_mailing_list,base.group_user,1,1,1,1
|
||||
access_mass_mailing_campaign,mail.mass_mailing.campaign,model_mail_mass_mailing_campaign,base.group_user,1,1,1,0
|
||||
access_mass_mailing_campaign_system,mail.mass_mailing.campaign.system,model_mail_mass_mailing_campaign,base.group_system,1,1,1,1
|
||||
access_mass_mailing,mail.mass_mailing,model_mail_mass_mailing,base.group_user,1,1,1,0
|
||||
|
|
|
|
@ -0,0 +1,19 @@
|
|||
.openerp .oe_kanban_email_template {
|
||||
width: 360px;
|
||||
min-height: 270px !important;
|
||||
}
|
||||
|
||||
|
||||
.html_preview {
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
-webkit-transform: scale(.50);
|
||||
-ms-transform: scale(.50);
|
||||
transform: scale(.50);
|
||||
-webkit-transform-origin: 0 0;
|
||||
-ms-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
border: 2px solid gray;
|
||||
margin: 0 0px -300px 0;
|
||||
overflow: hidden !important;
|
||||
}
|
Loading…
Reference in New Issue