From cb7bf9524f829698966465dc62a669e672b82546 Mon Sep 17 00:00:00 2001 From: Kunjal Date: Tue, 16 Jan 2018 18:21:36 +0530 Subject: [PATCH] [ADD]: Multi branch and CRM. --- addons/base_branch_company/__init__.py | 4 + addons/base_branch_company/__manifest__.py | 35 ++++++ .../base_branch_company/demo/branch_demo.xml | 42 +++++++ addons/base_branch_company/models/__init__.py | 8 ++ .../models/ir_branch_company.py | 15 +++ .../base_branch_company/models/res_branch.py | 105 +++++++++++++++++ .../base_branch_company/models/res_partner.py | 22 ++++ .../security/branch_security.xml | 20 ++++ .../security/ir.model.access.csv | 3 + addons/base_branch_company/tests/__init__.py | 1 + .../base_branch_company/tests/test_branch.py | 80 +++++++++++++ .../views/res_branch_view.xml | 106 ++++++++++++++++++ addons/crm/__manifest__.py | 2 +- addons/crm/data/crm_lead_demo.xml | 5 + addons/crm/models/crm_lead.py | 2 +- addons/crm/models/crm_team.py | 1 + addons/crm/security/crm_security.xml | 10 ++ addons/crm/tests/__init__.py | 1 + addons/crm/tests/common.py | 9 +- addons/crm/tests/test_crm_activity.py | 2 + addons/crm/tests/test_crm_branch.py | 68 +++++++++++ addons/crm/tests/test_crm_lead.py | 17 +-- addons/crm/tests/test_lead2opportunity.py | 23 ++-- .../crm/tests/test_new_lead_notification.py | 2 + addons/crm/views/crm_lead_views.xml | 3 + addons/sales_team/models/crm_team.py | 16 ++- .../security/sales_team_security.xml | 7 ++ addons/sales_team/tests/__init__.py | 3 + .../sales_team/tests/test_branch_crm_team.py | 56 +++++++++ 29 files changed, 643 insertions(+), 25 deletions(-) create mode 100644 addons/base_branch_company/__init__.py create mode 100644 addons/base_branch_company/__manifest__.py create mode 100644 addons/base_branch_company/demo/branch_demo.xml create mode 100644 addons/base_branch_company/models/__init__.py create mode 100644 addons/base_branch_company/models/ir_branch_company.py create mode 100644 addons/base_branch_company/models/res_branch.py create mode 100644 addons/base_branch_company/models/res_partner.py create mode 100644 addons/base_branch_company/security/branch_security.xml create mode 100644 addons/base_branch_company/security/ir.model.access.csv create mode 100644 addons/base_branch_company/tests/__init__.py create mode 100644 addons/base_branch_company/tests/test_branch.py create mode 100644 addons/base_branch_company/views/res_branch_view.xml create mode 100644 addons/crm/tests/test_crm_branch.py create mode 100644 addons/sales_team/tests/__init__.py create mode 100644 addons/sales_team/tests/test_branch_crm_team.py diff --git a/addons/base_branch_company/__init__.py b/addons/base_branch_company/__init__.py new file mode 100644 index 00000000..6a64595a --- /dev/null +++ b/addons/base_branch_company/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of flectra. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/addons/base_branch_company/__manifest__.py b/addons/base_branch_company/__manifest__.py new file mode 100644 index 00000000..4774f7fa --- /dev/null +++ b/addons/base_branch_company/__manifest__.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Part of flectra. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Branch & Company Mixin', + 'version': '1.0', + 'category': 'Discuss', + 'author': ['Flectra'], + 'sequence': 25, + 'summary': 'Include Branch & Company support', + 'description': """ +Branch & Company +================ + +Main Features +------------- +* Include Branch & Company in all objects +* Just need to inherit ir.branch.company.mixin in your object +* And in your xml file add below 2 lines in your Views + + +""", + 'website': '', + 'depends': ['base'], + 'data': [ + 'security/branch_security.xml', + 'security/ir.model.access.csv', + 'views/res_branch_view.xml', + ], + 'demo': [ + 'demo/branch_demo.xml', + ], + 'installable': True, + 'auto_install': True +} diff --git a/addons/base_branch_company/demo/branch_demo.xml b/addons/base_branch_company/demo/branch_demo.xml new file mode 100644 index 00000000..e71453f1 --- /dev/null +++ b/addons/base_branch_company/demo/branch_demo.xml @@ -0,0 +1,42 @@ + + + + + + + New York + NY + + 80 Broad St + Scranton + 10004 + + + +1 485 123 8989 + + + Washington + WA + + 2050 Bamako Place + DC 20521-7100 + + + +1 555 123 8069 + + + New Jersey + NJ + + 2711-2880 Nulla St. + NJ 20521-7100 + + + (372) 587-2335 + + + + + + + diff --git a/addons/base_branch_company/models/__init__.py b/addons/base_branch_company/models/__init__.py new file mode 100644 index 00000000..ee7e30da --- /dev/null +++ b/addons/base_branch_company/models/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# Part of flectra. See LICENSE file for full copyright and licensing details. + + +from . import res_branch +from . import ir_branch_company +from . import res_partner + diff --git a/addons/base_branch_company/models/ir_branch_company.py b/addons/base_branch_company/models/ir_branch_company.py new file mode 100644 index 00000000..7b355b2b --- /dev/null +++ b/addons/base_branch_company/models/ir_branch_company.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Part of flectra. See LICENSE file for full copyright and licensing details. + +from flectra import fields, models + + +class IrBranchCompanyMixin(models.AbstractModel): + _name = "ir.branch.company.mixin" + + branch_id = fields.Many2one( + 'res.branch', 'Branch', ondelete="restrict", + default=lambda self: self.env.user.default_branch_id) + company_id = fields.Many2one( + 'res.company', 'Company', ondelete="restrict", + default=lambda self: self.env.user.company_id) diff --git a/addons/base_branch_company/models/res_branch.py b/addons/base_branch_company/models/res_branch.py new file mode 100644 index 00000000..31335a74 --- /dev/null +++ b/addons/base_branch_company/models/res_branch.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- + +from flectra import api, fields, models + + +class Company(models.Model): + _name = "res.company" + _inherit = ["res.company"] + + branch_id = fields.Many2one('res.branch', 'Branch', ondelete="restrict") + + @api.model + def create(self, vals): + branch = self.env['res.branch'].create({ + 'name': vals['name'], + 'code': vals['name'], + }) + vals['branch_id'] = branch.id + self.clear_caches() + company = super(Company, self).create(vals) + branch.write({'partner_id': company.partner_id.id, + 'company_id': company.id}) + return company + +class ResBranch(models.Model): + _name = "res.branch" + + name = fields.Char(string='Name', required=True) + code = fields.Char(string='Code', required=True) + active = fields.Boolean(string='Active', default=True) + partner_id = fields.Many2one('res.partner', string='Partner', + ondelete='restrict') + company_id = fields.Many2one( + 'res.company', string="Company", + default=lambda self: self.env.user.company_id, required=True) + street = fields.Char() + street2 = fields.Char() + zip = fields.Char(change_default=True) + city = fields.Char() + state_id = fields.Many2one("res.country.state", string='State', + ondelete='restrict') + country_id = fields.Many2one('res.country', string='Country', + ondelete='restrict') + email = fields.Char() + phone = fields.Char() + mobile = fields.Char() + + _sql_constraints = [('branch_code_company_uniq', 'unique (code,company_id)', + 'The branch code must be unique per company!')] + + @api.model + def create(self, vals): + if not vals.get('partner_id', False): + partner_id = self.env['res.partner'].create({'name': vals['name']}) + vals.update({'partner_id': partner_id.id}) + res = super(ResBranch, self).create(vals) + vals.pop("name", None) + vals.pop("code", None) + vals.pop("partner_id", None) + vals.update({'branch_id': res.id}) + res.partner_id.write(vals) + return res + + @api.multi + def write(self, vals): + res = super(ResBranch, self).write(vals) + vals.pop("name", None) + vals.pop("code", None) + vals.pop("company_id", None) + vals.pop("partner_id", None) + ctx = self.env.context.copy() + if 'branch' not in ctx: + self.partner_id.write(vals) + return res + + +class Users(models.Model): + + _inherit = "res.users" + + @api.model + def branch_default_get(self, user): + if not user: + user = self._uid + branch_id = self.env['res.users'].browse(user).default_branch_id + if not branch_id: + branch_id = \ + self.env['res.users'].browse(user).company_id.branch_id + return branch_id + + @api.model + def _get_default_branch(self): + return self.branch_default_get(self._uid) + + branch_ids = fields.Many2many('res.branch', + 'res_branch_users_rel', + 'user_id', + 'branch_id', + 'Branches') + default_branch_id = fields.Many2one('res.branch', 'Default branch', + default=_get_default_branch, + domain="[('company_id','=',company_id)" + "]") + + diff --git a/addons/base_branch_company/models/res_partner.py b/addons/base_branch_company/models/res_partner.py new file mode 100644 index 00000000..932be8c8 --- /dev/null +++ b/addons/base_branch_company/models/res_partner.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +from flectra import api, fields, models + +class Partner(models.Model): + _name = "res.partner" + _inherit = ["res.partner", "ir.branch.company.mixin"] + + @api.multi + def write(self, vals): + field_list = ['street', 'street2', 'zip', 'city', 'state_id', + 'country_id', 'email', 'phone', 'mobile'] + branch_vals = dict((f, vals[f]) for f in field_list if f in vals) + if branch_vals and self.branch_id: + ctx = self.env.context.copy() + ctx.update({'branch': True}) + self.branch_id.with_context(ctx).write(branch_vals) + result = super(Partner, self).write(vals) + return result + + + diff --git a/addons/base_branch_company/security/branch_security.xml b/addons/base_branch_company/security/branch_security.xml new file mode 100644 index 00000000..c35a3964 --- /dev/null +++ b/addons/base_branch_company/security/branch_security.xml @@ -0,0 +1,20 @@ + + + + + Branch + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + + + ['|', ('id','=',user.default_branch_id.id), ('id','in',[g.id for g in user.branch_ids])] + + Allowed Branch + + + + diff --git a/addons/base_branch_company/security/ir.model.access.csv b/addons/base_branch_company/security/ir.model.access.csv new file mode 100644 index 00000000..9759f6d0 --- /dev/null +++ b/addons/base_branch_company/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_res_branch,access_res_branch,model_res_branch,,1,1,1,0 +access_ir_branch_company,access_ir_branch_company,model_ir_branch_company_mixin,,1,1,1,0 \ No newline at end of file diff --git a/addons/base_branch_company/tests/__init__.py b/addons/base_branch_company/tests/__init__.py new file mode 100644 index 00000000..f6fb8a09 --- /dev/null +++ b/addons/base_branch_company/tests/__init__.py @@ -0,0 +1 @@ +from . import test_branch diff --git a/addons/base_branch_company/tests/test_branch.py b/addons/base_branch_company/tests/test_branch.py new file mode 100644 index 00000000..5677d353 --- /dev/null +++ b/addons/base_branch_company/tests/test_branch.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Part of Flectra. See LICENSE file for full copyright and licensing details. + +from flectra.tests.common import TransactionCase +import logging +_logger = logging.getLogger(__name__) + +class TestMultiBranch(TransactionCase): + def setUp(self): + super(TestMultiBranch, self).setUp() + self.partner_obj = self.env['res.partner'] + self.main_company = self.env.ref('base.main_company') + + self.branch0 = self.env.ref('base_branch_company.data_branch_1') + self.branch1 = self.env.ref('base_branch_company.data_branch_2') + + self.user_1 = self.create_user(self.main_company, 'user_1', self.branch0, + [self.branch0, self.branch1]) + self.user_2 = self.create_user(self.main_company, 'user_2', self.branch1, + [self.branch1]) + + self.model_id = \ + self.env['ir.model'].search([('model', '=', 'res.partner')]) + self.record_rules = self.env['ir.rule'].create({ + 'name': 'Partner', + 'model_id': self.model_id.id, + 'domain_force': + "['|',('branch_id','=', False),'|', " + "('branch_id','=',user.default_branch_id.id), " + "('branch_id','in', [b.id for b in user.branch_ids] )]" + }) + self.branch_partner0 = self.partner_obj.create({ + 'name': 'Test Partner0', + 'email': 'test@123.example.com', + 'branch_id': self.branch0.id + }) + + self.env = self.env(user=self.user_1) + self.branch_partner1 = self.partner_obj.create({ + 'name': 'Test Partner1', + 'email': 'test@123.example.com', + 'branch_id': self.branch0.id + }) + + def create_user(self, main_company, user_name, branch_id, branch_ids): + data = { + 'company_ids': [(4, main_company.id)], + 'branch_ids': [(4, branch_id.id) for branch_id in branch_ids], + 'company_id': main_company.id, + 'default_branch_id': branch_id.id, + 'login': user_name, + 'name': 'Test User', + 'password': '123', + 'email': 'testuser@yourcompany.com', + + } + user_obj = self.env['res.users'].create(data) + return user_obj + + + def test_user_authentication(self): + partner = self.partner_obj.sudo(self.user_1.id).search( + [('id', '=', self.branch_partner1.id), + ('branch_id', '=', self.branch0.id)]) + self.assertNotEqual(partner.ids, [], 'Test User have access to ' + 'Branch %s' % self.branch0.name) + + partner = self.partner_obj.sudo(self.user_2.id).search( + [('id', '=', self.branch_partner0.id), + ('branch_id', '=', self.branch0.id)]) + self.assertEqual(partner.ids, [], + 'Test User should not have access to ' + 'Branch %s' % self.branch0.name) + + + + + + + diff --git a/addons/base_branch_company/views/res_branch_view.xml b/addons/base_branch_company/views/res_branch_view.xml new file mode 100644 index 00000000..0f792d3a --- /dev/null +++ b/addons/base_branch_company/views/res_branch_view.xml @@ -0,0 +1,106 @@ + + + + res.branch.form + res.branch + +
+ +
+ +
+ + + + + + + + + + + + + + + +
+
+
+
+ + + res.branch.tree + res.branch + + + + + + + + + + res.branch.search + res.branch + + + + + + + + + + Branches + res.branch + form + tree,form + +

+ Click to start a new Branch. +

+
+
+ + + + + + res.users.form.branch + res.users + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/addons/crm/__manifest__.py b/addons/crm/__manifest__.py index 41f4c57e..4204bd98 100644 --- a/addons/crm/__manifest__.py +++ b/addons/crm/__manifest__.py @@ -3,7 +3,7 @@ { 'name': 'CRM', - 'author': 'Odoo S.A', + 'author' : 'Odoo S.A', 'version': '1.0', 'category': 'Sales', 'sequence': 5, diff --git a/addons/crm/data/crm_lead_demo.xml b/addons/crm/data/crm_lead_demo.xml index 6bacd14c..9e35c74e 100644 --- a/addons/crm/data/crm_lead_demo.xml +++ b/addons/crm/data/crm_lead_demo.xml @@ -53,6 +53,7 @@ 1 + @@ -82,6 +83,7 @@ Bordeaux 33000 + Rue Ignasse Blanchoux 214/32 +33 1 25 54 45 69 @@ -111,6 +113,7 @@ contact@thekompany.example.com New York + 10001 Lafayette Ave 450/12 +1 555 754 3010 @@ -133,6 +136,7 @@ hmc@yahoo.example.com Manchester + 03101 United Street 68 @@ -369,6 +373,7 @@ Andrew

]]>
Rediff Mail willmac@rediffmail.example.com + Melbourne Kensington Road 189 diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 52d0a1ee..4f866fef 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -50,7 +50,7 @@ class Lead(models.Model): _name = "crm.lead" _description = "Lead/Opportunity" _order = "priority desc,activity_date_deadline,id desc" - _inherit = ['mail.thread', 'mail.activity.mixin', 'utm.mixin', 'format.address.mixin'] + _inherit = ['mail.thread', 'mail.activity.mixin', 'utm.mixin', 'format.address.mixin', 'ir.branch.company.mixin'] def _default_probability(self): stage_id = self._default_stage_id() diff --git a/addons/crm/models/crm_team.py b/addons/crm/models/crm_team.py index 353e99c1..b5793902 100644 --- a/addons/crm/models/crm_team.py +++ b/addons/crm/models/crm_team.py @@ -78,6 +78,7 @@ class Team(models.Model): values['alias_defaults'] = defaults = safe_eval(self.alias_defaults or "{}") defaults['type'] = 'lead' if has_group_use_lead and self.use_leads else 'opportunity' defaults['team_id'] = self.id + defaults['branch_id'] = self.branch_id and self.branch_id.id return values @api.onchange('use_leads', 'use_opportunities') diff --git a/addons/crm/security/crm_security.xml b/addons/crm/security/crm_security.xml index 37de86be..c46aff15 100644 --- a/addons/crm/security/crm_security.xml +++ b/addons/crm/security/crm_security.xml @@ -84,6 +84,16 @@ ['|',('user_id','=',user.id),('user_id','=',False)] + + + + Lead multi-branch + + + ['|', ('branch_id', '=', False), '|', ('branch_id', '=', user.default_branch_id.id), + ('branch_id', 'in', user.branch_ids.ids)] + + diff --git a/addons/crm/tests/__init__.py b/addons/crm/tests/__init__.py index f6f7d9a8..0b9831b2 100644 --- a/addons/crm/tests/__init__.py +++ b/addons/crm/tests/__init__.py @@ -5,3 +5,4 @@ from . import test_new_lead_notification from . import test_lead2opportunity from . import test_crm_activity from . import test_crm_ui +from . import test_crm_branch diff --git a/addons/crm/tests/common.py b/addons/crm/tests/common.py index ba29e67f..35d9eaa7 100644 --- a/addons/crm/tests/common.py +++ b/addons/crm/tests/common.py @@ -33,11 +33,13 @@ class TestCrmCases(TransactionCase): def setUp(self): super(TestCrmCases, self).setUp() - + branch0 = self.env.ref('base_branch_company.data_branch_1') + branch = self.env.ref('base_branch_company.data_branch_2') # Create a user as 'Crm Salesmanager' and added the `sales manager` group self.crm_salemanager = self.env['res.users'].create({ 'company_id': self.env.ref("base.main_company").id, - 'name': "Crm Sales manager", + 'name': "Crm Sales manager", 'default_branch_id': branch.id, + 'branch_ids': [(4, branch_id.id) for branch_id in [branch0, branch]], 'login': "csm", 'email': "crmmanager@yourcompany.com", 'groups_id': [(6, 0, [self.ref('sales_team.group_sale_manager')])] @@ -46,7 +48,8 @@ class TestCrmCases(TransactionCase): # Create a user as 'Crm Salesman' and added few groups self.crm_salesman = self.env['res.users'].create({ 'company_id': self.env.ref("base.main_company").id, - 'name': "Crm Salesman", + 'name': "Crm Salesman", 'default_branch_id': branch.id, + 'branch_ids': [(4, branch_id.id) for branch_id in [branch0, branch]], 'login': "csu", 'email': "crmuser@yourcompany.com", 'groups_id': [(6, 0, [self.env.ref('sales_team.group_sale_salesman_all_leads').id, self.env.ref('base.group_partner_manager').id])] diff --git a/addons/crm/tests/test_crm_activity.py b/addons/crm/tests/test_crm_activity.py index 046c9e6f..3e2639b9 100644 --- a/addons/crm/tests/test_crm_activity.py +++ b/addons/crm/tests/test_crm_activity.py @@ -34,10 +34,12 @@ class TestCrmMailActivity(TestCrmCases): # I create an opportunity, as salesman self.partner_client = self.env.ref("base.res_partner_1") + branch = self.env.ref('base_branch_company.data_branch_2') self.lead = self.env['crm.lead'].sudo(self.crm_salesman.id).create({ 'name': 'Test Opp', 'type': 'opportunity', 'partner_id': self.partner_client.id, + 'branch_id': branch.id, 'team_id': self.env.ref("sales_team.team_sales_department").id, 'user_id': self.crm_salesman.id, }) diff --git a/addons/crm/tests/test_crm_branch.py b/addons/crm/tests/test_crm_branch.py new file mode 100644 index 00000000..9770929d --- /dev/null +++ b/addons/crm/tests/test_crm_branch.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +from flectra.tests import common + + +class TestCrmBranch(common.TransactionCase): + + def setUp(self): + super(TestCrmBranch, self).setUp() + + self.branch_1 = self.env.ref('base_branch_company.data_branch_1') + self.branch_2 = self.env.ref('base_branch_company.data_branch_2') + self.model_crm = self.env['crm.lead'] + self.sale_user_group = self.env.ref('sales_team.group_sale_manager') + self.main_company = self.env.ref('base.main_company') + self.crm_user_group = self.env.ref('base.group_user') + + self.user_1 = self.create_crm_user(self.main_company, self.branch_1, [self.branch_1],'user_1', [self.sale_user_group, + self.crm_user_group]) + self.user_2 = self.create_crm_user(self.main_company, self.branch_2, [self.branch_2], 'user_2', [self.sale_user_group, + self.crm_user_group]) + self.team1=self.env.ref('sales_team.team_sales_department') + self.team1.write({'branch_id': self.branch_1.id, 'user_id': self.user_1.id}) + self.team2 = self.env.ref('sales_team.crm_team_1') + self.team2.write({'branch_id': self.branch_2.id, 'user_id': self.user_2.id}) + + self.lead_1 = self.lead_create(self.branch_1, self.team1, self.user_1.id) + self.lead_2 = self.lead_create(self.branch_2, self.team2, self.user_2.id) + + def create_crm_user(self, main_company, branch, branch_ids, login_user, groups): + groups = [group.id for group in groups] + user_obj = self.env['res.users'].create({ + 'company_id': main_company.id, + 'branch_ids': [(4, branch_id.id) for branch_id in branch_ids], + 'default_branch_id': branch.id, + 'company_ids': [(4, main_company.id)], + 'groups_id': [(6, 0, groups)], + 'login': login_user, + 'name': 'CRM Test ' + login_user, + 'email': 'demo@yourcompany.com', + 'password': '123', + }) + return user_obj + + + def lead_create(self, branch_id, team_id, user_id, ): + lead_name = 'CRM LEAD ' + lead = self.model_crm.create({ + 'user_id': user_id, + 'team_id': team_id.id, + 'name': lead_name + branch_id.name, + 'branch_id': branch_id.id, + }) + return lead + + def test_lead_authentication(self): + lead_ids = self.model_crm.sudo(self.user_2.id).search( + [('branch_id', '=', self.branch_1.id), ('id', '=', self.lead_1.id)]) + self.assertEqual(lead_ids.ids, [], ('%s should not have' + ' access to %s') + % (self.user_2.name, self.branch_1.name)) + + def test_team_branch(self): + lead = self.lead_create(self.branch_2, self.team2, self.user_2.id ) + self.assertEqual( + lead.branch_id, self.branch_2, ('%s lead ' + 'should have %s as branch') + % (self.user_2.name, + self.branch_2.name)) diff --git a/addons/crm/tests/test_crm_lead.py b/addons/crm/tests/test_crm_lead.py index 0455db4e..941aaa65 100644 --- a/addons/crm/tests/test_crm_lead.py +++ b/addons/crm/tests/test_crm_lead.py @@ -25,8 +25,10 @@ class TestCRMLead(TestCrmCases): def test_find_stage(self): # I create a new lead + branch = self.env.ref('base_branch_company.data_branch_1') lead = self.env['crm.lead'].create({ 'type': "lead", + 'branch_id': branch.id, 'name': "Test lead new", 'partner_id': self.env.ref("base.res_partner_1").id, 'description': "This is the description of the test new lead.", @@ -77,11 +79,12 @@ class TestCRMLead(TestCrmCases): # During a mixed merge (involving leads and opps), data should be handled a certain way following their type (m2o, m2m, text, ...) Start by creating two leads and an opp and giving the rights of Sales manager. default_stage_id = self.ref("crm.stage_lead1") LeadSalesmanager = self.env['crm.lead'].sudo(self.crm_salemanager.id) - + branch = self.env.ref('base_branch_company.data_branch_2') # TEST CASE 1 test_crm_opp_01 = LeadSalesmanager.create({ 'type': 'opportunity', 'name': 'Test opportunity 1', + 'branch_id': branch.id, 'partner_id': self.env.ref("base.res_partner_3").id, 'stage_id': default_stage_id, 'description': 'This is the description of the test opp 1.' @@ -91,7 +94,7 @@ class TestCRMLead(TestCrmCases): 'type': 'lead', 'name': 'Test lead first', 'partner_id': self.env.ref("base.res_partner_1").id, - 'stage_id': default_stage_id, + 'stage_id': default_stage_id, 'branch_id': branch.id, 'description': 'This is the description of the test lead first.' }) @@ -99,7 +102,7 @@ class TestCRMLead(TestCrmCases): 'type': 'lead', 'name': 'Test lead second', 'partner_id': self.env.ref("base.res_partner_1").id, - 'stage_id': default_stage_id, + 'stage_id': default_stage_id, 'branch_id': branch.id, 'description': 'This is the description of the test lead second.' }) @@ -124,14 +127,14 @@ class TestCRMLead(TestCrmCases): # I want to test leads merge. Start by creating two leads (with the same partner) test_crm_lead_03 = LeadSalesmanager.create({ 'type': 'lead', - 'name': 'Test lead 3', + 'name': 'Test lead 3', 'branch_id': branch.id, 'partner_id': self.env.ref("base.res_partner_1").id, 'stage_id': default_stage_id }) test_crm_lead_04 = LeadSalesmanager.create({ 'type': 'lead', - 'name': 'Test lead 4', + 'name': 'Test lead 4', 'branch_id': branch.id, 'partner_id': self.env.ref("base.res_partner_1").id, 'stage_id': default_stage_id }) @@ -154,14 +157,14 @@ class TestCRMLead(TestCrmCases): # I want to test opps merge. Start by creating two opportunities (with the same partner). test_crm_opp_02 = LeadSalesmanager.create({ 'type': 'opportunity', - 'name': 'Test opportunity 2', + 'name': 'Test opportunity 2', 'branch_id': branch.id, 'partner_id': self.env.ref("base.res_partner_3").id, 'stage_id': default_stage_id }) test_crm_opp_03 = LeadSalesmanager.create({ 'type': 'opportunity', - 'name': 'Test opportunity 3', + 'name': 'Test opportunity 3', 'branch_id': branch.id, 'partner_id': self.env.ref("base.res_partner_3").id, 'stage_id': default_stage_id }) diff --git a/addons/crm/tests/test_lead2opportunity.py b/addons/crm/tests/test_lead2opportunity.py index 861444b3..4f587470 100644 --- a/addons/crm/tests/test_lead2opportunity.py +++ b/addons/crm/tests/test_lead2opportunity.py @@ -38,6 +38,7 @@ class TestLead2opportunity2win(TestCrmCases): crm_case_3.message_post(subject='Test note', body='Détails envoyés par le client sur ​​le FAX pour la qualité') # I convert mass lead into opportunity customer. + branch = self.env.ref('base_branch_company.data_branch_1') mass = CrmLead2OpportunityPartnerMass.with_context({'active_model': 'crm.lead', 'active_ids': [crm_case_13.id, crm_case_2.id], 'active_id': crm_case_13.id}).create({ 'user_ids': [(6, 0, self.env.ref('base.user_root').ids)], 'team_id': self.env.ref("sales_team.team_sales_department").id @@ -73,25 +74,25 @@ class TestLead2opportunity2win(TestCrmCases): CrmLead2OpportunityPartnerMass = self.env['crm.lead2opportunity.partner.mass'] LeadSaleman = self.env['crm.lead'].sudo(self.crm_salesman.id) default_stage_id = self.ref("crm.stage_lead1") - + branch = self.env.ref('base_branch_company.data_branch_2') # During a lead to opp conversion, salesmen should be assigned to leads following the round-robin method. Start by creating 4 salesmen (A to D) and 6 leads (1 to 6). test_res_user_01 = self.env['res.users'].create({ - 'name': 'Test user A', + 'name': 'Test user A', 'default_branch_id': branch.id, 'login': 'tua@example.com', 'new_password': 'tua' }) test_res_user_02 = self.env['res.users'].create({ - 'name': 'Test user B', + 'name': 'Test user B', 'default_branch_id': branch.id, 'login': 'tub@example.com', 'new_password': 'tub' }) test_res_user_03 = self.env['res.users'].create({ - 'name': 'Test user C', + 'name': 'Test user C', 'default_branch_id': branch.id, 'login': 'tuc@example.com', 'new_password': 'tuc' }) test_res_user_04 = self.env['res.users'].create({ - 'name': 'Test user D', + 'name': 'Test user D', 'default_branch_id': branch.id, 'login': 'tud@example.com', 'new_password': 'tud' }) @@ -99,36 +100,36 @@ class TestLead2opportunity2win(TestCrmCases): # Salesman also creates lead so giving access rights of salesman. test_crm_lead_01 = LeadSaleman.create({ 'type': 'lead', - 'name': 'Test lead 1', + 'name': 'Test lead 1', 'branch_id': branch.id, 'email_from': 'Raoul Grosbedon ', 'stage_id': default_stage_id }) test_crm_lead_02 = LeadSaleman.create({ - 'type': 'lead', + 'type': 'lead', 'branch_id': branch.id, 'name': 'Test lead 2', 'email_from': 'Raoul Grosbedon ', 'stage_id': default_stage_id }) test_crm_lead_03 = LeadSaleman.create({ - 'type': 'lead', + 'type': 'lead', 'branch_id': branch.id, 'name': 'Test lead 3', 'email_from': 'Raoul Grosbedon ', 'stage_id': default_stage_id }) test_crm_lead_04 = LeadSaleman.create({ - 'type': 'lead', + 'type': 'lead', 'branch_id': branch.id, 'name': 'Test lead 4', 'email_from': 'Fabrice Lepoilu', 'stage_id': default_stage_id }) test_crm_lead_05 = LeadSaleman.create({ - 'type': 'lead', + 'type': 'lead', 'branch_id': branch.id, 'name': 'Test lead 5', 'email_from': 'Fabrice Lepoilu', 'stage_id': default_stage_id }) test_crm_lead_06 = LeadSaleman.create({ - 'type': 'lead', + 'type': 'lead', 'branch_id': branch.id, 'name': 'Test lead 6', 'email_from': 'Agrolait SuperSeed SA', 'stage_id': default_stage_id diff --git a/addons/crm/tests/test_new_lead_notification.py b/addons/crm/tests/test_new_lead_notification.py index db1d018a..796ec7c2 100644 --- a/addons/crm/tests/test_new_lead_notification.py +++ b/addons/crm/tests/test_new_lead_notification.py @@ -16,6 +16,7 @@ class NewLeadNotification(TestCrm): # Imitate what happens in the controller when somebody creates a new # lead from the website form + branch = self.env.ref('base_branch_company.data_branch_1') lead = self.env["crm.lead"].with_context(mail_create_nosubscribe=True).sudo().create({ "contact_name": "Somebody", "description": "Some question", @@ -23,6 +24,7 @@ class NewLeadNotification(TestCrm): "name": "Some subject", "partner_name": "Some company", "team_id": self.sales_team_1.id, + "branch_id": branch.id, "phone": "+0000000000" }) # partner and channel should be auto subscribed diff --git a/addons/crm/views/crm_lead_views.xml b/addons/crm/views/crm_lead_views.xml index 3a8a3275..3edfb58b 100644 --- a/addons/crm/views/crm_lead_views.xml +++ b/addons/crm/views/crm_lead_views.xml @@ -89,6 +89,7 @@ + @@ -492,6 +493,7 @@ + @@ -650,6 +652,7 @@ + diff --git a/addons/sales_team/models/crm_team.py b/addons/sales_team/models/crm_team.py index fc3c9600..c44ee16a 100644 --- a/addons/sales_team/models/crm_team.py +++ b/addons/sales_team/models/crm_team.py @@ -8,14 +8,14 @@ from dateutil.relativedelta import relativedelta import json from flectra import api, fields, models, _ -from flectra.exceptions import UserError +from flectra.exceptions import UserError, ValidationError from flectra.release import version from flectra.tools import DEFAULT_SERVER_DATE_FORMAT as DF class CrmTeam(models.Model): _name = "crm.team" - _inherit = ['mail.thread'] + _inherit = ['mail.thread', 'ir.branch.company.mixin'] _description = "Sales Channel" _order = "name" @@ -81,6 +81,18 @@ class CrmTeam(models.Model): ('year', 'Last Year'), ], string='Scale', default='month', help="The time period this channel's dashboard graph will consider.") + @api.constrains('company_id', 'branch_id') + def _check_company_branch(self): + for record in self: + if record.company_id and record.company_id != record.branch_id.company_id: + raise ValidationError( + _('Configuration Error of Company:\n' + 'The Company (%s) in the Team and ' + 'the Company (%s) of Branch must ' + 'be the same company!') % (record.company_id.name, + record.branch_id.company_id.name) + ) + @api.depends('dashboard_graph_group', 'dashboard_graph_model', 'dashboard_graph_period') def _compute_dashboard_graph(self): for team in self.filtered('dashboard_graph_model'): diff --git a/addons/sales_team/security/sales_team_security.xml b/addons/sales_team/security/sales_team_security.xml index 5e776de4..11802bd0 100644 --- a/addons/sales_team/security/sales_team_security.xml +++ b/addons/sales_team/security/sales_team_security.xml @@ -40,6 +40,13 @@ + + CRM Team multi-branch + + + ['|',('branch_id','=', False),'|',('branch_id','=',user.default_branch_id.id), ('branch_id','in', [b.id for b in user.branch_ids])] + + diff --git a/addons/sales_team/tests/__init__.py b/addons/sales_team/tests/__init__.py new file mode 100644 index 00000000..a265991d --- /dev/null +++ b/addons/sales_team/tests/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import test_branch_crm_team diff --git a/addons/sales_team/tests/test_branch_crm_team.py b/addons/sales_team/tests/test_branch_crm_team.py new file mode 100644 index 00000000..d3c9b900 --- /dev/null +++ b/addons/sales_team/tests/test_branch_crm_team.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +from flectra.tests import common + + +class TestBranchSaleTeam(common.TransactionCase): + + def setUp(self): + super(TestBranchSaleTeam, self).setUp() + + self.main_company = self.env.ref('base.main_company') + self.sale_user_group = self.env.ref('sales_team.group_sale_manager') + self.manager_user_group = self.env.ref('sales_team.group_sale_manager') + self.branch_1 = self.env.ref('base_branch_company.data_branch_1') + self.branch_3 = self.env.ref('base_branch_company.data_branch_3') + self.user_id_1 = self.create_sale_team_user(self.main_company, 'user_1', self.branch_1, + [self.branch_1, self.branch_3], + [self.sale_user_group, self.manager_user_group]) + self.user_id_2 = self.create_sale_team_user(self.main_company, 'user_2', self.branch_3, + [self.branch_3], + [self.sale_user_group, self.manager_user_group]) + self.sales_team_1 = self.crm_team_create('CRM Team User 1', self.user_id_1, self.branch_1) + self.sales_team_2 = self.crm_team_create('CRM Team User 2', self.user_id_2, self.branch_3) + + def create_sale_team_user(self, main_company, user_name, branch_id, branch_ids, groups): + group_ids = [grp.id for grp in groups] + data = { + 'company_ids': [(4, main_company.id)], + 'branch_ids': [(4, ou.id) for ou in branch_ids], + 'company_id': main_company.id, + 'groups_id': [(6, 0, group_ids)], + 'default_branch_id': branch_id.id, + 'login': user_name, + 'name': 'Ron Sales User', + 'password': '123', + 'email': 'ron@yourcompany.com', + } + user_obj = self.env['res.users'].create(data) + return user_obj + + def crm_team_create(self, team_name, user_id, branch_id): + crm_id = self.env['crm.team'].sudo(user_id.id).create({'name': team_name, + 'branch_id': branch_id.id}) + return crm_id + + def get_crm_team(self, user_id, sales_team_1, branch_id): + crm_team = self.env['crm.team'].sudo(user_id.id).search( + [('id', '=', sales_team_1.id), + ('branch_id', '=', branch_id.id)]) + return crm_team + + def test_user_authentication_2(self): + crm_team = self.get_crm_team(self.user_id_1, self.sales_team_1, self.branch_3) + self.assertEqual(crm_team.ids, [], ('%s should not have ' + 'access to Branch %s') % ( + self.user_id_1.name, self.branch_1.name))