[IMP] rating: parenting model mecanism

This commit provide a parenting system for rated
record, such as mail alias.
For instance, 'project.project' is the parent of
task and issue objects.

This will allow to have a global view of customer
statisfaction on 'parent' objects (project and
livechat channel for now).

To do so, the rating
mixin provides 2 methods that need to be
overriden: `rating_get_parent_model_name` and
`rating_get_parent_id`.
This commit is contained in:
dbh
2017-07-10 08:46:27 +02:00
committed by Jérome Maes
parent 0e39cc9345
commit 798c1da440
7 changed files with 82 additions and 8 deletions
@@ -133,8 +133,8 @@ class ImLivechatChannel(models.Model):
:returns : the ir.action 'action_view_rating' with the correct domain
"""
self.ensure_one()
action = self.env['ir.actions.act_window'].for_xml_id('rating', 'action_view_rating')
action['domain'] = [('res_id', 'in', [s.id for s in self.channel_ids]), ('res_model', '=', 'mail.channel')]
action = self.env['ir.actions.act_window'].for_xml_id('im_livechat', 'rating_rating_action_view_livechat_rating')
action['domain'] = [('parent_res_id', '=', self.id), ('parent_res_model', '=', 'im_livechat.channel')]
return action
# --------------------------
@@ -133,3 +133,11 @@ class MailChannel(models.Model):
'channel_ids': self.ids,
'info': 'transient_message',
})
# Rating Mixin
def rating_get_parent_model_name(self, values):
return 'im_livechat.channel'
def rating_get_parent_id(self):
return self.livechat_channel_id.id
+54 -3
View File
@@ -8,6 +8,10 @@ from odoo import api, fields, models, tools, _
from odoo.modules.module import get_resource_path
from odoo.tools import pycompat
RATING_LIMIT_SATISFIED = 7
RATING_LIMIT_OK = 3
RATING_LIMIT_MIN = 1
class Rating(models.Model):
@@ -32,7 +36,11 @@ class Rating(models.Model):
res_name = fields.Char(string='Resource name', compute='_compute_res_name', store=True, help="The name of the rated resource.")
res_model_id = fields.Many2one('ir.model', 'Related Document Model', index=True, ondelete='cascade', help='Model of the followed resource')
res_model = fields.Char(string='Document Model', related='res_model_id.model', store=True, index=True, readonly=True)
res_id = fields.Integer(string='Document ID', required=True, help="Identifier of the rated object", index=True)
res_id = fields.Integer(string='Document', required=True, help="Identifier of the rated object", index=True)
parent_res_name = fields.Char('Parent Document Name', compute='_compute_parent_res_name', store=True)
parent_res_model_id = fields.Many2one('ir.model', 'Parent Related Document Model', index=True)
parent_res_model = fields.Char('Parent Document Model', store=True, related='parent_res_model_id.model', index=True)
parent_res_id = fields.Integer('Parent Document', index=True)
rated_partner_id = fields.Many2one('res.partner', string="Rated person", help="Owner of the rated resource")
partner_id = fields.Many2one('res.partner', string='Customer', help="Author of the rating")
rating = fields.Float(string="Rating", group_operator="avg", default=0, help="Rating value: 0=Unhappy, 10=Happy")
@@ -43,6 +51,15 @@ class Rating(models.Model):
access_token = fields.Char('Security Token', default=new_access_token, help="Access token to set the rating of the value")
consumed = fields.Boolean(string="Filled Rating", help="Enabled if the rating has been filled.")
@api.depends('parent_res_model', 'parent_res_id')
def _compute_parent_res_name(self):
for rating in self:
name = False
if rating.parent_res_model and rating.parent_res_id:
name = self.env[rating.parent_res_model].sudo().browse(rating.parent_res_id).name_get()
name = name and name[0][1] or ('%s/%s') % (rating.parent_res_model, rating.parent_res_id)
rating.parent_res_name = name
@api.multi
@api.depends('rating')
def _compute_rating_image(self):
@@ -60,6 +77,32 @@ class Rating(models.Model):
for rating in self:
rating.rating_text = text[rating.rating] or _('No rating yet')
@api.model
def create(self, values):
if values.get('res_model_id') and values.get('res_id'):
values.update(self._find_parent_data(values))
return super(Rating, self).create(values)
@api.multi
def write(self, values):
if values.get('res_model_id') and values.get('res_id'):
values.update(self._find_parent_data(values))
return super(Rating, self).write(values)
def _find_parent_data(self, values):
""" Determine the parent res_model/res_id, based on the values to create or write """
current_model_name = self.env['ir.model'].sudo().browse(values['res_model_id']).model
current_record = self.env[current_model_name].browse(values['res_id'])
data = {
'parent_res_model_id': False,
'parent_res_id': False,
}
if hasattr(current_record, 'rating_get_parent_model_name'):
parent_res_model = current_record.rating_get_parent_model_name(values)
data['parent_res_model_id'] = self.env['ir.model']._get(parent_res_model).id
data['parent_res_id'] = current_record.rating_get_parent_id()
return data
@api.multi
def reset(self):
for record in self:
@@ -123,6 +166,14 @@ class RatingMixin(models.AbstractModel):
self.env['rating.rating'].sudo().search([('res_model', '=', self._name), ('res_id', 'in', record_ids)]).unlink()
return result
def rating_get_parent_model_name(self, vals):
""" Return the parent model name """
return None
def rating_get_parent_id(self):
""" Return the parent record id """
return None
def rating_get_partner_id(self):
if hasattr(self, 'partner_id') and self.partner_id:
return self.partner_id
@@ -236,9 +287,9 @@ class RatingMixin(models.AbstractModel):
data = self.rating_get_repartition(domain=domain)
res = dict.fromkeys(['great', 'okay', 'bad'], 0)
for key in data:
if key >= 7:
if key >= RATING_LIMIT_SATISFIED:
res['great'] += data[key]
elif key > 3:
elif key > RATING_LIMIT_OK:
res['okay'] += data[key]
else:
res['bad'] += data[key]
+4 -1
View File
@@ -7,6 +7,7 @@
<field name="arch" type="xml">
<tree string="Rating" create="false" edit="false">
<field name="res_name"/>
<field name="parent_res_name"/>
<field name="rated_partner_id"/>
<field name="partner_id"/>
<field name="rating_text"/>
@@ -25,6 +26,7 @@
<group>
<group>
<field name="res_name"/>
<field name="parent_res_name"/>
<field name="rated_partner_id"/>
<field name="partner_id"/>
<field name="rating" invisible="1"/>
@@ -127,13 +129,14 @@
<field name="partner_id"/>
<field name="res_name"/>
<field name="res_id"/>
<field name="parent_res_name"/>
<filter string="Satisfied" name="rating_happy" domain="[('rating', '=', 10)]"/>
<filter string="Not satisfied" name="rating_okay" domain="[('rating', '=', 5)]"/>
<filter string="Highly dissatisfied" name="rating_unhappy" domain="[('rating', '=', 1)]"/>
<separator/>
<filter string="My Ratings" domain="[('rated_partner_id.user_ids', 'in', [uid])]"/>
<group expand="0" string="Group By">
<filter string="Rated User" name="Responsible" context="{'group_by':'rated_partner_id'}"/>
<filter string="Rated User" name="responsible" context="{'group_by':'rated_partner_id'}"/>
<filter string="Customer" name="customer" context="{'group_by':'partner_id'}"/>
<filter string="Rating" name="rating" context="{'group_by':'rating'}"/>
<filter string="Resource" name="resource" context="{'group_by':'res_name'}"/>
+6
View File
@@ -53,6 +53,12 @@ class Task(models.Model):
def rating_apply(self, rate, token=None, feedback=None, subtype=None):
return super(Task, self).rating_apply(rate, token=token, feedback=feedback, subtype="rating_project.mt_task_rating")
def rating_get_parent_model_name(self, vals):
return 'project.project'
def rating_get_parent_id(self):
return self.project_id.id
class Project(models.Model):
+1 -1
View File
@@ -153,7 +153,7 @@
<field name="name">Customer Ratings</field>
<field name="res_model">rating.rating</field>
<field name="view_mode">kanban,tree,pivot,graph,form</field>
<field name="domain">[('res_model','in',['project.task', 'project.issue']), ('consumed', '=', True)]</field>
<field name="domain">[('parent_res_model','=','project.project'), ('consumed', '=', True)]</field>
<field name="help" type="html">
<p>
Customer ratings on tasks/issues. If you have no rating, change your project Settings to activate it.
@@ -29,10 +29,16 @@ class ProjectIssue(models.Model):
def rating_apply(self, rate, token=None, feedback=None, subtype=None):
return super(ProjectIssue, self).rating_apply(rate, token=token, feedback=feedback, subtype="rating_project_issue.mt_issue_rating")
def rating_get_parent_model_name(self, vals):
return 'project.project'
def rating_get_parent_id(self):
return self.project_id.id
class Stage(models.Model):
_inherit = ['project.task.type']
_inherit = 'project.task.type'
def _default_domain_rating_template_id(self):
domain = super(Stage, self)._default_domain_rating_template_id()