mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 00:52:07 +02:00
19.0 vanilla
This commit is contained in:
parent
d1963a3c3a
commit
2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions
|
|
@ -1,3 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import test_analytic_account
|
||||
from . import test_analytic_dynamic_update
|
||||
from . import test_plan_operations
|
||||
from . import test_analytic_mixin
|
||||
|
|
|
|||
63
odoo-bringout-oca-ocb-analytic/analytic/tests/common.py
Normal file
63
odoo-bringout-oca-ocb-analytic/analytic/tests/common.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
from odoo.addons.base.tests.common import BaseCommon
|
||||
from odoo.tests.common import new_test_user
|
||||
|
||||
|
||||
class AnalyticCommon(BaseCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
cls.analytic_plan_offset = len(cls.env['account.analytic.plan'].get_relevant_plans())
|
||||
cls.analytic_plan_1, cls.analytic_plan_2 = cls.env['account.analytic.plan'].create([
|
||||
{
|
||||
'name': 'Plan 1',
|
||||
'default_applicability': 'unavailable',
|
||||
},
|
||||
{
|
||||
'name': 'Plan 2',
|
||||
}
|
||||
])
|
||||
cls.analytic_plan_child = cls.env['account.analytic.plan'].create({
|
||||
'name': 'Plan Child',
|
||||
'parent_id': cls.analytic_plan_1.id,
|
||||
})
|
||||
|
||||
cls.analytic_account_1, cls.analytic_account_2, cls.analytic_account_3, cls.analytic_account_4 = cls.env['account.analytic.account'].create([
|
||||
{'name': 'Account 1', 'plan_id': cls.analytic_plan_1.id, 'company_id': False},
|
||||
{'name': 'Account 2', 'plan_id': cls.analytic_plan_child.id, 'company_id': False},
|
||||
{'name': 'Account 3', 'plan_id': cls.analytic_plan_2.id, 'company_id': False},
|
||||
{'name': 'Account 4', 'plan_id': cls.analytic_plan_2.id, 'company_id': False}
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def setup_independent_company(cls, **kwargs):
|
||||
# OVERRIDE
|
||||
company = super().setup_independent_company(**kwargs)
|
||||
if not company:
|
||||
company = cls._create_company(name='analytic', **kwargs)
|
||||
return company
|
||||
|
||||
@classmethod
|
||||
def get_default_groups(cls):
|
||||
groups = super().get_default_groups()
|
||||
return groups + cls.env.ref('analytic.group_analytic_accounting')
|
||||
|
||||
@classmethod
|
||||
def setup_independent_user(cls):
|
||||
# Add group_system to be able to create companies notably in the class setup
|
||||
default_groups = cls.env.ref('base.group_system') + cls.get_default_groups()
|
||||
# Removes access rights linked to timesheet
|
||||
core_group_ids = (cls.env.ref("hr_timesheet.group_hr_timesheet_user", raise_if_not_found=False) or cls.env['res.groups']) | (cls.env.ref("helpdesk.group_helpdesk_user", raise_if_not_found=False) or cls.env['res.groups'])
|
||||
problematic_group_ids = default_groups.filtered(lambda g: g.all_implied_ids & core_group_ids)
|
||||
if problematic_group_ids:
|
||||
default_groups -= problematic_group_ids
|
||||
return new_test_user(
|
||||
cls.env,
|
||||
name='The anal(ytic) expert!',
|
||||
login='analytic',
|
||||
password='analytic',
|
||||
email='analyticman@test.com',
|
||||
group_ids=default_groups.ids,
|
||||
company_id=cls.env.company.id,
|
||||
)
|
||||
|
|
@ -1,92 +1,59 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo.tests import tagged
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.tests import Form, tagged
|
||||
from odoo import Command
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.exceptions import RedirectWarning
|
||||
|
||||
from odoo.addons.analytic.tests.common import AnalyticCommon
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAnalyticAccount(TransactionCase):
|
||||
class TestAnalyticAccount(AnalyticCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
cls.analytic_plan_1 = cls.env['account.analytic.plan'].create({
|
||||
'name': 'Plan 1',
|
||||
'default_applicability': 'unavailable',
|
||||
'company_id': False,
|
||||
})
|
||||
cls.analytic_plan_child = cls.env['account.analytic.plan'].create({
|
||||
'name': 'Plan Child',
|
||||
'parent_id': cls.analytic_plan_1.id,
|
||||
'company_id': False,
|
||||
})
|
||||
cls.analytic_plan_2 = cls.env['account.analytic.plan'].create({
|
||||
'name': 'Plan 2',
|
||||
'company_id': False,
|
||||
})
|
||||
|
||||
# Create new user to avoid demo data.
|
||||
user = cls.env['res.users'].create({
|
||||
'name': 'The anal(ytic) expert!',
|
||||
'login': 'analytic',
|
||||
'password': 'analytic',
|
||||
'groups_id': [
|
||||
(6, 0, cls.env.user.groups_id.ids),
|
||||
(4, cls.env.ref('analytic.group_analytic_accounting').id),
|
||||
],
|
||||
})
|
||||
user.partner_id.email = 'analyticman@test.com'
|
||||
|
||||
# Shadow the current environment/cursor with one having the report user.
|
||||
# This is mandatory to test access rights.
|
||||
cls.env = cls.env(user=user)
|
||||
cls.cr = cls.env.cr
|
||||
|
||||
cls.company_data = cls.env['res.company'].create({
|
||||
'name': 'company_data',
|
||||
})
|
||||
cls.env.user.company_ids |= cls.company_data
|
||||
|
||||
user.write({
|
||||
'company_ids': [(6, 0, cls.company_data.ids)],
|
||||
'company_id': cls.company_data.id,
|
||||
})
|
||||
|
||||
cls.partner_a = cls.env['res.partner'].create({'name': 'partner_a', 'company_id': False})
|
||||
cls.partner_b = cls.env['res.partner'].create({'name': 'partner_b', 'company_id': False})
|
||||
|
||||
cls.analytic_account_1 = cls.env['account.analytic.account'].create({'name': 'Account 1', 'plan_id': cls.analytic_plan_1.id})
|
||||
cls.analytic_account_2 = cls.env['account.analytic.account'].create({'name': 'Account 2', 'plan_id': cls.analytic_plan_child.id})
|
||||
cls.analytic_account_3 = cls.env['account.analytic.account'].create({'name': 'Account 3', 'plan_id': cls.analytic_plan_2.id})
|
||||
cls.distribution_1, cls.distribution_2 = cls.env['account.analytic.distribution.model'].create([
|
||||
{
|
||||
'partner_id': cls.partner_a.id,
|
||||
'analytic_distribution': {cls.analytic_account_3.id: 100}
|
||||
},
|
||||
{
|
||||
'partner_id': cls.partner_b.id,
|
||||
'analytic_distribution': {cls.analytic_account_2.id: 100}
|
||||
},
|
||||
])
|
||||
cls.company_b_branch = cls.env['res.company'].create({'name': "B Branch", 'parent_id': cls.company.id})
|
||||
|
||||
cls.distribution_1 = cls.env['account.analytic.distribution.model'].create({
|
||||
'partner_id': cls.partner_a.id,
|
||||
'analytic_distribution': {cls.analytic_account_3.id: 100}
|
||||
})
|
||||
|
||||
cls.distribution_2 = cls.env['account.analytic.distribution.model'].create({
|
||||
'partner_id': cls.partner_b.id,
|
||||
'analytic_distribution': {cls.analytic_account_2.id: 100}
|
||||
})
|
||||
def test_aggregates(self):
|
||||
# debit and credit are hidden by the group when account is installed
|
||||
fields_to_agg = ['balance', 'debit', 'credit'] if self.env.user.has_group('account.group_account_readonly') else ['balance']
|
||||
model = self.env['account.analytic.account']
|
||||
self.assertEqual(
|
||||
model.fields_get(fields_to_agg, ['aggregator']),
|
||||
dict.fromkeys(fields_to_agg, {'aggregator': 'sum'}),
|
||||
f"Fields {', '.join(f for f in fields_to_agg)} must be flagged as aggregatable.",
|
||||
)
|
||||
|
||||
def test_get_plans_without_options(self):
|
||||
""" Test that the plans with the good appliability are returned without if no options are given """
|
||||
kwargs = {}
|
||||
plans_json = self.env['account.analytic.plan'].get_relevant_plans(**kwargs)
|
||||
self.assertEqual(1, len(plans_json), "Only the Default plan should be available")
|
||||
self.assertEqual(1, len(plans_json) - self.analytic_plan_offset, "Only the Default plan and the demo data plans should be available")
|
||||
|
||||
self.analytic_plan_1.write({'default_applicability': 'mandatory'})
|
||||
plans_json = self.env['account.analytic.plan'].get_relevant_plans(**kwargs)
|
||||
self.assertEqual(2, len(plans_json), "All root plans should be available")
|
||||
self.assertEqual(2, len(plans_json) - self.analytic_plan_offset, "All root plans should be available")
|
||||
|
||||
def test_get_plans_with_option(self):
|
||||
""" Test the plans returned with applicability rules and options """
|
||||
kwargs = {'business_domain': 'general'}
|
||||
plans_json = self.env['account.analytic.plan'].get_relevant_plans(**kwargs)
|
||||
self.assertEqual(1, len(plans_json), "Only the Default plan should be available")
|
||||
self.assertEqual(1, len(plans_json) - self.analytic_plan_offset, "Only the Default plan and the demo data plans should be available")
|
||||
|
||||
applicability = self.env['account.analytic.applicability'].create({
|
||||
'business_domain': 'general',
|
||||
|
|
@ -94,20 +61,20 @@ class TestAnalyticAccount(TransactionCase):
|
|||
'applicability': 'mandatory'
|
||||
})
|
||||
plans_json = self.env['account.analytic.plan'].get_relevant_plans(**kwargs)
|
||||
self.assertEqual(2, len(plans_json), "All root plans should be available")
|
||||
self.assertEqual(2, len(plans_json) - self.analytic_plan_offset, "All root plans should be available")
|
||||
|
||||
self.analytic_plan_1.write({'default_applicability': 'mandatory'})
|
||||
applicability.write({'applicability': 'unavailable'})
|
||||
plans_json = self.env['account.analytic.plan'].get_relevant_plans(**kwargs)
|
||||
self.assertEqual(1, len(plans_json), "Plan 1 should be unavailable")
|
||||
self.assertEqual(1, len(plans_json) - self.analytic_plan_offset, "Plan 1 should be unavailable")
|
||||
|
||||
kwargs = {'business_domain': 'purchase_order'}
|
||||
plans_json = self.env['account.analytic.plan'].get_relevant_plans(**kwargs)
|
||||
self.assertEqual(2, len(plans_json), "Both plans should be available")
|
||||
self.assertEqual(2, len(plans_json) - self.analytic_plan_offset, "Both plans should be available")
|
||||
|
||||
kwargs = {'applicability': 'optional'}
|
||||
plans_json = self.env['account.analytic.plan'].get_relevant_plans(**kwargs)
|
||||
self.assertEqual(2, len(plans_json), "All root plans should be available")
|
||||
self.assertEqual(2, len(plans_json) - self.analytic_plan_offset, "All root plans should be available")
|
||||
|
||||
def test_analytic_distribution_model(self):
|
||||
""" Test the distribution returned from the distribution model """
|
||||
|
|
@ -115,12 +82,12 @@ class TestAnalyticAccount(TransactionCase):
|
|||
self.assertEqual(distribution_json, {}, "No distribution should be given")
|
||||
distribution_json = self.env['account.analytic.distribution.model']._get_distribution({
|
||||
"partner_id": self.partner_a.id,
|
||||
"company_id": self.company_data.id,
|
||||
"company_id": self.company.id,
|
||||
})
|
||||
self.assertEqual(distribution_json, {str(self.analytic_account_3.id): 100}, "Distribution 1 should be given")
|
||||
distribution_json = self.env['account.analytic.distribution.model']._get_distribution({
|
||||
"partner_id": self.partner_b.id,
|
||||
"company_id": self.company_data.id,
|
||||
"company_id": self.company.id,
|
||||
})
|
||||
self.assertEqual(distribution_json, {str(self.analytic_account_2.id): 100}, "Distribution 2 should be given")
|
||||
|
||||
|
|
@ -129,21 +96,21 @@ class TestAnalyticAccount(TransactionCase):
|
|||
distribution_3 = self.env['account.analytic.distribution.model'].create({
|
||||
'partner_id': self.partner_a.id,
|
||||
'analytic_distribution': {self.analytic_account_1.id: 100},
|
||||
'company_id': self.company_data.id,
|
||||
'company_id': self.company.id,
|
||||
})
|
||||
distribution_json = self.env['account.analytic.distribution.model']._get_distribution({})
|
||||
self.assertEqual(distribution_json, {}, "No distribution should be given")
|
||||
|
||||
distribution_json = self.env['account.analytic.distribution.model']._get_distribution({
|
||||
"partner_id": self.partner_a.id,
|
||||
"company_id": self.company_data.id,
|
||||
"company_id": self.company.id,
|
||||
})
|
||||
self.assertEqual(distribution_json, distribution_3.analytic_distribution,
|
||||
"Distribution 3 should be given, as the company is specified in the model")
|
||||
self.assertEqual(distribution_json, distribution_3.analytic_distribution | self.distribution_1.analytic_distribution,
|
||||
"Distribution 3 & 1 should be given, as the company and partner are specified in the models")
|
||||
|
||||
distribution_json = self.env['account.analytic.distribution.model']._get_distribution({
|
||||
"partner_id": self.partner_b.id,
|
||||
"company_id": self.company_data.id,
|
||||
"company_id": self.company.id,
|
||||
})
|
||||
self.assertEqual(distribution_json, {str(self.analytic_account_2.id): 100},
|
||||
"Distribution 2 should be given, for the partner")
|
||||
|
|
@ -157,15 +124,17 @@ class TestAnalyticAccount(TransactionCase):
|
|||
'partner_id': self.partner_a.id,
|
||||
'analytic_distribution': {self.analytic_account_1.id: 100, self.analytic_account_2.id: 100},
|
||||
'partner_category_id': partner_category.id,
|
||||
'sequence': 1,
|
||||
})
|
||||
|
||||
distribution_json = self.env['account.analytic.distribution.model']._get_distribution({
|
||||
"partner_id": self.partner_a.id,
|
||||
"company_id": self.company_data.id,
|
||||
"company_id": self.company.id,
|
||||
"partner_category_id": partner_category.ids,
|
||||
})
|
||||
self.assertEqual(distribution_json, distribution_4.analytic_distribution,
|
||||
"Distribution 4 should be given, as the partner_category_id is better than the company_id")
|
||||
|
||||
self.assertEqual(distribution_json, distribution_4.analytic_distribution | self.distribution_1.analytic_distribution,
|
||||
"Distribution 4 & 1 should be given based on sequence")
|
||||
|
||||
def test_analytic_plan_account_child(self):
|
||||
"""
|
||||
|
|
@ -174,49 +143,219 @@ class TestAnalyticAccount(TransactionCase):
|
|||
"""
|
||||
self.analytic_plan = self.env['account.analytic.plan'].create({
|
||||
'name': 'Parent Plan',
|
||||
'company_id': False,
|
||||
})
|
||||
self.analytic_sub_plan = self.env['account.analytic.plan'].create({
|
||||
'name': 'Sub Plan',
|
||||
'parent_id': self.analytic_plan.id,
|
||||
'company_id': False,
|
||||
})
|
||||
self.analytic_sub_sub_plan = self.env['account.analytic.plan'].create({
|
||||
'name': 'Sub Sub Plan',
|
||||
'parent_id': self.analytic_sub_plan.id,
|
||||
'company_id': False,
|
||||
})
|
||||
self.analytic_account_1 = self.env['account.analytic.account'].create({'name': 'Child Account', 'plan_id': self.analytic_sub_sub_plan.id})
|
||||
self.env['account.analytic.account'].create({'name': 'Account', 'plan_id': self.analytic_plan.id})
|
||||
self.env['account.analytic.account'].create({'name': 'Child Account', 'plan_id': self.analytic_sub_plan.id})
|
||||
self.env['account.analytic.account'].create({'name': 'Grand Child Account', 'plan_id': self.analytic_sub_sub_plan.id})
|
||||
plans_json = self.env['account.analytic.plan'].get_relevant_plans()
|
||||
self.assertEqual(2, len(plans_json),
|
||||
self.assertEqual(2, len(plans_json) - self.analytic_plan_offset,
|
||||
"The parent plan should be available even if the analytic account is set on child of third generation")
|
||||
|
||||
def test_analytic_plan_account_parent(self):
|
||||
"""
|
||||
Check that when assigning an analytic plan as the parent to a child analytic plan,
|
||||
both plans must belong to the same company.
|
||||
"""
|
||||
company_1, company_2 = self.env['res.company'].create([
|
||||
{'name': 'company_1'},
|
||||
{'name': 'company_2'}
|
||||
])
|
||||
self.env.user.company_ids |= company_1 + company_2
|
||||
parent_analytic_plan_1, parent_analytic_plan_2 = self.env['account.analytic.plan'].create([{
|
||||
'name': 'Parent Plan 1',
|
||||
'company_id': company_1.id,
|
||||
}, {
|
||||
'name': 'Parent Plan 2',
|
||||
'company_id': company_1.id,
|
||||
}])
|
||||
child_analytic_plan_1 = self.env['account.analytic.plan'].create({
|
||||
'name': 'Child Plan 1',
|
||||
'company_id': company_1.id,
|
||||
'parent_id': parent_analytic_plan_1.id,
|
||||
def test_all_account_count_with_subplans(self):
|
||||
self.analytic_plan = self.env['account.analytic.plan'].create({
|
||||
'name': 'Parent Plan',
|
||||
})
|
||||
self.assertEqual(child_analytic_plan_1.parent_id.id, parent_analytic_plan_1.id)
|
||||
with self.assertRaises(UserError):
|
||||
self.env['account.analytic.plan'].create({
|
||||
'name': 'Chils Plan 2',
|
||||
'company_id': company_2.id,
|
||||
'parent_id': parent_analytic_plan_2.id,
|
||||
})
|
||||
self.analytic_sub_plan = self.env['account.analytic.plan'].create({
|
||||
'name': 'Sub Plan',
|
||||
'parent_id': self.analytic_plan.id,
|
||||
})
|
||||
self.analytic_sub_sub_plan = self.env['account.analytic.plan'].create({
|
||||
'name': 'Sub Sub Plan',
|
||||
'parent_id': self.analytic_sub_plan.id,
|
||||
})
|
||||
|
||||
self.env['account.analytic.account'].create([
|
||||
{'name': 'Account', 'plan_id': self.analytic_plan.id},
|
||||
{'name': 'Child Account', 'plan_id': self.analytic_sub_plan.id},
|
||||
{'name': 'Grand Child Account', 'plan_id': self.analytic_sub_sub_plan.id}
|
||||
])
|
||||
|
||||
expected_values = {self.analytic_plan: 3, self.analytic_sub_plan: 2, self.analytic_sub_sub_plan: 1}
|
||||
for plan, expected_value in expected_values.items():
|
||||
with self.subTest(plan=plan.name, expected_count=expected_value):
|
||||
with Form(plan) as plan_form:
|
||||
self.assertEqual(plan_form.record.all_account_count, expected_value)
|
||||
|
||||
def test_create_analytic_with_minimal_access(self):
|
||||
analyst_partner = self.env['res.partner'].create({'name': 'analyst'})
|
||||
analyst = self.env['res.users'].create({
|
||||
'login': 'analyst',
|
||||
'group_ids': [Command.set(self.env.ref('analytic.group_analytic_accounting').ids)],
|
||||
'partner_id': analyst_partner.id
|
||||
})
|
||||
plan = self.env['account.analytic.plan'].with_user(analyst).create({'name': 'test plan'})
|
||||
self.assertEqual(plan.create_uid, analyst)
|
||||
|
||||
def test_analytic_account_branches(self):
|
||||
"""
|
||||
Test that an analytic account defined in a parent company is accessible in its branches (children)
|
||||
"""
|
||||
# timesheet adds a rule to forcer a project_id; account overrides it
|
||||
timesheet_user = self.env.ref('hr_timesheet.group_hr_timesheet_user', raise_if_not_found=False)
|
||||
account_user = self.env.ref('account.analytic.model_account_analytic_line', raise_if_not_found=False)
|
||||
if timesheet_user and not account_user:
|
||||
self.skipTest("`hr_timesheet` overrides analytic rights. Without `account` the test would crash")
|
||||
|
||||
self.analytic_account_1.company_id = self.company
|
||||
self.env['account.analytic.line'].create({
|
||||
'name': 'company specific account',
|
||||
'account_id': self.analytic_account_1.id,
|
||||
'amount': 100,
|
||||
'company_id': self.company_b_branch.id,
|
||||
})
|
||||
|
||||
def test_change_plan(self):
|
||||
"""Changing the plan of an account updates columns of the analytic lines."""
|
||||
plan_1_col = self.analytic_plan_1._column_name()
|
||||
plan_2_col = self.analytic_plan_2._column_name()
|
||||
self.assertNotEqual(plan_1_col, plan_2_col)
|
||||
line = self.env['account.analytic.line'].create({
|
||||
'name': 'test',
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
})
|
||||
self.analytic_account_1.plan_id = self.analytic_plan_2
|
||||
self.assertRecordValues(line, [{
|
||||
plan_1_col: False,
|
||||
plan_2_col: self.analytic_account_1.id,
|
||||
}])
|
||||
|
||||
def test_change_plan_conflict(self):
|
||||
"""Don't allow changing the plan if some lines already have values set for that plan."""
|
||||
plan_1_col = self.analytic_plan_1._column_name()
|
||||
plan_2_col = self.analytic_plan_2._column_name()
|
||||
self.assertNotEqual(plan_1_col, plan_2_col)
|
||||
self.env['account.analytic.line'].create({
|
||||
'name': 'test',
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
plan_2_col: self.analytic_account_2.id,
|
||||
})
|
||||
with self.assertRaisesRegex(RedirectWarning, "wipe out your current data"):
|
||||
self.analytic_account_1.plan_id = self.analytic_plan_2
|
||||
|
||||
def test_change_plan_no_conflict(self):
|
||||
"""Exception for the previous test if it was already the correct value that is set."""
|
||||
plan_1_col = self.analytic_plan_1._column_name()
|
||||
plan_2_col = self.analytic_plan_2._column_name()
|
||||
self.assertNotEqual(plan_1_col, plan_2_col)
|
||||
line = self.env['account.analytic.line'].create({
|
||||
'name': 'test',
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
plan_2_col: self.analytic_account_1.id,
|
||||
})
|
||||
self.analytic_account_1.plan_id = self.analytic_plan_2
|
||||
self.assertRecordValues(line, [{
|
||||
plan_1_col: False,
|
||||
plan_2_col: self.analytic_account_1.id,
|
||||
}])
|
||||
|
||||
def test_change_parent_plan(self):
|
||||
"""Changing the parent of a plan updates account columns of the analytic lines."""
|
||||
plan_1_col = self.analytic_plan_1._column_name()
|
||||
plan_2_col = self.analytic_plan_2._column_name()
|
||||
line = self.env['account.analytic.line'].create({
|
||||
'name': 'test',
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
})
|
||||
|
||||
# Setting a parent plan should lead to the line having analytic_account_1 under Plan 2
|
||||
self.analytic_plan_1.parent_id = self.analytic_plan_2
|
||||
self.assertRecordValues(line, [{
|
||||
plan_2_col: self.analytic_account_1.id,
|
||||
}])
|
||||
# plan_1_col should no longer be a field of the analytic line
|
||||
self.assertNotIn(plan_1_col, line)
|
||||
|
||||
# Removing the parent plan should fully reverse the analytic line
|
||||
self.analytic_plan_1.parent_id = False
|
||||
self.assertRecordValues(line, [{
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
plan_2_col: False,
|
||||
}])
|
||||
|
||||
def test_change_parent_plan_conflict(self):
|
||||
"""
|
||||
Test case where changing the parent plan leads to more than one account under the same
|
||||
plan in an analytic line.
|
||||
"""
|
||||
plan_1_col = self.analytic_plan_1._column_name()
|
||||
plan_2_col = self.analytic_plan_2._column_name()
|
||||
self.env['account.analytic.line'].create({
|
||||
'name': 'test',
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
plan_2_col: self.analytic_account_3.id,
|
||||
})
|
||||
with self.assertRaisesRegex(RedirectWarning, "Making this change would wipe out"):
|
||||
self.analytic_plan_1.parent_id = self.analytic_plan_2
|
||||
|
||||
def test_change_parent_plan_with_intermediate(self):
|
||||
"""All the accounts are updated even if not direct members of the plan changed."""
|
||||
plan_1_col = self.analytic_plan_1._column_name()
|
||||
plan_2_col = self.analytic_plan_2._column_name()
|
||||
intermediate_plan = self.env['account.analytic.plan'].create({
|
||||
'name': 'Mid level',
|
||||
'parent_id': self.analytic_plan_1.id,
|
||||
})
|
||||
self.analytic_account_1.plan_id = intermediate_plan
|
||||
line = self.env['account.analytic.line'].create({
|
||||
'name': 'test',
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
})
|
||||
|
||||
# Setting a parent plan should lead to the line having analytic_account_1 under Plan 2
|
||||
self.analytic_plan_1.parent_id = self.analytic_plan_2
|
||||
self.assertRecordValues(line, [{
|
||||
plan_2_col: self.analytic_account_1.id,
|
||||
}])
|
||||
|
||||
# Removing the parent plan should fully reverse the analytic line
|
||||
self.analytic_plan_1.parent_id = False
|
||||
self.assertRecordValues(line, [{
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
plan_2_col: False,
|
||||
}])
|
||||
|
||||
def test_update_analytic_distribution_clean_all_plans(self):
|
||||
"""
|
||||
This test ensures no IndexError occurs and no changes are made when clearing all percentages
|
||||
in the analytic distribution wizard.
|
||||
"""
|
||||
plan_1_col = self.analytic_plan_1._column_name()
|
||||
plan_2_col = self.analytic_plan_2._column_name()
|
||||
|
||||
line = self.env['account.analytic.line'].create({
|
||||
'name': 'Test line',
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
plan_2_col: self.analytic_account_3.id,
|
||||
})
|
||||
|
||||
# Simulate the wizard cleaning all percentages: update all plans but provide no values
|
||||
# This results in an empty final distribution in the inverse method.
|
||||
line.write({
|
||||
'analytic_distribution': {
|
||||
'__update__': [plan_1_col, plan_2_col],
|
||||
# No other entries -> cleaned percentages
|
||||
}
|
||||
})
|
||||
|
||||
# No crash and the line remains unchanged (no lines created/deleted, same accounts)
|
||||
self.assertTrue(line.exists(), "The analytic line should still exist after update")
|
||||
self.assertRecordValues(line, [{
|
||||
plan_1_col: self.analytic_account_1.id,
|
||||
plan_2_col: self.analytic_account_3.id,
|
||||
}])
|
||||
|
||||
def test_change_sys_param(self):
|
||||
''' Test if changing project_plan param updates dynamic fields on account.analytic.line '''
|
||||
current_project_plan, _other_plans = self.env['account.analytic.plan']._get_all_plans()
|
||||
current_project_plan.write({'name': 'Old Project Plan'})
|
||||
self.analytic_account_1.write({'company_id': self.company.id})
|
||||
self.env['ir.config_parameter'].set_param('analytic.project_plan', self.analytic_plan_2.id)
|
||||
self.analytic_account_1._check_company_consistency()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,240 @@
|
|||
from contextlib import contextmanager
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo.tests import tagged
|
||||
from odoo.addons.analytic.tests.common import AnalyticCommon
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAnalyticDynamicUpdate(AnalyticCommon):
|
||||
def test_configurations(self):
|
||||
@contextmanager
|
||||
def capture_create():
|
||||
container = {'created': self.env['account.analytic.line']}
|
||||
super_create = self.env.registry['account.analytic.line'].create
|
||||
|
||||
def patch_create(self, vals_list):
|
||||
records = super_create(self, vals_list)
|
||||
container['created'] += records
|
||||
return records
|
||||
|
||||
with patch.object(self.env.registry['account.analytic.line'], 'create', patch_create):
|
||||
yield container
|
||||
|
||||
plan2 = self.analytic_account_3.plan_id._column_name()
|
||||
plan1 = self.analytic_account_1.plan_id._column_name()
|
||||
for comment, init, update, expect in [(
|
||||
"Add a distribution on a previously empty plan",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 40},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 60},
|
||||
], {
|
||||
'__update__': [plan2],
|
||||
f"{self.analytic_account_3.id}": 25,
|
||||
f"{self.analytic_account_4.id}": 75,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 10.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 15.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 30.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 45.0},
|
||||
],
|
||||
), (
|
||||
"Add a distribution on a previously empty plan, both less than 100%",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 20},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 30},
|
||||
], {
|
||||
'__update__': [plan2],
|
||||
f"{self.analytic_account_3.id}": 10,
|
||||
f"{self.analytic_account_4.id}": 40,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 2.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 3.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 8.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 10.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 12.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 15.0},
|
||||
],
|
||||
), (
|
||||
"Add a distribution on a previously empty plan, both more than 100%",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 200},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 300},
|
||||
], {
|
||||
'__update__': [plan2],
|
||||
f"{self.analytic_account_3.id}": 100,
|
||||
f"{self.analytic_account_4.id}": 400,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 40.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 60.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 160.0},
|
||||
{plan1: False, plan2: self.analytic_account_3.id, 'amount': 160.0},
|
||||
{plan1: False, plan2: self.analytic_account_4.id, 'amount': 640.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 240.0},
|
||||
{plan1: False, plan2: self.analytic_account_3.id, 'amount': 240.0},
|
||||
{plan1: False, plan2: self.analytic_account_4.id, 'amount': 960.0},
|
||||
],
|
||||
), (
|
||||
"Update the percentage of one plan without changing the other",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 10},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 15},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 30},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 45},
|
||||
], {
|
||||
'__update__': [plan1, plan2],
|
||||
f"{self.analytic_account_1.id},{self.analytic_account_3.id}": 15,
|
||||
f"{self.analytic_account_2.id},{self.analytic_account_3.id}": 10,
|
||||
f"{self.analytic_account_1.id},{self.analytic_account_4.id}": 45,
|
||||
f"{self.analytic_account_2.id},{self.analytic_account_4.id}": 30,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 1.5},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 2.25},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 4.5},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 6.75},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 1.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 4.5},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 3.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 1.5},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 6.75},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 4.5},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 3.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 13.5},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 9.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 4.5},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 20.25},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 13.5},
|
||||
],
|
||||
), (
|
||||
"Update the percentage on both plans at the same time",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 10},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 15},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 30},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 45},
|
||||
], {
|
||||
'__update__': [plan1, plan2],
|
||||
f"{self.analytic_account_1.id},{self.analytic_account_3.id}": 45,
|
||||
f"{self.analytic_account_2.id},{self.analytic_account_3.id}": 30,
|
||||
f"{self.analytic_account_1.id},{self.analytic_account_4.id}": 15,
|
||||
f"{self.analytic_account_2.id},{self.analytic_account_4.id}": 10,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 4.5},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 6.75},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 13.5},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 20.25},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 3.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 1.5},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 1.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 4.5},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 2.25},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 1.5},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 9.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 4.5},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 3.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 13.5},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 6.75},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 4.5},
|
||||
],
|
||||
), (
|
||||
"Remove everything set on plan 1",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 45},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 30},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 15},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 10},
|
||||
], {
|
||||
'__update__': [plan1],
|
||||
}, [
|
||||
{plan1: False, plan2: self.analytic_account_3.id, 'amount': 45.0},
|
||||
{plan1: False, plan2: self.analytic_account_3.id, 'amount': 30.0},
|
||||
{plan1: False, plan2: self.analytic_account_4.id, 'amount': 15.0},
|
||||
{plan1: False, plan2: self.analytic_account_4.id, 'amount': 10.0},
|
||||
],
|
||||
), (
|
||||
"Nothing changes because there is nothing in __update__",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 40},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 60},
|
||||
], {
|
||||
'__update__': [],
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 40.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 60.0},
|
||||
],
|
||||
), (
|
||||
"Add a distribution on a previously empty plan, with more than 100%",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 40},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 60},
|
||||
], {
|
||||
'__update__': [plan2],
|
||||
f"{self.analytic_account_3.id}": 33,
|
||||
f"{self.analytic_account_4.id}": 167,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 6.6},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 9.9},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 33.4},
|
||||
{plan1: False, plan2: self.analytic_account_3.id, 'amount': 6.6},
|
||||
{plan1: False, plan2: self.analytic_account_4.id, 'amount': 33.4},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 50.1},
|
||||
{plan1: False, plan2: self.analytic_account_3.id, 'amount': 9.9},
|
||||
{plan1: False, plan2: self.analytic_account_4.id, 'amount': 50.1},
|
||||
],
|
||||
), (
|
||||
"Add a distribution on a previously empty plan, with previous values more than 100%",
|
||||
[
|
||||
{plan1: False, plan2: self.analytic_account_3.id, 'amount': 33},
|
||||
{plan1: False, plan2: self.analytic_account_4.id, 'amount': 167},
|
||||
], {
|
||||
'__update__': [plan1],
|
||||
f"{self.analytic_account_1.id}": 40,
|
||||
f"{self.analytic_account_2.id}": 60,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 13.2},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 66.8},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 19.8},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 100.2},
|
||||
],
|
||||
), (
|
||||
"Add a distribution on a previously empty plan, with less than 100%",
|
||||
[
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 40},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 60},
|
||||
], {
|
||||
'__update__': [plan2],
|
||||
f"{self.analytic_account_3.id}": 20,
|
||||
f"{self.analytic_account_4.id}": 30,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 8.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 12.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 12.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: False, 'amount': 20.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 18.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: False, 'amount': 30.0},
|
||||
],
|
||||
), (
|
||||
"Add a distribution on a previously empty plan, with previous values less than 100%",
|
||||
[
|
||||
{plan1: False, plan2: self.analytic_account_3.id, 'amount': 20},
|
||||
{plan1: False, plan2: self.analytic_account_4.id, 'amount': 30},
|
||||
], {
|
||||
'__update__': [plan1],
|
||||
f"{self.analytic_account_1.id}": 40,
|
||||
f"{self.analytic_account_2.id}": 60,
|
||||
}, [
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_3.id, 'amount': 8.0},
|
||||
{plan1: self.analytic_account_1.id, plan2: self.analytic_account_4.id, 'amount': 12.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_3.id, 'amount': 12.0},
|
||||
{plan1: self.analytic_account_2.id, plan2: self.analytic_account_4.id, 'amount': 18.0},
|
||||
],
|
||||
)]:
|
||||
with self.subTest(comment=comment):
|
||||
lines = self.env['account.analytic.line'].create([
|
||||
{'name': 'test'} | vals
|
||||
for vals in init
|
||||
])
|
||||
with capture_create() as container:
|
||||
lines.analytic_distribution = update
|
||||
lines.invalidate_recordset(['analytic_distribution'])
|
||||
self.assertRecordValues(lines + container['created'], expect)
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
from odoo.tests import tagged
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAnalyticMixin(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
cls.analytic_plan = cls.env['account.analytic.plan'].create({'name': 'Plan'})
|
||||
|
||||
cls.sales_aa = cls.env['account.analytic.account'].create({'name': 'Sales', 'plan_id': cls.analytic_plan.id})
|
||||
cls.administrative_aa = cls.env['account.analytic.account'].create({'name': 'Administrative', 'plan_id': cls.analytic_plan.id})
|
||||
cls.rd_aa = cls.env['account.analytic.account'].create({'name': 'Research & Development', 'plan_id': cls.analytic_plan.id})
|
||||
cls.commercial_aa = cls.env['account.analytic.account'].create({'name': 'Commercial', 'plan_id': cls.analytic_plan.id})
|
||||
cls.marketing_aa = cls.env['account.analytic.account'].create({'name': 'Marketing', 'plan_id': cls.analytic_plan.id})
|
||||
cls.com_marketing_aa = cls.env['account.analytic.account'].create({'name': 'Commercial & Marketing', 'plan_id': cls.analytic_plan.id})
|
||||
|
||||
def test_filtered_domain(self):
|
||||
"""
|
||||
This test covers the filtered_domain override on analytic.mixin.
|
||||
It is supposed to handle the use of analytic_distribution with the following operators
|
||||
with a string representing the analytic account name :
|
||||
- `=`
|
||||
- `!=`
|
||||
- `ilike`,
|
||||
- `not ilike`,
|
||||
and the "in" operator used to directly indicate a tuple/list of analytic account ids.
|
||||
This test verifies that the public method handles all these operators.
|
||||
"""
|
||||
|
||||
self.adm_sales_admin_ad = self.env['account.analytic.distribution.model'].create({
|
||||
'analytic_distribution': {
|
||||
self.sales_aa.id: 50,
|
||||
self.administrative_aa.id: 50,
|
||||
}
|
||||
})
|
||||
self.adm_rd_ad = self.env['account.analytic.distribution.model'].create({
|
||||
'analytic_distribution': {self.rd_aa.id: 100},
|
||||
})
|
||||
self.adm_commercial_ad = self.env['account.analytic.distribution.model'].create({
|
||||
'analytic_distribution': {self.commercial_aa.id: 100},
|
||||
})
|
||||
self.adm_com_marketing_ad = self.env['account.analytic.distribution.model'].create({
|
||||
'analytic_distribution': {self.com_marketing_aa.id: 100},
|
||||
})
|
||||
self.adm_without_ad = self.env['account.analytic.distribution.model'].create({})
|
||||
self.adm_without_ad_1 = self.env['account.analytic.distribution.model'].create({})
|
||||
|
||||
adm_ids = self.env['account.analytic.distribution.model'].search([])
|
||||
|
||||
def filter_domain(comparator, value):
|
||||
return adm_ids.filtered_domain([('analytic_distribution', comparator, value)])
|
||||
|
||||
self.assertEqual(filter_domain('=', 'Research & Development'), self.adm_rd_ad)
|
||||
self.assertEqual(filter_domain('=', 'Sales'), self.adm_sales_admin_ad)
|
||||
self.assertEqual(filter_domain('=', 'Administrative'), self.adm_sales_admin_ad)
|
||||
self.assertEqual(filter_domain('=', 'Commercial'), self.adm_commercial_ad)
|
||||
self.assertFalse(filter_domain('=', '')) # Should returns an empty recordset
|
||||
self.assertEqual(filter_domain('=', self.commercial_aa.id), self.adm_commercial_ad)
|
||||
|
||||
self.assertEqual(filter_domain('ilike', 'Commercial'), self.adm_commercial_ad | self.adm_com_marketing_ad)
|
||||
self.assertEqual(filter_domain('ilike', ''), adm_ids - self.adm_without_ad - self.adm_without_ad_1)
|
||||
|
||||
self.assertEqual(filter_domain('not ilike', 'Commercial'), adm_ids - self.adm_com_marketing_ad - self.adm_commercial_ad)
|
||||
self.assertEqual(filter_domain('not ilike', ''), self.adm_without_ad + self.adm_without_ad_1) # Should returns an AML without analytic_distribution
|
||||
|
||||
self.assertEqual(filter_domain('!=', 'Commercial & Marketing'), adm_ids - self.adm_com_marketing_ad)
|
||||
self.assertEqual(filter_domain('!=', ''), adm_ids) # Should returns an every ADM
|
||||
self.assertEqual(filter_domain('!=', self.commercial_aa.id), adm_ids - self.adm_commercial_ad)
|
||||
|
||||
self.assertEqual(filter_domain('in', [self.commercial_aa.id]), self.adm_commercial_ad)
|
||||
self.assertEqual(filter_domain('in', (self.sales_aa + self.rd_aa).ids), self.adm_sales_admin_ad + self.adm_rd_ad)
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import psycopg2
|
||||
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import tagged
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAnalyticPlanOperations(TransactionCase):
|
||||
def test_delete_plan(self):
|
||||
plan = self.env['account.analytic.plan'].create({'name': 'Test Plan'})
|
||||
column = plan._column_name()
|
||||
|
||||
# columns exists
|
||||
self.env.cr.execute(f"SELECT {column} FROM account_analytic_line LIMIT 1")
|
||||
|
||||
plan.unlink()
|
||||
with self.assertRaises(psycopg2.errors.UndefinedColumn), mute_logger('odoo.sql_db'):
|
||||
# column has been deleted
|
||||
self.env.cr.execute(f"SELECT {column} FROM account_analytic_line LIMIT 1")
|
||||
|
||||
def test_delete_subplan(self):
|
||||
parent = self.env['account.analytic.plan'].create({'name': 'Parent Plan'})
|
||||
plan = self.env['account.analytic.plan'].create({'name': 'Test Plan', 'parent_id': parent.id})
|
||||
other_plan = self.env['account.analytic.plan'].create({'name': 'Other Plan', 'parent_id': parent.id})
|
||||
self.assertFalse(plan._find_plan_column('account.analytic.line'))
|
||||
related_field = plan._find_related_field('account.analytic.line')
|
||||
self.assertTrue(related_field.exists())
|
||||
other_plan.unlink()
|
||||
self.assertTrue(related_field.exists())
|
||||
plan.unlink()
|
||||
self.assertFalse(related_field.exists())
|
||||
|
||||
def test_rename_plan(self):
|
||||
plan = self.env['account.analytic.plan'].create({'name': 'Test Plan'})
|
||||
column = plan._find_plan_column('account.analytic.line')
|
||||
plan.name = 'New name'
|
||||
self.assertEqual(column.field_description, 'New name')
|
||||
|
||||
def test_promote_subplan(self):
|
||||
parent = self.env['account.analytic.plan'].create({'name': 'Parent Plan'})
|
||||
plan = self.env['account.analytic.plan'].create({'name': 'Test Plan', 'parent_id': parent.id})
|
||||
self.assertFalse(plan._find_plan_column('account.analytic.line'))
|
||||
self.assertTrue(plan._find_related_field('account.analytic.line'))
|
||||
plan.parent_id = False
|
||||
self.assertTrue(plan._find_plan_column('account.analytic.line'))
|
||||
self.assertFalse(plan._find_related_field('account.analytic.line'))
|
||||
|
||||
def test_demote_plan(self):
|
||||
parent = self.env['account.analytic.plan'].create({'name': 'Parent Plan'})
|
||||
plan = self.env['account.analytic.plan'].create({'name': 'Test Plan'})
|
||||
self.assertTrue(plan._find_plan_column('account.analytic.line'))
|
||||
self.assertFalse(plan._find_related_field('account.analytic.line'))
|
||||
plan.parent_id = parent
|
||||
self.assertFalse(plan._find_plan_column('account.analytic.line'))
|
||||
self.assertTrue(plan._find_related_field('account.analytic.line'))
|
||||
|
||||
def test_delete_plan_with_view(self):
|
||||
plan = self.env['account.analytic.plan'].create({'name': 'Test Plan'})
|
||||
column = plan._column_name()
|
||||
|
||||
self.env['ir.ui.view'].create({
|
||||
'name': 'Manual view',
|
||||
'model': 'account.analytic.line',
|
||||
'type': 'search',
|
||||
'arch': f'<search><field name="{column}"/></search>',
|
||||
})
|
||||
|
||||
# can't delete a plan still used in a view
|
||||
with self.assertRaisesRegex(UserError, 'still present in views'):
|
||||
plan.unlink()
|
||||
|
||||
def test_validate_deleted_account(self):
|
||||
plan, mandatory_plan = self.env['account.analytic.plan'].create([{
|
||||
'name': 'Test Plan',
|
||||
}, {
|
||||
'name': 'Mandatory Plan',
|
||||
'default_applicability': 'mandatory',
|
||||
}])
|
||||
test_account, mandatory_account = self.env['account.analytic.account'].create([{
|
||||
'name': 'Test Account',
|
||||
'code': 'TAC',
|
||||
'plan_id': plan.id,
|
||||
}, {
|
||||
'name': 'Mandatory Account',
|
||||
'code': 'manda',
|
||||
'plan_id': mandatory_plan.id,
|
||||
}])
|
||||
distribution_model = self.env['account.analytic.distribution.model'].create({}).with_context(validate_analytic=True)
|
||||
|
||||
# the configuration makes it raise an error
|
||||
distribution_model.analytic_distribution = {f"{test_account.id}": 100}
|
||||
with self.assertRaisesRegex(UserError, r'require a 100% analytic distribution'):
|
||||
distribution_model._validate_distribution()
|
||||
|
||||
# once it is fixed, the error is not raised anymore
|
||||
distribution_model.analytic_distribution = {f"{test_account.id},{mandatory_account.id}": 100}
|
||||
distribution_model._validate_distribution()
|
||||
|
||||
# even by keeping a deleted account, the validation still works
|
||||
test_account.unlink()
|
||||
plan.unlink()
|
||||
distribution_model._validate_distribution()
|
||||
|
||||
def test_validate_company_plans(self):
|
||||
company_2 = self.env['res.company'].create({
|
||||
'name': 'company_2',
|
||||
})
|
||||
plan = self.env['account.analytic.plan'].create([{
|
||||
'name': 'Plan',
|
||||
'default_applicability': 'optional',
|
||||
}])
|
||||
applicability = self.env['account.analytic.applicability'].create({
|
||||
'business_domain': 'general',
|
||||
'analytic_plan_id': plan.id,
|
||||
'applicability': 'mandatory',
|
||||
'company_id': company_2.id,
|
||||
})
|
||||
self.env['account.analytic.account'].create([{
|
||||
'name': 'Mandatory Account',
|
||||
'code': 'manda',
|
||||
'plan_id': plan.id,
|
||||
}])
|
||||
distribution_model = self.env['account.analytic.distribution.model'].create({}).with_context(validate_analytic=True)
|
||||
|
||||
# mandatory applicability is only in company_2, should not raise for company_1
|
||||
distribution_model._validate_distribution(business_domain='general', company_id=self.env.company.id)
|
||||
|
||||
applicability.company_id = False
|
||||
# It should apply for all companies now
|
||||
with self.assertRaisesRegex(UserError, r'require a 100% analytic distribution'):
|
||||
distribution_model._validate_distribution(business_domain='general', company_id=self.env.company.id)
|
||||
with self.assertRaisesRegex(UserError, r'require a 100% analytic distribution'):
|
||||
distribution_model._validate_distribution(business_domain='general')
|
||||
Loading…
Add table
Add a link
Reference in a new issue