[MERGE] event: ease event configuration and use of tracks
This merge proposes to ease the use and configuration of events as well as the use of event tracks and track proposals. This is done through two main modifications * first one aims at improving event categories so that they can be used as configuration for events. Categories can now define default values for automated mailing, ticketing, location management, questions to attendees, ... Preconfigured data for event categories are added to help user having finely-tuned events; * second one aims at improve event track model. Tracks now use dynamic stages with automated mailing, as well as kanban state, activities and all common chatter features.
This commit is contained in:
@@ -23,14 +23,13 @@ Key Features
|
||||
'security/ir.model.access.csv',
|
||||
'wizard/event_confirm_view.xml',
|
||||
'views/event_views.xml',
|
||||
'report/report_event_registration_view.xml',
|
||||
'report/event_event_templates.xml',
|
||||
'report/event_event_reports.xml',
|
||||
'data/email_template_data.xml',
|
||||
'data/event_data.xml',
|
||||
'views/event_config_settings_views.xml',
|
||||
'views/event_templates.xml',
|
||||
'views/res_partner_views.xml',
|
||||
'data/email_template_data.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/event_demo.xml',
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
<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="('event.config.settings', 'default_auto_confirmation', True)"/>
|
||||
|
||||
<!-- Event Mail Scheduler-->
|
||||
<record model="ir.cron" forcecreate="True" id="event_mail_scheduler">
|
||||
<field name="name">Event: Mail Scheduler</field>
|
||||
@@ -24,5 +21,18 @@
|
||||
<field name="doall" eval="False" />
|
||||
</record>
|
||||
|
||||
<record id="event_type_data_online" model="event.type">
|
||||
<field name="name">Online</field>
|
||||
<field name="is_online" eval="True"/>
|
||||
<field name="auto_confirm" eval="True"/>
|
||||
<field name="use_mail_schedule" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="event_type_data_physical" model="event.type">
|
||||
<field name="name">Physical Event</field>
|
||||
<field name="is_online" eval="False"/>
|
||||
<field name="auto_confirm" eval="True"/>
|
||||
<field name="use_mail_schedule" eval="False"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
+167
-112
@@ -11,51 +11,11 @@ from dateutil.relativedelta import relativedelta
|
||||
|
||||
|
||||
class EventType(models.Model):
|
||||
""" Event Type """
|
||||
_name = 'event.type'
|
||||
_description = 'Event Type'
|
||||
|
||||
name = fields.Char('Event Type', required=True, translate=True)
|
||||
default_reply_to = fields.Char('Reply To')
|
||||
default_registration_min = fields.Integer(
|
||||
'Default Minimum Registration', default=0,
|
||||
help="It will select this default minimum value when you choose this event")
|
||||
default_registration_max = fields.Integer(
|
||||
'Default Maximum Registration', default=0,
|
||||
help="It will select this default maximum value when you choose this event")
|
||||
|
||||
|
||||
class EventEvent(models.Model):
|
||||
"""Event"""
|
||||
_name = 'event.event'
|
||||
_description = 'Event'
|
||||
_inherit = ['mail.thread']
|
||||
_order = 'date_begin'
|
||||
|
||||
name = fields.Char(
|
||||
string='Event Name', translate=True, required=True,
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
active = fields.Boolean(default=True, track_visibility="onchange")
|
||||
user_id = fields.Many2one(
|
||||
'res.users', string='Responsible',
|
||||
default=lambda self: self.env.user,
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
company_id = fields.Many2one(
|
||||
'res.company', string='Company', change_default=True,
|
||||
default=lambda self: self.env['res.company']._company_default_get('event.event'),
|
||||
required=False, readonly=False, states={'done': [('readonly', True)]})
|
||||
organizer_id = fields.Many2one(
|
||||
'res.partner', string='Organizer',
|
||||
default=lambda self: self.env.user.company_id.partner_id)
|
||||
event_type_id = fields.Many2one(
|
||||
'event.type', string='Category',
|
||||
readonly=False, states={'done': [('readonly', True)]},
|
||||
oldname='type')
|
||||
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(), copy=True)
|
||||
_description = 'Event Category'
|
||||
|
||||
@api.model
|
||||
def _default_event_mail_ids(self):
|
||||
def _get_default_event_type_mail_ids(self):
|
||||
return [(0, 0, {
|
||||
'interval_unit': 'now',
|
||||
'interval_type': 'after_sub',
|
||||
@@ -72,6 +32,81 @@ class EventEvent(models.Model):
|
||||
'template_id': self.env.ref('event.event_reminder')
|
||||
})]
|
||||
|
||||
name = fields.Char('Event Category', required=True, translate=True)
|
||||
# registration
|
||||
has_seats_limitation = fields.Boolean(
|
||||
'Limited Seats', default=False)
|
||||
default_registration_min = fields.Integer(
|
||||
'Minimum Registrations', default=0,
|
||||
help="It will select this default minimum value when you choose this event")
|
||||
default_registration_max = fields.Integer(
|
||||
'Maximum Registrations', default=0,
|
||||
help="It will select this default maximum value when you choose this event")
|
||||
auto_confirm = fields.Boolean(
|
||||
'Automatically Confirm Registrations', default=True,
|
||||
help="Events and registrations will automatically be confirmed"
|
||||
"upon creation, easing the flow for simple events.")
|
||||
# location
|
||||
is_online = fields.Boolean(
|
||||
'Online Event', help='Online events like webinars do not require a specific location and are hosted online.')
|
||||
use_timezone = fields.Boolean('Use Default Timezone')
|
||||
default_timezone = fields.Selection(
|
||||
'_tz_get', string='Timezone',
|
||||
default=lambda self: self.env.user.tz)
|
||||
# communication
|
||||
use_reply_to = fields.Boolean('Use Default Reply-To')
|
||||
default_reply_to = fields.Char('Reply To')
|
||||
use_hashtag = fields.Boolean('Use Default Hashtag')
|
||||
default_hashtag = fields.Char('Twitter Hashtag')
|
||||
use_mail_schedule = fields.Boolean(
|
||||
'Automatically Send Emails', default=True)
|
||||
event_type_mail_ids = fields.One2many(
|
||||
'event.type.mail', 'event_type_id', string='Mail Schedule',
|
||||
copy=False,
|
||||
default=_get_default_event_type_mail_ids)
|
||||
|
||||
@api.onchange('has_seats_limitation')
|
||||
def _onchange_has_seats_limitation(self):
|
||||
if not self.has_seats_limitation:
|
||||
self.default_registration_min = 0
|
||||
self.default_registration_max = 0
|
||||
|
||||
@api.model
|
||||
def _tz_get(self):
|
||||
return [(x, x) for x in pytz.all_timezones]
|
||||
|
||||
|
||||
class EventEvent(models.Model):
|
||||
"""Event"""
|
||||
_name = 'event.event'
|
||||
_description = 'Event'
|
||||
_inherit = ['mail.thread']
|
||||
_order = 'date_begin'
|
||||
|
||||
name = fields.Char(
|
||||
string='Event Name', translate=True, required=True,
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
active = fields.Boolean(default=True)
|
||||
user_id = fields.Many2one(
|
||||
'res.users', string='Responsible',
|
||||
default=lambda self: self.env.user,
|
||||
track_visibility="onchange",
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
company_id = fields.Many2one(
|
||||
'res.company', string='Company', change_default=True,
|
||||
default=lambda self: self.env['res.company']._company_default_get('event.event'),
|
||||
required=False, readonly=False, states={'done': [('readonly', True)]})
|
||||
organizer_id = fields.Many2one(
|
||||
'res.partner', string='Organizer',
|
||||
track_visibility="onchange",
|
||||
default=lambda self: self.env.user.company_id.partner_id)
|
||||
event_type_id = fields.Many2one(
|
||||
'event.type', string='Category',
|
||||
readonly=False, states={'done': [('readonly', True)]},
|
||||
oldname='type')
|
||||
color = fields.Integer('Kanban Color Index')
|
||||
event_mail_ids = fields.One2many('event.mail', 'event_id', string='Mail Schedule', copy=True)
|
||||
|
||||
# Seats and computation
|
||||
seats_max = fields.Integer(
|
||||
string='Maximum Attendees Number', oldname='register_max',
|
||||
@@ -99,6 +134,48 @@ class EventEvent(models.Model):
|
||||
string='Number of Expected Attendees',
|
||||
readonly=True, compute='_compute_seats')
|
||||
|
||||
# Registration fields
|
||||
registration_ids = fields.One2many(
|
||||
'event.registration', 'event_id', string='Attendees',
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
# Date fields
|
||||
date_tz = fields.Selection('_tz_get', string='Timezone', required=True, default=lambda self: self.env.user.tz)
|
||||
date_begin = fields.Datetime(
|
||||
string='Start Date', required=True,
|
||||
track_visibility='onchange', states={'done': [('readonly', True)]})
|
||||
date_end = fields.Datetime(
|
||||
string='End Date', required=True,
|
||||
track_visibility='onchange', states={'done': [('readonly', True)]})
|
||||
date_begin_located = fields.Char(string='Start Date Located', compute='_compute_date_begin_tz')
|
||||
date_end_located = fields.Char(string='End Date Located', compute='_compute_date_end_tz')
|
||||
|
||||
state = fields.Selection([
|
||||
('draft', 'Unconfirmed'), ('cancel', 'Cancelled'),
|
||||
('confirm', 'Confirmed'), ('done', 'Done')],
|
||||
string='Status', default='draft', readonly=True, required=True, copy=False,
|
||||
help="If event is created, the status is 'Draft'. If event is confirmed for the particular dates the status is set to 'Confirmed'. If the event is over, the status is set to 'Done'. If event is cancelled the status is set to 'Cancelled'.")
|
||||
auto_confirm = fields.Boolean(string='Autoconfirm Registrations')
|
||||
reply_to = fields.Char(
|
||||
'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.")
|
||||
is_online = fields.Boolean('Online Event')
|
||||
address_id = fields.Many2one(
|
||||
'res.partner', string='Location',
|
||||
default=lambda self: self.env.user.company_id.partner_id,
|
||||
readonly=False, states={'done': [('readonly', True)]},
|
||||
track_visibility="onchange")
|
||||
country_id = fields.Many2one('res.country', 'Country', related='address_id.country_id', store=True)
|
||||
twitter_hashtag = fields.Char('Twitter Hashtag')
|
||||
description = fields.Html(
|
||||
string='Description', oldname='note', translate=html_translate, sanitize_attributes=False,
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
# badge fields
|
||||
badge_front = fields.Html(string='Badge Front')
|
||||
badge_back = fields.Html(string='Badge Back')
|
||||
badge_innerleft = fields.Html(string='Badge Inner Left')
|
||||
badge_innerright = fields.Html(string='Badge Inner Right')
|
||||
event_logo = fields.Html(string='Event Logo')
|
||||
|
||||
@api.multi
|
||||
@api.depends('seats_max', 'registration_ids.state')
|
||||
def _compute_seats(self):
|
||||
@@ -128,21 +205,6 @@ class EventEvent(models.Model):
|
||||
event.seats_available = event.seats_max - (event.seats_reserved + event.seats_used)
|
||||
event.seats_expected = event.seats_unconfirmed + event.seats_reserved + event.seats_used
|
||||
|
||||
# Registration fields
|
||||
registration_ids = fields.One2many(
|
||||
'event.registration', 'event_id', string='Attendees',
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
# Date fields
|
||||
date_tz = fields.Selection('_tz_get', string='Timezone', required=True, default=lambda self: self.env.user.tz)
|
||||
date_begin = fields.Datetime(
|
||||
string='Start Date', required=True,
|
||||
track_visibility='onchange', states={'done': [('readonly', True)]})
|
||||
date_end = fields.Datetime(
|
||||
string='End Date', required=True,
|
||||
track_visibility='onchange', states={'done': [('readonly', True)]})
|
||||
date_begin_located = fields.Char(string='Start Date Located', compute='_compute_date_begin_tz')
|
||||
date_end_located = fields.Char(string='End Date Located', compute='_compute_date_end_tz')
|
||||
|
||||
@api.model
|
||||
def _tz_get(self):
|
||||
return [(x, x) for x in pytz.all_timezones]
|
||||
@@ -163,33 +225,51 @@ class EventEvent(models.Model):
|
||||
else:
|
||||
self.date_end_located = False
|
||||
|
||||
state = fields.Selection([
|
||||
('draft', 'Unconfirmed'), ('cancel', 'Cancelled'),
|
||||
('confirm', 'Confirmed'), ('done', 'Done')],
|
||||
string='Status', default='draft', readonly=True, required=True, copy=False,
|
||||
help="If event is created, the status is 'Draft'. If event is confirmed for the particular dates the status is set to 'Confirmed'. If the event is over, the status is set to 'Done'. If event is cancelled the status is set to 'Cancelled'.")
|
||||
auto_confirm = fields.Boolean(string='Confirmation not required', compute='_compute_auto_confirm')
|
||||
@api.onchange('event_type_id')
|
||||
def _onchange_type(self):
|
||||
if self.event_type_id:
|
||||
self.seats_min = self.event_type_id.default_registration_min
|
||||
self.seats_max = self.event_type_id.default_registration_max
|
||||
if self.event_type_id.default_registration_max:
|
||||
self.seats_availability = 'limited'
|
||||
|
||||
if self.event_type_id.auto_confirm:
|
||||
self.auto_confirm = self.event_type_id.auto_confirm
|
||||
|
||||
if self.event_type_id.use_reply_to:
|
||||
self.reply_to = self.event_type_id.default_reply_to
|
||||
|
||||
if self.event_type_id.use_reply_to:
|
||||
self.twitter_hashtag = self.event_type_id.default_hashtag
|
||||
|
||||
if self.event_type_id.use_timezone:
|
||||
self.date_tz = self.event_type_id.default_timezone
|
||||
|
||||
self.is_online = self.event_type_id.is_online
|
||||
|
||||
if self.event_type_id.event_type_mail_ids:
|
||||
self.event_mail_ids = [(5, 0, 0)] + [{
|
||||
'template_id': line.template_id,
|
||||
'interval_nbr': line.interval_nbr,
|
||||
'interval_unit': line.interval_unit,
|
||||
'interval_type': line.interval_type}
|
||||
for line in self.event_type_id.event_type_mail_ids]
|
||||
|
||||
@api.constrains('seats_min', 'seats_max', 'seats_availability')
|
||||
def _check_seats_min_max(self):
|
||||
if any(event.seats_availability == 'limited' and event.seats_min > event.seats_max for event in self):
|
||||
raise ValidationError(_('Maximum attendees number should be greater than minimum attendees number.'))
|
||||
|
||||
@api.constrains('seats_max', 'seats_available')
|
||||
def _check_seats_limit(self):
|
||||
if any(event.seats_availability == 'limited' and event.seats_max and event.seats_available < 0 for event in self):
|
||||
raise ValidationError(_('No more available seats.'))
|
||||
|
||||
@api.one
|
||||
def _compute_auto_confirm(self):
|
||||
self.auto_confirm = self.env['ir.values'].get_default('event.config.settings', 'default_auto_confirmation')
|
||||
|
||||
reply_to = fields.Char(
|
||||
'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', 'Country', related='address_id.country_id', store=True)
|
||||
description = fields.Html(
|
||||
string='Description', oldname='note', translate=html_translate, sanitize_attributes=False,
|
||||
readonly=False, states={'done': [('readonly', True)]})
|
||||
# badge fields
|
||||
badge_front = fields.Html(string='Badge Front')
|
||||
badge_back = fields.Html(string='Badge Back')
|
||||
badge_innerleft = fields.Html(string='Badge Inner Left')
|
||||
badge_innerright = fields.Html(string='Badge Inner Right')
|
||||
event_logo = fields.Html(string='Event Logo')
|
||||
@api.constrains('date_begin', 'date_end')
|
||||
def _check_closing_date(self):
|
||||
if self.date_end < self.date_begin:
|
||||
raise ValidationError(_('Closing Date cannot be set before Beginning Date.'))
|
||||
|
||||
@api.multi
|
||||
@api.depends('name', 'date_begin', 'date_end')
|
||||
@@ -203,18 +283,6 @@ class EventEvent(models.Model):
|
||||
result.append((event.id, '%s (%s)' % (event.name, ' - '.join(dates))))
|
||||
return result
|
||||
|
||||
@api.one
|
||||
@api.constrains('seats_max', 'seats_available')
|
||||
def _check_seats_limit(self):
|
||||
if self.seats_availability == 'limited' and self.seats_max and self.seats_available < 0:
|
||||
raise ValidationError(_('No more available seats.'))
|
||||
|
||||
@api.one
|
||||
@api.constrains('date_begin', 'date_end')
|
||||
def _check_closing_date(self):
|
||||
if self.date_end < self.date_begin:
|
||||
raise ValidationError(_('Closing Date cannot be set before Beginning Date.'))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(EventEvent, self).create(vals)
|
||||
@@ -251,22 +319,6 @@ class EventEvent(models.Model):
|
||||
def button_confirm(self):
|
||||
self.state = 'confirm'
|
||||
|
||||
@api.onchange('event_type_id')
|
||||
def _onchange_type(self):
|
||||
if self.event_type_id:
|
||||
self.seats_min = self.event_type_id.default_registration_min
|
||||
self.seats_max = self.event_type_id.default_registration_max
|
||||
self.reply_to = self.event_type_id.default_reply_to
|
||||
|
||||
@api.multi
|
||||
def action_event_registration_report(self):
|
||||
res = self.env['ir.actions.act_window'].for_xml_id('event', 'action_report_event_registration')
|
||||
res['context'] = {
|
||||
"search_default_event_id": self.id,
|
||||
"group_by": ['create_date:day'],
|
||||
}
|
||||
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):
|
||||
@@ -278,6 +330,7 @@ class EventRegistration(models.Model):
|
||||
_description = 'Attendee'
|
||||
_inherit = ['mail.thread']
|
||||
_order = 'name, create_date desc'
|
||||
_mail_mass_mailing = _('Event Attendees')
|
||||
|
||||
origin = fields.Char(
|
||||
string='Source Document', readonly=True,
|
||||
@@ -361,10 +414,12 @@ class EventRegistration(models.Model):
|
||||
def button_reg_close(self):
|
||||
""" Close Registration """
|
||||
today = fields.Datetime.now()
|
||||
if self.event_id.date_begin <= today:
|
||||
if self.event_id.date_begin <= today and self.event_id.state == 'confirm':
|
||||
self.write({'state': 'done', 'date_closed': today})
|
||||
elif self.event_id.state == 'draft':
|
||||
raise UserError(_("You must wait the event confirmation before doing this action."))
|
||||
else:
|
||||
raise UserError(_("You must wait for the starting day of the event to do this action."))
|
||||
raise UserError(_("You must wait the event starting day before doing this action."))
|
||||
|
||||
@api.one
|
||||
def button_reg_cancel(self):
|
||||
|
||||
@@ -9,7 +9,6 @@ class event_config_settings(models.TransientModel):
|
||||
module_event_sale = fields.Boolean("Tickets")
|
||||
module_website_event_track = fields.Boolean("Tracks and Agenda")
|
||||
module_website_event_questions = fields.Boolean("Registration Survey")
|
||||
default_auto_confirmation = fields.Boolean("Auto Confirmation", default_model='event.config.settings')
|
||||
module_event_barcode = fields.Boolean("Barcode")
|
||||
module_website_event = fields.Boolean("Online Events")
|
||||
module_website_event_sale = fields.Boolean("Online Ticketing")
|
||||
|
||||
@@ -15,11 +15,39 @@ _INTERVALS = {
|
||||
}
|
||||
|
||||
|
||||
class EventTypeMail(models.Model):
|
||||
""" Template of event.mail to attach to event.type. Those will be copied
|
||||
upon all events created in that type to ease event creation. """
|
||||
_name = 'event.type.mail'
|
||||
_description = 'Mail Scheduling on Event Type'
|
||||
|
||||
event_type_id = fields.Many2one(
|
||||
'event.type', string='Event Type',
|
||||
ondelete='cascade', required=True)
|
||||
interval_nbr = fields.Integer('Interval', 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 registration'),
|
||||
('before_event', 'Before the event'),
|
||||
('after_event', 'After the event')],
|
||||
string='Trigger', default="before_event", required=True)
|
||||
template_id = fields.Many2one(
|
||||
'mail.template', string='Email Template',
|
||||
domain=[('model', '=', 'event.registration')], required=True, ondelete='restrict',
|
||||
help='This field contains the template of the mail that will be automatically sent')
|
||||
|
||||
|
||||
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'
|
||||
_rec_name = 'event_id'
|
||||
_description = 'Event Automated Mailing'
|
||||
|
||||
event_id = fields.Many2one('event.event', string='Event', required=True, ondelete='cascade')
|
||||
sequence = fields.Integer('Display order')
|
||||
@@ -33,9 +61,9 @@ class EventMailScheduler(models.Model):
|
||||
('after_sub', 'After each registration'),
|
||||
('before_event', 'Before the event'),
|
||||
('after_event', 'After the event')],
|
||||
string='When to Run ', default="before_event", required=True)
|
||||
string='Trigger ', default="before_event", required=True)
|
||||
template_id = fields.Many2one(
|
||||
'mail.template', string='Email to Send',
|
||||
'mail.template', string='Email Template',
|
||||
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)
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import report_event_registration
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, models, fields
|
||||
from odoo import tools
|
||||
|
||||
|
||||
class ReportEventRegistration(models.Model):
|
||||
"""Events Analysis"""
|
||||
_name = "report.event.registration"
|
||||
_order = 'event_date desc'
|
||||
_auto = False
|
||||
|
||||
create_date = fields.Datetime('Creation Date', readonly=True)
|
||||
event_date = fields.Datetime('Event Date', readonly=True)
|
||||
event_id = fields.Many2one('event.event', 'Event', required=True)
|
||||
draft_state = fields.Integer(' # No of Draft Registrations')
|
||||
cancel_state = fields.Integer(' # No of Cancelled Registrations')
|
||||
confirm_state = fields.Integer(' # No of Confirmed Registrations')
|
||||
seats_max = fields.Integer('Max Seats')
|
||||
nbevent = fields.Integer('Number of Events')
|
||||
nbregistration = fields.Integer('Number of Registrations')
|
||||
event_type_id = fields.Many2one('event.type', 'Event Type')
|
||||
registration_state = fields.Selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Attended'), ('cancel', 'Cancelled')], 'Registration State', readonly=True, required=True)
|
||||
event_state = fields.Selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Event State', readonly=True, required=True)
|
||||
user_id = fields.Many2one('res.users', 'Event Responsible', readonly=True)
|
||||
name_registration = fields.Char('Participant / Contact Name', readonly=True)
|
||||
company_id = fields.Many2one('res.company', 'Company', readonly=True)
|
||||
|
||||
@api.model_cr
|
||||
def init(self):
|
||||
"""Initialize the sql view for the event registration """
|
||||
tools.drop_view_if_exists(self.env.cr, 'report_event_registration')
|
||||
|
||||
# TOFIX this request won't select events that have no registration
|
||||
self.env.cr.execute(""" CREATE VIEW report_event_registration AS (
|
||||
SELECT
|
||||
e.id::varchar || '/' || coalesce(r.id::varchar,'') AS id,
|
||||
e.id AS event_id,
|
||||
e.user_id AS user_id,
|
||||
r.name AS name_registration,
|
||||
r.create_date AS create_date,
|
||||
e.company_id AS company_id,
|
||||
e.date_begin AS event_date,
|
||||
count(r.id) AS nbevent,
|
||||
count(r.event_id) AS nbregistration,
|
||||
CASE WHEN r.state IN ('draft') THEN count(r.event_id) ELSE 0 END AS draft_state,
|
||||
CASE WHEN r.state IN ('open','done') THEN count(r.event_id) ELSE 0 END AS confirm_state,
|
||||
CASE WHEN r.state IN ('cancel') THEN count(r.event_id) ELSE 0 END AS cancel_state,
|
||||
e.event_type_id AS event_type_id,
|
||||
e.seats_max AS seats_max,
|
||||
e.state AS event_state,
|
||||
r.state AS registration_state
|
||||
FROM
|
||||
event_event e
|
||||
LEFT JOIN event_registration r ON (e.id=r.event_id)
|
||||
|
||||
GROUP BY
|
||||
event_id,
|
||||
r.id,
|
||||
registration_state,
|
||||
event_type_id,
|
||||
e.id,
|
||||
e.date_begin,
|
||||
e.user_id,
|
||||
event_state,
|
||||
e.company_id,
|
||||
e.seats_max,
|
||||
name_registration
|
||||
)
|
||||
""")
|
||||
@@ -1,70 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record model ="ir.ui.view" id="report_event_registration_pivot">
|
||||
<field name="name">report.event.registration.pivot</field>
|
||||
<field name="model">report.event.registration</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Event on Registration" disable_linking="True">
|
||||
<field name="event_id" type="row"/>
|
||||
<field name="event_date" interval="month" type="col"/>
|
||||
<field name="confirm_state" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model ="ir.ui.view" id="report_event_registration_graph">
|
||||
<field name="name">report.event.registration.graph</field>
|
||||
<field name="model">report.event.registration</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Event on Registration">
|
||||
<field name="event_id"/>
|
||||
<field name="event_date" interval="month"/>
|
||||
<field name="confirm_state" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Event on Registration search view -->
|
||||
<record model="ir.ui.view" id="view_report_event_registration_search">
|
||||
<field name="name">report.event.registration.search</field>
|
||||
<field name="model">report.event.registration</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Event on Registration">
|
||||
<filter string="New" domain="[('event_state','=','draft')]" help="Events which are in New state"/>
|
||||
<filter string="Confirm" domain="[('event_state','=','confirm')]" help="Events which are in confirm state"/>
|
||||
<separator/>
|
||||
<field name="event_id" string="Event"/>
|
||||
<field name="user_id"/>
|
||||
<group expand="0" string="Extended Filters...">
|
||||
<field name="event_type_id" widget="selection"/>
|
||||
<field name="event_date"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Attendee / Contact" context="{'group_by':'name_registration'}" help="Registration contact"/>
|
||||
<filter string="Event Type" context="{'group_by':'event_type_id'}"/>
|
||||
<filter string="Event" name="event" context="{'group_by':'event_id', 'max_reg_event_visible':0}"/>
|
||||
<filter string="Event State" context="{'group_by':'event_state'}"/>
|
||||
<filter string="Company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator/>
|
||||
<filter string="Event Month" context="{'group_by':'event_date:month'}" help="Event Beginning Date"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_report_event_registration">
|
||||
<field name="name">Events Analysis</field>
|
||||
<field name="res_model">report.event.registration</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="search_view_id" ref="view_report_event_registration_search"/>
|
||||
<field name="context">{}</field> <!-- force empty -->
|
||||
</record>
|
||||
|
||||
<menuitem name="Events" parent="event.menu_reporting_events" action="action_report_event_registration" id="menu_report_event_registration" sequence="3" groups="event.group_event_manager"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -41,16 +41,5 @@
|
||||
]
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.rule" id="report_event_registration_company_rule">
|
||||
<field name="name">Event/Report Registration: multi-company</field>
|
||||
<field name="model_id" ref="model_report_event_registration"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',
|
||||
('company_id', '=', False),
|
||||
('company_id', 'child_of', [user.company_id.id]),
|
||||
]
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -10,4 +10,5 @@ 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
|
||||
access_report_event_registration,report.event.registration,model_report_event_registration,event.group_event_user,1,1,1,1
|
||||
access_event_type_mail_event_user,event.type.mail.event.user,model_event_type_mail,event.group_event_user,1,0,0,0
|
||||
access_event_type_mail_event_manager,event.type.mail.event.manager,model_event_type_mail,event.group_event_manager,1,1,1,1
|
||||
|
||||
|
@@ -15,14 +15,10 @@ class TestEventFlow(TestEventCommon):
|
||||
@mute_logger('odoo.addons.base.ir.ir_model', 'odoo.models')
|
||||
def test_00_basic_event_auto_confirm(self):
|
||||
""" Basic event management with auto confirmation """
|
||||
event_config = self.env['event.config.settings'].sudo(self.user_eventmanager).create({
|
||||
'default_auto_confirmation': 1
|
||||
})
|
||||
event_config.execute()
|
||||
|
||||
# EventUser creates a new event: ok
|
||||
test_event = self.Event.sudo(self.user_eventmanager).create({
|
||||
'name': 'TestEvent',
|
||||
'auto_confirm': True,
|
||||
'date_begin': datetime.datetime.now() + relativedelta(days=-1),
|
||||
'date_end': datetime.datetime.now() + relativedelta(days=1),
|
||||
'seats_max': 2,
|
||||
@@ -66,13 +62,10 @@ class TestEventFlow(TestEventCommon):
|
||||
with self.assertRaises(UserError):
|
||||
test_event.button_cancel()
|
||||
|
||||
|
||||
@mute_logger('odoo.addons.base.ir.ir_model', 'odoo.models')
|
||||
def test_10_advanced_event_flow(self):
|
||||
""" Avanced event flow: no auto confirmation, manage minimum / maximum
|
||||
seats, ... """
|
||||
self.env['ir.values'].set_default('event.config.settings', 'default_auto_confirmation', False)
|
||||
|
||||
# EventUser creates a new event: ok
|
||||
test_event = self.Event.sudo(self.user_eventmanager).create({
|
||||
'name': 'TestEvent',
|
||||
@@ -114,7 +107,6 @@ class TestEventFlow(TestEventCommon):
|
||||
]})
|
||||
with self.assertRaises(AccessError):
|
||||
event_config = self.env['event.config.settings'].sudo(self.user_eventmanager).create({
|
||||
'default_auto_confirmation': 1
|
||||
})
|
||||
event_config.execute()
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@ class TestMailSchedule(TestEventCommon):
|
||||
@mute_logger('odoo.addons.base.ir.ir_model', 'odoo.models')
|
||||
def test_00_event_mail_schedule(self):
|
||||
""" Test mail scheduling for events """
|
||||
self.env['ir.values'].set_default('event.config.settings', 'default_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',
|
||||
'auto_confirm': True,
|
||||
'date_begin': event_date_begin,
|
||||
'date_end': event_date_end,
|
||||
'seats_max': 10,
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" title="Add a navigation menu to your event web pages with an agenda, tracks, a track proposal form, etc.">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" title="Add a navigation menu to your event web pages with schedule, tracks, a track proposal form, etc.">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_event_track"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Agenda & Tracks" for="module_website_event_track"/>
|
||||
<label string="Schedule & Tracks" for="module_website_event_track"/>
|
||||
<div class="text-muted">
|
||||
Manage & publish an agenda with tracks
|
||||
Manage & publish a schedule with tracks
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -49,7 +49,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" name="event_settings_website">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_event_sale"/>
|
||||
</div>
|
||||
@@ -60,17 +60,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" id="default_auto_confirmation" title="Uncheck this option to manually manage draft event and draft registration.">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="default_auto_confirmation"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="default_auto_confirmation"/>
|
||||
<div class="text-muted">
|
||||
Confirm registrations automatically
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Attendance</h2>
|
||||
<div class="row mt16 o_settings_container">
|
||||
|
||||
@@ -11,14 +11,135 @@
|
||||
<field name="name">event.type.form</field>
|
||||
<field name="model">event.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Type">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="default_reply_to"/>
|
||||
<field name="default_registration_min"/>
|
||||
<field name="default_registration_max"/>
|
||||
</group>
|
||||
<form string="Event Category">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<h1><field name="name"/></h1>
|
||||
</div>
|
||||
<h2>Location</h2>
|
||||
<div class="row mt16 o_settings_container" name="event_type_location">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="is_online"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="is_online"/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mt16 text-muted">
|
||||
Online events like webinars do not require a specific location
|
||||
and are hosted online.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="use_timezone"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="use_timezone"/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mt16" attrs="{'invisible': [('use_timezone', '=', False)]}">
|
||||
<label for="default_timezone"/>
|
||||
<field name="default_timezone"
|
||||
attrs="{'required': [('use_timezone', '=', True)]}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Communication</h2>
|
||||
<div class="row mt16 o_settings_container" name="event_type_communication">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="use_reply_to"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="use_reply_to"/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mt16" attrs="{'invisible': [('use_reply_to', '=', False)]}">
|
||||
<label for="default_reply_to"/>
|
||||
<field name="default_reply_to"
|
||||
attrs="{'required': [('use_reply_to', '=', True)]}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="use_hashtag"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="use_hashtag"/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mt16" attrs="{'invisible': [('use_hashtag', '=', False)]}">
|
||||
<label for="default_hashtag"/>
|
||||
<field name="default_hashtag"
|
||||
attrs="{'required': [('use_hashtag', '=', True)]}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-12 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="use_mail_schedule"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="use_mail_schedule"/>
|
||||
<div class="row mt16" attrs="{'invisible': [('use_mail_schedule', '=', False)]}">
|
||||
<div class="col-md-9">
|
||||
<field name="event_type_mail_ids">
|
||||
<tree string="Email Schedule" editable="bottom">
|
||||
<field name="template_id"/>
|
||||
<field name="interval_nbr" attrs="{'readonly':[('interval_unit', '=', 'now')]}"/>
|
||||
<field name="interval_unit"/>
|
||||
<field name="interval_type"/>
|
||||
</tree>
|
||||
</field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Visibility</h2>
|
||||
<div class="row mt16 o_settings_container" name="event_type_visibility">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" name="event_type_visibility_seats">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="has_seats_limitation"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="has_seats_limitation"/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mt16" attrs="{'invisible': [('has_seats_limitation', '=', False)]}">
|
||||
<div>
|
||||
<label for="default_registration_min"/> <field name="default_registration_min"/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="default_registration_max"/> <field name="default_registration_max"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Attendees</h2>
|
||||
<div class="row mt16 o_settings_container" name="event_type_attendees">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" name="event_type_attendees_auto_confirm">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="auto_confirm"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="auto_confirm"/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mt16 text-muted">
|
||||
Events and registrations will automatically be confirmed
|
||||
upon creation, easing the flow for simple events.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
@@ -28,14 +149,14 @@
|
||||
<field name="name">event.type.tree</field>
|
||||
<field name="model">event.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Event Type">
|
||||
<tree string="Event Category">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_event_type">
|
||||
<field name="name">Event Types</field>
|
||||
<field name="name">Event Categories</field>
|
||||
<field name="res_model">event.type</field>
|
||||
<field name="view_type">form</field>
|
||||
</record>
|
||||
@@ -54,6 +175,13 @@
|
||||
</record>
|
||||
|
||||
<!-- EVENT.EVENT VIEWS -->
|
||||
<record id="event_event_action_pivot" model="ir.actions.act_window" >
|
||||
<field name="name">Events Analysis</field>
|
||||
<field name="res_model">event.event</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_form">
|
||||
<field name="name">event.event.form</field>
|
||||
<field name="model">event.event</field>
|
||||
@@ -69,14 +197,16 @@
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box" groups="base.group_user">
|
||||
<button name="%(event.act_event_registration_from_event)d"
|
||||
type="action"
|
||||
class="oe_stat_button oe_event_attendee_button"
|
||||
icon="fa-users"
|
||||
help="Register with this event">
|
||||
type="action"
|
||||
class="oe_stat_button"
|
||||
icon="fa-users"
|
||||
help="Register with this event">
|
||||
<field name="seats_expected" widget="statinfo" string="Attendees"/>
|
||||
</button>
|
||||
<button name="toggle_active" type="object"
|
||||
class="oe_stat_button" icon="fa-archive">
|
||||
<button name="toggle_active"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-archive">
|
||||
<field name="active" widget="boolean_button"
|
||||
options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
@@ -84,44 +214,44 @@
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<h1><field name="name" placeholder="Event Name"/></h1>
|
||||
<field name="is_online" groups="base.group_no_one"/>
|
||||
<label for="is_online" string="Online" groups="base.group_no_one"/>
|
||||
</div>
|
||||
<group name="main_field_group">
|
||||
<group>
|
||||
<group>
|
||||
<field name="address_id" context="{'show_address': 1}" options='{"always_reload": True}'/>
|
||||
<field name="organizer_id"/>
|
||||
<field name="address_id"
|
||||
attrs="{'invisible': [('is_online', '=', True)]}"
|
||||
context="{'show_address': 1}"
|
||||
options='{"always_reload": True}'/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="user_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="user_id"/>
|
||||
<field name="event_type_id" options="{'no_create':True}"/>
|
||||
<field name="reply_to" string="Contact Email"/>
|
||||
<field name="twitter_hashtag"/>
|
||||
<field name="auto_confirm" groups="base.group_no_one"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date_begin"/>
|
||||
<field name="date_end"/>
|
||||
<field name="date_tz" />
|
||||
<field name="date_tz"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="seats_min"/>
|
||||
<label for="seats_availability"/>
|
||||
<div>
|
||||
<field name="seats_availability" widget='radio'/>
|
||||
<span attrs="{'invisible': [('seats_availability', '=', 'unlimited')]}" class="oe_read_only">
|
||||
to
|
||||
</span>
|
||||
<field name="seats_max" attrs="{'invisible': [('seats_availability', '=', 'unlimited')], 'required': [('seats_availability', '=', 'limited')]}"/>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="registrations" string="Registrations">
|
||||
<group>
|
||||
<group>
|
||||
<field name="seats_min"/>
|
||||
<label for="seats_availability"/>
|
||||
<div>
|
||||
<field name="seats_availability" widget='radio'/>
|
||||
<span attrs="{'invisible': [('seats_availability', '=', 'unlimited')]}" class="oe_read_only">
|
||||
to
|
||||
</span>
|
||||
<field name="seats_max" attrs="{'invisible': [('seats_availability', '=', 'unlimited')], 'required': [('seats_availability', '=', 'limited')]}"/>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="auto_confirm" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Email Schedule">
|
||||
<group>
|
||||
<field name="reply_to"/>
|
||||
</group>
|
||||
<page string="Email Schedule" name="event_mail_schedule">
|
||||
<field name="event_mail_ids">
|
||||
<tree string="Email Schedule" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
@@ -211,8 +341,9 @@
|
||||
<t t-esc="record.seats_expected.raw_value"> Expected attendees </t>
|
||||
</a>
|
||||
<t t-if="(record.seats_reserved.raw_value + record.seats_used.raw_value) > 0 "><br/>
|
||||
<t t-esc="record.seats_reserved.raw_value + record.seats_used.raw_value"/> Confirmed attendees
|
||||
<a name="action_event_registration_report" type="object" >(stats)</a>
|
||||
<a name="%(event_event_action_pivot)d" type="action">
|
||||
<t t-esc="record.seats_reserved.raw_value + record.seats_used.raw_value"/> Confirmed attendees
|
||||
</a>
|
||||
</t>
|
||||
</h4>
|
||||
</div>
|
||||
@@ -264,12 +395,23 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_event_view_pivot" model="ir.ui.view" >
|
||||
<field name="name">event.event.view.pivot</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Event" disable_linking="True">
|
||||
<field name="name" type="row"/>
|
||||
<field name="seats_reserved" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_event_view">
|
||||
<field name="name">Events</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">event.event</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,calendar,tree,form</field>
|
||||
<field name="view_mode">kanban,calendar,tree,form,pivot</field>
|
||||
<field name="context">{"search_default_upcoming":1}</field>
|
||||
<field name="search_view_id" ref="view_event_search"/>
|
||||
<field name="help" type="html"><p class="oe_view_nocontent_create">
|
||||
@@ -291,6 +433,12 @@
|
||||
view_type="form"/>
|
||||
|
||||
<menuitem name="Events" id="menu_event_event" action="action_event_view" parent="event.event_main_menu" />
|
||||
<menuitem name="Events"
|
||||
id="event_event_menu_pivot_report"
|
||||
action="event_event_action_pivot"
|
||||
sequence="3"
|
||||
parent="event.menu_reporting_events"
|
||||
groups="event.group_event_manager"/>
|
||||
|
||||
<!-- EVENT.REGISTRATION VIEWS -->
|
||||
<record model="ir.ui.view" id="view_event_registration_tree">
|
||||
@@ -328,10 +476,10 @@
|
||||
<sheet string="Registration">
|
||||
<group>
|
||||
<group string="Attendee" name="attendee">
|
||||
<field name="partner_id" attrs="{'readonly':[('state', '!=', 'draft')]}"/>
|
||||
<field name="name"/>
|
||||
<field name="phone"/>
|
||||
<field name="email"/>
|
||||
<field name="partner_id" attrs="{'readonly':[('state', '!=', 'draft')]}"/>
|
||||
</group>
|
||||
<group string="Event Information" name="event">
|
||||
<field name="event_id" attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
||||
@@ -423,28 +571,35 @@
|
||||
<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" attrs="{'readonly':[('interval_unit', '=', 'now')]}"/>
|
||||
<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>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="event_id"/>
|
||||
<field name="template_id"/>
|
||||
<field name="mail_sent"/>
|
||||
</group>
|
||||
<group>
|
||||
<label for="interval_nbr"/>
|
||||
<div class="o_row">
|
||||
<field name="interval_nbr" attrs="{'invisible': [('interval_unit', '=', 'now')], 'readonly': [('interval_unit', '=', 'now')]}"/>
|
||||
<field name="interval_unit"/>
|
||||
</div>
|
||||
<field name="interval_type"/>
|
||||
<field name="scheduled_date"/>
|
||||
</group>
|
||||
</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>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="event_type" model="event.type">
|
||||
<field name="name">Generic Events</field>
|
||||
</record>
|
||||
|
||||
<record id="product_product_event" model="product.product">
|
||||
<field name="list_price">10.0</field>
|
||||
<field name="event_ok" eval="True"/>
|
||||
@@ -17,6 +12,12 @@
|
||||
<field name="type">service</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_data_sale" model="event.type">
|
||||
<field name="name">Ticketing</field>
|
||||
<field name="auto_confirm" eval="False"/>
|
||||
<field name="use_mail_schedule" eval="True"/>
|
||||
<field name="use_ticketing" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import account_invoice
|
||||
import sale_order
|
||||
import product
|
||||
import event
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
@api.multi
|
||||
def action_invoice_paid(self):
|
||||
""" When an invoice linked to a sales order selling registrations is
|
||||
paid confirm attendees. Attendees should indeed not be confirmed before
|
||||
full payment. """
|
||||
res = super(AccountInvoice, self).action_invoice_paid()
|
||||
self.mapped('invoice_line_ids.sale_line_ids')._update_registrations(confirm=True)
|
||||
return res
|
||||
@@ -2,31 +2,59 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
|
||||
import odoo.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
class EventType(models.Model):
|
||||
_inherit = 'event.type'
|
||||
|
||||
_inherit = 'event.event'
|
||||
|
||||
def _default_tickets(self):
|
||||
@api.model
|
||||
def _get_default_event_ticket_ids(self):
|
||||
product = self.env.ref('event_sale.product_product_event', raise_if_not_found=False)
|
||||
if not product:
|
||||
return self.env['event.event.ticket']
|
||||
return [{
|
||||
return False
|
||||
return [(0, 0, {
|
||||
'name': _('Registration'),
|
||||
'product_id': product.id,
|
||||
'price': 0,
|
||||
}]
|
||||
})]
|
||||
|
||||
event_ticket_ids = fields.One2many('event.event.ticket', 'event_id', string='Event Ticket',
|
||||
default=lambda self: self._default_tickets(), copy=True)
|
||||
use_ticketing = fields.Boolean('Ticketing')
|
||||
event_ticket_ids = fields.One2many(
|
||||
'event.event.ticket', 'event_type_id',
|
||||
string='Tickets', default=_get_default_event_ticket_ids)
|
||||
|
||||
@api.onchange('name')
|
||||
def _onchange_name(self):
|
||||
if self.name:
|
||||
self.event_ticket_ids.filtered(lambda ticket: ticket.name == _('Registration')).update({
|
||||
'name': _('Registration for %s') % self.name
|
||||
})
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
_inherit = 'event.event'
|
||||
|
||||
event_ticket_ids = fields.One2many(
|
||||
'event.event.ticket', 'event_id', string='Event Ticket',
|
||||
copy=True)
|
||||
|
||||
@api.onchange('event_type_id')
|
||||
def _onchange_type(self):
|
||||
super(Event, self)._onchange_type()
|
||||
if self.event_type_id.use_ticketing:
|
||||
self.event_ticket_ids = [(5, 0, 0)] + [
|
||||
(0, 0, {
|
||||
'name': self.name and _('Registration for %s') % self.name or ticket.name,
|
||||
'product_id': ticket.product_id.id,
|
||||
'price': ticket.price,
|
||||
})
|
||||
for ticket in self.event_type_id.event_ticket_ids]
|
||||
|
||||
|
||||
class EventTicket(models.Model):
|
||||
|
||||
_name = 'event.event.ticket'
|
||||
_description = 'Event Ticket'
|
||||
|
||||
@@ -34,7 +62,8 @@ class EventTicket(models.Model):
|
||||
return self.env.ref('event_sale.product_product_event', raise_if_not_found=False)
|
||||
|
||||
name = fields.Char(string='Name', required=True, translate=True)
|
||||
event_id = fields.Many2one('event.event', string="Event", required=True, ondelete='cascade')
|
||||
event_type_id = fields.Many2one('event.type', string='Event Category', ondelete='cascade')
|
||||
event_id = fields.Many2one('event.event', string="Event", ondelete='cascade')
|
||||
product_id = fields.Many2one('product.product', string='Product',
|
||||
required=True, domain=[("event_ok", "=", True)],
|
||||
default=_default_product_id)
|
||||
@@ -115,6 +144,11 @@ class EventTicket(models.Model):
|
||||
if record.seats_max and record.seats_available < 0:
|
||||
raise ValidationError(_('No more available seats for the ticket'))
|
||||
|
||||
@api.constrains('event_type_id', 'event_id')
|
||||
def _constrains_event(self):
|
||||
if any(ticket.event_type_id and ticket.event_id for ticket in self):
|
||||
raise UserError(_('Ticket should belong to either event category or event but not both'))
|
||||
|
||||
@api.onchange('product_id')
|
||||
def _onchange_product_id(self):
|
||||
self.price = self.product_id.list_price or 0
|
||||
|
||||
@@ -10,7 +10,7 @@ class SaleOrder(models.Model):
|
||||
def action_confirm(self):
|
||||
self.ensure_one()
|
||||
res = super(SaleOrder, self).action_confirm()
|
||||
self.order_line._update_registrations(confirm=True)
|
||||
self.order_line._update_registrations(confirm=False, cancel_to_draft=False)
|
||||
if any(self.order_line.filtered(lambda line: line.event_id)):
|
||||
return self.env['ir.actions.act_window'].with_context(default_sale_order_id=self.id).for_xml_id('event_sale', 'action_sale_order_event_registration')
|
||||
return res
|
||||
@@ -35,7 +35,7 @@ class SaleOrderLine(models.Model):
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _update_registrations(self, confirm=True, registration_data=None):
|
||||
def _update_registrations(self, confirm=True, cancel_to_draft=False, registration_data=None):
|
||||
""" Create or update registrations linked to a sales order line. A sale
|
||||
order line has a product_uom_qty attribute that will be the number of
|
||||
registrations linked to this line. This method update existing registrations
|
||||
@@ -46,7 +46,7 @@ class SaleOrderLine(models.Model):
|
||||
existing_registrations = registrations.filtered(lambda self: self.sale_order_line_id.id == so_line.id)
|
||||
if confirm:
|
||||
existing_registrations.filtered(lambda self: self.state != 'open').confirm_registration()
|
||||
else:
|
||||
if cancel_to_draft:
|
||||
existing_registrations.filtered(lambda self: self.state == 'cancel').do_draft()
|
||||
|
||||
for count in range(int(so_line.product_uom_qty) - len(existing_registrations)):
|
||||
|
||||
@@ -41,34 +41,55 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_view_form_inherit_sale" model="ir.ui.view">
|
||||
<field name="name">event.type.view.form.inherit.sale</field>
|
||||
<field name="model">event.type</field>
|
||||
<field name="inherit_id" ref="event.view_event_type_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="event_type_attendees_auto_confirm" position="after">
|
||||
<div class="col-xs-12 col-md-12 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="use_ticketing"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="use_ticketing"/>
|
||||
<div class="row mt16" attrs="{'invisible': [('use_ticketing', '=', False)]}">
|
||||
<div class="col-md-9">
|
||||
<field name="event_ticket_ids">
|
||||
<tree string="Tickets" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="product_id"/>
|
||||
<field name="price"/>
|
||||
</tree>
|
||||
</field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_event_form_inherit_ticket" model="ir.ui.view">
|
||||
<field name="name">event.form.inherit</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="inherit_id" ref="event.view_event_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='registrations']" position="replace">
|
||||
<page string="Tickets">
|
||||
<group>
|
||||
<group>
|
||||
<field name="auto_confirm" invisible="1"/>
|
||||
<field name="seats_min"/>
|
||||
<field name="seats_availability" widget='radio'/>
|
||||
<field name="seats_max" attrs="{'invisible': [('seats_availability', '=', 'unlimited')], 'required': [('seats_availability', '=', 'limited')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="event_ticket_ids" context="{'default_name': name}">
|
||||
<tree string="Tickets" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="product_id" context="{'default_event_ok':1}"/>
|
||||
<field name="deadline"/>
|
||||
<field name="price"/>
|
||||
<field name="seats_max"/>
|
||||
<field name="seats_reserved" readonly="1"/>
|
||||
<field name="seats_unconfirmed" readonly="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
<page name="event_mail_schedule" position="before">
|
||||
<page string="Tickets">
|
||||
<field name="event_ticket_ids" context="{'default_name': name}">
|
||||
<tree string="Tickets" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="product_id" context="{'default_event_ok':1}"/>
|
||||
<field name="deadline"/>
|
||||
<field name="price"/>
|
||||
<field name="seats_max"/>
|
||||
<field name="seats_reserved" readonly="1"/>
|
||||
<field name="seats_unconfirmed" readonly="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</page>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ class RegistrationEditor(models.TransientModel):
|
||||
self.env['event.registration'].create(values)
|
||||
if self.env.context.get('active_model') == 'sale.order':
|
||||
for order in self.env['sale.order'].browse(self.env.context.get('active_ids', [])):
|
||||
order.order_line._update_registrations(confirm=True)
|
||||
order.order_line._update_registrations(confirm=False)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
|
||||
@@ -734,6 +734,8 @@ class MailThread(models.AbstractModel):
|
||||
recipient_ids.add(record.partner_id.id)
|
||||
elif 'email_from' in self._fields and record.email_from:
|
||||
email_to = record.email_from
|
||||
elif 'partner_email' in self._fields and record.partner_email:
|
||||
email_to = record.partner_email
|
||||
elif 'email' in self._fields:
|
||||
email_to = record.email
|
||||
res[record.id] = {'partner_ids': list(recipient_ids), 'email_to': email_to, 'email_cc': email_cc}
|
||||
|
||||
@@ -10,7 +10,7 @@ Create Awesome Event Pages
|
||||
|
||||
### Get rid of old WYSIWYG editors
|
||||
|
||||
Create beautiful event pages by drag & droping well designed *'Building Blocks'*. Publish event photos, speakers, agenda, etc.
|
||||
Create beautiful event pages by drag & droping well designed *'Building Blocks'*. Publish event photos, speakers, schedule, etc.
|
||||
|
||||
Odoo's unique *'edit inline'* approach makes website creation surprisingly easy. "Want to introduce a speaker? to change the price of a ticket? to update a banner? promote sponsors?" just click and change.
|
||||
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
'name': 'Online Events',
|
||||
'category': 'Marketing',
|
||||
'sequence': 135,
|
||||
'summary': 'Schedule, Promote and Sell Events',
|
||||
'summary': 'Publish Events and Manage Online Registrations on your Website',
|
||||
'website': 'https://www.odoo.com/page/website-builder',
|
||||
'description': """
|
||||
Online Events
|
||||
""",
|
||||
'depends': ['website', 'website_partner', 'website_mail', 'event'],
|
||||
'data': [
|
||||
'data/website_event_data.xml',
|
||||
'data/event_data.xml',
|
||||
'views/event_config_settings_views.xml',
|
||||
'views/website_event_templates.xml',
|
||||
'views/website_event_views.xml',
|
||||
'views/event_templates.xml',
|
||||
'views/event_views.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/website_event_security.xml',
|
||||
'security/event_security.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/website_event_demo.xml'
|
||||
'data/event_demo.xml'
|
||||
],
|
||||
'application': True,
|
||||
}
|
||||
|
||||
@@ -6,14 +6,18 @@ from odoo import api, fields, models, _
|
||||
from odoo.addons.website.models.website import slug
|
||||
|
||||
|
||||
class EventType(models.Model):
|
||||
_name = 'event.type'
|
||||
_inherit = ['event.type']
|
||||
|
||||
website_menu = fields.Boolean(
|
||||
'Display a dedicated menu on Website')
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
_name = 'event.event'
|
||||
_inherit = ['event.event', 'website.seo.metadata', 'website.published.mixin']
|
||||
|
||||
def _default_hashtag(self):
|
||||
return re.sub("[- \\.\\(\\)\\@\\#\\&]+", "", self.env.user.company_id.name).lower()
|
||||
|
||||
twitter_hashtag = fields.Char('Twitter Hashtag', default=_default_hashtag)
|
||||
website_published = fields.Boolean(track_visibility='onchange')
|
||||
website_message_ids = fields.One2many(
|
||||
'mail.message', 'res_id',
|
||||
@@ -25,9 +29,10 @@ class Event(models.Model):
|
||||
)
|
||||
is_participating = fields.Boolean("Is Participating", compute="_compute_is_participating")
|
||||
|
||||
show_menu = fields.Boolean('Dedicated Menu', compute='_get_show_menu', inverse='_set_show_menu',
|
||||
help="Creates menus Introduction, Location and Register on the page "
|
||||
" of the event on the website.", store=True)
|
||||
website_menu = fields.Boolean(
|
||||
'Dedicated Menu', compute='_compute_website_menu', inverse='_set_website_menu',
|
||||
help="Creates menus Introduction, Location and Register on the page "
|
||||
" of the event on the website.", store=True)
|
||||
menu_id = fields.Many2one('website.menu', 'Event Menu')
|
||||
|
||||
def _compute_is_participating(self):
|
||||
@@ -46,46 +51,47 @@ class Event(models.Model):
|
||||
if event.id: # avoid to perform a slug on a not yet saved record in case of an onchange.
|
||||
event.website_url = '/event/%s' % slug(event)
|
||||
|
||||
@api.multi
|
||||
def _get_new_menu_pages(self):
|
||||
""" Retuns a list of tuple ('Page name', 'relative page url') for the event """
|
||||
@api.onchange('event_type_id')
|
||||
def _onchange_type(self):
|
||||
super(Event, self)._onchange_type()
|
||||
if self.event_type_id:
|
||||
self.website_menu = self.event_type_id.website_menu
|
||||
|
||||
def _get_menu_entries(self):
|
||||
self.ensure_one()
|
||||
todo = [
|
||||
(_('Introduction'), 'website_event.template_intro'),
|
||||
(_('Location'), 'website_event.template_location')
|
||||
return [
|
||||
(_('Introduction'), False, 'website_event.template_intro'),
|
||||
(_('Location'), False, 'website_event.template_location'),
|
||||
(_('Register'), '/event/%s/register' % slug(self), False),
|
||||
]
|
||||
result = []
|
||||
for name, path in todo:
|
||||
complete_name = name + ' ' + self.name
|
||||
newpath = self.env['website'].new_page(complete_name, path, ispage=False)
|
||||
url = "/event/" + slug(self) + "/page/" + newpath
|
||||
result.append((name, url))
|
||||
result.append((_('Register'), '/event/%s/register' % slug(self)))
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def _set_show_menu(self):
|
||||
def _set_website_menu(self):
|
||||
for event in self:
|
||||
if event.menu_id and not event.show_menu:
|
||||
if event.menu_id and not event.website_menu:
|
||||
event.menu_id.unlink()
|
||||
elif event.show_menu and not event.menu_id:
|
||||
root_menu = self.env['website.menu'].create({'name': event.name})
|
||||
to_create_menus = event._get_new_menu_pages()
|
||||
seq = 0
|
||||
for name, url in to_create_menus:
|
||||
self.env['website.menu'].create({
|
||||
'name': name,
|
||||
'url': url,
|
||||
'parent_id': root_menu.id,
|
||||
'sequence': seq,
|
||||
})
|
||||
seq += 1
|
||||
event.menu_id = root_menu
|
||||
elif event.website_menu:
|
||||
if not event.menu_id:
|
||||
root_menu = self.env['website.menu'].create({'name': event.name})
|
||||
event.menu_id = root_menu
|
||||
|
||||
for sequence, (name, url, xml_id) in enumerate(self._get_menu_entries()):
|
||||
existing_pages = event.menu_id.child_id.mapped('name')
|
||||
if name not in existing_pages:
|
||||
if not url:
|
||||
newpath = self.env['website'].new_page(name + ' ' + self.name, xml_id, ispage=False)
|
||||
url = "/event/" + slug(self) + "/page/" + newpath
|
||||
self.env['website.menu'].create({
|
||||
'name': name,
|
||||
'url': url,
|
||||
'parent_id': event.menu_id.id,
|
||||
'sequence': sequence,
|
||||
})
|
||||
|
||||
@api.multi
|
||||
def _get_show_menu(self):
|
||||
def _compute_website_menu(self):
|
||||
for event in self:
|
||||
event.show_menu = bool(event.menu_id)
|
||||
event.website_menu = bool(event.menu_id)
|
||||
|
||||
@api.multi
|
||||
def google_map_img(self, zoom=8, width=298, height=298):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h2 class="oe_slogan" style="color:#875A7B;">Create your own events</h2>
|
||||
<h3 class="oe_slogan">Organize, publish, promote and sell.</h3>
|
||||
<h3 class="oe_slogan">Organize, publish and promote.</h3>
|
||||
<div class="oe_span12">
|
||||
<div class="oe_demo oe_picture oe_screenshot">
|
||||
<img src="event_sc_00.png">
|
||||
@@ -15,7 +15,7 @@
|
||||
<h2 class="oe_slogan" style="color:#875A7B;">Host events that resonates with your audience</h2>
|
||||
<h3 class="oe_slogan">Easily create live or online events</h3>
|
||||
<p class="oe_mt32">
|
||||
One platform to manage it all. Odoo Events covers all aspects of an event manager's work: organization, visibility, promotion and sale. Use it with any kind of event, including conferences, meetings, seminars, training and webinars.
|
||||
One platform to manage it all. Odoo Events covers all aspects of an event manager's work: organization, visibility, promotion. Use it with any kind of event, including conferences, meetings, seminars, training and webinars.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
@@ -51,7 +51,7 @@
|
||||
</div>
|
||||
<div class="oe_span3 text-center">
|
||||
<span class="fa fa-2x fa-calendar"/>
|
||||
<p class="oe_mt16">Automatically display your event's agenda in a clear, classy design on your website.</p>
|
||||
<p class="oe_mt16">Automatically display your event's schedule in a clear, classy design on your website.</p>
|
||||
</div>
|
||||
<div class="oe_span3 text-center">
|
||||
<span class="fa fa-2x fa-search"/>
|
||||
@@ -69,9 +69,9 @@
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="sponsors.png" style="margin-left: -1px;">
|
||||
<h2 class="oe_slogan oe_mt32" style="text-align: left; color:#875A7B;">Get sponsors to come to you</h2>
|
||||
<h3 class="oe_slogan" style="text-align: left;">Sell sponsorship, promote your sponsors</h3>
|
||||
<h3 class="oe_slogan" style="text-align: left;">Promote your sponsors</h3>
|
||||
<p class="oe_mt32 text-justify">
|
||||
Easily manage existing and new sponsors with Odoo Events. Add sponsors to your events and publish sponsors per level (e.g., gold) on the bottom of every page of the event. Sell sponsorship packages online through Odoo eCommerce.</p>
|
||||
Easily manage existing and new sponsors with Odoo Events. Add sponsors to your events and publish sponsors per level (e.g., gold) on the bottom of every page of the event.</p>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="website_seo.png" style="margin-left: -1px;">
|
||||
@@ -83,22 +83,16 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h2 class="oe_slogan" style="color:#875A7B;">Total promotion tools</h2>
|
||||
<h3 class="oe_slogan">Promote events efficiently on all channels</h3>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="event_promote.png" style="margin-left: -1px;">
|
||||
<h2 class="oe_slogan oe_mt32" style="text-align: left; color:#875A7B;">Total promotion tools</h2>
|
||||
<h3 class="oe_slogan" style="text-align: left;">Promote events efficiently on all channels</h3>
|
||||
<p class="oe_mt32 text-justify">
|
||||
Segment your audience, leverage social media and email marketing to promote your events to the right audience. Odoo Events' smooth integration with countless Odoo apps simplifies promotion to the extreme. Setup automated campaigns for attendees, or automatically send timely emails to registrants. Optimize conversions with ad-hoc landing pages for your different marketing campaigns.
|
||||
</p>
|
||||
<img class="oe_picture oe_screenshot" src="event_promote.png">
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="event_sell.png" style="margin-left: -1px;">
|
||||
<h2 class="oe_slogan oe_mt32" style="text-align: left; color:#875A7B;">Sell tickets online</h2>
|
||||
<h3 class="oe_slogan" style="text-align: left;">Automate the registration and payment process</h3>
|
||||
<p class="oe_mt32 text-justify">
|
||||
Manage registrations and sell tickets online to your events. Choose whether it is a free event or whether attendees need to register for a fee. Pick the paying method -pay online with a credit card or with the invoice. Define special conditions such as early-bird prices, member benefits or extra services with multiple tickets. All you need to boost your event attendance.
|
||||
Segment your audience, leverage social media and email marketing to promote your events to the right audience. Odoo Events' smooth integration with countless Odoo apps simplifies promotion to the extreme. Setup automated campaigns for attendees, or automatically send timely emails to registrants. Optimize conversions with ad-hoc landing pages for your different marketing campaigns.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -26,13 +26,21 @@ var EventRegistrationForm = Widget.extend({
|
||||
$("#registration_form select").each(function() {
|
||||
post[$(this).attr('name')] = $(this).val();
|
||||
});
|
||||
return ajax.jsonRpc($form.attr('action'), 'call', post).then(function (modal) {
|
||||
var $modal = $(modal);
|
||||
$modal.appendTo($form).modal();
|
||||
$modal.on('click', '.js_goto_event', function () {
|
||||
$modal.modal('hide');
|
||||
var tickets_ordered = _.some(_.map(post, function(value, key) { return parseInt(value) }));
|
||||
if (! tickets_ordered) {
|
||||
return $('#registration_form table').after(
|
||||
'<div class="alert alert-info">Please select at least one ticket.</div>'
|
||||
);
|
||||
}
|
||||
else {
|
||||
return ajax.jsonRpc($form.attr('action'), 'call', post).then(function (modal) {
|
||||
var $modal = $(modal);
|
||||
$modal.appendTo($form).modal();
|
||||
$modal.on('click', '.js_goto_event', function () {
|
||||
$modal.modal('hide');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="event_config_settings_view_form_inherit_website_event" model="ir.ui.view">
|
||||
<field name="name">event.config.settings.form.inherit.website.event</field>
|
||||
<record id="event_config_settings_view_form_inherit_website" model="ir.ui.view">
|
||||
<field name="name">event.config.settings.view.form.inherit.website</field>
|
||||
<field name="model">event.config.settings</field>
|
||||
<field name="inherit_id" ref="event.event_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<div id="default_auto_confirmation" position="before">
|
||||
<div name="event_settings_website" position="after">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_website_event_questions"/>
|
||||
|
||||
+6
-1
@@ -438,7 +438,12 @@
|
||||
<td>
|
||||
<select t-if="event.seats_available or event.seats_availability == 'unlimited'" name="nb_register-0" class="form-control">
|
||||
<t t-foreach="range(0, (event.seats_availability == 'unlimited' or event.seats_available > 9) and 10 or event.seats_available+1)" t-as="nb">
|
||||
<option t-esc="nb"/>
|
||||
<t t-if="nb == 1">
|
||||
<option t-esc="nb" selected="selected"/>
|
||||
</t>
|
||||
<t t-if="nb != 1">
|
||||
<option t-esc="nb"/>
|
||||
</t>
|
||||
</t>
|
||||
</select>
|
||||
<span t-if="event.seats_availability == 'limited' and not event.seats_available">Sold Out</span>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="event_type_view_form_inherit_website" model="ir.ui.view">
|
||||
<field name="name">event.type.view.form.inherit.website</field>
|
||||
<field name="model">event.type</field>
|
||||
<field name="inherit_id" ref="event.view_event_type_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="event_type_visibility_seats" position="after">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" name="event_type_visibility_website">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="website_menu"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="website_menu"/>
|
||||
<div class="row">
|
||||
<div class="col-md-8 mt16 text-muted">
|
||||
Check this option to have menus for your event on the
|
||||
website: registrations, schedule, map, ...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_event_view_form_inherit_website" model="ir.ui.view">
|
||||
<field name="name">event.event.view.form.inherit.website</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="inherit_id" ref="event.view_event_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="toggle_active" position="before">
|
||||
<field name="website_url" invisible="1"/>
|
||||
<button name="website_publish_button"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-globe">
|
||||
<field name="website_published" widget="website_button"/>
|
||||
</button>
|
||||
</button>
|
||||
<label for="is_online" position="after">
|
||||
<field name="website_menu"/>
|
||||
<label for="website_menu" string="Website Menu"/>
|
||||
</label>
|
||||
<xpath expr="//button[@name='button_done']" position="before">
|
||||
<button name="action_open_badge_editor"
|
||||
type="object"
|
||||
states="confirm"
|
||||
string="Edit Badges"
|
||||
class="oe_highlight"/>
|
||||
<button name="action_open_badge_editor"
|
||||
type="object"
|
||||
states="done"
|
||||
string="Edit Badges"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_sale_form">
|
||||
<field name="name">event.event.website.form</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="inherit_id" ref="event.view_event_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- add state field in header -->
|
||||
<button name="toggle_active" position="before">
|
||||
<field name="website_url" invisible="1"/>
|
||||
<button class="oe_stat_button" name="website_publish_button"
|
||||
type="object" icon="fa-globe">
|
||||
<field name="website_published" widget="website_button"/>
|
||||
</button>
|
||||
</button>
|
||||
<xpath expr="//field[@name='organizer_id']" position="after">
|
||||
<field name="twitter_hashtag"/>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='button_done']" position="before">
|
||||
<button name="action_open_badge_editor"
|
||||
type="object"
|
||||
states="confirm"
|
||||
string="Edit Badges"
|
||||
class="oe_highlight"/>
|
||||
<button name="action_open_badge_editor"
|
||||
type="object"
|
||||
states="done"
|
||||
string="Edit Badges"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -7,13 +7,13 @@
|
||||
'version': '1.0',
|
||||
'depends': ['website_event'],
|
||||
'data': [
|
||||
'views/website_event_questions_backend.xml',
|
||||
'views/website_event_questions_templates.xml',
|
||||
'views/event_views.xml',
|
||||
'views/event_templates.xml',
|
||||
'report/report_event_question_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'demo': [
|
||||
'data/demo.xml',
|
||||
'data/event_demo.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class EventType(models.Model):
|
||||
_inherit = 'event.type'
|
||||
|
||||
use_questions = fields.Boolean('Questions to Attendees')
|
||||
question_ids = fields.One2many(
|
||||
'event.question', 'event_type_id',
|
||||
string='Questions', copy=True)
|
||||
|
||||
|
||||
class EventEvent(models.Model):
|
||||
@@ -14,6 +24,23 @@ class EventEvent(models.Model):
|
||||
specific_question_ids = fields.One2many('event.question', 'event_id', 'Specific Questions',
|
||||
domain=[('is_individual', '=', True)])
|
||||
|
||||
@api.onchange('event_type_id')
|
||||
def _onchange_type(self):
|
||||
super(EventEvent, self)._onchange_type()
|
||||
if self.event_type_id.use_questions and self.event_type_id.question_ids:
|
||||
self.question_ids = [(5, 0, 0)] + [
|
||||
(0, 0, {
|
||||
'title': question.title,
|
||||
'sequence': question.sequence,
|
||||
'is_individual': question.is_individual,
|
||||
'answer_ids': [(0, 0, {
|
||||
'name': answer.name,
|
||||
'sequence': answer.sequence,
|
||||
}) for answer in question.answer_ids]
|
||||
})
|
||||
for question in self.event_type_id.question_ids
|
||||
]
|
||||
|
||||
|
||||
class EventRegistrationAnswer(models.Model):
|
||||
''' This m2m table has to be explicitly instanciated as we need unique ids
|
||||
@@ -41,13 +68,19 @@ class EventQuestion(models.Model):
|
||||
_order = 'sequence,id'
|
||||
|
||||
title = fields.Char(required=True, translate=True)
|
||||
event_id = fields.Many2one('event.event', required=True, ondelete='cascade')
|
||||
event_type_id = fields.Many2one('event.type', 'Event Type', ondelete='cascade')
|
||||
event_id = fields.Many2one('event.event', 'Event', ondelete='cascade')
|
||||
answer_ids = fields.One2many('event.answer', 'question_id', "Answers", required=True, copy=True)
|
||||
sequence = fields.Integer(default=10)
|
||||
is_individual = fields.Boolean('Ask each attendee',
|
||||
help="If True, this question will be asked for every attendee of a reservation. If "
|
||||
"not it will be asked only once and its value propagated to every attendees.")
|
||||
|
||||
@api.constrains('event_type_id', 'event_id')
|
||||
def _constrains_event(self):
|
||||
if any(question.event_type_id and question.event_id for question in self):
|
||||
raise UserError(_('Question should belong to either event category or event but not both'))
|
||||
|
||||
|
||||
class EventAnswer(models.Model):
|
||||
_name = 'event.answer'
|
||||
|
||||
+25
-2
@@ -31,10 +31,33 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_view_form_inherit_question" model="ir.ui.view">
|
||||
<field name="name">event.type.view.form.inherit.question</field>
|
||||
<field name="model">event.type</field>
|
||||
<field name="inherit_id" ref="website_event.event_type_view_form_inherit_website"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="event_type_attendees_auto_confirm" position="after">
|
||||
<div class="col-xs-12 col-md-12 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="use_questions"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="use_questions"/>
|
||||
<div class="row mt16" attrs="{'invisible': [('use_ticketing', '=', False)]}">
|
||||
<div class="col-md-9">
|
||||
<field name="question_ids"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_form_inherit_question">
|
||||
<field name="name">event.form.inherit.question</field>
|
||||
<field name="name">event.event.view.form.inherit.question</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="inherit_id" ref="event.view_event_form"/>
|
||||
<field name="inherit_id" ref="website_event.event_event_view_form_inherit_website"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="//notebook" position="inside">
|
||||
@@ -3,7 +3,7 @@
|
||||
{
|
||||
'name': "Online Event's Tickets",
|
||||
'category': 'Marketing',
|
||||
'summary': "Sell Your Event's Tickets",
|
||||
'summary': "Manage Events and Sell Tickets Online",
|
||||
'website': 'https://www.odoo.com/page/events',
|
||||
'description': """
|
||||
Online Event's Tickets
|
||||
@@ -12,7 +12,8 @@ Online Event's Tickets
|
||||
""",
|
||||
'depends': ['website_event', 'event_sale', 'website_sale'],
|
||||
'data': [
|
||||
'views/website_event_sale_templates.xml',
|
||||
'data/event_data.xml',
|
||||
'views/event_templates.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/website_event_sale_security.xml',
|
||||
],
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="event_sale.event_type_data_sale" model="event.type">
|
||||
<field name="name">Sell Online</field>
|
||||
<field name="website_menu" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -92,7 +92,7 @@ class SaleOrder(models.Model):
|
||||
# adding attendees
|
||||
elif ticket and new_qty > old_qty:
|
||||
line = OrderLine.browse(values['line_id'])
|
||||
line._update_registrations(confirm=False, registration_data=kwargs.get('registration_data', []))
|
||||
line._update_registrations(confirm=False, cancel_to_draft=True, registration_data=kwargs.get('registration_data', []))
|
||||
# add in return values the registrations, to display them on website (or not)
|
||||
values['attendee_ids'] = self.env['event.registration'].search([('sale_order_line_id', '=', line.id), ('state', '!=', 'cancel')]).ids
|
||||
return values
|
||||
|
||||
+22
-2
@@ -25,6 +25,7 @@
|
||||
</xpath>
|
||||
<xpath expr="//tbody" position="replace">
|
||||
<tbody>
|
||||
<t t-set="ticket_count" t-value="len([ticket for ticket in event.event_ticket_ids if not ticket.is_expired])"/>
|
||||
<t t-foreach="event.event_ticket_ids" t-as="ticket">
|
||||
<tr itemscope="itemscope" itemtype="http://data-vocabulary.org/Offer" t-if="not ticket.is_expired">
|
||||
<td itemscope="itemscope" itemtype="http://data-vocabulary.org/Product">
|
||||
@@ -74,7 +75,12 @@
|
||||
<t t-set="seats_max_event" t-value="(event.seats_availability == 'unlimited' or event.seats_available > 9) and 10 or event.seats_available + 1"/>
|
||||
<t t-set="seats_max" t-value="min(seats_max_ticket, seats_max_event)"/>
|
||||
<t t-foreach="range(0, seats_max)" t-as="nb">
|
||||
<option t-esc="nb"/>
|
||||
<t t-if="ticket_count == 1 and nb == 1">
|
||||
<option t-esc="nb" selected="selected"/>
|
||||
</t>
|
||||
<t t-if="ticket_count != 1 or nb != 1">
|
||||
<option t-esc="nb"/>
|
||||
</t>
|
||||
</t>
|
||||
</select>
|
||||
<span t-if="(not event.seats_available and event.seats_availability == 'limited') or (ticket.seats_availability == 'limited' and not ticket.seats_available)">Sold Out</span>
|
||||
@@ -84,8 +90,16 @@
|
||||
</tbody>
|
||||
</xpath>
|
||||
<xpath expr="//button[@type='submit']" position="replace">
|
||||
<t t-set="ticket_buy" t-value="any(ticket for ticket in event.event_ticket_ids if not ticket.is_expired and ticket.price)"/>
|
||||
<button type="submit" t-if="event.state == 'confirm' and (event.seats_available or event.seats_availability == 'unlimited')"
|
||||
class="btn btn-primary btn-lg pull-right a-submit" t-attf-id="#{event.id}">Order Now</button>
|
||||
class="btn btn-primary btn-lg pull-right a-submit" t-attf-id="#{event.id}">
|
||||
<t t-if="ticket_buy">
|
||||
Order Now
|
||||
</t>
|
||||
<t t-if="not ticket_buy">
|
||||
Register Now
|
||||
</t>
|
||||
</button>
|
||||
</xpath>
|
||||
<xpath expr="//form[@id='registration_form']" position="attributes">
|
||||
<attribute name="t-if">event.event_ticket_ids</attribute>
|
||||
@@ -93,6 +107,12 @@
|
||||
</template>
|
||||
|
||||
<template id="cart" inherit_id="website_sale.cart_lines" name="Hide product reduction for event tickets">
|
||||
<xpath expr="//td[@class='td-product_name']/div/a" position="attributes">
|
||||
<attribute name="t-attf-href"/>
|
||||
<attribute name="t-att-href">
|
||||
line.event_id and ('/event/%s/register' % slug(line.event_id)) or ('/shop/product/%s' % slug(line.product_id.product_tmpl_id))
|
||||
</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//del" position="attributes">
|
||||
<attribute name="t-attf-class" separator=" " add="#{line.event_id and 'hidden' or ''}"/>
|
||||
</xpath>
|
||||
@@ -22,14 +22,14 @@ Adds support for:
|
||||
'depends': ['website_event'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/website_event_track_security.xml',
|
||||
'data/website_event_track_data.xml',
|
||||
'views/website_event_track_templates.xml',
|
||||
'views/website_event_track_views.xml',
|
||||
'security/event_track_security.xml',
|
||||
'data/event_data.xml',
|
||||
'data/event_track_data.xml',
|
||||
'views/event_track_templates.xml',
|
||||
'views/event_track_views.xml',
|
||||
'views/event_views.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/event_demo.xml',
|
||||
'data/website_event_track_demo.xml'
|
||||
],
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class WebsiteEventTrackController(http.Controller):
|
||||
'dates': dates
|
||||
}
|
||||
|
||||
@http.route(['''/event/<model("event.event", "[('show_tracks','=',1)]"):event>/agenda'''], type='http', auth="public", website=True)
|
||||
@http.route(['''/event/<model("event.event", "[('website_track','=',1)]"):event>/agenda'''], type='http', auth="public", website=True)
|
||||
def event_agenda(self, event, tag=None, **post):
|
||||
days_tracks = collections.defaultdict(lambda: [])
|
||||
for track in event.track_ids.sorted(lambda track: (track.date, bool(track.location_id))):
|
||||
@@ -79,22 +79,16 @@ class WebsiteEventTrackController(http.Controller):
|
||||
tracks_by_days[day] = tracks
|
||||
days[day] = self._prepare_calendar(event, tracks)
|
||||
|
||||
speakers = {}
|
||||
for track in event.sudo().track_ids:
|
||||
speakers_name = u" – ".join(track.speaker_ids.mapped('name'))
|
||||
speakers[track.id] = speakers_name
|
||||
|
||||
return request.render("website_event_track.agenda", {
|
||||
'event': event,
|
||||
'days': days,
|
||||
'tracks_by_days': tracks_by_days,
|
||||
'speakers': speakers,
|
||||
'tag': tag
|
||||
})
|
||||
|
||||
@http.route([
|
||||
'''/event/<model("event.event", "[('show_tracks','=',1)]"):event>/track''',
|
||||
'''/event/<model("event.event", "[('show_tracks','=',1)]"):event>/track/tag/<model("event.track.tag"):tag>'''
|
||||
'''/event/<model("event.event", "[('website_track','=',1)]"):event>/track''',
|
||||
'''/event/<model("event.event", "[('website_track','=',1)]"):event>/track/tag/<model("event.track.tag"):tag>'''
|
||||
], type='http', auth="public", website=True)
|
||||
def event_tracks(self, event, tag=None, **post):
|
||||
searches = {}
|
||||
@@ -114,7 +108,7 @@ class WebsiteEventTrackController(http.Controller):
|
||||
}
|
||||
return request.render("website_event_track.tracks", values)
|
||||
|
||||
@http.route(['''/event/<model("event.event", "[('show_track_proposal','=',1)]"):event>/track_proposal'''], type='http', auth="public", website=True)
|
||||
@http.route(['''/event/<model("event.event", "[('website_track_proposal','=',1)]"):event>/track_proposal'''], type='http', auth="public", website=True)
|
||||
def event_track_proposal(self, event, **post):
|
||||
return request.render("website_event_track.event_track_proposal", {'event': event})
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="event_type_data_tracks" model="event.type">
|
||||
<field name="name">Conference</field>
|
||||
<field name="auto_confirm" eval="True"/>
|
||||
<field name="use_mail_schedule" eval="True"/>
|
||||
<field name="website_menu" eval="True"/>
|
||||
<field name="website_track" eval="True"/>
|
||||
<field name="website_track_proposal" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -1,75 +1,399 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="event_track_tag1" model="event.track.tag">
|
||||
<field name="name">Technical</field>
|
||||
</record>
|
||||
<record id="event_track_tag2" model="event.track.tag">
|
||||
<field name="name">Business</field>
|
||||
</record>
|
||||
<record id="event_track_tag3" model="event.track.tag">
|
||||
<field name="name">Lightning Talks</field>
|
||||
</record>
|
||||
<record id="event_track_tag4" model="event.track.tag">
|
||||
<field name="name">Round Table</field>
|
||||
</record>
|
||||
<!--
|
||||
This should be done at the end so that the menu is complete
|
||||
-->
|
||||
<record id="event.event_0" model="event.event">
|
||||
<field name="show_tracks">True</field>
|
||||
<field name="show_track_proposal">True</field>
|
||||
</record>
|
||||
<record id="event_track_tag1" model="event.track.tag">
|
||||
<field name="name">Technical</field>
|
||||
</record>
|
||||
<record id="event_track_tag2" model="event.track.tag">
|
||||
<field name="name">Business</field>
|
||||
</record>
|
||||
<record id="event_track_tag3" model="event.track.tag">
|
||||
<field name="name">Lightning Talks</field>
|
||||
</record>
|
||||
<record id="event_track_tag4" model="event.track.tag">
|
||||
<field name="name">Round Table</field>
|
||||
</record>
|
||||
<!--
|
||||
This should be done at the end so that the menu is complete
|
||||
-->
|
||||
<record id="event.event_0" model="event.event">
|
||||
<field name="website_track">True</field>
|
||||
<field name="website_track_proposal">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Show menu after so that the menu is created with tracks -->
|
||||
<!-- Show menu after so that the menu is created with tracks -->
|
||||
|
||||
<record id="event.event_0" model="event.event">
|
||||
<field name="show_menu">True</field>
|
||||
</record>
|
||||
<record id="event.event_0" model="event.event">
|
||||
<field name="website_menu">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Sponsorships -->
|
||||
<!-- Sponsorships -->
|
||||
|
||||
<record id="event_sponsor_0" model="event.sponsor">
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="sponsor_type_id" ref="event_sponsor_type1"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="url">http://odoo.com</field>
|
||||
</record>
|
||||
<record id="event_sponsor_0" model="event.sponsor">
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="sponsor_type_id" ref="event_sponsor_type1"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="url">http://odoo.com</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_1" model="event.sponsor">
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="sponsor_type_id" ref="event_sponsor_type2"/>
|
||||
<field name="partner_id" ref="base.res_partner_12"/>
|
||||
<field name="url">http://odoo.com</field>
|
||||
</record>
|
||||
<record id="event_sponsor_1" model="event.sponsor">
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="sponsor_type_id" ref="event_sponsor_type2"/>
|
||||
<field name="partner_id" ref="base.res_partner_12"/>
|
||||
<field name="url">http://odoo.com</field>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_2" model="event.sponsor">
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="sponsor_type_id" ref="event_sponsor_type2"/>
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
</record>
|
||||
<record id="event_sponsor_2" model="event.sponsor">
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="sponsor_type_id" ref="event_sponsor_type2"/>
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_3" model="event.sponsor">
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="sponsor_type_id" ref="event_sponsor_type3"/>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="url">http://odoo.com</field>
|
||||
</record>
|
||||
<record id="event_sponsor_3" model="event.sponsor">
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="sponsor_type_id" ref="event_sponsor_type3"/>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="url">http://odoo.com</field>
|
||||
</record>
|
||||
|
||||
<!-- Tracks -->
|
||||
<record id="base.res_partner_address_16" model="res.partner">
|
||||
<field name="website">http://facebook.com/odoo</field>
|
||||
<field name="website_description" type="xml">
|
||||
<p>
|
||||
Ayaan has in the IT sector <b>since 20 years</b>. He
|
||||
develops software to help develop websites. He sold his
|
||||
first company at 30 years old and manage to grow OpenCorp
|
||||
from 1 to 55 employees mostly by reselling services on
|
||||
Odoo.
|
||||
</p><p>
|
||||
Ayaan is the <b>author of several books</b>, including Amazon best seller
|
||||
"How Odoo will change the business world!".
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_location5" model="event.track.location">
|
||||
<field name="name">Le Foyer du lac</field>
|
||||
</record>
|
||||
<record id="event_track_location6" model="event.track.location">
|
||||
<field name="name">Theatre</field>
|
||||
</record>
|
||||
<record id="event_track_location7" model="event.track.location">
|
||||
<field name="name">Lauzelle</field>
|
||||
</record>
|
||||
<record id="event_track_location8" model="event.track.location">
|
||||
<field name="name">Foyer Royal</field>
|
||||
</record>
|
||||
<record id="event_track_location9" model="event.track.location">
|
||||
<field name="name">Biereau</field>
|
||||
</record>
|
||||
<record id="event_track_location10" model="event.track.location">
|
||||
<field name="name">Bruyère</field>
|
||||
</record>
|
||||
<record id="event_track1" model="event.track">
|
||||
<field name="name">How to develop a website module.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 06:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location5"/>
|
||||
<field name="duration" eval="1"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="color">3</field>
|
||||
<field name="stage_id" ref="event_track_stage0"/>
|
||||
<field name="kanban_state">blocked</field>
|
||||
</record>
|
||||
<record id="event_track2" model="event.track">
|
||||
<field name="name">How to integrate hardware materials with the Odoo point of sale.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location5"/>
|
||||
<field name="duration" eval="0.25"/>
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
<field name="kanban_state">done</field>
|
||||
</record>
|
||||
<record id="event_track3" model="event.track">
|
||||
<field name="name">How to develop real time apps, the website live chat module explained.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location5"/>
|
||||
<field name="duration" eval="0.3"/>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
</record>
|
||||
<record id="event_track4" model="event.track">
|
||||
<field name="name">How to develop automated tests in the Odoo web client.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 9:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location5"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track5" model="event.track">
|
||||
<field name="name">The new way to promote your modules in the Apps platform and Odoo website.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location6"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="stage_id" ref="event_track_stage2"/>
|
||||
</record>
|
||||
<record id="event_track6" model="event.track">
|
||||
<field name="name">Detailed roadmap of accounting new modules and improvements for version 8.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location6"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
<field name="stage_id" ref="event_track_stage2"/>
|
||||
</record>
|
||||
<record id="event_track7" model="event.track">
|
||||
<field name="name">A technical explanation of Odoo as a CMS and a eCommerce platform for version 8.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location6"/>
|
||||
<field name="duration" eval="1"/>
|
||||
<field name="partner_id" ref="base.res_partner_1"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track8" model="event.track">
|
||||
<field name="name">Discover Odoo CRM: How to optimize your sales, from leads to sales orders.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">2</field>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
<field name="kanban_state">blocked</field>
|
||||
</record>
|
||||
<record id="event_track9" model="event.track">
|
||||
<field name="name">How to use Odoo for your HR process: recruitment, leaves management, appraisals, expenses, etc.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="1"/>
|
||||
<field name="color">2</field>
|
||||
<field name="partner_id" ref="base.res_partner_12"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track10" model="event.track">
|
||||
<field name="name">Raising qualitive insights with the survey app</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">5</field>
|
||||
<field name="stage_id" ref="event_track_stage0"/>
|
||||
</record>
|
||||
<record id="event_track11" model="event.track">
|
||||
<field name="name">Discover Odoo Point-of-Sale: Your shop ready to use in 30 minutes.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
</record>
|
||||
<record id="event_track12" model="event.track">
|
||||
<field name="name">Manage your events with Odoo, the new training modules.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 11:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="stage_id" ref="event_track_stage2"/>
|
||||
</record>
|
||||
<record id="event_track13" model="event.track">
|
||||
<field name="name">Advanced reporting with Google Spreadsheets integration.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location8"/>
|
||||
<field name="duration" eval="0.25"/>
|
||||
<field name="partner_id" ref="base.res_partner_12"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track14" model="event.track">
|
||||
<field name="name">New Paypal modules (portal, handling, installments).</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 7:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location8"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_10"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track15" model="event.track">
|
||||
<field name="name">Odoo Mobile for Notes, Meetings and Messages.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location8"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track16" model="event.track">
|
||||
<field name="name">Odoo as your Enterprise Social Network.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 11:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location8"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_12"/>
|
||||
<field name="stage_id" ref="event_track_stage0"/>
|
||||
</record>
|
||||
<record id="event_track17" model="event.track">
|
||||
<field name="name">The Art of Making an Odoo Demo.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_10"/>
|
||||
<field name="stage_id" ref="event_track_stage0"/>
|
||||
</record>
|
||||
<record id="event_track18" model="event.track">
|
||||
<field name="name">How to build your marketing strategy for the purpose of generating leads with Odoo.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">5</field>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
</record>
|
||||
<record id="event_track19" model="event.track">
|
||||
<field name="name">Advanced lead management with Odoo: tips and tricks from the fields</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 9:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">5</field>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
</record>
|
||||
<record id="event_track20" model="event.track">
|
||||
<field name="name">New Certification Program (valid from Oct. 2013).</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
</record>
|
||||
<record id="event_track21" model="event.track">
|
||||
<field name="name">Recruiting high skilled talents with Odoo HR apps</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">7</field>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
</record>
|
||||
<record id="event_track22" model="event.track">
|
||||
<field name="name">Manage your KPIs (recomended to openERP partners).</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 11:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
<field name="stage_id" ref="event_track_stage0"/>
|
||||
</record>
|
||||
<record id="event_track23" model="event.track">
|
||||
<field name="name">Key Success factors selling Odoo.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 7:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_1"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track24" model="event.track">
|
||||
<field name="name">Merge proposals review, code sprint (entire day).</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location10"/>
|
||||
<field name="duration" eval="1.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_18"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track25" model="event.track">
|
||||
<field name="name">Merge proposals review, code sprint (entire afternoon)</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location10"/>
|
||||
<field name="duration" eval="2.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_18"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
</record>
|
||||
<record id="event_track27" model="event.track">
|
||||
<field name="name">Odoo in 2014</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 04:00:00')"></field>
|
||||
<field name="duration" eval="1"/>
|
||||
<field name="partner_id" ref="base.res_partner_1"/>
|
||||
<field name="stage_id" ref="event_track_stage3"/>
|
||||
<field name="color">3</field>
|
||||
</record>
|
||||
<record id="event_track28" model="event.track">
|
||||
<field name="name">Odoo Status & Strategy 2014</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 5:00:00')"></field>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="stage_id" ref="event_track_stage2"/>
|
||||
</record>
|
||||
<record id="event_track29" model="event.track">
|
||||
<field name="name">The new marketing strategy.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 5:30:00')"></field>
|
||||
<field name="duration" eval="0.25"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="stage_id" ref="event_track_stage2"/>
|
||||
<field name="color">6</field>
|
||||
</record>
|
||||
<record id="event_track30" model="event.track">
|
||||
<field name="name">Morning break</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 5:45:00')"></field>
|
||||
<field name="duration" eval="0.25"/>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
</record>
|
||||
<record id="event_track31" model="event.track">
|
||||
<field name="name">Lunch</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 7:30:00')"></field>
|
||||
<field name="duration" eval="1"/>
|
||||
<field name="stage_id" ref="event_track_stage1"/>
|
||||
</record>
|
||||
|
||||
<!-- Tracks -->
|
||||
<record id="base.res_partner_address_16" model="res.partner">
|
||||
<field name="website">http://facebook.com/odoo</field>
|
||||
<field name="website_description" type="xml">
|
||||
<p>
|
||||
Ayaan has in the IT sector <b>since 20 years</b>. He
|
||||
develops software to help develop websites. He sold his
|
||||
first company at 30 years old and manage to grow OpenCorp
|
||||
from 1 to 55 employees mostly by reselling services on
|
||||
Odoo.
|
||||
</p><p>
|
||||
Ayaan is the <b>author of several books</b>, including Amazon best seller
|
||||
"How Odoo will change the business world!".
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- Email templates -->
|
||||
<record id="mail_template_data_track_confirmation" model="mail.template">
|
||||
<field name="name">Track: Confirmation</field>
|
||||
<field name="subject">Confirmation of ${object.name}</field>
|
||||
<field name="model_id" ref="website_event_track.model_event_track"/>
|
||||
<field name="use_default_to" eval="True"/>
|
||||
<field name="body_html" type="xml">
|
||||
<div>
|
||||
<p>
|
||||
Dear <t t-esc="object.partner_name"/>
|
||||
</p><p>
|
||||
We are pleased to inform you that your proposal ${object.name} has been accepted and confirmed for the event ${object.event_id.name}.
|
||||
</p><p>
|
||||
You will find more details here:
|
||||
<div style="margin-top: 16px;">
|
||||
<a href="/event/${object.event_id.id}/"
|
||||
style="padding: 8px 12px; font-size: 12px; color: #FFFFFF; text-decoration: none !important; font-weight: 400; background-color: #875A7B; border: 0px solid #875A7B; border-radius:3px">
|
||||
View Event
|
||||
</a>
|
||||
</div>
|
||||
</p>
|
||||
<p>Sincerely,</p>
|
||||
</div>
|
||||
</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="event_sponsor_type1" model="event.sponsor.type">
|
||||
<field name="name">Bronze</field>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
<record id="event_sponsor_type2" model="event.sponsor.type">
|
||||
<field name="name">Silver</field>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
<record id="event_sponsor_type3" model="event.sponsor.type">
|
||||
<field name="name">Gold</field>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_stage0" model="event.track.stage">
|
||||
<field name="name">Proposal</field>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
<record id="event_track_stage1" model="event.track.stage">
|
||||
<field name="name">Confirmed</field>
|
||||
<field name="sequence">2</field>
|
||||
<field name="mail_template_id" ref="mail_template_data_track_confirmation"/>
|
||||
</record>
|
||||
<record id="event_track_stage2" model="event.track.stage">
|
||||
<field name="name">Announced</field>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
<record id="event_track_stage3" model="event.track.stage">
|
||||
<field name="name">Published</field>
|
||||
<field name="sequence">4</field>
|
||||
<field name="is_done" eval="True"/>
|
||||
</record>
|
||||
<record id="event_track_stage4" model="event.track.stage">
|
||||
<field name="name">Refused</field>
|
||||
<field name="sequence">5</field>
|
||||
<field name="fold" eval="True"/>
|
||||
</record>
|
||||
<record id="event_track_stage5" model="event.track.stage">
|
||||
<field name="name">Cancelled</field>
|
||||
<field name="sequence">6</field>
|
||||
<field name="fold" eval="True"/>
|
||||
<field name="is_cancel" eval="True"/>
|
||||
</record>
|
||||
|
||||
<!-- Event-related subtypes for new track / Chatter -->
|
||||
<record id="mt_event_track" model="mail.message.subtype">
|
||||
<field name="name">New Track</field>
|
||||
<field name="res_model">event.event</field>
|
||||
<field name="description">New Track Created</field>
|
||||
<field name="default" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- Track subtypes -->
|
||||
<record id="mt_track_blocked" model="mail.message.subtype">
|
||||
<field name="name">Track Blocked</field>
|
||||
<field name="res_model">event.track</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="internal" eval="True"/>
|
||||
<field name="description">Track blocked</field>
|
||||
</record>
|
||||
<record id="mt_track_ready" model="mail.message.subtype">
|
||||
<field name="name">Track Ready</field>
|
||||
<field name="res_model">event.track</field>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="internal" eval="True"/>
|
||||
<field name="description">Track Ready for Next Stage</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="event_sponsor_type1" model="event.sponsor.type">
|
||||
<field name="name">Bronze</field>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
<record id="event_sponsor_type2" model="event.sponsor.type">
|
||||
<field name="name">Silver</field>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
<record id="event_sponsor_type3" model="event.sponsor.type">
|
||||
<field name="name">Gold</field>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
|
||||
<!-- Event-related subtypes for new track / Chatter -->
|
||||
<record id="mt_event_track" model="mail.message.subtype">
|
||||
<field name="name">New Track</field>
|
||||
<field name="res_model">event.event</field>
|
||||
<field name="description">New Track Created</field>
|
||||
<field name="default" eval="False"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -1,325 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="event_track_location5" model="event.track.location">
|
||||
<field name="name">Le Foyer du lac</field>
|
||||
</record>
|
||||
<record id="event_track_location6" model="event.track.location">
|
||||
<field name="name">Theatre</field>
|
||||
</record>
|
||||
<record id="event_track_location7" model="event.track.location">
|
||||
<field name="name">Lauzelle</field>
|
||||
</record>
|
||||
<record id="event_track_location8" model="event.track.location">
|
||||
<field name="name">Foyer Royal</field>
|
||||
</record>
|
||||
<record id="event_track_location9" model="event.track.location">
|
||||
<field name="name">Biereau</field>
|
||||
</record>
|
||||
<record id="event_track_location10" model="event.track.location">
|
||||
<field name="name">Bruyère</field>
|
||||
</record>
|
||||
<record id="event_track1" model="event.track">
|
||||
<field name="name">How to develop a website module.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 06:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location5"/>
|
||||
<field name="duration" eval="1"/>
|
||||
<field eval="[(4, ref('base.res_partner_2')),(4, ref('base.res_partner_3'))]" name="speaker_ids"/>
|
||||
<field name="color">3</field>
|
||||
<field name="state">draft</field>
|
||||
|
||||
</record>
|
||||
<record id="event_track2" model="event.track">
|
||||
<field name="name">How to integrate hardware materials with the Odoo point of sale.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location5"/>
|
||||
<field name="duration" eval="0.25"/>
|
||||
<field eval="[(4, ref('base.res_partner_3'))]" name="speaker_ids"/>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
<record id="event_track3" model="event.track">
|
||||
<field name="name">How to develop real time apps, the website live chat module explained.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location5"/>
|
||||
<field name="duration" eval="0.3"/>
|
||||
<field eval="[(4, ref('base.res_partner_4'))]" name="speaker_ids"/>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
<record id="event_track4" model="event.track">
|
||||
<field name="name">How to develop automated tests in the Odoo web client.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 9:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location5"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_2'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
</record>
|
||||
<record id="event_track5" model="event.track">
|
||||
<field name="name">The new way to promote your modules in the Apps platform and Odoo website.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location6"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_4'))]" name="speaker_ids"/>
|
||||
<field name="state">announced</field>
|
||||
</record>
|
||||
<record id="event_track6" model="event.track">
|
||||
<field name="name">Detailed roadmap of accounting new modules and improvements for version 8.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location6"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_3'))]" name="speaker_ids"/>
|
||||
<field name="state">announced</field>
|
||||
</record>
|
||||
<record id="event_track7" model="event.track">
|
||||
<field name="name">A technical explanation of Odoo as a CMS and a eCommerce platform for version 8.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location6"/>
|
||||
<field name="duration" eval="1"/>
|
||||
<field eval="[(4, ref('base.res_partner_1'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
</record>
|
||||
<record id="event_track8" model="event.track">
|
||||
<field name="name">Discover Odoo CRM: How to optimize your sales, from leads to sales orders.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">2</field>
|
||||
<field eval="[(4, ref('base.res_partner_4'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
</record>
|
||||
<record id="event_track9" model="event.track">
|
||||
<field name="name">How to use Odoo for your HR process: recruitment, leaves management, appraisals, expenses, etc.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="1"/>
|
||||
<field name="color">2</field>
|
||||
<field eval="[(4, ref('base.res_partner_12'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
</record>
|
||||
<record id="event_track10" model="event.track">
|
||||
<field name="name">Raising qualitive insights with the survey app</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">5</field>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
<record id="event_track11" model="event.track">
|
||||
<field name="name">Discover Odoo Point-of-Sale: Your shop ready to use in 30 minutes.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_4'))]" name="speaker_ids"/>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
<record id="event_track12" model="event.track">
|
||||
<field name="name">Manage your events with Odoo, the new training modules.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 11:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location7"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_2')),(4, ref('base.res_partner_12'))]" name="speaker_ids"/>
|
||||
<field name="state">announced</field>
|
||||
</record>
|
||||
<record id="event_track13" model="event.track">
|
||||
<field name="name">Advanced reporting with Google Spreadsheets integration.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location8"/>
|
||||
<field name="duration" eval="0.25"/>
|
||||
<field eval="[(4, ref('base.res_partner_12'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
</record>
|
||||
<record id="event_track14" model="event.track">
|
||||
<field name="name">New Paypal modules (portal, handling, installments).</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 7:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location8"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_10'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
</record>
|
||||
<record id="event_track15" model="event.track">
|
||||
<field name="name">Odoo Mobile for Notes, Meetings and Messages.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location8"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_3'))]" name="speaker_ids"/>
|
||||
<field name="state">announced</field>
|
||||
</record>
|
||||
<record id="event_track16" model="event.track">
|
||||
<field name="name">Odoo as your Enterprise Social Network.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 11:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location8"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_12'))]" name="speaker_ids"/>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
<record id="event_track17" model="event.track">
|
||||
<field name="name">The Art of Making an Odoo Demo.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_10'))]" name="speaker_ids"/>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
<record id="event_track18" model="event.track">
|
||||
<field name="name">How to build your marketing strategy for the purpose of generating leads with Odoo.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">5</field>
|
||||
<field eval="[(4, ref('base.res_partner_2'))]" name="speaker_ids"/>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
<record id="event_track19" model="event.track">
|
||||
<field name="name">Advanced lead management with Odoo: tips and tricks from the fields</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 9:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">5</field>
|
||||
<field eval="[(4, ref('base.res_partner_4'))]" name="speaker_ids"/>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
<record id="event_track20" model="event.track">
|
||||
<field name="name">New Certification Program (valid from Oct. 2013).</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_3'))]" name="speaker_ids"/>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
<record id="event_track21" model="event.track">
|
||||
<field name="name">Recruiting high skilled talents with Odoo HR apps</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 10:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field name="color">7</field>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
<record id="event_track22" model="event.track">
|
||||
<field name="name">Manage your KPIs (recomended to openERP partners).</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 11:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_3'))]" name="speaker_ids"/>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
<record id="event_track23" model="event.track">
|
||||
<field name="name">Key Success factors selling Odoo.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 7:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location9"/>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_1'))]" name="speaker_ids"/>
|
||||
<field name="state">announced</field>
|
||||
</record>
|
||||
<record id="event_track24" model="event.track">
|
||||
<field name="name">Merge proposals review, code sprint (entire day).</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 6:00:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location10"/>
|
||||
<field name="duration" eval="1.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_12')),(4, ref('base.res_partner_18'))]" name="speaker_ids"/>
|
||||
<field name="state">announced</field>
|
||||
</record>
|
||||
<record id="event_track25" model="event.track">
|
||||
<field name="name">Merge proposals review, code sprint (entire afternoon)</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 8:30:00')"></field>
|
||||
<field name="location_id" ref="website_event_track.event_track_location10"/>
|
||||
<field name="duration" eval="2.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_12')),(4, ref('base.res_partner_18'))]" name="speaker_ids"/>
|
||||
<field name="state">announced</field>
|
||||
</record>
|
||||
<record id="event_track27" model="event.track">
|
||||
<field name="name">Odoo in 2014</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 04:00:00')"></field>
|
||||
<field name="duration" eval="1"/>
|
||||
<field eval="[(4, ref('base.res_partner_1'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
<field name="color">3</field>
|
||||
</record>
|
||||
<record id="event_track28" model="event.track">
|
||||
<field name="name">Odoo Status & Strategy 2014</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 5:00:00')"></field>
|
||||
<field name="duration" eval="0.5"/>
|
||||
<field eval="[(4, ref('base.res_partner_2'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
</record>
|
||||
<record id="event_track29" model="event.track">
|
||||
<field name="name">The new marketing strategy.</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 5:30:00')"></field>
|
||||
<field name="duration" eval="0.25"/>
|
||||
<field eval="[(4, ref('base.res_partner_2'))]" name="speaker_ids"/>
|
||||
<field name="state">published</field>
|
||||
<field name="color">6</field>
|
||||
</record>
|
||||
<record id="event_track30" model="event.track">
|
||||
<field name="name">Morning break</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 5:45:00')"></field>
|
||||
<field name="duration" eval="0.25"/>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
<record id="event_track31" model="event.track">
|
||||
<field name="name">Lunch</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="event_id" ref="event.event_0"/>
|
||||
<field name="date" eval="time.strftime(str(DateTime.today().year) + '-06-04 7:30:00')"></field>
|
||||
<field name="duration" eval="1"/>
|
||||
<field name="state">confirmed</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import website_event_track
|
||||
import event_track
|
||||
import event
|
||||
|
||||
@@ -5,53 +5,76 @@ from odoo import api, fields, models, _
|
||||
from odoo.addons.website.models.website import slug
|
||||
|
||||
|
||||
class EventType(models.Model):
|
||||
_inherit = 'event.type'
|
||||
|
||||
website_track = fields.Boolean('Tracks on Website')
|
||||
website_track_proposal = fields.Boolean('Tracks Proposals on Website')
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
_inherit = "event.event"
|
||||
|
||||
track_ids = fields.One2many('event.track', 'event_id', 'Tracks')
|
||||
track_count = fields.Integer('Tracks', compute='_compute_track_count')
|
||||
|
||||
sponsor_ids = fields.One2many('event.sponsor', 'event_id', 'Sponsors')
|
||||
show_track_proposal = fields.Boolean('Tracks Proposals', compute='_get_show_menu', inverse='_set_show_menu', store=True)
|
||||
show_tracks = fields.Boolean('Show Tracks on Website', compute='_get_show_menu', inverse='_set_show_menu', store=True)
|
||||
count_tracks = fields.Integer('Tracks', compute='_count_tracks')
|
||||
sponsor_count = fields.Integer('Sponsors', compute='_compute_sponsor_count')
|
||||
|
||||
website_track = fields.Boolean('Tracks on Website', compute='_compute_website_track', inverse='_set_website_menu')
|
||||
website_track_proposal = fields.Boolean('Proposals on Website', compute='_compute_website_track_proposal', inverse='_set_website_menu')
|
||||
|
||||
allowed_track_tag_ids = fields.Many2many('event.track.tag', relation='event_allowed_track_tags_rel', string='Available Track Tags')
|
||||
tracks_tag_ids = fields.Many2many('event.track.tag', relation='event_track_tags_rel', string='Track Tags', compute='_get_tracks_tag_ids', store=True)
|
||||
count_sponsor = fields.Integer('# Sponsors', compute='_count_sponsor')
|
||||
tracks_tag_ids = fields.Many2many(
|
||||
'event.track.tag', relation='event_track_tags_rel', string='Track Tags',
|
||||
compute='_compute_tracks_tag_ids', store=True)
|
||||
|
||||
@api.multi
|
||||
def _get_new_menu_pages(self):
|
||||
self.ensure_one()
|
||||
result = super(Event, self)._get_new_menu_pages()
|
||||
if self.show_tracks:
|
||||
result.append((_('Talks'), '/event/%s/track' % slug(self)))
|
||||
result.append((_('Agenda'), '/event/%s/agenda' % slug(self)))
|
||||
if self.show_track_proposal:
|
||||
result.append((_('Talk Proposals'), '/event/%s/track_proposal' % slug(self)))
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def _set_show_menu(self):
|
||||
def _compute_track_count(self):
|
||||
data = self.env['event.track'].read_group([('stage_id.is_cancel', '!=', True)], ['event_id'], ['event_id'])
|
||||
result = dict((data['event_id'][0], data['event_id_count']) for data in data)
|
||||
for event in self:
|
||||
# if the number of menu items have changed, then menu items must be regenerated
|
||||
if event.menu_id:
|
||||
nbr_menu_items = len(event._get_new_menu_pages())
|
||||
if nbr_menu_items != len(event.menu_id.child_id):
|
||||
event.menu_id.unlink()
|
||||
return super(Event, self)._set_show_menu()
|
||||
event.track_count = result.get(event.id, 0)
|
||||
|
||||
@api.multi
|
||||
def _count_tracks(self):
|
||||
track_data = self.env['event.track'].read_group([('state', '!=', 'cancel')], ['event_id', 'state'], ['event_id'])
|
||||
result = dict((data['event_id'][0], data['event_id_count']) for data in track_data)
|
||||
def _compute_sponsor_count(self):
|
||||
data = self.env['event.sponsor'].read_group([], ['event_id'], ['event_id'])
|
||||
result = dict((data['event_id'][0], data['event_id_count']) for data in data)
|
||||
for event in self:
|
||||
event.count_tracks = result.get(event.id, 0)
|
||||
event.sponsor_count = result.get(event.id, 0)
|
||||
|
||||
@api.multi
|
||||
def _compute_website_track(self):
|
||||
for event in self:
|
||||
existing_pages = event.menu_id.child_id.mapped('name')
|
||||
event.website_track = _('Talks') in existing_pages
|
||||
|
||||
@api.multi
|
||||
def _compute_website_track_proposal(self):
|
||||
for event in self:
|
||||
existing_pages = event.menu_id.child_id.mapped('name')
|
||||
event.website_track_proposal = _('Talk Proposals') in existing_pages
|
||||
|
||||
@api.multi
|
||||
@api.depends('track_ids.tag_ids')
|
||||
def _get_tracks_tag_ids(self):
|
||||
def _compute_tracks_tag_ids(self):
|
||||
for event in self:
|
||||
event.tracks_tag_ids = event.track_ids.mapped('tag_ids').ids
|
||||
|
||||
@api.multi
|
||||
def _count_sponsor(self):
|
||||
for event in self:
|
||||
event.count_sponsor = len(event.sponsor_ids)
|
||||
@api.onchange('event_type_id')
|
||||
def _onchange_type(self):
|
||||
super(Event, self)._onchange_type()
|
||||
if self.event_type_id:
|
||||
self.website_track = self.event_type_id.website_track
|
||||
self.website_track_proposal = self.event_type_id.website_track_proposal
|
||||
|
||||
def _get_menu_entries(self):
|
||||
self.ensure_one()
|
||||
res = super(Event, self)._get_menu_entries()
|
||||
if self.website_track:
|
||||
res += [
|
||||
(_('Talks'), '/event/%s/track' % slug(self), False),
|
||||
(_('Agenda'), '/event/%s/agenda' % slug(self), False)]
|
||||
if self.website_track_proposal:
|
||||
res += [(_('Talk Proposals'), '/event/%s/track_proposal' % slug(self), False)]
|
||||
return res
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.translate import _, html_translate
|
||||
from odoo.addons.website.models.website import slug
|
||||
|
||||
|
||||
class TrackTag(models.Model):
|
||||
_name = "event.track.tag"
|
||||
_description = 'Track Tag'
|
||||
_order = 'name'
|
||||
|
||||
name = fields.Char('Tag')
|
||||
track_ids = fields.Many2many('event.track', string='Tracks')
|
||||
color = fields.Integer(string='Color Index', default=10)
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', "Tag name already exists !"),
|
||||
]
|
||||
|
||||
|
||||
class TrackLocation(models.Model):
|
||||
_name = "event.track.location"
|
||||
_description = 'Track Location'
|
||||
|
||||
name = fields.Char('Room')
|
||||
|
||||
|
||||
class TrackStage(models.Model):
|
||||
_name = 'event.track.stage'
|
||||
_description = 'Track Stage'
|
||||
_order = 'sequence, id'
|
||||
|
||||
name = fields.Char(string='Stage Name', required=True, translate=True)
|
||||
sequence = fields.Integer(string='Sequence', default=1)
|
||||
mail_template_id = fields.Many2one(
|
||||
'mail.template', string='Email Template',
|
||||
domain=[('model', '=', 'event.track')],
|
||||
help="If set an email will be sent to the customer when the track reaches this step.")
|
||||
fold = fields.Boolean(
|
||||
string='Folded in Kanban',
|
||||
help='This stage is folded in the kanban view when there are no records in that stage to display.')
|
||||
is_done = fields.Boolean(string='Accepted Stage')
|
||||
is_cancel = fields.Boolean(string='Canceled Stage')
|
||||
|
||||
|
||||
class Track(models.Model):
|
||||
_name = "event.track"
|
||||
_description = 'Event Track'
|
||||
_order = 'priority, date'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin', 'website.seo.metadata', 'website.published.mixin']
|
||||
_mail_mass_mailing = _('Track Speakers')
|
||||
|
||||
@api.model
|
||||
def _get_default_stage_id(self):
|
||||
return self.env['event.track.stage'].search([], limit=1).id
|
||||
|
||||
name = fields.Char('Title', required=True, translate=True)
|
||||
active = fields.Boolean(default=True)
|
||||
user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange', default=lambda self: self.env.user)
|
||||
partner_id = fields.Many2one('res.partner', 'Speaker')
|
||||
partner_name = fields.Char('Speaker Name')
|
||||
partner_email = fields.Char('Speaker Email')
|
||||
partner_phone = fields.Char('Speaker Phone')
|
||||
partner_biography = fields.Html('Speaker Biography')
|
||||
tag_ids = fields.Many2many('event.track.tag', string='Tags')
|
||||
stage_id = fields.Many2one(
|
||||
'event.track.stage', string='Stage',
|
||||
index=True, copy=False, default=_get_default_stage_id,
|
||||
group_expand='_read_group_stage_ids',
|
||||
required=True, track_visibility='onchange')
|
||||
kanban_state = fields.Selection([
|
||||
('normal', 'Grey'),
|
||||
('done', 'Green'),
|
||||
('blocked', 'Red')], string='Kanban State',
|
||||
copy=False, default='normal', required=True, track_visibility='onchange',
|
||||
help="A track's kanban state indicates special situations affecting it:\n"
|
||||
" * Grey is the default situation\n"
|
||||
" * Red indicates something is preventing the progress of this track\n"
|
||||
" * Green indicates the track is ready to be pulled to the next stage")
|
||||
description = fields.Html('Track Description', translate=html_translate, sanitize_attributes=False)
|
||||
date = fields.Datetime('Track Date')
|
||||
duration = fields.Float('Duration', default=1.5)
|
||||
location_id = fields.Many2one('event.track.location', 'Room')
|
||||
event_id = fields.Many2one('event.event', 'Event', required=True)
|
||||
color = fields.Integer('Color Index')
|
||||
priority = fields.Selection([
|
||||
('0', 'Low'), ('1', 'Medium'),
|
||||
('2', 'High'), ('3', 'Highest')],
|
||||
'Priority', required=True, default='1')
|
||||
image = fields.Binary('Image', related='partner_id.image_medium', store=True, attachment=True)
|
||||
|
||||
@api.multi
|
||||
@api.depends('name')
|
||||
def _compute_website_url(self):
|
||||
super(Track, self)._compute_website_url()
|
||||
for track in self:
|
||||
if not isinstance(track.id, models.NewId):
|
||||
track.website_url = '/event/%s/track/%s' % (slug(track.event_id), slug(track))
|
||||
|
||||
@api.onchange('partner_id')
|
||||
def _onchange_partner_id(self):
|
||||
if self.partner_id:
|
||||
self.partner_name = self.partner_id.name
|
||||
self.partner_email = self.partner_id.email
|
||||
self.partner_phone = self.partner_id.phone
|
||||
self.partner_biography = self.partner_id.website_description
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
track = super(Track, self).create(vals)
|
||||
|
||||
track.event_id.message_post_with_view(
|
||||
'website_event_track.event_track_template_new',
|
||||
values={'track': track},
|
||||
subject=track.name,
|
||||
subtype_id=self.env.ref('website_event_track.mt_event_track').id,
|
||||
)
|
||||
|
||||
return track
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if 'stage_id' in vals and 'kanban_state' not in vals:
|
||||
vals['kanban_state'] = 'normal'
|
||||
res = super(Track, self).write(vals)
|
||||
if vals.get('partner_id'):
|
||||
self.message_subscribe(vals['partner_id'])
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _read_group_stage_ids(self, stages, domain, order):
|
||||
""" Always display all stages """
|
||||
return stages.search([], order=order)
|
||||
|
||||
@api.multi
|
||||
def _track_template(self, tracking):
|
||||
res = super(Track, self)._track_template(tracking)
|
||||
track = self[0]
|
||||
changes, tracking_value_ids = tracking[track.id]
|
||||
if 'stage_id' in changes and track.stage_id.mail_template_id:
|
||||
res['stage_id'] = (track.stage_id.mail_template_id, {'composition_mode': 'mass_mail'})
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _track_subtype(self, init_values):
|
||||
self.ensure_one()
|
||||
if 'kanban_state' in init_values and self.kanban_state == 'blocked':
|
||||
return 'website_event_track.mt_track_blocked'
|
||||
elif 'kanban_state' in init_values and self.kanban_state == 'done':
|
||||
return 'website_event_track.mt_track_ready'
|
||||
return super(Track, self)._track_subtype(init_values)
|
||||
|
||||
@api.multi
|
||||
def message_get_suggested_recipients(self):
|
||||
recipients = super(Track, self).message_get_suggested_recipients()
|
||||
for track in self:
|
||||
if track.partner_email != track.partner_id.email:
|
||||
track._message_add_suggested_recipient(recipients, email=track.partner_email, reason=_('Speaker Email'))
|
||||
return recipients
|
||||
|
||||
@api.multi
|
||||
def open_track_speakers_list(self):
|
||||
return {
|
||||
'name': _('Speakers'),
|
||||
'domain': [('id', 'in', self.mapped('partner_id').ids)],
|
||||
'view_type': 'form',
|
||||
'view_mode': 'kanban,form',
|
||||
'res_model': 'res.partner',
|
||||
'view_id': False,
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
|
||||
class SponsorType(models.Model):
|
||||
_name = "event.sponsor.type"
|
||||
_description = 'Event Sponsor Type'
|
||||
_order = "sequence"
|
||||
|
||||
name = fields.Char('Sponsor Type', required=True, translate=True)
|
||||
sequence = fields.Integer('Sequence')
|
||||
|
||||
|
||||
class Sponsor(models.Model):
|
||||
_name = "event.sponsor"
|
||||
_description = 'Event Sponsor'
|
||||
_order = "sequence"
|
||||
|
||||
event_id = fields.Many2one('event.event', 'Event', required=True)
|
||||
sponsor_type_id = fields.Many2one('event.sponsor.type', 'Sponsoring Type', required=True)
|
||||
partner_id = fields.Many2one('res.partner', 'Sponsor/Customer', required=True)
|
||||
url = fields.Char('Sponsor Website')
|
||||
sequence = fields.Integer('Sequence', store=True, related='sponsor_type_id.sequence')
|
||||
image_medium = fields.Binary(string='Logo', related='partner_id.image_medium', store=True, attachment=True)
|
||||
@@ -1,152 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.translate import _, html_translate
|
||||
from odoo.addons.website.models.website import slug
|
||||
|
||||
|
||||
class TrackTag(models.Model):
|
||||
|
||||
_name = "event.track.tag"
|
||||
_description = 'Track Tag'
|
||||
_order = 'name'
|
||||
|
||||
name = fields.Char('Tag')
|
||||
track_ids = fields.Many2many('event.track', string='Tracks')
|
||||
color = fields.Integer(string='Color Index', default=10)
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', "Tag name already exists !"),
|
||||
]
|
||||
|
||||
|
||||
class TrackLocation(models.Model):
|
||||
|
||||
_name = "event.track.location"
|
||||
_description = 'Track Location'
|
||||
|
||||
name = fields.Char('Room')
|
||||
|
||||
|
||||
class Track(models.Model):
|
||||
|
||||
_name = "event.track"
|
||||
_description = 'Event Track'
|
||||
_order = 'priority, date'
|
||||
_inherit = ['mail.thread', 'website.seo.metadata', 'website.published.mixin']
|
||||
|
||||
name = fields.Char('Title', required=True, translate=True)
|
||||
active = fields.Boolean(default=True)
|
||||
user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange', default=lambda self: self.env.user)
|
||||
partner_id = fields.Many2one('res.partner', 'Proposed by')
|
||||
partner_name = fields.Char('Partner Name')
|
||||
partner_email = fields.Char('Partner Email')
|
||||
partner_phone = fields.Char('Partner Phone')
|
||||
partner_biography = fields.Html('Partner Biography')
|
||||
speaker_ids = fields.Many2many('res.partner', string='Speakers')
|
||||
tag_ids = fields.Many2many('event.track.tag', string='Tags')
|
||||
state = fields.Selection([
|
||||
('draft', 'Proposal'), ('confirmed', 'Confirmed'), ('announced', 'Announced'), ('published', 'Published'), ('refused', 'Refused'), ('cancel', 'Cancelled')],
|
||||
'Status', default='draft', required=True, copy=False, track_visibility='onchange')
|
||||
description = fields.Html('Track Description', translate=html_translate, sanitize_attributes=False)
|
||||
date = fields.Datetime('Track Date')
|
||||
duration = fields.Float('Duration', default=1.5)
|
||||
location_id = fields.Many2one('event.track.location', 'Room')
|
||||
event_id = fields.Many2one('event.event', 'Event', required=True)
|
||||
color = fields.Integer('Color Index')
|
||||
priority = fields.Selection([
|
||||
('0', 'Low'), ('1', 'Medium'),
|
||||
('2', 'High'), ('3', 'Highest')],
|
||||
'Priority', required=True, default='1')
|
||||
image = fields.Binary('Image', related='speaker_ids.image_medium', store=True, attachment=True)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(Track, self).create(vals)
|
||||
res.message_subscribe(res.speaker_ids.ids)
|
||||
res.message_post_with_view(
|
||||
'website_event_track.event_track_template_new',
|
||||
subject=res.name,
|
||||
subtype_id=self.env['ir.model.data'].xmlid_to_res_id('website_event_track.mt_event_track'))
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if vals.get('state') == 'published':
|
||||
vals.update({'website_published': True})
|
||||
res = super(Track, self).write(vals)
|
||||
if vals.get('speaker_ids'):
|
||||
self.message_subscribe([speaker['id'] for speaker in self.resolve_2many_commands('speaker_ids', vals['speaker_ids'], ['id'])])
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
@api.depends('name')
|
||||
def _compute_website_url(self):
|
||||
super(Track, self)._compute_website_url()
|
||||
for track in self:
|
||||
if not isinstance(track.id, models.NewId):
|
||||
track.website_url = '/event/%s/track/%s' % (slug(track.event_id), slug(track))
|
||||
|
||||
@api.model
|
||||
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
|
||||
""" Override read_group to always display all states. """
|
||||
if groupby and groupby[0] == "state":
|
||||
# Default result structure
|
||||
states = [('draft', 'Proposal'), ('confirmed', 'Confirmed'), ('announced', 'Announced'), ('published', 'Published'), ('cancel', 'Cancelled')]
|
||||
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(Track, self).read_group(domain, fields, groupby, offset=offset, limit=limit, 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)
|
||||
if state_value == 'cancel':
|
||||
res[0]['__fold'] = True
|
||||
res[0]['state'] = [state_value, state_name]
|
||||
result.append(res[0])
|
||||
return result
|
||||
else:
|
||||
return super(Track, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby)
|
||||
|
||||
@api.multi
|
||||
def open_track_speakers_list(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'name': _('Speakers'),
|
||||
'domain': [('id', 'in', [partner.id for partner in self.speaker_ids])],
|
||||
'view_type': 'form',
|
||||
'view_mode': 'kanban,form',
|
||||
'res_model': 'res.partner',
|
||||
'view_id': False,
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
|
||||
class SponsorType(models.Model):
|
||||
|
||||
_name = "event.sponsor.type"
|
||||
_order = "sequence"
|
||||
|
||||
name = fields.Char('Sponsor Type', required=True, translate=True)
|
||||
sequence = fields.Integer('Sequence')
|
||||
|
||||
|
||||
class Sponsor(models.Model):
|
||||
|
||||
_name = "event.sponsor"
|
||||
_order = "sequence"
|
||||
|
||||
event_id = fields.Many2one('event.event', 'Event', required=True)
|
||||
sponsor_type_id = fields.Many2one('event.sponsor.type', 'Sponsoring Type', required=True)
|
||||
partner_id = fields.Many2one('res.partner', 'Sponsor/Customer', required=True)
|
||||
url = fields.Char('Sponsor Website')
|
||||
sequence = fields.Integer('Sequence', store=True, related='sponsor_type_id.sequence')
|
||||
image_medium = fields.Binary(string='Logo', related='partner_id.image_medium', store=True, attachment=True)
|
||||
@@ -10,3 +10,5 @@ access_event_track_sponsor_type_manager,event.track.sponsor.type.public,model_ev
|
||||
access_event_track_sponsor_type_public,event.track.sponsor.type.public,model_event_sponsor_type,,1,0,0,0
|
||||
access_event_track_sponsor_manager,event.track.sponsor.type.public,model_event_sponsor,event.group_event_manager,1,1,1,1
|
||||
access_event_track_sponsor_public,event.track.sponsor.public,model_event_sponsor,,1,0,0,0
|
||||
access_event_track_stage_all,event.track.stage.all,model_event_track_stage,,1,0,0,0
|
||||
access_event_track_stage_event_manager,event.track.stage.event.manager,model_event_track_stage,event.group_event_manager,1,1,1,1
|
||||
|
+19
-19
@@ -80,9 +80,10 @@
|
||||
<t t-if="track">
|
||||
<a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }">
|
||||
<span t-esc="track and track.name"/>
|
||||
<span t-if="not track.website_published" class="label label-warning">unpublished</span>
|
||||
</a>
|
||||
<div class="text-muted">
|
||||
<small t-esc="speakers[track.id]"/>
|
||||
<small t-esc="track.partner_id.sudo().name"/>
|
||||
</div>
|
||||
</t>
|
||||
</td>
|
||||
@@ -97,7 +98,7 @@
|
||||
<span t-esc="track.name"/>
|
||||
</a>
|
||||
<div class="text-muted">
|
||||
<small t-esc="speakers[track.id]"/>
|
||||
<small t-esc="track.partner_id.sudo()"/>
|
||||
</div>
|
||||
</td>
|
||||
</t>
|
||||
@@ -129,8 +130,8 @@
|
||||
<small t-if="not track.website_published" class="label label-danger">unpublished</small>
|
||||
</h3>
|
||||
<ul class="list-inline mb0">
|
||||
<li t-if="track.speaker_ids" class="text-muted fa fa-user">
|
||||
<t t-esc="', '.join([speaker.name for speaker in track.speaker_ids])"></t>
|
||||
<li t-if="track.partner_id" class="text-muted fa fa-user">
|
||||
<t t-esc="track.partner_id.sudo().name"/>
|
||||
</li>
|
||||
<li t-if="track.date" class="text-muted fa fa-calendar"> <span t-field="track.date" t-options='{"hide_seconds":"True"}'/></li>
|
||||
<li class="text-muted fa fa-map-marker" t-if="track.location_id">
|
||||
@@ -224,17 +225,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div t-foreach="track.speaker_ids" t-as="speaker" class="well mt32">
|
||||
<div t-if="track.partner_id" class="well mt32">
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<span t-field="speaker.sudo().image_medium"
|
||||
<span t-field="track.partner_id.sudo().image_medium"
|
||||
t-options='{"widget": "image", "class": "img-circle"}'/>
|
||||
</div><div class="col-sm-10">
|
||||
<h4 t-field="speaker.name" class="mb4"/>
|
||||
<div class="fa fa-home mb16" t-if="speaker.website">
|
||||
<a t-att-href="speaker.website"><span t-field="speaker.website"/></a>
|
||||
<h4 t-field="track.partner_id.name" class="mb4"/>
|
||||
<div class="fa fa-home mb16" t-if="track.partner_id.website">
|
||||
<a t-att-href="track.partner_id.website"><span t-field="track.partner_id.website"/></a>
|
||||
</div>
|
||||
<div t-field="speaker.website_description"/>
|
||||
<div t-field="track.partner_id.website_description"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -301,7 +302,7 @@
|
||||
<h1 class="text-center mb0">Call for Proposals</h1>
|
||||
<h2 class="text-center text-muted mb32" t-esc="event.name"></h2>
|
||||
</section>
|
||||
<section id="forms" t-if="not event.show_track_proposal">
|
||||
<section id="forms" t-if="not event.website_track_proposal">
|
||||
<h1>Proposals are closed!</h1>
|
||||
<p>
|
||||
This event does not accept proposals.
|
||||
@@ -332,7 +333,7 @@
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
<section id="forms" t-if="event.show_track_proposal">
|
||||
<section id="forms" t-if="event.website_track_proposal">
|
||||
<form class="form-horizontal mt32 js_website_submit_form" t-attf-action="/event/#{event.id}/track_proposal/post" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
||||
<div class="form-group">
|
||||
@@ -448,14 +449,13 @@
|
||||
|
||||
<!-- Chatter templates -->
|
||||
<template id="event_track_template_new">
|
||||
<h3>New track proposal</h3>
|
||||
<p>New track proposal <a href="#" t-att-data-oe-model="track._name" t-att-data-oe-id="track.id"> <t t-esc="track.name"/></a></p>
|
||||
<ul>
|
||||
<li><b>Proposed By</b>: <t t-esc="object.partner_id.name or object.partner_name or object.partner_email"/></li>
|
||||
<li><b>Mail</b>: <a t-attf-href="mailto:#{object.partner_email}"><t t-esc="object.partner_email"/></a></li>
|
||||
<li><b>Phone</b>: <t t-esc="object.partner_phone"/></li>
|
||||
<li><b>Title</b>: <t t-esc="object.name"/></li>
|
||||
<li><b>Speakers Biography</b>: <t t-esc="object.partner_biography"/></li>
|
||||
<li><b>Talk Introduction</b>: <t t-esc="object.description"/></li>
|
||||
<li><b>Proposed By</b>: <t t-esc="track.partner_name or track.partner_email"/></li>
|
||||
<li><b>Mail</b>: <a t-attf-href="mailto:#{track.partner_email}"><t t-esc="track.partner_email"/></a></li>
|
||||
<li><b>Phone</b>: <t t-esc="track.partner_phone"/></li>
|
||||
<li><b>Speakers Biography</b>: <t t-esc="track.partner_biography"/></li>
|
||||
<li><b>Talk Introduction</b>: <t t-esc="track.description"/></li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
+104
-19
@@ -6,11 +6,14 @@
|
||||
<field name="name">event.track.kanban</field>
|
||||
<field name="model">event.track</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="state">
|
||||
<kanban default_group_by="stage_id">
|
||||
<templates>
|
||||
<field name="color"/>
|
||||
<field name="speaker_ids"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="website_url"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="activity_state"/>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click">
|
||||
<div class="o_dropdown_kanban dropdown" groups="base.group_user">
|
||||
@@ -31,16 +34,17 @@
|
||||
<div>
|
||||
<t t-if="duration"><field name="duration" widget="float_time"/> hours</t>
|
||||
</div>
|
||||
<div class="oe_kanban_bottom_right">
|
||||
<div class="oe_kanban_bottom_left">
|
||||
<field name="priority" widget="priority"/>
|
||||
</div>
|
||||
<div class="oe_kanban_footer_left">
|
||||
<t t-foreach="record.speaker_ids.raw_value.slice(0,11)" t-as="speaker">
|
||||
<img t-att-src="kanban_image('res.partner', 'image_small', speaker)" t-att-data-member_id="speaker" width="30px" height="30px"/>
|
||||
</t>
|
||||
<t t-if="record.speaker_ids.raw_value.length > 11 ">
|
||||
<a name="open_track_speakers_list" type="object"><t t-esc="record.speaker_ids.raw_value.length - 11"> More</t></a>
|
||||
</t>
|
||||
<div class="oe_kanban_bottom_right">
|
||||
<img t-att-src="kanban_image('res.partner', 'image_small', record.partner_id.raw_value)"
|
||||
t-att-title="record.partner_id.value" width="24" height="24"
|
||||
class="oe_kanban_avatar pull-right"/>
|
||||
<div class="pull-left mr4">
|
||||
<field name="activity_ids" widget="kanban_activity"/>
|
||||
<field name="kanban_state" widget="kanban_state_selection" groups="base.group_user"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
@@ -71,14 +75,26 @@
|
||||
<field name="name"/>
|
||||
<field name="event_id"/>
|
||||
<field name="location_id"/>
|
||||
<field name="state"/>
|
||||
<field name="speaker_ids"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="partner_id"/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||
<separator/>
|
||||
<filter string="My Activities" name="activities_my"
|
||||
domain="[('activity_ids.user_id', '=', uid)]"/>
|
||||
<filter string="Today Activities" name="activities_today"
|
||||
domain="[('activity_ids.date_deadline', '=', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<filter string="Upcoming Activities (7 days)" name="activities_week"
|
||||
domain="['&', ('activity_ids.date_deadline', '>=', context_today().strftime('%Y-%m-%d')),
|
||||
('activity_ids.date_deadline', '<=', (context_today()+datetime.timedelta(days=7)).strftime('%Y-%m-%d'))
|
||||
]"/>
|
||||
<filter string="Overdue Activities" name="activities_overdue"
|
||||
domain="[('activity_ids.date_deadline', '<', context_today().strftime('%Y-%m-%d'))]"
|
||||
help="Show all records which has next action date is before today"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Responsible" context="{'group_by': 'user_id'}"/>
|
||||
<filter string="Status" context="{'group_by':'state'}"/>
|
||||
<filter string="Stage" context="{'group_by':'stage_id'}"/>
|
||||
<filter string="Date" context="{'group_by':'date'}"/>
|
||||
<filter string="Event" context="{'group_by':'event_id'}"/>
|
||||
</group>
|
||||
@@ -92,7 +108,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Track">
|
||||
<header>
|
||||
<field name="state" widget="statusbar" clickable="True"/>
|
||||
<field name="stage_id" widget="statusbar" clickable="True"/>
|
||||
</header>
|
||||
<sheet string="Track">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
@@ -124,7 +140,6 @@
|
||||
<field name="partner_phone"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="speaker_ids" widget="many2many_tags"/>
|
||||
<field name="date"/>
|
||||
<label for="duration"/>
|
||||
<div>
|
||||
@@ -137,6 +152,7 @@
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="activity_ids" widget="mail_activity"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
@@ -174,7 +190,7 @@
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a track.
|
||||
</p><p>
|
||||
Tracks define the agenda of your event. These can bea talk, a round table, a meeting, etc.
|
||||
Tracks define the schedule of your event. These can bea talk, a round table, a meeting, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -184,12 +200,12 @@
|
||||
<field name="name">Event Tracks</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form,calendar,graph</field>
|
||||
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id, 'group_by': 'state'}</field>
|
||||
<field name="context">{'search_default_event_id': active_id, 'default_event_id': active_id, 'group_by': 'stage_id'}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a track.
|
||||
</p><p>
|
||||
Tracks define the agenda of your event. These can be a talk, a round table, a meeting, etc.
|
||||
Tracks define the schedule of your event. These can be a talk, a round table, a meeting, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
@@ -272,7 +288,8 @@
|
||||
<menuitem
|
||||
id="menu_event_sponsor_type"
|
||||
action="action_event_sponsor_type"
|
||||
parent="event.menu_event_configuration"/>
|
||||
parent="event.menu_event_configuration"
|
||||
groups="base.group_no_one"/>
|
||||
|
||||
<!-- EVENT.SPONSOR VIEWS -->
|
||||
<record model="ir.ui.view" id="view_event_sponsor_tree">
|
||||
@@ -338,6 +355,74 @@
|
||||
<menuitem
|
||||
id="menu_event_track_tag"
|
||||
action="action_event_track_tag"
|
||||
parent="event.menu_event_configuration"
|
||||
groups="base.group_no_one"/>
|
||||
|
||||
<!-- EVENTS TRACK STAGES-->
|
||||
<record id="event_track_stage_view_search" model="ir.ui.view">
|
||||
<field name="name">event.track.stage.view.search</field>
|
||||
<field name="model">event.track.stage</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Track Stage">
|
||||
<field name="name" string="Track Stages"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_stage_view_form" model="ir.ui.view">
|
||||
<field name="name">event.track.stage.view.form</field>
|
||||
<field name="model">event.track.stage</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Track Stage">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="mail_template_id"/>
|
||||
<field name="sequence" groups="base.group_no_one"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="fold"/>
|
||||
<field name="is_done"/>
|
||||
<field name="is_cancel"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_stage_view_tree" model="ir.ui.view">
|
||||
<field name="name">event.track.stage.view.tree</field>
|
||||
<field name="model">event.track.stage</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Track Stage">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="fold"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="event_track_stage_action" model="ir.actions.act_window">
|
||||
<field name="name">Track Stages</field>
|
||||
<field name="res_model">event.track.stage</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="event_track_stage_view_tree"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a stage in the task pipeline.
|
||||
</p><p>
|
||||
Define the steps that will be used in the event from the
|
||||
creation of the track, up to the closing of the track.
|
||||
You will use these stages in order to track the progress in
|
||||
solving an event track.
|
||||
</p></field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Track Stages"
|
||||
id="event_track_stage_menu"
|
||||
action="event_track_stage_action"
|
||||
parent="event.menu_event_configuration"/>
|
||||
|
||||
</odoo>
|
||||
@@ -1,36 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="event_type_view_form_inherit_track" model="ir.ui.view">
|
||||
<field name="name">event.type.view.form.inherit.track</field>
|
||||
<field name="model">event.type</field>
|
||||
<field name="inherit_id" ref="website_event.event_type_view_form_inherit_website"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='event_type_visibility_website']/div[@class='o_setting_right_pane']" position='inside'>
|
||||
<div class="row mt16">
|
||||
<label class="col-md-4" for="website_track"/> <field name="website_track"/>
|
||||
</div>
|
||||
<div class="row mt16">
|
||||
<label class="col-md-4" for="website_track_proposal"/> <field name="website_track_proposal"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Events Organisation/CONFIGURATION/EVENTS -->
|
||||
<record id="view_event_form" model="ir.ui.view">
|
||||
<field name="name">Event Tracks</field>
|
||||
<field name="inherit_id" ref="event.view_event_form"/>
|
||||
<field name="inherit_id" ref="website_event.event_event_view_form_inherit_website"/>
|
||||
<field name="model">event.event</field>
|
||||
<field name="arch" type="xml">
|
||||
<button name="toggle_active" position="before">
|
||||
<button name="website_publish_button" position="before">
|
||||
<button name="%(action_event_track_from_event)d"
|
||||
type="action"
|
||||
class="oe_stat_button"
|
||||
icon="fa-inbox"
|
||||
attrs="{'invisible': [('show_tracks', '=', False), ('show_track_proposal', '=', False)]}">
|
||||
<field name="count_tracks" widget="statinfo"/>
|
||||
icon="fa-inbox">
|
||||
<field name="track_count" widget="statinfo"/>
|
||||
</button>
|
||||
<button name="%(action_event_sponsor_from_event)d"
|
||||
type="action"
|
||||
class="oe_stat_button"
|
||||
icon="fa-users">
|
||||
<field name="count_sponsor" widget="statinfo" string="Sponsors"/>
|
||||
<field name="sponsor_count" widget="statinfo"/>
|
||||
</button>
|
||||
</button>
|
||||
<xpath expr="//div[@class='oe_title']" position="inside">
|
||||
<div name="event_checkboxes">
|
||||
<field name="show_menu"/>
|
||||
<label for="show_menu"/>
|
||||
<field name="show_tracks" attrs="{'invisible': [('show_menu', '=', False)]}"/>
|
||||
<label for="show_tracks" attrs="{'invisible': [('show_menu', '=', False)]}"/>
|
||||
<field name="show_track_proposal" attrs="{'invisible': [('show_menu', '=', False)]}"/>
|
||||
<label for="show_track_proposal" attrs="{'invisible': [('show_menu', '=', False)]}"/>
|
||||
</div>
|
||||
</xpath>
|
||||
<label for="website_menu" position="after">
|
||||
<field name="website_track" attrs="{'invisible': [('website_menu', '=', False)]}"/>
|
||||
<label for="website_track" string="Tracks on Website" attrs="{'invisible': [('website_menu', '=', False)]}"/>
|
||||
<field name="website_track_proposal" attrs="{'invisible': [('website_menu', '=', False)]}"/>
|
||||
<label for="website_track_proposal" string="Track Proposals on Website" attrs="{'invisible': [('website_menu', '=', False)]}"/>
|
||||
</label>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user