[MERGE] crm, sales_team: lint modules and clean tests to prepare sales team enhancements

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.

Lint sales_team module. 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;

Clean sales team tests and extract common test data from crm

LINKS

Task ID 2086889 (sales team enhancements)
Task ID 2234698 (preparation lint)
Community PR #49520

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Odoo's Mergebot
2020-04-14 14:33:22 +02:00
committed by GitHub
33 changed files with 716 additions and 660 deletions
+13 -11
View File
@@ -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',
],
-35
View File
@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="sales_team.salesteam_website_sales" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
<record id="sales_team.pos_sales_team" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
<record id="sales_team.ebay_sales_team" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
<!--default alias for leads-->
<record id="mail_alias_lead_info" model="mail.alias">
<field name="alias_name"></field>
<field name="alias_model_id" ref="model_crm_lead"/>
<field name="alias_user_id" ref="base.user_admin"/>
<field name="alias_parent_model_id" ref="model_crm_team"/>
</record>
<!-- opportunities' lost causes -->
<record id="lost_reason_1" model="crm.lost.reason">
<field name="name">Too expensive</field>
</record>
<record id="lost_reason_2" model="crm.lost.reason">
<field name="name">We don't have people/skills</field>
</record>
<record id="lost_reason_3" model="crm.lost.reason">
<field name="name">Not enough stock</field>
</record>
</data>
</odoo>
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo><data noupdate="1">
<!-- opportunities' lost causes -->
<record id="lost_reason_1" model="crm.lost.reason">
<field name="name">Too expensive</field>
</record>
<record id="lost_reason_2" model="crm.lost.reason">
<field name="name">We don't have people/skills</field>
</record>
<record id="lost_reason_3" model="crm.lost.reason">
<field name="name">Not enough stock</field>
</record>
</data></odoo>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo><data noupdate="1">
<record id="sales_team.salesteam_website_sales" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
<record id="sales_team.pos_sales_team" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
<record id="sales_team.ebay_sales_team" model="crm.team" forcecreate="False">
<field name="use_opportunities" eval="False"/>
</record>
</data></odoo>
@@ -1,14 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="base.user_demo" model="res.users">
<field name="groups_id" eval="[(4,ref('sales_team.group_sale_salesman'))]"/>
</record>
<record id="sales_team.team_sales_department" model="crm.team" forcecreate="False">
<field name="alias_name">sales</field>
<field name="alias_user_id" ref="base.user_admin"/>
<field name="company_id" eval="False"/>
</record>
<record id="sales_team.crm_team_1" model="crm.team">
@@ -1,6 +1,13 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<!--default alias for leads-->
<record id="mail_alias_lead_info" model="mail.alias">
<field name="alias_name"></field>
<field name="alias_model_id" ref="model_crm_lead"/>
<field name="alias_user_id" ref="base.user_admin"/>
<field name="alias_parent_model_id" ref="model_crm_team"/>
</record>
<!-- CRM-related subtypes for messaging / Chatter -->
<record id="mt_lead_create" model="mail.message.subtype">
+5 -2
View File
@@ -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")})
@@ -123,11 +123,9 @@
teams of the sales pipeline.</field>
</record>
<menuitem id="crm_opportunity_report_menu"
name="Pipeline"
parent="crm_menu_report"
action="crm_opportunity_report_action"
sequence="2"/>
<record id="crm_opportunity_report_menu" model="ir.ui.menu">
<field name="action" ref="crm.crm_opportunity_report_action"/>
</record>
<record id="crm_opportunity_report_action_lead" model="ir.actions.act_window">
<field name="name">Leads Analysis</field>
@@ -142,12 +140,8 @@
<field name="help">This report analyses the source of your leads.</field>
</record>
<menuitem
id="crm_opportunity_report_menu_lead"
name="Leads"
parent="crm_menu_report"
action="crm_opportunity_report_action_lead"
groups="crm.group_use_lead"
sequence="1"/>
<record id="crm_opportunity_report_menu_lead" model="ir.ui.menu">
<field name="action" ref="crm.crm_opportunity_report_action_lead"/>
</record>
</odoo>
+7 -29
View File
@@ -4,8 +4,8 @@
from unittest.mock import patch
from odoo.addons.mail.tests.common import MailCase, mail_new_test_user
from odoo.addons.sales_team.tests.common import TestSalesCommon
from odoo.fields import Datetime
from odoo.tests.common import SavepointCase
INCOMING_EMAIL = """Return-Path: {return_path}
X-Original-To: {to}
@@ -39,43 +39,21 @@ Cheers,
Somebody."""
class TestCrmCommon(SavepointCase, MailCase):
class TestCrmCommon(TestSalesCommon, MailCase):
@classmethod
def setUpClass(cls):
super(TestCrmCommon, cls).setUpClass()
cls._init_mail_gateway()
cls.user_sales_manager = mail_new_test_user(
cls.env, login='user_sales_manager',
name='Martin Sales Manager', email='crm_manager@test.example.com',
company_id=cls.env.ref("base.main_company").id,
notification_type='inbox',
groups='sales_team.group_sale_manager,base.group_partner_manager,crm.group_use_lead',
)
cls.user_sales_leads = mail_new_test_user(
cls.env, login='user_sales_leads',
name='Laetitia Sales Leads', email='crm_leads@test.example.com',
company_id=cls.env.ref("base.main_company").id,
notification_type='inbox',
groups='sales_team.group_sale_salesman_all_leads,base.group_partner_manager,crm.group_use_lead',
)
cls.user_sales_salesman = mail_new_test_user(
cls.env, login='user_sales_salesman',
name='Orteil Sales Own', email='crm_salesman@test.example.com',
company_id=cls.env.ref("base.main_company").id,
notification_type='inbox',
groups='sales_team.group_sale_salesman,crm.group_use_lead',
)
cls.sales_team_1 = cls.env['crm.team'].create({
'name': 'Test Sales Team',
cls.sales_team_1.write({
'alias_name': 'sales.test',
'use_leads': True,
'use_opportunities': True,
'company_id': False,
'user_id': cls.user_sales_manager.id,
'member_ids': [(4, cls.user_sales_leads.id), (4, cls.env.ref('base.user_admin').id)],
})
(cls.user_sales_manager | cls.user_sales_leads | cls.user_sales_salesman).write({
'groups_id': [(4, cls.env.ref('crm.group_use_lead').id)]
})
cls.env['crm.stage'].search([]).write({'sequence': 9999}) # ensure search will find test data first
-5
View File
@@ -1,11 +1,6 @@
<?xml version="1.0"?>
<odoo>
<menuitem
id="menu_import_crm"
name="Import &amp; Synchronize"
parent="crm_menu_root"/>
<record id="view_crm_meeting_search" model="ir.ui.view">
<field name="name">calendar.event.form.inherit</field>
<field name="model">calendar.event</field>
+9 -46
View File
@@ -767,28 +767,6 @@ if record:
</field>
</record>
<!--
Menu Actions
-->
<menuitem
id="crm_menu_sales"
name="Sales"
parent="crm_menu_root"
sequence="1"/>
<menuitem id="sales_team_menu_team_pipeline"
name="Team Pipelines"
parent="crm_menu_sales"
action="sales_team.crm_team_salesteams_pipelines_act"
groups="sales_team.group_sale_manager"
sequence="4"/>
<menuitem id="res_partner_menu_customer"
name="Customers"
parent="crm_menu_sales"
action="base.action_partner_form"
sequence="5"/>
<!-- Lead Menu -->
<record model="ir.actions.act_window" id="crm_lead_all_leads">
<field name="name">Leads</field>
@@ -839,12 +817,9 @@ if record:
<field name="act_window_id" ref="crm_lead_all_leads"/>
</record>
<menuitem id="crm_menu_leads"
name="Leads"
parent="crm_menu_root"
groups="crm.group_use_lead"
action="crm_lead_all_leads"
sequence="5"/>
<record id="crm_menu_leads" model="ir.ui.menu">
<field name="action" ref="crm.crm_lead_all_leads"/>
</record>
<!-- 'My Pipeline' menu : Server action, act_window_views and act_windows -->
<record model="ir.actions.act_window" id="crm_lead_opportunities">
@@ -948,22 +923,10 @@ if record:
<field name="act_window_id" ref="crm_lead_action_pipeline"/>
</record>
<menuitem
id="menu_crm_opportunities"
action="action_your_pipeline"
name="My Pipeline"
parent="crm_menu_sales"
sequence="1"/>
<menuitem
id="crm.crm_menu_root"
name="CRM"
action="action_your_pipeline"/>
<menuitem
id="menu_crm_lead_categ"
name="Tags"
action="sales_team.sales_team_crm_tag_action"
parent="menu_crm_config_lead"
sequence="1"/>
<record id="menu_crm_opportunities" model="ir.ui.menu">
<field name="action" ref="crm.action_your_pipeline"/>
</record>
<record id="crm_menu_root" model="ir.ui.menu">
<field name="action" ref="crm.action_your_pipeline"/>
</record>
</odoo>
+3 -5
View File
@@ -69,9 +69,7 @@
</field>
</record>
<menuitem
id="menu_crm_lost_reason"
action="crm_lost_reason_action"
parent="menu_crm_config_lead"
sequence="6"/>
<record id="menu_crm_lost_reason" model="ir.ui.menu">
<field name="action" ref="crm.crm_lost_reason_action"/>
</record>
</odoo>
+122 -22
View File
@@ -1,26 +1,126 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<menuitem
id="crm_menu_sales"
name="Sales"
parent="crm_menu_root"
sequence="1"/>
<menuitem id="sales_team_menu_team_pipeline"
name="Team Pipelines"
parent="crm_menu_sales"
action="crm_team_salesteams_pipelines_act"
sequence="4"/>
<!-- Top menu item -->
<!--
This menu item's purpose is to overwrite another one defined in
the base module in order to set new groups.
-->
<menuitem
id="crm_menu_root"
name="CRM"
web_icon="crm,static/description/icon.png"
groups="sales_team.group_sale_salesman,sales_team.group_sale_manager"
sequence="6"/>
<menuitem id="res_partner_menu_customer"
name="Customers"
parent="crm_menu_sales"
action="base.action_partner_form"
sequence="5"/>
<!-- SALES (MAIN USER MENU) -->
<menuitem
id="crm_menu_sales"
name="Sales"
parent="crm_menu_root"
sequence="1"/>
<menuitem
id="menu_crm_opportunities"
name="My Pipeline"
parent="crm_menu_sales"
sequence="1"/>
<menuitem
id="sales_team_menu_team_pipeline"
name="Team Pipelines"
parent="crm_menu_sales"
action="sales_team.crm_team_salesteams_pipelines_act"
groups="sales_team.group_sale_manager"
sequence="4"/>
<menuitem
id="res_partner_menu_customer"
name="Customers"
parent="crm_menu_sales"
action="base.action_partner_form"
sequence="5"/>
<menuitem id="crm_menu_leads"
name="Leads"
parent="crm_menu_root"
groups="crm.group_use_lead"
sequence="5"/>
</odoo>
<!-- LEADS (MAIN USER MENU) -->
<menuitem
id="crm_menu_leads"
name="Leads"
parent="crm_menu_root"
groups="crm.group_use_lead"
sequence="5"/>
<!-- REPORTING -->
<menuitem
id="crm_menu_report"
name="Reporting"
parent="crm_menu_root"
sequence="20"
groups="sales_team.group_sale_manager"/>
<menuitem
id="crm_opportunity_report_menu_lead"
name="Leads"
parent="crm_menu_report"
groups="crm.group_use_lead"
sequence="1"/>
<menuitem
id="crm_opportunity_report_menu"
name="Pipeline"
parent="crm_menu_report"
sequence="2"/>
<!-- CONFIGURATION -->
<menuitem
id="crm_menu_config"
name="Configuration"
parent="crm_menu_root"
sequence="25" groups="sales_team.group_sale_manager"/>
<menuitem
id="crm_config_settings_menu"
name="Settings"
parent="crm_menu_config"
groups="base.group_system"
sequence="0"/>
<menuitem
id="menu_crm_config_opportunity"
name="Opportunities"
parent="crm_menu_config"
sequence="1"
groups="sales_team.group_sale_manager"/>
<menuitem
id="crm_team_config"
name="Sales Teams"
parent="crm_menu_config"
action="sales_team.sales_team_config_action"
sequence="5"/>
<menuitem
id="crm_team_menu_config_activity_types"
name="Activity Types"
parent="crm_menu_config"
action="sales_team.mail_activity_type_action_config_sales"
sequence="10"/>
<menuitem
id="menu_crm_config_lead"
name="Pipeline"
parent="crm_menu_config"
sequence="15"
groups="sales_team.group_sale_manager"/>
<menuitem
id="menu_crm_lead_stage_act"
name="Stages"
sequence="0"
parent="menu_crm_config_lead"
groups="base.group_no_one"/>
<menuitem
id="menu_crm_lead_categ"
name="Tags"
action="sales_team.sales_team_crm_tag_action"
parent="menu_crm_config_lead"
sequence="1"/>
<menuitem
id="menu_crm_lost_reason"
name="Lost Reasons"
parent="menu_crm_config_lead"
sequence="6"/>
<menuitem
id="menu_import_crm"
name="Import &amp; Synchronize"
parent="crm_menu_root"/>
</odoo>
+3 -7
View File
@@ -71,12 +71,8 @@
</field>
</record>
<menuitem
id="menu_crm_lead_stage_act"
name="Stages"
sequence="0"
action="crm_stage_action"
parent="menu_crm_config_lead"
groups="base.group_no_one"/>
<record id="menu_crm_lead_stage_act" model="ir.ui.menu">
<field name="action" ref="crm.crm_stage_action"/>
</record>
</odoo>
-5
View File
@@ -268,9 +268,4 @@
</field>
</record>
<record id="sales_team.mail_activity_type_action_config_sales" model="ir.actions.act_window">
<field name="domain">['|', ('res_model_id', '=', False), ('res_model_id.model', 'in', ['crm.lead', 'res.partner'])]</field>
<field name="context">{'default_res_model': 'crm.lead'}</field>
</record>
</odoo>
-61
View File
@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Top menu item -->
<!--
This menu item's purpose is to overwrite another one defined in
the base module in order to set new groups.
-->
<menuitem
id="crm_menu_root"
name="CRM"
web_icon="crm,static/description/icon.png"
groups="sales_team.group_sale_salesman,sales_team.group_sale_manager"
sequence="6"/>
<menuitem
id="crm_menu_config"
name="Configuration"
parent="crm_menu_root"
sequence="25" groups="sales_team.group_sale_manager"/>
<menuitem
id="menu_crm_config_lead"
name="Pipeline"
parent="crm_menu_config"
sequence="15"
groups="sales_team.group_sale_manager"/>
<menuitem
id="menu_crm_config_opportunity"
name="Opportunities"
parent="crm_menu_config"
sequence="1"
groups="sales_team.group_sale_manager"/>
<menuitem id="crm_config_settings_menu"
name="Settings"
parent="crm_menu_config"
action="crm_config_settings_action"
groups="base.group_system"
sequence="0"/>
<menuitem id="crm_menu_report"
name="Reporting"
parent="crm_menu_root"
sequence="20"
groups="sales_team.group_sale_manager"/>
<menuitem id="crm_team_config"
name="Sales Teams"
parent="crm_menu_config"
action="sales_team.sales_team_config_action"
sequence="5"/>
<menuitem id="crm_team_menu_config_activity_types"
name="Activity Types"
parent="crm_menu_config"
action="sales_team.mail_activity_type_action_config_sales"
sequence="10"/>
</odoo>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="sales_team.mail_activity_type_action_config_sales" model="ir.actions.act_window">
<field name="domain">['|', ('res_model_id', '=', False), ('res_model_id.model', 'in', ['crm.lead', 'res.partner'])]</field>
<field name="context">{'default_res_model': 'crm.lead'}</field>
</record>
</odoo>
@@ -133,4 +133,9 @@
<field name="target">inline</field>
<field name="context">{'module' : 'crm'}</field>
</record>
<record id="crm_config_settings_menu" model="ir.ui.menu">
<field name="action" ref="crm.crm_config_settings_action"/>
</record>
</odoo>
+16 -12
View File
@@ -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,
}
+36 -37
View File
@@ -1,39 +1,38 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<odoo><data noupdate="1">
<!-- crm categories -->
<record id="categ_oppor1" model="crm.tag">
<field name="name">Product</field>
<field name="color" eval="1"/>
</record>
<record id="categ_oppor2" model="crm.tag">
<field name="name">Software</field>
<field name="color" eval="2"/>
</record>
<record id="categ_oppor3" model="crm.tag">
<field name="name">Services</field>
<field name="color" eval="3"/>
</record>
<record id="categ_oppor4" model="crm.tag">
<field name="name">Information</field>
<field name="color" eval="4"/>
</record>
<record id="categ_oppor5" model="crm.tag">
<field name="name">Design</field>
<field name="color" eval="5"/>
</record>
<record id="categ_oppor6" model="crm.tag">
<field name="name">Training</field>
<field name="color" eval="6"/>
</record>
<record id="categ_oppor7" model="crm.tag">
<field name="name">Consulting</field>
<field name="color" eval="7"/>
</record>
<record id="categ_oppor8" model="crm.tag">
<field name="name">Other</field>
<field name="color" eval="8"/>
</record>
</data>
</odoo>
<!-- crm categories -->
<record id="categ_oppor1" model="crm.tag">
<field name="name">Product</field>
<field name="color" eval="1"/>
</record>
<record id="categ_oppor2" model="crm.tag">
<field name="name">Software</field>
<field name="color" eval="2"/>
</record>
<record id="categ_oppor3" model="crm.tag">
<field name="name">Services</field>
<field name="color" eval="3"/>
</record>
<record id="categ_oppor4" model="crm.tag">
<field name="name">Information</field>
<field name="color" eval="4"/>
</record>
<record id="categ_oppor5" model="crm.tag">
<field name="name">Design</field>
<field name="color" eval="5"/>
</record>
<record id="categ_oppor6" model="crm.tag">
<field name="name">Training</field>
<field name="color" eval="6"/>
</record>
<record id="categ_oppor7" model="crm.tag">
<field name="name">Consulting</field>
<field name="color" eval="7"/>
</record>
<record id="categ_oppor8" model="crm.tag">
<field name="name">Other</field>
<field name="color" eval="8"/>
</record>
</data></odoo>
+77 -62
View File
@@ -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]
+1 -1
View File
@@ -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):
+5 -1
View File
@@ -1 +1,5 @@
from . import test_default_team
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import common
from . import test_sales_team_membership
+62
View File
@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.tests.common import SavepointCase
class TestSalesCommon(SavepointCase):
@classmethod
def setUpClass(cls):
super(TestSalesCommon, cls).setUpClass()
cls.company_main = cls.env.user.company_id
cls.user_sales_manager = mail_new_test_user(
cls.env, login='user_sales_manager',
name='Martin Sales Manager', email='crm_manager@test.example.com',
company_id=cls.company_main.id,
notification_type='inbox',
groups='sales_team.group_sale_manager,base.group_partner_manager',
)
cls.user_sales_leads = mail_new_test_user(
cls.env, login='user_sales_leads',
name='Laetitia Sales Leads', email='crm_leads@test.example.com',
company_id=cls.company_main.id,
notification_type='inbox',
groups='sales_team.group_sale_salesman_all_leads,base.group_partner_manager',
)
cls.user_sales_salesman = mail_new_test_user(
cls.env, login='user_sales_salesman',
name='Orteil Sales Own', email='crm_salesman@test.example.com',
company_id=cls.company_main.id,
notification_type='inbox',
groups='sales_team.group_sale_salesman',
)
cls.env['crm.team'].search([]).write({'sequence': 9999})
cls.sales_team_1 = cls.env['crm.team'].create({
'name': 'Test Sales Team',
'sequence': 5,
'company_id': False,
'user_id': cls.user_sales_manager.id,
'member_ids': [(4, cls.user_sales_leads.id), (4, cls.env.ref('base.user_admin').id)],
})
class TestSalesMC(TestSalesCommon):
""" Multi Company / Multi Sales Team environment """
@classmethod
def setUpClass(cls):
super(TestSalesMC, cls).setUpClass()
cls.company_2 = cls.env['res.company'].create({
'name': 'New Test Company',
'email': 'company.2@test.example.com',
'country_id': cls.env.ref('base.fr'),
})
cls.team_c2 = cls.env['crm.team'].create({
'name': 'C2 Team1',
'sequence': 1,
'company_id': cls.company_2.id,
})
@@ -1,53 +0,0 @@
from odoo.tests import common
class TestDefaultTeam(common.SavepointCase):
"""Tests to check if correct default team is found."""
@classmethod
def setUpClass(cls):
"""Set up data for default team tests."""
super(TestDefaultTeam, cls).setUpClass()
cls.CrmTeam = cls.env['crm.team']
ResUsers = cls.env['res.users'].with_context(
{'no_reset_password': True})
group_sale_manager = cls.env.ref('sales_team.group_sale_manager')
cls.user = ResUsers.create({
'name': 'Team User',
'login': 'sales_team_user',
'email': 'sales.team.user@example.com',
'groups_id': [(6, 0, [group_sale_manager.id])]
})
cls.team_1 = cls.env['crm.team'].create({
'name': 'Test Team',
'member_ids': [(4, cls.user.id)],
'company_id': False
})
# Europe Team (fall back team)
cls.team_2 = cls.env.ref('sales_team.team_sales_department')
cls.team_3 = cls.env['crm.team'].create({
'name': 'Team 3',
'sequence': 2,
'company_id': False
})
def test_01_user_team(self):
"""Get default team, when user belongs to one."""
team = self.CrmTeam.with_user(self.user)._get_default_team_id()
self.assertEqual(team, self.team_1)
def test_02_fallback_team(self):
"""Get default team when user does not belong to any team.
Case 1: fall back default team (from XML ref) is active.
Case 2: fall back default team is not active.
"""
# Clear users from team.
self.team_1.member_ids = [(5,)]
# Case 1.
team = self.CrmTeam.with_user(self.user)._get_default_team_id()
self.assertEqual(team, self.team_2)
# Case 2. If default team is not active, fall back is the next team with the higher sequence
self.team_2.active = False
team = self.CrmTeam.with_user(self.user)._get_default_team_id()
self.assertEqual(team, self.team_3)
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.sales_team.tests.common import TestSalesMC
class TestDefaultTeam(TestSalesMC):
"""Tests to check if correct default team is found."""
@classmethod
def setUpClass(cls):
"""Set up data for default team tests."""
super(TestDefaultTeam, cls).setUpClass()
cls.team_sequence = cls.env['crm.team'].create({
'name': 'Team LowSequence',
'sequence': 0,
'company_id': False,
})
cls.team_responsible = cls.env['crm.team'].create({
'name': 'Team 3',
'user_id': cls.user_sales_manager.id,
'sequence': 3,
'company_id': cls.company_main.id
})
def test_default_team_member(self):
with self.with_user('user_sales_leads'):
team = self.env['crm.team']._get_default_team_id()
self.assertEqual(team, self.sales_team_1)
# responsible with lower sequence better than member with higher sequence
self.team_responsible.user_id = self.user_sales_leads.id
with self.with_user('user_sales_leads'):
team = self.env['crm.team']._get_default_team_id()
self.assertEqual(team, self.team_responsible)
def test_default_team_fallback(self):
""" Test fallback: domain, order """
self.sales_team_1.member_ids = [(5,)]
with self.with_user('user_sales_leads'):
team = self.env['crm.team']._get_default_team_id()
self.assertEqual(team, self.team_sequence)
# next one is team_responsible with sequence = 3 (team_c2 is in another company)
self.team_sequence.active = False
with self.with_user('user_sales_leads'):
team = self.env['crm.team']._get_default_team_id()
self.assertEqual(team, self.team_responsible)
self.user_sales_leads.write({
'company_ids': [(4, self.company_2.id)],
'company_id': self.company_2.id,
})
# multi company: switch company
self.user_sales_leads.write({'company_id': self.company_2.id})
with self.with_user('user_sales_leads'):
team = self.env['crm.team']._get_default_team_id()
self.assertEqual(team, self.team_c2)
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets_backend" name="sales_team assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/sales_team/static/src/scss/sales_team_dashboard.scss"/>
</xpath>
</template>
</odoo>
+228 -166
View File
@@ -1,182 +1,244 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<odoo><data>
<!-- Sales Teams Search view -->
<record id="crm_team_salesteams_search" model="ir.ui.view">
<field name="name">Sales Teams - Search</field>
<field name="model">crm.team</field>
<field name="arch" type="xml">
<search string="Salesteams Search">
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<field name="name"/>
<field name="user_id"/>
<group expand="0" string="Group By...">
<filter string="Team Leader" name="team_leader" domain="[]" context="{'group_by':'user_id'}"/>
</group>
</search>
</field>
</record>
<record id="crm_team_salesteams_search" model="ir.ui.view">
<field name="name">Sales Teams - Search</field>
<field name="model">crm.team</field>
<field name="arch" type="xml">
<search string="Salesteams Search">
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<field name="name"/>
<field name="user_id"/>
<group expand="0" string="Group By...">
<filter string="Team Leader" name="team_leader" domain="[]" context="{'group_by':'user_id'}"/>
</group>
</search>
</field>
</record>
<!-- Sales Teams Action -->
<record id="crm_team_salesteams_act" model="ir.actions.act_window">
<field name="name">Sales Teams</field>
<field name="res_model">crm.team</field>
<field name="view_mode">kanban,form</field>
<field name="view_id" ref="crm_team_salesteams_search"/>
<field name="context">{'in_sales_app': True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new sales team
</p><p>
Use Sales Teams to organize your sales departments.
Each team will work with a separate pipeline.
</p>
</field>
</record>
<record id="crm_team_salesteams_pipelines_act" model="ir.actions.act_window">
<field name="name">Team Pipelines</field>
<field name="res_model">crm.team</field>
<field name="view_mode">kanban,form</field>
<field name="view_id" ref="crm_team_salesteams_search"/>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new sales team
</p><p>
Use Sales Teams to organize your sales departments.
Each team will work with a separate pipeline.
</p>
</field>
</record>
<!-- Sales Teams Form View -->
<record id="crm_team_view_form" model="ir.ui.view">
<field name="name">crm.team.form</field>
<field name="model">crm.team</field>
<field name="arch" type="xml">
<form string="Sales Team">
<sheet>
<div class="oe_button_box" name="button_box"/>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Sales Team"/>
<h1>
<field name="name" placeholder="Sales Team name..."/>
</h1>
<div name="options_active" />
</div>
<group>
<group name="left">
<field name="active" invisible="1"/>
<field name="user_id" domain="[('share', '=', False)]"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<field name="currency_id" invisible="1"/>
</group>
<group name="right">
</group>
<record id="crm_team_view_form" model="ir.ui.view">
<field name="name">crm.team.form</field>
<field name="model">crm.team</field>
<field name="arch" type="xml">
<form string="Sales Team">
<sheet>
<div class="oe_button_box" name="button_box"/>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Sales Team"/>
<h1>
<field name="name" placeholder="Sales Team name..."/>
</h1>
<div name="options_active" />
</div>
<group>
<group name="left">
<field name="active" invisible="1"/>
<field name="user_id" domain="[('share', '=', False)]"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<field name="currency_id" invisible="1"/>
</group>
<notebook>
<page name="members" string="Team Members" >
<field name="member_ids" widget="many2many" options="{'not_delete': True}">
<kanban quick_create="false" create="true" delete="true">
<field name="id"/>
<field name="name"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click" style="max-width: 200px">
<div class="o_kanban_record_top">
<img t-att-src="kanban_image('res.users', 'image_128', record.id.raw_value)" class="oe_avatar oe_kanban_avatar_smallbox o_image_40_cover mb0" alt="Avatar"/>
<div class="o_kanban_record_headings ml8">
<strong class="o_kanban_record_title"><field name="name"/></strong>
</div>
<group name="right">
</group>
</group>
<notebook>
<page name="members" string="Team Members" >
<field name="member_ids" widget="many2many" options="{'not_delete': True}">
<kanban quick_create="false" create="true" delete="true">
<field name="id"/>
<field name="name"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click" style="max-width: 200px">
<div class="o_kanban_record_top">
<img t-att-src="kanban_image('res.users', 'image_128', record.id.raw_value)" class="oe_avatar oe_kanban_avatar_smallbox o_image_40_cover mb0" alt="Avatar"/>
<div class="o_kanban_record_headings ml8">
<strong class="o_kanban_record_title"><field name="name"/></strong>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" help="Follow this salesteam to automatically track the events associated to users of this team."/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
</div>
</t>
</templates>
</kanban>
</field>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" help="Follow this salesteam to automatically track the events associated to users of this team."/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Sales Teams Tree View -->
<record id="crm_team_view_tree" model="ir.ui.view">
<field name="name">crm.team.tree</field>
<field name="model">crm.team</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Sales Team">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="active" invisible="1"/>
<field name="user_id"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record id="crm_team_view_tree" model="ir.ui.view">
<field name="name">crm.team.tree</field>
<field name="model">crm.team</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Sales Team">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="active" invisible="1"/>
<field name="user_id"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<!-- Sales Teams Kanban View -->
<record id="crm_team_view_kanban" model="ir.ui.view">
<field name="name">crm.team.kanban</field>
<field name="model">crm.team</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_content oe_kanban_global_click">
<div class="row">
<div class="col-6">
<strong><field name="name"/></strong>
<record id="crm_team_view_kanban" model="ir.ui.view">
<field name="name">crm.team.kanban</field>
<field name="model">crm.team</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_content oe_kanban_global_click">
<div class="row">
<div class="col-6">
<strong><field name="name"/></strong>
</div>
<div class="col-6">
<span class="float-right"><field name="user_id"/></span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- Case Teams Salesteams dashboard view -->
<record id="crm_team_salesteams_view_kanban" model="ir.ui.view" >
<field name="name">crm.team.dashboard</field>
<field name="model">crm.team</field>
<field name="arch" type="xml">
<kanban class="oe_background_grey o_kanban_dashboard o_salesteam_kanban" create="0">
<field name="name"/>
<field name="user_id"/>
<field name="member_ids"/>
<field name="color"/>
<field name="currency_id"/>
<field name="is_favorite"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{!selection_mode ? kanban_color(record.color.raw_value) : ''}">
<div t-attf-class="o_kanban_card_header">
<div class="o_kanban_card_header_title">
<div class="o_primary"><field name="name"/></div>
</div>
<div class="o_kanban_manage_button_section">
<a class="o_kanban_manage_toggle_button" href="#"><i class="fa fa-ellipsis-v" role="img" aria-label="Manage" title="Manage"/></a>
</div>
</div>
<div class="container o_kanban_card_content">
<div class="row o_kanban_card_upper_content">
<div class="col-5 o_kanban_primary_left" name="to_replace_in_sale_crm">
<button type="object" class="btn btn-primary" name="action_primary_channel_button"><field name="dashboard_button_name"/></button>
</div>
<div class="col-6">
<span class="float-right"><field name="user_id"/></span>
<div class="col-7 o_kanban_primary_right" style="padding-bottom:0;">
<t name="first_options"/>
<t name="second_options"/>
<t name="third_options"/>
</div>
</div>
<div class="row">
<div class="col-12 o_kanban_primary_bottom">
<t t-call="SalesTeamDashboardGraph"/>
</div>
<div class="col-12 o_kanban_primary_bottom bottom_block">
</div>
</div>
</div><div class="container o_kanban_card_manage_pane dropdown-menu" role="menu">
<div class="row">
<div class="col-4 o_kanban_card_manage_section o_kanban_manage_view">
<div role="menuitem" class="o_kanban_card_manage_title">
<span>View</span>
</div>
</div>
<div class="col-4 o_kanban_card_manage_section o_kanban_manage_new">
<div role="menuitem" class="o_kanban_card_manage_title">
<span>New</span>
</div>
</div>
<div class="col-4 o_kanban_card_manage_section o_kanban_manage_reports">
<div role="menuitem" class="o_kanban_card_manage_title">
<span>Reporting</span>
</div>
</div>
</div>
<div t-if="widget.editable" class="o_kanban_card_manage_settings row" groups="sales_team.group_sale_manager">
<div role="menuitem" aria-haspopup="true" class="col-8">
<ul class="oe_kanban_colorpicker" data-field="color" role="menu"/>
</div>
<div role="menuitem" class="col-4 text-right">
<a type="edit">Settings</a>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</div>
</t>
<t t-name="SalesTeamDashboardGraph">
<div t-if="record.dashboard_graph_data.raw_value" class="o_sales_team_kanban_graph_section">
<field name="dashboard_graph_data" widget="dashboard_graph" t-att-graph_type="'bar'"/>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- add css / js -->
<template id="assets_backend" name="sales_team assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/sales_team/static/src/scss/sales_team_dashboard.scss"/>
</xpath>
</template>
<!-- Sales Teams Actions -->
<record id="crm_team_salesteams_act" model="ir.actions.act_window">
<field name="name">Sales Teams</field>
<field name="res_model">crm.team</field>
<field name="view_mode">kanban,form</field>
<field name="view_id" ref="crm_team_salesteams_search"/>
<field name="context">{'in_sales_app': True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new sales team
</p><p>
Use Sales Teams to organize your sales departments.
Each team will work with a separate pipeline.
</p>
</field>
</record>
<record id="sales_team_config_action" model="ir.actions.act_window">
<field name="name">Sales Teams</field>
<field name="res_model">crm.team</field>
<field name="view_mode">tree,form</field>
<field name="context">{}</field>
<field name="view_id" ref="crm_team_salesteams_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new sales team
</p><p>
Use Sales Teams to organize your sales departments.
Each team will work with a separate pipeline.
</p>
</field>
</record>
<record id="crm_team_salesteams_pipelines_act" model="ir.actions.act_window">
<field name="name">Team Pipelines</field>
<field name="res_model">crm.team</field>
<field name="view_mode">kanban,form</field>
<field name="view_id" ref="crm_team_salesteams_search"/>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new sales team
</p><p>
Use Sales Teams to organize your sales departments.
Each team will work with a separate pipeline.
</p>
</field>
</record>
<record id="mail_activity_type_action_config_sales" model="ir.actions.act_window">
<field name="name">Activity Types</field>
<field name="res_model">mail.activity.type</field>
<field name="view_mode">tree,form</field>
<field name="domain">['|', ('res_model_id', '=', False), ('res_model_id.model', '=', 'res.partner')]</field>
</record>
</data>
<record id="sales_team_config_action" model="ir.actions.act_window">
<field name="name">Sales Teams</field>
<field name="res_model">crm.team</field>
<field name="view_mode">tree,form</field>
<field name="context">{}</field>
<field name="view_id" ref="crm_team_salesteams_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new sales team
</p><p>
Use Sales Teams to organize your sales departments.
Each team will work with a separate pipeline.
</p>
</field>
</record>
</data>
</odoo>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="mail_activity_type_action_config_sales" model="ir.actions.act_window">
<field name="name">Activity Types</field>
<field name="res_model">mail.activity.type</field>
<field name="view_mode">tree,form</field>
<field name="domain">['|', ('res_model_id', '=', False), ('res_model_id.model', '=', 'res.partner')]</field>
</record>
</odoo>
@@ -1,83 +0,0 @@
<odoo>
<!-- Case Teams Salesteams dashboard view -->
<record id="crm_team_salesteams_view_kanban" model="ir.ui.view" >
<field name="name">crm.team.dashboard</field>
<field name="model">crm.team</field>
<field name="arch" type="xml">
<kanban class="oe_background_grey o_kanban_dashboard o_salesteam_kanban" create="0">
<field name="name"/>
<field name="user_id"/>
<field name="member_ids"/>
<field name="color"/>
<field name="currency_id"/>
<field name="is_favorite"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{!selection_mode ? kanban_color(record.color.raw_value) : ''}">
<div t-attf-class="o_kanban_card_header">
<div class="o_kanban_card_header_title">
<div class="o_primary"><field name="name"/></div>
</div>
<div class="o_kanban_manage_button_section">
<a class="o_kanban_manage_toggle_button" href="#"><i class="fa fa-ellipsis-v" role="img" aria-label="Manage" title="Manage"/></a>
</div>
</div>
<div class="container o_kanban_card_content">
<div class="row o_kanban_card_upper_content">
<div class="col-5 o_kanban_primary_left" name="to_replace_in_sale_crm">
<button type="object" class="btn btn-primary" name="action_primary_channel_button"><field name="dashboard_button_name"/></button>
</div>
<div class="col-7 o_kanban_primary_right" style="padding-bottom:0;">
<t name="first_options"/>
<t name="second_options"/>
<t name="third_options"/>
</div>
</div>
<div class="row">
<div class="col-12 o_kanban_primary_bottom">
<t t-call="SalesTeamDashboardGraph"/>
</div>
<div class="col-12 o_kanban_primary_bottom bottom_block">
</div>
</div>
</div><div class="container o_kanban_card_manage_pane dropdown-menu" role="menu">
<div class="row">
<div class="col-4 o_kanban_card_manage_section o_kanban_manage_view">
<div role="menuitem" class="o_kanban_card_manage_title">
<span>View</span>
</div>
</div>
<div class="col-4 o_kanban_card_manage_section o_kanban_manage_new">
<div role="menuitem" class="o_kanban_card_manage_title">
<span>New</span>
</div>
</div>
<div class="col-4 o_kanban_card_manage_section o_kanban_manage_reports">
<div role="menuitem" class="o_kanban_card_manage_title">
<span>Reporting</span>
</div>
</div>
</div>
<div t-if="widget.editable" class="o_kanban_card_manage_settings row" groups="sales_team.group_sale_manager">
<div role="menuitem" aria-haspopup="true" class="col-8">
<ul class="oe_kanban_colorpicker" data-field="color" role="menu"/>
</div>
<div role="menuitem" class="col-4 text-right">
<a type="edit">Settings</a>
</div>
</div>
</div>
</div>
</t>
<t t-name="SalesTeamDashboardGraph">
<div t-if="record.dashboard_graph_data.raw_value" class="o_sales_team_kanban_graph_section">
<field name="dashboard_graph_data" widget="dashboard_graph" t-att-graph_type="'bar'"/>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</odoo>