diff options
| author | Mahendra barad <mba@openerp.com> | 2014-08-11 19:08:37 +0530 |
|---|---|---|
| committer | Thibault Delavallée <tde@openerp.com> | 2014-10-17 16:48:29 +0200 |
| commit | ad48bf6d7d7f3c1678b0cd2d55fe64163ad10c38 (patch) | |
| tree | c4e46963793ed04cda930503aac9ce56aca318d5 /addons | |
| parent | fd54df5c7cb4fe2fd606baef347b23ee911f0e2f (diff) | |
[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.
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/event/__init__.py | 1 | ||||
| -rw-r--r-- | addons/event/email_template.xml | 79 | ||||
| -rw-r--r-- | addons/event/event.py | 102 | ||||
| -rw-r--r-- | addons/event/event_data.xml | 19 | ||||
| -rw-r--r-- | addons/event/event_mail.py | 111 | ||||
| -rw-r--r-- | addons/event/event_view.xml | 75 | ||||
| -rw-r--r-- | addons/event/security/ir.model.access.csv | 6 | ||||
| -rw-r--r-- | addons/event/tests/__init__.py | 3 | ||||
| -rw-r--r-- | addons/event/tests/common.py | 4 | ||||
| -rw-r--r-- | addons/event/tests/test_event_flow.py | 4 | ||||
| -rw-r--r-- | addons/event/tests/test_mail_schedule.py | 78 |
11 files changed, 354 insertions, 128 deletions
diff --git a/addons/event/__init__.py b/addons/event/__init__.py index 9e0115a7300..bf40e48d681 100644 --- a/addons/event/__init__.py +++ b/addons/event/__init__.py @@ -20,6 +20,7 @@ ############################################################################## import event +import event_mail import wizard import report import res_config diff --git a/addons/event/email_template.xml b/addons/event/email_template.xml index d4479bcfc87..4a561d38e72 100644 --- a/addons/event/email_template.xml +++ b/addons/event/email_template.xml @@ -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> - </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_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> - <!-- 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 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> - <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> diff --git a/addons/event/event.py b/addons/event/event.py index 5fded7e15c9..603886906e2 100644 --- a/addons/event/event.py +++ b/addons/event/event.py @@ -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 @@ -237,26 +223,15 @@ class event_event(models.Model): 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): @@ -332,12 +311,6 @@ class event_registration(models.Model): 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 """ today = fields.Datetime.now() @@ -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: diff --git a/addons/event/event_data.xml b/addons/event/event_data.xml index 823d6428993..2419132f409 100644 --- a/addons/event/event_data.xml +++ b/addons/event/event_data.xml @@ -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> diff --git a/addons/event/event_mail.py b/addons/event/event_mail.py new file mode 100644 index 00000000000..ea4a9a81e93 --- /dev/null +++ b/addons/event/event_mail.py @@ -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) diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml index 9371dbe25e9..0991c4bb7af 100644 --- a/addons/event/event_view.xml +++ b/addons/event/event_view.xml @@ -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> diff --git a/addons/event/security/ir.model.access.csv b/addons/event/security/ir.model.access.csv index 1d803796007..8801c173f17 100644 --- a/addons/event/security/ir.model.access.csv +++ b/addons/event/security/ir.model.access.csv @@ -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
\ No newline at end of file +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
\ No newline at end of file diff --git a/addons/event/tests/__init__.py b/addons/event/tests/__init__.py index d1ddc66c11c..abcc4a3ca2b 100644 --- a/addons/event/tests/__init__.py +++ b/addons/event/tests/__init__.py @@ -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, ] diff --git a/addons/event/tests/common.py b/addons/event/tests/common.py index bcf0a1e5df0..1b59c662da6 100644 --- a/addons/event/tests/common.py +++ b/addons/event/tests/common.py @@ -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') diff --git a/addons/event/tests/test_event_flow.py b/addons/event/tests/test_event_flow.py index 3af0fb9185c..ed5219d4d0a 100644 --- a/addons/event/tests/test_event_flow.py +++ b/addons/event/tests/test_event_flow.py @@ -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), diff --git a/addons/event/tests/test_mail_schedule.py b/addons/event/tests/test_mail_schedule.py new file mode 100644 index 00000000000..752403ed22b --- /dev/null +++ b/addons/event/tests/test_mail_schedule.py @@ -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') |
