From 34ff16a2002e429041845054a61ea37ff1791ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 18 Mar 2021 23:04:17 +0100 Subject: [PATCH] Remove tree structure from company issue10163 review332181002 --- CHANGELOG | 1 + __init__.py | 1 + company.py | 12 ++--- company.xml | 31 +---------- doc/index.rst | 12 ++--- res.py | 121 +++++++++++++++++++++++------------------- setup.py | 2 +- tests/test_company.py | 30 +++-------- view/company_form.xml | 6 +-- view/company_tree.xml | 7 --- view/user_form.xml | 5 +- 11 files changed, 90 insertions(+), 138 deletions(-) delete mode 100644 view/company_tree.xml diff --git a/CHANGELOG b/CHANGELOG index 1ffe67b1fa..d4d173e129 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Remove tree structure from company * Add test on context of company multivalue target fields * Use report header for CompanyReport diff --git a/__init__.py b/__init__.py index 6ee59e2ef6..3e602da768 100644 --- a/__init__.py +++ b/__init__.py @@ -16,6 +16,7 @@ def register(): company.Company, company.Employee, company.CompanyConfigStart, + res.UserCompany, res.UserEmployee, res.User, ir.Sequence, diff --git a/company.py b/company.py index 159e0a6eb4..1a4520abb8 100644 --- a/company.py +++ b/company.py @@ -1,6 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -from trytond.model import ModelView, ModelSQL, fields, tree +from trytond.model import ModelView, ModelSQL, fields from trytond.wizard import Wizard, StateView, Button, StateTransition from trytond.report import Report from trytond.pyson import Eval, If @@ -17,15 +17,11 @@ TIMEZONES += [(None, '')] Transaction.cache_keys.update({'company', 'employee'}) -class Company(tree(), ModelSQL, ModelView): +class Company(ModelSQL, ModelView): 'Company' __name__ = 'company.company' party = fields.Many2One('party.party', 'Party', required=True, ondelete='CASCADE') - parent = fields.Many2One('company.company', 'Parent', - help="Add the company below the parent.") - childs = fields.One2Many('company.company', 'parent', 'Children', - help="Add children below the company.") header = fields.Text( 'Header', help="The text to display on report headers.") footer = fields.Text( @@ -130,10 +126,10 @@ class CompanyConfig(Wizard): self.company.save() users = User.search([ - ('main_company', '=', None), + ('companies', '=', None), ]) User.write(users, { - 'main_company': self.company.id, + 'companies': [('add', [self.company.id])], 'company': self.company.id, }) return 'end' diff --git a/company.xml b/company.xml index b4f46d787a..dfd3b805a6 100644 --- a/company.xml +++ b/company.xml @@ -44,41 +44,12 @@ this repository contains the full copyright notices and license terms. --> company_form - - company.company - tree - childs - company_tree - company.company tree company_list - - Companies - company.company - - - - - - - - - - - - - - Companies @@ -97,7 +68,7 @@ this repository contains the full copyright notices and license terms. --> diff --git a/doc/index.rst b/doc/index.rst index e8af59bcdb..06379a721e 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -27,10 +27,8 @@ user form. User **** -Are added to the user model: a main company, a company and an employee -field. The company field defines the current company of the user, this -current company will influence the data this user see in Tryton: most -of the records that are linked to a company will only be available for -users in this very company. The main company define which current -company a user can choose: either the main company itself or one of -the children companies. +Are added to the user model: companies, a company and an employee field. The +company field defines the current company of the user, this current company +will influence the data this user see in Tryton: most of the records that are +linked to a company will only be available for users in this very company. The +companies define which current company a user can choose. diff --git a/res.py b/res.py index 3ace2ad05e..2a7a1ad683 100644 --- a/res.py +++ b/res.py @@ -1,11 +1,24 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. +from sql import Null + from trytond.model import ModelSQL, fields from trytond.pool import PoolMeta, Pool from trytond.pyson import Eval from trytond.transaction import Transaction +class UserCompany(ModelSQL): + "User - Company" + __name__ = 'res.user-company.company' + + user = fields.Many2One( + 'res.user', "User", ondelete='CASCADE', select=True, required=True) + company = fields.Many2One( + 'company.company', "Company", + ondelete='CASCADE', select=True, required=True) + + class UserEmployee(ModelSQL): 'User - Employee' __name__ = 'res.user-company.employee' @@ -17,16 +30,23 @@ class UserEmployee(ModelSQL): class User(metaclass=PoolMeta): __name__ = 'res.user' - main_company = fields.Many2One('company.company', 'Main Company', - help="Grant access to the company and its children.") - company = fields.Many2One('company.company', 'Current Company', - domain=[('parent', 'child_of', [Eval('main_company')], 'parent')], - depends=['main_company'], + + companies = fields.Many2Many( + 'res.user-company.company', 'user', 'company', "Companies", + help="The companies that the user has access to.") + company = fields.Many2One( + 'company.company', "Current Company", + domain=[ + ('id', 'in', Eval('companies', [])), + ], + depends=['companies'], help="Select the company to work for.") - companies = fields.Function(fields.One2Many('company.company', None, - 'Companies'), 'get_companies') employees = fields.Many2Many('res.user-company.employee', 'user', 'employee', 'Employees', + domain=[ + ('company', 'in', Eval('companies', [])), + ], + depends=['companies'], help="Add employees to grant the user access to them.") employee = fields.Many2One('company.employee', 'Current Employee', domain=[ @@ -42,37 +62,42 @@ class User(metaclass=PoolMeta): cls._context_fields.insert(0, 'company') cls._context_fields.insert(0, 'employee') - @staticmethod - def default_main_company(): - return Transaction().context.get('company') + @classmethod + def __register__(cls, module): + pool = Pool() + UserCompany = pool.get('res.user-company.company') + transaction = Transaction() + table = cls.__table__() + user_company = UserCompany.__table__() + + super().__register__(module) + + table_h = cls.__table_handler__(module) + cursor = transaction.connection.cursor() + + # Migration from 5.8: remove main_company + if table_h.column_exist('main_company'): + cursor.execute(*user_company.insert( + [user_company.user, user_company.company], + table.select( + table.id, table.main_company, + where=table.main_company != Null))) + cursor.execute(*user_company.insert( + [user_company.user, user_company.company], + table.select( + table.id, table.company, + where=(table.company != Null) + & (table.company != table.main_company)))) + table_h.drop_column('main_company') + + @classmethod + def default_companies(cls): + company = Transaction().context.get('company') + return [company] if company else None @classmethod def default_company(cls): - return cls.default_main_company() - - @classmethod - def get_companies(cls, users, name): - Company = Pool().get('company.company') - companies = {} - company_childs = {} - for user in users: - companies[user.id] = [] - company = None - if user.company: - company = user.company - elif user.main_company: - company = user.main_company - if company: - if company in company_childs: - company_ids = company_childs[company] - else: - company_ids = list(map(int, Company.search([ - ('parent', 'child_of', [company.id]), - ]))) - company_childs[company] = company_ids - if company_ids: - companies[user.id].extend(company_ids) - return companies + return Transaction().context.get('company') def get_status_bar(self, name): def same_company(record): @@ -82,16 +107,11 @@ class User(metaclass=PoolMeta): and len(list(filter(same_company, self.employees))) > 1): status += ' - %s' % self.employee.rec_name if self.company: - if self.main_company.childs: + if len(self.companies) > 1: status += ' - %s' % self.company.rec_name status += ' [%s]' % self.company.currency.code return status - @fields.depends('main_company') - def on_change_main_company(self): - self.company = self.main_company - self.employee = None - @fields.depends('company', 'employees') def on_change_company(self): Employee = Pool().get('company.employee') @@ -109,16 +129,12 @@ class User(metaclass=PoolMeta): res = super(User, cls)._get_preferences(user, context_only=context_only) if not context_only: - res['main_company'] = None - if user.main_company: - res['main_company'] = user.main_company.id - res['main_company.rec_name'] = user.main_company.rec_name + res['companies'] = [c.id for c in user.companies] res['employees'] = [e.id for e in user.employees] return res @classmethod def read(cls, ids, fields_names): - Company = Pool().get('company.company') user_id = Transaction().user if user_id == 0 and 'user' in Transaction().context: user_id = Transaction().context['user'] @@ -138,15 +154,12 @@ class User(metaclass=PoolMeta): if values: if ('company' in fields_names and 'company' in Transaction().context): - main_company_id = values.get('main_company') - if not main_company_id: - main_company_id = cls.read([user_id], - ['main_company'])[0]['main_company'] - companies = Company.search([ - ('parent', 'child_of', [main_company_id]), - ]) + companies = values.get('companies') + if not companies: + companies = cls.read([user_id], + ['companies'])[0]['companies'] company_id = Transaction().context['company'] - if ((company_id and company_id in map(int, companies)) + if ((company_id and company_id in companies) or not company_id or Transaction().user == 0): values['company'] = company_id diff --git a/setup.py b/setup.py index 3593b6d531..f7b7bb1c04 100755 --- a/setup.py +++ b/setup.py @@ -57,7 +57,7 @@ else: if local_version: version += '+' + '.'.join(local_version) -requires = [] +requires = ['python-sql >= 0.4'] for dep in info.get('depends', []): if not re.match(r'(ir|res)(\W|$)', dep): requires.append(get_require_version('trytond_%s' % dep)) diff --git a/tests/test_company.py b/tests/test_company.py index 94b014c269..b743f50d66 100644 --- a/tests/test_company.py +++ b/tests/test_company.py @@ -51,7 +51,7 @@ def set_company(company): pool = Pool() User = pool.get('res.user') User.write([User(Transaction().user)], { - 'main_company': company.id, + 'companies': [('add', [company.id])], 'company': company.id, }) with Transaction().set_context(User.get_preferences(context_only=True)): @@ -110,23 +110,6 @@ class CompanyTestCase( company = create_company() self.assertTrue(company) - @with_transaction() - def test_company_recursion(self): - 'Test company recursion' - pool = Pool() - Company = pool.get('company.company') - - company1 = create_company() - company2 = create_company('Michael Scott Paper Company') - company2.parent = company1 - company2.save() - self.assertTrue(company2) - - self.assertRaises(Exception, Company.write, - [company1], { - 'parent': company2.id, - }) - @with_transaction() def test_employe(self): 'Create employee' @@ -154,19 +137,18 @@ class CompanyTestCase( company1 = create_company() company2 = create_company('Michael Scott Paper Company', currency=company1.currency) - company2.parent = company1 company2.save() company3 = create_company() user1, user2 = User.create([{ 'name': 'Jim Halper', 'login': 'jim', - 'main_company': company1.id, + 'companies': [('add', [company1.id, company2.id])], 'company': company1.id, }, { 'name': 'Pam Beesly', 'login': 'pam', - 'main_company': company2.id, + 'companies': [('add', [company2.id])], 'company': company2.id, }]) self.assertTrue(user1) @@ -200,7 +182,7 @@ class CompanyTestCase( company = create_company() root = User(0) root.company = None - root.main_company = None + root.companies = None root.save() with transaction.set_user(0): @@ -224,14 +206,14 @@ class CompanyTestCase( user1, user2 = User.create([{ 'name': "Jim Halper", 'login': "jim", - 'main_company': company.id, + 'companies': [('add', [company.id])], 'company': company.id, 'employees': [('add', [employee1.id, employee2.id])], 'employee': employee1.id, }, { 'name': "Pam Beesly", 'login': "pam", - 'main_company': company.id, + 'companies': [('add', [company.id])], 'company': company.id, 'employees': [('add', [employee2.id])], 'employee': employee2.id, diff --git a/view/company_form.xml b/view/company_form.xml index c5061d6e8e..07c9c1e844 100644 --- a/view/company_form.xml +++ b/view/company_form.xml @@ -9,10 +9,8 @@ this repository contains the full copyright notices and license terms. -->