diff --git a/.eslintrc.yml b/.eslintrc.yml index fed88d70..1e64063c 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -4,7 +4,7 @@ env: # See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 parserOptions: - ecmaVersion: 2019 + ecmaVersion: 2021 overrides: - files: diff --git a/setup/survey_sign_oca/odoo/addons/survey_sign_oca b/setup/survey_sign_oca/odoo/addons/survey_sign_oca new file mode 120000 index 00000000..9418f635 --- /dev/null +++ b/setup/survey_sign_oca/odoo/addons/survey_sign_oca @@ -0,0 +1 @@ +../../../../survey_sign_oca \ No newline at end of file diff --git a/setup/survey_sign_oca/setup.py b/setup/survey_sign_oca/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/survey_sign_oca/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/survey_sign_oca/README.rst b/survey_sign_oca/README.rst new file mode 100644 index 00000000..098879e8 --- /dev/null +++ b/survey_sign_oca/README.rst @@ -0,0 +1,174 @@ +=============== +Survey Sign Oca +=============== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:c6ec61a6c8661f9097946736d2cd67efc929e1531803516fa6d82728aab2c98a + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/licence-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%2Fsign-lightgray.png?logo=github + :target: https://github.com/OCA/sign/tree/16.0/survey_sign_oca + :alt: OCA/sign +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/sign-16-0/sign-16-0-survey_sign_oca + :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/sign&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows you to make survey signature requests manually or +automatically. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +1. Go to Sign > Settings > Roles and create a new one with the following + data if not there: + + - For the survey participant + + - Partner type: Expression + - Expression: {{object.partner_id.id}} + + - For the survey responsible if you want + + - Partner type: Expression + - Expression: {{object.survey_id.user_id.partner_id.id}} + +2. Go to Sign > Settings > Fields and create a new one with the + following data if not there: + + - Text Survey Field + + - Field Type: text + - Default Value: survey + + - Check Survey Field + + - Field Type: check + - Default Value: survey + + - Signature Survey Field + + - Field Type: signature + - Default Value: survey + +3. Go to Sign > Templates and create a template with the following data: + + - Model: Survey User Input + - In some of the elements you will have to set the previously created + role[s]. + +4. Go to Settings > Survey Sign OCA: + +5. Defines the template previously created (optional, only for automatic + creation of signature requests). + +Usage +===== + +A smart-button will be displayed on the participations form view of the +linked sign requests. + +Manual Sign Request creation process: + +:: + + - Go to Surveys \> Participations and change to list view. + - Select the records that you want. + - Click on the "Sign from template" action. + - Select a template. + - Click on Generate. + - Sign Requests will have been generated (and sent) for the selected items. + +Automatic Sign Request creation process: + +:: + + - When a partner takes a survey, a sign request will be created automatically. + +For generated sign requests scoping survey, input values are populated +automatically with the survey answered values. + +Answers for multiple choice questions are displayed as a sequence if you +add the question in placeholder. If you suffix the question in +placeholder with specific answer then it will be displayed or checked if +it is the answer. + +Answers of yes/no type are shown in text fields as Yes/No and in check +fields as checked/unchecked. + +Answers of type binary can be trated as signature fields if the survey +question is the same as the signature placeholder in sign request. + +In that case make sure to have this module: +``survey_question_type_binary`` from OCA installed. + +Signers can still update the input values if they want. + +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/sign `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/survey_sign_oca/__init__.py b/survey_sign_oca/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/survey_sign_oca/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/survey_sign_oca/__manifest__.py b/survey_sign_oca/__manifest__.py new file mode 100644 index 00000000..7bb85a3a --- /dev/null +++ b/survey_sign_oca/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Survey Sign Oca", + "version": "16.0.1.0.0", + "category": "Surveys", + "website": "https://github.com/OCA/sign", + "author": "Kencove, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["sign_oca", "survey"], + "data": [ + "views/survey_user_views.xml", + "views/res_config_settings_view.xml", + "views/sign_oca_request_views.xml", + "data/sign_oca_role.xml", + ], + "installable": True, + "maintainers": ["Kencove"], +} diff --git a/survey_sign_oca/data/sign_oca_role.xml b/survey_sign_oca/data/sign_oca_role.xml new file mode 100644 index 00000000..6b1dd03b --- /dev/null +++ b/survey_sign_oca/data/sign_oca_role.xml @@ -0,0 +1,33 @@ + + + Survey Text + text + survey + + + + Survey Check + check + survey + + + + Survey Signature + signature + survey + + + + Survey Participant + expression + {{object.partner_id.id}} + + + + Survey Responsible + expression + {{object.survey_id.user_id.partner_id.id}} + + diff --git a/survey_sign_oca/models/__init__.py b/survey_sign_oca/models/__init__.py new file mode 100644 index 00000000..1d665615 --- /dev/null +++ b/survey_sign_oca/models/__init__.py @@ -0,0 +1,4 @@ +from . import survey_invite +from . import res_company +from . import res_config_settings +from . import sign_oca_request diff --git a/survey_sign_oca/models/res_company.py b/survey_sign_oca/models/res_company.py new file mode 100644 index 00000000..534fc9dd --- /dev/null +++ b/survey_sign_oca/models/res_company.py @@ -0,0 +1,14 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + survey_user_input_sign_oca_template_id = fields.Many2one( + comodel_name="sign.oca.template", + domain="[('model_id.model', '=', 'survey.user_input')]", + string="Sign Oca Template", + ) diff --git a/survey_sign_oca/models/res_config_settings.py b/survey_sign_oca/models/res_config_settings.py new file mode 100644 index 00000000..e50fa838 --- /dev/null +++ b/survey_sign_oca/models/res_config_settings.py @@ -0,0 +1,15 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + survey_user_input_sign_oca_template_id = fields.Many2one( + comodel_name="sign.oca.template", + related="company_id.survey_user_input_sign_oca_template_id", + string="Sign Oca Template", + readonly=False, + ) diff --git a/survey_sign_oca/models/sign_oca_request.py b/survey_sign_oca/models/sign_oca_request.py new file mode 100644 index 00000000..eff50921 --- /dev/null +++ b/survey_sign_oca/models/sign_oca_request.py @@ -0,0 +1,109 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from collections import defaultdict + +from odoo import api, fields, models + + +# This class is to format questions of type (yes, no) +# in case we need the answer as (True, False) in case of filling checkboxes +class SurveyUtils: + @staticmethod + def is_yes_no_answer(value): + return str(value).strip().lower() in ["yes", "no"] + + @staticmethod + def answer_is_yes(value): + return str(value).strip().lower() == "yes" + + @staticmethod + def format_answer(answer): + if SurveyUtils.is_yes_no_answer(answer): + answer = SurveyUtils.answer_is_yes(answer) + return answer + + +class SignOcaRequest(models.Model): + _inherit = "sign.oca.request" + + # This field is required for the inverse of survey.user.input. + survey_user_input_id = fields.Many2one( + comodel_name="survey.user_input", + compute="_compute_survey_user_input_id", + string="Survey Participation", + readonly=True, + store=True, + ondelete="cascade", + ) + + @api.depends("record_ref") + def _compute_survey_user_input_id(self): + for item in self.filtered( + lambda x: x.record_ref and x.record_ref._name == "survey.user_input" + ): + item.survey_user_input_id = item.record_ref.id + + +class SignOcaRequestSigner(models.Model): + + _inherit = "sign.oca.request.signer" + + def get_related_survey_answers(self): + self.ensure_one() + survey_participation = self.request_id.record_ref + survey = {} + answers_list = [] + if survey_participation: + for line in survey_participation.user_input_line_ids: + # Questions of type matrix have questions and suggested answers like a matrix + # We map the answeres to the questions for each matrix type + if line.question_id.question_type == "matrix": + answer = line.suggested_answer_id.value + survey.update({line.matrix_row_id.value: answer}) + elif line.question_id.question_type in ["binary", "signature"]: + answer = line.answer_binary_ids[:1].value_binary + survey.update({line.question_id.display_name: answer}) + elif line.question_id.question_type == "multiple_choice": + answer = line.display_name + answers_list.append([line.question_id.display_name, answer]) + survey.update( + {f"{line.question_id.display_name}, {answer}": answer} + ) + else: + answer = line.display_name + survey.update({line.question_id.display_name: answer}) + # Map answers for the same questions + mapped_answers = defaultdict(list) + for question, answer in answers_list: + mapped_answers[question].append(answer) + survey.update(dict(mapped_answers)) + return survey + + def fill_survey_related_items(self, vals): + survey = self.get_related_survey_answers() + items = vals["items"] + for key in items: + item = items[key] + placeholder = item.get("placeholder") + # According to placeholder we target the answer of a question + # having same text as the placeholder + # and we choose the answer format based on the item field_typ + if survey.get(placeholder) and item["role_id"] == self.role_id.id: + if survey.get(placeholder) and item["field_type"] == "text": + item["value"] = survey.get(placeholder) + elif survey.get(placeholder) and item["field_type"] == "check": + item["value"] = SurveyUtils.format_answer(survey.get(placeholder)) + elif survey.get(placeholder) and item["field_type"] == "signature": + item["value"] = survey.get(placeholder) + if item.get("default_value") and item.get("default_value") != "survey": + item["value"] = vals.get("partner").get(item["default_value"]) + return vals + + def get_info(self, access_token=False): + vals = super().get_info(access_token) + # get survey answers for this sign request + # and fill items with answers / default values + model_id = self.request_id.template_id.model_id + if model_id and model_id.model == "survey.user_input": + vals = self.fill_survey_related_items(vals) + return vals diff --git a/survey_sign_oca/models/survey_invite.py b/survey_sign_oca/models/survey_invite.py new file mode 100644 index 00000000..febb82eb --- /dev/null +++ b/survey_sign_oca/models/survey_invite.py @@ -0,0 +1,73 @@ +# Copyright 2025 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import api, fields, models + + +class SurveyUserInput(models.Model): + _inherit = "survey.user_input" + + # This field is stored as a help to filter by. + sign_request_ids = fields.One2many( + comodel_name="sign.oca.request", + inverse_name="survey_user_input_id", + string="Sign Requests", + ) + sign_request_count = fields.Integer( + string="Sign request count", + compute="_compute_sign_request_count", + compute_sudo=True, + store=True, + ) + + @api.depends("sign_request_ids") + def _compute_sign_request_count(self): + request_data = self.env["sign.oca.request"].read_group( + [("survey_user_input_id", "in", self.ids)], + ["survey_user_input_id"], + ["survey_user_input_id"], + ) + mapped_data = { + x["survey_user_input_id"][0]: x["survey_user_input_id_count"] + for x in request_data + } + for item in self: + item.sign_request_count = mapped_data.get(item.id, 0) + + def action_view_sign_requests(self): + self.ensure_one() + result = self.env["ir.actions.act_window"]._for_xml_id( + "sign_oca.sign_oca_request_act_window" + ) + result["domain"] = [("id", "in", self.sign_request_ids.ids)] + ctx = dict(self.env.context) + ctx.update( + { + "default_survey_user_input_id": self.id, + "search_default_survey_user_input_id": self.id, + } + ) + result["context"] = ctx + return result + + def _process_generate_sign_oca_request(self, data): + """Generate request from template if owner has changed.""" + request_model = self.env["sign.oca.request"].sudo() + for item in self.filtered("partner_id"): + sign_template = ( + item.survey_id.user_id.company_id.survey_user_input_sign_oca_template_id + ) + old_partner_id = data[item.id] if item.id in data else False + if sign_template and item.partner_id != old_partner_id: + # Apply sudo because the user who creates the record may not have + # permissions on sign.oca.template + sign_template = sign_template.sudo() + request_model.create( + sign_template._prepare_sign_oca_request_vals_from_record(item) + ) + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + if any(item.partner_id for item in res): + res._process_generate_sign_oca_request({}) + return res diff --git a/survey_sign_oca/readme/CONFIGURE.md b/survey_sign_oca/readme/CONFIGURE.md new file mode 100644 index 00000000..49faa479 --- /dev/null +++ b/survey_sign_oca/readme/CONFIGURE.md @@ -0,0 +1,40 @@ +1. Go to Sign \> Settings \> Roles and create a new one with the following data if not + there: + + - For the survey participant + + - Partner type: Expression + - Expression: {{object.partner_id.id}} + + - For the survey responsible if you want + + - Partner type: Expression + - Expression: {{object.survey_id.user_id.partner_id.id}} + +2. Go to Sign \> Settings \> Fields and create a new one with the following data if not + there: + + - Text Survey Field + + - Field Type: text + - Default Value: survey + + - Check Survey Field + + - Field Type: check + - Default Value: survey + + - Signature Survey Field + + - Field Type: signature + - Default Value: survey + +3. Go to Sign \> Templates and create a template with the following data: + + - Model: Survey User Input + - In some of the elements you will have to set the previously created role[s]. + +4. Go to Settings \> Survey Sign OCA: + +5. Defines the template previously created (optional, only for automatic creation of + signature requests). diff --git a/survey_sign_oca/readme/CONTRIBUTORS.md b/survey_sign_oca/readme/CONTRIBUTORS.md new file mode 100644 index 00000000..bbd23bec --- /dev/null +++ b/survey_sign_oca/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [Kencove](https://kencove.com) + - Mohamed Alkobrosli diff --git a/survey_sign_oca/readme/DESCRIPTION.md b/survey_sign_oca/readme/DESCRIPTION.md new file mode 100644 index 00000000..f58c4007 --- /dev/null +++ b/survey_sign_oca/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +This module allows you to make survey signature requests manually or +automatically. diff --git a/survey_sign_oca/readme/USAGE.md b/survey_sign_oca/readme/USAGE.md new file mode 100644 index 00000000..00f42928 --- /dev/null +++ b/survey_sign_oca/readme/USAGE.md @@ -0,0 +1,32 @@ +A smart-button will be displayed on the participations form view of the linked sign +requests. + +Manual Sign Request creation process: + + - Go to Surveys \> Participations and change to list view. + - Select the records that you want. + - Click on the "Sign from template" action. + - Select a template. + - Click on Generate. + - Sign Requests will have been generated (and sent) for the selected items. + +Automatic Sign Request creation process: + + - When a partner takes a survey, a sign request will be created automatically. + +For generated sign requests scoping survey, input values are populated automatically +with the survey answered values. + +Answers for multiple choice questions are displayed as a sequence if you add the question in placeholder. +If you suffix the question in placeholder with specific answer then it will be displayed or checked if it is the answer. + +Answers of yes/no type are shown in text fields as Yes/No and in check fields as +checked/unchecked. + +Answers of type binary can be trated as signature fields if the survey question is the +same as the signature placeholder in sign request. + +In that case make sure to have this module: `survey_question_type_binary` from OCA +installed. + +Signers can still update the input values if they want. diff --git a/survey_sign_oca/static/description/icon.png b/survey_sign_oca/static/description/icon.png new file mode 100644 index 00000000..40f020bf Binary files /dev/null and b/survey_sign_oca/static/description/icon.png differ diff --git a/survey_sign_oca/static/description/index.html b/survey_sign_oca/static/description/index.html new file mode 100644 index 00000000..3d0d7294 --- /dev/null +++ b/survey_sign_oca/static/description/index.html @@ -0,0 +1,509 @@ + + + + + +Survey Sign Oca + + + +
+

Survey Sign Oca

+ + +

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

+

This module allows you to make survey signature requests manually or +automatically.

+

Table of contents

+ +
+

Configuration

+
    +
  1. Go to Sign > Settings > Roles and create a new one with the following +data if not there:
      +
    • For the survey participant
        +
      • Partner type: Expression
      • +
      • Expression: {{object.partner_id.id}}
      • +
      +
    • +
    • For the survey responsible if you want
        +
      • Partner type: Expression
      • +
      • Expression: {{object.survey_id.user_id.partner_id.id}}
      • +
      +
    • +
    +
  2. +
  3. Go to Sign > Settings > Fields and create a new one with the +following data if not there:
      +
    • Text Survey Field
        +
      • Field Type: text
      • +
      • Default Value: survey
      • +
      +
    • +
    • Check Survey Field
        +
      • Field Type: check
      • +
      • Default Value: survey
      • +
      +
    • +
    • Signature Survey Field
        +
      • Field Type: signature
      • +
      • Default Value: survey
      • +
      +
    • +
    +
  4. +
  5. Go to Sign > Templates and create a template with the following data:
      +
    • Model: Survey User Input
    • +
    • In some of the elements you will have to set the previously created +role[s].
    • +
    +
  6. +
  7. Go to Settings > Survey Sign OCA:
  8. +
  9. Defines the template previously created (optional, only for automatic +creation of signature requests).
  10. +
+
+
+

Usage

+

A smart-button will be displayed on the participations form view of the +linked sign requests.

+

Manual Sign Request creation process:

+
+- Go to Surveys \> Participations and change to list view.
+- Select the records that you want.
+- Click on the "Sign from template" action.
+- Select a template.
+- Click on Generate.
+- Sign Requests will have been generated (and sent) for the selected items.
+
+

Automatic Sign Request creation process:

+
+- When a partner takes a survey, a sign request will be created automatically.
+
+

For generated sign requests scoping survey, input values are populated +automatically with the survey answered values.

+

Answers for multiple choice questions are displayed as a sequence if you +add the question in placeholder. If you suffix the question in +placeholder with specific answer then it will be displayed or checked if +it is the answer.

+

Answers of yes/no type are shown in text fields as Yes/No and in check +fields as checked/unchecked.

+

Answers of type binary can be trated as signature fields if the survey +question is the same as the signature placeholder in sign request.

+

In that case make sure to have this module: +survey_question_type_binary from OCA installed.

+

Signers can still update the input values if they want.

+
+
+

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/sign project on GitHub.

+

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

+
+
+
+ + diff --git a/survey_sign_oca/tests/__init__.py b/survey_sign_oca/tests/__init__.py new file mode 100644 index 00000000..e2b55b52 --- /dev/null +++ b/survey_sign_oca/tests/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2023 Kencove - Mohamed Alkobrosli +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/survey_sign_oca/views/res_config_settings_view.xml b/survey_sign_oca/views/res_config_settings_view.xml new file mode 100644 index 00000000..600fc3e3 --- /dev/null +++ b/survey_sign_oca/views/res_config_settings_view.xml @@ -0,0 +1,49 @@ + + + + + res.config.settings.view.form.inherit + res.config.settings + + + + +
+

Surveys Sign Template

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/survey_sign_oca/views/sign_oca_request_views.xml b/survey_sign_oca/views/sign_oca_request_views.xml new file mode 100644 index 00000000..64dddaeb --- /dev/null +++ b/survey_sign_oca/views/sign_oca_request_views.xml @@ -0,0 +1,24 @@ + + + + sign.oca.request.search + sign.oca.request + + + + + + + + + + + diff --git a/survey_sign_oca/views/survey_user_views.xml b/survey_sign_oca/views/survey_user_views.xml new file mode 100644 index 00000000..bc3530ea --- /dev/null +++ b/survey_sign_oca/views/survey_user_views.xml @@ -0,0 +1,22 @@ + + + + survey.user.input.view.form + survey.user_input + + +
+ +
+
+
+
diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 00000000..ff7a0095 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +odoo-addon-sign_oca @ git+https://github.com/OCA/sign.git@refs/pull/91/head#subdirectory=setup/sign_oca +odoo-addon-survey_question_type_binary @ git+https://github.com/OCA/survey.git@refs/pull/157/head#subdirectory=setup/survey_question_type_binary