From 4d1eaebc06c44feec53219187673e30c5048847e Mon Sep 17 00:00:00 2001 From: luis Date: Mon, 22 Sep 2025 12:47:58 +0200 Subject: [PATCH] add survey_score_ranges: displays different messages depending on the score obtained, allowing different score ranges --- survey_score_ranges/__init__.py | 1 + survey_score_ranges/__manifest__.py | 19 +++++ survey_score_ranges/models/__init__.py | 3 + .../models/survey_score_range.py | 75 +++++++++++++++++++ survey_score_ranges/models/survey_survey.py | 13 ++++ .../models/survey_user_input.py | 50 +++++++++++++ .../security/ir.model.access.csv | 2 + .../views/survey_score_range_views.xml | 50 +++++++++++++ .../views/survey_survey_views.xml | 42 +++++++++++ .../views/survey_templates.xml | 13 ++++ website_partner_directory/__manifest__.py | 2 +- 11 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 survey_score_ranges/__init__.py create mode 100644 survey_score_ranges/__manifest__.py create mode 100644 survey_score_ranges/models/__init__.py create mode 100644 survey_score_ranges/models/survey_score_range.py create mode 100644 survey_score_ranges/models/survey_survey.py create mode 100644 survey_score_ranges/models/survey_user_input.py create mode 100644 survey_score_ranges/security/ir.model.access.csv create mode 100644 survey_score_ranges/views/survey_score_range_views.xml create mode 100644 survey_score_ranges/views/survey_survey_views.xml create mode 100644 survey_score_ranges/views/survey_templates.xml diff --git a/survey_score_ranges/__init__.py b/survey_score_ranges/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/survey_score_ranges/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/survey_score_ranges/__manifest__.py b/survey_score_ranges/__manifest__.py new file mode 100644 index 0000000..51eb4e9 --- /dev/null +++ b/survey_score_ranges/__manifest__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +{ + "name": "Survey Score Ranges", + "version": "17.0.1.0.0", + "summary": "Rangos de puntuación para encuestas", + "category": "Survey", + "author": "Criptomart", + "website": "https://criptomart.net", + "license": "LGPL-3", + "depends": ["survey", "website"], + "data": [ + "security/ir.model.access.csv", + "views/survey_score_range_views.xml", + "views/survey_survey_views.xml", + "views/survey_templates.xml", + ], + "installable": True, + "application": False, +} diff --git a/survey_score_ranges/models/__init__.py b/survey_score_ranges/models/__init__.py new file mode 100644 index 0000000..5aa973b --- /dev/null +++ b/survey_score_ranges/models/__init__.py @@ -0,0 +1,3 @@ +from . import survey_score_range +from . import survey_survey +from . import survey_user_input diff --git a/survey_score_ranges/models/survey_score_range.py b/survey_score_ranges/models/survey_score_range.py new file mode 100644 index 0000000..d1a3e6c --- /dev/null +++ b/survey_score_ranges/models/survey_score_range.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError + + +class SurveyScoreRange(models.Model): + _name = "survey.score.range" + _description = "Survey Score Range" + _order = "survey_id, min_score, max_score, id" + + name = fields.Char("Name", required=True, translate=True) + survey_id = fields.Many2one( + "survey.survey", string="Survey", required=True, ondelete="cascade", index=True + ) + min_score = fields.Float("Min Score", required=True, help="Inclusive lower bound") + max_score = fields.Float( + "Max Score", + required=True, + help="Inclusive upper bound (use same value as min for exact match). Deje vacío para indicar sin límite superior.", + default=0.0, + ) + no_upper_limit = fields.Boolean( + "No upper limit", + help="If checked, max_score is ignored and the range is open-ended ( >= min_score ).", + ) + result_html = fields.Html( + "Result Content", translate=True, sanitize=True, sanitize_overridable=True + ) + active = fields.Boolean(default=True) + + _sql_constraints = [ + ( + "min_le_max", + "CHECK( min_score <= max_score )", + "El mínimo debe ser menor o igual que el máximo.", + ) + ] + + @api.constrains("min_score", "max_score", "no_upper_limit", "survey_id", "active") + def _check_overlapping(self): + for rec in self: + if rec.no_upper_limit: + domain = [ + ("id", "!=", rec.id), + ("survey_id", "=", rec.survey_id.id), + ("active", "=", True), + "|", + ("no_upper_limit", "=", True), + ("max_score", ">=", rec.min_score), + ] + else: + domain = [ + ("id", "!=", rec.id), + ("survey_id", "=", rec.survey_id.id), + ("active", "=", True), + ("min_score", "<=", rec.max_score), + "|", + ("no_upper_limit", "=", True), + ("max_score", ">=", rec.min_score), + ] + overlaps = self.search_count(domain) + if overlaps: + raise ValidationError( + _("Los rangos de puntuación no pueden solaparse.") + ) + + def name_get(self): + res = [] + for r in self: + if r.no_upper_limit: + label = _("%s (%s+ pts)") % (r.name, r.min_score) + else: + label = _("%s (%s-%s pts)") % (r.name, r.min_score, r.max_score) + res.append((r.id, label)) + return res diff --git a/survey_score_ranges/models/survey_survey.py b/survey_score_ranges/models/survey_survey.py new file mode 100644 index 0000000..6b9e8ca --- /dev/null +++ b/survey_score_ranges/models/survey_survey.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +from odoo import models, fields + + +class SurveySurvey(models.Model): + _inherit = "survey.survey" + + enable_score_ranges = fields.Boolean( + "Enable Score Ranges", help="Show a result page based on score ranges." + ) + score_range_ids = fields.One2many( + "survey.score.range", "survey_id", string="Score Ranges" + ) diff --git a/survey_score_ranges/models/survey_user_input.py b/survey_score_ranges/models/survey_user_input.py new file mode 100644 index 0000000..f4afb7a --- /dev/null +++ b/survey_score_ranges/models/survey_user_input.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +from odoo import models, fields, api + + +class SurveyUserInput(models.Model): + _inherit = "survey.user_input" + + result_range_id = fields.Many2one( + "survey.score.range", + string="Score Range", + compute="_compute_result_range_id", + store=True, + compute_sudo=True, + ) + result_range_html = fields.Html( + string="Result Range Content", + compute="_compute_result_range_html", + sanitize=False, + ) + + @api.depends( + "scoring_total", "survey_id.enable_score_ranges", "survey_id.score_range_ids" + ) + def _compute_result_range_id(self): + for user_input in self: + selected = False + if user_input.survey_id.enable_score_ranges and user_input.state == "done": + total = user_input.scoring_total + ranges = user_input.survey_id.score_range_ids.filtered("active").sorted( + lambda r: r.min_score + ) + for r in ranges: + if r.no_upper_limit: + if total >= r.min_score: + selected = r + else: + if total >= r.min_score and total <= r.max_score: + selected = r + if selected: + break + user_input.result_range_id = selected + + @api.depends("result_range_id") + def _compute_result_range_html(self): + for user_input in self: + user_input.result_range_html = ( + user_input.result_range_id.result_html + if user_input.result_range_id + else False + ) diff --git a/survey_score_ranges/security/ir.model.access.csv b/survey_score_ranges/security/ir.model.access.csv new file mode 100644 index 0000000..fcece7b --- /dev/null +++ b/survey_score_ranges/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_survey_score_range_user,survey.score.range user,model_survey_score_range,survey.group_survey_manager,1,1,1,1 diff --git a/survey_score_ranges/views/survey_score_range_views.xml b/survey_score_ranges/views/survey_score_range_views.xml new file mode 100644 index 0000000..c4e0af0 --- /dev/null +++ b/survey_score_ranges/views/survey_score_range_views.xml @@ -0,0 +1,50 @@ + + + + survey.score.range.tree + survey.score.range + + + + + + + + + + + + + + survey.score.range.form + survey.score.range + +
+ + + + + + + + + + + + + + + +
+
+
+ + + Score Ranges + survey.score.range + tree,form + {} + + + +
diff --git a/survey_score_ranges/views/survey_survey_views.xml b/survey_score_ranges/views/survey_survey_views.xml new file mode 100644 index 0000000..c82ec5b --- /dev/null +++ b/survey_score_ranges/views/survey_survey_views.xml @@ -0,0 +1,42 @@ + + + + survey.survey.form.score.ranges + survey.survey + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/survey_score_ranges/views/survey_templates.xml b/survey_score_ranges/views/survey_templates.xml new file mode 100644 index 0000000..72795e8 --- /dev/null +++ b/survey_score_ranges/views/survey_templates.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/website_partner_directory/__manifest__.py b/website_partner_directory/__manifest__.py index e539065..64ad2ea 100644 --- a/website_partner_directory/__manifest__.py +++ b/website_partner_directory/__manifest__.py @@ -3,7 +3,7 @@ "version": "17.0.1.0.0", "summary": "Directorio de empresas en website con mapa Leaflet", "category": "Website", - "author": "Luis", + "author": "Criptomart", "depends": ["website_partner", "base_geolocalize"], "data": ["views/res_partner_views.xml", "views/directory_template.xml"], "assets": {