diff --git a/CHANGELOG b/CHANGELOG index 05526f6577..b3a9e82d67 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +* Add company and employee administrator group +* Add top level menu entry + Version 5.4.0 - 2019-11-04 * Bug fixes (see mercurial logs for details) diff --git a/__init__.py b/__init__.py index 5a960224f6..ed915a6a5f 100644 --- a/__init__.py +++ b/__init__.py @@ -2,35 +2,39 @@ # this repository contains the full copyright notices and license terms. from trytond.pool import Pool -from .company import * -from .cron import * +from . import company +from . import ir from . import party +from . import res +from .company import CompanyReport + +__all__ = ['register', 'CompanyReport'] def register(): Pool.register( - Company, - Employee, - UserEmployee, - User, - Sequence, - SequenceStrict, - Date, - CompanyConfigStart, - Cron, - CronCompany, + company.Company, + company.Employee, + company.CompanyConfigStart, + res.UserEmployee, + res.User, + ir.Sequence, + ir.SequenceStrict, + ir.Date, + ir.Rule, + ir.Cron, + ir.CronCompany, party.Configuration, party.PartyConfigurationLang, party.Party, party.PartyLang, party.ContactMechanism, - Rule, module='company', type_='model') Pool.register( - CompanyConfig, + company.CompanyConfig, party.PartyReplace, party.PartyErase, module='company', type_='wizard') Pool.register( - LetterReport, + party.LetterReport, module='company', type_='report') diff --git a/company.xml b/company.xml index 8224737030..0e7c058c8a 100644 --- a/company.xml +++ b/company.xml @@ -3,11 +3,37 @@ this repository contains the full copyright notices and license terms. --> + + Company Administration + + + + + + + + Employee Administration + + + + + + tryton-company icons/tryton-company.svg + + + + + + + + + + company.company form @@ -44,7 +70,7 @@ this repository contains the full copyright notices and license terms. --> - + Companies @@ -62,8 +88,7 @@ this repository contains the full copyright notices and license terms. --> - + @@ -74,7 +99,7 @@ this repository contains the full copyright notices and license terms. --> - + @@ -92,49 +117,6 @@ this repository contains the full copyright notices and license terms. --> user_form_preferences - - ir.sequence - - sequence_form - - - ir.sequence - - sequence_tree - - - - User in company - - - - - - - - - - - - - - User in company - - - - - - - - - - - - company.company.config.start form @@ -180,8 +162,7 @@ this repository contains the full copyright notices and license terms. --> - + @@ -192,7 +173,7 @@ this repository contains the full copyright notices and license terms. --> - + diff --git a/cron.py b/cron.py deleted file mode 100644 index 02dde296d9..0000000000 --- a/cron.py +++ /dev/null @@ -1,40 +0,0 @@ -# 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 ModelSQL, ModelView, fields, dualmethod -from trytond.pool import Pool, PoolMeta -from trytond.transaction import Transaction - - -__all__ = ['Cron', 'CronCompany'] - - -class Cron(metaclass=PoolMeta): - __name__ = "ir.cron" - companies = fields.Many2Many('ir.cron-company.company', 'cron', 'company', - 'Companies', help='Companies registered for this cron') - - @dualmethod - @ModelView.button - def run_once(cls, crons): - for cron in crons: - if not cron.companies: - super(Cron, cls).run_once([cron]) - else: - for company in cron.companies: - with Transaction().set_context(company=company.id): - super(Cron, cls).run_once([cron]) - - @staticmethod - def default_companies(): - Company = Pool().get('company.company') - return list(map(int, Company.search([]))) - - -class CronCompany(ModelSQL): - 'Cron - Company' - __name__ = 'ir.cron-company.company' - _table = 'cron_company_rel' - cron = fields.Many2One('ir.cron', 'Cron', ondelete='CASCADE', - required=True, select=True) - company = fields.Many2One('company.company', 'Company', ondelete='CASCADE', - required=True, select=True) diff --git a/cron.xml b/cron.xml deleted file mode 100644 index 292c7e30e9..0000000000 --- a/cron.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - ir.cron - - cron_form - - - diff --git a/ir.py b/ir.py new file mode 100644 index 0000000000..7a3b65d066 --- /dev/null +++ b/ir.py @@ -0,0 +1,89 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. +import pytz + +from trytond.model import ModelSQL, ModelView, fields, dualmethod +from trytond.pool import PoolMeta, Pool +from trytond.pyson import Eval, If +from trytond.transaction import Transaction + + +class Sequence(metaclass=PoolMeta): + __name__ = 'ir.sequence' + company = fields.Many2One('company.company', 'Company', + domain=[ + ('id', If(Eval('context', {}).contains('company'), '=', '!='), + Eval('context', {}).get('company', -1)), + ], help="Restrict the sequence usage to the company.") + + @classmethod + def __setup__(cls): + super(Sequence, cls).__setup__() + cls._order.insert(0, ('company', 'ASC')) + + @staticmethod + def default_company(): + return Transaction().context.get('company') + + +class SequenceStrict(Sequence): + __name__ = 'ir.sequence.strict' + + +class Date(metaclass=PoolMeta): + __name__ = 'ir.date' + + @classmethod + def today(cls, timezone=None): + pool = Pool() + Company = pool.get('company.company') + company_id = Transaction().context.get('company') + if timezone is None and company_id: + company = Company(company_id) + if company.timezone: + timezone = pytz.timezone(company.timezone) + return super(Date, cls).today(timezone=timezone) + + +class Rule(metaclass=PoolMeta): + __name__ = 'ir.rule' + + @classmethod + def _get_cache_key(cls): + key = super(Rule, cls)._get_cache_key() + # XXX Use company from context instead of browse to prevent infinite + # loop, but the cache is cleared when User is written. + return key + (Transaction().context.get('company'), + Transaction().context.get('employee')) + + +class Cron(metaclass=PoolMeta): + __name__ = "ir.cron" + companies = fields.Many2Many('ir.cron-company.company', 'cron', 'company', + 'Companies', help='Companies registered for this cron') + + @dualmethod + @ModelView.button + def run_once(cls, crons): + for cron in crons: + if not cron.companies: + super(Cron, cls).run_once([cron]) + else: + for company in cron.companies: + with Transaction().set_context(company=company.id): + super(Cron, cls).run_once([cron]) + + @staticmethod + def default_companies(): + Company = Pool().get('company.company') + return list(map(int, Company.search([]))) + + +class CronCompany(ModelSQL): + 'Cron - Company' + __name__ = 'ir.cron-company.company' + _table = 'cron_company_rel' + cron = fields.Many2One('ir.cron', 'Cron', ondelete='CASCADE', + required=True, select=True) + company = fields.Many2One('company.company', 'Company', ondelete='CASCADE', + required=True, select=True) diff --git a/ir.xml b/ir.xml new file mode 100644 index 0000000000..de5ef43c60 --- /dev/null +++ b/ir.xml @@ -0,0 +1,56 @@ + + + + + + ir.sequence + + sequence_form + + + + ir.sequence + + sequence_tree + + + + User in company + + + + + + + + + + + + + + User in company + + + + + + + + + + + + + + ir.cron + + cron_form + + + diff --git a/party.py b/party.py index 06694837a7..8fb8d53d2e 100644 --- a/party.py +++ b/party.py @@ -5,6 +5,7 @@ from trytond.pool import PoolMeta, Pool from trytond.tools.multivalue import migrate_property from trytond.transaction import Transaction +from .company import CompanyReport from .model import CompanyMultiValueMixin, CompanyValueMixin __all__ = ['Configuration', 'PartyConfigurationLang', 'Party', 'PartyLang', @@ -110,3 +111,12 @@ class ContactMechanism(CompanyMultiValueMixin, metaclass=PoolMeta): for address in company.party.addresses: if address.country: yield address.country.code + + +class LetterReport(CompanyReport): + __name__ = 'party.letter' + + @classmethod + def execute(cls, ids, data): + with Transaction().set_context(address_with_party=True): + return super(LetterReport, cls).execute(ids, data) diff --git a/company.py b/res.py similarity index 55% rename from company.py rename to res.py index 4c2c6fb227..ce844d8dec 100644 --- a/company.py +++ b/res.py @@ -2,95 +2,10 @@ # this repository contains the full copyright notices and license terms. import copy -from trytond.model import ModelView, ModelSQL, fields, tree -from trytond.wizard import Wizard, StateView, Button, StateTransition -from trytond.report import Report -from trytond.pyson import Eval, If +from trytond.model import ModelSQL, fields +from trytond.pool import PoolMeta, Pool +from trytond.pyson import Eval from trytond.transaction import Transaction -from trytond.pool import Pool, PoolMeta - -try: - import pytz - TIMEZONES = [(x, x) for x in pytz.common_timezones] -except ImportError: - TIMEZONES = [] -TIMEZONES += [(None, '')] - -Transaction.cache_keys.update({'company', 'employee'}) - -__all__ = ['Company', 'Employee', 'UserEmployee', 'User', - 'Sequence', 'SequenceStrict', 'Date', 'CompanyConfigStart', - 'CompanyConfig', 'CompanyReport', 'LetterReport', 'Rule'] - - -class Company(tree(), 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( - 'Footer', help="The text to display on report footers.") - currency = fields.Many2One('currency.currency', 'Currency', required=True, - help="The main currency for the company.") - timezone = fields.Selection(TIMEZONES, 'Timezone', translate=False, - help="Used to compute the today date.") - employees = fields.One2Many('company.employee', 'company', 'Employees', - help="Add employees to the company.") - - def get_rec_name(self, name): - return self.party.rec_name - - @classmethod - def search_rec_name(cls, name, clause): - return [('party.rec_name',) + tuple(clause[1:])] - - @classmethod - def write(cls, companies, values, *args): - super(Company, cls).write(companies, values, *args) - # Restart the cache on the domain_get method - Pool().get('ir.rule')._domain_get_cache.clear() - - -class Employee(ModelSQL, ModelView): - 'Employee' - __name__ = 'company.employee' - party = fields.Many2One('party.party', 'Party', required=True, - help="The party which represents the employee.") - company = fields.Many2One('company.company', 'Company', required=True, - help="The company to which the employee belongs.") - start_date = fields.Date('Start Date', - domain=[If((Eval('start_date')) & (Eval('end_date')), - ('start_date', '<=', Eval('end_date')), - (), - ) - ], - depends=['end_date'], - help="When the employee joins the company.") - end_date = fields.Date('End Date', - domain=[If((Eval('start_date')) & (Eval('end_date')), - ('end_date', '>=', Eval('start_date')), - (), - ) - ], - depends=['start_date'], - help="When the employee leaves the company.") - - @staticmethod - def default_company(): - return Transaction().context.get('company') - - def get_rec_name(self, name): - return self.party.rec_name - - @classmethod - def search_rec_name(cls, name, clause): - return [('party.rec_name',) + tuple(clause[1:])] class UserEmployee(ModelSQL): @@ -284,104 +199,3 @@ class User(metaclass=PoolMeta): super(User, cls).write(*args) # Restart the cache on the domain_get method Rule._domain_get_cache.clear() - - -class Sequence(metaclass=PoolMeta): - __name__ = 'ir.sequence' - company = fields.Many2One('company.company', 'Company', - domain=[ - ('id', If(Eval('context', {}).contains('company'), '=', '!='), - Eval('context', {}).get('company', -1)), - ], help="Restrict the sequence usage to the company.") - - @classmethod - def __setup__(cls): - super(Sequence, cls).__setup__() - cls._order.insert(0, ('company', 'ASC')) - - @staticmethod - def default_company(): - return Transaction().context.get('company') - - -class SequenceStrict(Sequence): - __name__ = 'ir.sequence.strict' - - -class Date(metaclass=PoolMeta): - __name__ = 'ir.date' - - @classmethod - def today(cls, timezone=None): - pool = Pool() - Company = pool.get('company.company') - company_id = Transaction().context.get('company') - if timezone is None and company_id: - company = Company(company_id) - if company.timezone: - timezone = pytz.timezone(company.timezone) - return super(Date, cls).today(timezone=timezone) - - -class CompanyConfigStart(ModelView): - 'Company Config' - __name__ = 'company.company.config.start' - - -class CompanyConfig(Wizard): - 'Configure Company' - __name__ = 'company.company.config' - start = StateView('company.company.config.start', - 'company.company_config_start_view_form', [ - Button('Cancel', 'end', 'tryton-cancel'), - Button('OK', 'company', 'tryton-ok', True), - ]) - company = StateView('company.company', - 'company.company_view_form', [ - Button('Cancel', 'end', 'tryton-cancel'), - Button('Add', 'add', 'tryton-ok', True), - ]) - add = StateTransition() - - def transition_add(self): - User = Pool().get('res.user') - - self.company.save() - users = User.search([ - ('main_company', '=', None), - ]) - User.write(users, { - 'main_company': self.company.id, - 'company': self.company.id, - }) - return 'end' - - -class CompanyReport(Report): - - @classmethod - def get_context(cls, records, data): - report_context = super(CompanyReport, cls).get_context(records, data) - report_context['company'] = report_context['user'].company - return report_context - - -class LetterReport(CompanyReport): - __name__ = 'party.letter' - - @classmethod - def execute(cls, ids, data): - with Transaction().set_context(address_with_party=True): - return super(LetterReport, cls).execute(ids, data) - - -class Rule(metaclass=PoolMeta): - __name__ = 'ir.rule' - - @classmethod - def _get_cache_key(cls): - key = super(Rule, cls)._get_cache_key() - # XXX Use company from context instead of browse to prevent infinite - # loop, but the cache is cleared when User is written. - return key + (Transaction().context.get('company'), - Transaction().context.get('employee')) diff --git a/tryton.cfg b/tryton.cfg index 7b6b04f7d7..f50b88fadb 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -7,4 +7,4 @@ depends: res xml: company.xml - cron.xml + ir.xml