Rationale ========= Since v8, the `display_name` field is present on all models. By default, `display_name` uses `name_get` which has pretty much the same purpose (return record name used by the web client). Gradually, many (backend) developers (and the ORM: https://github.com/odoo/odoo/commit/6da1c3ac4c036eac289597602976538e243cb939) started using `display_name` (more convenient than `record.name_get()[0][1]`) but it still had the `name_get` override. It becomes more complex than necessary and poeple start to misunderstand the two (and sometimes override both, leading to inconstiencies between `display_name`/`name_get`). To simplify the ORM and the API, we decided to keep only one of them, the `display_name` field: - It is much more convenient from a backend point of view (`record.name_get()[0][1]` vs `record.display_name`) - It is cached during the same transaction (and invalidated if its dependencies change) - It can be overridden like any other compute field (override `_compute_display_name` with any extra dependencies) - `name_get` is replaced by `read(['display_name'])` (API perceptive), which can actually be more efficient (if `display_name`'s depends are correct, the ORM will only fetch the fields it needs instead of every prefetchable field) Changes ======= - Deprecates `name_get` for the v17 and based the method on `display_name` (the opposite of before) - Converts all usage of `name_get` - Overrides of `name_get` are now overrides of `_compute_display_name` - For `res.partner`, rename the field store `display_name` into `complete_name` because `display_name` context-dependent and it makes no sense to have a compute store that is context-dependent. - Previously, it was possible to return multiple names for the same record with `name_get`, but it was tricky and most of the usage of this `name_get` didn't take this into account. The only example of this is the `name_get` of `product.product` (now use `", ".join(<names>)`). Part-of: odoo/odoo#122085
90 lines
4.4 KiB
Python
90 lines
4.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models
|
|
from odoo.osv import expression
|
|
|
|
|
|
class WebsiteVisitor(models.Model):
|
|
_name = 'website.visitor'
|
|
_inherit = ['website.visitor']
|
|
|
|
event_registration_ids = fields.One2many(
|
|
'event.registration', 'visitor_id', string='Event Registrations',
|
|
groups="event.group_event_registration_desk")
|
|
event_registration_count = fields.Integer(
|
|
'# Registrations', compute='_compute_event_registration_count',
|
|
groups="event.group_event_registration_desk")
|
|
event_registered_ids = fields.Many2many(
|
|
'event.event', string="Registered Events",
|
|
compute="_compute_event_registered_ids", compute_sudo=True,
|
|
search="_search_event_registered_ids",
|
|
groups="event.group_event_registration_desk")
|
|
|
|
@api.depends('partner_id', 'event_registration_ids.name')
|
|
def _compute_display_name(self):
|
|
""" If there is an event registration for an anonymous visitor, use that
|
|
registered attendee name as visitor name. """
|
|
super()._compute_display_name()
|
|
# sudo is needed for `event_registration_ids`
|
|
for visitor in self.sudo().filtered(lambda v: not v.partner_id and v.event_registration_ids):
|
|
visitor.display_name = visitor.event_registration_ids[-1].name
|
|
|
|
@api.depends('event_registration_ids')
|
|
def _compute_event_registration_count(self):
|
|
read_group_res = self.env['event.registration']._read_group(
|
|
[('visitor_id', 'in', self.ids)],
|
|
['visitor_id'], ['__count'])
|
|
visitor_mapping = {visitor.id: count for visitor, count in read_group_res}
|
|
for visitor in self:
|
|
visitor.event_registration_count = visitor_mapping.get(visitor.id, 0)
|
|
|
|
@api.depends('event_registration_ids.email', 'event_registration_ids.mobile', 'event_registration_ids.phone')
|
|
def _compute_email_phone(self):
|
|
super(WebsiteVisitor, self)._compute_email_phone()
|
|
|
|
for visitor in self.filtered(lambda visitor: not visitor.email or not visitor.mobile):
|
|
linked_registrations = visitor.event_registration_ids.sorted(lambda reg: (reg.create_date, reg.id), reverse=False)
|
|
if not visitor.email:
|
|
visitor.email = next((reg.email for reg in linked_registrations if reg.email), False)
|
|
if not visitor.mobile:
|
|
visitor.mobile = next((reg.mobile or reg.phone for reg in linked_registrations if reg.mobile or reg.phone), False)
|
|
|
|
@api.depends('event_registration_ids')
|
|
def _compute_event_registered_ids(self):
|
|
# include parent's registrations in a visitor o2m field. We don't add
|
|
# child one as child should not have registrations (moved to the parent)
|
|
for visitor in self:
|
|
all_registrations = visitor.event_registration_ids
|
|
visitor.event_registered_ids = all_registrations.mapped('event_id')
|
|
|
|
def _search_event_registered_ids(self, operator, operand):
|
|
""" Search visitors with terms on events within their event registrations. E.g. [('event_registered_ids',
|
|
'in', [1, 2])] should return visitors having a registration on events 1, 2 as
|
|
well as their children for notification purpose. """
|
|
if operator == "not in":
|
|
raise NotImplementedError("Unsupported 'Not In' operation on visitors registrations")
|
|
|
|
all_registrations = self.env['event.registration'].sudo().search([
|
|
('event_id', operator, operand)
|
|
])
|
|
if all_registrations:
|
|
visitor_ids = all_registrations.with_context(active_test=False).visitor_id.ids
|
|
else:
|
|
visitor_ids = []
|
|
|
|
return [('id', 'in', visitor_ids)]
|
|
|
|
def _inactive_visitors_domain(self):
|
|
""" Visitors registered to events are considered always active and should not be deleted. """
|
|
domain = super()._inactive_visitors_domain()
|
|
return expression.AND([domain, [('event_registration_ids', '=', False)]])
|
|
|
|
def _merge_visitor(self, target):
|
|
""" Override linking process to link registrations to the final visitor. """
|
|
self.event_registration_ids.visitor_id = target.id
|
|
registration_wo_partner = self.event_registration_ids.filtered(lambda registration: not registration.partner_id)
|
|
if registration_wo_partner:
|
|
registration_wo_partner.partner_id = target.partner_id
|
|
return super()._merge_visitor(target)
|