diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py
index d38cb705339..4d9e0246234 100644
--- a/addons/hr_holidays/hr_holidays.py
+++ b/addons/hr_holidays/hr_holidays.py
@@ -504,7 +504,7 @@ class hr_employee(osv.osv):
if diff > 0:
leave_id = holiday_obj.create(cr, uid, {'name': _('Allocation for %s') % employee.name, 'employee_id': employee.id, 'holiday_status_id': status_id, 'type': 'add', 'holiday_type': 'employee', 'number_of_days_temp': diff}, context=context)
elif diff < 0:
- leave_id = holiday_obj.create(cr, uid, {'name': _('Leave Request for %s') % employee.name, 'employee_id': employee.id, 'holiday_status_id': status_id, 'type': 'remove', 'holiday_type': 'employee', 'number_of_days_temp': abs(diff)}, context=context)
+ raise osv.except_osv(_('Warning!'), _('You cannot reduce validated allocation requests'))
else:
return False
holiday_obj.signal_confirm(cr, uid, [leave_id])
diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py
index 5b716a14ef2..5542cd411ec 100644
--- a/addons/mail/mail_message.py
+++ b/addons/mail/mail_message.py
@@ -77,7 +77,8 @@ class mail_message(osv.Model):
def default_get(self, cr, uid, fields, context=None):
# protection for `default_type` values leaking from menu action context (e.g. for invoices)
- if context and context.get('default_type') and context.get('default_type') not in self._columns['type'].selection:
+ if context and context.get('default_type') and context.get('default_type') not in [
+ val[0] for val in self._columns['type'].selection]:
context = dict(context, default_type=None)
return super(mail_message, self).default_get(cr, uid, fields, context=context)
diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py
index 7c86bb7cc43..d04221cd0f5 100644
--- a/addons/mail/mail_thread.py
+++ b/addons/mail/mail_thread.py
@@ -377,7 +377,10 @@ class mail_thread(osv.AbstractModel):
# automatic logging unless asked not to (mainly for various testing purpose)
if not context.get('mail_create_nolog'):
- self.message_post(cr, uid, thread_id, body=_('%s created') % (self._description), context=context)
+ ir_model_pool = self.pool['ir.model']
+ ids = ir_model_pool.search(cr, uid, [('model', '=', self._name)], context=context)
+ name = ir_model_pool.read(cr, uid, ids, ['name'], context=context)[0]['name']
+ self.message_post(cr, uid, thread_id, body=_('%s created') % name, context=context)
# auto_subscribe: take values and defaults into account
create_values = dict(values)
diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py
index e3f2cd6668b..515973d77b3 100644
--- a/addons/project/report/project_report.py
+++ b/addons/project/report/project_report.py
@@ -50,7 +50,6 @@ class report_project_task_user(osv.osv):
'nbr': fields.integer('# of tasks', readonly=True),
'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')],
string='Priority', readonly=True),
- 'state': fields.selection([('draft', 'Draft'), ('open', 'In Progress'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')],'Status', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True),
'partner_id': fields.many2one('res.partner', 'Contact', readonly=True),
'stage_id': fields.many2one('project.task.type', 'Stage'),
diff --git a/addons/sale/res_config.py b/addons/sale/res_config.py
index 94fd74e035e..e81075be03a 100644
--- a/addons/sale/res_config.py
+++ b/addons/sale/res_config.py
@@ -93,6 +93,7 @@ Example: 10% for retailers, promotion of 5 EUR on this product, etc."""),
product = ir_model_data.xmlid_to_object(cr, uid, 'product.product_product_consultant')
if product and product.exists():
res['time_unit'] = product.uom_id.id
+ res['timesheet'] = res.get('module_account_analytic_analysis')
return res
def _get_default_time_unit(self, cr, uid, context=None):
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 9ac2124c80c..30ada7eab4f 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -283,7 +283,7 @@ class sale_order(osv.osv):
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
def copy_quotation(self, cr, uid, ids, context=None):
- id = self.copy(cr, uid, ids[0], context=None)
+ id = self.copy(cr, uid, ids[0], context=context)
view_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'view_order_form')
view_id = view_ref and view_ref[1] or False,
return {
diff --git a/addons/sale/views/report_saleorder.xml b/addons/sale/views/report_saleorder.xml
index 5c198c635a3..243004869e3 100644
--- a/addons/sale/views/report_saleorder.xml
+++ b/addons/sale/views/report_saleorder.xml
@@ -45,6 +45,10 @@
Salesperson:
+
Payment Term:
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 6b8a7c493e1..08b5e133587 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -932,8 +932,7 @@ class stock_picking(osv.osv):
'pack_operation_ids': [],
'backorder_id': picking.id,
})
- back_order_name = self.browse(cr, uid, backorder_id, context=context).name
- self.message_post(cr, uid, picking.id, body=_("Back order
%s created.") % (back_order_name), context=context)
+ self.message_post(cr, uid, picking.id, body=_("Back order
%s created.") % (picking.name), context=context)
move_obj = self.pool.get("stock.move")
move_obj.write(cr, uid, backorder_move_ids, {'picking_id': backorder_id}, context=context)
@@ -1443,7 +1442,7 @@ class stock_production_lot(osv.osv):
'product_id': lambda x, y, z, c: c.get('product_id', False),
}
_sql_constraints = [
- ('name_ref_uniq', 'unique (name, ref)', 'The combination of Serial Number and internal reference must be unique !'),
+ ('name_ref_uniq', 'unique (name, ref, product_id, company_id)', 'The combination of Serial Number, internal reference, Product and Company must be unique !'),
]
def action_traceability(self, cr, uid, ids, context=None):
diff --git a/addons/survey/controllers/main.py b/addons/survey/controllers/main.py
index 638b2aefed4..e21b0bb0223 100644
--- a/addons/survey/controllers/main.py
+++ b/addons/survey/controllers/main.py
@@ -298,7 +298,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, current_filters, filter_display_data, filter_finish = 'survey.result', [], [], False
+ 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'
@@ -307,7 +311,7 @@ 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, filter_data, filter_finish, context=request.context)
+ 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)
return request.website.render(result_template,
{'survey': survey,
@@ -317,11 +321,48 @@ class WebsiteSurvey(http.Controller):
'filter_display_data': filter_display_data,
'filter_finish': filter_finish
})
+ # Quick retroengineering of what is injected into the template for now:
+ # (TODO: flatten and simplify this)
+ #
+ # survey: a browse record of the survey
+ # survey_dict: very messy dict containing all the info to display answers
+ # {'page_ids': [
+ #
+ # ...
+ #
+ # {'page': browse record of the page,
+ # 'question_ids': [
+ #
+ # ...
+ #
+ # {'graph_data': data to be displayed on the graph
+ # 'input_summary': number of answered, skipped...
+ # 'prepare_result': {
+ # answers displayed in the tables
+ # }
+ # 'question': browse record of the question_ids
+ # }
+ #
+ # ...
+ #
+ # ]
+ # }
+ #
+ # ...
+ #
+ # ]
+ # }
+ #
+ # page_range: pager helper function
+ # current_filters: a list of ids
+ # filter_display_data: [{'labels': ['a', 'b'], question_text} ... ]
+ # filter_finish: boolean => only finished surveys or not
+ #
def prepare_result_dict(self,survey, current_filters=[]):
"""Returns dictionary having values for rendering template"""
survey_obj = request.registry['survey.survey']
- result = {'survey':survey, 'page_ids': []}
+ result = {'page_ids': []}
for page in survey.page_ids:
page_dict = {'page': page, 'question_ids': []}
for question in page.question_ids:
@@ -353,9 +394,10 @@ class WebsiteSurvey(http.Controller):
result = []
if question.type == 'multiple_choice':
result.append({'key': str(question.question),
- 'values': survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context)})
+ 'values': survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context)['answers']
+ })
if question.type == 'simple_choice':
- result = survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context)
+ result = survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context)['answers']
if question.type == 'matrix':
data = survey_obj.prepare_result(request.cr, request.uid, question, current_filters, context=request.context)
for answer in data['answers']:
diff --git a/addons/survey/survey.py b/addons/survey/survey.py
index 1389e63e9e2..f110afae352 100644
--- a/addons/survey/survey.py
+++ b/addons/survey/survey.py
@@ -282,7 +282,7 @@ class survey_survey(osv.Model):
else:
return (pages[current_page_index + 1][1], current_page_index + 1, False)
- def filter_input_ids(self, cr, uid, filters, finished=False, context=None):
+ def filter_input_ids(self, cr, uid, survey, filters, finished=False, context=None):
'''If user applies any filters, then this function returns list of
filtered user_input_id and label's strings for display data in web.
:param filters: list of dictionary (having: row_id, ansewr_id)
@@ -311,7 +311,7 @@ class survey_survey(osv.Model):
if finished:
user_input = self.pool.get('survey.user_input')
if not filtered_input_ids:
- current_filters = user_input.search(cr, uid, [], context=context)
+ current_filters = user_input.search(cr, uid, [('survey_id', '=', survey.id)], context=context)
user_input_objs = user_input.browse(cr, uid, current_filters, context=context)
else:
user_input_objs = user_input.browse(cr, uid, filtered_input_ids, context=context)
@@ -345,16 +345,20 @@ class survey_survey(osv.Model):
context = {}
#Calculate and return statistics for choice
if question.type in ['simple_choice', 'multiple_choice']:
- result_summary = {}
- [result_summary.update({label.id: {'text': label.value, 'count': 0, 'answer_id': label.id}}) for label in question.labels_ids]
+ answers = {}
+ comments = []
+ [answers.update({label.id: {'text': label.value, 'count': 0, 'answer_id': label.id}}) for label in question.labels_ids]
for input_line in question.user_input_line_ids:
- if input_line.answer_type == 'suggestion' and result_summary.get(input_line.value_suggested.id) and (not(current_filters) or input_line.user_input_id.id in current_filters):
- result_summary[input_line.value_suggested.id]['count'] += 1
- result_summary = result_summary.values()
+ if input_line.answer_type == 'suggestion' and answers.get(input_line.value_suggested.id) and (not(current_filters) or input_line.user_input_id.id in current_filters):
+ answers[input_line.value_suggested.id]['count'] += 1
+ if input_line.answer_type == 'text' and (not(current_filters) or input_line.user_input_id.id in current_filters):
+ comments.append(input_line)
+ result_summary = {'answers': answers.values(), 'comments': comments}
#Calculate and return statistics for matrix
if question.type == 'matrix':
rows, answers, res = {}, {}, {}
+ comments = []
[rows.update({label.id: label.value}) for label in question.labels_ids_2]
[answers.update({label.id: label.value}) for label in question.labels_ids]
for cell in product(rows.keys(), answers.keys()):
@@ -362,7 +366,9 @@ class survey_survey(osv.Model):
for input_line in question.user_input_line_ids:
if input_line.answer_type == 'suggestion' and (not(current_filters) or input_line.user_input_id.id in current_filters):
res[(input_line.value_suggested_row.id, input_line.value_suggested.id)] += 1
- result_summary = {'answers': answers, 'rows': rows, 'result': res}
+ if input_line.answer_type == 'text' and (not(current_filters) or input_line.user_input_id.id in current_filters):
+ comments.append(input_line)
+ result_summary = {'answers': answers, 'rows': rows, 'result': res, 'comments': comments}
#Calculate and return statistics for free_text, textbox, datetime
if question.type in ['free_text', 'textbox', 'datetime']:
@@ -1138,11 +1144,14 @@ class survey_user_input_line(osv.Model):
vals.update({'answer_type': 'suggestion', 'value_suggested': post[answer_tag]})
else:
vals.update({'answer_type': None, 'skipped': True})
- self.create(cr, uid, vals, context=context)
+
+ # '-1' indicates 'comment count as an answer' so do not need to record it
+ if post.get(answer_tag) and post.get(answer_tag) != '-1':
+ self.create(cr, uid, vals, context=context)
comment_answer = post.pop(("%s_%s" % (answer_tag, 'comment')), '').strip()
if comment_answer:
- vals.update({'answer_type': 'text', 'value_text': comment_answer, 'skipped': False})
+ vals.update({'answer_type': 'text', 'value_text': comment_answer, 'skipped': False, 'value_suggested': False})
self.create(cr, uid, vals, context=context)
return True
@@ -1166,10 +1175,12 @@ class survey_user_input_line(osv.Model):
comment_answer = ca.pop(("%s_%s" % (answer_tag, 'comment')), '').strip()
if len(ca) > 0:
for a in ca:
- vals.update({'answer_type': 'suggestion', 'value_suggested': ca[a]})
- self.create(cr, uid, vals, context=context)
+ # '-1' indicates 'comment count as an answer' so do not need to record it
+ if a != ('%s_%s' % (answer_tag, '-1')):
+ vals.update({'answer_type': 'suggestion', 'value_suggested': ca[a]})
+ self.create(cr, uid, vals, context=context)
if comment_answer:
- vals.update({'answer_type': 'text', 'value_text': comment_answer})
+ vals.update({'answer_type': 'text', 'value_text': comment_answer, 'value_suggested': False})
self.create(cr, uid, vals, context=context)
if not ca and not comment_answer:
vals.update({'answer_type': None, 'skipped': True})
diff --git a/addons/survey/views/survey_result.xml b/addons/survey/views/survey_result.xml
index 40a8a75fc28..c1303b87b0f 100644
--- a/addons/survey/views/survey_result.xml
+++ b/addons/survey/views/survey_result.xml
@@ -13,9 +13,8 @@
Filters Clear All Filters
@@ -34,6 +33,7 @@
+
@@ -56,7 +56,7 @@
-
+
@@ -115,6 +115,28 @@
+
+
+
+
@@ -154,7 +176,7 @@
-
+
|
@@ -168,6 +190,14 @@
+
+
+
+
+
+
+
+
@@ -217,6 +247,13 @@
+
+
+
+
+
+
+
@@ -275,10 +312,7 @@
|
-
-
- |
+
|
diff --git a/addons/survey/views/survey_templates.xml b/addons/survey/views/survey_templates.xml
index 9ae973b9345..449a6b159cf 100644
--- a/addons/survey/views/survey_templates.xml
+++ b/addons/survey/views/survey_templates.xml
@@ -8,7 +8,7 @@
Thank you!
-
+
You scored points.
@@ -70,7 +70,7 @@