diff --git a/survey_custom_matrix/__manifest__.py b/survey_custom_matrix/__manifest__.py index 56191a6..7dd4b5b 100644 --- a/survey_custom_matrix/__manifest__.py +++ b/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", } diff --git a/survey_custom_matrix/controllers/__init__.py b/survey_custom_matrix/controllers/__init__.py index 757b12a..51363d8 100644 --- a/survey_custom_matrix/controllers/__init__.py +++ b/survey_custom_matrix/controllers/__init__.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -from . import main +from . import survey diff --git a/survey_custom_matrix/controllers/main.py b/survey_custom_matrix/controllers/main.py deleted file mode 100644 index c78176a..0000000 --- a/survey_custom_matrix/controllers/main.py +++ /dev/null @@ -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//', - '/survey/prefill///'], - 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) diff --git a/survey_custom_matrix/controllers/survey.py b/survey_custom_matrix/controllers/survey.py new file mode 100644 index 0000000..1c7cd87 --- /dev/null +++ b/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//', + '/survey/prefill///', + ], + 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) diff --git a/survey_custom_matrix/models/survey_label.py b/survey_custom_matrix/models/survey_label.py index cf54499..aea02a8 100644 --- a/survey_custom_matrix/models/survey_label.py +++ b/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") diff --git a/survey_custom_matrix/models/survey_label_value.py b/survey_custom_matrix/models/survey_label_value.py index 796eea0..11cfaee 100644 --- a/survey_custom_matrix/models/survey_label_value.py +++ b/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") diff --git a/survey_custom_matrix/models/survey_question.py b/survey_custom_matrix/models/survey_question.py index 08eae02..b24fceb 100644 --- a/survey_custom_matrix/models/survey_question.py +++ b/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 diff --git a/survey_custom_matrix/models/survey_user_input_line.py b/survey_custom_matrix/models/survey_user_input_line.py index ebe13b5..a0ff2b1 100644 --- a/survey_custom_matrix/models/survey_user_input_line.py +++ b/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 diff --git a/survey_deadline_autoclose/__manifest__.py b/survey_deadline_autoclose/__manifest__.py index aaed471..36705fa 100644 --- a/survey_deadline_autoclose/__manifest__.py +++ b/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", } diff --git a/survey_deadline_autoclose/data/ir_cron.xml b/survey_deadline_autoclose/data/ir_cron.xml index b3bf025..6a2e338 100644 --- a/survey_deadline_autoclose/data/ir_cron.xml +++ b/survey_deadline_autoclose/data/ir_cron.xml @@ -7,12 +7,12 @@ Close expired surveys code - model.action_close_survey() + model.with_context(cron=True).close_deadline_survey() 1 days - + -1 diff --git a/survey_deadline_autoclose/i18n/fr.po b/survey_deadline_autoclose/i18n/fr.po index eeb4df7..09fb9ee 100644 --- a/survey_deadline_autoclose/i18n/fr.po +++ b/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é." diff --git a/survey_deadline_autoclose/models/survey_survey.py b/survey_deadline_autoclose/models/survey_survey.py index 736f4d8..0f6ff59 100644 --- a/survey_deadline_autoclose/models/survey_survey.py +++ b/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: diff --git a/survey_deadline_autoclose/views/survey_survey.xml b/survey_deadline_autoclose/views/survey_survey.xml index ddda35d..31ac0e5 100644 --- a/survey_deadline_autoclose/views/survey_survey.xml +++ b/survey_deadline_autoclose/views/survey_survey.xml @@ -72,7 +72,7 @@ - + diff --git a/survey_description/__manifest__.py b/survey_description/__manifest__.py index c04a129..a683ec1 100644 --- a/survey_description/__manifest__.py +++ b/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", } diff --git a/survey_description/i18n/fr.po b/survey_description/i18n/fr.po index ca2eff9..19fed8b 100644 --- a/survey_description/i18n/fr.po +++ b/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 diff --git a/survey_input_attachment/__manifest__.py b/survey_input_attachment/__manifest__.py index ce11383..376628a 100644 --- a/survey_input_attachment/__manifest__.py +++ b/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", } diff --git a/survey_input_attachment/i18n/fr.po b/survey_input_attachment/i18n/fr.po index d913a30..fdfc2af 100644 --- a/survey_input_attachment/i18n/fr.po +++ b/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 diff --git a/survey_input_attachment/models/survey_question.py b/survey_input_attachment/models/survey_question.py index 6f2d02a..6a53ac1 100644 --- a/survey_input_attachment/models/survey_question.py +++ b/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 diff --git a/survey_input_attachment/models/survey_user_input_line.py b/survey_input_attachment/models/survey_user_input_line.py index d028325..7c6d411 100644 --- a/survey_input_attachment/models/survey_user_input_line.py +++ b/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: diff --git a/survey_input_dates/__manifest__.py b/survey_input_dates/__manifest__.py index 3c0a602..63dae3a 100644 --- a/survey_input_dates/__manifest__.py +++ b/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", } diff --git a/survey_input_dates/i18n/fr.po b/survey_input_dates/i18n/fr.po index 957580e..503c3bf 100644 --- a/survey_input_dates/i18n/fr.po +++ b/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" diff --git a/survey_input_dates/models/survey_user_input.py b/survey_input_dates/models/survey_user_input.py index 1c92fbd..57bdb7d 100644 --- a/survey_input_dates/models/survey_user_input.py +++ b/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) diff --git a/survey_input_dates/views/survey_user_input.xml b/survey_input_dates/views/survey_user_input.xml index b35704a..7d71043 100644 --- a/survey_input_dates/views/survey_user_input.xml +++ b/survey_input_dates/views/survey_user_input.xml @@ -11,6 +11,7 @@ + @@ -25,6 +26,7 @@ + @@ -39,6 +41,7 @@ + diff --git a/survey_input_odoo_debrand/__manifest__.py b/survey_input_odoo_debrand/__manifest__.py index a81d855..8e87495 100644 --- a/survey_input_odoo_debrand/__manifest__.py +++ b/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", } diff --git a/survey_input_template_custom/__manifest__.py b/survey_input_template_custom/__manifest__.py index 98938a2..858a006 100644 --- a/survey_input_template_custom/__manifest__.py +++ b/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", } diff --git a/survey_link_input_ratio/__manifest__.py b/survey_link_input_ratio/__manifest__.py index 2c1be54..97fda44 100644 --- a/survey_link_input_ratio/__manifest__.py +++ b/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", } diff --git a/survey_link_input_ratio/models/survey_survey.py b/survey_link_input_ratio/models/survey_survey.py index 0d141da..cac7a50 100644 --- a/survey_link_input_ratio/models/survey_survey.py +++ b/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 diff --git a/survey_link_input_ratio/views/survey_survey.xml b/survey_link_input_ratio/views/survey_survey.xml index 183ccfb..7504914 100644 --- a/survey_link_input_ratio/views/survey_survey.xml +++ b/survey_link_input_ratio/views/survey_survey.xml @@ -27,28 +27,4 @@ - - - - diff --git a/survey_partner_input/__manifest__.py b/survey_partner_input/__manifest__.py index a9d9adf..3cf947e 100644 --- a/survey_partner_input/__manifest__.py +++ b/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", } diff --git a/survey_partner_input/models/res_partner.py b/survey_partner_input/models/res_partner.py index 323b76b..f09beee 100644 --- a/survey_partner_input/models/res_partner.py +++ b/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): diff --git a/survey_question_duplicate/__manifest__.py b/survey_question_duplicate/__manifest__.py index 752cec4..7e4aff5 100644 --- a/survey_question_duplicate/__manifest__.py +++ b/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", } diff --git a/survey_select_input/__manifest__.py b/survey_select_input/__manifest__.py index 25ea2d1..e634d2e 100644 --- a/survey_select_input/__manifest__.py +++ b/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", } diff --git a/survey_template/__manifest__.py b/survey_template/__manifest__.py index a7c6f24..4b49c12 100644 --- a/survey_template/__manifest__.py +++ b/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", } diff --git a/survey_template/models/survey_survey.py b/survey_template/models/survey_survey.py index 9d4d388..13413ee 100644 --- a/survey_template/models/survey_survey.py +++ b/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: