summaryrefslogtreecommitdiff
path: root/addons/website_event_questions/models
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/website_event_questions/models
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/website_event_questions/models')
-rw-r--r--addons/website_event_questions/models/__init__.py5
-rw-r--r--addons/website_event_questions/models/event_event.py69
-rw-r--r--addons/website_event_questions/models/event_question.py65
-rw-r--r--addons/website_event_questions/models/event_registration.py30
4 files changed, 169 insertions, 0 deletions
diff --git a/addons/website_event_questions/models/__init__.py b/addons/website_event_questions/models/__init__.py
new file mode 100644
index 00000000..14919447
--- /dev/null
+++ b/addons/website_event_questions/models/__init__.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+
+from . import event_event
+from . import event_question
+from . import event_registration
diff --git a/addons/website_event_questions/models/event_event.py b/addons/website_event_questions/models/event_event.py
new file mode 100644
index 00000000..f81f5316
--- /dev/null
+++ b/addons/website_event_questions/models/event_event.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, fields, models
+
+
+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):
+ """ Override Event model to add optional questions when buying tickets. """
+ _inherit = 'event.event'
+
+ question_ids = fields.One2many(
+ 'event.question', 'event_id', 'Questions', copy=True,
+ compute='_compute_question_ids', readonly=False, store=True)
+ general_question_ids = fields.One2many('event.question', 'event_id', 'General Questions',
+ domain=[('once_per_order', '=', True)])
+ specific_question_ids = fields.One2many('event.question', 'event_id', 'Specific Questions',
+ domain=[('once_per_order', '=', False)])
+
+ @api.depends('event_type_id')
+ def _compute_question_ids(self):
+ """ Update event questions from its event type. Depends are set only on
+ event_type_id itself to emulate an onchange. Changing event type content
+ itself should not trigger this method.
+
+ When synchronizing questions:
+
+ * lines that no answer are removed;
+ * type lines are added;
+ """
+ if self._origin.question_ids:
+ # lines to keep: those with already sent emails or registrations
+ questions_tokeep_ids = self.env['event.registration.answer'].search(
+ [('question_id', 'in', self._origin.question_ids.ids)]
+ ).question_id.ids
+ else:
+ questions_tokeep_ids = []
+ for event in self:
+ if not event.event_type_id and not event.question_ids:
+ event.question_ids = False
+ continue
+
+ if questions_tokeep_ids:
+ questions_toremove = event._origin.question_ids.filtered(lambda question: question.id not in questions_tokeep_ids)
+ command = [(3, question.id) for question in questions_toremove]
+ else:
+ command = [(5, 0)]
+ if event.event_type_id.use_mail_schedule:
+ command += [
+ (0, 0, {
+ 'title': question.title,
+ 'question_type': question.question_type,
+ 'sequence': question.sequence,
+ 'once_per_order': question.once_per_order,
+ 'answer_ids': [(0, 0, {
+ 'name': answer.name,
+ 'sequence': answer.sequence
+ }) for answer in question.answer_ids],
+ }) for question in event.event_type_id.question_ids
+ ]
+ event.question_ids = command
diff --git a/addons/website_event_questions/models/event_question.py b/addons/website_event_questions/models/event_question.py
new file mode 100644
index 00000000..4d058569
--- /dev/null
+++ b/addons/website_event_questions/models/event_question.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, fields, models, _
+from odoo.exceptions import UserError
+
+
+class EventQuestion(models.Model):
+ _name = 'event.question'
+ _rec_name = 'title'
+ _order = 'sequence,id'
+ _description = 'Event Question'
+
+ title = fields.Char(required=True, translate=True)
+ question_type = fields.Selection([
+ ('simple_choice', 'Selection'),
+ ('text_box', 'Text Input')], default='simple_choice', string="Question Type", required=True)
+ 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.question.answer', 'question_id', "Answers", copy=True)
+ sequence = fields.Integer(default=10)
+ once_per_order = fields.Boolean('Ask only once per order',
+ help="If True, this question will be asked only once and its value will be propagated to every attendees."
+ "If not it will be asked for every attendee of a reservation.")
+
+ @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 cannot belong to both the event category and itself.'))
+
+ def write(self, vals):
+ """ We add a check to prevent changing the question_type of a question that already has answers.
+ Indeed, it would mess up the event.registration.answer (answer type not matching the question type). """
+
+ if 'question_type' in vals:
+ questions_new_type = self.filtered(lambda question: question.question_type != vals['question_type'])
+ if questions_new_type:
+ answer_count = self.env['event.registration.answer'].search_count([('question_id', 'in', questions_new_type.ids)])
+ if answer_count > 0:
+ raise UserError(_("You cannot change the question type of a question that already has answers!"))
+ return super(EventQuestion, self).write(vals)
+
+ def action_view_question_answers(self):
+ """ Allow analyzing the attendees answers to event questions in a convenient way:
+ - A graph view showing counts of each suggestions for simple_choice questions
+ (Along with secondary pivot and tree views)
+ - A tree view showing textual answers values for text_box questions. """
+ self.ensure_one()
+ action = self.env["ir.actions.actions"]._for_xml_id("website_event_questions.action_event_registration_report")
+ action['domain'] = [('question_id', '=', self.id)]
+ if self.question_type == 'simple_choice':
+ action['views'] = [(False, 'graph'), (False, 'pivot'), (False, 'tree')]
+ elif self.question_type == 'text_box':
+ action['views'] = [(False, 'tree')]
+ return action
+
+class EventQuestionAnswer(models.Model):
+ """ Contains suggested answers to a 'simple_choice' event.question. """
+ _name = 'event.question.answer'
+ _order = 'sequence,id'
+ _description = 'Event Question Answer'
+
+ name = fields.Char('Answer', required=True, translate=True)
+ question_id = fields.Many2one('event.question', required=True, ondelete='cascade')
+ sequence = fields.Integer(default=10)
diff --git a/addons/website_event_questions/models/event_registration.py b/addons/website_event_questions/models/event_registration.py
new file mode 100644
index 00000000..72683374
--- /dev/null
+++ b/addons/website_event_questions/models/event_registration.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class EventRegistration(models.Model):
+ """ Store answers on attendees. """
+ _inherit = 'event.registration'
+
+ registration_answer_ids = fields.One2many('event.registration.answer', 'registration_id', string='Attendee Answers')
+
+class EventRegistrationAnswer(models.Model):
+ """ Represents the user input answer for a single event.question """
+ _name = 'event.registration.answer'
+ _description = 'Event Registration Answer'
+
+ question_id = fields.Many2one(
+ 'event.question', ondelete='restrict', required=True,
+ domain="[('event_id', '=', event_id)]")
+ registration_id = fields.Many2one('event.registration', required=True, ondelete='cascade')
+ partner_id = fields.Many2one('res.partner', related='registration_id.partner_id')
+ event_id = fields.Many2one('event.event', related='registration_id.event_id')
+ question_type = fields.Selection(related='question_id.question_type')
+ value_answer_id = fields.Many2one('event.question.answer', string="Suggested answer")
+ value_text_box = fields.Text('Text answer')
+
+ _sql_constraints = [
+ ('value_check', "CHECK(value_answer_id IS NOT NULL OR COALESCE(value_text_box, '') <> '')", "There must be a suggested value or a text value.")
+ ]