diff --git a/setup/survey_prefilled_answer/odoo/addons/survey_prefilled_answer b/setup/survey_prefilled_answer/odoo/addons/survey_prefilled_answer new file mode 120000 index 00000000..db9b22b9 --- /dev/null +++ b/setup/survey_prefilled_answer/odoo/addons/survey_prefilled_answer @@ -0,0 +1 @@ +../../../../survey_prefilled_answer \ No newline at end of file diff --git a/setup/survey_prefilled_answer/setup.py b/setup/survey_prefilled_answer/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/survey_prefilled_answer/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/survey_prefilled_answer/README.rst b/survey_prefilled_answer/README.rst new file mode 100644 index 00000000..95c2dd19 --- /dev/null +++ b/survey_prefilled_answer/README.rst @@ -0,0 +1,122 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +========================= +Survey Prefilled Answeres +========================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:77246d7bd6c9b0ba8ec58d79fe03411e6978e035959dd475f53c7b9c308ebe21 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsurvey-lightgray.png?logo=github + :target: https://github.com/OCA/survey/tree/16.0/survey_prefilled_answer + :alt: OCA/survey +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/survey-16-0/survey-16-0-survey_prefilled_answer + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/survey&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module is used to add a dynamic answer for the questions like +email, phone number, etc.. + +If the answer can be a field value for the partner (survey participant) +then this module can be used. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use the module with single select or multi-select answers: +------------------------------------------------------------- + +:: + + - go to survey app > create a template + - create a question of type single select or multi-select + - add a selective answer and write the answer including the field value like: + + - "My name is {{object.name}}" or just {{object.name}} + +To use the module with text or multi-text answers: +-------------------------------------------------- + +:: + + - go to survey app > create a template + - create a question of type single text or multi-text + - go to options tab > add a value to suggested_prefilled_answer or suggested_prefilled_answer_multi + - The dynamic prefilled answer can be like "My name is {{object.name}}" or just {{object.name}} + - For multi-text answer you can add answer in muti-lines text + +Survey participant can still modify the prefilled answers the way they +like during the survey. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Kencove + +Contributors +------------ + +- `Kencove `__: + + - Mohamed Alkobrosli + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-Kencove| image:: https://github.com/Kencove.png?size=40px + :target: https://github.com/Kencove + :alt: Kencove + +Current `maintainer `__: + +|maintainer-Kencove| + +This module is part of the `OCA/survey `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/survey_prefilled_answer/__init__.py b/survey_prefilled_answer/__init__.py new file mode 100644 index 00000000..fadb30e6 --- /dev/null +++ b/survey_prefilled_answer/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import models +from . import controllers diff --git a/survey_prefilled_answer/__manifest__.py b/survey_prefilled_answer/__manifest__.py new file mode 100644 index 00000000..0cb2e5e7 --- /dev/null +++ b/survey_prefilled_answer/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "Survey Prefilled Answeres", + "summary": "Prefill answers with partner's fields values", + "category": "Marketing", + "version": "16.0.1.0.0", + "depends": ["contacts", "survey", "mail"], + "data": [ + "views/survey_templates.xml", + "views/survey_question_views.xml", + ], + "author": "Kencove, Odoo Community Association (OCA)", + "maintainers": ["Kencove"], + "website": "https://github.com/OCA/survey", + "license": "AGPL-3", + "installable": True, +} diff --git a/survey_prefilled_answer/controllers/__init__.py b/survey_prefilled_answer/controllers/__init__.py new file mode 100644 index 00000000..3840f4cf --- /dev/null +++ b/survey_prefilled_answer/controllers/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import main diff --git a/survey_prefilled_answer/controllers/main.py b/survey_prefilled_answer/controllers/main.py new file mode 100644 index 00000000..86526d01 --- /dev/null +++ b/survey_prefilled_answer/controllers/main.py @@ -0,0 +1,110 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from collections import OrderedDict + +from odoo import http +from odoo.http import request +from odoo.tools import format_date, format_datetime, is_html_empty + +from odoo.addons.survey.controllers.main import Survey + + +class CustomSurvey(Survey): + def render_value(self, value): + if value: + partner = request.env.user.partner_id + render_env = request.env["mail.render.mixin"].sudo() + try: + rendered_answer = render_env._render_template( + value, partner._name, [partner.id] + )[partner.id] + return rendered_answer or False + except Exception as e: + # handel ValueError raised for NameError or AttributeError + error_msg = str(e).lower() + if "nameerror" in error_msg or "attributeerror" in error_msg: + return False + else: + raise + return False + + def get_prefilled_answers(self, questions): + # require participants to be logged in to make sure thier own field values be filled in + # and not the public user field values + prefilled_answers = OrderedDict() + for question in questions or []: + if question.question_type in ( + "simple_choice", + "multiple_choice", + ): + suggested_answer_ids = question.suggested_answer_ids + for suggested_answer_id in suggested_answer_ids: + suggested_answer_value = suggested_answer_id.value + rendered_answer = self.render_value(suggested_answer_value) + if rendered_answer: + prefilled_answers[suggested_answer_id] = rendered_answer + elif question.question_type == "char_box": + suggested_answer_value = question.suggested_prefilled_answer + rendered_answer = self.render_value(suggested_answer_value) + if rendered_answer: + prefilled_answers[question] = rendered_answer + elif question.question_type == "text_box": + suggested_answer_value = question.suggested_prefilled_answer_multi + rendered_answer = self.render_value(suggested_answer_value) + if rendered_answer: + prefilled_answers[question] = rendered_answer + return prefilled_answers + + def _prepare_survey_data(self, survey_sudo, answer_sudo, **post): + data = super()._prepare_survey_data(survey_sudo, answer_sudo, **post) + # if survey_sudo.users_login_required: # we ignore this line but not sure yet + questions = survey_sudo.question_ids + data["prefilled_answers"] = self.get_prefilled_answers(questions) + return data + + @http.route( + "/survey/print/", + type="http", + auth="public", + website=True, + sitemap=False, + ) + def survey_print(self, survey_token, review=False, answer_token=None, **post): + """Display an survey in printable view; if is set, it will + grab the answers of the user_input_id that has .""" + access_data = self._get_access_data( + survey_token, answer_token, ensure_token=False, check_partner=False + ) + if access_data["validity_code"] is not True and ( + access_data["has_survey_access"] + or access_data["validity_code"] + not in ["token_required", "survey_closed", "survey_void", "answer_deadline"] + ): + return self._redirect_with_error(access_data, access_data["validity_code"]) + survey_sudo, answer_sudo = ( + access_data["survey_sudo"], + access_data["answer_sudo"], + ) + questions = answer_sudo._get_print_questions() + prefilled_answers = self.get_prefilled_answers(questions) + return request.render( + "survey.survey_page_print", + { + "is_html_empty": is_html_empty, + "review": review, + "survey": survey_sudo, + "answer": answer_sudo + if survey_sudo.scoring_type != "scoring_without_answers" + else answer_sudo.browse(), + "questions_to_display": answer_sudo._get_print_questions(), + "scoring_display_correction": survey_sudo.scoring_type + == "scoring_with_answers" + and answer_sudo, + "format_datetime": lambda dt: format_datetime( + request.env, dt, dt_format=False + ), + "format_date": lambda date: format_date(request.env, date), + "prefilled_answers": prefilled_answers, + }, + ) diff --git a/survey_prefilled_answer/models/__init__.py b/survey_prefilled_answer/models/__init__.py new file mode 100644 index 00000000..a97b63e1 --- /dev/null +++ b/survey_prefilled_answer/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import survey_user_input +from . import survey_question diff --git a/survey_prefilled_answer/models/survey_question.py b/survey_prefilled_answer/models/survey_question.py new file mode 100644 index 00000000..a96b937b --- /dev/null +++ b/survey_prefilled_answer/models/survey_question.py @@ -0,0 +1,12 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + + +from odoo import fields, models + + +class SurveyQuestion(models.Model): + _inherit = "survey.question" + + suggested_prefilled_answer = fields.Char() + suggested_prefilled_answer_multi = fields.Text() diff --git a/survey_prefilled_answer/models/survey_user_input.py b/survey_prefilled_answer/models/survey_user_input.py new file mode 100644 index 00000000..2e4adcdc --- /dev/null +++ b/survey_prefilled_answer/models/survey_user_input.py @@ -0,0 +1,56 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import textwrap + +from odoo import _, api, fields, models + + +class SurveyUserInputLine(models.Model): + _inherit = "survey.user_input.line" + + def render_answer(self, suggested_answer_id): + partner = self.user_input_id.partner_id + suggested_answer_value = suggested_answer_id.value + render_env = self.env["mail.render.mixin"].sudo() + try: + rendered_answer = render_env._render_template( + suggested_answer_value, partner._name, [partner.id] + )[partner.id] + return rendered_answer or False + except Exception as e: + # handel ValueError raised for NameError or AttributeError + error_msg = str(e).lower() + if "nameerror" in error_msg or "attributeerror" in error_msg: + return False + else: + raise + + @api.depends("answer_type") + def _compute_display_name(self): + for line in self: + if line.answer_type == "char_box": + line.display_name = line.value_char_box + elif line.answer_type == "text_box" and line.value_text_box: + line.display_name = textwrap.shorten( + line.value_text_box, width=50, placeholder=" [...]" + ) + elif line.answer_type == "numerical_box": + line.display_name = line.value_numerical_box + elif line.answer_type == "date": + line.display_name = fields.Date.to_string(line.value_date) + elif line.answer_type == "datetime": + line.display_name = fields.Datetime.to_string(line.value_datetime) + elif line.answer_type == "suggestion": + rendered_answer = self.render_answer(line.suggested_answer_id) + if line.matrix_row_id: + line.display_name = "%s: %s" % ( + line.suggested_answer_id.value, + line.matrix_row_id.value, + ) + else: + line.display_name = ( + rendered_answer or line.suggested_answer_id.value + ) + if not line.display_name: + line.display_name = _("Skipped") diff --git a/survey_prefilled_answer/readme/CONTRIBUTORS.md b/survey_prefilled_answer/readme/CONTRIBUTORS.md new file mode 100644 index 00000000..6f39b50e --- /dev/null +++ b/survey_prefilled_answer/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [Kencove](https://kencove.com): + - Mohamed Alkobrosli diff --git a/survey_prefilled_answer/readme/DESCRIPTION.md b/survey_prefilled_answer/readme/DESCRIPTION.md new file mode 100644 index 00000000..3b83375b --- /dev/null +++ b/survey_prefilled_answer/readme/DESCRIPTION.md @@ -0,0 +1,4 @@ +This module is used to add a dynamic answer for the questions like email, phone number, etc.. + +If the answer can be a field value for the partner (survey participant) then this module can be used. + diff --git a/survey_prefilled_answer/readme/USAGE.md b/survey_prefilled_answer/readme/USAGE.md new file mode 100644 index 00000000..3adf553c --- /dev/null +++ b/survey_prefilled_answer/readme/USAGE.md @@ -0,0 +1,18 @@ +## To use the module with single select or multi-select answers: + + - go to survey app > create a template + - create a question of type single select or multi-select + - add a selective answer and write the answer including the field value like: + + - "My name is {{object.name}}" or just {{object.name}} + +## To use the module with text or multi-text answers: + + - go to survey app > create a template + - create a question of type single text or multi-text + - go to options tab > add a value to suggested_prefilled_answer or suggested_prefilled_answer_multi + - The dynamic prefilled answer can be like "My name is {{object.name}}" or just {{object.name}} + - For multi-text answer you can add answer in muti-lines text + +Survey participant can still modify the prefilled answers the way they like during the +survey. diff --git a/survey_prefilled_answer/static/description/icon.png b/survey_prefilled_answer/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/survey_prefilled_answer/static/description/icon.png differ diff --git a/survey_prefilled_answer/static/description/index.html b/survey_prefilled_answer/static/description/index.html new file mode 100644 index 00000000..d1af1d6c --- /dev/null +++ b/survey_prefilled_answer/static/description/index.html @@ -0,0 +1,467 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Survey Prefilled Answeres

+ +

Beta License: AGPL-3 OCA/survey Translate me on Weblate Try me on Runboat

+

This module is used to add a dynamic answer for the questions like +email, phone number, etc..

+

If the answer can be a field value for the partner (survey participant) +then this module can be used.

+

Table of contents

+ +
+

Usage

+
+

To use the module with single select or multi-select answers:

+
+- go to survey app > create a template
+- create a question of type single select or multi-select
+- add a selective answer and write the answer including the field value like:
+
+    - "My name is {{object.name}}" or just {{object.name}}
+
+
+
+

To use the module with text or multi-text answers:

+
+- go to survey app > create a template
+- create a question of type single text or multi-text
+- go to options tab > add a value to suggested_prefilled_answer or suggested_prefilled_answer_multi
+- The dynamic prefilled answer can be like "My name is {{object.name}}" or just {{object.name}}
+- For multi-text answer you can add answer in muti-lines text
+
+

Survey participant can still modify the prefilled answers the way they +like during the survey.

+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Kencove
  • +
+
+
+

Contributors

+
    +
  • Kencove:
      +
    • Mohamed Alkobrosli
    • +
    +
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

Kencove

+

This module is part of the OCA/survey project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/survey_prefilled_answer/views/survey_question_views.xml b/survey_prefilled_answer/views/survey_question_views.xml new file mode 100644 index 00000000..8e581aed --- /dev/null +++ b/survey_prefilled_answer/views/survey_question_views.xml @@ -0,0 +1,20 @@ + + + + Custom form view for survey question + survey.question + + + + + + + + + diff --git a/survey_prefilled_answer/views/survey_templates.xml b/survey_prefilled_answer/views/survey_templates.xml new file mode 100644 index 00000000..84b12484 --- /dev/null +++ b/survey_prefilled_answer/views/survey_templates.xml @@ -0,0 +1,54 @@ + + + + + + + + + +