mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-21 04:12:03 +02:00
19.0 vanilla
This commit is contained in:
parent
d1963a3c3a
commit
2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions
102
odoo-bringout-oca-ocb-event/event/models/event_question.py
Normal file
102
odoo-bringout-oca-ocb-event/event/models/event_question.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# 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'),
|
||||
('name', 'Name'),
|
||||
('email', 'Email'),
|
||||
('phone', 'Phone'),
|
||||
('company_name', 'Company'),
|
||||
], default='simple_choice', string="Question Type", required=True)
|
||||
active = fields.Boolean('Active', default=True)
|
||||
event_type_ids = fields.Many2many('event.type', string='Event Types', copy=False)
|
||||
event_ids = fields.Many2many('event.event', string='Events', copy=False)
|
||||
event_count = fields.Integer('# Events', compute='_compute_event_count')
|
||||
is_default = fields.Boolean('Default question', help="Include by default in new events.")
|
||||
is_reusable = fields.Boolean('Is Reusable',
|
||||
compute='_compute_is_reusable', default=True, store=True,
|
||||
help='Allow this question to be selected and reused for any future event. Always true for default questions.')
|
||||
answer_ids = fields.One2many('event.question.answer', 'question_id', "Answers", copy=True)
|
||||
sequence = fields.Integer(default=10)
|
||||
once_per_order = fields.Boolean('Ask once per order',
|
||||
help="Check this for order-level questions (e.g., 'Company Name') where the answer is the same for everyone.")
|
||||
is_mandatory_answer = fields.Boolean('Mandatory Answer')
|
||||
|
||||
_check_default_question_is_reusable = models.Constraint(
|
||||
'CHECK(is_default IS DISTINCT FROM TRUE OR is_reusable IS TRUE)',
|
||||
"A default question must be reusable."
|
||||
)
|
||||
|
||||
@api.depends('event_ids')
|
||||
def _compute_event_count(self):
|
||||
event_count_per_question = dict(self.env['event.event']._read_group(
|
||||
domain=[('question_ids', 'in', self.ids)],
|
||||
groupby=['question_ids'],
|
||||
aggregates=['__count']
|
||||
))
|
||||
for question in self:
|
||||
question.event_count = event_count_per_question.get(question, 0)
|
||||
|
||||
@api.depends('is_default', 'event_type_ids')
|
||||
def _compute_is_reusable(self):
|
||||
self.filtered('is_default').is_reusable = True
|
||||
|
||||
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().write(vals)
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_except_answered_question(self):
|
||||
if self.env['event.registration.answer'].search_count([('question_id', 'in', self.ids)]):
|
||||
raise UserError(_('You cannot delete a question that has already been answered by attendees. You can archive it instead.'))
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_except_default_question(self):
|
||||
if set(self.ids) & set(self.env['event.type']._default_question_ids()):
|
||||
raise UserError(_('You cannot delete a default question.'))
|
||||
|
||||
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 suggestion for simple_choice questions
|
||||
(Along with secondary pivot and list views)
|
||||
- A list view showing textual answers values for text_box questions.
|
||||
"""
|
||||
self.ensure_one()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("event.action_event_registration_report")
|
||||
action['context'] = {'search_default_question_id': self.id}
|
||||
if event_id := self.env.context.get('search_default_event_id'):
|
||||
action['context'].update(search_default_event_id=event_id)
|
||||
# Fetch attendee answers for which the event is still linked to the question.
|
||||
action['domain'] = [('event_id.question_ids', 'in', self.ids)]
|
||||
|
||||
if self.question_type == 'simple_choice':
|
||||
action['views'] = [(False, 'graph'), (False, 'pivot'), (False, 'list')]
|
||||
elif self.question_type == 'text_box':
|
||||
action['views'] = [(False, 'list')]
|
||||
return action
|
||||
|
||||
def action_event_view(self):
|
||||
self.ensure_one()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("event.action_event_view")
|
||||
action['domain'] = [('question_ids', 'in', self.ids)]
|
||||
return action
|
||||
Loading…
Add table
Add a link
Reference in a new issue