502 lines
18 KiB
Python
502 lines
18 KiB
Python
# 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 datetime as dt
|
|
import unittest
|
|
from collections import defaultdict
|
|
from contextlib import contextmanager
|
|
from unittest.mock import patch
|
|
|
|
from trytond.model import ModelStorage, ModelView
|
|
from trytond.modules.company.model import CompanyMultiValueMixin
|
|
from trytond.modules.currency.tests import add_currency_rate, create_currency
|
|
from trytond.modules.party.tests import (
|
|
PartyCheckEraseMixin, PartyCheckReplaceMixin)
|
|
from trytond.pool import Pool, isregisteredby
|
|
from trytond.pyson import Eval, PYSONEncoder
|
|
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
|
from trytond.tools import timezone as tz
|
|
from trytond.transaction import Transaction
|
|
|
|
|
|
def create_company(name='Dunder Mifflin', currency=None):
|
|
pool = Pool()
|
|
Party = pool.get('party.party')
|
|
Company = pool.get('company.company')
|
|
|
|
if currency is None:
|
|
currency = create_currency('usd')
|
|
add_currency_rate(currency, 1)
|
|
|
|
party, = Party.create([{
|
|
'name': name,
|
|
'addresses': [('create', [{}])],
|
|
}])
|
|
company = Company(party=party, currency=currency)
|
|
company.save()
|
|
return company
|
|
|
|
|
|
def create_employee(company, name="Pam Beesly"):
|
|
pool = Pool()
|
|
Party = pool.get('party.party')
|
|
Employee = pool.get('company.employee')
|
|
|
|
party, = Party.create([{
|
|
'name': name,
|
|
'addresses': [('create', [{}])],
|
|
}])
|
|
employee = Employee(party=party, company=company)
|
|
employee.save()
|
|
return employee
|
|
|
|
|
|
@contextmanager
|
|
def set_company(company):
|
|
pool = Pool()
|
|
User = pool.get('res.user')
|
|
User.write([User(Transaction().user)], {
|
|
'companies': [('add', [company.id])],
|
|
'company': company.id,
|
|
})
|
|
with Transaction().set_context(User.get_preferences(context_only=True)):
|
|
yield
|
|
|
|
|
|
class PartyCompanyCheckEraseMixin(PartyCheckEraseMixin):
|
|
|
|
def setup_check_erase_party(self):
|
|
create_company()
|
|
return super().setup_check_erase_party()
|
|
|
|
|
|
class CompanyTestMixin:
|
|
|
|
@with_transaction()
|
|
def test_company_multivalue_context(self):
|
|
"Test context of company multivalue target"
|
|
pool = Pool()
|
|
Company = pool.get('company.company')
|
|
for mname, model in pool.iterobject():
|
|
if (not isregisteredby(model, self.module)
|
|
or issubclass(model, Company)):
|
|
continue
|
|
company = None
|
|
for fname, field in model._fields.items():
|
|
if (field._type == 'many2one'
|
|
and issubclass(field.get_target(), Company)):
|
|
company = fname
|
|
break
|
|
else:
|
|
continue
|
|
for fname, field in model._fields.items():
|
|
if not hasattr(field, 'get_target'):
|
|
continue
|
|
Target = field.get_target()
|
|
if not issubclass(Target, CompanyMultiValueMixin):
|
|
continue
|
|
if company in model._fields:
|
|
self.assertIn(
|
|
'company', list(field.context.keys()),
|
|
msg="Missing '%s' value as company "
|
|
'in "%s"."%s" context' % (
|
|
company, mname, fname))
|
|
|
|
@property
|
|
def _skip_company_rule(self):
|
|
"""Return a set of couple field name and model name
|
|
for which no company rules are needed."""
|
|
return {
|
|
('company.employee', 'company'),
|
|
('res.user', 'company'),
|
|
}
|
|
|
|
@with_transaction()
|
|
def test_company_rule(self):
|
|
"Test missing company rule"
|
|
pool = Pool()
|
|
Rule = pool.get('ir.rule')
|
|
Company = pool.get('company.company')
|
|
|
|
to_check = defaultdict(set)
|
|
for mname, model in pool.iterobject():
|
|
if (not isregisteredby(model, self.module)
|
|
or model.__access__
|
|
or not (issubclass(model, ModelView)
|
|
and issubclass(model, ModelStorage))):
|
|
continue
|
|
for fname, field in model._fields.items():
|
|
if (mname, fname) in self._skip_company_rule:
|
|
continue
|
|
if (field._type == 'many2one'
|
|
and issubclass(field.get_target(), Company)):
|
|
to_check[fname].add(mname)
|
|
|
|
for fname, models in to_check.items():
|
|
rules = Rule.search([
|
|
('rule_group', 'where', [
|
|
('model', 'in', list(models)),
|
|
('global_p', '=', True),
|
|
('perm_read', '=', True),
|
|
]),
|
|
('domain', '=', PYSONEncoder(sort_keys=True).encode(
|
|
[(fname, 'in', Eval('companies', []))])),
|
|
])
|
|
with_rules = {r.rule_group.model for r in rules}
|
|
self.assertGreaterEqual(with_rules, models,
|
|
msg='Models %(models)s are missing a global rule '
|
|
'for field "%(field)s"' % {
|
|
'models': ', '.join(
|
|
f'"{m}"' for m in (models - with_rules)),
|
|
'field': fname,
|
|
})
|
|
|
|
|
|
class CompanyTestCase(
|
|
PartyCompanyCheckEraseMixin, PartyCheckReplaceMixin, CompanyTestMixin,
|
|
ModuleTestCase):
|
|
'Test Company module'
|
|
module = 'company'
|
|
|
|
@with_transaction()
|
|
def test_company(self):
|
|
'Create company'
|
|
company = create_company()
|
|
self.assertTrue(company)
|
|
|
|
@with_transaction()
|
|
def test_employe(self):
|
|
'Create employee'
|
|
pool = Pool()
|
|
Party = pool.get('party.party')
|
|
Employee = pool.get('company.employee')
|
|
company1 = create_company()
|
|
|
|
party, = Party.create([{
|
|
'name': 'Pam Beesly',
|
|
}])
|
|
employee, = Employee.create([{
|
|
'party': party.id,
|
|
'company': company1.id,
|
|
}])
|
|
self.assertTrue(employee)
|
|
|
|
@with_transaction()
|
|
def test_user_company(self):
|
|
'Test user company'
|
|
pool = Pool()
|
|
User = pool.get('res.user')
|
|
transaction = Transaction()
|
|
|
|
company1 = create_company()
|
|
company2 = create_company('Michael Scott Paper Company',
|
|
currency=company1.currency)
|
|
company2.save()
|
|
company3 = create_company()
|
|
|
|
user1, user2 = User.create([{
|
|
'name': 'Jim Halper',
|
|
'login': 'jim',
|
|
'companies': [('add', [company1.id, company2.id])],
|
|
'company': company1.id,
|
|
}, {
|
|
'name': 'Pam Beesly',
|
|
'login': 'pam',
|
|
'companies': [('add', [company2.id])],
|
|
'company': company2.id,
|
|
}])
|
|
self.assertTrue(user1)
|
|
|
|
with transaction.set_user(user1.id):
|
|
user1, user2 = User.browse([user1.id, user2.id])
|
|
self.assertEqual(user1.company, company1)
|
|
self.assertEqual(user2.company, company2)
|
|
|
|
with transaction.set_context({'company': company2.id}):
|
|
user1, user2 = User.browse([user1.id, user2.id])
|
|
self.assertEqual(user1.company, company2)
|
|
self.assertEqual(user2.company, company2)
|
|
|
|
with transaction.set_context({'company': None}):
|
|
user1, user2 = User.browse([user1.id, user2.id])
|
|
self.assertEqual(user1.company, None)
|
|
self.assertEqual(user2.company, company2)
|
|
|
|
with transaction.set_context(company=company3.id):
|
|
user1, user2 = User.browse([user1.id, user2.id])
|
|
self.assertEqual(user1.company, None)
|
|
self.assertEqual(user2.company, company2)
|
|
|
|
@with_transaction()
|
|
def test_user_root_company(self):
|
|
"Test root user company"
|
|
pool = Pool()
|
|
User = pool.get('res.user')
|
|
transaction = Transaction()
|
|
company = create_company()
|
|
root = User(0)
|
|
root.company = None
|
|
root.companies = None
|
|
root.save()
|
|
|
|
with transaction.set_user(0):
|
|
with Transaction().set_context(company=company.id):
|
|
root = User(0)
|
|
self.assertEqual(root.company, company)
|
|
|
|
@with_transaction()
|
|
def test_user_employee(self):
|
|
"Test user employee"
|
|
pool = Pool()
|
|
User = pool.get('res.user')
|
|
transaction = Transaction()
|
|
|
|
company = create_company()
|
|
|
|
employee1 = create_employee(company, "Jim Halper")
|
|
employee2 = create_employee(company, "Pam Bessly")
|
|
employee3 = create_employee(company, "Michael Scott")
|
|
|
|
user1, user2 = User.create([{
|
|
'name': "Jim Halper",
|
|
'login': "jim",
|
|
'companies': [('add', [company.id])],
|
|
'company': company.id,
|
|
'employees': [('add', [employee1.id, employee2.id])],
|
|
'employee': employee1.id,
|
|
}, {
|
|
'name': "Pam Beesly",
|
|
'login': "pam",
|
|
'companies': [('add', [company.id])],
|
|
'company': company.id,
|
|
'employees': [('add', [employee2.id])],
|
|
'employee': employee2.id,
|
|
}])
|
|
|
|
with transaction.set_user(user1.id):
|
|
user1, user2 = User.browse([user1.id, user2.id])
|
|
self.assertEqual(user1.employee, employee1)
|
|
self.assertEqual(user2.employee, employee2)
|
|
|
|
with transaction.set_context(employee=employee2.id):
|
|
user1, user2 = User.browse([user1.id, user2.id])
|
|
self.assertEqual(user1.employee, employee2)
|
|
self.assertEqual(user2.employee, employee2)
|
|
|
|
with transaction.set_context(employee=None):
|
|
user1, user2 = User.browse([user1.id, user2.id])
|
|
self.assertEqual(user1.employee, None)
|
|
self.assertEqual(user2.employee, employee2)
|
|
|
|
with transaction.set_context(employee=employee3.id):
|
|
user1, user2 = User.browse([user1.id, user2.id])
|
|
self.assertEqual(user1.employee, None)
|
|
self.assertEqual(user2.employee, employee2)
|
|
|
|
@with_transaction()
|
|
def test_user_root_employee(self):
|
|
"Test root user employee"
|
|
pool = Pool()
|
|
User = pool.get('res.user')
|
|
transaction = Transaction()
|
|
company = create_company()
|
|
employee = create_employee(company, "Jim Halper")
|
|
root = User(0)
|
|
root.employee = None
|
|
root.employees = None
|
|
root.save()
|
|
|
|
with transaction.set_user(0):
|
|
with Transaction().set_context(employee=employee.id):
|
|
root = User(0)
|
|
self.assertEqual(root.employee, employee)
|
|
|
|
@with_transaction()
|
|
def test_company_header(self):
|
|
"Test company header"
|
|
company = create_company()
|
|
company.party.email = 'company@example.com'
|
|
company.party.save()
|
|
company.header = "${name} - ${email}"
|
|
company.save()
|
|
|
|
self.assertEqual(
|
|
company.header_used, "Dunder Mifflin - company@example.com")
|
|
|
|
@with_transaction()
|
|
def test_company_footer(self):
|
|
"Test company footer"
|
|
company = create_company()
|
|
company.party.email = 'company@example.com'
|
|
company.party.save()
|
|
company.footer = "${name} - ${email}"
|
|
company.save()
|
|
|
|
self.assertEqual(
|
|
company.footer_used, "Dunder Mifflin - company@example.com")
|
|
|
|
@with_transaction()
|
|
def test_employee_active_no_dates(self):
|
|
"Test employee active with dates"
|
|
pool = Pool()
|
|
Employee = pool.get('company.employee')
|
|
|
|
company = create_company()
|
|
employee = create_employee(company, "Jim Halper")
|
|
|
|
self.assertEqual(employee.active, True)
|
|
self.assertEqual(Employee.search([
|
|
('active', '=', True),
|
|
]), [employee])
|
|
self.assertEqual(Employee.search([
|
|
('active', '!=', False),
|
|
]), [employee])
|
|
self.assertEqual(Employee.search([
|
|
('active', '=', False),
|
|
]), [])
|
|
self.assertEqual(Employee.search([
|
|
('active', '!=', True),
|
|
]), [])
|
|
|
|
@with_transaction()
|
|
def test_employee_active_start_date(self):
|
|
"Test employee active with start date"
|
|
pool = Pool()
|
|
Employee = pool.get('company.employee')
|
|
|
|
company = create_company()
|
|
employee = create_employee(company, "Jim Halper")
|
|
employee.start_date = dt.date.today()
|
|
employee.save()
|
|
|
|
with Transaction().set_context(date=employee.start_date):
|
|
self.assertEqual(Employee(employee).active, True)
|
|
self.assertEqual(Employee.search([
|
|
('active', '=', True),
|
|
]), [employee])
|
|
with Transaction().set_context(
|
|
date=employee.start_date - dt.timedelta(days=1)):
|
|
self.assertEqual(Employee(employee).active, False)
|
|
self.assertEqual(Employee.search([
|
|
('active', '=', True),
|
|
]), [])
|
|
with Transaction().set_context(
|
|
date=employee.start_date + dt.timedelta(days=1)):
|
|
self.assertEqual(Employee(employee).active, True)
|
|
self.assertEqual(Employee.search([
|
|
('active', '=', True),
|
|
]), [employee])
|
|
|
|
@with_transaction()
|
|
def test_employee_active_end_date(self):
|
|
"Test employee active with end date"
|
|
pool = Pool()
|
|
Employee = pool.get('company.employee')
|
|
|
|
company = create_company()
|
|
employee = create_employee(company, "Jim Halper")
|
|
employee.end_date = dt.date.today()
|
|
employee.save()
|
|
|
|
with Transaction().set_context(date=employee.end_date):
|
|
self.assertEqual(Employee(employee).active, True)
|
|
self.assertEqual(Employee.search([
|
|
('active', '=', True),
|
|
]), [employee])
|
|
with Transaction().set_context(
|
|
date=employee.end_date - dt.timedelta(days=1)):
|
|
self.assertEqual(Employee(employee).active, True)
|
|
self.assertEqual(Employee.search([
|
|
('active', '=', True),
|
|
]), [employee])
|
|
with Transaction().set_context(
|
|
date=employee.end_date + dt.timedelta(days=1)):
|
|
self.assertEqual(Employee(employee).active, False)
|
|
self.assertEqual(Employee.search([
|
|
('active', '=', True),
|
|
]), [])
|
|
|
|
@unittest.skipUnless(
|
|
'CET' in tz.available_timezones(), "missing CET timezone")
|
|
@with_transaction()
|
|
def test_today(self):
|
|
"Test today is using the timezone of the contextual company"
|
|
pool = Pool()
|
|
Date = pool.get('ir.date')
|
|
|
|
company = create_company()
|
|
company.timezone = 'CET'
|
|
company.save()
|
|
|
|
with patch('datetime.datetime') as datetime:
|
|
with Transaction().set_context(company=company.id):
|
|
Date.today()
|
|
|
|
datetime.now.assert_called_with(tz.ZoneInfo('CET'))
|
|
|
|
@with_transaction()
|
|
def test_company_tax_identifier(self):
|
|
"Test company tax identifier"
|
|
pool = Pool()
|
|
Country = pool.get('country.country')
|
|
Organization = pool.get('country.organization')
|
|
Identifier = pool.get('party.identifier')
|
|
TaxIdentifier = pool.get('company.company.tax_identifier')
|
|
|
|
company = create_company()
|
|
|
|
fr_vat = Identifier(
|
|
party=company.party, type='fr_vat', code="FR23334175221")
|
|
fr_vat.save()
|
|
be_vat = Identifier(
|
|
party=company.party, type='be_vat', code="BE403019261")
|
|
be_vat.save()
|
|
|
|
belgium = Country(name="Belgium")
|
|
belgium.save()
|
|
france = Country(name="France")
|
|
france.save()
|
|
germany = Country(name="Germany")
|
|
germany.save()
|
|
switzerland = Country(name="Switzerland")
|
|
switzerland.save()
|
|
europe = Organization(
|
|
name="Europe",
|
|
members=[
|
|
{'country': belgium},
|
|
{'country': france},
|
|
{'country': germany},
|
|
])
|
|
europe.save()
|
|
|
|
TaxIdentifier.create([{
|
|
'company': company,
|
|
'country': france,
|
|
'tax_identifier': fr_vat,
|
|
}, {
|
|
'company': company,
|
|
'country': belgium,
|
|
'tax_identifier': be_vat,
|
|
}, {
|
|
'company': company,
|
|
'organization': europe,
|
|
'tax_identifier': be_vat,
|
|
}])
|
|
|
|
self.assertEqual(company.party.tax_identifier, fr_vat)
|
|
self.assertEqual(company.get_tax_identifier({
|
|
'country': france.id,
|
|
}), fr_vat)
|
|
self.assertEqual(company.get_tax_identifier({
|
|
'country': belgium.id,
|
|
}), be_vat)
|
|
self.assertEqual(company.get_tax_identifier({
|
|
'country': germany.id,
|
|
}), be_vat)
|
|
self.assertEqual(company.get_tax_identifier({
|
|
'country': switzerland,
|
|
}), fr_vat)
|
|
|
|
|
|
del ModuleTestCase
|