Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions setup/survey_prefilled_answer/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,
)
122 changes: 122 additions & 0 deletions survey_prefilled_answer/README.rst
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/OCA/survey/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 <https://github.com/OCA/survey/issues/new?body=module:%20survey_prefilled_answer%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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

Credits
=======

Authors
-------

* Kencove

Contributors
------------

- `Kencove <https://kencove.com>`__:

- 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 <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-Kencove|

This module is part of the `OCA/survey <https://github.com/OCA/survey/tree/16.0/survey_prefilled_answer>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
5 changes: 5 additions & 0 deletions survey_prefilled_answer/__init__.py
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions survey_prefilled_answer/__manifest__.py
Original file line number Diff line number Diff line change
@@ -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,
}
4 changes: 4 additions & 0 deletions survey_prefilled_answer/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -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
110 changes: 110 additions & 0 deletions survey_prefilled_answer/controllers/main.py
Original file line number Diff line number Diff line change
@@ -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/<string:survey_token>",
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 <answer_token> is set, it will
grab the answers of the user_input_id that has <answer_token>."""
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,
},
)
5 changes: 5 additions & 0 deletions survey_prefilled_answer/models/__init__.py
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions survey_prefilled_answer/models/survey_question.py
Original file line number Diff line number Diff line change
@@ -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()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you put only one field with different widget according the type of the answer?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wil try

56 changes: 56 additions & 0 deletions survey_prefilled_answer/models/survey_user_input.py
Original file line number Diff line number Diff line change
@@ -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")
2 changes: 2 additions & 0 deletions survey_prefilled_answer/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- [Kencove](https://kencove.com):
- Mohamed Alkobrosli
4 changes: 4 additions & 0 deletions survey_prefilled_answer/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -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.

18 changes: 18 additions & 0 deletions survey_prefilled_answer/readme/USAGE.md
Original file line number Diff line number Diff line change
@@ -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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading