mirror of
https://github.com/bringout/oca-ocb-project.git
synced 2026-04-22 01:42:04 +02:00
19.0 vanilla
This commit is contained in:
parent
a2f74aefd8
commit
4a4d12c333
844 changed files with 212348 additions and 270090 deletions
|
|
@ -1,4 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_analytics
|
||||
from . import test_project_profitability
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import tagged
|
||||
from odoo.addons.hr_expense.tests.common import TestExpenseCommon
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestAnalytics(TestExpenseCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env.user.group_ids += cls.env.ref('project.group_project_manager')
|
||||
cls.project_plan, _other_plans = cls.env['account.analytic.plan']._get_all_plans()
|
||||
cls.analytic_account1, cls.analytic_account2 = cls.env['account.analytic.account'].create([
|
||||
{
|
||||
'name': 'Account 1',
|
||||
'plan_id': cls.project_plan.id,
|
||||
},
|
||||
{
|
||||
'name': 'Account 2',
|
||||
'plan_id': cls.project_plan.id,
|
||||
},
|
||||
])
|
||||
cls.project = cls.env['project.project'].create({
|
||||
'name': 'Project',
|
||||
'account_id': cls.analytic_account1.id,
|
||||
})
|
||||
|
||||
def test_project_analytics_to_expense(self):
|
||||
expense = self.env['hr.expense'].with_context(project_id=self.project.id).create({
|
||||
'name': 'Expense',
|
||||
'employee_id': self.expense_employee.id,
|
||||
'product_id': self.product_a.id,
|
||||
})
|
||||
self.assertEqual(
|
||||
expense.analytic_distribution,
|
||||
{str(self.analytic_account1.id): 100},
|
||||
"The analytic distribution of the created expense should be set to the account of the project specified in the context.",
|
||||
)
|
||||
self.project.account_id = self.analytic_account2
|
||||
expense.analytic_distribution = False
|
||||
expense.with_context(project_id=self.project.id)._compute_analytic_distribution()
|
||||
self.assertEqual(
|
||||
expense.analytic_distribution,
|
||||
{str(self.analytic_account2.id): 100},
|
||||
"The analytic distribution of the expense should be set to the account of the project specified in the context.",
|
||||
)
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.hr_expense.tests.common import TestExpenseCommon
|
||||
|
|
@ -7,67 +6,147 @@ from odoo.tests.common import tagged
|
|||
|
||||
|
||||
class TestProjectHrExpenseProfitabilityCommon(TestExpenseCommon):
|
||||
def check_project_profitability_before_creating_and_approving_expense_sheet(self, expense, project, project_profitability_items_empty):
|
||||
def check_project_profitability_before_creating_and_approving_expense(self, expense, project, project_profitability_items_empty):
|
||||
self.assertDictEqual(
|
||||
project._get_profitability_items(False),
|
||||
project_profitability_items_empty,
|
||||
'No data should be found since the expense is not approved yet.',
|
||||
)
|
||||
|
||||
expense_sheet_vals_list = expense._get_default_expense_sheet_values()
|
||||
expense_sheet = self.env['hr.expense.sheet'].create(expense_sheet_vals_list)
|
||||
self.assertEqual(len(expense_sheet), 1, '1 expense sheet should be created.')
|
||||
|
||||
expense_sheet.action_submit_sheet()
|
||||
self.assertEqual(expense_sheet.state, 'submit')
|
||||
|
||||
expense.action_submit()
|
||||
self.assertDictEqual(
|
||||
project._get_profitability_items(False),
|
||||
project_profitability_items_empty,
|
||||
'No data should be found since the sheet is not approved yet.',
|
||||
'No data should be found since the expense is not approved yet.',
|
||||
)
|
||||
|
||||
expense_sheet.approve_expense_sheets()
|
||||
self.assertEqual(expense_sheet.state, 'approve')
|
||||
return expense_sheet
|
||||
expense.action_approve()
|
||||
return expense
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestProjectHrExpenseProfitability(TestProjectProfitabilityCommon, TestProjectHrExpenseProfitabilityCommon):
|
||||
|
||||
def test_project_profitability(self):
|
||||
expense = self.env['hr.expense'].create({
|
||||
'name': 'Car Travel Expenses',
|
||||
'employee_id': self.expense_employee.id,
|
||||
'product_id': self.product_a.id,
|
||||
'unit_amount': 350.00,
|
||||
'company_id': self.project.company_id.id,
|
||||
'analytic_distribution': {self.project.analytic_account_id.id: 100},
|
||||
self.project.company_id = False
|
||||
# Create a new company with the foreign currency.
|
||||
foreign_company = self.company_data_2['company']
|
||||
foreign_company.currency_id = self.foreign_currency
|
||||
foreign_employee = self.env['hr.employee'].sudo().create({
|
||||
'name': 'Foreign employee',
|
||||
'company_id': foreign_company.id,
|
||||
'expense_manager_id': self.expense_user_manager.id,
|
||||
'work_email': 'email@email',
|
||||
})
|
||||
|
||||
expense_sheet = self.check_project_profitability_before_creating_and_approving_expense_sheet(
|
||||
expense = self.create_expenses({
|
||||
'name': 'Car Travel Expenses',
|
||||
'employee_id': self.expense_employee.id,
|
||||
'product_id': self.product_c.id,
|
||||
'total_amount_currency': 350.00,
|
||||
'company_id': self.env.company.id,
|
||||
'analytic_distribution': {self.project.account_id.id: 100},
|
||||
})
|
||||
|
||||
self.check_project_profitability_before_creating_and_approving_expense(
|
||||
expense,
|
||||
self.project,
|
||||
self.project_profitability_items_empty)
|
||||
self.assertEqual(expense.state, 'approved')
|
||||
|
||||
sequence_per_invoice_type = self.project._get_profitability_sequence_per_invoice_type()
|
||||
self.assertIn('expenses', sequence_per_invoice_type)
|
||||
expense_sequence = sequence_per_invoice_type['expenses']
|
||||
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(False),
|
||||
self.project_profitability_items_empty,
|
||||
'No data should be found since the expenses are not posted.',
|
||||
)
|
||||
|
||||
# Create an expense in a foreign company, the expense is linked to the AA of the project.
|
||||
expense_foreign = self.create_expenses({
|
||||
'name': 'Car Travel Expenses foreign',
|
||||
'employee_id': foreign_employee.id,
|
||||
'product_id': self.product_c.id,
|
||||
'total_amount_currency': 350.00,
|
||||
'company_id': foreign_company.id,
|
||||
'analytic_distribution': {self.project.account_id.id: 100},
|
||||
'currency_id': self.foreign_currency.id,
|
||||
})
|
||||
expense_foreign.action_submit()
|
||||
self.assertEqual(expense_foreign.state, 'submitted')
|
||||
expense_foreign.action_approve()
|
||||
self.assertEqual(expense_foreign.state, 'approved')
|
||||
self.post_expenses_with_wizard(expense_foreign.with_company(foreign_company))
|
||||
self.assertEqual(expense_foreign.state, 'posted')
|
||||
self.post_expenses_with_wizard(expense)
|
||||
self.assertEqual(expense.state, 'posted')
|
||||
|
||||
# Both costs should now be computed in the project profitability, since both expenses were posted
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(False),
|
||||
{
|
||||
'costs': {
|
||||
'data': [{'id': 'expenses', 'sequence': expense_sequence, 'to_bill': 0.0, 'billed': -expense.untaxed_amount}],
|
||||
'total': {'to_bill': 0.0, 'billed': -expense.untaxed_amount},
|
||||
'data': [{
|
||||
'id': 'expenses',
|
||||
'sequence': expense_sequence,
|
||||
'to_bill': 0.0,
|
||||
'billed': -expense.untaxed_amount_currency - expense_foreign.untaxed_amount_currency * 0.2
|
||||
}],
|
||||
'total': {'to_bill': 0.0, 'billed': -expense.untaxed_amount_currency - expense_foreign.untaxed_amount_currency * 0.2},
|
||||
},
|
||||
'revenues': {'data': [], 'total': {'to_invoice': 0.0, 'invoiced': 0.0}},
|
||||
},
|
||||
)
|
||||
|
||||
expense_sheet.refuse_sheet('Test cancel expense')
|
||||
# Reset to approved the expense of the main company. Only the total from the foreign company should be computed
|
||||
expense.account_move_id.button_draft()
|
||||
expense.account_move_id.unlink()
|
||||
self.assertEqual(expense.state, 'approved')
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(False),
|
||||
{
|
||||
'costs': {
|
||||
'data': [{'id': 'expenses', 'sequence': expense_sequence, 'to_bill': 0.0, 'billed': -expense_foreign.untaxed_amount_currency * 0.2}],
|
||||
'total': {'to_bill': 0.0, 'billed': -expense_foreign.untaxed_amount_currency * 0.2},
|
||||
},
|
||||
'revenues': {'data': [], 'total': {'to_invoice': 0.0, 'invoiced': 0.0}},
|
||||
},
|
||||
)
|
||||
|
||||
# Reset to approved the expense of the foreign company. No data should be computed now.
|
||||
expense_foreign.account_move_id.button_draft()
|
||||
expense_foreign.account_move_id.unlink()
|
||||
self.assertEqual(expense_foreign.state, 'approved')
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(False),
|
||||
self.project_profitability_items_empty,
|
||||
'No data should be found since the sheet is not approved yet.',
|
||||
'No data should be found since the sheets are not posted or done.',
|
||||
)
|
||||
|
||||
def test_project_profitability_after_expense_actions(self):
|
||||
expense = self.create_expenses({
|
||||
"name": "Car Travel Expenses",
|
||||
"total_amount": 50.00,
|
||||
"company_id": self.project.company_id.id,
|
||||
"analytic_distribution": {self.project.account_id.id: 100},
|
||||
})
|
||||
|
||||
sequence_per_invoice_type = self.project._get_profitability_sequence_per_invoice_type()
|
||||
self.assertIn('expenses', sequence_per_invoice_type)
|
||||
expense_sequence = sequence_per_invoice_type['expenses']
|
||||
|
||||
expense.action_submit()
|
||||
expense.action_approve()
|
||||
self.post_expenses_with_wizard(expense)
|
||||
|
||||
self.assertDictEqual(
|
||||
self.project._get_profitability_items(False),
|
||||
{
|
||||
'costs': {
|
||||
'data': [{'id': 'expenses', 'sequence': expense_sequence, 'to_bill': 0.0, 'billed': -expense.untaxed_amount_currency}],
|
||||
'total': {'to_bill': 0.0, 'billed': -expense.untaxed_amount_currency},
|
||||
},
|
||||
'revenues': {'data': [], 'total': {'to_invoice': 0.0, 'invoiced': 0.0}},
|
||||
},
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue