diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/rating/models/rating.py | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/rating/models/rating.py')
| -rw-r--r-- | addons/rating/models/rating.py | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/addons/rating/models/rating.py b/addons/rating/models/rating.py new file mode 100644 index 00000000..c5fa842b --- /dev/null +++ b/addons/rating/models/rating.py @@ -0,0 +1,176 @@ +# -*- 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.modules.module import get_resource_path + +RATING_LIMIT_SATISFIED = 5 +RATING_LIMIT_OK = 3 +RATING_LIMIT_MIN = 1 + + +class Rating(models.Model): + _name = "rating.rating" + _description = "Rating" + _order = 'write_date desc' + _rec_name = 'res_name' + _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.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'].search([])] + + create_date = fields.Datetime(string="Submitted on") + 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', required=True, help="Identifier of the rated object", 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", help="Owner of the rated resource") + partner_id = fields.Many2one('res.partner', string='Customer', help="Author of the rating") + rating = fields.Float(string="Rating Value", group_operator="avg", default=0, help="Rating value: 0=Unhappy, 5=Happy") + rating_image = fields.Binary('Image', compute='_compute_rating_image') + rating_text = fields.Selection([ + ('satisfied', 'Satisfied'), + ('not_satisfied', 'Not satisfied'), + ('highly_dissatisfied', 'Highly dissatisfied'), + ('no_rating', 'No Rating yet')], string='Rating', store=True, compute='_compute_rating_text', readonly=True) + feedback = fields.Text('Comment', help="Reason of the rating") + message_id = fields.Many2one( + 'mail.message', string="Message", + index=True, ondelete='cascade', + help="Associated message when posting a review. Mainly used in website addons.") + 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, 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('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() + if self.rating >= RATING_LIMIT_SATISFIED: + rating_int = 5 + elif self.rating >= RATING_LIMIT_OK: + rating_int = 3 + elif self.rating >= RATING_LIMIT_MIN: + rating_int = 1 + else: + rating_int = 0 + return 'rating_%s.png' % rating_int + + def _compute_rating_image(self): + for rating in self: + try: + image_path = get_resource_path('rating', 'static/src/img', rating._get_rating_image_filename()) + rating.rating_image = base64.b64encode(open(image_path, 'rb').read()) if image_path else False + except (IOError, OSError): + rating.rating_image = False + + @api.depends('rating') + def _compute_rating_text(self): + for rating in self: + if rating.rating >= RATING_LIMIT_SATISFIED: + rating.rating_text = 'satisfied' + elif rating.rating >= RATING_LIMIT_OK: + rating.rating_text = 'not_satisfied' + elif rating.rating >= RATING_LIMIT_MIN: + rating.rating_text = 'highly_dissatisfied' + else: + rating.rating_text = 'no_rating' + + @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) + + 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']] + } |
