Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[ADD] sales_team_security
============================== Security rules for sales teams ============================== This module sets different permissions levels for accessing sales and CRM records based on the sales team: customers, sales orders, leads, opportunities, phone calls and sales teams. It also handles the propagation of the sales team from commercial partners to the contacts, which standard doesn't make. Installation ============ At installation time, this module sets int all the contacts that have the sales team empty the sales team of the parent. If you have a lot of contacts, this operation can take a while. Usage ===== On the user configuration (Configuration > Users > Users), select in the *Sales Team* section the option "See only own team". Then, the documents mentioned before will be filtered out to have only those belonging to the teams the user belongs to. This is complementary to the Sales level access, but sometimes can be incoherent depending on the combination chosen. If you chose "See Own Leads" on _Sales_ section, marking on unmarking the sales team check will be irrelevant, because the most restricting level, which the sales one, will prevail. Known issues/Roadmap ==================== * This module is designed for supporting only sales part, so someone that has access to other Odoo parts (for example, an accountant), shouldn't have this new permission, or some access errors will be found when seeing invoices and other documents. A _sales_team_security_account_ bridge module can be done for fixing this case, but not in the case of for example warehouse.
- Loading branch information
1 parent
a3cca91
commit 17efd97
Showing
12 changed files
with
328 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg | ||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
|
||
============================== | ||
Security rules for sales teams | ||
============================== | ||
|
||
This module sets different permissions levels for accessing sales and CRM | ||
records based on the sales team: customers, sales orders, leads, opportunities, | ||
phone calls and sales teams. | ||
|
||
It also handles the propagation of the sales team from commercial partners to | ||
the contacts, which standard doesn't make. | ||
|
||
Installation | ||
============ | ||
|
||
At installation time, this module sets in all the contacts that have the sales | ||
team empty the sales team of the parent. If you have a lot of contacts, this | ||
operation can take a while. | ||
|
||
Configuration | ||
============= | ||
|
||
On the user configuration (Configuration > Users > Users), select in the | ||
*Sales Team* section the option "See only own team". Then, the documents | ||
mentioned before will be filtered out to have only those belonging to the | ||
teams the user belongs to. | ||
|
||
This is complementary to the "Sales" level access, but sometimes can be | ||
incoherent depending on the combination chosen. If you chose "See Own Leads" | ||
on *Sales* section, marking or unmarking the sales team check will be | ||
irrelevant, because the most restricting level, which is the sales one, will | ||
prevail. | ||
|
||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas | ||
:alt: Try me on Runbot | ||
:target: https://runbot.odoo-community.org/runbot/167/8.0 | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues | ||
<https://github.com/OCA/sale-workflow/issues>`_. In case of trouble, please | ||
check there if your issue has already been reported. If you spotted it first, | ||
help us smashing it by providing a detailed and welcomed feedback. | ||
|
||
Known issues/Roadmap | ||
==================== | ||
|
||
* This module is designed for supporting only sales part, so someone that has | ||
access to other Odoo parts (for example, an accountant), shouldn't have | ||
this new permission, or some access errors will be found when seeing invoices | ||
and other documents. A *sales_team_security_account* bridge module can be | ||
done for fixing this case, but not in the case of for example warehouse. | ||
|
||
Credits | ||
======= | ||
|
||
Contributors | ||
------------ | ||
|
||
* Pedro M. Baeza <pedro.baeza@serviciosbaeza.com> | ||
|
||
Maintainer | ||
---------- | ||
|
||
.. image:: http://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
|
||
This module is maintained by the OCA. | ||
|
||
OCA, or the Odoo Community Association, is a nonprofit organization whose | ||
mission is to support the collaborative development of Odoo features and | ||
promote its widespread use. | ||
|
||
To contribute to this module, please visit https://odoo-community.org. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# -*- coding: utf-8 -*- | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
from . import models | ||
from .hooks import assign_contacts_team |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2016 Tecnativa - Pedro M. Baeza | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
{ | ||
"name": "Sales teams security", | ||
"version": "8.0.1.0.0", | ||
"license": "AGPL-3", | ||
"depends": [ | ||
"sales_team", | ||
"sale", | ||
"crm", | ||
], | ||
"author": "Tecnativa, " | ||
"Odoo Community Association (OCA)", | ||
"website": "https://www.tecnativa.com", | ||
"category": "Sales Management", | ||
"installable": True, | ||
"data": [ | ||
'security/sales_team_security.xml', | ||
'views/res_partner_view.xml', | ||
], | ||
"post_init_hook": "assign_contacts_team", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2016 Tecnativa - Pedro M. Baeza | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
|
||
def assign_contacts_team(cr, registry): | ||
"""At installation time, propagate the parent sales team to the children | ||
contacts that have this field empty, as it's supposed that the intention | ||
is to have the same. | ||
""" | ||
cr.execute( | ||
""" | ||
UPDATE res_partner | ||
SET section_id=parent.section_id | ||
FROM res_partner AS parent | ||
WHERE parent.section_id IS NOT NULL | ||
AND res_partner.parent_id = parent.id | ||
AND res_partner.section_id IS NULL | ||
""") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# -*- coding: utf-8 -*- | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
from . import res_partner | ||
from . import res_users |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2016 Tecnativa - Pedro M. Baeza | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
from openerp import api, models | ||
from lxml import etree | ||
|
||
|
||
class ResPartner(models.Model): | ||
_inherit = 'res.partner' | ||
|
||
@api.model | ||
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, | ||
submenu=False): | ||
"""Patch view to inject the default value for the section_id.""" | ||
res = super(ResPartner, self).fields_view_get( | ||
view_id=view_id, view_type=view_type, toolbar=toolbar, | ||
submenu=submenu) | ||
if view_type == 'form': | ||
eview = etree.fromstring(res['arch']) | ||
xml_fields = eview.xpath("//field[@name='child_ids']") | ||
if xml_fields: | ||
context_str = xml_fields[0].get('context', '{}').replace( | ||
'{', "{'default_section_id': section_id, ", 1, | ||
) | ||
xml_fields[0].set('context', context_str) | ||
res['arch'] = etree.tostring(eview) | ||
return res | ||
|
||
@api.multi | ||
def onchange_address(self, use_parent_address, parent_id): | ||
res = super(ResPartner, self).onchange_address( | ||
use_parent_address, parent_id) | ||
if parent_id: | ||
parent = self.browse(parent_id) | ||
if parent.section_id: | ||
value = res.setdefault('value', {}) | ||
value['section_id'] = parent.section_id.id | ||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2016 Tecnativa - Pedro M. Baeza | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
from openerp import fields, models | ||
|
||
|
||
class ResUsers(models.Model): | ||
_inherit = 'res.users' | ||
|
||
sale_team_ids = fields.Many2many( | ||
comodel_name="crm.case.section", string="Sales teams", | ||
relation='sale_member_rel', column1='member_id', column2='section_id') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<openerp> | ||
<data noupdate="0"> | ||
|
||
<record model="ir.module.category" id="module_category_sales_team"> | ||
<field name="name">Sales Teams</field> | ||
<field name="sequence">2</field> | ||
</record> | ||
|
||
<record id="group_see_only_own_team" model="res.groups"> | ||
<field name="name">See only own team</field> | ||
<field name="category_id" ref="sales_team_security.module_category_sales_team"/> | ||
</record> | ||
|
||
</data> | ||
<data noupdate="1"> | ||
|
||
<record id="sale_order_team_rule" model="ir.rule"> | ||
<field name="name">Sales Team Orders</field> | ||
<field ref="sale.model_sale_order" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), '|', ('section_id', 'in', user.sale_team_ids.ids), ('section_id', '=', False)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
<record id="sale_order_report_team_rule" model="ir.rule"> | ||
<field name="name">Sales Team Orders Analysis</field> | ||
<field ref="sale.model_sale_report" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), '|', ('section_id', 'in', user.sale_team_ids.ids), ('section_id', '=', False)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
<record id="sale_order_line_team_rule" model="ir.rule"> | ||
<field name="name">Sales Team Order Lines</field> | ||
<field ref="sale.model_sale_order_line" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), '|', ('section_id', 'in', user.sale_team_ids.ids), ('section_id', '=', False)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
<record id="res_partner_team_rule" model="ir.rule"> | ||
<field name="name">Sales Team Partners</field> | ||
<field ref="base.model_res_partner" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), '|', ('section_id', 'in', user.sale_team_ids.ids), ('section_id', '=', False)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
<record id="crm_lead_team_rule" model="ir.rule"> | ||
<field name="name">Sales Team Leads/Opportunities</field> | ||
<field ref="crm.model_crm_lead" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), '|', ('section_id', 'in', user.sale_team_ids.ids), ('section_id', '=', False)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
<record id="crm_lead_report_team" model="ir.rule"> | ||
<field name="name">Sales Team Leads Analysis</field> | ||
<field ref="crm.model_crm_lead_report" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), '|', ('section_id', 'in', user.sale_team_ids.ids), ('section_id', '=', False)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
<record id="crm_phonecall_team_rule" model="ir.rule"> | ||
<field name="name">Sales Team Phone Calls</field> | ||
<field ref="crm.model_crm_phonecall" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), '|', ('section_id', 'in', user.sale_team_ids.ids), ('section_id', '=', False)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
<record id="crm_phonecall_report_team" model="ir.rule"> | ||
<field name="name">Sales Team Phone Calls Analysis</field> | ||
<field ref="crm.model_crm_phonecall_report" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), '|', ('section_id', 'in', user.sale_team_ids.ids), ('section_id', '=', False)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
<record id="sales_team_team_rule" model="ir.rule"> | ||
<field name="name">Own Sales Teams</field> | ||
<field ref="sales_team.model_crm_case_section" name="model_id"/> | ||
<field name="domain_force">['|', ('message_follower_ids', 'in', user.partner_id.ids), ('id', 'in', user.sale_team_ids.ids)]</field> | ||
<field name="groups" eval="[(4, ref('sales_team_security.group_see_only_own_team'))]"/> | ||
</record> | ||
|
||
</data> | ||
</openerp> |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
from . import test_sales_team_security |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2016 Tecnativa - Pedro M. Baeza | ||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html | ||
|
||
from openerp.tests import common | ||
from ..hooks import assign_contacts_team | ||
from lxml import etree | ||
|
||
|
||
class TestSalesTeamSecurity(common.SavepointCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
super(TestSalesTeamSecurity, cls).setUpClass() | ||
cls.section = cls.env['crm.case.section'].create({ | ||
'name': 'Test section', | ||
}) | ||
cls.partner = cls.env['res.partner'].create({ | ||
'name': 'Test partner', | ||
'section_id': cls.section.id, | ||
}) | ||
|
||
def test_onchange_parent_id(self): | ||
res = self.env['res.partner'].onchange_address(True, self.partner.id) | ||
self.assertEqual(res['value']['section_id'], self.section.id) | ||
|
||
def test_assign_contacts_team(self): | ||
contact = self.env['res.partner'].create({ | ||
'name': 'Test contact', | ||
'parent_id': self.partner.id, | ||
'section_id': False, | ||
}) | ||
assign_contacts_team(self.env.cr, self.env.registry) | ||
contact.refresh() | ||
self.assertEqual(contact.section_id, self.partner.section_id) | ||
|
||
def test_partner_fields_view_get(self): | ||
res = self.env['res.partner'].fields_view_get( | ||
view_id=self.ref('base.view_partner_form')) | ||
eview = etree.fromstring(res['arch']) | ||
xml_fields = eview.xpath("//field[@name='child_ids']") | ||
self.assertTrue(xml_fields) | ||
self.assertTrue( | ||
'default_section_id' in xml_fields[0].get('context', '')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<openerp> | ||
<data> | ||
<record id="view_partner_form" model="ir.ui.view"> | ||
<field name="name">Partner form (with sales team in contacts)</field> | ||
<field name="model">res.partner</field> | ||
<field name="inherit_id" ref="base.view_partner_form"/> | ||
<field name="arch" type="xml"> | ||
<xpath expr="//field[@name='child_ids']/form//field[@name='function']" position="before"> | ||
<field name="section_id" invisible="1" groups="base.group_multi_salesteams"/> | ||
</xpath> | ||
</field> | ||
</record> | ||
</data> | ||
</openerp> |