Browse Source

[REF] for myceliandre addons

12.0
RemiFr82 1 year ago
parent
commit
83efbf8951
  1. 60
      survey_custom_matrix/__manifest__.py
  2. 2
      survey_custom_matrix/controllers/__init__.py
  3. 78
      survey_custom_matrix/controllers/main.py
  4. 146
      survey_custom_matrix/controllers/survey.py
  5. 18
      survey_custom_matrix/models/survey_label.py
  6. 2
      survey_custom_matrix/models/survey_label_value.py
  7. 16
      survey_custom_matrix/models/survey_question.py
  8. 177
      survey_custom_matrix/models/survey_user_input_line.py
  9. 59
      survey_deadline_autoclose/__manifest__.py
  10. 4
      survey_deadline_autoclose/data/ir_cron.xml
  11. 4
      survey_deadline_autoclose/i18n/fr.po
  12. 73
      survey_deadline_autoclose/models/survey_survey.py
  13. 2
      survey_deadline_autoclose/views/survey_survey.xml
  14. 57
      survey_description/__manifest__.py
  15. 2
      survey_description/i18n/fr.po
  16. 61
      survey_input_attachment/__manifest__.py
  17. 24
      survey_input_attachment/i18n/fr.po
  18. 28
      survey_input_attachment/models/survey_question.py
  19. 84
      survey_input_attachment/models/survey_user_input_line.py
  20. 55
      survey_input_dates/__manifest__.py
  21. 12
      survey_input_dates/i18n/fr.po
  22. 42
      survey_input_dates/models/survey_user_input.py
  23. 3
      survey_input_dates/views/survey_user_input.xml
  24. 55
      survey_input_odoo_debrand/__manifest__.py
  25. 63
      survey_input_template_custom/__manifest__.py
  26. 55
      survey_link_input_ratio/__manifest__.py
  27. 88
      survey_link_input_ratio/models/survey_survey.py
  28. 24
      survey_link_input_ratio/views/survey_survey.xml
  29. 57
      survey_partner_input/__manifest__.py
  30. 92
      survey_partner_input/models/res_partner.py
  31. 55
      survey_question_duplicate/__manifest__.py
  32. 57
      survey_select_input/__manifest__.py
  33. 55
      survey_template/__manifest__.py
  34. 56
      survey_template/models/survey_survey.py

60
survey_custom_matrix/__manifest__.py

@ -1,28 +1,42 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': "Survey custom matrix",
'version': '1.0',
'summary': 'This app allows handling of complex survey forms with options like multiple choice questions, custom matrix etc.',
'description': """
Custom Matrix Survey.
================================
"name": "Survey Custom Matrix",
"version": "1.0.0",
"summary": """
This app allows handling of complex survey forms with options like multiple choice questions, custom matrix etc.
""",
'license': 'OPL-1',
'author': "Kanak Infosystems LLP.",
'website': "http://www.kanakinfosystems.com",
'images': ['static/description/banner.jpg'],
'category': 'Website',
'depends': ['survey'],
'data': [
'security/ir_model_access.xml',
'templates/matrix.xml',
'reports/user_input.xml',
'views/survey_question.xml',
'views/survey_user_input.xml',
'views/survey_user_input_line.xml',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'application': True,
# 'price': 49,
# 'currency': 'EUR',
"data": [
"security/ir_model_access.xml",
"templates/matrix.xml",
"reports/user_input.xml",
"views/survey_question.xml",
"views/survey_user_input.xml",
"views/survey_user_input_line.xml",
],
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

2
survey_custom_matrix/controllers/__init__.py

@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
from . import main
from . import survey

78
survey_custom_matrix/controllers/main.py

@ -1,78 +0,0 @@
# -*- coding: utf-8 -*-
import json
from odoo import http
from odoo.http import request
from odoo.addons.survey.controllers.main import Survey
import logging
_logger = logging.getLogger(__name__)
class Survey(Survey):
@http.route([
'/survey/prefill/<model("survey.survey"):survey>/<string:token>',
'/survey/prefill/<model("survey.survey"):survey>/<string:token>/<model("survey.page"):page>'],
type='http', auth='public', website=True)
def prefill(self, survey, token, page=None, **post):
UserInputLine = request.env['survey.user_input_line']
ret = {}
# Fetch previous answers
if page:
previous_answers = UserInputLine.sudo().search([('user_input_id.token', '=', token), ('page_id', '=', page.id)])
else:
previous_answers = UserInputLine.sudo().search([('user_input_id.token', '=', token)])
# Return non empty answers in a JSON compatible format
for answer in previous_answers:
if not answer.skipped:
answer_tag = '%s_%s_%s' % (answer.survey_id.id, answer.page_id.id, answer.question_id.id)
answer_value = None
if answer.question_id.matrix_subtype == 'custom':
if answer.answer_type == 'free_text':
answer_tag = "%s_%s_%s" % (answer_tag, answer.value_suggested_row.id, answer.value_suggested.id)
answer_value = answer.value_free_text
elif answer.answer_type == 'text':
answer_tag = "%s_%s_%s" % (answer_tag, answer.value_suggested_row.id, answer.value_suggested.id)
answer_value = answer.value_text
elif answer.answer_type == 'number':
answer_tag = "%s_%s_%s" % (answer_tag, answer.value_suggested_row.id, answer.value_suggested.id)
answer_value = str(answer.value_number)
elif answer.answer_type == 'date':
answer_tag = "%s_%s_%s" % (answer_tag, answer.value_suggested_row.id, answer.value_suggested.id)
answer_value = answer.value_date
elif answer.answer_type == 'dropdown':
answer_tag = "%s_%s_%s" % (answer_tag, answer.value_suggested_row.id, answer.value_suggested.id)
answer_value = answer.value_id.id
elif answer.answer_type == 'suggestion' and not answer.value_suggested_row:
answer_tag = "%s_%s_%s" % (answer_tag, answer.value_suggested_row.id, answer.value_suggested.id)
answer_value = answer.value_suggested.id
elif answer.answer_type == 'suggestion' and answer.value_suggested_row:
answer_tag = "%s_%s_%s" % (answer_tag, answer.value_suggested_row.id, answer.value_suggested.id)
answer_value = answer.value_suggested.id
if answer_value:
ret.setdefault(answer_tag, []).append(answer_value)
else:
_logger.warning("[survey] No answer has been found for question %s marked as non skipped" % answer_tag)
else:
if answer.answer_type == 'free_text':
answer_value = answer.value_free_text
elif answer.answer_type == 'text' and answer.question_id.type == 'textbox':
answer_value = answer.value_text
elif answer.answer_type == 'text' and answer.question_id.type != 'textbox':
# here come comment answers for matrices, simple choice and multiple choice
answer_tag = "%s_%s" % (answer_tag, 'comment')
answer_value = answer.value_text
elif answer.answer_type == 'number':
answer_value = str(answer.value_number)
elif answer.answer_type == 'date':
answer_value = answer.value_date
elif answer.answer_type == 'suggestion' and not answer.value_suggested_row:
answer_value = answer.value_suggested.id
elif answer.answer_type == 'suggestion' and answer.value_suggested_row:
answer_tag = "%s_%s" % (answer_tag, answer.value_suggested_row.id)
answer_value = answer.value_suggested.id
if answer_value:
ret.setdefault(answer_tag, []).append(answer_value)
else:
_logger.warning("[survey] No answer has been found for question %s marked as non skipped" % answer_tag)
return json.dumps(ret)

146
survey_custom_matrix/controllers/survey.py

@ -0,0 +1,146 @@
# -*- coding: utf-8 -*-
import json
from odoo import http
from odoo.http import request
from odoo.addons.survey.controllers.main import Survey
import logging
_logger = logging.getLogger(__name__)
class Survey(Survey):
@http.route(
[
'/survey/prefill/<model("survey.survey"):survey>/<string:token>',
'/survey/prefill/<model("survey.survey"):survey>/<string:token>/<model("survey.page"):page>',
],
type="http",
auth="public",
website=True,
)
def prefill(self, survey, token, page=None, **post):
UserInputLine = request.env["survey.user_input_line"]
ret = {}
# Fetch previous answers
if page:
previous_answers = UserInputLine.sudo().search(
[("user_input_id.token", "=", token), ("page_id", "=", page.id)]
)
else:
previous_answers = UserInputLine.sudo().search(
[("user_input_id.token", "=", token)]
)
# Return non empty answers in a JSON compatible format
for answer in previous_answers:
if not answer.skipped:
answer_tag = "%s_%s_%s" % (
answer.survey_id.id,
answer.page_id.id,
answer.question_id.id,
)
answer_value = None
if answer.question_id.matrix_subtype == "custom":
if answer.answer_type == "free_text":
answer_tag = "%s_%s_%s" % (
answer_tag,
answer.value_suggested_row.id,
answer.value_suggested.id,
)
answer_value = answer.value_free_text
elif answer.answer_type == "text":
answer_tag = "%s_%s_%s" % (
answer_tag,
answer.value_suggested_row.id,
answer.value_suggested.id,
)
answer_value = answer.value_text
elif answer.answer_type == "number":
answer_tag = "%s_%s_%s" % (
answer_tag,
answer.value_suggested_row.id,
answer.value_suggested.id,
)
answer_value = str(answer.value_number)
elif answer.answer_type == "date":
answer_tag = "%s_%s_%s" % (
answer_tag,
answer.value_suggested_row.id,
answer.value_suggested.id,
)
answer_value = answer.value_date
elif answer.answer_type == "dropdown":
answer_tag = "%s_%s_%s" % (
answer_tag,
answer.value_suggested_row.id,
answer.value_suggested.id,
)
answer_value = answer.value_id.id
elif (
answer.answer_type == "suggestion"
and not answer.value_suggested_row
):
answer_tag = "%s_%s_%s" % (
answer_tag,
answer.value_suggested_row.id,
answer.value_suggested.id,
)
answer_value = answer.value_suggested.id
elif (
answer.answer_type == "suggestion"
and answer.value_suggested_row
):
answer_tag = "%s_%s_%s" % (
answer_tag,
answer.value_suggested_row.id,
answer.value_suggested.id,
)
answer_value = answer.value_suggested.id
if answer_value:
ret.setdefault(answer_tag, []).append(answer_value)
else:
_logger.warning(
"[survey] No answer has been found for question %s marked as non skipped"
% answer_tag
)
else:
if answer.answer_type == "free_text":
answer_value = answer.value_free_text
elif (
answer.answer_type == "text"
and answer.question_id.type == "textbox"
):
answer_value = answer.value_text
elif (
answer.answer_type == "text"
and answer.question_id.type != "textbox"
):
# here come comment answers for matrices, simple choice and multiple choice
answer_tag = "%s_%s" % (answer_tag, "comment")
answer_value = answer.value_text
elif answer.answer_type == "number":
answer_value = str(answer.value_number)
elif answer.answer_type == "date":
answer_value = answer.value_date
elif (
answer.answer_type == "suggestion"
and not answer.value_suggested_row
):
answer_value = answer.value_suggested.id
elif (
answer.answer_type == "suggestion"
and answer.value_suggested_row
):
answer_tag = "%s_%s" % (
answer_tag,
answer.value_suggested_row.id,
)
answer_value = answer.value_suggested.id
if answer_value:
ret.setdefault(answer_tag, []).append(answer_value)
else:
_logger.warning(
"[survey] No answer has been found for question %s marked as non skipped"
% answer_tag
)
return json.dumps(ret)

18
survey_custom_matrix/models/survey_label.py

@ -2,17 +2,19 @@
from odoo import models, fields
TYPES = [
('free_text', 'Multiple Lines Text Box'),
('textbox', 'Single Line Text Box'),
('numerical_box', 'Numerical Value'),
("free_text", "Multiple Lines Text Box"),
("textbox", "Single Line Text Box"),
("numerical_box", "Numerical Value"),
# ('date', 'Date'),
('dropdown', 'Dropdown'),
('checkbox', 'Checkbox'),
("dropdown", "Dropdown"),
("checkbox", "Checkbox"),
]
class SurveyLabel(models.Model):
_inherit = 'survey.label'
_inherit = "survey.label"
type = fields.Selection(selection=TYPES, string="Type of question", default="checkbox")
value_ids = fields.Many2many(comodel_name='survey.label.value', string="Values")
type = fields.Selection(
selection=TYPES, string="Type of question", default="checkbox"
)
value_ids = fields.Many2many(comodel_name="survey.label.value", string="Values")

2
survey_custom_matrix/models/survey_label_value.py

@ -3,7 +3,7 @@ from odoo import models, fields
class SurveyLabelValue(models.Model):
_name = 'survey.label.value'
_name = "survey.label.value"
_description = "Value"
name = fields.Char(string="Name")

16
survey_custom_matrix/models/survey_question.py

@ -4,9 +4,9 @@ from odoo.addons.survey.models.survey import dict_keys_startswith
class SurveyQuestion(models.Model):
_inherit = 'survey.question'
_inherit = "survey.question"
matrix_subtype = fields.Selection(selection_add=[('custom', 'Custom Matrix')])
matrix_subtype = fields.Selection(selection_add=[("custom", "Custom Matrix")])
@api.multi
def validate_matrix(self, post, answer_tag):
@ -15,14 +15,14 @@ class SurveyQuestion(models.Model):
if self.constr_mandatory:
lines_number = len(self.labels_ids_2)
answer_candidates = dict_keys_startswith(post, answer_tag)
answer_candidates.pop(("%s_%s" % (answer_tag, 'comment')), '').strip()
answer_candidates.pop(("%s_%s" % (answer_tag, "comment")), "").strip()
# Number of lines that have been answered
if self.matrix_subtype == 'simple':
if self.matrix_subtype == "simple":
answer_number = len(answer_candidates)
elif self.matrix_subtype == 'multiple':
answer_number = len({sk.rsplit('_', 1)[0] for sk in answer_candidates})
elif self.matrix_subtype == 'custom':
answer_number = len({sk.rsplit('_', 1)[0] for sk in answer_candidates})
elif self.matrix_subtype == "multiple":
answer_number = len({sk.rsplit("_", 1)[0] for sk in answer_candidates})
elif self.matrix_subtype == "custom":
answer_number = len({sk.rsplit("_", 1)[0] for sk in answer_candidates})
else:
raise RuntimeError("Invalid matrix subtype")
# Validate that each line has been answered

177
survey_custom_matrix/models/survey_user_input_line.py

@ -4,119 +4,144 @@ from odoo.addons.survey.models.survey import dict_keys_startswith
class SurveyUserInputLine(models.Model):
_inherit = 'survey.user_input_line'
_inherit = "survey.user_input_line"
answer_type = fields.Selection(selection_add=[('dropdown', 'Dropdown')], string='Answer Type')
matrix_subtype = fields.Selection(related='question_id.matrix_subtype')
value_id = fields.Many2one('survey.label.value', string="Value Dropdown")
answer_type = fields.Selection(
selection_add=[("dropdown", "Dropdown")], string="Answer Type"
)
matrix_subtype = fields.Selection(related="question_id.matrix_subtype")
value_id = fields.Many2one("survey.label.value", string="Value Dropdown")
@api.model
def save_line_matrix(self, user_input_id, question, post, answer_tag):
vals = {
'user_input_id': user_input_id,
'question_id': question.id,
'survey_id': question.survey_id.id,
'skipped': False
"user_input_id": user_input_id,
"question_id": question.id,
"survey_id": question.survey_id.id,
"skipped": False,
}
suil = self.search([
('user_input_id', '=', user_input_id),
('survey_id', '=', question.survey_id.id),
('question_id', '=', question.id)
])
suil = self.search(
[
("user_input_id", "=", user_input_id),
("survey_id", "=", question.survey_id.id),
("question_id", "=", question.id),
]
)
suil.sudo().unlink()
no_answers = True
ca_dict = dict_keys_startswith(post, answer_tag + '_')
ca_dict = dict_keys_startswith(post, answer_tag + "_")
comment_answer = ca_dict.pop(("%s_%s" % (answer_tag, 'comment')), '').strip()
comment_answer = ca_dict.pop(("%s_%s" % (answer_tag, "comment")), "").strip()
if comment_answer:
vals.update({
'answer_type': 'text',
'value_text': comment_answer,
})
vals.update(
{
"answer_type": "text",
"value_text": comment_answer,
}
)
self.create(vals)
no_answers = False
if question.matrix_subtype == 'simple':
if question.matrix_subtype == "simple":
for row in question.labels_ids_2:
a_tag = "%s_%s" % (answer_tag, row.id)
if a_tag in ca_dict:
no_answers = False
vals.update({
'answer_type': 'suggestion',
'value_suggested': ca_dict[a_tag],
'value_suggested_row': row.id,
})
vals.update(
{
"answer_type": "suggestion",
"value_suggested": ca_dict[a_tag],
"value_suggested_row": row.id,
}
)
self.create(vals)
elif question.matrix_subtype == 'multiple':
elif question.matrix_subtype == "multiple":
for col in question.labels_ids:
for row in question.labels_ids_2:
a_tag = "%s_%s_%s" % (answer_tag, row.id, col.id)
if a_tag in ca_dict:
no_answers = False
vals.update({
'answer_type': 'suggestion',
'value_suggested': col.id,
'value_suggested_row': row.id,
})
vals.update(
{
"answer_type": "suggestion",
"value_suggested": col.id,
"value_suggested_row": row.id,
}
)
self.create(vals)
elif question.matrix_subtype == 'custom':
elif question.matrix_subtype == "custom":
for col in question.labels_ids:
for row in question.labels_ids_2:
a_tag = "%s_%s_%s" % (answer_tag, row.id, col.id)
if a_tag in ca_dict:
no_answers = False
if post.get(a_tag):
sline = a_tag.split('_')[-1]
sline = a_tag.split("_")[-1]
label_obj = question.labels_ids.browse(int(sline))
if label_obj.type == 'textbox':
vals.update({
'answer_type': 'text',
'value_suggested': col.id,
'value_suggested_row': row.id,
'value_text': post.get(a_tag),
})
elif label_obj.type == 'free_text':
vals.update({
'answer_type': 'free_text',
'value_suggested': col.id,
'value_suggested_row': row.id,
'value_free_text': post.get(a_tag),
})
elif label_obj.type == 'numerical_box':
vals.update({
'answer_type': 'number',
'value_suggested': col.id,
'value_suggested_row': row.id,
'value_number': post.get(a_tag),
})
elif label_obj.type == 'date':
vals.update({
'answer_type': 'date',
'value_suggested': col.id,
'value_suggested_row': row.id,
'value_date': post.get(a_tag),
})
elif label_obj.type == 'dropdown':
vals.update({
'answer_type': 'dropdown',
'value_suggested': col.id,
'value_suggested_row': row.id,
'value_id': int(post.get(a_tag)),
})
if label_obj.type == "textbox":
vals.update(
{
"answer_type": "text",
"value_suggested": col.id,
"value_suggested_row": row.id,
"value_text": post.get(a_tag),
}
)
elif label_obj.type == "free_text":
vals.update(
{
"answer_type": "free_text",
"value_suggested": col.id,
"value_suggested_row": row.id,
"value_free_text": post.get(a_tag),
}
)
elif label_obj.type == "numerical_box":
vals.update(
{
"answer_type": "number",
"value_suggested": col.id,
"value_suggested_row": row.id,
"value_number": post.get(a_tag),
}
)
elif label_obj.type == "date":
vals.update(
{
"answer_type": "date",
"value_suggested": col.id,
"value_suggested_row": row.id,
"value_date": post.get(a_tag),
}
)
elif label_obj.type == "dropdown":
vals.update(
{
"answer_type": "dropdown",
"value_suggested": col.id,
"value_suggested_row": row.id,
"value_id": int(post.get(a_tag)),
}
)
else:
vals.update({
'answer_type': 'suggestion',
'value_suggested': col.id,
'value_suggested_row': row.id})
vals.update(
{
"answer_type": "suggestion",
"value_suggested": col.id,
"value_suggested_row": row.id,
}
)
self.create(vals)
if no_answers:
vals.update({
'answer_type': None,
'skipped': True,
})
vals.update(
{
"answer_type": None,
"skipped": True,
}
)
self.create(vals)
return True

59
survey_deadline_autoclose/__manifest__.py

@ -1,34 +1,39 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Auto-close survey on deadline',
'version': '1.0.0',
'summary': """
"name": "Auto-close survey on deadline",
"version": "1.0.0",
"summary": """
The module adds a deadline date on surveys and a checkbox to automatically close them with a planned action.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'data/ir_cron.xml',
'data/mail_message_subtype.xml',
'views/survey_survey.xml',
"data": [
"data/ir_cron.xml",
"data/mail_message_subtype.xml",
"views/survey_survey.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

4
survey_deadline_autoclose/data/ir_cron.xml

@ -7,12 +7,12 @@
<field name="name">Close expired surveys</field>
<field name="model_id" ref="survey.model_survey_survey"/>
<field name="state">code</field>
<field name="code">model.action_close_survey()</field>
<field name="code">model.with_context(cron=True).close_deadline_survey()</field>
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="nextcall" eval="(datetime.today() + relativedelta(days=1)).strftime('%Y-%m-%d 00:10:00')"/>
<field name="nextcall" eval="(datetime.today() + relativedelta(days=1)).strftime('%Y-%m-%d 00:08:00')"/>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
</record>

4
survey_deadline_autoclose/i18n/fr.po

@ -66,9 +66,9 @@ msgstr "Sondage"
#. module: survey_deadline_autoclose
#: model:mail.message.subtype,description:survey_deadline_autoclose.mail_message_subtype_survey_expired
msgid "This survey has expired."
msgstr "Ce sondage a été clôturé."
msgstr "Ce sondage est arrivé à échéance."
#. module: survey_deadline_autoclose
#: model:mail.message.subtype,description:survey_deadline_autoclose.mail_message_subtype_survey_closed
msgid "This survey was closed."
msgstr "Ce sondage est arrivé à échéance."
msgstr "Ce sondage a été clôturé."

73
survey_deadline_autoclose/models/survey_survey.py

@ -3,22 +3,33 @@ from odoo.exceptions import UserError
class SurveySurvey(models.Model):
_inherit = 'survey.survey'
_inherit = "survey.survey"
@api.model
def close_deadline_survey(self):
deadline = self.search([
('date_deadline', '!=', False),
('date_deadline', '<', fields.Date.today()),
])
to_close = deadline.filtered('auto_close')
def cron_close_deadline_survey(self):
deadline = self.search(
[
("date_deadline", "!=", False),
("date_deadline", "<", fields.Date.today()),
]
)
to_close = deadline.filtered("auto_close")
if to_close:
to_close.action_close_survey()
for survey in deadline - to_close:
survey.message_post(subtype='survey_deadline_autoclose.mail_message_subtype_survey_deadline')
survey.message_post(
subtype="survey_deadline_autoclose.mail_message_subtype_survey_deadline"
)
date_deadline = fields.Date(string="Deadline", copy=False, track_visibility='onchange')
auto_close = fields.Boolean(string="Auto close", default=False, help="If checked, the survey will be closed automatically when deadline is overpassed.", track_visibility='onchange')
date_deadline = fields.Date(
string="Deadline", copy=False, track_visibility="onchange"
)
auto_close = fields.Boolean(
string="Auto close",
default=False,
help="If checked, the survey will be automatically closed when deadline is overpassed.",
track_visibility="onchange",
)
# ACTIONS
@ -26,25 +37,45 @@ class SurveySurvey(models.Model):
def action_send_survey(self):
self.ensure_one()
action = super(SurveySurvey, self).action_send_survey()
action['context'].update({
'default_date_deadline': self.date_deadline,
})
action["context"].update(
{
"default_date_deadline": self.date_deadline,
}
)
return action
@api.multi
def action_close_survey(self):
stage = self.env['survey.stage'].search([('closed', '=', True)], limit=1)
stage = self.env["survey.stage"].search([("closed", "=", True)], limit=1)
if not stage:
raise UserError(_("No \"closed\" status found, the requested operation is impossible."))
self.write({
'stage_id': stage.id
})
for survey in self:
survey.message_post(subtype='survey_deadline_autoclose.mail_message_subtype_survey_closed')
if self.env.context.get("cron", False):
for survey in self:
survey.message_post(
message_type="comment",
subject=_("Survey closing impossible"),
body=_(
'Survey should have been automatically closed but no "closed" '
"stage was found, the requested operation was impossible to proceed.\n"
'To fix this situation, you have to check "Closed" at least on one survey stage.'
),
)
else:
raise UserError(
_(
'No "closed" stage found, the requested operation is impossible.\n'
'To fix this situation, you have to check "Closed" at least on one survey stage.'
)
)
else:
self.write({"stage_id": stage.id})
for survey in self:
survey.message_post(
subtype="survey_deadline_autoclose.mail_message_subtype_survey_closed"
)
# ONCHANGES
@api.onchange('date_deadline')
@api.onchange("date_deadline")
def onchange_is_template(self):
self.ensure_one()
if not self.date_deadline:

2
survey_deadline_autoclose/views/survey_survey.xml

@ -72,7 +72,7 @@
<field name="arch" type="xml">
<search position="inside">
<group expand="0" string="Group By">
<filter string="Échéance" name="group_date_deadline" context="{'group_by':'date_deadline:month'}"/>
<filter string="Expiration month" name="group_date_deadline_month" context="{'group_by':'date_deadline:month'}"/>
</group>
</search>
</field>

57
survey_description/__manifest__.py

@ -1,33 +1,38 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey description',
'version': '1.0.0',
'summary': """
"name": "Survey description",
"version": "1.0.0",
"summary": """
This module displays standard HTML fields \"Description\" and \"Thank you message\" on survey and survey pages.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'views/survey_page.xml',
'views/survey_survey.xml',
"data": [
"views/survey_page.xml",
"views/survey_survey.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

2
survey_description/i18n/fr.po

@ -18,7 +18,7 @@ msgstr ""
#. module: survey_description
#: model_terms:ir.ui.view,arch_db:survey_description.survey_survey_form
msgid "Description"
msgstr "Description"
msgstr ""
#. module: survey_description
#: model:ir.model,name:survey_description.model_survey_survey

61
survey_input_attachment/__manifest__.py

@ -1,35 +1,40 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey input attachment',
'version': '1.0.0',
'summary': """
"name": "Survey input attachment",
"version": "1.0.0",
"summary": """
This module provides a new type of question in surveys, that allows to join a file as answer.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com/',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'templates/upload_file.xml',
'templates/page.xml',
'templates/survey_print.xml',
'views/survey_user_input_line.xml',
"data": [
"templates/upload_file.xml",
"templates/page.xml",
"templates/survey_print.xml",
"views/survey_user_input_line.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': ['static/description/survey.jpg'],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

24
survey_input_attachment/i18n/fr.po

@ -21,15 +21,15 @@ msgid "Answer Type"
msgstr "Type de réponse"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_question.py:9
#: code:addons/survey_input_attachment/models/survey_question.py:10
#: selection:survey.question,type:0
#: selection:survey.user_input_line,answer_type:0
#, python-format
msgid "Attachment"
msgstr "Pièce jointe"
msgid "Attachment (img/pdf)"
msgstr "Pièce jointe (img/pdf)"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_question.py:8
#: code:addons/survey_input_attachment/models/survey_question.py:9
#: selection:survey.question,type:0
#: selection:survey.user_input_line,answer_type:0
#, python-format
@ -47,7 +47,7 @@ msgid "File type"
msgstr "Type de fichier"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_user_input_line.py:7
#: code:addons/survey_input_attachment/models/survey_user_input_line.py:8
#: selection:survey.user_input_line,file_type:0
#, python-format
msgid "Image"
@ -59,7 +59,7 @@ msgid "Joined attachment"
msgstr "Pièce jointe"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_question.py:12
#: code:addons/survey_input_attachment/models/survey_question.py:13
#: selection:survey.question,type:0
#: selection:survey.user_input_line,answer_type:0
#, python-format
@ -67,7 +67,7 @@ msgid "Matrix"
msgstr "Matrice"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_question.py:5
#: code:addons/survey_input_attachment/models/survey_question.py:6
#: selection:survey.question,type:0
#: selection:survey.user_input_line,answer_type:0
#, python-format
@ -75,7 +75,7 @@ msgid "Multiple Lines Text Box"
msgstr "Plusieurs lignes de champ de texte"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_question.py:11
#: code:addons/survey_input_attachment/models/survey_question.py:12
#: selection:survey.question,type:0
#: selection:survey.user_input_line,answer_type:0
#, python-format
@ -83,7 +83,7 @@ msgid "Multiple choice: multiple answers allowed"
msgstr "Choix multiples : réponses multiples"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_question.py:10
#: code:addons/survey_input_attachment/models/survey_question.py:11
#: selection:survey.question,type:0
#: selection:survey.user_input_line,answer_type:0
#, python-format
@ -91,7 +91,7 @@ msgid "Multiple choice: only one answer"
msgstr "Choix multiples : une seule réponse possible"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_question.py:7
#: code:addons/survey_input_attachment/models/survey_question.py:8
#: selection:survey.question,type:0
#: selection:survey.user_input_line,answer_type:0
#, python-format
@ -99,14 +99,14 @@ msgid "Numerical Value"
msgstr "Valeur numérique"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_user_input_line.py:8
#: code:addons/survey_input_attachment/models/survey_user_input_line.py:9
#: selection:survey.user_input_line,file_type:0
#, python-format
msgid "PDF file"
msgstr "Fichier PDF"
#. module: survey_input_attachment
#: code:addons/survey_input_attachment/models/survey_question.py:6
#: code:addons/survey_input_attachment/models/survey_question.py:7
#: selection:survey.question,type:0
#: selection:survey.user_input_line,answer_type:0
#, python-format

28
survey_input_attachment/models/survey_question.py

@ -3,19 +3,19 @@ from odoo import models, fields, api, _
from werkzeug.datastructures import FileStorage
TYPES = [
('free_text', _('Multiple Lines Text Box')),
('textbox', _('Single Line Text Box')),
('numerical_box', _('Numerical Value')),
('date', _('Date')),
('upload_file', _('Attachment')),
('simple_choice', _('Multiple choice: only one answer')),
('multiple_choice', _('Multiple choice: multiple answers allowed')),
('matrix', _('Matrix')),
("free_text", _("Multiple Lines Text Box")),
("textbox", _("Single Line Text Box")),
("numerical_box", _("Numerical Value")),
("date", _("Date")),
("upload_file", _("Attachment (img/pdf)")),
("simple_choice", _("Multiple choice: only one answer")),
("multiple_choice", _("Multiple choice: multiple answers allowed")),
("matrix", _("Matrix")),
]
class SurveyQuestion(models.Model):
_inherit = 'survey.question'
_inherit = "survey.question"
# question_attachment = fields.Binary(string="Joined attachment")
type = fields.Selection(selection=TYPES)
@ -28,6 +28,12 @@ class SurveyQuestion(models.Model):
if self.constr_mandatory and not isinstance(post[answer_tag], FileStorage):
errors.update({answer_tag: self.constr_error_msg})
# Bad file type
if isinstance(post[answer_tag], FileStorage) and post[answer_tag].content_type != 'application/pdf' and 'image/' not in post[answer_tag].content_type:
errors.update({answer_tag: _("The file you joined is not an image nor a PDF file.")})
if (
isinstance(post[answer_tag], FileStorage)
and post[answer_tag].content_type != "application/pdf"
and "image/" not in post[answer_tag].content_type
):
errors.update(
{answer_tag: _("The file you joined is not an image nor a PDF file.")}
)
return errors

84
survey_input_attachment/models/survey_user_input_line.py

@ -3,64 +3,74 @@ import base64
from odoo import models, fields, api, _
ANSWER_TYPES = [
('text', _('Text')),
('number', _('Number')),
('date', _('Date')),
('free_text', _('Free Text')),
('upload_file', _('Attachment')),
('suggestion', _('Suggestion')),
("text", _("Text")),
("number", _("Number")),
("date", _("Date")),
("free_text", _("Free Text")),
("upload_file", _("Attachment (img/pdf)")),
("suggestion", _("Suggestion")),
]
FILE_TYPES = [
('image', _('Image')),
('pdf', _('PDF file')),
("image", _("Image")),
("pdf", _("PDF file")),
]
class SurveyUserInputLine(models.Model):
_inherit = 'survey.user_input_line'
_inherit = "survey.user_input_line"
answer_type = fields.Selection(selection=ANSWER_TYPES)
file = fields.Binary(string='Uploaded file')
filename = fields.Char(string='Uploaded file name')
file = fields.Binary(string="Uploaded file")
filename = fields.Char(string="Uploaded file name")
file_type = fields.Selection(selection=FILE_TYPES, string="File type")
@api.model
def save_line_upload_file(self, user_input_id, question, post, answer_tag):
vals = {
'user_input_id': user_input_id,
'question_id': question.id,
'survey_id': question.survey_id.id,
'skipped': False
"user_input_id": user_input_id,
"question_id": question.id,
"survey_id": question.survey_id.id,
"skipped": False,
}
file = False
# import ipdb; ipdb.set_trace()
if question.constr_mandatory:
file = base64.encodebytes(post[answer_tag].read())
file = base64.encodebytes(post[answer_tag].read())
else:
file = base64.encodebytes(post[answer_tag].read()) if not isinstance(post[answer_tag], str) else None
file = (
base64.encodebytes(post[answer_tag].read())
if not isinstance(post[answer_tag], str)
else None
)
if answer_tag in post and not isinstance(post[answer_tag], str):
vals.update({
'answer_type': 'upload_file',
'file': file,
'filename': post[answer_tag].filename,
})
if post[answer_tag].content_type == 'application/pdf':
vals.update({'file_type': 'pdf'})
if 'image/' in post[answer_tag].content_type:
vals.update({'file_type': 'image'})
vals.update(
{
"answer_type": "upload_file",
"file": file,
"filename": post[answer_tag].filename,
}
)
if post[answer_tag].content_type == "application/pdf":
vals.update({"file_type": "pdf"})
if "image/" in post[answer_tag].content_type:
vals.update({"file_type": "image"})
else:
vals.update({
'answer_type': None,
'file': False,
'filename': False,
'skipped': True,
})
old_uil = self.search([
('user_input_id', '=', user_input_id),
('survey_id', '=', question.survey_id.id),
('question_id', '=', question.id)
])
vals.update(
{
"answer_type": None,
"file": False,
"filename": False,
"skipped": True,
}
)
old_uil = self.search(
[
("user_input_id", "=", user_input_id),
("survey_id", "=", question.survey_id.id),
("question_id", "=", question.id),
]
)
if old_uil:
old_uil.write(vals)
else:

55
survey_input_dates/__manifest__.py

@ -1,32 +1,37 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey input dates',
'version': '1.0.0',
'summary': """
"name": "Survey input dates",
"version": "1.0.0",
"summary": """
This module adds date start and date done on surveys answers.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'views/survey_user_input.xml',
"data": [
"views/survey_user_input.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

12
survey_input_dates/i18n/fr.po

@ -21,6 +21,18 @@ msgstr ""
msgid "Date done"
msgstr "Réponse terminée le"
#. module: survey_input_dates
#: code:addons/survey_input_dates/models/survey_user_input.py:27
#, python-format
msgid "Not done"
msgstr "Non terminé"
#. module: survey_input_dates
#: code:addons/survey_input_dates/models/survey_user_input.py:25
#, python-format
msgid "Not started"
msgstr "Non commencé"
#. module: survey_input_dates
#: model:ir.model.fields,field_description:survey_input_dates.field_survey_user_input__date_start
msgid "Start date"

42
survey_input_dates/models/survey_user_input.py

@ -1,16 +1,42 @@
from odoo import models, fields, api
from odoo import models, fields, api, _
class SurveyUserInput(models.Model):
_inherit = 'survey.user_input'
_inherit = "survey.user_input"
date_start = fields.Datetime(string="Start date", readonly=True, help="This date is set when the user clicks on \"Start survey\" button for the first time.")
date_done = fields.Datetime(string="Date done", readonly=True, help="This date is set when the user input is set ton \"Done\" status.")
date_start = fields.Datetime(
string="Start date",
readonly=True,
help='This date is set when the user clicks on "Start survey" button for the first time.',
)
date_done = fields.Datetime(
string="Date done",
readonly=True,
help='This date is set when the user input is set ton "Done" status.',
)
duration = fields.Integer(
string="Duration",
compute="_get_duration",
store=True,
help="Time expressed in seconds, neet 'duration' widget to be read by user.",
)
@api.depends("date_start", "date_stop")
def _get_duration(self):
for input in self:
start = input.date_start
done = input.date_done
if not start and done:
input.duration = 0
else:
input.duration = int((done - start).total_seconds())
@api.multi
def write(self, vals):
if vals.get('state', False) == 'done':
vals.update({
'date_done': fields.Datetime.now(),
})
if vals.get("state", False) == "done":
vals.update(
{
"date_done": fields.Datetime.now(),
}
)
return super(SurveyUserInput, self).write(vals)

3
survey_input_dates/views/survey_user_input.xml

@ -11,6 +11,7 @@
<field name="date_create" position="after">
<field name="date_start"/>
<field name="date_done"/>
<field name="duration" widget="duration" options="{'unit': 'second', 'round': 'second'}"/>
</field>
</field>
</record>
@ -25,6 +26,7 @@
<field name="date_create" position="after">
<field name="date_start"/>
<field name="date_done"/>
<field name="duration" widget="duration" options="{'unit': 'minute', 'round': 'minute'}"/>
</field>
</field>
</record>
@ -39,6 +41,7 @@
<field name="date_create" position="after">
<field name="date_start"/>
<field name="date_done"/>
<!-- <field name="duration"/> -->
</field>
</field>
</record>

55
survey_input_odoo_debrand/__manifest__.py

@ -1,32 +1,37 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey input debranding',
'version': '1.0.0',
'summary': """
"name": "Survey input debranding",
"version": "1.0.0",
"summary": """
This module removes the \"Create a free website with odoo\" mention at the bottom right of survey inputs.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'templates/layout.xml',
"data": [
"templates/layout.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

63
survey_input_template_custom/__manifest__.py

@ -1,36 +1,41 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey input custom',
'version': '1.0.0',
'summary': """
"name": "Survey input custom",
"version": "1.0.0",
"summary": """
This module allows to customize the survey start button label and the \"Thank you\" page title.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey_description',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey_description",
],
'data': [
'templates/layout.xml',
'templates/page.xml',
'templates/sfinished.xml',
'templates/survey_init.xml',
'views/survey_survey.xml',
"data": [
"templates/layout.xml",
"templates/page.xml",
"templates/sfinished.xml",
"templates/survey_init.xml",
"views/survey_survey.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

55
survey_link_input_ratio/__manifest__.py

@ -1,32 +1,37 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey sent answer ratio',
'version': '1.0.0',
'summary': """
"name": "Survey sent answer ratio",
"version": "1.0.0",
"summary": """
This module displays percent pies statistics on sent inputs in survey form stat-buttons.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'views/survey_survey.xml',
"data": [
"views/survey_survey.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

88
survey_link_input_ratio/models/survey_survey.py

@ -3,62 +3,100 @@ from odoo.osv.expression import normalize_domain, AND
class SurveySurvey(models.Model):
_inherit = 'survey.survey'
_inherit = "survey.survey"
tot_sent_start_survey = fields.Integer("Started sent survey count", compute="_count_sent_input")
tot_sent_comp_survey = fields.Integer("Completed sent survey count", compute="_count_sent_input")
sent_start_ratio = fields.Integer(string="Started sent survey ratio", compute="_get_sent_start_ratio")
sent_comp_ratio = fields.Integer(string="Completed sent survey ratio", compute="_get_sent_comp_ratio")
tot_sent_start_survey = fields.Integer(
"Started sent survey count", compute="_count_sent_input"
)
tot_sent_comp_survey = fields.Integer(
"Completed sent survey count", compute="_count_sent_input"
)
sent_start_ratio = fields.Integer(
string="Started sent survey ratio", compute="_get_sent_start_ratio"
)
sent_comp_ratio = fields.Integer(
string="Completed sent survey ratio", compute="_get_sent_comp_ratio"
)
# COMPUTES
@api.multi
def _count_sent_input(self):
UserInput = self.env['survey.user_input']
sent_start_survey = UserInput.search([('survey_id', 'in', self.ids), ('type', '=', 'link'), ('state', '=', 'skip')])
sent_comp_survey = UserInput.search([('survey_id', 'in', self.ids), ('type', '=', 'link'), ('state', '=', 'done')])
UserInput = self.env["survey.user_input"]
sent_start_survey = UserInput.search(
[
("survey_id", "in", self.ids),
("type", "=", "link"),
("state", "=", "skip"),
]
)
sent_comp_survey = UserInput.search(
[
("survey_id", "in", self.ids),
("type", "=", "link"),
("state", "=", "done"),
]
)
for survey in self:
survey.tot_sent_start_survey = len(sent_start_survey.filtered(lambda user_input: user_input.survey_id == survey))
survey.tot_sent_comp_survey = len(sent_comp_survey.filtered(lambda user_input: user_input.survey_id == survey))
survey.tot_sent_start_survey = len(
sent_start_survey.filtered(
lambda user_input: user_input.survey_id == survey
)
)
survey.tot_sent_comp_survey = len(
sent_comp_survey.filtered(
lambda user_input: user_input.survey_id == survey
)
)
@api.depends('tot_sent_start_survey', 'tot_sent_survey')
@api.depends("tot_sent_start_survey", "tot_sent_survey")
def _get_sent_start_ratio(self):
for survey in self:
if survey.tot_sent_survey == 0:
survey.sent_start_ratio = 0
else:
survey.sent_start_ratio = int(round(100 * (survey.tot_sent_start_survey) / survey.tot_sent_survey, 0))
survey.sent_start_ratio = int(
round(
100 * (survey.tot_sent_start_survey) / survey.tot_sent_survey, 0
)
)
@api.depends('tot_sent_comp_survey', 'tot_sent_survey')
@api.depends("tot_sent_comp_survey", "tot_sent_survey")
def _get_sent_comp_ratio(self):
for survey in self:
if survey.tot_sent_survey == 0:
survey.sent_comp_ratio = 0
else:
survey.sent_comp_ratio = int(round(100 * survey.tot_sent_comp_survey / survey.tot_sent_survey, 0))
survey.sent_comp_ratio = int(
round(100 * survey.tot_sent_comp_survey / survey.tot_sent_survey, 0)
)
# ACTIONS
@api.multi
def action_survey_user_input(self):
ctx = dict(self.env.context)
search_completed = ctx.get('search_default_completed', None)
search_completed = ctx.get("search_default_completed", None)
action = super(SurveySurvey, self).action_survey_user_input()
if ctx.get('link_only', False):
domain = action.get('domain') or []
if ctx.get("link_only", False):
domain = action.get("domain") or []
if isinstance(domain, str):
domain = eval(domain)
if len(domain) > 1:
action['domain'] = AND([[('type', '=', 'link')], normalize_domain(domain)])
action["domain"] = AND(
[[("type", "=", "link")], normalize_domain(domain)]
)
else:
action['domain'] = [('type', '=', 'link')]
action['display_name'] += _(" (from private links)")
action["domain"] = [("type", "=", "link")]
action["display_name"] += _(" (from private links)")
if search_completed is not None:
act_ctx = action.get('context') or {}
act_ctx = action.get("context") or {}
if isinstance(act_ctx, str):
act_ctx = eval(act_ctx)
if 'search_default_completed' in act_ctx:
if bool(act_ctx['search_default_completed']) is not bool(search_completed):
act_ctx['search_default_completed'] = int(bool(search_completed))
action['context'] = act_ctx
if "search_default_completed" in act_ctx:
if bool(act_ctx["search_default_completed"]) is not bool(
search_completed
):
act_ctx["search_default_completed"] = int(bool(search_completed))
action["context"] = act_ctx
return action

24
survey_link_input_ratio/views/survey_survey.xml

@ -27,28 +27,4 @@
</field>
</record>
<!-- <record id="survey_survey_tree" model="ir.ui.view">
<field name="name">OT31 SURVEY survey.survey tree</field>
<field name="model">survey.survey</field>
<field name="inherit_id" ref="survey.survey_tree"/>
<field name="priority">36</field>
<field name="arch" type="xml">
<field name="title" position="after">
<field name="aa_type"/>
</field>
</field>
</record> -->
<!-- <record id="survey_survey_kanban" model="ir.ui.view">
<field name="name">OT31 SURVEY survey.survey kanban</field>
<field name="model">survey.survey</field>
<field name="inherit_id" ref="survey.survey_kanban"/>
<field name="priority">36</field>
<field name="arch" type="xml">
<field name="title" position="after">
<field name="aa_type" readonly="1"/>
</field>
</field>
</record> -->
</odoo>

57
survey_partner_input/__manifest__.py

@ -1,33 +1,38 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey partner answers',
'version': '1.0.0',
'summary': """
"name": "Survey partner answers",
"version": "1.0.0",
"summary": """
This module displays a counter and a percent pie on partner survey answers statistics in form stat-buttons.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'views/res_partner.xml',
'views/survey_user_input.xml',
"data": [
"views/res_partner.xml",
"views/survey_user_input.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

92
survey_partner_input/models/res_partner.py

@ -3,83 +3,115 @@ from odoo.osv.expression import normalize_domain, AND
class ResPartner(models.Model):
_inherit = 'res.partner'
_inherit = "res.partner"
tot_sent_survey = fields.Integer("Sent survey count", compute="_count_survey_input")
tot_comp_survey = fields.Integer("Completed survey count", compute="_count_survey_input")
tot_sent_comp_survey = fields.Integer("Completed sent survey count", compute="_count_survey_input")
sent_comp_ratio = fields.Integer(string="Completed sent survey ratio", compute="_get_sent_comp_ratio")
tot_comp_survey = fields.Integer(
"Completed survey count", compute="_count_survey_input"
)
tot_sent_comp_survey = fields.Integer(
"Completed sent survey count", compute="_count_survey_input"
)
sent_comp_ratio = fields.Integer(
string="Completed sent survey ratio", compute="_get_sent_comp_ratio"
)
# COMPUTES
@api.multi
def _count_survey_input(self):
UserInput = self.env['survey.user_input']
UserInput = self.env["survey.user_input"]
partners_survey = UserInput
in_onchange = self.env.in_onchange
origin = in_onchange and self._origin or False
if in_onchange:
domain = [
('partner_id', '=', self._origin.id),
'|', ('type', '=', 'link'),
('state', '=', 'dones'),
("partner_id", "=", self._origin.id),
"|",
("type", "=", "link"),
("state", "=", "dones"),
]
if self.email:
domain = ['|', ('email', '=', self.email)] + domain
domain = ["|", ("email", "=", self.email)] + domain
partners_survey = UserInput.search(domain)
else:
partners_survey = UserInput.search([
'|', ('partner_id', 'in', self.ids),
('email', 'in', self.filtered('email').mapped('email')),
'|', ('type', '=', 'link'),
('state', '=', 'done'),
])
partners_survey = UserInput.search(
[
"|",
("partner_id", "in", self.ids),
("email", "in", self.filtered("email").mapped("email")),
"|",
("type", "=", "link"),
("state", "=", "done"),
]
)
for partner in self:
done = partners_survey.filtered(lambda sui: (sui.partner_id == (origin or partner) or partner.email and sui.email == partner.email) and sui.state == 'done')
link = partners_survey.filtered(lambda sui: (sui.partner_id == (origin or partner) or partner.email and sui.email == partner.email) and sui.type == 'link')
done = partners_survey.filtered(
lambda sui: (
sui.partner_id == (origin or partner)
or partner.email
and sui.email == partner.email
)
and sui.state == "done"
)
link = partners_survey.filtered(
lambda sui: (
sui.partner_id == (origin or partner)
or partner.email
and sui.email == partner.email
)
and sui.type == "link"
)
partner.tot_sent_survey = len(link)
partner.tot_comp_survey = len(done)
partner.tot_sent_comp_survey = len(link & done)
@api.depends('tot_sent_comp_survey', 'tot_sent_survey')
@api.depends("tot_sent_comp_survey", "tot_sent_survey")
def _get_sent_comp_ratio(self):
for survey in self:
if survey.tot_sent_survey == 0:
survey.sent_comp_ratio = 0
else:
survey.sent_comp_ratio = int(round(100 * survey.tot_sent_comp_survey / survey.tot_sent_survey, 0))
survey.sent_comp_ratio = int(
round(100 * survey.tot_sent_comp_survey / survey.tot_sent_survey, 0)
)
# ACTIONS
@api.multi
def action_survey_user_input(self):
self.ensure_one()
action = self.env.ref('survey.action_survey_user_input').read()[0]
action['display_name'] += _(" from {}").format(self.display_name)
action = self.env.ref("survey.action_survey_user_input").read()[0]
action["display_name"] += _(" from {}").format(self.display_name)
# manage context
ctx = dict(self.env.context)
link_only = ctx.pop('link_only', False)
action['context'] = ctx
link_only = ctx.pop("link_only", False)
action["context"] = ctx
# manage domain
domain = action.get('domain') or []
domain = action.get("domain") or []
if isinstance(domain, str):
domain = eval(domain)
if len(domain) > 1:
domain = AND([['|', ('partner_id', '=', self.id), ('email', 'ilike', self.email)], normalize_domain(domain)])
domain = AND(
[
["|", ("partner_id", "=", self.id), ("email", "ilike", self.email)],
normalize_domain(domain),
]
)
else:
domain = ['|', ('partner_id', '=', self.id), ('email', 'ilike', self.email)]
domain = ["|", ("partner_id", "=", self.id), ("email", "ilike", self.email)]
if link_only:
if len(domain) > 1:
domain = AND([[('type', '=', 'link')], normalize_domain(domain)])
domain = AND([[("type", "=", "link")], normalize_domain(domain)])
else:
domain = [('type', '=', 'link')]
action['domain'] = domain
domain = [("type", "=", "link")]
action["domain"] = domain
# return updated action
return action
# ONCHANGES
@api.onchange('email')
@api.onchange("email")
def onchange_email(self):
self.ensure_one()
if isinstance(self._origin.id, int):

55
survey_question_duplicate/__manifest__.py

@ -1,32 +1,37 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey question duplicate',
'version': '1.0.0',
'summary': """
"name": "Survey question duplicate",
"version": "1.0.0",
"summary": """
This module adds a \"Copy\" button in question lines on survey page form, only in edit mode.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com/',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'views/survey_page.xml',
"data": [
"views/survey_page.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': ['static/description/survey.jpg'],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

57
survey_select_input/__manifest__.py

@ -1,33 +1,38 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey answer selection',
'version': '1.0.0',
'summary': """
"name": "Survey answer selection",
"version": "1.0.0",
"summary": """
This module adds the mossibility to select some of the surveys answers.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'views/survey_survey.xml',
'views/survey_user_input.xml',
"data": [
"views/survey_survey.xml",
"views/survey_user_input.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

55
survey_template/__manifest__.py

@ -1,32 +1,37 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
'name': 'Survey template',
'version': '1.0.0',
'summary': """
"name": "Survey template",
"version": "1.0.0",
"summary": """
This module adds templating feature on surveys and their own menu item.
""",
'description': """ """,
'author': 'Sudokeys',
'website': 'http://www.sudokeys.com',
'license': 'AGPL-3',
'category': 'Marketing',
'depends': [
'survey',
"description": """ """,
"author": "RemiFr82",
"contributors": "",
"website": "https://remifr82.me",
"license": "LGPL-3",
"category": "Marketing",
# "price": 0,
# "currency": "EUR",
"application": False,
"installable": True,
"auto_install": False,
"pre_init_hook": "",
"post_init_hook": "",
"uninstall_hook": "",
"excludes": [],
"external_dependencies": [],
"depends": [
"survey",
],
'data': [
'views/survey_survey.xml',
"data": [
"views/survey_survey.xml",
],
'demo': [],
'auto_install': False,
'external_dependencies': [],
'application': False,
'css': [],
'images': [],
'js': [],
'installable': True,
'maintainer': 'Sudokeys',
'pre_init_hook': '',
'post_init_hook': '',
'uninstall_hook': '',
"css": [],
"images": [],
"js": [],
"test": [],
"demo": [],
"maintainer": "RemiFr82",
}

56
survey_template/models/survey_survey.py

@ -3,18 +3,18 @@ from odoo.exceptions import UserError
class SurveySurvey(models.Model):
_inherit = 'survey.survey'
_inherit = "survey.survey"
is_template = fields.Boolean(string="Is a template", default=False, copy=False)
@api.multi
def copy_data(self, default=None):
data = super(SurveySurvey, self).copy_data(default)[0]
title = isinstance(default, dict) and default.get('title', False) or False
title = isinstance(default, dict) and default.get("title", False) or False
if title:
data['title'] = title
elif _(" (Template)") in data['title']:
data['title'] = data['title'].replace(_(" (Template)"), "")
data["title"] = title
elif _(" (Template)") in data["title"]:
data["title"] = data["title"].replace(_(" (Template)"), "")
return [data]
# ACTIONS
@ -23,43 +23,55 @@ class SurveySurvey(models.Model):
def create_template_from_survey(self, default={}):
self.ensure_one()
if self.is_template:
raise UserError(_("You should use the \"Copy\" secondary action to duplicate a survey template."))
default.update({'is_template': True})
raise UserError(
_(
'You should use the "Copy" secondary action to duplicate a survey template.'
)
)
default.update({"is_template": True})
new_survey = self.copy(default=default)
return {
'type': 'ir.actions.act_window',
'res_model': 'survey.survey',
'view_type': 'form',
'view_mode': 'form',
'target': 'current',
'res_id': new_survey.id,
"type": "ir.actions.act_window",
"res_model": "survey.survey",
"view_type": "form",
"view_mode": "form",
"target": "current",
"res_id": new_survey.id,
}
@api.multi
def create_survey_from_template(self, default={}):
self.ensure_one()
if not self.is_template:
raise UserError(_("You should use the \"Copy\" secondary action to duplicate a non-template survey."))
raise UserError(
_(
'You should use the "Copy" secondary action to duplicate a non-template survey.'
)
)
new_survey = self.copy(default=default)
return {
'type': 'ir.actions.act_window',
'res_model': 'survey.survey',
'view_type': 'form',
'view_mode': 'form',
'target': 'current',
'res_id': new_survey.id,
"type": "ir.actions.act_window",
"res_model": "survey.survey",
"view_type": "form",
"view_mode": "form",
"target": "current",
"res_id": new_survey.id,
}
@api.multi
def action_send_survey(self):
self.ensure_one()
if self.is_template:
raise UserError(_("You cannot send a template survey, create a new survey from this template and you'll be able to share it."))
raise UserError(
_(
"You cannot send a template survey, create a new survey from this template and you'll be able to share it."
)
)
return super(SurveySurvey, self).action_send_survey()
# ONCHANGES
@api.onchange('is_template')
@api.onchange("is_template")
def onchange_is_template(self):
if self.title:
if self.is_template:

Loading…
Cancel
Save