From bc86d8c57da74ec9abe21091953e5e8e279e4b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 6 Apr 2020 08:19:53 +0000 Subject: [PATCH 1/3] [IMP] crm: lint data and menu entries PURPOSE Prepare enhancements of sales team membership. SPECIFICATIONS Lint crm data and demo, notably about sales team and file organization. Also move crm menu entries declaration in a single file and remove some menu entries not imported anymore. LINKS Task ID 2086889 (sales team enhancements) Task ID 2234698 (preparation lint) Community PR odoo/odoo#49520 --- addons/crm/__manifest__.py | 24 +-- addons/crm/data/crm_data.xml | 35 ----- addons/crm/data/crm_lost_reason_data.xml | 13 ++ addons/crm/data/crm_team_data.xml | 14 ++ .../data/{crm_demo.xml => crm_team_demo.xml} | 5 - .../data/{crm_lead_data.xml => mail_data.xml} | 7 + addons/crm/models/crm_team.py | 7 +- .../report/crm_opportunity_report_views.xml | 18 +-- .../views/{crm_templates.xml => assets.xml} | 0 addons/crm/views/calendar_views.xml | 5 - addons/crm/views/crm_lead_views.xml | 55 ++----- addons/crm/views/crm_lost_reason_views.xml | 8 +- addons/crm/views/crm_menu_views.xml | 144 +++++++++++++++--- addons/crm/views/crm_stage_views.xml | 10 +- addons/crm/views/crm_team_views.xml | 5 - addons/crm/views/crm_views.xml | 61 -------- addons/crm/views/mail_activity_views.xml | 7 + .../crm/views/res_config_settings_views.xml | 5 + 18 files changed, 207 insertions(+), 216 deletions(-) delete mode 100644 addons/crm/data/crm_data.xml create mode 100644 addons/crm/data/crm_lost_reason_data.xml create mode 100644 addons/crm/data/crm_team_data.xml rename addons/crm/data/{crm_demo.xml => crm_team_demo.xml} (67%) rename addons/crm/data/{crm_lead_data.xml => mail_data.xml} (92%) rename addons/crm/views/{crm_templates.xml => assets.xml} (100%) delete mode 100644 addons/crm/views/crm_views.xml create mode 100644 addons/crm/views/mail_activity_views.xml diff --git a/addons/crm/__manifest__.py b/addons/crm/__manifest__.py index 8c7a6a892f5..839a1e70ef3 100644 --- a/addons/crm/__manifest__.py +++ b/addons/crm/__manifest__.py @@ -26,33 +26,35 @@ 'security/crm_security.xml', 'security/ir.model.access.csv', - 'data/crm_data.xml', - 'data/crm_stage_data.xml', - 'data/crm_lead_data.xml', - 'data/digest_data.xml', 'data/crm_lead_prediction_data.xml', + 'data/crm_lost_reason_data.xml', + 'data/crm_stage_data.xml', + 'data/crm_team_data.xml', + 'data/digest_data.xml', + 'data/mail_data.xml', 'wizard/crm_lead_lost_views.xml', 'wizard/crm_lead_to_opportunity_views.xml', 'wizard/crm_lead_to_opportunity_mass_views.xml', 'wizard/crm_merge_opportunities_views.xml', - 'views/crm_templates.xml', - 'views/res_config_settings_views.xml', - 'views/crm_views.xml', + 'views/assets.xml', + 'views/calendar_views.xml', + 'views/crm_menu_views.xml', 'views/crm_lost_reason_views.xml', 'views/crm_stage_views.xml', 'views/crm_lead_views.xml', - 'views/calendar_views.xml', + 'views/digest_views.xml', + 'views/mail_activity_views.xml', + 'views/res_config_settings_views.xml', 'views/res_partner_views.xml', + 'views/utm_campaign_views.xml', 'report/crm_activity_report_views.xml', 'report/crm_opportunity_report_views.xml', 'views/crm_team_views.xml', - 'views/digest_views.xml', - 'views/utm_campaign_views.xml' ], 'demo': [ - 'data/crm_demo.xml', + 'data/crm_team_demo.xml', 'data/mail_activity_demo.xml', 'data/crm_lead_demo.xml', ], diff --git a/addons/crm/data/crm_data.xml b/addons/crm/data/crm_data.xml deleted file mode 100644 index 0ee888fea90..00000000000 --- a/addons/crm/data/crm_data.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - Too expensive - - - We don't have people/skills - - - Not enough stock - - - diff --git a/addons/crm/data/crm_lost_reason_data.xml b/addons/crm/data/crm_lost_reason_data.xml new file mode 100644 index 00000000000..a13a1d77b34 --- /dev/null +++ b/addons/crm/data/crm_lost_reason_data.xml @@ -0,0 +1,13 @@ + + + + + Too expensive + + + We don't have people/skills + + + Not enough stock + + diff --git a/addons/crm/data/crm_team_data.xml b/addons/crm/data/crm_team_data.xml new file mode 100644 index 00000000000..016777ce78f --- /dev/null +++ b/addons/crm/data/crm_team_data.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/addons/crm/data/crm_demo.xml b/addons/crm/data/crm_team_demo.xml similarity index 67% rename from addons/crm/data/crm_demo.xml rename to addons/crm/data/crm_team_demo.xml index f5f0ed06bed..f04c60baa30 100644 --- a/addons/crm/data/crm_demo.xml +++ b/addons/crm/data/crm_team_demo.xml @@ -1,14 +1,9 @@ - - - - sales - diff --git a/addons/crm/data/crm_lead_data.xml b/addons/crm/data/mail_data.xml similarity index 92% rename from addons/crm/data/crm_lead_data.xml rename to addons/crm/data/mail_data.xml index 52f7575aa79..28253e529b5 100644 --- a/addons/crm/data/crm_lead_data.xml +++ b/addons/crm/data/mail_data.xml @@ -1,6 +1,13 @@ + + + + + + + diff --git a/addons/crm/models/crm_team.py b/addons/crm/models/crm_team.py index 25b1965de97..9161c69116c 100644 --- a/addons/crm/models/crm_team.py +++ b/addons/crm/models/crm_team.py @@ -15,7 +15,9 @@ class Team(models.Model): use_leads = fields.Boolean('Leads', help="Check this box to filter and qualify incoming requests as leads before converting them into opportunities and assigning them to a salesperson.") use_opportunities = fields.Boolean('Pipeline', default=True, help="Check this box to manage a presales process with opportunities.") - alias_id = fields.Many2one('mail.alias', string='Alias', ondelete="restrict", required=True, help="The email address associated with this channel. New emails received will automatically create new leads assigned to the channel.") + alias_id = fields.Many2one( + 'mail.alias', string='Alias', ondelete="restrict", required=True, + help="The email address associated with this channel. New emails received will automatically create new leads assigned to the channel.") # statistics about leads / opportunities / both lead_unassigned_count = fields.Integer( string='# Unassigned Leads', compute='_compute_lead_unassigned_count') @@ -118,6 +120,7 @@ class Team(models.Model): if not use_leads and not use_opportunities: return {'alias_name': False} return {} + # ------------------------------------------------------------ # MESSAGING # ------------------------------------------------------------ @@ -162,7 +165,7 @@ class Team(models.Model): return action def _compute_dashboard_button_name(self): - super(Team,self)._compute_dashboard_button_name() + super(Team, self)._compute_dashboard_button_name() team_with_pipelines = self.filtered(lambda el: el.use_opportunities) team_with_pipelines.update({'dashboard_button_name': _("Pipeline")}) diff --git a/addons/crm/report/crm_opportunity_report_views.xml b/addons/crm/report/crm_opportunity_report_views.xml index cf6eec4bfc7..1d6972d0aaf 100644 --- a/addons/crm/report/crm_opportunity_report_views.xml +++ b/addons/crm/report/crm_opportunity_report_views.xml @@ -123,11 +123,9 @@ teams of the sales pipeline. - + + + Leads Analysis @@ -142,12 +140,8 @@ This report analyses the source of your leads. - + + + diff --git a/addons/crm/views/crm_templates.xml b/addons/crm/views/assets.xml similarity index 100% rename from addons/crm/views/crm_templates.xml rename to addons/crm/views/assets.xml diff --git a/addons/crm/views/calendar_views.xml b/addons/crm/views/calendar_views.xml index b82569b1845..8267a60558d 100644 --- a/addons/crm/views/calendar_views.xml +++ b/addons/crm/views/calendar_views.xml @@ -1,11 +1,6 @@ - - calendar.event.form.inherit calendar.event diff --git a/addons/crm/views/crm_lead_views.xml b/addons/crm/views/crm_lead_views.xml index b7d86291efb..5edbfb84020 100644 --- a/addons/crm/views/crm_lead_views.xml +++ b/addons/crm/views/crm_lead_views.xml @@ -767,28 +767,6 @@ if record: - - - - - - - Leads @@ -839,12 +817,9 @@ if record: - + + + @@ -948,22 +923,10 @@ if record: - - - - - + + + + + + diff --git a/addons/crm/views/crm_lost_reason_views.xml b/addons/crm/views/crm_lost_reason_views.xml index 7f65379bcc0..33986e14da8 100644 --- a/addons/crm/views/crm_lost_reason_views.xml +++ b/addons/crm/views/crm_lost_reason_views.xml @@ -69,9 +69,7 @@ - + + + diff --git a/addons/crm/views/crm_menu_views.xml b/addons/crm/views/crm_menu_views.xml index cbcfe85b201..e679fb8f122 100644 --- a/addons/crm/views/crm_menu_views.xml +++ b/addons/crm/views/crm_menu_views.xml @@ -1,26 +1,126 @@ - + - - + + + - + + + + + - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/crm/views/crm_stage_views.xml b/addons/crm/views/crm_stage_views.xml index 95e2a321990..2dc3a4c7c10 100644 --- a/addons/crm/views/crm_stage_views.xml +++ b/addons/crm/views/crm_stage_views.xml @@ -71,12 +71,8 @@ - + + + diff --git a/addons/crm/views/crm_team_views.xml b/addons/crm/views/crm_team_views.xml index 90301bc7385..a1981660cc3 100644 --- a/addons/crm/views/crm_team_views.xml +++ b/addons/crm/views/crm_team_views.xml @@ -268,9 +268,4 @@ - - ['|', ('res_model_id', '=', False), ('res_model_id.model', 'in', ['crm.lead', 'res.partner'])] - {'default_res_model': 'crm.lead'} - - diff --git a/addons/crm/views/crm_views.xml b/addons/crm/views/crm_views.xml deleted file mode 100644 index 59a07dfb804..00000000000 --- a/addons/crm/views/crm_views.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/crm/views/mail_activity_views.xml b/addons/crm/views/mail_activity_views.xml new file mode 100644 index 00000000000..6b489ee8807 --- /dev/null +++ b/addons/crm/views/mail_activity_views.xml @@ -0,0 +1,7 @@ + + + + ['|', ('res_model_id', '=', False), ('res_model_id.model', 'in', ['crm.lead', 'res.partner'])] + {'default_res_model': 'crm.lead'} + + diff --git a/addons/crm/views/res_config_settings_views.xml b/addons/crm/views/res_config_settings_views.xml index f0cabe5d527..d2ff6b19c98 100644 --- a/addons/crm/views/res_config_settings_views.xml +++ b/addons/crm/views/res_config_settings_views.xml @@ -133,4 +133,9 @@ inline {'module' : 'crm'} + + + + + From 150095ebc7ef112a03f3e6a4704e06cde6e7c5f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 3 Apr 2020 12:17:40 +0000 Subject: [PATCH 2/3] [IMP] sales_team: lint module PURPOSE Prepare enhancements of sales team membership. SPECIFICATIONS Linting containing * reorder fields according to their use; * order methods according to guidelines (compute, CRUD, actions, tools); * fix some docstrings and typos; * remove unused imports and dead code; * rename files according to guidelines; * move views in their own file for mail.activity and assets; * correctly name data and demo files; * rename some inner methods to ease understanding; LINKS Task ID 2086889 (sales team enhancements) Task ID 2234698 (preparation lint) Community PR odoo/odoo#49520 --- addons/sales_team/__manifest__.py | 28 +- addons/sales_team/data/crm_tag_demo.xml | 73 ++-- ...{sales_team_data.xml => crm_team_data.xml} | 0 ...{sales_team_demo.xml => crm_team_demo.xml} | 0 addons/sales_team/models/crm_team.py | 139 +++--- addons/sales_team/models/res_users.py | 2 +- addons/sales_team/views/assets.xml | 8 + addons/sales_team/views/crm_team_views.xml | 394 ++++++++++-------- .../sales_team/views/mail_activity_views.xml | 9 + .../sales_team/views/sales_team_dashboard.xml | 83 ---- 10 files changed, 375 insertions(+), 361 deletions(-) rename addons/sales_team/data/{sales_team_data.xml => crm_team_data.xml} (100%) rename addons/sales_team/data/{sales_team_demo.xml => crm_team_demo.xml} (100%) create mode 100644 addons/sales_team/views/assets.xml create mode 100644 addons/sales_team/views/mail_activity_views.xml delete mode 100644 addons/sales_team/views/sales_team_dashboard.xml diff --git a/addons/sales_team/__manifest__.py b/addons/sales_team/__manifest__.py index 39fae18b93c..d856467e068 100644 --- a/addons/sales_team/__manifest__.py +++ b/addons/sales_team/__manifest__.py @@ -1,26 +1,30 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. + { 'name': 'Sales Teams', 'version': '1.0', 'category': 'Sales/Sales', 'summary': 'Sales Teams', 'description': """ -Using this application you can manage Sales Teams with CRM and/or Sales -=========================================================================== +Using this application you can manage Sales Teams with CRM and/or Sales +======================================================================= """, 'website': 'https://www.odoo.com/page/crm', 'depends': ['base', 'mail'], - 'data': ['security/sales_team_security.xml', - 'security/ir.model.access.csv', - 'data/sales_team_data.xml', - 'views/crm_team_views.xml', - 'views/sales_team_dashboard.xml', - 'views/crm_tag_views.xml', - ], - 'demo': ['data/sales_team_demo.xml', - 'data/crm_tag_demo.xml', - ], + 'data': [ + 'security/sales_team_security.xml', + 'security/ir.model.access.csv', + 'data/crm_team_data.xml', + 'views/assets.xml', + 'views/crm_tag_views.xml', + 'views/crm_team_views.xml', + 'views/mail_activity_views.xml', + ], + 'demo': [ + 'data/crm_team_demo.xml', + 'data/crm_tag_demo.xml', + ], 'installable': True, 'auto_install': False, } diff --git a/addons/sales_team/data/crm_tag_demo.xml b/addons/sales_team/data/crm_tag_demo.xml index 4b409e0bf27..85d61b063ea 100644 --- a/addons/sales_team/data/crm_tag_demo.xml +++ b/addons/sales_team/data/crm_tag_demo.xml @@ -1,39 +1,38 @@ - - + - - - Product - - - - Software - - - - Services - - - - Information - - - - Design - - - - Training - - - - Consulting - - - - Other - - - - + + + Product + + + + Software + + + + Services + + + + Information + + + + Design + + + + Training + + + + Consulting + + + + Other + + + + diff --git a/addons/sales_team/data/sales_team_data.xml b/addons/sales_team/data/crm_team_data.xml similarity index 100% rename from addons/sales_team/data/sales_team_data.xml rename to addons/sales_team/data/crm_team_data.xml diff --git a/addons/sales_team/data/sales_team_demo.xml b/addons/sales_team/data/crm_team_demo.xml similarity index 100% rename from addons/sales_team/data/sales_team_demo.xml rename to addons/sales_team/data/crm_team_demo.xml diff --git a/addons/sales_team/models/crm_team.py b/addons/sales_team/models/crm_team.py index 4b84837c506..ef919653fea 100644 --- a/addons/sales_team/models/crm_team.py +++ b/addons/sales_team/models/crm_team.py @@ -1,16 +1,15 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. - -from babel.dates import format_date -from datetime import date, datetime -from dateutil.relativedelta import relativedelta import json +from babel.dates import format_date +from datetime import date +from dateutil.relativedelta import relativedelta + from odoo import api, fields, models, _ -from odoo.exceptions import AccessError, UserError +from odoo.exceptions import UserError from odoo.release import version -from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF class CrmTeam(models.Model): @@ -38,32 +37,29 @@ class CrmTeam(models.Model): name = fields.Char('Sales Team', required=True, translate=True) sequence = fields.Integer('Sequence', default=10) active = fields.Boolean(default=True, help="If the active field is set to false, it will allow you to hide the Sales Team without removing it.") - company_id = fields.Many2one('res.company', string='Company', - default=lambda self: self.env.company, index=True) + company_id = fields.Many2one( + 'res.company', string='Company', index=True, + default=lambda self: self.env.company) currency_id = fields.Many2one( - "res.currency", related='company_id.currency_id', - string="Currency", readonly=True) + "res.currency", string="Currency", + related='company_id.currency_id', readonly=True) user_id = fields.Many2one('res.users', string='Team Leader', check_company=True) + # memberships member_ids = fields.One2many( - 'res.users', 'sale_team_id', string='Channel Members', check_company=True, - domain=[('share', '=', False)], + 'res.users', 'sale_team_id', string='Channel Members', + check_company=True, domain=[('share', '=', False)], help="Add members to automatically assign their documents to this sales team. You can only be member of one team.") + # UX options + color = fields.Integer(string='Color Index', help="The color of the channel") favorite_user_ids = fields.Many2many( 'res.users', 'team_favorite_user_rel', 'team_id', 'user_id', - string='Favorite Members', - default=_get_default_favorite_user_ids) + string='Favorite Members', default=_get_default_favorite_user_ids) is_favorite = fields.Boolean( - string='Show on dashboard', - compute='_compute_is_favorite', inverse='_inverse_is_favorite', + string='Show on dashboard', compute='_compute_is_favorite', inverse='_inverse_is_favorite', help="Favorite teams to display them in the dashboard and access them easily.") - color = fields.Integer(string='Color Index', help="The color of the channel") dashboard_button_name = fields.Char(string="Dashboard Button", compute='_compute_dashboard_button_name') dashboard_graph_data = fields.Text(compute='_compute_dashboard_graph') - def _compute_dashboard_graph(self): - for team in self: - team.dashboard_graph_data = json.dumps(team._get_graph()) - def _compute_is_favorite(self): for team in self: team.is_favorite = self.env.user in team.favorite_user_ids @@ -75,6 +71,65 @@ class CrmTeam(models.Model): (sudoed_self - to_fav).write({'favorite_user_ids': [(3, self.env.uid)]}) return True + def _compute_dashboard_button_name(self): + """ Sets the adequate dashboard button name depending on the Sales Team's options + """ + for team in self: + team.dashboard_button_name = _("Big Pretty Button :)") # placeholder + + def _compute_dashboard_graph(self): + for team in self: + team.dashboard_graph_data = json.dumps(team._get_dashboard_graph_data()) + + # ------------------------------------------------------------ + # CRUD + # ------------------------------------------------------------ + + @api.model + def create(self, values): + team = super(CrmTeam, self.with_context(mail_create_nosubscribe=True)).create(values) + if values.get('member_ids'): + team._add_members_to_favorites() + return team + + def write(self, values): + res = super(CrmTeam, self).write(values) + if values.get('member_ids'): + self._add_members_to_favorites() + return res + + def unlink(self): + default_teams = [ + self.env.ref('sales_team.salesteam_website_sales'), + self.env.ref('sales_team.pos_sales_team'), + self.env.ref('sales_team.ebay_sales_team') + ] + for team in self: + if team in default_teams: + raise UserError(_('Cannot delete default team "%s"' % (team.name))) + return super(CrmTeam,self).unlink() + + # ------------------------------------------------------------ + # ACTIONS + # ------------------------------------------------------------ + + def action_primary_channel_button(self): + """ Skeleton function to be overloaded It will return the adequate action + depending on the Sales Team's options. """ + return False + + # ------------------------------------------------------------ + # TOOLS + # ------------------------------------------------------------ + + def _add_members_to_favorites(self): + for team in self: + team.favorite_user_ids = [(4, member.id) for member in team.member_ids] + + # ------------------------------------------------------------ + # GRAPH + # ------------------------------------------------------------ + def _graph_get_model(self): """ skeleton function defined here because it'll be called by crm and/or sale """ @@ -146,7 +201,7 @@ class CrmTeam(models.Model): self._cr.execute(query, [self.id, start_date, end_date] + where_clause_params) return self.env.cr.dictfetchall() - def _get_graph(self): + def _get_dashboard_graph_data(self): def get_week_name(start_date, locale): """ Generates a week name (string) from a datetime according to the locale: E.g.: locale start_date (datetime) return string @@ -183,43 +238,3 @@ class CrmTeam(models.Model): [graph_title, graph_key] = self._graph_title_and_key() color = '#875A7B' if '+e' in version else '#7c7bad' return [{'values': values, 'area': True, 'title': graph_title, 'key': graph_key, 'color': color}] - - def _compute_dashboard_button_name(self): - """ Sets the adequate dashboard button name depending on the Sales Team's options - """ - for team in self: - team.dashboard_button_name = _("Big Pretty Button :)") # placeholder - - def action_primary_channel_button(self): - """ skeleton function to be overloaded - It will return the adequate action depending on the Sales Team's options - """ - return False - - @api.model - def create(self, values): - team = super(CrmTeam, self.with_context(mail_create_nosubscribe=True)).create(values) - if values.get('member_ids'): - team._add_members_to_favorites() - return team - - def write(self, values): - res = super(CrmTeam, self).write(values) - if values.get('member_ids'): - self._add_members_to_favorites() - return res - - def unlink(self): - default_teams = [ - self.env.ref('sales_team.salesteam_website_sales'), - self.env.ref('sales_team.pos_sales_team'), - self.env.ref('sales_team.ebay_sales_team') - ] - for team in self: - if team in default_teams: - raise UserError(_('Cannot delete default team "%s"' % (team.name))) - return super(CrmTeam,self).unlink() - - def _add_members_to_favorites(self): - for team in self: - team.favorite_user_ids = [(4, member.id) for member in team.member_ids] diff --git a/addons/sales_team/models/res_users.py b/addons/sales_team/models/res_users.py index 0714af03dce..f2fdd18337a 100644 --- a/addons/sales_team/models/res_users.py +++ b/addons/sales_team/models/res_users.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, fields, models +from odoo import fields, models class ResUsers(models.Model): diff --git a/addons/sales_team/views/assets.xml b/addons/sales_team/views/assets.xml new file mode 100644 index 00000000000..3331b7cf4c1 --- /dev/null +++ b/addons/sales_team/views/assets.xml @@ -0,0 +1,8 @@ + + + + diff --git a/addons/sales_team/views/crm_team_views.xml b/addons/sales_team/views/crm_team_views.xml index 008a40f7d0c..f495e5cd62d 100644 --- a/addons/sales_team/views/crm_team_views.xml +++ b/addons/sales_team/views/crm_team_views.xml @@ -1,182 +1,244 @@ - - + - - - Sales Teams - Search - crm.team - - - - - - - - - - - + + Sales Teams - Search + crm.team + + + + + + + + + + + - - - Sales Teams - crm.team - kanban,form - - {'in_sales_app': True} - -

- Define a new sales team -

- Use Sales Teams to organize your sales departments. - Each team will work with a separate pipeline. -

-
-
- - - Team Pipelines - crm.team - kanban,form - - {} - -

- Define a new sales team -

- Use Sales Teams to organize your sales departments. - Each team will work with a separate pipeline. -

-
-
- - - - - crm.team.form - crm.team - -
- -
- -
-