[IMP] calendar, crm, hr_holidays: move meeting stat button to calendar

Move the meeting stat button and kanban pill from CRM to Calendar, purpose is to
allow its usage even if CRM is not installed as this makes more sense since this
field is usually related to Calendar.

Increase query number limit in company leave test, in order to take into account
the newly introduced query in Calendar.

UPG-PR: https://github.com/odoo/upgrade/pull/2423

Task-2514473

closes odoo/odoo#69846

Related: odoo/upgrade#2423
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
nounoubensebia
2021-04-28 14:05:07 +00:00
parent 907d129bdd
commit d01e5c5cdb
6 changed files with 97 additions and 60 deletions
+1
View File
@@ -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,
+52
View File
@@ -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
@@ -0,0 +1,43 @@
<?xml version="1.0"?>
<odoo>
<!-- Partner kanban view inherit -->
<record id="res_partner_kanban_view" model="ir.ui.view">
<field name="name">res.partner.view.kanban.calendar</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="priority" eval="10"/>
<field name="arch" type="xml">
<field name="mobile" position="after">
<field name="meeting_count"/>
</field>
<xpath expr="//span[hasclass('oe_kanban_partner_links')]" position="inside">
<span class="badge badge-pill" t-if="record.meeting_count.value>0">
<i class="fa fa-fw fa-calendar" aria-label="Meetings" role="img" title="Meetings"/>
<t t-esc="record.meeting_count.value"/>
</span>
</xpath>
</field>
</record>
<!-- Add contextual button on partner form view -->
<record id="view_partners_form" model="ir.ui.view">
<field name="name">res_partner.view.form.calendar</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field eval="1" name="priority"/>
<field name="arch" type="xml">
<data>
<div name="button_box" position="inside">
<button class="oe_stat_button" type="object"
name="schedule_meeting"
icon="fa-calendar"
context="{'partner_id': active_id, 'partner_name': name}">
<field string="Meetings" name="meeting_count" widget="statinfo"/>
</button>
</div>
</data>
</field>
</record>
</odoo>
-51
View File
@@ -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.
-8
View File
@@ -15,7 +15,6 @@
</field>
<xpath expr="//span[hasclass('oe_kanban_partner_links')]" position="inside">
<span class="badge badge-pill" t-if="record.opportunity_count.value>0"><i class="fa fa-fw fa-star" aria-label="Favorites" role="img" title="Favorites"/><t t-esc="record.opportunity_count.value"/></span>
<span class="badge badge-pill" t-if="record.meeting_count.value>0"><i class="fa fa-fw fa-calendar" aria-label="Meetings" role="img" title="Meetings"/><t t-esc="record.meeting_count.value"/></span>
</xpath>
</field>
</record>
@@ -37,13 +36,6 @@
context="{'default_partner_id': active_id}">
<field string="Opportunities" name="opportunity_count" widget="statinfo"/>
</button>
<button class="oe_stat_button" type="object"
name="schedule_meeting"
icon="fa-calendar"
groups="sales_team.group_sale_salesman"
context="{'partner_id': active_id, 'partner_name': name}">
<field string="Meetings" name="meeting_count" widget="statinfo"/>
</button>
</div>
</data>
</field>
@@ -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()