[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:
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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'}"/>
|
||||
|
||||
@@ -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):
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user