Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
2 changes: 1 addition & 1 deletion .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ env:

# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449
parserOptions:
ecmaVersion: 2019
ecmaVersion: 2021

overrides:
- files:
Expand Down
1 change: 1 addition & 0 deletions setup/survey_sign_oca/odoo/addons/survey_sign_oca
6 changes: 6 additions & 0 deletions setup/survey_sign_oca/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,
)
169 changes: 169 additions & 0 deletions survey_sign_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
===============
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 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 <https://github.com/OCA/sign/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/sign/issues/new?body=module:%20survey_sign_oca%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/sign <https://github.com/OCA/sign/tree/16.0/survey_sign_oca>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions survey_sign_oca/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
19 changes: 19 additions & 0 deletions survey_sign_oca/__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 (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"],
}
33 changes: 33 additions & 0 deletions survey_sign_oca/data/sign_oca_role.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<odoo>
<record id="sign_field_survey_text" model="sign.oca.field">
<field name="name">Survey Text</field>
<field name="field_type">text</field>
<field name="default_value">survey</field>
</record>

<record id="sign_field_survey_check" model="sign.oca.field">
<field name="name">Survey Check</field>
<field name="field_type">check</field>
<field name="default_value">survey</field>
</record>

<record id="sign_field_survey_signature" model="sign.oca.field">
<field name="name">Survey Signature</field>
<field name="field_type">signature</field>
<field name="default_value">survey</field>
</record>

<record id="role_survey_user_input" model="sign.oca.role">
<field name="name">Survey Participant</field>
<field name="partner_selection_policy">expression</field>
<field name="expression_partner">{{object.partner_id.id}}</field>
</record>

<record id="role_survey_responsible_input" model="sign.oca.role">
<field name="name">Survey Responsible</field>
<field name="partner_selection_policy">expression</field>
<field
name="expression_partner"
>{{object.survey_id.user_id.partner_id.id}}</field>
</record>
</odoo>
4 changes: 4 additions & 0 deletions survey_sign_oca/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import survey_invite
from . import res_company
from . import res_config_settings
from . import sign_oca_request
14 changes: 14 additions & 0 deletions survey_sign_oca/models/res_company.py
Original file line number Diff line number Diff line change
@@ -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",
)
15 changes: 15 additions & 0 deletions survey_sign_oca/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -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,
)
95 changes: 95 additions & 0 deletions survey_sign_oca/models/sign_oca_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Copyright 2025 Kencove - Mohamed Alkobrosli
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
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"]

Check warning on line 11 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L11

Added line #L11 was not covered by tests

@staticmethod
def answer_is_yes(value):
return str(value).strip().lower() == "yes"

Check warning on line 15 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L15

Added line #L15 was not covered by tests

@staticmethod
def format_answer(answer):
if SurveyUtils.is_yes_no_answer(answer):
answer = SurveyUtils.answer_is_yes(answer)
return answer

Check warning on line 21 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L20-L21

Added lines #L20 - L21 were not covered by tests


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

Check warning on line 42 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L42

Added line #L42 was not covered by tests


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 = {}

Check warning on line 52 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L50-L52

Added lines #L50 - L52 were not covered by tests
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})

Check warning on line 59 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L58-L59

Added lines #L58 - L59 were not covered by tests
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})

Check warning on line 62 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L61-L62

Added lines #L61 - L62 were not covered by tests
else:
answer = line.display_name
survey.update({line.question_id.display_name: answer})
return survey

Check warning on line 66 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L64-L66

Added lines #L64 - L66 were not covered by tests

def fill_survey_related_items(self, vals):
survey = self.get_related_survey_answers()
items = vals["items"]

Check warning on line 70 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L69-L70

Added lines #L69 - L70 were not covered by tests
for key in items:
item = items[key]
placeholder = item.get("placeholder")

Check warning on line 73 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L72-L73

Added lines #L72 - L73 were not covered by tests
# 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)

Check warning on line 79 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L79

Added line #L79 was not covered by tests
elif survey.get(placeholder) and item["field_type"] == "check":
item["value"] = SurveyUtils.format_answer(survey.get(placeholder))

Check warning on line 81 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L81

Added line #L81 was not covered by tests
elif survey.get(placeholder) and item["field_type"] == "signature":
item["value"] = survey.get(placeholder)

Check warning on line 83 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L83

Added line #L83 was not covered by tests
if item.get("default_value") and item.get("default_value") != "survey":
item["value"] = vals.get("partner").get(item["default_value"])
return vals

Check warning on line 86 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L85-L86

Added lines #L85 - L86 were not covered by tests

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)

Check warning on line 94 in survey_sign_oca/models/sign_oca_request.py

View check run for this annotation

Codecov / codecov/patch

survey_sign_oca/models/sign_oca_request.py#L94

Added line #L94 was not covered by tests
return vals
Loading
Loading