Files
odoo_source/addons/analytic/tests/test_analytic_account.py
T
williamandh4818 dc696c8ed4 [IMP] analytic: allow cross analytics
Purpose
=======

Make it possible to compare analytic values between plans by inputting
up to one account per plan on each line.
For instance, if we have 2 plans: "Country" and "Product Type", with the
following accounts

| Country | Product Type |
| ------- | ------------ |
| BE      | Drinks       |
| LU      | Food         |

And the following invoices:
* 1000€ of drinks in Belgium
* 2000€ of food in Belgium
* 3000€ of food in Luxemburg

We want to be able to display the following pivot tables:

|     | Drinks | Food | Total |
| --- | ------ | ---- | ----- |
| BE  |   1000 | 2000 |  3000 |
| LU  |      0 | 3000 |  3000 |
| Tot |   1000 | 5000 |  6000 |

|        | Total |
| ------ | ----- |
| Food   |  5000 |
| * BE   |  2000 |
| * LU   |  3000 |
| Drinks |  1000 |
| * BE   |  1000 |
| Total  |  6000 |

Implementation
==============

* `ir.fields` are added/removed dynamically on `account.analytic.line`
* Each analytic plan corresponds to one field on `account.analytic.line`
* The fields are added dynamically in the views.
* `account.analytic.plan` doesn't have a `company_id` field anymore,
  meaning that all the companies have access to all the plans. This
  means that the applicability fields and lines are now company
  dependent, and those can be used to know which fields/plans to display
  for which company.
* There can no longer be one "Project" plan per company, even if the
  accounts of that project can still be owned by only one company.
* There is now only one method to get the default (or "Project" plan),
  which is `_get_plan_columns`

task-3497653

closes odoo/odoo#139225

Related: odoo/upgrade#5306
Related: odoo/enterprise#49226
Signed-off-by: William André (wan) <wan@odoo.com>
Co-authored-by: william <wan@odoo.com>
Co-authored-by: h4818 <ayh@odoo.com>
2023-10-25 18:10:57 +00:00

189 lines
9.4 KiB
Python

# -*- coding: utf-8 -*-
from odoo.tests import tagged
from odoo.tests.common import TransactionCase
from odoo import Command
@tagged('post_install', '-at_install')
class TestAnalyticAccount(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# 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.analytic_plan_offset = len(cls.env['account.analytic.plan'].get_relevant_plans())
cls.analytic_plan_1 = cls.env['account.analytic.plan'].create({
'name': 'Plan 1',
'default_applicability': 'unavailable',
})
cls.analytic_plan_child = cls.env['account.analytic.plan'].create({
'name': 'Plan Child',
'parent_id': cls.analytic_plan_1.id,
})
cls.analytic_plan_2 = cls.env['account.analytic.plan'].create({
'name': 'Plan 2',
})
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.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_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) - 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) - 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) - 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',
'analytic_plan_id': self.analytic_plan_1.id,
'applicability': 'mandatory'
})
plans_json = self.env['account.analytic.plan'].get_relevant_plans(**kwargs)
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) - 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) - 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) - self.analytic_plan_offset, "All root plans should be available")
def test_analytic_distribution_model(self):
""" Test the distribution returned from the distribution model """
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,
})
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,
})
self.assertEqual(distribution_json, {str(self.analytic_account_2.id): 100}, "Distribution 2 should be given")
def test_order_analytic_distribution_model(self):
""" Test the distribution returned with company field"""
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,
})
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,
})
self.assertEqual(distribution_json, distribution_3.analytic_distribution,
"Distribution 3 should be given, as the company is specified in the model")
distribution_json = self.env['account.analytic.distribution.model']._get_distribution({
"partner_id": self.partner_b.id,
"company_id": self.company_data.id,
})
self.assertEqual(distribution_json, {str(self.analytic_account_2.id): 100},
"Distribution 2 should be given, for the partner")
partner_category = self.env['res.partner.category'].create({'name': 'partner_categ'})
self.partner_a.write({
'category_id': [Command.set([partner_category.id])]
})
distribution_4 = self.env['account.analytic.distribution.model'].create({
'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,
})
distribution_json = self.env['account.analytic.distribution.model']._get_distribution({
"partner_id": self.partner_a.id,
"company_id": self.company_data.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")
def test_analytic_plan_account_child(self):
"""
Check that when an analytic account is set to the third (or more) child,
the root plan is correctly retrieved.
"""
self.analytic_plan = self.env['account.analytic.plan'].create({
'name': 'Parent Plan',
})
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})
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.analytic_plan_offset,
"The parent plan should be available even if the analytic account is set on child of third generation")