[IMP] [ADD] event: mail schedulign system.
This commit adds a way to configure scheduled emails on events. It replaces existing automatic emails at confirmation and subscription. It proposes to configure some schedulers, based on subscription or event, using a template and a configurable timedelta. A cron is added that regularly checks for event mailing schedulers to execute and launch them. The granularity of send emails is therefore limited to the granularity of the cron, aka 1 hour. [TEST] Added tests for this feature. Also cleaned a bit event, country_id is now a pure related instead of a computed field trying to be a related. Also removed default templates on event category. Configuration in the event itself should be easy enough for most use cases.
This commit is contained in:
committed by
Thibault Delavallée
parent
fd54df5c7c
commit
ad48bf6d7d
@@ -20,6 +20,7 @@
|
||||
##############################################################################
|
||||
|
||||
import event
|
||||
import event_mail
|
||||
import wizard
|
||||
import report
|
||||
import res_config
|
||||
|
||||
@@ -1,51 +1,48 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="confirmation_event" model="email.template">
|
||||
<field name="name">Confirmation of the Event</field>
|
||||
<field name="model_id" ref="event.model_event_registration"/>
|
||||
<field name="email_from" >${(object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com')|safe}</field>
|
||||
<field name="email_to" >${object.email|safe}</field>
|
||||
<field name="subject">Your registration at ${object.event_id.name}</field>
|
||||
<field name="body_html"><![CDATA[
|
||||
<p>Hello ${object.name},</p>
|
||||
<p>The event ${object.event_id.name} that you registered for is confirmed and will be held from ${object.event_id.date_begin_located.strftime('%Y-%m-%d %H:%M:%S (%Z)')} to ${object.event_id.date_end_located.strftime('%Y-%m-%d %H:%M:%S (%Z)')}.
|
||||
For any further information please contact our event department.</p>
|
||||
<p>Thank you for your participation!</p>
|
||||
<p>Best regards</p>]]></field>
|
||||
|
||||
<record id="event_subscription" model="email.template">
|
||||
<field name="name">Event subscription</field>
|
||||
<field name="model_id" ref="event.model_event_registration"/>
|
||||
<field name="email_from">${(object.event_id.organizer_id.email or object.event_id.user_id.email or '')|safe}</field>
|
||||
<field name="email_to" >${object.email|safe}</field>
|
||||
<field name="subject">Your subscription at ${object.event_id.name}</field>
|
||||
<field name="body_html"><![CDATA[<p>Hello ${object.name},</p>
|
||||
<p>We confirm that your subscription to the event ${object.event_id.name} has been recorded.
|
||||
You will automatically receive an email providing you more practical information (such as the schedule, the agenda...) as soon as the event is confirmed.</p>
|
||||
<p>Thank you for your participation!</p>
|
||||
<p>Best regards</p>]]></field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
<data>
|
||||
|
||||
<record id="confirmation_registration" model="email.template">
|
||||
<field name="name">Confirmation of the Registration</field>
|
||||
<field name="model_id" ref="event.model_event_registration"/>
|
||||
<field name="email_from" >${(object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com')|safe}</field>
|
||||
<field name="email_to" >${object.email|safe}</field>
|
||||
<field name="subject">Your registration at ${object.event_id.name}</field>
|
||||
<field name="body_html"><![CDATA[
|
||||
<p>Hello ${object.name},</p>
|
||||
<p>We confirm that your registration to the event ${object.event_id.name} has been recorded.
|
||||
You will automatically receive an email providing you more practical information (such as the schedule, the agenda...) as soon as the event is confirmed.</p>
|
||||
<p>Thank you for your participation!</p>
|
||||
<p>Best regards</p>]]></field>
|
||||
<record id="event_reminder" model="email.template">
|
||||
<field name="name">Event: reminder</field>
|
||||
<field name="model_id" ref="event.model_event_registration"/>
|
||||
<field name="email_from">${(object.event_id.organizer_id.email or object.event_id.user_id.email or '')|safe}</field>
|
||||
<field name="email_to" >${object.partner_id.email or object.email|safe}</field>
|
||||
<field name="subject">Reminder of event ${object.event_id.name}</field>
|
||||
<field name="body_html"><![CDATA[<p>Hello ${object.name},</p>
|
||||
<p>This is a reminder for ${object.event_id.name} that you registered for is confirmed and will be held from ${object.event_id.date_begin_located} to ${object.event_id.date_end_located}.
|
||||
For any further information please contact our event department.</p>
|
||||
<p>Thank you for your participation!</p>
|
||||
<p>Best regards</p>]]></field>
|
||||
</record>
|
||||
|
||||
<!-- Default Values -->
|
||||
<record model="ir.values" id="default_value_event_mail_confirmation">
|
||||
<field name="name">default_email_event</field>
|
||||
<field name="key">default</field>
|
||||
<field name="key2"></field>
|
||||
<field eval="ref('confirmation_event')" name="value_unpickle"/>
|
||||
<field name="model">event.type</field>
|
||||
</record>
|
||||
<record model="ir.values" id="default_value_registration_mail_confirmation">
|
||||
<field name="name">default_email_registration</field>
|
||||
<field name="key">default</field>
|
||||
<field name="key2"></field>
|
||||
<field eval="ref('confirmation_registration')" name="value_unpickle"/>
|
||||
<field name="model">event.type</field>
|
||||
<record id="event_thanks" model="email.template">
|
||||
<field name="name">Event: thanks for attending</field>
|
||||
<field name="model_id" ref="event.model_event_registration"/>
|
||||
<field name="email_from">${(object.event_id.organizer_id.email or object.event_id.user_id.email or '')|safe}</field>
|
||||
<field name="email_to" >${object.partner_id.email or object.email|safe}</field>
|
||||
<field name="subject">Thanks for attending ${object.event_id.name}</field>
|
||||
<field name="body_html"><![CDATA[<p>Hello ${object.name},</p>
|
||||
<p>We would like to thank you for your presence at our event ${object.event_id.name}.
|
||||
<br/><br/>
|
||||
% if object.event_id.organizer_id and object.event_id.organizer_id.is_company:
|
||||
<strong>The ${object.event_id.organizer_id.name} Team</strong>
|
||||
% elif object.event_id.organizer_id:
|
||||
<strong>${object.event_id.organizer_id.name}</strong>
|
||||
% endif
|
||||
</p>]]></field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
+29
-73
@@ -2,7 +2,7 @@
|
||||
|
||||
import pytz
|
||||
|
||||
from openerp import models, fields, api, _
|
||||
from openerp import _, api, fields, models
|
||||
from openerp.exceptions import Warning
|
||||
|
||||
|
||||
@@ -11,21 +11,13 @@ class event_type(models.Model):
|
||||
_name = 'event.type'
|
||||
_description = 'Event Type'
|
||||
|
||||
name = fields.Char(string='Event Type', required=True)
|
||||
default_reply_to = fields.Char(
|
||||
string='Default Reply-To',
|
||||
help="The email address of the organizer which is put in the 'Reply-To' of all emails sent automatically at event or registrations confirmation. You can also put your email address of your mail gateway if you use one.")
|
||||
default_email_event = fields.Many2one(
|
||||
'email.template', string='Event Confirmation Email',
|
||||
help="It will select this default confirmation event mail value when you choose this event")
|
||||
default_email_registration = fields.Many2one(
|
||||
'email.template', string='Registration Confirmation Email',
|
||||
help="It will select this default confirmation registration mail value when you choose this event")
|
||||
name = fields.Char('Event Type', required=True)
|
||||
default_reply_to = fields.Char('Reply To')
|
||||
default_registration_min = fields.Integer(
|
||||
string='Default Minimum Registration', default=0,
|
||||
'Default Minimum Registration', default=0,
|
||||
help="It will select this default minimum value when you choose this event")
|
||||
default_registration_max = fields.Integer(
|
||||
string='Default Maximum Registration', default=0,
|
||||
'Default Maximum Registration', default=0,
|
||||
help="It will select this default maximum value when you choose this event")
|
||||
|
||||
|
||||
@@ -54,6 +46,15 @@ class event_event(models.Model):
|
||||
'event.type', string='Category',
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
color = fields.Integer('Kanban Color Index')
|
||||
event_mail_ids = fields.One2many('event.mail', 'event_id', string='Mail Schedule', default=lambda self: self._default_event_mail_ids())
|
||||
|
||||
@api.model
|
||||
def _default_event_mail_ids(self):
|
||||
return [(0, 0, {
|
||||
'interval_unit': 'now',
|
||||
'interval_type': 'after_sub',
|
||||
'template_id': self.env['ir.model.data'].xmlid_to_res_id('event.event_subscription')
|
||||
})]
|
||||
|
||||
# Seats and computation
|
||||
seats_max = fields.Integer(
|
||||
@@ -154,11 +155,6 @@ class event_event(models.Model):
|
||||
else:
|
||||
self.date_end_located = False
|
||||
|
||||
@api.one
|
||||
@api.depends('address_id')
|
||||
def _compute_country(self):
|
||||
self.country_id = self.address_id.country_id
|
||||
|
||||
state = fields.Selection([
|
||||
('draft', 'Unconfirmed'), ('cancel', 'Cancelled'),
|
||||
('confirm', 'Confirmed'), ('done', 'Done')],
|
||||
@@ -170,23 +166,13 @@ class event_event(models.Model):
|
||||
def _compute_auto_confirm(self):
|
||||
self.auto_confirm = self.env['ir.values'].get_default('marketing.config.settings', 'auto_confirmation')
|
||||
|
||||
# Mailing
|
||||
email_registration_id = fields.Many2one(
|
||||
'email.template', string='Registration Confirmation Email',
|
||||
domain=[('model', '=', 'event.registration')],
|
||||
help='This field contains the template of the mail that will be automatically sent each time a registration for this event is confirmed.')
|
||||
email_confirmation_id = fields.Many2one(
|
||||
'email.template', string='Event Confirmation Email',
|
||||
domain=[('model', '=', 'event.registration')],
|
||||
help="If you set an email template, each participant will receive this email announcing the confirmation of the event.")
|
||||
reply_to = fields.Char(
|
||||
string='Reply-To Email', readonly=False, states={'done': [('readonly', True)]},
|
||||
'Reply-To Email', readonly=False, states={'done': [('readonly', True)]},
|
||||
help="The email address of the organizer is likely to be put here, with the effect to be in the 'Reply-To' of the mails sent automatically at event or registrations confirmation. You can also put the email address of your mail gateway if you use one.")
|
||||
address_id = fields.Many2one(
|
||||
'res.partner', string='Location', default=lambda self: self.env.user.company_id.partner_id,
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
country_id = fields.Many2one('res.country', string='Country',
|
||||
store=True, compute='_compute_country')
|
||||
country_id = fields.Many2one('res.country', 'Country', related='address_id.country_id', store=True)
|
||||
description = fields.Html(
|
||||
string='Description', oldname='note', translate=True,
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
@@ -217,7 +203,7 @@ class event_event(models.Model):
|
||||
def create(self, vals):
|
||||
res = super(event_event, self).create(vals)
|
||||
if res.auto_confirm:
|
||||
res.confirm_event()
|
||||
res.button_confirm()
|
||||
return res
|
||||
|
||||
@api.one
|
||||
@@ -236,27 +222,16 @@ class event_event(models.Model):
|
||||
def button_done(self):
|
||||
self.state = 'done'
|
||||
|
||||
@api.one
|
||||
def confirm_event(self):
|
||||
if self.email_confirmation_id:
|
||||
# send reminder that will confirm the event for all the people that were already confirmed
|
||||
regs = self.registration_ids.filtered(lambda reg: reg.state not in ('draft', 'cancel'))
|
||||
regs.mail_user_confirm()
|
||||
self.state = 'confirm'
|
||||
|
||||
@api.one
|
||||
def button_confirm(self):
|
||||
""" Confirm Event and send confirmation email to all register peoples """
|
||||
self.confirm_event()
|
||||
self.state = 'confirm'
|
||||
|
||||
@api.onchange('type')
|
||||
def _onchange_type(self):
|
||||
if self.type:
|
||||
self.reply_to = self.type.default_reply_to
|
||||
self.email_registration_id = self.type.default_email_registration
|
||||
self.email_confirmation_id = self.type.default_email_event
|
||||
self.seats_min = self.type.default_registration_min
|
||||
self.seats_max = self.type.default_registration_max
|
||||
self.reply_to = self.type.default_reply_to
|
||||
|
||||
@api.multi
|
||||
def action_event_registration_report(self):
|
||||
@@ -267,6 +242,11 @@ class event_event(models.Model):
|
||||
}
|
||||
return res
|
||||
|
||||
@api.one
|
||||
def mail_attendees(self, template_id, force_send=False, filter_func=lambda self: True):
|
||||
for attendee in self.registration_ids.filtered(filter_func):
|
||||
self.env['email.template'].browse(template_id).send_mail(attendee.id, force_send=force_send)
|
||||
|
||||
|
||||
class event_registration(models.Model):
|
||||
_name = 'event.registration'
|
||||
@@ -283,9 +263,8 @@ class event_registration(models.Model):
|
||||
partner_id = fields.Many2one(
|
||||
'res.partner', string='Contact',
|
||||
states={'done': [('readonly', True)]})
|
||||
date_open = fields.Datetime(string='Registration Date', readonly=True)
|
||||
date_open = fields.Datetime(string='Registration Date', readonly=True, default=lambda self: fields.datetime.now()) # weird crash is directly now
|
||||
date_closed = fields.Datetime(string='Attended Date', readonly=True)
|
||||
reply_to = fields.Char(string='Reply-to Email', related='event_id.reply_to', readonly=True)
|
||||
event_begin_date = fields.Datetime(string="Event Start Date", related='event_id.date_begin', readonly=True)
|
||||
event_end_date = fields.Datetime(string="Event End Date", related='event_id.date_end', readonly=True)
|
||||
company_id = fields.Many2one(
|
||||
@@ -315,10 +294,10 @@ class event_registration(models.Model):
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(event_registration, self).create(vals)
|
||||
if res._check_auto_confirmation()[0]:
|
||||
res.sudo().confirm_registration()
|
||||
return res
|
||||
registration = super(event_registration, self).create(vals)
|
||||
if registration._check_auto_confirmation():
|
||||
registration.sudo().confirm_registration()
|
||||
return registration
|
||||
|
||||
@api.one
|
||||
def do_draft(self):
|
||||
@@ -331,12 +310,6 @@ class event_registration(models.Model):
|
||||
subtype="event.mt_event_registration")
|
||||
self.state = 'open'
|
||||
|
||||
@api.one
|
||||
def registration_open(self):
|
||||
""" Open Registration """
|
||||
self.confirm_registration()
|
||||
self.mail_user()
|
||||
|
||||
@api.one
|
||||
def button_reg_close(self):
|
||||
""" Close Registration """
|
||||
@@ -350,23 +323,6 @@ class event_registration(models.Model):
|
||||
def button_reg_cancel(self):
|
||||
self.state = 'cancel'
|
||||
|
||||
@api.one
|
||||
def mail_user(self):
|
||||
"""Send email to user with email_template when registration is done """
|
||||
if self.event_id.state == 'confirm' and self.event_id.email_confirmation_id:
|
||||
self.mail_user_confirm()
|
||||
else:
|
||||
template = self.event_id.email_registration_id
|
||||
if template:
|
||||
template.send_mail(self.id)
|
||||
|
||||
@api.one
|
||||
def mail_user_confirm(self):
|
||||
"""Send email to user when the event is confirmed """
|
||||
template = self.event_id.email_confirmation_id
|
||||
if template:
|
||||
template.send_mail(self.id)
|
||||
|
||||
@api.onchange('partner_id')
|
||||
def _onchange_partner(self):
|
||||
if self.partner_id:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- After installation of the module, open the related menu -->
|
||||
<record id="action_client_event_menu" model="ir.actions.client">
|
||||
<field name="name">Open Event Menu</field>
|
||||
@@ -21,11 +22,27 @@
|
||||
|
||||
<!-- notify all employees of module installation -->
|
||||
<function model="mail.group" name="message_post">
|
||||
<!-- ids, subject, body, parent_id=False, type='notification', content_subtype='html' -->
|
||||
<value eval="[ref('mail.group_all_employees')]"/>
|
||||
<value>From the top menu Events, you can organize events, manage registrations, automate communication around your event and sell events through your quotations.</value>
|
||||
<value>Module Events has been installed</value>
|
||||
</function>
|
||||
|
||||
<!-- Automatic confirmation of events by default -->
|
||||
<function id="default_auto_confirmation" model="ir.values" name="set_default" eval="('marketing.config.settings', 'auto_confirmation', True)"/>
|
||||
|
||||
<!-- Event Mail Scheduler-->
|
||||
<record model="ir.cron" forcecreate="True" id="event_mail_scheduler">
|
||||
<field name="name">[event] mail scheduler</field>
|
||||
<field name="active">True</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">hours</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field name="doall" eval="False" />
|
||||
<field eval="'()'" name="args"/>
|
||||
<field name="model">event.mail</field>
|
||||
<field name="function">run</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from openerp import api, fields, models, tools
|
||||
|
||||
|
||||
_INTERVALS = {
|
||||
'hours': lambda interval: relativedelta(hours=interval),
|
||||
'days': lambda interval: relativedelta(days=interval),
|
||||
'weeks': lambda interval: relativedelta(days=7*interval),
|
||||
'months': lambda interval: relativedelta(months=interval),
|
||||
'now': lambda interval: relativedelta(hours=0),
|
||||
}
|
||||
|
||||
|
||||
class EventMailScheduler(models.Model):
|
||||
""" Event automated mailing. This model replaces all existing fields and
|
||||
configuration allowing to send emails on events since Odoo 9. A cron exists
|
||||
that periodically checks for mailing to run. """
|
||||
_name = 'event.mail'
|
||||
|
||||
event_id = fields.Many2one('event.event', string='Event', required=True, readonly=True, ondelete='cascade')
|
||||
interval_nbr = fields.Integer('Timing', default=1)
|
||||
interval_unit = fields.Selection([
|
||||
('now', 'Immediately'),
|
||||
('hours', 'Hour(s)'), ('days', 'Day(s)'),
|
||||
('weeks', 'Week(s)'), ('months', 'Month(s)')],
|
||||
string='Unit', default='hours', required=True)
|
||||
interval_type = fields.Selection([
|
||||
('after_sub', 'After each subscription'),
|
||||
('before_event', 'Before the event'),
|
||||
('after_event', 'After the event')],
|
||||
string='When to Run ', default="before_event", required=True)
|
||||
template_id = fields.Many2one(
|
||||
'email.template', string='Email to Send',
|
||||
domain=[('model', '=', 'event.registration')], required=True, ondelete='restrict',
|
||||
help='This field contains the template of the mail that will be automatically sent')
|
||||
scheduled_date = fields.Datetime('Scheduled Sent Mail', compute='_compute_scheduled_date', store=True)
|
||||
mail_registration_ids = fields.One2many('event.mail.registration', 'scheduler_id')
|
||||
mail_sent = fields.Boolean('Mail Sent on Event')
|
||||
done = fields.Boolean('Sent', compute='_compute_done', store=True)
|
||||
|
||||
@api.one
|
||||
@api.depends('mail_sent', 'interval_type', 'event_id.registration_ids', 'mail_registration_ids')
|
||||
def _compute_done(self):
|
||||
if self.interval_type in ['before_event', 'after_event']:
|
||||
self.done = self.mail_sent
|
||||
else:
|
||||
self.done = len(self.mail_registration_ids) == len(self.event_id.registration_ids) and all(filter(lambda line: line.mail_sent, self.mail_registration_ids))
|
||||
|
||||
@api.one
|
||||
@api.depends('event_id.state', 'event_id.date_begin', 'interval_type', 'interval_unit', 'interval_nbr')
|
||||
def _compute_scheduled_date(self):
|
||||
if self.event_id.state not in ['confirm', 'done']:
|
||||
self.scheduled_date = False
|
||||
else:
|
||||
if self.interval_type == 'after_sub':
|
||||
date, sign = self.event_id.create_date, 1
|
||||
elif self.interval_type == 'before_event':
|
||||
date, sign = self.event_id.date_begin, -1
|
||||
else:
|
||||
date, sign = self.event_id.date_end, 1
|
||||
|
||||
self.scheduled_date = datetime.strptime(date, tools.DEFAULT_SERVER_DATETIME_FORMAT) + _INTERVALS[self.interval_unit](sign * self.interval_nbr)
|
||||
|
||||
@api.one
|
||||
def execute(self):
|
||||
if self.interval_type == 'after_sub':
|
||||
# update registration lines
|
||||
lines = []
|
||||
for registration in filter(lambda item: item not in [mail_reg.registration_id for mail_reg in self.mail_registration_ids], self.event_id.registration_ids):
|
||||
lines.append((0, 0, {'registration_id': registration.id}))
|
||||
if lines:
|
||||
self.write({'mail_registration_ids': lines})
|
||||
# execute scheduler on registrations
|
||||
self.mail_registration_ids.filtered(lambda reg: reg.scheduled_date and reg.scheduled_date <= datetime.strftime(fields.datetime.now(), tools.DEFAULT_SERVER_DATETIME_FORMAT)).execute()
|
||||
else:
|
||||
if not self.mail_sent:
|
||||
self.event_id.mail_attendees(self.template_id.id)
|
||||
self.write({'mail_sent': True})
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def run(self):
|
||||
schedulers = self.search([('done', '=', False), ('scheduled_date', '<=', datetime.strftime(fields.datetime.now(), tools.DEFAULT_SERVER_DATETIME_FORMAT))])
|
||||
return schedulers.execute()
|
||||
|
||||
|
||||
class EventMailRegistration(models.Model):
|
||||
_name = 'event.mail.registration'
|
||||
_description = 'Registration Mail Scheduler'
|
||||
_rec_name = 'scheduler_id'
|
||||
_order = 'scheduled_date DESC'
|
||||
|
||||
scheduler_id = fields.Many2one('event.mail', 'Mail Scheduler', required=True, ondelete='cascade')
|
||||
registration_id = fields.Many2one('event.registration', 'Attendee', required=True, ondelete='cascade')
|
||||
scheduled_date = fields.Datetime('Scheduled Time', compute='_compute_scheduled_date', store=True)
|
||||
mail_sent = fields.Boolean('Mail Sent')
|
||||
|
||||
@api.one
|
||||
def execute(self):
|
||||
if self.registration_id.state in ['open', 'done'] and not self.mail_sent:
|
||||
self.scheduler_id.template_id.send_mail(self.registration_id.id)
|
||||
self.write({'mail_sent': True})
|
||||
|
||||
@api.one
|
||||
@api.depends('registration_id', 'scheduler_id.interval_unit', 'scheduler_id.interval_type')
|
||||
def _compute_scheduled_date(self):
|
||||
self.scheduled_date = datetime.strptime(self.registration_id.date_open, tools.DEFAULT_SERVER_DATETIME_FORMAT) + _INTERVALS[self.scheduler_id.interval_unit](self.scheduler_id.interval_nbr)
|
||||
@@ -16,9 +16,7 @@
|
||||
<field name="name"/>
|
||||
<field name="default_reply_to"/>
|
||||
<field name="default_registration_min"/>
|
||||
<field name="default_email_event" domain="[('model_id.model','=','event.registration')]"/>
|
||||
<field name="default_registration_max"/>
|
||||
<field name="default_email_registration" domain="[('model_id.model','=','event.registration')]"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
@@ -103,12 +101,17 @@
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string='Event Details' groups="base.group_no_one">
|
||||
<group colspan="4">
|
||||
<field name="reply_to"/>
|
||||
<field name="email_registration_id"/>
|
||||
<field name="email_confirmation_id"/>
|
||||
</group>
|
||||
<page string="Email Schedule">
|
||||
<field name="reply_to"/>
|
||||
<field name="event_mail_ids">
|
||||
<tree string="Email Schedule" editable="bottom">
|
||||
<field name="template_id" />
|
||||
<field name="interval_nbr"/>
|
||||
<field name="interval_unit"/>
|
||||
<field name="interval_type"/>
|
||||
<field name="done"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
@@ -294,7 +297,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Registration">
|
||||
<header>
|
||||
<button name="registration_open" string="Confirm" states="draft" type="object" class="oe_highlight"/>
|
||||
<button name="confirm_registration" string="Confirm" states="draft" type="object" class="oe_highlight"/>
|
||||
<button name="button_reg_close" string="Attended" states="open" type="object" class="oe_highlight"/>
|
||||
<button string="Set To Unconfirmed" name="do_draft" states="cancel,done" type="object" />
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object"/>
|
||||
@@ -382,5 +385,59 @@
|
||||
id="menu_action_registration" parent="event.event_main_menu"
|
||||
action="action_registration" groups="event.group_event_manager,event.group_event_user"/>
|
||||
|
||||
<!-- EVENT.MAIL VIEWS -->
|
||||
<record model="ir.ui.view" id="view_event_mail_form">
|
||||
<field name="name">event.mail.form</field>
|
||||
<field name="model">event.mail</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Mail Scheduler">
|
||||
<group>
|
||||
<field name="event_id"/>
|
||||
<field name="template_id"/>
|
||||
<field name="mail_sent"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="interval_nbr"/>
|
||||
<field name="interval_unit"/>
|
||||
<field name="interval_type"/>
|
||||
<field name="scheduled_date"/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Registration Mails">
|
||||
<field name="mail_registration_ids">
|
||||
<tree string="Registration mail" editable="bottom">
|
||||
<field name="registration_id"/>
|
||||
<field name="scheduled_date"/>
|
||||
<field name="mail_sent"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_mail_tree">
|
||||
<field name="name">event.mail.tree</field>
|
||||
<field name="model">event.mail</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Event Mail Schedulers">
|
||||
<field name="event_id"/>
|
||||
<field name="template_id"/>
|
||||
<field name="scheduled_date"/>
|
||||
<field name="mail_sent"/>
|
||||
<field name="done"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_event_mail">
|
||||
<field name="name">Events Mail Schedulers</field>
|
||||
<field name="res_model">event.mail</field>
|
||||
<field name="view_type">form</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Events Mail Schedulers" id="menu_event_type" action="action_event_mail" parent="event.event_configuration" groups="base.group_no_one"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -5,4 +5,8 @@ access_event_event,event.event,model_event_event,event.group_event_user,1,1,1,1
|
||||
access_event_registration,event.registration,model_event_registration,event.group_event_user,1,1,1,1
|
||||
access_report_event_registration,report.event.registration,model_report_event_registration,event.group_event_user,1,1,1,1
|
||||
access_event_event_portal,event.event,model_event_event,,1,0,0,0
|
||||
access_event_registration_portal,event.registration,model_event_registration,,1,0,0,0
|
||||
access_event_registration_portal,event.registration,model_event_registration,,1,0,0,0
|
||||
access_event_mail,event.mail,model_event_mail,event.group_event_user,1,0,0,0
|
||||
access_event_mail_manager,event.mail manager,model_event_mail,event.group_event_manager,1,1,1,1
|
||||
access_event_mail_registration,event.mail.registration,model_event_mail_registration,event.group_event_user,1,0,0,0
|
||||
access_event_mail_registration_manager,event.mail.registration.manager,model_event_mail_registration,event.group_event_manager,1,1,1,1
|
||||
|
@@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.addons.event.tests import test_event_flow
|
||||
from openerp.addons.event.tests import test_event_flow, test_mail_schedule
|
||||
|
||||
checks = [
|
||||
test_event_flow,
|
||||
test_mail_schedule,
|
||||
]
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from openerp import fields
|
||||
from openerp.tests import common
|
||||
|
||||
|
||||
@@ -12,6 +15,7 @@ class TestEventCommon(common.TransactionCase):
|
||||
self.Users = self.env['res.users']
|
||||
self.Event = self.env['event.event']
|
||||
self.Registration = self.env['event.registration']
|
||||
self.EventMail = self.env['event.mail']
|
||||
|
||||
# User groups
|
||||
self.group_employee_id = self.env['ir.model.data'].xmlid_to_res_id('base.group_user')
|
||||
|
||||
@@ -16,7 +16,7 @@ class TestEventFlow(TestEventCommon):
|
||||
self.env['ir.values'].set_default('marketing.config.settings', 'auto_confirmation', True)
|
||||
|
||||
# EventUser creates a new event: ok
|
||||
test_event = self.Event.sudo(self.user_eventuser).create({
|
||||
test_event = self.Event.sudo(self.user_eventmanager).create({
|
||||
'name': 'TestEvent',
|
||||
'date_begin': datetime.datetime.now() + relativedelta(days=-1),
|
||||
'date_end': datetime.datetime.now() + relativedelta(days=1),
|
||||
@@ -68,7 +68,7 @@ class TestEventFlow(TestEventCommon):
|
||||
self.env['ir.values'].set_default('marketing.config.settings', 'auto_confirmation', False)
|
||||
|
||||
# EventUser creates a new event: ok
|
||||
test_event = self.Event.sudo(self.user_eventuser).create({
|
||||
test_event = self.Event.sudo(self.user_eventmanager).create({
|
||||
'name': 'TestEvent',
|
||||
'date_begin': datetime.datetime.now() + relativedelta(days=-1),
|
||||
'date_end': datetime.datetime.now() + relativedelta(days=1),
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from openerp import fields, tools
|
||||
from openerp.addons.event.tests.common import TestEventCommon
|
||||
from openerp.tools import mute_logger
|
||||
|
||||
|
||||
class TestMailSchedule(TestEventCommon):
|
||||
|
||||
@mute_logger('openerp.addons.base.ir.ir_model', 'openerp.models')
|
||||
def test_00_event_mail_schedule(self):
|
||||
""" Test mail scheduling for events """
|
||||
self.env['ir.values'].set_default('marketing.config.settings', 'auto_confirmation', True)
|
||||
now = fields.datetime.now()
|
||||
event_date_begin = now + relativedelta(days=1)
|
||||
event_date_end = now + relativedelta(days=3)
|
||||
|
||||
test_event = self.Event.sudo(self.user_eventmanager).create({
|
||||
'name': 'TestEventMail',
|
||||
'date_begin': event_date_begin,
|
||||
'date_end': event_date_end,
|
||||
'seats_max': 10,
|
||||
'event_mail_ids': [
|
||||
(0, 0, { # right at subscription
|
||||
'interval_unit': 'now',
|
||||
'interval_type': 'after_sub',
|
||||
'template_id': self.env['ir.model.data'].xmlid_to_res_id('event.event_subscription')}),
|
||||
(0, 0, { # 2 days before event
|
||||
'interval_nbr': 2,
|
||||
'interval_unit': 'days',
|
||||
'interval_type': 'before_event',
|
||||
'template_id': self.env['ir.model.data'].xmlid_to_res_id('event.event_reminder')}),
|
||||
]
|
||||
})
|
||||
|
||||
# create some registrations
|
||||
self.Registration.sudo(self.user_eventuser).create({
|
||||
'event_id': test_event.id,
|
||||
'name': 'Reg0',
|
||||
'email': 'reg0@example.com',
|
||||
})
|
||||
self.Registration.sudo(self.user_eventuser).create({
|
||||
'event_id': test_event.id,
|
||||
'name': 'Reg1',
|
||||
'email': 'reg1@example.com',
|
||||
})
|
||||
|
||||
# check before event scheduler
|
||||
schedulers = self.EventMail.search([('event_id', '=', test_event.id), ('interval_type', '=', 'before_event')])
|
||||
self.assertEqual(len(schedulers), 1, 'event: wrong scheduler creation')
|
||||
self.assertEqual(schedulers[0].scheduled_date, datetime.datetime.strftime(event_date_begin + relativedelta(days=-2), tools.DEFAULT_SERVER_DATETIME_FORMAT), 'event: incorrect scheduled date')
|
||||
|
||||
# execute event reminder scheduler
|
||||
schedulers[0].execute()
|
||||
|
||||
self.assertTrue(schedulers[0].mail_sent, 'event: reminder scheduler should have sent an email')
|
||||
self.assertTrue(schedulers[0].done, 'event: reminder scheduler should be done')
|
||||
|
||||
mails = self.env['mail.mail'].search([('subject', 'ilike', 'reminder'), ('date', '>=', datetime.datetime.strftime(now, tools.DEFAULT_SERVER_DATETIME_FORMAT))], order='date DESC', limit=3)
|
||||
self.assertEqual(len(mails), 2, 'event: wrong number of reminder mail sent')
|
||||
|
||||
# check subscription scheduler
|
||||
schedulers = self.EventMail.search([('event_id', '=', test_event.id), ('interval_type', '=', 'after_sub')])
|
||||
self.assertEqual(len(schedulers), 1, 'event: wrong scheduler creation')
|
||||
self.assertEqual(schedulers[0].scheduled_date, test_event.create_date, 'event: incorrect scheduled date for checking controller')
|
||||
|
||||
# execute subscription scheduler
|
||||
schedulers[0].execute()
|
||||
self.assertEqual(len(schedulers[0].mail_registration_ids), 2, 'event: incorrect number of mail scheduled date')
|
||||
|
||||
mails = self.env['mail.mail'].search([('subject', 'ilike', 'subscription'), ('date', '>=', datetime.datetime.strftime(now, tools.DEFAULT_SERVER_DATETIME_FORMAT))], order='date DESC', limit=3)
|
||||
self.assertEqual(len(mails), 2, 'event: wrong number of subscription mail sent')
|
||||
|
||||
for registration in schedulers[0].mail_registration_ids:
|
||||
self.assertTrue(registration.mail_sent, 'event: wrongly confirmed mailing on subscription')
|
||||
@@ -145,7 +145,7 @@
|
||||
</record>
|
||||
|
||||
<record model="res.groups" id="group_multi_currency">
|
||||
<field name="category_id" ref="module_category_hidden"/>
|
||||
<field name="category_id" ref="module_category_usability"/>
|
||||
</record>
|
||||
|
||||
<record model="res.groups" id="group_no_one">
|
||||
|
||||
Reference in New Issue
Block a user