Skip to content

Commit 9ab5256

Browse files
[IMP] Ensure at least one checkbox is checked in mandatory multiple questions
--------- Co-authored-by: Hugo Trentesaux <hugo@le-filament.com> Co-authored-by: Rémi - Le Filament <30716308+remi-filament@users.noreply.github.com>
1 parent 54aeed2 commit 9ab5256

7 files changed

Lines changed: 307 additions & 31 deletions

File tree

website_event_questions_multiple/README.rst

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ Questions on Events - Type multiple
1313
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
1414
:target: https://odoo-community.org/page/development-status
1515
:alt: Production/Stable
16-
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17-
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18-
:alt: License: AGPL-3
16+
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
18+
:alt: License: LGPL-3
1919
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fevent-lightgray.png?logo=github
2020
:target: https://github.com/OCA/event/tree/16.0/website_event_questions_multiple
2121
:alt: OCA/event
@@ -28,7 +28,7 @@ Questions on Events - Type multiple
2828

2929
|badge1| |badge2| |badge3| |badge4| |badge5|
3030

31-
This module allows to add new question type : Selection multiple which allows
31+
This module allows to add new question type : Multiple Selection which allows
3232
attendees to select multiple answers to a question.
3333

3434
**Table of contents**
@@ -39,7 +39,7 @@ attendees to select multiple answers to a question.
3939
Configuration
4040
=============
4141

42-
On an event, when creating a new question, you can select new type : Selection multiple
42+
On an event, when creating a new question, you can select new type : Multiple Selection
4343

4444
Bug Tracker
4545
===========
@@ -58,6 +58,7 @@ Authors
5858
~~~~~~~
5959

6060
* Le Filament
61+
* Odoo S.A.
6162

6263
Contributors
6364
~~~~~~~~~~~~

website_event_questions_multiple/__manifest__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@
44
"category": "Marketing",
55
"website": "https://github.com/OCA/event",
66
"development_status": "Production/Stable",
7-
"author": "Le Filament, Odoo Community Association (OCA)",
8-
"license": "AGPL-3",
7+
"author": "Le Filament, Odoo Community Association (OCA), Odoo S.A.",
8+
"license": "LGPL-3",
99
"application": False,
1010
"depends": ["website_event_questions"],
1111
"data": [
1212
"templates/event_template.xml",
1313
"views/event_questions_views.xml",
1414
"views/event_registration_views.xml",
1515
],
16+
"assets": {
17+
"web.assets_frontend": [
18+
"website_event_questions_multiple/static/src/js/form_validation.esm.js"
19+
],
20+
},
1621
"installable": True,
1722
"auto_install": False,
1823
}

website_event_questions_multiple/controllers/main.py

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright 2023 Le Filament (https://le-filament.com)
22
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
33

4+
from odoo.exceptions import UserError
45
from odoo.http import request
56

67
from odoo.addons.website_event_questions.controllers.main import WebsiteEvent
@@ -11,33 +12,85 @@ def _process_attendees_form(self, event, form_details):
1112
"""Process data posted from the attendee details form.
1213
Extracts question answers:
1314
- For questions of type 'multiple_choice', extracting the suggested answer id"""
14-
registrations = super(WebsiteEvent, self)._process_attendees_form(
15-
event, form_details
15+
registrations = super()._process_attendees_form(event, form_details)
16+
17+
# list all question_multi_answer with is_mandatory_answer
18+
mandatory_multiple_general_question_answer_count = {}
19+
mandatory_multiple_specific_question_ids = set()
20+
req_filter = (
21+
lambda q: q.question_type == "multiple_choice" and q.is_mandatory_answer
1622
)
23+
for general_question in event.general_question_ids.filtered(req_filter):
24+
mandatory_multiple_general_question_answer_count[general_question.id] = 0
25+
for specific_question in event.specific_question_ids.filtered(req_filter):
26+
mandatory_multiple_specific_question_ids.add(specific_question.id)
27+
28+
mandatory_multiple_specific_question_answer_count = [
29+
{i: 0 for i in mandatory_multiple_specific_question_ids}
30+
for j in range(len(registrations))
31+
]
1732

1833
general_answer_ids = []
1934
for key, _value in form_details.items():
20-
if "question_multi_answer" in key:
21-
dummy, registration_index, question_answer = key.split("-")
22-
question_id, answer_id = question_answer.split("_")
23-
question_sudo = request.env["event.question"].browse(int(question_id))
35+
# test html input prefix
36+
if key.startswith("question_multi_answer"):
37+
_html_input_prefix, registration_index_str, question_answer = key.split(
38+
"-"
39+
)
40+
registration_index = int(registration_index_str)
41+
question_id_str, answer_id = question_answer.split("_")
42+
question_id = int(question_id_str)
43+
question_sudo = request.env["event.question"].browse(question_id)
2444
answer_sudo = request.env["event.question.answer"].browse(
2545
int(answer_id)
2646
)
27-
answer_values = None
28-
if question_sudo.question_type == "multiple_choice":
29-
answer_values = {
30-
"question_id": int(question_id),
31-
"value_text_box": answer_sudo.name,
32-
}
33-
34-
if answer_values and not int(registration_index):
47+
assert (
48+
question_sudo.question_type == "multiple_choice"
49+
) # otherwise, html is malformed
50+
answer_values = {
51+
"question_id": question_id,
52+
"value_text_box": answer_sudo.name,
53+
}
54+
# question with null registration index are general
55+
if registration_index == 0:
3556
general_answer_ids.append((0, 0, answer_values))
36-
elif answer_values:
37-
registrations[int(registration_index) - 1][
38-
"registration_answer_ids"
39-
].append((0, 0, answer_values))
57+
if question_sudo.is_mandatory_answer:
58+
mandatory_multiple_general_question_answer_count[
59+
question_id
60+
] += 1
61+
# question with registration index are specific to one registration
62+
else:
63+
rindex = registration_index - 1 # zero-based array ¹indexing
64+
registrations[rindex]["registration_answer_ids"].append(
65+
(0, 0, answer_values)
66+
)
67+
if question_sudo.is_mandatory_answer:
68+
mandatory_multiple_specific_question_answer_count[rindex][
69+
question_id
70+
] += 1
71+
72+
# check that answers contain at least one for mandatory question
73+
# general
74+
for q, c in mandatory_multiple_general_question_answer_count.items():
75+
if c == 0:
76+
raise UserError(
77+
"Question "
78+
+ str(q)
79+
+ " is mandatory but did not receive an answer."
80+
)
81+
# specific
82+
for r, cc in enumerate(mandatory_multiple_specific_question_answer_count):
83+
for q, c in cc.items():
84+
if c == 0:
85+
raise UserError(
86+
"Question "
87+
+ str(q)
88+
+ " is mandatory but did not receive an answer in ticket number "
89+
+ str(r)
90+
+ "."
91+
)
4092

93+
# append general question to all items
4194
for registration in registrations:
4295
registration["registration_answer_ids"].extend(general_answer_ids)
4396

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Translation of Odoo Server.
2+
# This file contains the translation of the following modules:
3+
# * website_event_questions_multiple
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: Odoo Server 16.0\n"
8+
"Report-Msgid-Bugs-To: \n"
9+
"POT-Creation-Date: 2025-03-06 11:52+0000\n"
10+
"PO-Revision-Date: 2025-03-06 11:52+0000\n"
11+
"Last-Translator: \n"
12+
"Language-Team: \n"
13+
"MIME-Version: 1.0\n"
14+
"Content-Type: text/plain; charset=UTF-8\n"
15+
"Content-Transfer-Encoding: \n"
16+
"Plural-Forms: \n"
17+
18+
#. module: website_event_questions_multiple
19+
#: model:ir.model,name:website_event_questions_multiple.model_event_question
20+
msgid "Event Question"
21+
msgstr "Question"
22+
23+
#. module: website_event_questions_multiple
24+
#: model:ir.model.fields.selection,name:website_event_questions_multiple.selection__event_question__question_type__multiple_choice
25+
msgid "Multiple Selection"
26+
msgstr "Sélection multiple"
27+
28+
#. module: website_event_questions_multiple
29+
#: model:ir.model.fields,field_description:website_event_questions_multiple.field_event_question__question_type
30+
msgid "Question Type"
31+
msgstr "Type de question"
32+
33+
#. module: website_event_questions_multiple
34+
#: model_terms:ir.ui.view,arch_db:website_event_questions_multiple.registration_event_question
35+
msgid "Please select at least one checkbox."
36+
msgstr "Veuillez cocher au moins une case."

website_event_questions_multiple/static/description/index.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,8 @@ <h1 class="title">Questions on Events - Type multiple</h1>
369369
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
370370
!! source digest: sha256:de10ccad1e53385cb3c9aa56bc533e4cd053db148e2d5fec32a0a0e04ac0e690
371371
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
372-
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/event/tree/16.0/website_event_questions_multiple"><img alt="OCA/event" src="https://img.shields.io/badge/github-OCA%2Fevent-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/event-16-0/event-16-0-website_event_questions_multiple"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/event&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
373-
<p>This module allows to add new question type : Selection multiple which allows
372+
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/event/tree/16.0/website_event_questions_multiple"><img alt="OCA/event" src="https://img.shields.io/badge/github-OCA%2Fevent-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/event-16-0/event-16-0-website_event_questions_multiple"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/event&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
373+
<p>This module allows to add new question type : Multiple Selection which allows
374374
attendees to select multiple answers to a question.</p>
375375
<p><strong>Table of contents</strong></p>
376376
<div class="contents local topic" id="contents">
@@ -388,7 +388,7 @@ <h1 class="title">Questions on Events - Type multiple</h1>
388388
</div>
389389
<div class="section" id="configuration">
390390
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
391-
<p>On an event, when creating a new question, you can select new type : Selection multiple</p>
391+
<p>On an event, when creating a new question, you can select new type : Multiple Selection</p>
392392
</div>
393393
<div class="section" id="bug-tracker">
394394
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
@@ -404,6 +404,7 @@ <h1><a class="toc-backref" href="#toc-entry-3">Credits</a></h1>
404404
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
405405
<ul class="simple">
406406
<li>Le Filament</li>
407+
<li>Odoo S.A.</li>
407408
</ul>
408409
</div>
409410
<div class="section" id="contributors">

0 commit comments

Comments
 (0)