Skip to content

Commit

Permalink
[ADD] survey_condition_validation_option
Browse files Browse the repository at this point in the history
- condition validation for date and datetime about today option
- condition validation for limit max or min count item into multiple
selection
  • Loading branch information
mathben committed Nov 17, 2024
1 parent 471d0e0 commit 24e0f8d
Show file tree
Hide file tree
Showing 21 changed files with 1,657 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from . import models
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2024 TechnoLibre - Mathieu Benoit
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Survey condition validation option",
"version": "16.0.1.0.0",
"author": "TechnoLibre, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/survey",
"license": "AGPL-3",
"category": "Marketing/Surveys",
"development_status": "Beta",
"data": ["views/survey_question_views.xml"],
"depends": [
"survey",
],
"installable": True,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)

from . import survey_question
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#!/usr/bin/env python3
# © 2024 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

import logging
from datetime import datetime

from dateutil.relativedelta import relativedelta
from pytz import timezone

from odoo import _, api, exceptions, fields, models

_logger = logging.getLogger(__name__)


class SurveyQuestion(models.Model):
_inherit = "survey.question"

validation_min_multiple_choice_option = fields.Integer(
default=-1,
help="The option is affected by validation_max_multiple_choice_option, limit the selection value to be choose.",
)

validation_max_multiple_choice_option = fields.Integer(
default=-1,
help="The option is affected by validation_min_multiple_choice_option, limit the selection value to be choose.",
)

validation_min_datetime_option = fields.Selection(
selection=[
("today", "Today"),
],
help="The option is affected by validation_max_datetime_option",
)

validation_max_datetime_option = fields.Selection(
selection=[
("today", "Today"),
],
help="The option is affected by validation_min_datetime_option",
)

validation_min_date_option = fields.Selection(
selection=[
("today", "Today"),
],
help="The option is affected by validation_max_date_option",
)

validation_max_date_option = fields.Selection(
selection=[
("today", "Today"),
],
help="The option is affected by validation_min_date_option",
)

@api.depends("question_type")
def _compute_validation_required(self):
for question in self:
if (
not question.validation_required
or question.question_type
not in [
"char_box",
"numerical_box",
"date",
"datetime",
"multiple_choice",
]
):
question.validation_required = False

def _validate_choice(self, answer, comment):
# Empty comment
if (
self.constr_mandatory
and not answer
and not (
self.comments_allowed
and self.comment_count_as_answer
and comment
)
):
return {
self.id: self.constr_error_msg
or _("This question requires an answer.")
}
if (
self.validation_required
and self.question_type == "multiple_choice"
):
lst_answer = answer if type(answer) == list else [answer]
if self.validation_min_multiple_choice_option == -1:
min_value = 0
else:
min_value = self.validation_min_multiple_choice_option
if self.validation_max_multiple_choice_option == -1:
max_value = len(self.suggested_answer_ids)
else:
max_value = self.validation_max_multiple_choice_option
if not (min_value <= len(lst_answer) <= max_value):
return {
self.id: self.constr_error_msg
or _(
"You need to select between %s and %s answers, you chose %s answer."
% (min_value, max_value, len(answer))
)
}
# "Choisir entre %s et %s réponses. Vous avez choisi %s réponse(s)."
return {}

def _validate_date(self, answer):
# Overwrite survey/models/survey_question.py
isDatetime = self.question_type == "datetime"
# Checks if user input is a date
try:
dateanswer = (
fields.Datetime.from_string(answer)
if isDatetime
else fields.Date.from_string(answer)
)
except ValueError:
return {self.id: _("This is not a date")}
if self.validation_required:

# Calculate delay time
user_tz = self.env.user.tz or "UTC"
user_timezone = timezone(user_tz)
heure_actuelle = datetime.now(user_timezone)
decalage_horaire = (
heure_actuelle.utcoffset().total_seconds() / 3600
)
diff_hour = int(decalage_horaire)

# Check if answer is in the right range
if isDatetime:
if self.validation_min_datetime_option:
if self.validation_min_datetime_option == "today":
today = fields.Date.today()
min_date = fields.datetime(
today.year, today.month, today.day
) - relativedelta(hours=diff_hour)
else:
_logger.error(
f"Missing information about validation_min_datetime_option: {self.validation_min_datetime_option}"
)
min_date = False
else:
min_date = fields.Datetime.from_string(
self.validation_min_datetime
)
if self.validation_max_datetime_option:
if self.validation_max_datetime_option == "today":
today = fields.Date.today() + relativedelta(days=1)
max_date = fields.datetime(
today.year, today.month, today.day, -diff_hour
)
else:
_logger.error(
f"Missing information about validation_max_datetime_option: {self.validation_max_datetime_option}"
)
max_date = False
else:
max_date = fields.Datetime.from_string(
self.validation_max_datetime
)
dateanswer = fields.Datetime.from_string(answer)
else:
if self.validation_min_date_option:
if self.validation_min_date_option == "today":
min_date = fields.Date.today()
else:
_logger.error(
f"Missing information about validation_min_date_option: {self.validation_min_date_option}"
)
min_date = False
else:
min_date = fields.Date.from_string(
self.validation_min_date
)
if self.validation_max_date_option:
if self.validation_max_date_option == "today":
max_date = fields.Date.today() + relativedelta(days=1)
else:
_logger.error(
f"Missing information about validation_max_date_option: {self.validation_max_date_option}"
)
max_date = False
else:
max_date = fields.Date.from_string(
self.validation_max_date
)
dateanswer = fields.Date.from_string(answer)
if (
min_date
and max_date
and not (min_date <= dateanswer < max_date)
):
date_min_show = min_date.astimezone(user_timezone).strftime(
"%Y-%m-%d %H:%M:%S"
)
date_max_show = max_date.astimezone(user_timezone).strftime(
"%Y-%m-%d %H:%M:%S"
)
return {
self.id: self.validation_error_msg
or _(
"The date needs to be between %s and %s."
% (date_min_show, date_max_show)
)
}
elif min_date and not min_date <= dateanswer:
date_min_show = min_date.astimezone(user_timezone).strftime(
"%Y-%m-%d %H:%M:%S"
)
return {
self.id: self.validation_error_msg
or _("The date needs to be after %s." % date_min_show)
}
elif max_date and not dateanswer <= max_date:
date_max_show = max_date.astimezone(user_timezone).strftime(
"%Y-%m-%d %H:%M:%S"
)
return {
self.id: self.validation_error_msg
or _("The date needs to be before %s." % date_max_show)
}

return {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* `TechnoLibre <https://technolibre.ca>`_:

* Mathieu Benoit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This module add conditional option to survey:

* Add a condition of an option on date and datetime types to apply a minimum or maximum on today's day
* Add a condition to set a minimum or maximum of answers on a multiple selection
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<!-- QUESTIONS -->
<record model="ir.ui.view" id="survey_question_form">
<field name="name">Form view for survey question</field>
<field name="inherit_id" ref="survey.survey_question_form" />
<field name="model">survey.question</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='validation_min_datetime']" position="after">
<field
name="validation_min_datetime_option"
string="'Datetime minimum' option"
attrs="{'invisible': ['|', ('question_type', '!=', 'datetime'), ('validation_required', '=', False)]}"
/>
</xpath>
<!-- <field name="validation_required"-->
<!-- attrs="{'invisible': [('question_type', 'not in', ['char_box', 'numerical_box', 'date', 'datetime'])]}"/>-->
<xpath expr="//field[@name='validation_required']" position="attributes">
<attribute name="attrs">
{'invisible': [('question_type', 'not
in', ['char_box', 'numerical_box', 'date', 'datetime', 'multiple_choice'])]}
</attribute>
</xpath>
<xpath expr="//field[@name='validation_min_datetime']" position="attributes">
<attribute name="attrs">
{'invisible': ['|', '|', ('question_type', '!=', 'datetime'), ('validation_required', '=', False), ('validation_min_datetime_option', '!=', False)]}
</attribute>
</xpath>
<xpath expr="//field[@name='validation_max_datetime']" position="after">
<field
name="validation_max_datetime_option"
string="'Datetime maximum' option"
attrs="{'invisible': ['|', ('question_type', '!=', 'datetime'), ('validation_required', '=', False)]}"
/>
<field
name="validation_min_multiple_choice_option"
string="Multiple choice min"
attrs="{'invisible': ['|', ('question_type', '!=', 'multiple_choice'), ('validation_required', '=', False)]}"
/>
<field
name="validation_max_multiple_choice_option"
string="Multiple choice max"
attrs="{'invisible': ['|', ('question_type', '!=', 'multiple_choice'), ('validation_required', '=', False)]}"
/>
</xpath>
<xpath expr="//field[@name='validation_max_datetime']" position="attributes">
<attribute name="attrs">
{'invisible': ['|', '|', ('question_type', '!=', 'datetime'), ('validation_required', '=', False), ('validation_max_datetime_option', '!=', False)]}
</attribute>
</xpath>
</field>
</record>
</data>
</odoo>
6 changes: 6 additions & 0 deletions setup/survey_condition_validation_option/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
Loading

0 comments on commit 24e0f8d

Please sign in to comment.