[ADD] website_event_questions: ask questions to event attendees
[IMP] event,event_sale,website_event_sale: refactoring to be more easily extended (code portions are courtesy of Thibault Delavallée <tde@odoo.com>)
This commit is contained in:
@@ -303,6 +303,24 @@ class event_registration(models.Model):
|
||||
registration.sudo().confirm_registration()
|
||||
return registration
|
||||
|
||||
@api.model
|
||||
def _prepare_attendee_values(self, registration):
|
||||
""" Method preparing the values to create new attendees based on a
|
||||
sale order line. It takes some registration data (dict-based) that are
|
||||
optional values coming from an external input like a web page. This method
|
||||
is meant to be inherited in various addons that sell events. """
|
||||
partner_id = registration.pop('partner_id', self.env.user.partner_id)
|
||||
event_id = registration.pop('event_id', False)
|
||||
data = {
|
||||
'name': registration.get('name', partner_id.name),
|
||||
'phone': registration.get('phone', partner_id.phone),
|
||||
'email': registration.get('email', partner_id.email),
|
||||
'partner_id': partner_id.id,
|
||||
'event_id': event_id and event_id.id or False,
|
||||
}
|
||||
data.update({key: registration[key] for key in registration.keys() if key in self._fields})
|
||||
return data
|
||||
|
||||
@api.one
|
||||
def do_draft(self):
|
||||
self.state = 'draft'
|
||||
|
||||
@@ -227,7 +227,15 @@
|
||||
<field name="event_id" ref="event_1"/>
|
||||
</record>
|
||||
|
||||
<record id="reg_0_2" model="event.registration">
|
||||
<record id="reg_1_3" model="event.registration">
|
||||
<field name="name">Delta PC</field>
|
||||
<field name="email">deltapc@yourcompany.example.com</field>
|
||||
<field name="phone">+1 510 340 2385</field>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="event_id" ref="event_1"/>
|
||||
</record>
|
||||
|
||||
<record id="reg_2_0" model="event.registration">
|
||||
<field name="name">Camptocamp</field>
|
||||
<field name="email">openerp@camptocamp.com</field>
|
||||
<field name="phone">+41 21 619 10 04 </field>
|
||||
|
||||
@@ -305,7 +305,7 @@
|
||||
</header>
|
||||
<sheet string="Registration">
|
||||
<group>
|
||||
<group string="Attendee Information" name="attendee">
|
||||
<group string="Attendee" name="attendee">
|
||||
<field name="name"/>
|
||||
<field name="phone"/>
|
||||
<field name="email"/>
|
||||
|
||||
@@ -175,3 +175,21 @@ class event_registration(models.Model):
|
||||
'order': res.origin or res.sale_order_id.name})
|
||||
res.message_post(body=message)
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _prepare_attendee_values(self, registration):
|
||||
""" Override to add sale related stuff """
|
||||
line_id = registration.get('sale_order_line_id')
|
||||
if line_id:
|
||||
registration.setdefault('partner_id', line_id.order_id.partner_id)
|
||||
att_data = super(event_registration, self)._prepare_attendee_values(registration)
|
||||
if line_id:
|
||||
att_data.update({
|
||||
'event_id': line_id.event_id.id,
|
||||
'event_id': line_id.event_id.id,
|
||||
'event_ticket_id': line_id.event_ticket_id.id,
|
||||
'origin': line_id.order_id.name,
|
||||
'sale_order_id': line_id.order_id.id,
|
||||
'sale_order_line_id': line_id.id,
|
||||
})
|
||||
return att_data
|
||||
|
||||
@@ -62,7 +62,8 @@ class sale_order_line(osv.osv):
|
||||
order line has a product_uom_qty attribute that will be the number of
|
||||
registrations linked to this line. This method update existing registrations
|
||||
and create new one for missing one. """
|
||||
registrations = self.env['event.registration'].search([('sale_order_line_id', 'in', self.ids)])
|
||||
Registration = self.env['event.registration']
|
||||
registrations = Registration.search([('sale_order_line_id', 'in', self.ids)])
|
||||
for so_line in [l for l in self if l.event_id]:
|
||||
existing_registrations = registrations.filtered(lambda self: self.sale_order_line_id.id == so_line.id)
|
||||
if confirm:
|
||||
@@ -75,17 +76,9 @@ class sale_order_line(osv.osv):
|
||||
if registration_data:
|
||||
registration = registration_data.pop()
|
||||
# TDE CHECK: auto confirmation
|
||||
self.env['event.registration'].with_context(registration_force_draft=True).create({
|
||||
'name': registration.get('name', so_line.order_id.partner_id.name),
|
||||
'phone': registration.get('phone', so_line.order_id.partner_id.phone),
|
||||
'email': registration.get('email', so_line.order_id.partner_id.email),
|
||||
'event_id': so_line.event_id.id,
|
||||
'event_ticket_id': so_line.event_ticket_id.id,
|
||||
'partner_id': so_line.order_id.partner_id.id,
|
||||
'origin': so_line.order_id.name,
|
||||
'sale_order_id': so_line.order_id.id,
|
||||
'sale_order_line_id': so_line.id,
|
||||
})
|
||||
registration['sale_order_line_id'] = so_line
|
||||
self.env['event.registration'].with_context(registration_force_draft=True).create(
|
||||
Registration._prepare_attendee_values(registration))
|
||||
return True
|
||||
|
||||
def button_confirm(self, cr, uid, ids, context=None):
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
</field>
|
||||
<group name="event" position="after">
|
||||
<group string="Origin">
|
||||
<field name="origin" attrs="{'invisible': [('sale_order_id', '!=', False)]}"/>
|
||||
<field name="sale_order_id"/>
|
||||
<field name="origin" attrs="{'invisible': [('sale_order_id', '!=', False)]}"/>
|
||||
<field name="sale_order_line_id" readonly="1" attrs="{'invisible': [('sale_order_id', '=', False)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
@@ -4,7 +4,6 @@ import time
|
||||
import werkzeug.urls
|
||||
from datetime import datetime, timedelta
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from collections import OrderedDict
|
||||
|
||||
from openerp import http
|
||||
from openerp import tools, SUPERUSER_ID
|
||||
@@ -244,9 +243,16 @@ class website_event(http.Controller):
|
||||
def _process_registration_details(self, details):
|
||||
''' Process data posted from the attendee details form. '''
|
||||
registrations = {}
|
||||
global_values = {}
|
||||
for key, value in details.iteritems():
|
||||
counter, field_name = key.split('-', 1)
|
||||
registrations.setdefault(counter, dict())[field_name] = value
|
||||
if counter == '0':
|
||||
global_values[field_name] = value
|
||||
else:
|
||||
registrations.setdefault(counter, dict())[field_name] = value
|
||||
for key, value in global_values.iteritems():
|
||||
for registration in registrations.values():
|
||||
registration[key] = value
|
||||
return registrations.values()
|
||||
|
||||
@http.route(['/event/<model("event.event"):event>/registration/confirm'], type='http', auth="public", methods=['POST'], website=True)
|
||||
@@ -256,16 +262,13 @@ class website_event(http.Controller):
|
||||
registrations = self._process_registration_details(post)
|
||||
|
||||
registration_ids = []
|
||||
user = request.registry.get('res.users').browse(cr, uid, uid, context=context)
|
||||
for registration in registrations:
|
||||
registration['event_id'] = event
|
||||
registration_ids.append(
|
||||
Registration.create(cr, SUPERUSER_ID, {
|
||||
'name': registration.get('name', user.name),
|
||||
'phone': registration.get('phone', user.phone),
|
||||
'email': registration.get('email', user.email),
|
||||
'partner_id': user.partner_id.id,
|
||||
'event_id': event.id,
|
||||
}, context=context))
|
||||
Registration.create(
|
||||
cr, SUPERUSER_ID,
|
||||
Registration._prepare_attendee_values(cr, SUPERUSER_ID, registration),
|
||||
context=context))
|
||||
|
||||
attendees = Registration.browse(cr, uid, registration_ids, context=context)
|
||||
return request.website.render("website_event.registration_complete", {
|
||||
|
||||
@@ -428,31 +428,28 @@
|
||||
<t t-set="counter_type" t-value="1"/>
|
||||
<t t-set="counter" t-value="0"/>
|
||||
<t t-foreach="tickets" t-as="ticket">
|
||||
<div>
|
||||
<h4>
|
||||
<strong>
|
||||
Ticket Type #<t t-raw="counter_type"/>: <t t-esc="ticket['name']"/> (
|
||||
<t t-if="ticket['price'] > 0">
|
||||
<t t-esc="ticket['price']"/>
|
||||
<t t-esc="website.pricelist_id.currency_id.symbol"/>
|
||||
</t>
|
||||
<t t-if="ticket['price'] == 0">Free</t>)
|
||||
</strong>
|
||||
</h4><hr/>
|
||||
</div>
|
||||
<h4 class="page-header mt16">
|
||||
<strong>
|
||||
Ticket Type #<t t-raw="counter_type"/>: <t t-esc="ticket['name']"/> (
|
||||
<t t-if="ticket['price'] > 0">
|
||||
<t t-esc="ticket['price']"/>
|
||||
<t t-esc="website.pricelist_id.currency_id.symbol"/>
|
||||
</t>
|
||||
<t t-if="ticket['price'] == 0">Free</t>)
|
||||
</strong>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-4"><strong>Name</strong></div>
|
||||
<div class="col-md-3"><strong>Phone</strong> <span class="text-muted">(Optional)</span></div>
|
||||
<div class="col-md-5"><strong>Email</strong> <span class="text-muted">(Optional)</span></div>
|
||||
</div>
|
||||
<t t-foreach="range(1, ticket['quantity'] + 1)" t-as="att_counter">
|
||||
<t t-foreach="range(1, ticket['quantity'] + 1)" t-as="att_counter" name="attendee_loop">
|
||||
<t t-set="counter" t-value="counter + 1"/>
|
||||
<div class="row">
|
||||
<div class="col-md-4"><input class='form-control input-sm' type='text' t-attf-name="#{counter}-name" required="This field is required" t-att-placeholder="'Attendee #%s' %counter"/></div>
|
||||
<div class="col-md-3"><input class='form-control input-sm' type='tel' t-attf-name="#{counter}-phone"/></div>
|
||||
<div class="col-md-5"><input class='form-control input-sm' type='email' t-attf-name="#{counter}-email"/></div>
|
||||
<div class="row mb4">
|
||||
<div class="col-md-4"><input class='form-control' type='text' t-attf-name="#{counter}-name" required="This field is required" t-att-placeholder="'Attendee #%s' %counter"/></div>
|
||||
<div class="col-md-3"><input class='form-control' type='tel' t-attf-name="#{counter}-phone"/></div>
|
||||
<div class="col-md-5"><input class='form-control' type='email' t-attf-name="#{counter}-email"/></div>
|
||||
<input class='hidden' type='text' t-attf-name="#{counter}-ticket_id" t-attf-value="#{ticket['id']}"/>
|
||||
<hr style="width:50%"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-set="counter_type" t-value="counter_type + 1"/>
|
||||
@@ -461,7 +458,7 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="pull-left">
|
||||
<button type="submit" class="btn btn-primary">Continue</button> or
|
||||
<button type="submit" class="btn btn-primary">Continue</button> or
|
||||
<a class="js_goto_event"> Cancel Registration</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2015-TODAY Odoo S.A. (<https://www.odoo.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import controllers
|
||||
import models
|
||||
import report
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
{
|
||||
'name': 'Questions on Events',
|
||||
'description': 'Questions on Events',
|
||||
'category': 'Website',
|
||||
'version': '1.0',
|
||||
'author': 'Odoo S.A.',
|
||||
'depends': ['website_event'],
|
||||
'data': [
|
||||
'views/website_event_questions_backend.xml',
|
||||
'views/website_event_questions_templates.xml',
|
||||
'report/report_event_question_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'demo': [
|
||||
'data/demo.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import main
|
||||
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.addons.website_event.controllers.main import website_event
|
||||
|
||||
|
||||
class website_event(website_event):
|
||||
|
||||
def _process_registration_details(self, details):
|
||||
''' Process data posted from the attendee details form. '''
|
||||
registrations = super(website_event, self)._process_registration_details(details)
|
||||
for registration in registrations:
|
||||
answer_ids = []
|
||||
for key, value in registration.iteritems():
|
||||
if key.startswith('answer_ids-'):
|
||||
answer_ids.append([4, int(value)])
|
||||
registration['answer_ids'] = answer_ids
|
||||
return registrations
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="event_question_0" model="event.question">
|
||||
<field name="title">Kind of partner</field>
|
||||
<field name="event_id" ref="event.event_1"/>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
<record id="event_question_1" model="event.question">
|
||||
<field name="title">Veggie</field>
|
||||
<field name="event_id" ref="event.event_1"/>
|
||||
<field name="sequence">2</field>
|
||||
<field name="is_individual" eval="True"/>
|
||||
</record>
|
||||
<record id="event_question_2" model="event.question">
|
||||
<field name="title">Accommodation</field>
|
||||
<field name="event_id" ref="event.event_1"/>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
|
||||
<record id="event_suggestion_0_0" model="event.answer">
|
||||
<field name="name">Gold</field>
|
||||
<field name="question_id" ref="event_question_0"/>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
<record id="event_suggestion_0_1" model="event.answer">
|
||||
<field name="name">Silver</field>
|
||||
<field name="question_id" ref="event_question_0"/>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
<record id="event_suggestion_0_2" model="event.answer">
|
||||
<field name="name">Bronze</field>
|
||||
<field name="question_id" ref="event_question_0"/>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
|
||||
<record id="event_suggestion_1_0" model="event.answer">
|
||||
<field name="name">Yes</field>
|
||||
<field name="question_id" ref="event_question_1"/>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
<record id="event_suggestion_1_1" model="event.answer">
|
||||
<field name="name">No</field>
|
||||
<field name="question_id" ref="event_question_1"/>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
|
||||
<record id="event_suggestion_2_0" model="event.answer">
|
||||
<field name="name">Personal</field>
|
||||
<field name="question_id" ref="event_question_2"/>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
<record id="event_suggestion_2_1" model="event.answer">
|
||||
<field name="name">In Charge</field>
|
||||
<field name="question_id" ref="event_question_2"/>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
|
||||
<record id="event.reg_1_1" model="event.registration">
|
||||
<field name="answer_ids" eval="[(4, ref('event_suggestion_0_0')), (4, ref('event_suggestion_1_1')), (4, ref('event_suggestion_2_0'))]"/>
|
||||
</record>
|
||||
<record id="event.reg_1_2" model="event.registration">
|
||||
<field name="answer_ids" eval="[(4, ref('event_suggestion_0_2')), (4, ref('event_suggestion_1_1')), (4, ref('event_suggestion_2_0'))]"/>
|
||||
</record>
|
||||
<record id="event.reg_1_3" model="event.registration">
|
||||
<field name="answer_ids" eval="[(4, ref('event_suggestion_0_0')), (4, ref('event_suggestion_1_0')), (4, ref('event_suggestion_2_1'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import event
|
||||
@@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp import models, fields
|
||||
|
||||
|
||||
class EventEvent(models.Model):
|
||||
""" Override Event model to add optional questions when buying tickets. """
|
||||
_inherit = 'event.event'
|
||||
|
||||
question_ids = fields.One2many('event.question', 'event_id', 'Questions')
|
||||
general_question_ids = fields.One2many('event.question', 'event_id', 'Questions',
|
||||
domain=[('is_individual', '=', False)])
|
||||
specific_question_ids = fields.One2many('event.question', 'event_id', 'Questions',
|
||||
domain=[('is_individual', '=', True)])
|
||||
|
||||
|
||||
class EventRegistrationAnswer(models.Model):
|
||||
''' This m2m table has to be explicitly instanciated as we need unique ids
|
||||
in the reporting view event.question.report.
|
||||
|
||||
This model is purely technical. '''
|
||||
|
||||
_name = 'event.registration.answer'
|
||||
_table = 'event_registration_answer'
|
||||
|
||||
event_answer_id = fields.Many2one('event.answer', required=True)
|
||||
event_registration_id = fields.Many2one('event.registration', required=True)
|
||||
|
||||
|
||||
class EventRegistration(models.Model):
|
||||
""" Store answers on attendees. """
|
||||
_inherit = 'event.registration'
|
||||
|
||||
answer_ids = fields.Many2many('event.answer', 'event_registration_answer', string='Answers')
|
||||
|
||||
|
||||
class EventQuestion(models.Model):
|
||||
_name = 'event.question'
|
||||
_rec_name = 'title'
|
||||
_order = 'sequence,id'
|
||||
|
||||
title = fields.Char(required=True, translate=True)
|
||||
event_id = fields.Many2one('event.event', required=True, ondelete='cascade')
|
||||
answer_ids = fields.One2many('event.answer', 'question_id', "Answers", required=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.")
|
||||
|
||||
|
||||
class EventAnswer(models.Model):
|
||||
_name = 'event.answer'
|
||||
_order = 'sequence,id'
|
||||
|
||||
name = fields.Char('Answer', required=True, translate=True)
|
||||
question_id = fields.Many2one('event.question', required=True, ondelete='cascade')
|
||||
sequence = fields.Integer(default=10)
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import report_event_registrations_questions
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Graph view for question analysis-->
|
||||
<record model="ir.ui.view" id="view_event_question_report_graph">
|
||||
<field name="name">event.question.report.graph</field>
|
||||
<field name="model">event.question.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Questions Analysis">
|
||||
<field name="answer_id"/>
|
||||
<field name="question_id"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Pivot view for question analysis -->
|
||||
<record model="ir.ui.view" id="view_event_question_report_pivot">
|
||||
<field name="name">event.question.report.pivot</field>
|
||||
<field name="model">event.question.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Questions Analysis" disable_linking="True">
|
||||
<field name="event_id" type="row"/>
|
||||
<field name="attendee_id" type="row"/>
|
||||
<field name="question_id" type="col"/>
|
||||
<field name="answer_id" type="col"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Seach view for question analysis-->
|
||||
<record model="ir.ui.view" id="view_event_question_report_search">
|
||||
<field name="name">event.question.report.search</field>
|
||||
<field name="model">event.question.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Questions Analysis">
|
||||
<field name="event_id" string="Event"/>
|
||||
<field name="attendee_id" string="Registration"/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Event" context="{'group_by': 'event_id'}" />
|
||||
<filter string="Question" context="{'group_by': 'question_id'}"/>
|
||||
<filter string="Answer" context="{'group_by': 'answer_id'}" />
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Action for reporting -->
|
||||
<record model="ir.actions.act_window" id="action_event_question_report">
|
||||
<field name="name">Questions Analysis</field>
|
||||
<field name="res_model">event.question.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
</record>
|
||||
|
||||
<!-- Menu -->
|
||||
<menuitem name="Questions Analysis" id="menu_report_event_questions"
|
||||
parent="event.menu_reporting_events" action="action_event_question_report" sequence="4"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp import fields, models, tools
|
||||
|
||||
|
||||
class ReportEventRegistrationQuestions(models.Model):
|
||||
_name = "event.question.report"
|
||||
_auto = False
|
||||
|
||||
attendee_id = fields.Many2one(comodel_name='event.registration', string='Registration')
|
||||
question_id = fields.Many2one(comodel_name='event.question', string='Question')
|
||||
answer_id = fields.Many2one(comodel_name='event.answer', string='Answer')
|
||||
event_id = fields.Many2one(comodel_name='event.event', string='Event')
|
||||
|
||||
def init(self, cr):
|
||||
""" Event Question main report """
|
||||
tools.drop_view_if_exists(cr, 'event_question_report')
|
||||
cr.execute(""" CREATE VIEW event_question_report AS (
|
||||
SELECT
|
||||
att_answer.id as id,
|
||||
att_answer.event_registration_id as attendee_id,
|
||||
answer.question_id as question_id,
|
||||
answer.id as answer_id,
|
||||
question.event_id as event_id
|
||||
FROM
|
||||
event_registration_answer as att_answer
|
||||
LEFT JOIN
|
||||
event_answer as answer ON answer.id = att_answer.event_answer_id
|
||||
LEFT JOIN
|
||||
event_question as question ON question.id = answer.question_id
|
||||
GROUP BY
|
||||
attendee_id,
|
||||
event_id,
|
||||
question_id,
|
||||
answer_id,
|
||||
att_answer.id
|
||||
)""")
|
||||
@@ -0,0 +1,7 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
event_question_all,event.question.all,model_event_question,,1,0,0,0
|
||||
event_question_event_user,event.question.event.user,model_event_question,event.group_event_user,1,1,1,1
|
||||
event_answer_all,event.answer.all,model_event_answer,,1,0,0,0
|
||||
event_answer_event_user,event.answer.event.user,model_event_answer,event.group_event_user,1,1,1,1
|
||||
event_question_report_all,event.question.report.all,model_event_question_report,event.group_event_user,1,1,1,1
|
||||
event_registration_answer_all,access_event_registration_answer,model_event_registration_answer,,1,1,1,1
|
||||
|
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_question_form">
|
||||
<field name="name">event.question.form</field>
|
||||
<field name="model">event.question</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Question">
|
||||
<h1><field name="title" /></h1>
|
||||
<field name="is_individual"/>
|
||||
<label for="is_individual"/>
|
||||
<field name="answer_ids">
|
||||
<tree editable="bottom">
|
||||
<field name="sequence" widget="handle" />
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_answer_simplified_form">
|
||||
<field name="name">event.answer.simplified.form</field>
|
||||
<field name="model">event.answer</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Question">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_form_inherit_question">
|
||||
<field name="name">event.form.inherit.question</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="inherit_id" ref="event.view_event_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="//notebook" position="inside">
|
||||
<page string="Questions">
|
||||
<field name="question_ids" nolabel="1">
|
||||
<tree>
|
||||
<field name="sequence" widget="handle" />
|
||||
<field name="title"/>
|
||||
<field name="is_individual"/>
|
||||
<field name="answer_ids"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_registration_form_inherit_question">
|
||||
<field name="name">event.registration.form.inherit.question</field>
|
||||
<field name="model">event.registration</field>
|
||||
<field name="inherit_id" ref="event.view_event_registration_form" />
|
||||
<field name="arch" type="xml">
|
||||
<group name="event" position="inside">
|
||||
<field name="answer_ids" widget="many2many_tags" readonly="1"/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_registration_search_inherit_question">
|
||||
<field name="name">event.registration.search.inherit.question</field>
|
||||
<field name="model">event.registration</field>
|
||||
<field name="inherit_id" ref="event.view_registration_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<search position="inside">
|
||||
<field name="answer_ids" string="Answers"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="registration_attendee_details_questions" inherit_id="website_event.registration_attendee_details" name="Registration Attendee Details with questions">
|
||||
<data>
|
||||
<!-- Attendee specific questions -->
|
||||
<xpath expr="//t[@name='attendee_loop']" position="inside">
|
||||
<t t-if="event.specific_question_ids">
|
||||
<div class="row mb32">
|
||||
<div class="col-md-4" t-foreach='event.specific_question_ids' t-as='question'>
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon"><t t-esc="question.title"/></span>
|
||||
<select t-attf-name="#{counter}-answer_ids-#{question.id}" class="form-control" required="true">
|
||||
<t t-foreach='question.answer_ids' t-as="answer">
|
||||
<option t-esc='answer.name' t-att-value='answer.id'/>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
|
||||
<!-- Generic questions -->
|
||||
<xpath expr="//div[@class='container']/t[last()]" position="after">
|
||||
<t t-if="event.general_question_ids">
|
||||
<h4 class="page-header mt32"><strong>Last questions</strong></h4>
|
||||
<div class="row">
|
||||
<div class="col-md-4" t-foreach='event.general_question_ids' t-as='question'>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><t t-esc='question.title'/></span>
|
||||
<select t-attf-name="0-answer_ids-#{question.id}" class="form-control" required="true">
|
||||
<t t-foreach='question.answer_ids' t-as="answer">
|
||||
<option t-esc='answer.name' t-att-value='answer.id'/>
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
|
||||
</data>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user