[REF][MOV] sales_team, crm: move team membership model to sales_team
GLOBAL PURPOSE Ability to have salesmen belonging to several sales team is a core requirement of CRM. It is therefore moved from website_crm_score to crm along with cleaning and behavior improvement. Automatic lead assignment is also moved and cleaned. SPECIFICIATIONS Move sales team membership model from website_crm_score (enterprise) directly into sales_team. It allows to have the base requirements to correctly handle mono and multi sales team for salesperson. Membership is modeled using a decorated many2many relationship. Members of a sales team are res.users. Subscriptions are crm.team.member linking a team and an user. It is a rename of team.user model coming from website_crm_score as well as some other relational fields renaming. Part of old team.user model is moved directly to sales team, part of it to crm module (notably assignment limits). Its support will be improved in the upcoming commits. Assignment related fields will be cleaned and used when moving assignment directly into CRM. LINKS Task ID-2086889 (main task) Task ID-2357969 (scoring migration task) Community PR odoo/odoo#48422 Enterprise PR odoo/enterprise#499 Upgrade PR odoo/upgrade#996996
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
'views/crm_lost_reason_views.xml',
|
||||
'views/crm_stage_views.xml',
|
||||
'views/crm_lead_views.xml',
|
||||
'views/crm_team_member_views.xml',
|
||||
'views/digest_views.xml',
|
||||
'views/mail_activity_views.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
@@ -59,6 +60,7 @@
|
||||
'demo': [
|
||||
'data/crm_team_demo.xml',
|
||||
'data/mail_template_demo.xml',
|
||||
'data/crm_team_member_demo.xml',
|
||||
'data/mail_activity_demo.xml',
|
||||
'data/crm_lead_demo.xml',
|
||||
],
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo><data noupdate="1">
|
||||
|
||||
<record id="sales_team.crm_team_member_admin_sales" model="crm.team.member">
|
||||
<field name="maximum_user_leads">1</field>
|
||||
</record>
|
||||
<record id="sales_team.crm_team_member_demo_team_1" model="crm.team.member">
|
||||
<field name="maximum_user_leads">2</field>
|
||||
<field name="team_user_domain">['&', ['lang_id', '=', 'English'], ['country_id', '=', 'Belgium']]</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -7,6 +7,7 @@ from . import crm_lead
|
||||
from . import crm_lost_reason
|
||||
from . import crm_stage
|
||||
from . import crm_team
|
||||
from . import crm_team_member
|
||||
from . import ir_config_parameter
|
||||
from . import res_config_settings
|
||||
from . import res_partner
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
|
||||
import logging
|
||||
import threading
|
||||
from collections import OrderedDict, defaultdict
|
||||
from datetime import date, datetime, timedelta
|
||||
from psycopg2 import sql
|
||||
|
||||
from odoo import api, fields, models, tools, SUPERUSER_ID
|
||||
from odoo.addons.phone_validation.tools import phone_validation
|
||||
from odoo.exceptions import UserError, AccessError
|
||||
from odoo.osv import expression
|
||||
from odoo.tools.translate import _
|
||||
from odoo.tools import email_re, email_split
|
||||
from odoo.exceptions import UserError, AccessError
|
||||
from collections import OrderedDict, defaultdict
|
||||
from odoo.tools import email_re, email_split, safe_eval
|
||||
|
||||
from . import crm_stage
|
||||
|
||||
@@ -71,6 +71,12 @@ PARTNER_ADDRESS_FIELDS_TO_SYNC = [
|
||||
PLS_COMPUTE_BATCH_STEP = 50000 # odoo.models.PREFETCH_MAX = 1000 but larger cluster can speed up global computation
|
||||
PLS_UPDATE_BATCH_STEP = 5000
|
||||
|
||||
# Evaluation context for all domain-based lead auto assignment
|
||||
LEAD_ASSIGN_EVAL_CONTEXT = {
|
||||
'datetime': safe_eval.datetime,
|
||||
'context_today': datetime.now,
|
||||
}
|
||||
|
||||
|
||||
class Lead(models.Model):
|
||||
_name = "crm.lead"
|
||||
@@ -249,7 +255,7 @@ class Lead(models.Model):
|
||||
if not lead.user_id:
|
||||
continue
|
||||
user = lead.user_id
|
||||
if lead.team_id and user in lead.team_id.member_ids | lead.team_id.user_id:
|
||||
if lead.team_id and user in (lead.team_id.member_ids | lead.team_id.user_id):
|
||||
continue
|
||||
team_domain = [('use_leads', '=', True)] if lead.type == 'lead' else [('use_opportunities', '=', True)]
|
||||
team = self.env['crm.team']._get_default_team_id(user_id=user.id, domain=team_domain)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import datetime
|
||||
|
||||
from odoo import api, exceptions, fields, models, _
|
||||
from odoo.addons.crm.models.crm_lead import LEAD_ASSIGN_EVAL_CONTEXT
|
||||
from odoo.tools import safe_eval
|
||||
|
||||
|
||||
class Team(models.Model):
|
||||
_inherit = 'crm.team.member'
|
||||
|
||||
# assignment
|
||||
team_user_domain = fields.Char('Domain', tracking=True)
|
||||
maximum_user_leads = fields.Integer('Leads Per Month')
|
||||
lead_month_count = fields.Integer(
|
||||
'Assigned Leads', compute='_compute_lead_month_count',
|
||||
help='Lead assigned to this member those last 30 days')
|
||||
|
||||
def _compute_lead_month_count(self):
|
||||
for member in self:
|
||||
if member.id:
|
||||
limit_date = fields.Datetime.now() - datetime.timedelta(days=30)
|
||||
domain = [('user_id', '=', member.user_id.id),
|
||||
('team_id', '=', member.crm_team_id.id),
|
||||
('date_open', '>=', limit_date)]
|
||||
member.lead_month_count = self.env['crm.lead'].search_count(domain)
|
||||
else:
|
||||
member.lead_month_count = 0
|
||||
|
||||
@api.constrains('team_user_domain')
|
||||
def _constrains_team_user_domain(self):
|
||||
for member in self:
|
||||
try:
|
||||
domain = safe_eval.safe_eval(member.team_user_domain or '[]', LEAD_ASSIGN_EVAL_CONTEXT)
|
||||
self.env['crm.lead'].search(domain, limit=1)
|
||||
except Exception:
|
||||
raise exceptions.UserError(_('Team membership assign domain is incorrectly formatted'))
|
||||
@@ -96,6 +96,13 @@
|
||||
parent="crm_menu_config"
|
||||
action="sales_team.crm_team_action_config"
|
||||
sequence="5"/>
|
||||
<menuitem
|
||||
id="crm_team_member_config"
|
||||
name="Teams Members"
|
||||
parent="crm_menu_config"
|
||||
action="sales_team.crm_team_member_action"
|
||||
sequence="6"
|
||||
groups="base.group_no_one"/>
|
||||
<menuitem
|
||||
id="crm_team_menu_config_activity_types"
|
||||
name="Activity Types"
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo><data>
|
||||
|
||||
<record id="crm_team_member_view_tree" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.tree</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="inherit_id" ref="sales_team.crm_team_member_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="user_id" position="after">
|
||||
<field name="maximum_user_leads"/>
|
||||
<field name="lead_month_count"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_view_kanban" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.kanban.inherit.crm</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="inherit_id" ref="sales_team.crm_team_member_view_kanban"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//li[hasclass('o_salesteam_member_name')]" position="after">
|
||||
<li class="nav-item"><field name="team_user_domain" widget="filters"/></li>
|
||||
</xpath>
|
||||
<xpath expr="//ul[hasclass('o_assignation_body')]" position="after">
|
||||
<div class="o_assignation_leads_count">
|
||||
<field name="maximum_user_leads" invisible="1"/>
|
||||
<field name="lead_month_count" widget="gauge"
|
||||
options="{'max_field': 'maximum_user_leads'}"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_view_form" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.form.inherit.crm</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="inherit_id" ref="sales_team.crm_team_member_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="user_id" position="after">
|
||||
<field name="lead_month_count" invisible="1"/>
|
||||
</field>
|
||||
<xpath expr="//group" position="inside">
|
||||
<label for="maximum_user_leads" string="Maximum Leads / 30 days" />
|
||||
<div>
|
||||
<field name="maximum_user_leads" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="team_user_domain" widget="domain" options="{'model': 'crm.lead'}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sales_team.crm_team_member_action" model="ir.actions.act_window">
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a new salesman
|
||||
</p><p>
|
||||
Link users to salesteam, set a per 30 days lead capacity for each
|
||||
of them and set filters to auto assign your leads.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -19,6 +19,7 @@ Using this application you can manage Sales Teams with CRM and/or Sales
|
||||
'views/assets.xml',
|
||||
'views/crm_tag_views.xml',
|
||||
'views/crm_team_views.xml',
|
||||
'views/crm_team_member_views.xml',
|
||||
'views/mail_activity_views.xml',
|
||||
'views/res_partner_views.xml',
|
||||
],
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
<record id="team_sales_department" model="crm.team">
|
||||
<field name="name">Sales</field>
|
||||
<field name="sequence">0</field>
|
||||
<field name="member_ids" eval="[(4, ref('base.user_admin'))]"/>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
<record id="crm_team_member_admin_sales" model="crm.team.member">
|
||||
<field name="crm_team_id" ref="team_sales_department"/>
|
||||
<field name="user_id" ref="base.user_admin"/>
|
||||
</record>
|
||||
|
||||
<record id="salesteam_website_sales" model="crm.team">
|
||||
<field name="name">Website</field>
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- rename for demo-data -->
|
||||
<record model="crm.team" id="team_sales_department">
|
||||
<field name="name">Europe</field>
|
||||
<field name="member_ids" eval="[(4, ref('base.user_demo'))]"/>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
<record id="base.user_demo" model="res.users">
|
||||
<record model="res.users" id="base.user_demo">
|
||||
<field name="groups_id" eval="[(4,ref('sales_team.group_sale_salesman'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="team_sales_department" model="crm.team">
|
||||
<field name="member_ids" eval="[(4, ref('base.user_demo'))]"/>
|
||||
<record model="crm.team" id="team_sales_department">
|
||||
<field name="name">Sales</field>
|
||||
</record>
|
||||
|
||||
<record model="crm.team" id="crm_team_1">
|
||||
<field name="name">America</field>
|
||||
<field name="name">Pre-Sales</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
<field name="member_ids" eval="[(4, ref('base.user_demo'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_demo_team_1" model="crm.team.member">
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="crm_team_id" ref="sales_team.crm_team_1"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import crm_team_member
|
||||
from . import crm_team
|
||||
from . import crm_tag
|
||||
from . import res_partner
|
||||
|
||||
@@ -20,16 +20,18 @@ class CrmTeam(models.Model):
|
||||
_check_company_auto = True
|
||||
|
||||
def _get_default_team_id(self, user_id=None, domain=None):
|
||||
user_id = user_id or self.env.uid
|
||||
user_salesteam_id = self.env['res.users'].browse(user_id).sale_team_id.id
|
||||
# Avoid searching on member_ids (+1 query) when we may have the user salesteam already in cache.
|
||||
if user_id is None:
|
||||
user_id = self.env.user.id
|
||||
|
||||
team = self.env['crm.team'].search([
|
||||
('company_id', 'in', [False, self.env.company.id]),
|
||||
'|', ('user_id', '=', user_id), ('id', '=', user_salesteam_id),
|
||||
'|', ('user_id', '=', user_id), ('member_ids', 'in', user_id),
|
||||
], limit=1)
|
||||
if not team and 'default_team_id' in self.env.context:
|
||||
team = self.env['crm.team'].browse(self.env.context.get('default_team_id'))
|
||||
return team or self.env['crm.team'].search(domain or [], limit=1)
|
||||
if not team:
|
||||
team = self.env['crm.team'].search(domain or [], limit=1)
|
||||
return team
|
||||
|
||||
def _get_default_favorite_user_ids(self):
|
||||
return [(6, 0, [self.env.uid])]
|
||||
@@ -45,10 +47,11 @@ class CrmTeam(models.Model):
|
||||
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',
|
||||
member_ids = fields.Many2many(
|
||||
'res.users', 'crm_team_member', 'crm_team_id', 'user_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.")
|
||||
help="Add members to automatically assign their documents to this sales team.")
|
||||
crm_team_member_ids = fields.One2many('crm.team.member', 'crm_team_id', string='Sales Team Memberships')
|
||||
# UX options
|
||||
color = fields.Integer(string='Color Index', help="The color of the channel")
|
||||
favorite_user_ids = fields.Many2many(
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class CrmTeamMember(models.Model):
|
||||
_name = 'crm.team.member'
|
||||
_inherit = ['mail.thread']
|
||||
_description = 'Sales Team Member'
|
||||
_rec_name = 'user_id'
|
||||
|
||||
crm_team_id = fields.Many2one('crm.team', string='Sales Team', required=True)
|
||||
user_id = fields.Many2one('res.users', string='Saleman', required=True) # check responsible field
|
||||
name = fields.Char(string="Name", related='user_id.partner_id.display_name', readonly=False)
|
||||
active = fields.Boolean(string='Running', default=True)
|
||||
@@ -7,6 +7,14 @@ from odoo import fields, models
|
||||
class ResUsers(models.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
crm_team_ids = fields.Many2many('crm.team', 'crm_team_member', 'user_id', 'crm_team_id', string='Sales Teams')
|
||||
crm_team_member_ids = fields.One2many('crm.team.member', 'user_id', string='Sales Team Memberships')
|
||||
# mov of the field defined in website_crm_score. The field is now computed
|
||||
# based on the new modeling introduced in this module. It is stored to avoid
|
||||
# breaking the member_ids inverse field. As the relationship between users
|
||||
# and sales team is a one2many / many2one relationship we take the first of
|
||||
# the crm.team.member record to find the user's sales team.
|
||||
sale_team_id = fields.Many2one(
|
||||
'crm.team', "User's Sales Team",
|
||||
help='Sales Team the user is member of. Used to compute the members of a Sales Team through the inverse one2many')
|
||||
'crm.team', string='User Sales Team',
|
||||
related='crm_team_member_ids.crm_team_id',
|
||||
readonly=False, store=True)
|
||||
|
||||
@@ -2,6 +2,9 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_crm_team,crm.team,model_crm_team,base.group_user,1,0,0,0
|
||||
access_crm_team_user,crm.team.user,model_crm_team,sales_team.group_sale_salesman,1,0,0,0
|
||||
access_crm_team_manager,crm.team.manager,model_crm_team,sales_team.group_sale_manager,1,1,1,1
|
||||
access_crm_team_member_all,access.crm.team.member.all,model_crm_team_member,,0,0,0,0
|
||||
access_crm_team_member_user,access.crm.team.member.user,model_crm_team_member,base.group_user,1,0,0,0
|
||||
access_crm_team_member_salesman,access.crm.team.member.salesman,model_crm_team_member,sales_team.group_sale_salesman,1,1,1,1
|
||||
access_crm_tag,crm_tag,model_crm_tag,base.group_user,0,0,0,0
|
||||
access_crm_tag_salesman,crm_tag salesman,model_crm_tag,sales_team.group_sale_salesman,1,1,1,0
|
||||
access_crm_tag_manager,crm_tag manager,model_crm_tag,sales_team.group_sale_manager,1,1,1,1
|
||||
|
||||
|
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo><data>
|
||||
|
||||
<record id="crm_team_member_view_search" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.search</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Sales Person">
|
||||
<field name="name"/>
|
||||
<field name="crm_team_id"/>
|
||||
<separator/>
|
||||
<filter name="archived" string="Archived" domain="[('active', '=', False)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Sales Team" name="groupby_crm_team_id" context="{'group_by': 'crm_team_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_view_tree" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.tree</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Sales Men" sample="1">
|
||||
<field name="crm_team_id"/>
|
||||
<field name="user_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_view_tree_from_team" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.tree.from.team</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="inherit_id" ref="sales_team.crm_team_member_view_tree"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="priority">32</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='crm_team_id']" position="replace">
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_view_kanban" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.kanban</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban quick_create="false"
|
||||
create="true"
|
||||
sample="1">
|
||||
<field name="user_id"/>
|
||||
<field name="active"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<t t-set="active" t-value="record.active.raw_value"/>
|
||||
<t t-set="button_state" t-value="active ? 'o_assignation_button_active' : 'o_assignation_button_inactive'"/>
|
||||
<div class="o_assignation_kanban_record oe_kanban_global_click pb-0">
|
||||
<div class="o_kanban_record_top mb-0">
|
||||
<ul class="nav">
|
||||
<li class="nav-item">
|
||||
<a type="open" class="nav-link">
|
||||
<img t-att-src="kanban_image('res.users', 'image_128', record.user_id.raw_value)" class="o_kanban_image o_image_64_cover" alt="Avatar"/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="nav o_assignation_body">
|
||||
<li class="nav-item o_salesteam_member_name"><a type="open" class="nav-link"><b><field name="name"/></b></a></li>
|
||||
<li class="nav-item o_salesteam_member_crm_team_id w-100"><a type="open" class="nav-link"><field name="crm_team_id"/></a></li>
|
||||
<li t-attf-class="nav-item #{button_state}">
|
||||
<a type="object" name="toggle_active" t-attf-class="nav-link fa fa-check-square" title="Toggle active"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_view_kanban_from_team" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.kanban.from.team</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="inherit_id" ref="sales_team.crm_team_member_view_kanban"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="priority">32</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//li[hasclass('o_salesteam_member_crm_team_id')]" position="replace">
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_view_form" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.form</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Sales Men">
|
||||
<field name="active" invisible="1"/>
|
||||
<sheet>
|
||||
<h1>
|
||||
<field name="user_id" domain="[('share', '=', False)]"/>
|
||||
</h1>
|
||||
<group>
|
||||
<field name="crm_team_id" kanban_view_ref="%(sales_team.crm_team_view_kanban)s" readonly="context.get('ro_team', False)"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_view_form_from_team" model="ir.ui.view">
|
||||
<field name="name">crm.team.member.view.form.from.team</field>
|
||||
<field name="model">crm.team.member</field>
|
||||
<field name="inherit_id" ref="sales_team.crm_team_member_view_form"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="priority">32</field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="crm_team_id" position="replace"/>
|
||||
<xpath expr="//div[hasclass('oe_chatter')]" position="replace"/>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_team_member_action" model="ir.actions.act_window">
|
||||
<field name="name">Team Members</field>
|
||||
<field name="res_model">crm.team.member</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a new salesman
|
||||
</p><p>
|
||||
Link users to salesteam.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data></odoo>
|
||||
@@ -42,25 +42,15 @@
|
||||
</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>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
<page string="Assignment" name="assignment">
|
||||
<field name="crm_team_member_ids" mode="kanban"
|
||||
class="w-100"
|
||||
context="{
|
||||
'kanban_view_ref': 'sales_team.crm_team_member_view_kanban_from_team',
|
||||
'form_view_ref': 'sales_team.crm_team_member_view_form_from_team',
|
||||
'tree_view_ref': 'sales_team.crm_team_member_view_tree_from_team',
|
||||
'default_crm_team_id': active_id,
|
||||
}"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
|
||||
Reference in New Issue
Block a user