diff --git a/addons/calendar/__manifest__.py b/addons/calendar/__manifest__.py index 8e068662534..a34889b121b 100644 --- a/addons/calendar/__manifest__.py +++ b/addons/calendar/__manifest__.py @@ -32,6 +32,7 @@ If you need to manage your meetings, you should install the CRM module. 'views/mail_activity_views.xml', 'views/calendar_templates.xml', 'views/calendar_views.xml', + 'views/res_partner_views.xml', ], 'installable': True, 'application': True, diff --git a/addons/calendar/models/res_partner.py b/addons/calendar/models/res_partner.py index 2cfe4551337..47d3b5ca5a6 100644 --- a/addons/calendar/models/res_partner.py +++ b/addons/calendar/models/res_partner.py @@ -9,9 +9,50 @@ from odoo import api, fields, models class Partner(models.Model): _inherit = 'res.partner' + meeting_count = fields.Integer("# Meetings", compute='_compute_meeting_count') + meeting_ids = fields.Many2many('calendar.event', 'calendar_event_res_partner_rel', 'res_partner_id', + 'calendar_event_id', string='Meetings', copy=False) + calendar_last_notif_ack = fields.Datetime( 'Last notification marked as read from base Calendar', default=fields.Datetime.now) + def _compute_meeting_count(self): + result = self._compute_meeting() + for p in self: + p.meeting_count = len(result.get(p.id, [])) + + def _compute_meeting(self): + if self.ids: + all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) + self.env.cr.execute(""" + SELECT res_partner_id, calendar_event_id, count(1) + FROM calendar_event_res_partner_rel + WHERE res_partner_id IN %s + GROUP BY res_partner_id, calendar_event_id + """, [tuple(all_partners.ids)]) + meeting_data = self.env.cr.fetchall() + + # Keep only valid meeting data based on record rules of events + events = [row[1] for row in meeting_data] + events = self.env['calendar.event'].search([('id', 'in', events)]).ids + meeting_data = [m for m in meeting_data if m[1] in events] + + # Create a dict {partner_id: event_ids} and fill with events linked to the partner + meetings = {p.id: set() for p in all_partners} + for m in meeting_data: + meetings[m[0]].add(m[1]) + + # Add the events linked to the children of the partner + all_partners.read(['parent_id']) + for p in all_partners: + partner = p + while partner: + if partner in self: + meetings[partner.id] |= meetings[p.id] + partner = partner.parent_id + return {p.id: list(meetings[p.id]) for p in self} + return {} + def get_attendee_detail(self, meeting_ids): """ Return a list of dict of the given meetings with the attendees details Used by: @@ -40,3 +81,14 @@ class Partner(models.Model): def _set_calendar_last_notif_ack(self): partner = self.env['res.users'].browse(self.env.context.get('uid', self.env.uid)).partner_id partner.write({'calendar_last_notif_ack': datetime.now()}) + + def schedule_meeting(self): + self.ensure_one() + partner_ids = self.ids + partner_ids.append(self.env.user.partner_id.id) + action = self.env["ir.actions.actions"]._for_xml_id("calendar.action_calendar_event") + action['context'] = { + 'default_partner_ids': partner_ids, + } + action['domain'] = ['|', ('id', 'in', self._compute_meeting()[self.id]), ('partner_ids', 'in', self.ids)] + return action diff --git a/addons/calendar/views/res_partner_views.xml b/addons/calendar/views/res_partner_views.xml new file mode 100644 index 00000000000..0542d010134 --- /dev/null +++ b/addons/calendar/views/res_partner_views.xml @@ -0,0 +1,43 @@ + + + + + + res.partner.view.kanban.calendar + res.partner + + + + + + + + + + + + + + + + + + res_partner.view.form.calendar + res.partner + + + + +
+ +
+
+
+
+ +
diff --git a/addons/crm/models/res_partner.py b/addons/crm/models/res_partner.py index 45a8bb2dadc..1110025ed6f 100644 --- a/addons/crm/models/res_partner.py +++ b/addons/crm/models/res_partner.py @@ -10,9 +10,7 @@ class Partner(models.Model): team_id = fields.Many2one('crm.team', string='Sales Team') opportunity_ids = fields.One2many('crm.lead', 'partner_id', string='Opportunities', domain=[('type', '=', 'opportunity')]) - meeting_ids = fields.Many2many('calendar.event', 'calendar_event_res_partner_rel', 'res_partner_id', 'calendar_event_id', string='Meetings', copy=False) opportunity_count = fields.Integer("Opportunity", compute='_compute_opportunity_count') - meeting_count = fields.Integer("# Meetings", compute='_compute_meeting_count') @api.model def default_get(self, fields): @@ -54,55 +52,6 @@ class Partner(models.Model): partner.opportunity_count += group['partner_id_count'] partner = partner.parent_id - def _compute_meeting_count(self): - result = self._compute_meeting() - for p in self: - p.meeting_count = len(result.get(p.id, [])) - - def _compute_meeting(self): - if self.ids: - all_partners = self.with_context(active_test=False).search([('id', 'child_of', self.ids)]) - self.env.cr.execute(""" - SELECT res_partner_id, calendar_event_id, count(1) - FROM calendar_event_res_partner_rel - WHERE res_partner_id IN %s - GROUP BY res_partner_id, calendar_event_id - """, [tuple(all_partners.ids)]) - meeting_data = self.env.cr.fetchall() - - # Keep only valid meeting data based on record rules of events - events = [row[1] for row in meeting_data] - events = self.env['calendar.event'].search([('id', 'in', events)]).ids - meeting_data = [m for m in meeting_data if m[1] in events] - - # Create a dict {partner_id: event_ids} and fill with events linked to the partner - meetings = {p.id: set() for p in all_partners} - for m in meeting_data: - meetings[m[0]].add(m[1]) - - # Add the events linked to the children of the partner - all_partners.read(['parent_id']) - for p in all_partners: - partner = p - while partner: - if partner in self: - meetings[partner.id] |= meetings[p.id] - partner = partner.parent_id - return {p.id: list(meetings[p.id]) for p in self} - return {} - - - def schedule_meeting(self): - self.ensure_one() - partner_ids = self.ids - partner_ids.append(self.env.user.partner_id.id) - action = self.env["ir.actions.actions"]._for_xml_id("calendar.action_calendar_event") - action['context'] = { - 'default_partner_ids': partner_ids, - } - action['domain'] = ['|', ('id', 'in', self._compute_meeting()[self.id]), ('partner_ids', 'in', self.ids)] - return action - def action_view_opportunity(self): ''' This function returns an action that displays the opportunities from partner. diff --git a/addons/crm/views/res_partner_views.xml b/addons/crm/views/res_partner_views.xml index 009f7d6f817..10947a6eb59 100644 --- a/addons/crm/views/res_partner_views.xml +++ b/addons/crm/views/res_partner_views.xml @@ -15,7 +15,6 @@ - @@ -37,13 +36,6 @@ context="{'default_partner_id': active_id}"> - diff --git a/addons/hr_holidays/tests/test_company_leave.py b/addons/hr_holidays/tests/test_company_leave.py index 53b528a5cc8..da2b444617f 100644 --- a/addons/hr_holidays/tests/test_company_leave.py +++ b/addons/hr_holidays/tests/test_company_leave.py @@ -313,7 +313,7 @@ class TestCompanyLeave(TransactionCase): }) company_leave._compute_date_from_to() - with self.assertQueryCount(__system__=842, admin=865): + with self.assertQueryCount(__system__=843, admin=865): # Original query count: 1987 # Without tracking/activity context keys: 5154 company_leave.action_validate()