From a1fb5bc5ca6c7412418abdf867cbbecd280f8e98 Mon Sep 17 00:00:00 2001 From: clementthomas Date: Mon, 18 Sep 2023 16:54:59 +0200 Subject: [PATCH] [IMP] survey_event_registration_generation: event registration generation --- .../__manifest__.py | 4 +- .../controllers/main.py | 6 +- .../models/__init__.py | 3 +- .../models/survey_question.py | 93 ++++++++++++++++++- .../models/survey_survey.py | 11 +++ .../models/survey_user_input.py | 89 +++++++++++++++++- .../views/survey_question_views.xml | 25 ++++- .../views/survey_survey_views.xml | 14 +++ 8 files changed, 232 insertions(+), 13 deletions(-) create mode 100644 survey_event_registration_generation/models/survey_survey.py create mode 100644 survey_event_registration_generation/views/survey_survey_views.xml diff --git a/survey_event_registration_generation/__manifest__.py b/survey_event_registration_generation/__manifest__.py index 02890d9..6ad497c 100644 --- a/survey_event_registration_generation/__manifest__.py +++ b/survey_event_registration_generation/__manifest__.py @@ -12,7 +12,9 @@ "depends": ["survey"], "data": [ 'views/survey_question_views.xml', - 'views/survey_templates.xml' + 'views/survey_survey_views.xml', + 'views/survey_templates.xml', + #'security/ir.model.access.csv', ], 'assets': { 'survey.survey_assets': [ diff --git a/survey_event_registration_generation/controllers/main.py b/survey_event_registration_generation/controllers/main.py index 44e0aac..cf1f0b6 100644 --- a/survey_event_registration_generation/controllers/main.py +++ b/survey_event_registration_generation/controllers/main.py @@ -7,7 +7,7 @@ from odoo.http import request class Survey(main.Survey): def _prepare_survey_data(self, survey_sudo, answer_sudo, **post): result = super(Survey, self)._prepare_survey_data(survey_sudo, answer_sudo, **post) - result['event_products'] = request.env['product.product'].search([('detailed_type','=','event')]) + result['event_products'] = request.env['product.product'].sudo().search([('detailed_type','=','event')]) next_event_question = self._get_next_event_question(answer_sudo) if next_event_question: @@ -15,10 +15,10 @@ class Survey(main.Survey): if next_event_question.event_product_question_id: event_product = self._get_answer_event_product(next_event_question.event_product_question_id, answer_sudo) if event_product: - event_tickets = request.env['event.event.ticket'].search([('product_id','=',event_product.id)]) + event_tickets = request.env['event.event.ticket'].sudo().search([('product_id','=',event_product.id)]) result['events'] = event_tickets.event_id else: - result['events'] = request.env['event.event'].search([]) + result['events'] = request.env['event.event'].sudo().search([]) return result diff --git a/survey_event_registration_generation/models/__init__.py b/survey_event_registration_generation/models/__init__.py index d6b6801..12bd654 100644 --- a/survey_event_registration_generation/models/__init__.py +++ b/survey_event_registration_generation/models/__init__.py @@ -1,3 +1,4 @@ from . import survey_question from . import survey_user_input -from . import survey_user_input_line \ No newline at end of file +from . import survey_user_input_line +from . import survey_survey \ No newline at end of file diff --git a/survey_event_registration_generation/models/survey_question.py b/survey_event_registration_generation/models/survey_question.py index 94c1b05..8e90af2 100644 --- a/survey_event_registration_generation/models/survey_question.py +++ b/survey_event_registration_generation/models/survey_question.py @@ -9,7 +9,7 @@ class SurveyQuestion(models.Model): event_product_question_id = fields.Many2one( - 'survey.question', string="Event ticket question", copy=False, compute="_compute_event_product_question_id", + 'survey.question', string="Event product question", copy=False, compute="_compute_event_product_question_id", store=True, readonly=False, help="If you specify question of event product, only events of selected product will be proposed.", domain="[('survey_id', '=', survey_id), \ '&', ('question_type', '=', 'event_product'), \ @@ -17,12 +17,95 @@ class SurveyQuestion(models.Model): ('sequence', '<', sequence), \ '&', ('sequence', '=', sequence), ('id', '<', id)]") + event_registration_allowed_field_ids = fields.Many2many( + comodel_name="ir.model.fields", + compute="_compute_event_registration_allowed_field_ids", + ) + event_registration_field = fields.Many2one( + string="Event registration field", + comodel_name="ir.model.fields", + domain="[('id', 'in', event_registration_allowed_field_ids)]", + ) + + @api.depends("question_type") + def _compute_event_registration_allowed_field_ids(self): + type_mapping = { + "char_box": ["char", "text"], + "text_box": ["html"], + "numerical_box": ["integer", "float", "html", "char"], + "date": ["date", "text", "char"], + "datetime": ["datetime", "html", "char"], + "simple_choice": ["many2one", "html", "char"], + "multiple_choice": ["many2many", "html", "char"], + } + for record in self: + if record.question_type == "event": + record.event_registration_allowed_field_ids = ( + self.env["ir.model.fields"] + .search( + [ + ("model", "=", "event.registration"), + ("name", "=", "event_id"), + ] + ) + .ids + ) + record.event_registration_allowed_field_ids = ( + self.env["ir.model.fields"] + .search( + [ + ("model", "=", "event.registration"), + ("ttype", "in", type_mapping.get(record.question_type, [])), + ] + ) + .ids + ) + @api.depends('question_type') def _compute_event_product_question_id(self): - """ Used as an 'onchange' : Reset the event ticket question if user change question type + """ Used as an 'onchange' : Reset the event product question if user change question type Avoid CacheMiss : set the value to False if the value is not set yet.""" for question in self: - if not question.question_type == 'event' or question.triggering_question_id is None: - question.triggering_question_id = False - \ No newline at end of file + if not question.question_type == 'event' or question.event_product_question_id is None: + question.event_product_question_id = False + + +class SurveyQuestionAnswer(models.Model): + _inherit = "survey.question.answer" + + @api.model + def default_get(self, fields): + result = super().default_get(fields) + if ( + not result.get("event_registration_field") + or "event_registration_field_resource_ref" not in fields + ): + return result + registration_field = self.env["ir.model.fields"].browse(result["event_registration_field"]) + # Otherwise we'll just use the value (char, text) + if registration_field.ttype not in {"many2one", "many2many"}: + return result + res = self.env[registration_field.relation].search([], limit=1) + if res: + result["event_registration_field_resource_ref"] = "%s,%s" % ( + registration_field.relation, + res.id, + ) + return result + + @api.model + def _selection_event_registration_field_resource_ref(self): + return [(model.model, model.name) for model in self.env["ir.model"].search([])] + + event_registration_field = fields.Many2one(related="question_id.event_registration_field") + event_registration_field_resource_ref = fields.Reference( + string="Event registration field value", + selection="_selection_event_registration_field_resource_ref", + ) + + @api.onchange("event_registration_field_resource_ref") + def _onchange_event_registration_field_resource_ref(self): + """Set the default value as the display_name, although we can change it""" + if self.event_registration_field_resource_ref: + self.value = self.event_registration_field_resource_ref.display_name or "" diff --git a/survey_event_registration_generation/models/survey_survey.py b/survey_event_registration_generation/models/survey_survey.py new file mode 100644 index 0000000..8e8f6f4 --- /dev/null +++ b/survey_event_registration_generation/models/survey_survey.py @@ -0,0 +1,11 @@ +# Copyright 2023 Tecnativa - David Vidal +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class SurveySurvey(models.Model): + _inherit = "survey.survey" + + generate_registration = fields.Boolean( + help="Generate registration for selected event", + ) diff --git a/survey_event_registration_generation/models/survey_user_input.py b/survey_event_registration_generation/models/survey_user_input.py index 2b225bf..e89dfed 100644 --- a/survey_event_registration_generation/models/survey_user_input.py +++ b/survey_event_registration_generation/models/survey_user_input.py @@ -15,7 +15,14 @@ _logger = logging.getLogger(__name__) class SurveyUserInput(models.Model): _inherit = 'survey.user_input' + registration_id = fields.Many2one('event.registration', 'Event registration') + def save_lines(self, question, answer, comment=None): + """ + Inherit save_lines method, called after each answer + to save selected event or event_product in user_input.line + depending on the question type + """ old_answers = self.env['survey.user_input.line'].search([ ('user_input_id', '=', self.id), ('question_id', '=', question.id) @@ -29,6 +36,9 @@ class SurveyUserInput(models.Model): def _save_event_product(self, question, old_answers, answer): + """ + Save event product to user_input.line + """ vals = self._get_line_answer_values(question, answer, question.question_type) vals['value_event_product'] = int(vals['value_event_product']) if old_answers: @@ -38,10 +48,87 @@ class SurveyUserInput(models.Model): return self.env['survey.user_input.line'].create(vals) def _save_event(self, question, old_answers, answer): + """ + Save event to user_input.line + """ vals = self._get_line_answer_values(question, answer, question.question_type) vals['value_event'] = int(vals['value_event']) if old_answers: old_answers.write(vals) return old_answers else: - return self.env['survey.user_input.line'].create(vals) \ No newline at end of file + return self.env['survey.user_input.line'].create(vals) + + def _prepare_registration(self): + """Extract registration values from the answers""" + + elegible_inputs = self.user_input_line_ids.filtered( + lambda x: x.question_id.event_registration_field and not x.skipped + ) + basic_inputs = elegible_inputs.filtered( + lambda x: x.answer_type not in {"suggestion"} + and x.question_id.event_registration_field.name != "comment" + ) + + vals = {} + for line in basic_inputs: + if line.question_id.event_registration_field.ttype == 'many2one': + vals[line.question_id.event_registration_field.name] = line[f"value_{line.answer_type}"].id + else: + vals[line.question_id.event_registration_field.name] = line[f"value_{line.answer_type}"] + + for line in elegible_inputs - basic_inputs: + field_name = line.question_id.event_registration_field.name + if line.question_id.event_registration_field.ttype == "many2one": + vals[ + field_name + ] = line.suggested_answer_id.event_registration_field_resource_ref.id + elif line.question_id.event_registration_field.ttype == "many2many": + vals.setdefault(field_name, []) + vals[field_name] += [ + (4, line.suggested_answer_id.event_registration_field_resource_ref.id) + ] + # We'll use the comment field to add any other infos + elif field_name == "comment": + vals.setdefault("comment", "") + value = ( + line.suggested_answer_id.value + if line.answer_type == "suggestion" + else line[f"value_{line.answer_type}"] + ) + vals["comment"] += f"\n{line.question_id.title}: {value}" + else: + if line.question_id.question_type == "multiple_choice": + if not vals.get(field_name): + vals[field_name] = line.suggested_answer_id.value + else: + vals[field_name] += line.suggested_answer_id.value + else: + vals[field_name] = line.suggested_answer_id.value + return vals + + def _create_registration_post_process(self, registration): + """After creating the lead send an internal message with the input link""" + registration.message_post_with_view( + "mail.message_origin_link", + values={"self": registration, "origin": self.survey_id}, + subtype_id=self.env.ref("mail.mt_note").id, + ) + + def _mark_done(self): + """Generate registration when the survey is submitted""" + for user_input in self.filtered( + lambda r: r.survey_id.generate_registration and not self.registration_id + ): + vals = user_input._prepare_registration() + + registration = self.env["event.registration"].create(vals) + self._create_registration_post_process(registration) + self.update({"registration_id": registration.id}) + res = super()._mark_done() + + # after all, set partner id of registration as the partner of user input + for user_input in self: + if user_input.registration_id and user_input.partner_id: + user_input.registration_id.partner_id = user_input.partner_id + return res diff --git a/survey_event_registration_generation/views/survey_question_views.xml b/survey_event_registration_generation/views/survey_question_views.xml index 0d25cf4..cbb90b4 100644 --- a/survey_event_registration_generation/views/survey_question_views.xml +++ b/survey_event_registration_generation/views/survey_question_views.xml @@ -7,10 +7,31 @@ - + attrs="{'invisible': [('question_type','!=','event')]}" + help="Select the question asking for event product, to filter proposed events." /> + + + + + + {'default_question_id': active_id, 'default_event_registration_field': event_registration_field} + + + + + diff --git a/survey_event_registration_generation/views/survey_survey_views.xml b/survey_event_registration_generation/views/survey_survey_views.xml new file mode 100644 index 0000000..f236e78 --- /dev/null +++ b/survey_event_registration_generation/views/survey_survey_views.xml @@ -0,0 +1,14 @@ + + + + survey.survey + + + + + + + + + +