[MIG] survey: migrate into new api
This commit is contained in:
@@ -4,30 +4,26 @@
|
||||
import json
|
||||
import logging
|
||||
import werkzeug
|
||||
import werkzeug.utils
|
||||
from datetime import datetime
|
||||
from math import ceil
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT as DTF, ustr
|
||||
|
||||
from odoo import fields, http, SUPERUSER_ID
|
||||
from odoo.http import request
|
||||
from odoo.tools import ustr
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WebsiteSurvey(http.Controller):
|
||||
# HELPER METHODS #
|
||||
|
||||
## HELPER METHODS ##
|
||||
|
||||
def _check_bad_cases(self, cr, uid, request, survey_obj, survey, user_input_obj, token=None, context=None):
|
||||
def _check_bad_cases(self, survey, token=None):
|
||||
# In case of bad survey, redirect to surveys list
|
||||
if survey_obj.exists(cr, SUPERUSER_ID, survey.id, context=context) == []:
|
||||
if not survey.sudo().exists():
|
||||
return werkzeug.utils.redirect("/survey/")
|
||||
|
||||
# In case of auth required, block public user
|
||||
if survey.auth_required and uid == request.website.user_id.id:
|
||||
if survey.auth_required and request.env.user == request.website.user_id:
|
||||
return request.website.render("survey.auth_required", {'survey': survey, 'token': token})
|
||||
|
||||
# In case of non open surveys
|
||||
@@ -41,16 +37,16 @@ class WebsiteSurvey(http.Controller):
|
||||
# Everything seems to be ok
|
||||
return None
|
||||
|
||||
def _check_deadline(self, cr, uid, user_input, context=None):
|
||||
def _check_deadline(self, user_input):
|
||||
'''Prevent opening of the survey if the deadline has turned out
|
||||
|
||||
! This will NOT disallow access to users who have already partially filled the survey !'''
|
||||
if user_input.deadline:
|
||||
dt_deadline = datetime.strptime(user_input.deadline, DTF)
|
||||
deadline = user_input.deadline
|
||||
if deadline:
|
||||
dt_deadline = fields.Datetime.from_string(deadline)
|
||||
dt_now = datetime.now()
|
||||
if dt_now > dt_deadline: # survey is not open anymore
|
||||
return request.website.render("survey.notopen")
|
||||
|
||||
return None
|
||||
|
||||
## ROUTES HANDLERS ##
|
||||
@@ -60,41 +56,34 @@ class WebsiteSurvey(http.Controller):
|
||||
'/survey/start/<model("survey.survey"):survey>/<string:token>'],
|
||||
type='http', auth='public', website=True)
|
||||
def start_survey(self, survey, token=None, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
survey_obj = request.registry['survey.survey']
|
||||
user_input_obj = request.registry['survey.user_input']
|
||||
UserInput = request.env['survey.user_input']
|
||||
|
||||
# Test mode
|
||||
if token and token == "phantom":
|
||||
_logger.info("[survey] Phantom mode")
|
||||
user_input_id = user_input_obj.create(cr, uid, {'survey_id': survey.id, 'test_entry': True}, context=context)
|
||||
user_input = user_input_obj.browse(cr, uid, [user_input_id], context=context)[0]
|
||||
user_input = UserInput.create({'survey_id': survey.id, 'test_entry': True})
|
||||
data = {'survey': survey, 'page': None, 'token': user_input.token}
|
||||
return request.website.render('survey.survey_init', data)
|
||||
# END Test mode
|
||||
|
||||
# Controls if the survey can be displayed
|
||||
errpage = self._check_bad_cases(cr, uid, request, survey_obj, survey, user_input_obj, token=token, context=context)
|
||||
errpage = self._check_bad_cases(survey, token=token)
|
||||
if errpage:
|
||||
return errpage
|
||||
|
||||
# Manual surveying
|
||||
if not token:
|
||||
vals = {'survey_id': survey.id}
|
||||
if request.website.user_id.id != uid:
|
||||
vals['partner_id'] = request.registry['res.users'].browse(cr, uid, uid, context=context).partner_id.id
|
||||
user_input_id = user_input_obj.create(cr, uid, vals, context=context)
|
||||
user_input = user_input_obj.browse(cr, uid, [user_input_id], context=context)[0]
|
||||
if request.website.user_id != request.env.user:
|
||||
vals['partner_id'] = request.env.user.partner_id.id
|
||||
user_input = UserInput.create(vals)
|
||||
else:
|
||||
try:
|
||||
user_input_id = user_input_obj.search(cr, SUPERUSER_ID, [('token', '=', token)], context=context)[0]
|
||||
except IndexError: # Invalid token
|
||||
user_input = UserInput.sudo().search([('token', '=', token)], limit=1)
|
||||
if not user_input:
|
||||
return request.website.render("website.403")
|
||||
else:
|
||||
user_input = user_input_obj.browse(cr, SUPERUSER_ID, [user_input_id], context=context)[0]
|
||||
|
||||
# Do not open expired survey
|
||||
errpage = self._check_deadline(cr, uid, user_input, context=context)
|
||||
errpage = self._check_deadline(user_input)
|
||||
if errpage:
|
||||
return errpage
|
||||
|
||||
@@ -111,32 +100,29 @@ class WebsiteSurvey(http.Controller):
|
||||
type='http', auth='public', website=True)
|
||||
def fill_survey(self, survey, token, prev=None, **post):
|
||||
'''Display and validates a survey'''
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
survey_obj = request.registry['survey.survey']
|
||||
user_input_obj = request.registry['survey.user_input']
|
||||
Survey = request.env['survey.survey']
|
||||
UserInput = request.env['survey.user_input']
|
||||
|
||||
# Controls if the survey can be displayed
|
||||
errpage = self._check_bad_cases(cr, uid, request, survey_obj, survey, user_input_obj, context=context)
|
||||
errpage = self._check_bad_cases(survey)
|
||||
if errpage:
|
||||
return errpage
|
||||
|
||||
# Load the user_input
|
||||
try:
|
||||
user_input_id = user_input_obj.search(cr, SUPERUSER_ID, [('token', '=', token)])[0]
|
||||
user_input = UserInput.sudo().search([('token', '=', token)], limit=1)
|
||||
except IndexError: # Invalid token
|
||||
return request.website.render("website.403")
|
||||
else:
|
||||
user_input = user_input_obj.browse(cr, SUPERUSER_ID, [user_input_id], context=context)[0]
|
||||
|
||||
# Do not display expired survey (even if some pages have already been
|
||||
# displayed -- There's a time for everything!)
|
||||
errpage = self._check_deadline(cr, uid, user_input, context=context)
|
||||
errpage = self._check_deadline(user_input)
|
||||
if errpage:
|
||||
return errpage
|
||||
|
||||
# Select the right page
|
||||
if user_input.state == 'new': # First page
|
||||
page, page_nr, last = survey_obj.next_page(cr, uid, user_input, 0, go_back=False, context=context)
|
||||
page, page_nr, last = Survey.next_page(user_input, 0, go_back=False)
|
||||
data = {'survey': survey, 'page': page, 'page_nr': page_nr, 'token': user_input.token}
|
||||
if last:
|
||||
data.update({'last': True})
|
||||
@@ -147,11 +133,11 @@ class WebsiteSurvey(http.Controller):
|
||||
'user_input': user_input})
|
||||
elif user_input.state == 'skip':
|
||||
flag = (True if prev and prev == 'prev' else False)
|
||||
page, page_nr, last = survey_obj.next_page(cr, uid, user_input, user_input.last_displayed_page_id.id, go_back=flag, context=context)
|
||||
page, page_nr, last = Survey.next_page(user_input, user_input.last_displayed_page_id.id, go_back=flag)
|
||||
|
||||
#special case if you click "previous" from the last page, then leave the survey, then reopen it from the URL, avoid crash
|
||||
if not page:
|
||||
page, page_nr, last = survey_obj.next_page(cr, uid, user_input, user_input.last_displayed_page_id.id, go_back=True, context=context)
|
||||
page, page_nr, last = Survey.next_page(user_input, user_input.last_displayed_page_id.id, go_back=True)
|
||||
|
||||
data = {'survey': survey, 'page': page, 'page_nr': page_nr, 'token': user_input.token}
|
||||
if last:
|
||||
@@ -165,16 +151,14 @@ class WebsiteSurvey(http.Controller):
|
||||
'/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):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
user_input_line_obj = request.registry['survey.user_input_line']
|
||||
UserInputLine = request.env['survey.user_input_line']
|
||||
ret = {}
|
||||
|
||||
# Fetch previous answers
|
||||
if page:
|
||||
ids = user_input_line_obj.search(cr, SUPERUSER_ID, [('user_input_id.token', '=', token), ('page_id', '=', page.id)], context=context)
|
||||
previous_answers = UserInputLine.sudo().search([('user_input_id.token', '=', token), ('page_id', '=', page.id)])
|
||||
else:
|
||||
ids = user_input_line_obj.search(cr, SUPERUSER_ID, [('user_input_id.token', '=', token)], context=context)
|
||||
previous_answers = user_input_line_obj.browse(cr, uid, ids, context=context)
|
||||
previous_answers = UserInputLine.sudo().search([('user_input_id.token', '=', token)])
|
||||
|
||||
# Return non empty answers in a JSON compatible format
|
||||
for answer in previous_answers:
|
||||
@@ -199,7 +183,7 @@ class WebsiteSurvey(http.Controller):
|
||||
answer_tag = "%s_%s" % (answer_tag, answer.value_suggested_row.id)
|
||||
answer_value = answer.value_suggested.id
|
||||
if answer_value:
|
||||
dict_soft_update(ret, answer_tag, 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)
|
||||
@@ -208,13 +192,10 @@ class WebsiteSurvey(http.Controller):
|
||||
@http.route(['/survey/scores/<model("survey.survey"):survey>/<string:token>'],
|
||||
type='http', auth='public', website=True)
|
||||
def get_scores(self, survey, token, page=None, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
user_input_line_obj = request.registry['survey.user_input_line']
|
||||
ret = {}
|
||||
|
||||
# Fetch answers
|
||||
ids = user_input_line_obj.search(cr, SUPERUSER_ID, [('user_input_id.token', '=', token)], context=context)
|
||||
previous_answers = user_input_line_obj.browse(cr, uid, ids, context=context)
|
||||
previous_answers = request.env['survey.user_input_line'].sudo().search([('user_input_id.token', '=', token)])
|
||||
|
||||
# Compute score for each question
|
||||
for answer in previous_answers:
|
||||
@@ -223,50 +204,42 @@ class WebsiteSurvey(http.Controller):
|
||||
return json.dumps(ret)
|
||||
|
||||
# AJAX submission of a page
|
||||
@http.route(['/survey/submit/<model("survey.survey"):survey>'],
|
||||
type='http', methods=['POST'], auth='public', website=True)
|
||||
@http.route(['/survey/submit/<model("survey.survey"):survey>'], type='http', methods=['POST'], auth='public', website=True)
|
||||
def submit(self, survey, **post):
|
||||
_logger.debug('Incoming data: %s', post)
|
||||
page_id = int(post['page_id'])
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
survey_obj = request.registry['survey.survey']
|
||||
questions_obj = request.registry['survey.question']
|
||||
questions_ids = questions_obj.search(cr, uid, [('page_id', '=', page_id)], context=context)
|
||||
questions = questions_obj.browse(cr, uid, questions_ids, context=context)
|
||||
questions = request.env['survey.question'].search([('page_id', '=', page_id)])
|
||||
|
||||
# Answer validation
|
||||
errors = {}
|
||||
for question in questions:
|
||||
answer_tag = "%s_%s_%s" % (survey.id, page_id, question.id)
|
||||
errors.update(questions_obj.validate_question(cr, uid, question, post, answer_tag, context=context))
|
||||
errors.update(question.validate_question(post, answer_tag))
|
||||
|
||||
ret = {}
|
||||
if (len(errors) != 0):
|
||||
if len(errors):
|
||||
# Return errors messages to webpage
|
||||
ret['errors'] = errors
|
||||
else:
|
||||
# Store answers into database
|
||||
user_input_obj = request.registry['survey.user_input']
|
||||
|
||||
user_input_line_obj = request.registry['survey.user_input_line']
|
||||
try:
|
||||
user_input_id = user_input_obj.search(cr, SUPERUSER_ID, [('token', '=', post['token'])], context=context)[0]
|
||||
user_input = request.env['survey.user_input'].sudo().search([('token', '=', post['token'])], limit=1)
|
||||
except KeyError: # Invalid token
|
||||
return request.website.render("website.403")
|
||||
user_input = user_input_obj.browse(cr, SUPERUSER_ID, user_input_id, context=context)
|
||||
user_id = uid if user_input.type != 'link' else SUPERUSER_ID
|
||||
user_id = request.env.user.id if user_input.type != 'link' else SUPERUSER_ID
|
||||
|
||||
for question in questions:
|
||||
answer_tag = "%s_%s_%s" % (survey.id, page_id, question.id)
|
||||
user_input_line_obj.save_lines(cr, user_id, user_input_id, question, post, answer_tag, context=context)
|
||||
request.env['survey.user_input_line'].sudo(user=user_id).save_lines(user_input.id, question, post, answer_tag)
|
||||
|
||||
go_back = post['button_submit'] == 'previous'
|
||||
next_page, _, last = survey_obj.next_page(cr, uid, user_input, page_id, go_back=go_back, context=context)
|
||||
next_page, _, last = request.env['survey.survey'].next_page(user_input, page_id, go_back=go_back)
|
||||
vals = {'last_displayed_page_id': page_id}
|
||||
if next_page is None and not go_back:
|
||||
vals.update({'state': 'done'})
|
||||
else:
|
||||
vals.update({'state': 'skip'})
|
||||
user_input_obj.write(cr, user_id, user_input_id, vals, context=context)
|
||||
user_input.sudo(user=user_id).write(vals)
|
||||
ret['redirect'] = '/survey/fill/%s/%s' % (survey.id, post['token'])
|
||||
if go_back:
|
||||
ret['redirect'] += '/prev'
|
||||
@@ -289,12 +262,11 @@ class WebsiteSurvey(http.Controller):
|
||||
type='http', auth='user', website=True)
|
||||
def survey_reporting(self, survey, token=None, **post):
|
||||
'''Display survey Results & Statistics for given survey.'''
|
||||
result_template ='survey.result'
|
||||
result_template = 'survey.result'
|
||||
current_filters = []
|
||||
filter_display_data = []
|
||||
filter_finish = False
|
||||
|
||||
survey_obj = request.registry['survey.survey']
|
||||
if not survey.user_input_ids or not [input_id.id for input_id in survey.user_input_ids if input_id.state != 'new']:
|
||||
result_template = 'survey.no_result'
|
||||
if 'finished' in post:
|
||||
@@ -302,8 +274,8 @@ class WebsiteSurvey(http.Controller):
|
||||
filter_finish = True
|
||||
if post or filter_finish:
|
||||
filter_data = self.get_filter_data(post)
|
||||
current_filters = survey_obj.filter_input_ids(request.cr, request.uid, survey, filter_data, filter_finish, context=request.context)
|
||||
filter_display_data = survey_obj.get_filter_display_data(request.cr, request.uid, filter_data, context=request.context)
|
||||
current_filters = survey.filter_input_ids(filter_data, filter_finish)
|
||||
filter_display_data = survey.get_filter_display_data(filter_data)
|
||||
return request.website.render(result_template,
|
||||
{'survey': survey,
|
||||
'survey_dict': self.prepare_result_dict(survey, current_filters),
|
||||
@@ -350,15 +322,21 @@ class WebsiteSurvey(http.Controller):
|
||||
# filter_finish: boolean => only finished surveys or not
|
||||
#
|
||||
|
||||
def prepare_result_dict(self,survey, current_filters=None):
|
||||
def prepare_result_dict(self, survey, current_filters=None):
|
||||
"""Returns dictionary having values for rendering template"""
|
||||
current_filters = current_filters if current_filters else []
|
||||
survey_obj = request.registry['survey.survey']
|
||||
Survey = request.env['survey.survey']
|
||||
result = {'page_ids': []}
|
||||
for page in survey.page_ids:
|
||||
page_dict = {'page': page, 'question_ids': []}
|
||||
for question in page.question_ids:
|
||||
question_dict = {'question':question, 'input_summary':survey_obj.get_input_summary(request.cr, request.uid, question, current_filters, context=request.context), 'prepare_result':survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context), 'graph_data': self.get_graph_data(question, current_filters)}
|
||||
question_dict = {
|
||||
'question': question,
|
||||
'input_summary': Survey.get_input_summary(question, current_filters),
|
||||
'prepare_result': Survey.prepare_result(question, current_filters),
|
||||
'graph_data': self.get_graph_data(question, current_filters),
|
||||
}
|
||||
|
||||
page_dict['question_ids'].append(question_dict)
|
||||
result['page_ids'].append(page_dict)
|
||||
return result
|
||||
@@ -384,28 +362,19 @@ class WebsiteSurvey(http.Controller):
|
||||
'''Returns formatted data required by graph library on basis of filter'''
|
||||
# TODO refactor this terrible method and merge it with prepare_result_dict
|
||||
current_filters = current_filters if current_filters else []
|
||||
survey_obj = request.registry['survey.survey']
|
||||
Survey = request.env['survey.survey']
|
||||
result = []
|
||||
if question.type == 'multiple_choice':
|
||||
result.append({'key': ustr(question.question),
|
||||
'values': survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context)['answers']
|
||||
'values': Survey.prepare_result(question, current_filters)['answers']
|
||||
})
|
||||
if question.type == 'simple_choice':
|
||||
result = survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context)['answers']
|
||||
result = Survey.prepare_result(question, current_filters)['answers']
|
||||
if question.type == 'matrix':
|
||||
data = survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context)
|
||||
data = Survey.prepare_result(question, current_filters)
|
||||
for answer in data['answers']:
|
||||
values = []
|
||||
for row in data['rows']:
|
||||
values.append({'text': data['rows'].get(row), 'count': data['result'].get((row, answer))})
|
||||
result.append({'key': data['answers'].get(answer), 'values': values})
|
||||
return json.dumps(result)
|
||||
|
||||
def dict_soft_update(dictionary, key, value):
|
||||
''' Insert the pair <key>: <value> into the <dictionary>. If <key> is
|
||||
already present, this function will append <value> to the list of
|
||||
existing data (instead of erasing it) '''
|
||||
if key in dictionary:
|
||||
dictionary[key].append(value)
|
||||
else:
|
||||
dictionary.update({key: [value]})
|
||||
|
||||
+562
-728
File diff suppressed because it is too large
Load Diff
@@ -7,10 +7,10 @@ from collections import Counter
|
||||
from itertools import product
|
||||
from urlparse import urljoin
|
||||
|
||||
from openerp import _
|
||||
from openerp.exceptions import UserError
|
||||
from openerp.tests.common import TransactionCase
|
||||
from openerp.addons.website.models.website import slug
|
||||
from odoo import _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.addons.website.models.website import slug
|
||||
|
||||
|
||||
class TestSurvey(TransactionCase):
|
||||
@@ -31,19 +31,11 @@ class TestSurvey(TransactionCase):
|
||||
'name': 'Wout Janssens', 'login': 'Wout', 'alias_name': 'wout', 'email': 'wout.janssens@example.com',
|
||||
'groups_id': [(6, 0, [self.ref('base.group_public')])]})
|
||||
|
||||
self.Partner = self.env['res.partner']
|
||||
self.Survey = self.env['survey.survey']
|
||||
self.Question = self.env['survey.question']
|
||||
self.Stage = self.env['survey.stage']
|
||||
self.SurveyMailMessage = self.env['survey.mail.compose.message']
|
||||
self.UserInput = self.env['survey.user_input']
|
||||
self.UserInputLine = self.env['survey.user_input_line']
|
||||
|
||||
self.survey1 = self.Survey.sudo(self.survey_manager).create({'title': "S0", 'page_ids': [(0, 0, {'title': "P0"})]})
|
||||
self.survey1 = self.env['survey.survey'].sudo(self.survey_manager).create({'title': "S0", 'page_ids': [(0, 0, {'title': "P0"})]})
|
||||
self.page1 = self.survey1.page_ids[0]
|
||||
|
||||
def test_00_create_minimal_survey(self):
|
||||
question = self.Question.sudo(self.survey_manager).create({'page_id': self.page1.id, 'question': 'Q0'})
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({'page_id': self.page1.id, 'question': 'Q0'})
|
||||
self.assertEqual(self.survey1.title, "S0", msg="Title of the survey is somehow modified.")
|
||||
self.assertEqual(len(self.survey1.page_ids), 1, msg="Additional Pages are linked with the survey after creation.")
|
||||
self.assertEqual(self.page1.title, "P0", msg="Title of the page is somehow modified.")
|
||||
@@ -51,88 +43,88 @@ class TestSurvey(TransactionCase):
|
||||
self.assertEqual(question.question, "Q0", msg="Title of the Question is somehow modified.")
|
||||
|
||||
def test_01_question_type_validation_save_line_function(self):
|
||||
for (question_type, text) in self.Question._columns['type'].selection:
|
||||
for (question_type, text) in self.env['survey.question']._columns['type'].selection:
|
||||
# Each question ype must have validation function.
|
||||
self.assertTrue(hasattr(self.Question, 'validate_' + question_type), msg="Question must have a validation method in\
|
||||
self.assertTrue(hasattr(self.env['survey.question'], 'validate_' + question_type), msg="Question must have a validation method in\
|
||||
the form of 'validate_' followed by the name of the type.")
|
||||
|
||||
# Survey Input Lines must have validation function for each line.
|
||||
self.assertTrue(hasattr(self.UserInputLine, 'save_line_' + question_type), msg="Inputline must have Save method in \
|
||||
self.assertTrue(hasattr(self.env['survey.user_input_line'], 'save_line_' + question_type), msg="Inputline must have Save method in \
|
||||
the form of 'save_line_' followed by the name of the type.")
|
||||
|
||||
def test_02_question_answer_required(self):
|
||||
for (question_type, text) in self.Question._columns['type'].selection:
|
||||
for (question_type, text) in self.env['survey.question']._columns['type'].selection:
|
||||
# Blank value of field is not accepted for mandatory questions.
|
||||
if question_type == 'multiple_choice':
|
||||
question = self.Question.sudo(self.survey_manager).create({
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q0', 'type': 'multiple_choice',
|
||||
'constr_mandatory': True, 'constr_error_msg': 'Error',
|
||||
'labels_ids': [(0, 0, {'value': "MChoice0", "quizz_mark": 0}), (0, 0, {'value': "MChoice1", "quizz_mark": 0})]})
|
||||
|
||||
elif question_type == 'matrix':
|
||||
question = self.Question.sudo(self.survey_manager).create({
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q0', 'type': 'matrix', 'matrix_subtype': 'simple',
|
||||
'constr_mandatory': True, 'constr_error_msg': 'Error',
|
||||
'labels_ids': [(0, 0, {'value': "Column0", "quizz_mark": 0}), (0, 0, {'value': "Column1", "quizz_mark": 0})],
|
||||
'labels_ids_2': [(0, 0, {'value': "Row0", "quizz_mark": 0}), (0, 0, {'value': "Row1", "quizz_mark": 0})]})
|
||||
|
||||
else:
|
||||
question = self.Question.sudo(self.survey_manager).create({
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q0', 'type': question_type, 'constr_mandatory': True, 'constr_error_msg': 'Error'})
|
||||
answer_tag = '%s_%s_%s' % (self.survey1.id, self.page1.id, question.id)
|
||||
self.assertDictEqual({answer_tag: "Error"}, self.Question.validate_question(question, {answer_tag: ''}, answer_tag),
|
||||
self.assertDictEqual({answer_tag: "Error"}, question.validate_question({answer_tag: ''}, answer_tag),
|
||||
msg=("Validation function for type %s is unable to generate error if it is mandatory and answer is blank." % question_type))
|
||||
|
||||
def test_03_question_textbox(self):
|
||||
questions = [
|
||||
self.Question.sudo(self.survey_manager).create({
|
||||
self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q0', 'type': 'textbox', 'validation_email': True}),
|
||||
self.Question.sudo(self.survey_manager).create({
|
||||
self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q1', 'type': 'textbox', 'validation_required': True,
|
||||
'validation_length_min': 2, 'validation_length_max': 8, 'validation_error_msg': "Error"})]
|
||||
|
||||
results = [('test @ testcom', _('This answer must be an email address')), ('t', 'Error')]
|
||||
for i in range(len(questions)):
|
||||
answer_tag = '%s_%s_%s' % (self.survey1.id, self.page1.id, questions[i].id)
|
||||
self.assertEqual(self.Question.validate_question(questions[i], {answer_tag: results[i][0]}, answer_tag), {answer_tag: results[i][1]}, msg="\
|
||||
self.assertEqual(questions[i].validate_question({answer_tag: results[i][0]}, answer_tag), {answer_tag: results[i][1]}, msg="\
|
||||
Validation function for textbox is unable to notify if answer is violating the validation rules")
|
||||
|
||||
def test_04_question_numerical_box(self):
|
||||
question = self.Question.sudo(self.survey_manager).create({
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q0', 'type': 'numerical_box', 'validation_required': True,
|
||||
'validation_min_float_value': 2.1, 'validation_max_float_value': 3.0, 'validation_error_msg': "Error"})
|
||||
answer_tag = '%s_%s_%s' % (self.survey1.id, self.page1.id, question.id)
|
||||
results = [('aaa', _('This is not a number')), ('4.5', 'Error'), ('0.1', 'Error')]
|
||||
for i in range(len(results)):
|
||||
self.assertEqual(self.Question.validate_question(question, {answer_tag: results[i][0]}, answer_tag), {answer_tag: results[i][1]}, msg="\
|
||||
self.assertEqual(question.validate_question({answer_tag: results[i][0]}, answer_tag), {answer_tag: results[i][1]}, msg="\
|
||||
Validation function for type numerical_box is unable to notify if answer is violating the validation rules")
|
||||
|
||||
def test_05_question_datetime(self):
|
||||
question = self.Question.sudo(self.survey_manager).create({
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q0', 'type': 'datetime', 'validation_required': True,
|
||||
'validation_min_date': '2015-03-20 00:00:00', 'validation_max_date': '2015-03-25 00:00:00', 'validation_error_msg': "Error"})
|
||||
answer_tag = '%s_%s_%s' % (self.survey1.id, self.page1.id, question.id)
|
||||
results = [('2015-55-10', _('This is not a date/time')), ('2015-03-19 00:00:00', 'Error'), ('2015-03-26 00:00:00', 'Error')]
|
||||
for i in range(len(results)):
|
||||
self.assertEqual(self.Question.validate_question(question, {answer_tag: results[i][0]}, answer_tag), {answer_tag: results[i][1]}, msg="\
|
||||
self.assertEqual(question.validate_question({answer_tag: results[i][0]}, answer_tag), {answer_tag: results[i][1]}, msg="\
|
||||
Validation function for type datetime is unable to notify if answer is violating the validation rules")
|
||||
|
||||
def test_06_survey_sharing(self):
|
||||
# Case-1: Executing action with correct data.
|
||||
correct_survey = self.Survey.sudo(self.survey_manager).create({
|
||||
'title': "S0", 'stage_id': self.Stage.search([('sequence', '=', 1)]).id,
|
||||
correct_survey = self.env['survey.survey'].sudo(self.survey_manager).create({
|
||||
'title': "S0", 'stage_id': self.env['survey.stage'].search([('sequence', '=', 1)]).id,
|
||||
'page_ids': [(0, 0, {'title': "P0", 'question_ids': [(0, 0, {'question': "Q0", 'type': 'free_text'})]})]})
|
||||
action = correct_survey.action_send_survey()
|
||||
templates = self.env['ir.model.data'].get_object_reference('survey', 'email_template_survey')
|
||||
template_id = templates[1] if len(templates) > 0 else False
|
||||
ctx = dict(self.env.context)
|
||||
ctx.update({
|
||||
'default_model': 'survey.survey',
|
||||
'default_res_id': correct_survey.id,
|
||||
'default_survey_id': correct_survey.id,
|
||||
'default_use_template': bool(template_id),
|
||||
'default_template_id': template_id,
|
||||
'default_composition_mode': 'comment'})
|
||||
template = self.env.ref('survey.email_template_survey', raise_if_not_found=False)
|
||||
|
||||
ctx = dict(
|
||||
self.env.context,
|
||||
default_model='survey.survey',
|
||||
default_res_id=correct_survey.id,
|
||||
default_survey_id=correct_survey.id,
|
||||
default_use_template=bool(template),
|
||||
default_template_id=template and template.id or False,
|
||||
default_composition_mode='comment')
|
||||
|
||||
self.assertDictEqual(action, {
|
||||
'type': 'ir.actions.act_window',
|
||||
@@ -145,26 +137,26 @@ class TestSurvey(TransactionCase):
|
||||
|
||||
# Case-2: Executing action with incorrect data.
|
||||
surveys = [
|
||||
self.Survey.sudo(self.survey_manager).create({ # Survey without any page or question.
|
||||
self.env['survey.survey'].sudo(self.survey_manager).create({ # Survey without any page or question.
|
||||
'title': "Test survey"}),
|
||||
self.Survey.sudo(self.survey_manager).create({ # Closed Survey.
|
||||
'title': "S0", 'stage_id': self.Stage.search([('closed', '=', True)]).id, # Getting Closed stage id.
|
||||
self.env['survey.survey'].sudo(self.survey_manager).create({ # Closed Survey.
|
||||
'title': "S0", 'stage_id': self.env['survey.stage'].search([('closed', '=', True)]).id, # Getting Closed stage id.
|
||||
'page_ids': [(0, 0, {'title': "P0", 'question_ids': [(0, 0, {'question': "Q0", 'type': 'free_text'})]})]})]
|
||||
for survey in surveys:
|
||||
self.assertRaises(UserError, survey.action_send_survey)
|
||||
|
||||
def test_07_survey_email_message(self):
|
||||
# Case-1: Executing send_mail with correct data.
|
||||
partner = self.Partner.create({'name': 'Marie De Cock', 'email': 'marie.de.cock@gmail.com'})
|
||||
survey_mail_message = self.SurveyMailMessage.sudo(self.survey_manager).create({
|
||||
partner = self.env['res.partner'].create({'name': 'Marie De Cock', 'email': 'marie.de.cock@gmail.com'})
|
||||
survey_mail_message = self.env['survey.mail.compose.message'].sudo(self.survey_manager).create({
|
||||
'survey_id': self.survey1.id, 'public': 'email_public_link', 'body': '__URL__', 'partner_ids': [(4, partner.id)]})
|
||||
survey_mail_message.send_mail()
|
||||
|
||||
# Case-2: Executing send_mail with incorrect data.
|
||||
mail_messages = [
|
||||
self.SurveyMailMessage.sudo(self.survey_manager).create({ # Mail Message without __URL__ in body.
|
||||
self.env['survey.mail.compose.message'].sudo(self.survey_manager).create({ # Mail Message without __URL__ in body.
|
||||
'survey_id': self.survey1.id, 'public': 'email_public_link'}),
|
||||
self.SurveyMailMessage.sudo(self.survey_manager).create({ # Mail Message without recipents.
|
||||
self.env['survey.mail.compose.message'].sudo(self.survey_manager).create({ # Mail Message without recipents.
|
||||
'survey_id': self.survey1.id, 'public': 'email_public_link', 'body': "__URL__"})]
|
||||
for message in mail_messages:
|
||||
self.assertRaises(UserError, message.send_mail)
|
||||
@@ -198,20 +190,20 @@ class TestSurvey(TransactionCase):
|
||||
self.assertEqual(url_html % ('/' + url), getattr(self.survey1.with_context({'relative_url': True}), urltype + '_url_html'), msg="Public URL is incorrect.")
|
||||
|
||||
def test_09_answer_survey(self):
|
||||
question = self.Question.sudo(self.survey_manager).create({'page_id': self.page1.id, 'question': 'Q0'})
|
||||
input_portal = self.UserInput.sudo(self.survey_user).create({
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({'page_id': self.page1.id, 'question': 'Q0'})
|
||||
input_portal = self.env['survey.user_input'].sudo(self.survey_user).create({
|
||||
'survey_id': self.survey1.id,
|
||||
'partner_id': self.survey_user.partner_id.id,
|
||||
'user_input_line_ids': [(0, 0, {
|
||||
'skipped': False, 'answer_type': 'free_text', 'value_free_text': "Test Answer",
|
||||
'survey_id': self.survey1.id, 'page_id': self.page1, 'question_id': question.id})]})
|
||||
'survey_id': self.survey1.id, 'question_id': question.id})]})
|
||||
|
||||
input_public = self.UserInput.sudo(self.user_public).create({
|
||||
input_public = self.env['survey.user_input'].sudo(self.user_public).create({
|
||||
'survey_id': self.survey1.id,
|
||||
'partner_id': self.survey_user.partner_id.id,
|
||||
'user_input_line_ids': [(0, 0, {
|
||||
'skipped': False, 'answer_type': 'free_text', 'value_free_text': "Test Answer",
|
||||
'survey_id': self.survey1.id, 'page_id': self.page1, 'question_id': question.id})]})
|
||||
'survey_id': self.survey1.id, 'question_id': question.id})]})
|
||||
|
||||
answers = [input_portal.user_input_line_ids[0], input_public.user_input_line_ids[0]]
|
||||
expected_values = {'answer_type': 'free_text', 'value_free_text': "Test Answer"}
|
||||
@@ -220,52 +212,52 @@ class TestSurvey(TransactionCase):
|
||||
self.assertEqual(getattr(answer, field), value, msg="Unable to answer the survey. Expected behaviour of %s is not proper." % (field))
|
||||
|
||||
def test_10_survey_result_simple_multiple_choice(self):
|
||||
question = self.Question.sudo(self.survey_manager).create({
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q0', 'type': 'simple_choice',
|
||||
'labels_ids': [(0, 0, {'value': "Choice0", 'quizz_mark': 0}), (0, 0, {'value': "Choice1", 'quizz_mark': 0})]})
|
||||
for i in range(3):
|
||||
self.UserInput.sudo(self.user_public).create({'survey_id': self.survey1.id, 'user_input_line_ids': [(0, 0, {
|
||||
self.env['survey.user_input'].sudo(self.user_public).create({'survey_id': self.survey1.id, 'user_input_line_ids': [(0, 0, {
|
||||
'question_id': question.id,
|
||||
'answer_type': 'suggestion',
|
||||
'value_suggested': random.choice(question.labels_ids.ids)})]})
|
||||
lines = [line.value_suggested.id for line in question.user_input_line_ids]
|
||||
answers = [{'text': label.value, 'count': lines.count(label.id), 'answer_id': label.id} for label in question.labels_ids]
|
||||
prp_result = self.Survey.prepare_result(question)['answers']
|
||||
prp_result = self.env['survey.survey'].prepare_result(question)['answers']
|
||||
answers.sort()
|
||||
prp_result.sort()
|
||||
self.assertEqual(prp_result, answers, msg="Statistics of simple, multiple choice questions are different from expectation")
|
||||
|
||||
def test_11_survey_result_matrix(self):
|
||||
question = self.Question.sudo(self.survey_manager).create({
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({
|
||||
'page_id': self.page1.id, 'question': 'Q0', 'type': 'matrix', 'matrix_subtype': 'simple',
|
||||
'labels_ids': [(0, 0, {'value': "Column0", "quizz_mark": 0}), (0, 0, {'value': "Column1", "quizz_mark": 0})],
|
||||
'labels_ids_2': [(0, 0, {'value': "Row0", "quizz_mark": 0}), (0, 0, {'value': "Row1", "quizz_mark": 0})]})
|
||||
for i in range(3):
|
||||
self.UserInput.sudo(self.user_public).create({'survey_id': self.survey1.id, 'user_input_line_ids': [(0, 0, {
|
||||
self.env['survey.user_input'].sudo(self.user_public).create({'survey_id': self.survey1.id, 'user_input_line_ids': [(0, 0, {
|
||||
'question_id': question.id, 'answer_type': 'suggestion', 'value_suggested': random.choice(question.labels_ids.ids),
|
||||
'value_suggested_row': random.choice(question.labels_ids_2.ids)})]})
|
||||
lines = [(line.value_suggested_row.id, line.value_suggested.id) for line in question.user_input_line_ids]
|
||||
res = {}
|
||||
for i in product(question.labels_ids_2.ids, question.labels_ids.ids):
|
||||
res[i] = lines.count((i))
|
||||
self.assertEqual(self.Survey.prepare_result(question)['result'], res, msg="Statistics of matrix type questions are different from expectations")
|
||||
self.assertEqual(self.env['survey.survey'].prepare_result(question)['result'], res, msg="Statistics of matrix type questions are different from expectations")
|
||||
|
||||
def test_12_survey_result_numeric_box(self):
|
||||
question = self.Question.sudo(self.survey_manager).create({'page_id': self.page1.id, 'question': 'Q0', 'type': 'numerical_box'})
|
||||
question = self.env['survey.question'].sudo(self.survey_manager).create({'page_id': self.page1.id, 'question': 'Q0', 'type': 'numerical_box'})
|
||||
num = map(float, random.sample(range(1, 100), 3))
|
||||
nsum = sum(num)
|
||||
for i in range(3):
|
||||
self.UserInput.sudo(self.user_public).create({'survey_id': self.survey1.id, 'user_input_line_ids': [(0, 0, {
|
||||
self.env['survey.user_input'].sudo(self.user_public).create({'survey_id': self.survey1.id, 'user_input_line_ids': [(0, 0, {
|
||||
'question_id': question.id, 'answer_type': 'number', 'value_number': num[i]})]})
|
||||
exresult = {
|
||||
'average': round((nsum / len(num)), 2), 'max': round(max(num), 2),
|
||||
'min': round(min(num), 2), 'sum': nsum, 'most_common': Counter(num).most_common(5)}
|
||||
result = self.Survey.prepare_result(question)
|
||||
result = self.env['survey.survey'].prepare_result(question)
|
||||
for key in exresult.keys():
|
||||
self.assertEqual(result[key], exresult[key], msg="Statistics of numeric box type questions are different from expectations")
|
||||
|
||||
def test_13_survey_actions(self):
|
||||
self.Question.sudo(self.survey_manager).create({'page_id': self.page1.id, 'question': 'Q0', 'type': 'numerical_box'})
|
||||
self.env['survey.question'].sudo(self.survey_manager).create({'page_id': self.page1.id, 'question': 'Q0', 'type': 'numerical_box'})
|
||||
|
||||
actions = {
|
||||
'start': {'method': 'public', 'token': '/test', 'text': 'Start'},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import openerp.tests
|
||||
import odoo.tests
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
|
||||
@openerp.tests.common.at_install(False)
|
||||
@openerp.tests.common.post_install(True)
|
||||
class TestUi(openerp.tests.HttpCase):
|
||||
@odoo.tests.common.at_install(False)
|
||||
@odoo.tests.common.post_install(True)
|
||||
class TestUi(odoo.tests.HttpCase):
|
||||
|
||||
def test_01_admin_survey_tour(self):
|
||||
self.phantom_js("/", "odoo.__DEBUG__.services['web.Tour'].run('test_survey', 'test')", "odoo.__DEBUG__.services['web.Tour'].tours.test_survey", login="admin")
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Survey User inputs" create="false">
|
||||
<header>
|
||||
<button name="action_survey_resent" string="Sent Invitation Again" type="object" class="oe_highlight" attrs="{'invisible': ['|', ('type','=','manually'), ('state', '=', 'done')]}"/>
|
||||
<button name="action_survey_resend" string="Send Invitation Again" type="object" class="oe_highlight" attrs="{'invisible': ['|', ('type','=','manually'), ('state', '=', 'done')]}"/>
|
||||
<button name="action_view_answers" states="done" string="Print These Answers" type="object" class="oe_highlight" />
|
||||
<button name="action_survey_results" string="View Results" type="object" />
|
||||
<field name="state" widget="statusbar"/>
|
||||
@@ -401,7 +401,7 @@
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Answers">
|
||||
<field name="validation_email" attrs="{'invisible': [('type', '!=', 'textbox')]}" on_change="onchange_validation_email(validation_email)"/>
|
||||
<field name="validation_email" attrs="{'invisible': [('type', '!=', 'textbox')]}"/>
|
||||
<label for="validation_email" attrs="{'invisible': [('type', '!=', 'textbox')]}"/>
|
||||
<separator />
|
||||
<field name="labels_ids" string="Type of answers" context="{'default_question_id': active_id}" attrs="{'invisible': [('type', 'not in', ['simple_choice', 'multiple_choice', 'matrix'])]}">
|
||||
@@ -622,8 +622,7 @@
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
if context.get('active_ids'):
|
||||
test_answers = self.pool['survey.user_input'].search(cr, uid, [('survey_id', 'in', context['active_ids']), ('test_entry', '=', 'True')], context=context)
|
||||
self.pool['survey.user_input'].unlink(cr, uid, test_answers, context=context)
|
||||
test_answers = env['survey.user_input'].search([('survey_id', 'in', context['active_ids']), ('test_entry', '=', 'True')]).unlink()
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -1,121 +1,85 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import osv
|
||||
from openerp.osv import fields
|
||||
from openerp.tools.translate import _
|
||||
from datetime import datetime
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
import re
|
||||
import uuid
|
||||
import urlparse
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
emails_split = re.compile(r"[;,\n\r]+")
|
||||
email_validator = re.compile(r"[^@]+@[^@]+\.[^@]+")
|
||||
|
||||
|
||||
class survey_mail_compose_message(osv.TransientModel):
|
||||
class SurveyMailComposeMessage(models.TransientModel):
|
||||
_name = 'survey.mail.compose.message'
|
||||
_inherit = 'mail.compose.message'
|
||||
_description = 'Email composition wizard for Survey'
|
||||
_log_access = True
|
||||
|
||||
def _get_public_url(self, cr, uid, ids, name, arg, context=None):
|
||||
res = dict((id, 0) for id in ids)
|
||||
survey_obj = self.pool.get('survey.survey')
|
||||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
res[wizard.id] = wizard.survey_id.public_url
|
||||
return res
|
||||
def default_survey_id(self):
|
||||
context = self.env.context
|
||||
if context.get('model') == 'survey.survey':
|
||||
return context.get('res_id')
|
||||
|
||||
def _get_public_url_html(self, cr, uid, ids, name, arg, context=None):
|
||||
""" Compute if the message is unread by the current user """
|
||||
urls = self._get_public_url(cr, uid, ids, name, arg, context=context)
|
||||
for key, url in urls.items():
|
||||
urls[key] = '<a href="%s">%s</a>' % (url, _("Click here to start survey"))
|
||||
return urls
|
||||
survey_id = fields.Many2one('survey.survey', string='Survey', default=default_survey_id, required=True)
|
||||
public = fields.Selection([('public_link', 'Share the public web link to your audience.'),
|
||||
('email_public_link', 'Send by email the public web link to your audience.'),
|
||||
('email_private', 'Send private invitation to your audience (only one response per recipient and per invitation).')],
|
||||
string='Share options', default='public_link', required=True)
|
||||
public_url = fields.Char(compute="_compute_survey_url", string="Public url")
|
||||
public_url_html = fields.Char(compute="_compute_survey_url", string="Public HTML web link")
|
||||
partner_ids = fields.Many2many('res.partner', 'survey_mail_compose_message_res_partner_rel', 'wizard_id', 'partner_id', string='Existing contacts')
|
||||
attachment_ids = fields.Many2many('ir.attachment', 'survey_mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id', string='Attachments')
|
||||
multi_email = fields.Text(string='List of emails', help="This list of emails of recipients will not be converted in contacts.\
|
||||
Emails must be separated by commas, semicolons or newline.")
|
||||
date_deadline = fields.Date(string="Deadline to which the invitation to respond is valid",
|
||||
help="Deadline to which the invitation to respond for this survey is valid. If the field is empty,\
|
||||
the invitation is still valid.")
|
||||
|
||||
_columns = {
|
||||
'survey_id': fields.many2one('survey.survey', 'Survey', required=True),
|
||||
'public': fields.selection([('public_link', 'Share the public web link to your audience.'),
|
||||
('email_public_link', 'Send by email the public web link to your audience.'),
|
||||
('email_private', 'Send private invitation to your audience (only one response per recipient and per invitation).')],
|
||||
string='Share options', required=True),
|
||||
'public_url': fields.function(_get_public_url, string="Public url", type="char"),
|
||||
'public_url_html': fields.function(_get_public_url_html, string="Public HTML web link", type="char"),
|
||||
'partner_ids': fields.many2many('res.partner',
|
||||
'survey_mail_compose_message_res_partner_rel',
|
||||
'wizard_id', 'partner_id', 'Existing contacts'),
|
||||
'attachment_ids': fields.many2many('ir.attachment',
|
||||
'survey_mail_compose_message_ir_attachments_rel',
|
||||
'wizard_id', 'attachment_id', 'Attachments'),
|
||||
'multi_email': fields.text(string='List of emails', help="This list of emails of recipients will not converted in contacts. Emails separated by commas, semicolons or newline."),
|
||||
'date_deadline': fields.date(string="Deadline to which the invitation to respond is valid", help="Deadline to which the invitation to respond for this survey is valid. If the field is empty, the invitation is still valid."),
|
||||
}
|
||||
@api.depends('survey_id')
|
||||
def _compute_survey_url(self):
|
||||
for wizard in self:
|
||||
wizard.public_url = wizard.survey_id.public_url
|
||||
wizard.public_url_html = wizard.survey_id.public_url_html
|
||||
|
||||
_defaults = {
|
||||
'public': 'public_link',
|
||||
'survey_id': lambda self, cr, uid, ctx={}: ctx.get('model') == 'survey.survey' and ctx.get('res_id') or None
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
res = super(survey_mail_compose_message, self).default_get(cr, uid, fields, context=context)
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(SurveyMailComposeMessage, self).default_get(fields)
|
||||
context = self.env.context
|
||||
if context.get('active_model') == 'res.partner' and context.get('active_ids'):
|
||||
res.update({'partner_ids': context.get('active_ids')})
|
||||
res.update({'partner_ids': context['active_ids']})
|
||||
return res
|
||||
|
||||
def onchange_multi_email(self, cr, uid, ids, multi_email, context=None):
|
||||
emails = list(set(emails_split.split(multi_email or "")))
|
||||
@api.onchange('multi_email')
|
||||
def onchange_multi_email(self):
|
||||
emails = list(set(emails_split.split(self.multi_email or "")))
|
||||
emails_checked = []
|
||||
error_message = ""
|
||||
for email in emails:
|
||||
email = email.strip()
|
||||
if email:
|
||||
if not re.search(r"^[^@]+@[^@]+$", email):
|
||||
if not email_validator.match(email):
|
||||
error_message += "\n'%s'" % email
|
||||
else:
|
||||
emails_checked.append(email)
|
||||
if error_message:
|
||||
raise UserError(_("One email at least is incorrect: %s") % error_message)
|
||||
raise UserError(_("Incorrect Email Address: %s") % error_message)
|
||||
|
||||
emails_checked.sort()
|
||||
values = {'multi_email': '\n'.join(emails_checked)}
|
||||
return {'value': values}
|
||||
|
||||
def onchange_survey_id(self, cr, uid, ids, survey_id, context=None):
|
||||
""" Compute if the message is unread by the current user. """
|
||||
if survey_id:
|
||||
survey = self.pool.get('survey.survey').browse(cr, uid, survey_id, context=context)
|
||||
return {
|
||||
'value': {
|
||||
'subject': survey.title,
|
||||
'public_url': survey.public_url,
|
||||
'public_url_html': '<a href="%s">%s</a>' % (survey.public_url, _("Click here to take survey")),
|
||||
}}
|
||||
else:
|
||||
txt = _("Please select a survey")
|
||||
return {
|
||||
'value': {
|
||||
'public_url': txt,
|
||||
'public_url_html': txt,
|
||||
}}
|
||||
self.multi_email = '\n'.join(emails_checked)
|
||||
|
||||
#------------------------------------------------------
|
||||
# Wizard validation and send
|
||||
#------------------------------------------------------
|
||||
|
||||
def send_mail(self, cr, uid, ids, auto_commit=False, context=None):
|
||||
@api.multi
|
||||
def send_mail(self, auto_commit=False):
|
||||
""" Process the wizard content and proceed with sending the related
|
||||
email(s), rendering any template patterns on the fly if needed """
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
survey_response_obj = self.pool.get('survey.user_input')
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
mail_mail_obj = self.pool.get('mail.mail')
|
||||
try:
|
||||
model, anonymous_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_anonymous')
|
||||
except ValueError:
|
||||
anonymous_id = None
|
||||
SurveyUserInput = self.env['survey.user_input']
|
||||
Partner = self.env['res.partner']
|
||||
Mail = self.env['mail.mail']
|
||||
anonymous_group = self.env.ref('portal.group_anonymous', raise_if_not_found=False)
|
||||
|
||||
def create_response_and_send_mail(wizard, token, partner_id, email):
|
||||
""" Create one mail by recipients and replace __URL__ by link with identification token """
|
||||
@@ -143,37 +107,38 @@ class survey_mail_compose_message(osv.TransientModel):
|
||||
values['recipient_ids'] = [(4, partner_id)]
|
||||
else:
|
||||
values['email_to'] = email
|
||||
mail_id = mail_mail_obj.create(cr, uid, values, context=context)
|
||||
mail_mail_obj.send(cr, uid, [mail_id], context=context)
|
||||
Mail.create(values).send()
|
||||
|
||||
def create_token(wizard, partner_id, email):
|
||||
if context.get("survey_resent_token"):
|
||||
response_ids = survey_response_obj.search(cr, uid, [('survey_id', '=', wizard.survey_id.id), ('state', 'in', ['new', 'skip']), '|', ('partner_id', '=', partner_id), ('email', '=', email)], context=context)
|
||||
if response_ids:
|
||||
return survey_response_obj.read(cr, uid, response_ids, ['token'], context=context)[0]['token']
|
||||
survey_user_input = SurveyUserInput.search([('survey_id', '=', wizard.survey_id.id),
|
||||
('state', 'in', ['new', 'skip']), '|', ('partner_id', '=', partner_id),
|
||||
('email', '=', email)], limit=1)
|
||||
if survey_user_input:
|
||||
return survey_user_input.token
|
||||
if wizard.public != 'email_private':
|
||||
return None
|
||||
else:
|
||||
token = uuid.uuid4().__str__()
|
||||
# create response with token
|
||||
survey_response_obj.create(cr, uid, {
|
||||
survey_user_input = SurveyUserInput.create({
|
||||
'survey_id': wizard.survey_id.id,
|
||||
'deadline': wizard.date_deadline,
|
||||
'date_create': datetime.now(),
|
||||
'date_create': fields.Datetime.now(),
|
||||
'type': 'link',
|
||||
'state': 'new',
|
||||
'token': token,
|
||||
'partner_id': partner_id,
|
||||
'email': email},
|
||||
context=context)
|
||||
return token
|
||||
'email': email})
|
||||
return survey_user_input.token
|
||||
|
||||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
for wizard in self:
|
||||
# check if __URL__ is in the text
|
||||
if wizard.body.find("__URL__") < 0:
|
||||
raise UserError(_("The content of the text don't contain '__URL__'. \
|
||||
__URL__ is automaticaly converted into the special url of the survey."))
|
||||
|
||||
context = self.env.context
|
||||
if not wizard.multi_email and not wizard.partner_ids and (context.get('default_partner_ids') or context.get('default_multi_email')):
|
||||
wizard.multi_email = context.get('default_multi_email')
|
||||
wizard.partner_ids = context.get('default_partner_ids')
|
||||
@@ -181,16 +146,16 @@ class survey_mail_compose_message(osv.TransientModel):
|
||||
# quick check of email list
|
||||
emails_list = []
|
||||
if wizard.multi_email:
|
||||
emails = list(set(emails_split.split(wizard.multi_email)) - set([partner.email for partner in wizard.partner_ids]))
|
||||
emails = set(emails_split.split(wizard.multi_email)) - set(wizard.partner_ids.mapped('email'))
|
||||
for email in emails:
|
||||
email = email.strip()
|
||||
if re.search(r"^[^@]+@[^@]+$", email):
|
||||
if email_validator.match(email):
|
||||
emails_list.append(email)
|
||||
|
||||
# remove public anonymous access
|
||||
partner_list = []
|
||||
for partner in wizard.partner_ids:
|
||||
if not anonymous_id or not partner.user_ids or anonymous_id not in [x.id for x in partner.user_ids[0].groups_id]:
|
||||
if not anonymous_group or not partner.user_ids or anonymous_group not in partner.user_ids[0].groups_id:
|
||||
partner_list.append({'id': partner.id, 'email': partner.email})
|
||||
|
||||
if not len(emails_list) and not len(partner_list):
|
||||
@@ -199,10 +164,9 @@ class survey_mail_compose_message(osv.TransientModel):
|
||||
raise UserError(_("Please enter at least one valid recipient."))
|
||||
|
||||
for email in emails_list:
|
||||
partner_id = partner_obj.search(cr, uid, [('email', '=', email)], context=context)
|
||||
partner_id = partner_id and partner_id[0] or None
|
||||
token = create_token(wizard, partner_id, email)
|
||||
create_response_and_send_mail(wizard, token, partner_id, email)
|
||||
partner = Partner.search([('email', '=', email)], limit=1)
|
||||
token = create_token(wizard, partner.id, email)
|
||||
create_response_and_send_mail(wizard, token, partner.id, email)
|
||||
|
||||
for partner in partner_list:
|
||||
token = create_token(wizard, partner['id'], partner['email'])
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<field name="res_id" invisible="1"/>
|
||||
<field name="parent_id" invisible="1"/>
|
||||
<group col="2">
|
||||
<field name="survey_id" readonly="context.get('default_survey_id')" on_change="onchange_survey_id(survey_id)" />
|
||||
<field name="survey_id" readonly="context.get('default_survey_id')"/>
|
||||
<field name="public" widget="radio" invisible="context.get('survey_resent_token')" />
|
||||
</group>
|
||||
<group col="1" invisible="context.get('survey_resent_token')" attrs="{'invisible':[('public','in',['email_private', 'email_public_link'])]}" class="oe_survey_email_public">
|
||||
@@ -45,7 +45,7 @@
|
||||
<group col="1" attrs="{'invisible':['|',('public','=',False),('public','in',['public_link'])]}">
|
||||
<group col="2">
|
||||
<field invisible="context.get('survey_resent_token')" name="partner_ids" widget="many2many_tags_email" placeholder="Add list of existing contacts..." context="{'force_email':True, 'show_email':True}" />
|
||||
<field invisible="context.get('survey_resent_token')" name="multi_email" placeholder="Add list of email of recipients (will not converted in partner), separated by commas, semicolons or newline..." on_change="onchange_multi_email(multi_email)" />
|
||||
<field invisible="context.get('survey_resent_token')" name="multi_email" placeholder="Add list of email of recipients (will not converted in partner), separated by commas, semicolons or newline..."/>
|
||||
<field name="subject" placeholder="Subject..."/>
|
||||
</group>
|
||||
<field name="body" options="{'style-inline': true}"/>
|
||||
|
||||
Reference in New Issue
Block a user