Odoo18-Base/addons/rating/models/rating.py

161 lines
7.2 KiB
Python
Raw Permalink Normal View History

2025-03-10 11:12:23 +07:00
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
import uuid
from odoo import api, fields, models
from odoo.addons.rating.models import rating_data
from odoo.modules.module import get_resource_path
class Rating(models.Model):
_name = "rating.rating"
_description = "Rating"
_order = 'write_date desc, id desc'
_rec_name = 'res_name'
@api.model
def _default_access_token(self):
return uuid.uuid4().hex
@api.model
def _selection_target_model(self):
return [(model.model, model.name) for model in self.env['ir.model'].sudo().search([])]
create_date = fields.Datetime(string="Submitted on")
res_name = fields.Char(string='Resource name', compute='_compute_res_name', store=True)
res_model_id = fields.Many2one('ir.model', 'Related Document Model', index=True, ondelete='cascade')
res_model = fields.Char(string='Document Model', related='res_model_id.model', store=True, index=True, readonly=True)
res_id = fields.Many2oneReference(string='Document', model_field='res_model', required=True, index=True)
resource_ref = fields.Reference(
string='Resource Ref', selection='_selection_target_model',
compute='_compute_resource_ref', readonly=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, ondelete='cascade')
parent_res_model = fields.Char('Parent Document Model', store=True, related='parent_res_model_id.model', index=True, readonly=False)
parent_res_id = fields.Integer('Parent Document', index=True)
parent_ref = fields.Reference(
string='Parent Ref', selection='_selection_target_model',
compute='_compute_parent_ref', readonly=True)
rated_partner_id = fields.Many2one('res.partner', string="Rated Operator")
rated_partner_name = fields.Char(related="rated_partner_id.name")
partner_id = fields.Many2one('res.partner', string='Customer')
rating = fields.Float(string="Rating Value", group_operator="avg", default=0)
rating_image = fields.Binary('Image', compute='_compute_rating_image')
rating_image_url = fields.Char('Image URL', compute='_compute_rating_image')
rating_text = fields.Selection(rating_data.RATING_TEXT, string='Rating', store=True, compute='_compute_rating_text', readonly=True)
feedback = fields.Text('Comment')
message_id = fields.Many2one(
'mail.message', string="Message",
index=True, ondelete='cascade')
is_internal = fields.Boolean('Visible Internally Only', readonly=False, related='message_id.is_internal', store=True)
access_token = fields.Char('Security Token', default=_default_access_token)
consumed = fields.Boolean(string="Filled Rating")
_sql_constraints = [
('rating_range', 'check(rating >= 0 and rating <= 5)', 'Rating should be between 0 and 5'),
]
@api.depends('res_model', 'res_id')
def _compute_res_name(self):
for rating in self:
name = self.env[rating.res_model].sudo().browse(rating.res_id).name_get()
rating.res_name = name and name[0][1] or ('%s/%s') % (rating.res_model, rating.res_id)
@api.depends('res_model', 'res_id')
def _compute_resource_ref(self):
for rating in self:
if rating.res_model and rating.res_model in self.env:
rating.resource_ref = '%s,%s' % (rating.res_model, rating.res_id or 0)
else:
rating.resource_ref = None
@api.depends('parent_res_model', 'parent_res_id')
def _compute_parent_ref(self):
for rating in self:
if rating.parent_res_model and rating.parent_res_model in self.env:
rating.parent_ref = '%s,%s' % (rating.parent_res_model, rating.parent_res_id or 0)
else:
rating.parent_ref = None
@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
def _get_rating_image_filename(self):
self.ensure_one()
return 'rating_%s.png' % rating_data._rating_to_threshold(self.rating)
@api.depends('rating')
def _compute_rating_image(self):
self.rating_image_url = False
self.rating_image = False
for rating in self:
try:
image_path = get_resource_path('rating', 'static/src/img', rating._get_rating_image_filename())
rating.rating_image_url = '/rating/static/src/img/%s' % rating._get_rating_image_filename()
rating.rating_image = base64.b64encode(open(image_path, 'rb').read()) if image_path else False
except (IOError, OSError):
pass
@api.depends('rating')
def _compute_rating_text(self):
for rating in self:
rating.rating_text = rating_data._rating_to_text(rating.rating)
@api.model_create_multi
def create(self, vals_list):
for values in vals_list:
if values.get('res_model_id') and values.get('res_id'):
values.update(self._find_parent_data(values))
return super().create(vals_list)
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 unlink(self):
# OPW-2181568: Delete the chatter message too
self.env['mail.message'].search([('rating_ids', 'in', self.ids)]).unlink()
return super(Rating, self).unlink()
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_field_name'):
current_record_parent = current_record._rating_get_parent_field_name()
if current_record_parent:
parent_res_model = getattr(current_record, current_record_parent)
data['parent_res_model_id'] = self.env['ir.model']._get(parent_res_model._name).id
data['parent_res_id'] = parent_res_model.id
return data
def reset(self):
for record in self:
record.write({
'rating': 0,
'access_token': record._default_access_token(),
'feedback': False,
'consumed': False,
})
def action_open_rated_object(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'res_model': self.res_model,
'res_id': self.res_id,
'views': [[False, 'form']]
}