diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/hr_expense/tests | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/hr_expense/tests')
| -rw-r--r-- | addons/hr_expense/tests/__init__.py | 8 | ||||
| -rw-r--r-- | addons/hr_expense/tests/common.py | 54 | ||||
| -rw-r--r-- | addons/hr_expense/tests/test_expenses.py | 294 | ||||
| -rw-r--r-- | addons/hr_expense/tests/test_expenses_access_rights.py | 115 | ||||
| -rw-r--r-- | addons/hr_expense/tests/test_expenses_mail_import.py | 153 | ||||
| -rw-r--r-- | addons/hr_expense/tests/test_expenses_multi_company.py | 116 |
6 files changed, 740 insertions, 0 deletions
diff --git a/addons/hr_expense/tests/__init__.py b/addons/hr_expense/tests/__init__.py new file mode 100644 index 00000000..54cba710 --- /dev/null +++ b/addons/hr_expense/tests/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import common +from . import test_expenses +from . import test_expenses_access_rights +from . import test_expenses_mail_import +from . import test_expenses_multi_company diff --git a/addons/hr_expense/tests/common.py b/addons/hr_expense/tests/common.py new file mode 100644 index 00000000..406f8b14 --- /dev/null +++ b/addons/hr_expense/tests/common.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.account.tests.common import AccountTestInvoicingCommon +from odoo.addons.mail.tests.common import mail_new_test_user + + +class TestExpenseCommon(AccountTestInvoicingCommon): + + @classmethod + def setUpClass(cls, chart_template_ref=None): + super().setUpClass(chart_template_ref=chart_template_ref) + + group_expense_manager = cls.env.ref('hr_expense.group_hr_expense_manager') + + cls.expense_user_employee = mail_new_test_user( + cls.env, + name='expense_user_employee', + login='expense_user_employee', + email='expense_user_employee@example.com', + notification_type='email', + groups='base.group_user', + company_ids=[(6, 0, cls.env.companies.ids)], + ) + cls.expense_user_manager = mail_new_test_user( + cls.env, + name='Expense manager', + login='expense_manager_1', + email='expense_manager_1@example.com', + notification_type='email', + groups='base.group_user,hr_expense.group_hr_expense_manager', + company_ids=[(6, 0, cls.env.companies.ids)], + ) + + cls.expense_employee = cls.env['hr.employee'].create({ + 'name': 'expense_employee', + 'user_id': cls.expense_user_employee.id, + 'address_home_id': cls.expense_user_employee.partner_id.id, + 'address_id': cls.expense_user_employee.partner_id.id, + }) + + # Allow the current accounting user to access the expenses. + cls.env.user.groups_id |= group_expense_manager + + # Create analytic account + cls.analytic_account_1 = cls.env['account.analytic.account'].create({ + 'name': 'analytic_account_1', + }) + cls.analytic_account_2 = cls.env['account.analytic.account'].create({ + 'name': 'analytic_account_2', + }) + + # Ensure products can be expensed. + (cls.product_a + cls.product_b).write({'can_be_expensed': True}) diff --git a/addons/hr_expense/tests/test_expenses.py b/addons/hr_expense/tests/test_expenses.py new file mode 100644 index 00000000..566e187b --- /dev/null +++ b/addons/hr_expense/tests/test_expenses.py @@ -0,0 +1,294 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.addons.hr_expense.tests.common import TestExpenseCommon +from odoo.tests import tagged, Form +from odoo import fields +from odoo.exceptions import UserError + + +@tagged('-at_install', 'post_install') +class TestExpenses(TestExpenseCommon): + + def test_expense_values(self): + """ Checking accounting move entries and analytic entries when submitting expense """ + + # The expense employee is able to a create an expense sheet. + # The total should be 1725.0 because: + # - first line: 1000.0 (unit amount) + 150.0 (tax) = 1150.0 + # - second line: (1500.0 (unit amount) + 225.0 (tax)) * 1/3 (rate) = 575.0. + + expense_sheet = self.env['hr.expense.sheet'].create({ + 'name': 'First Expense for employee', + 'employee_id': self.expense_employee.id, + 'journal_id': self.company_data['default_journal_purchase'].id, + 'accounting_date': '2017-01-01', + 'expense_line_ids': [ + (0, 0, { + # Expense without foreign currency. + 'name': 'expense_1', + 'date': '2016-01-01', + 'product_id': self.product_a.id, + 'unit_amount': 1000.0, + 'tax_ids': [(6, 0, self.company_data['default_tax_purchase'].ids)], + 'analytic_account_id': self.analytic_account_1.id, + 'employee_id': self.expense_employee.id, + }), + (0, 0, { + # Expense with foreign currency (rate 1:3). + 'name': 'expense_1', + 'date': '2016-01-01', + 'product_id': self.product_b.id, + 'unit_amount': 1500.0, + 'tax_ids': [(6, 0, self.company_data['default_tax_purchase'].ids)], + 'analytic_account_id': self.analytic_account_2.id, + 'currency_id': self.currency_data['currency'].id, + 'employee_id': self.expense_employee.id, + }), + ], + }) + + # Check expense sheet values. + self.assertRecordValues(expense_sheet, [{'state': 'draft', 'total_amount': 1725.0}]) + + expense_sheet.action_submit_sheet() + expense_sheet.approve_expense_sheets() + expense_sheet.action_sheet_move_create() + + # Check expense sheet journal entry values. + self.assertRecordValues(expense_sheet.account_move_id.line_ids.sorted('balance'), [ + # Receivable line (company currency): + { + 'debit': 0.0, + 'credit': 1150.0, + 'amount_currency': -1150.0, + 'account_id': self.company_data['default_account_payable'].id, + 'product_id': False, + 'currency_id': self.company_data['currency'].id, + 'tax_line_id': False, + 'analytic_account_id': False, + }, + # Receivable line (foreign currency): + { + 'debit': 0.0, + 'credit': 862.5, + 'amount_currency': -1725.0, + 'account_id': self.company_data['default_account_payable'].id, + 'product_id': False, + 'currency_id': self.currency_data['currency'].id, + 'tax_line_id': False, + 'analytic_account_id': False, + }, + # Tax line (foreign currency): + { + 'debit': 112.5, + 'credit': 0.0, + 'amount_currency': 225.0, + 'account_id': self.company_data['default_account_tax_purchase'].id, + 'product_id': False, + 'currency_id': self.currency_data['currency'].id, + 'tax_line_id': self.company_data['default_tax_purchase'].id, + 'analytic_account_id': False, + }, + # Tax line (company currency): + { + 'debit': 150.0, + 'credit': 0.0, + 'amount_currency': 150.0, + 'account_id': self.company_data['default_account_tax_purchase'].id, + 'product_id': False, + 'currency_id': self.company_data['currency'].id, + 'tax_line_id': self.company_data['default_tax_purchase'].id, + 'analytic_account_id': False, + }, + # Product line (foreign currency): + { + 'debit': 750.0, + 'credit': 0.0, + 'amount_currency': 1500.0, + 'account_id': self.company_data['default_account_expense'].id, + 'product_id': self.product_b.id, + 'currency_id': self.currency_data['currency'].id, + 'tax_line_id': False, + 'analytic_account_id': self.analytic_account_2.id, + }, + # Product line (company currency): + { + 'debit': 1000.0, + 'credit': 0.0, + 'amount_currency': 1000.0, + 'account_id': self.company_data['default_account_expense'].id, + 'product_id': self.product_a.id, + 'currency_id': self.company_data['currency'].id, + 'tax_line_id': False, + 'analytic_account_id': self.analytic_account_1.id, + }, + ]) + + # Check expense analytic lines. + self.assertRecordValues(expense_sheet.account_move_id.line_ids.analytic_line_ids.sorted('amount'), [ + { + 'amount': -1000.0, + 'date': fields.Date.from_string('2017-01-01'), + 'account_id': self.analytic_account_1.id, + 'currency_id': self.company_data['currency'].id, + }, + { + 'amount': -750.0, + 'date': fields.Date.from_string('2017-01-01'), + 'account_id': self.analytic_account_2.id, + 'currency_id': self.company_data['currency'].id, + }, + ]) + + def test_account_entry_multi_currency(self): + """ Checking accounting move entries and analytic entries when submitting expense. With + multi-currency. And taxes. """ + + # Clean-up the rates + self.cr.execute("UPDATE res_company SET currency_id = %s WHERE id = %s", [self.env.ref('base.USD').id, self.env.company.id]) + self.env['res.currency.rate'].search([]).unlink() + self.env['res.currency.rate'].create({ + 'currency_id': self.env.ref('base.EUR').id, + 'company_id': self.env.company.id, + 'rate': 2.0, + 'name': '2010-01-01', + }) + + expense = self.env['hr.expense.sheet'].create({ + 'name': 'Expense for Dick Tracy', + 'employee_id': self.expense_employee.id, + }) + tax = self.env['account.tax'].create({ + 'name': 'Expense 10%', + 'amount': 10, + 'amount_type': 'percent', + 'type_tax_use': 'purchase', + 'price_include': True, + }) + expense_line = self.env['hr.expense'].create({ + 'name': 'Choucroute Saucisse', + 'employee_id': self.expense_employee.id, + 'product_id': self.product_a.id, + 'unit_amount': 700.00, + 'tax_ids': [(6, 0, tax.ids)], + 'sheet_id': expense.id, + 'analytic_account_id': self.analytic_account_1.id, + 'currency_id': self.env.ref('base.EUR').id, + }) + + # State should default to draft + self.assertEqual(expense.state, 'draft', 'Expense should be created in Draft state') + # Submitted to Manager + expense.action_submit_sheet() + self.assertEqual(expense.state, 'submit', 'Expense is not in Reported state') + # Approve + expense.approve_expense_sheets() + self.assertEqual(expense.state, 'approve', 'Expense is not in Approved state') + # Create Expense Entries + expense.action_sheet_move_create() + self.assertEqual(expense.state, 'post', 'Expense is not in Waiting Payment state') + self.assertTrue(expense.account_move_id.id, 'Expense Journal Entry is not created') + + # Should get this result [(0.0, 350.0, -700.0), (318.18, 0.0, 636.36), (31.82, 0.0, 63.64)] + for line in expense.account_move_id.line_ids: + if line.credit: + self.assertAlmostEqual(line.credit, 350.0) + self.assertAlmostEqual(line.amount_currency, -700.0) + self.assertEqual(len(line.analytic_line_ids), 0, "The credit move line should not have analytic lines") + self.assertFalse(line.product_id, "Product of credit move line should be false") + else: + if not line.tax_line_id == tax: + self.assertAlmostEqual(line.debit, 318.18) + self.assertAlmostEqual(line.amount_currency, 636.36) + self.assertEqual(len(line.analytic_line_ids), 1, "The debit move line should have 1 analytic lines") + self.assertEqual(line.product_id, self.product_a, "Product of debit move line should be the one from the expense") + else: + self.assertEqual(line.tax_base_amount, 318.18) + self.assertAlmostEqual(line.debit, 31.82) + self.assertAlmostEqual(line.amount_currency, 63.64) + self.assertEqual(len(line.analytic_line_ids), 0, "The tax move line should not have analytic lines") + self.assertFalse(line.product_id, "Product of tax move line should be false") + + def test_expenses_with_tax_and_lockdate(self): + ''' Test creating a journal entry for multiple expenses using taxes. A lock date is set in order to trigger + the recomputation of the taxes base amount. + ''' + self.env.company.tax_lock_date = '2020-02-01' + + expense = self.env['hr.expense.sheet'].create({ + 'name': 'Expense for John Smith', + 'employee_id': self.expense_employee.id, + 'accounting_date': '2020-01-01' + }) + + for i in range(2): + expense_line = 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, + 'tax_ids': [(6, 0, [self.tax_purchase_a.id])], + 'sheet_id': expense.id, + 'analytic_account_id': self.analytic_account_1.id, + }) + expense_line._onchange_product_id_date_account_id() + + expense.action_submit_sheet() + expense.approve_expense_sheets() + + # Assert not "Cannot create unbalanced journal entry" error. + expense.action_sheet_move_create() + + def test_reconcile_payment(self): + tax = self.env['account.tax'].create({ + 'name': 'tax abc', + 'type_tax_use': 'purchase', + 'amount_type': 'percent', + 'amount': 15, + 'price_include': False, + 'include_base_amount': False, + 'tax_exigibility': 'on_payment' + }) + current_assets_type = self.env.ref('account.data_account_type_current_assets') + company = self.env.company.id + tax.cash_basis_transition_account_id = self.env['account.account'].create({ + 'name': "test", + 'code': 999991, + 'reconcile': True, + 'user_type_id': current_assets_type.id, + 'company_id': company, + }).id + + sheet = self.env['hr.expense.sheet'].create({ + 'company_id': company, + 'employee_id': self.expense_employee.id, + 'name': 'test sheet', + 'expense_line_ids': [ + (0, 0, { + 'name': 'expense_1', + 'date': '2016-01-01', + 'product_id': self.product_a.id, + 'unit_amount': 10.0, + 'employee_id': self.expense_employee.id, + 'tax_ids': tax + }), + (0, 0, { + 'name': 'expense_2', + 'date': '2016-01-01', + 'product_id': self.product_a.id, + 'unit_amount': 1.0, + 'employee_id': self.expense_employee.id, + 'tax_ids': tax + }), + ], + }) + + + #actions + sheet.action_submit_sheet() + sheet.approve_expense_sheets() + sheet.action_sheet_move_create() + action_data = sheet.action_register_payment() + wizard = Form(self.env['account.payment.register'].with_context(action_data['context'])).save() + wizard.action_create_payments() + self.assertEqual(sheet.state, 'done', 'all account.move.line linked to expenses must be reconciled after payment') diff --git a/addons/hr_expense/tests/test_expenses_access_rights.py b/addons/hr_expense/tests/test_expenses_access_rights.py new file mode 100644 index 00000000..01043a73 --- /dev/null +++ b/addons/hr_expense/tests/test_expenses_access_rights.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.addons.hr_expense.tests.common import TestExpenseCommon +from odoo.exceptions import AccessError, UserError +from odoo.tests import tagged + + +@tagged('-at_install', 'post_install') +class TestExpensesAccessRights(TestExpenseCommon): + + def test_expense_access_rights(self): + ''' The expense employee can't be able to create an expense for someone else.''' + + expense_employee_2 = self.env['hr.employee'].create({ + 'name': 'expense_employee_2', + 'user_id': self.env.user.id, + 'address_home_id': self.env.user.partner_id.id, + 'address_id': self.env.user.partner_id.id, + }) + + with self.assertRaises(AccessError): + self.env['hr.expense'].with_user(self.expense_user_employee).create({ + 'name': "Superboy costume washing", + 'employee_id': expense_employee_2.id, + 'product_id': self.product_a.id, + 'quantity': 1, + 'unit_amount': 1, + }) + + def test_expense_sheet_access_rights_approve(self): + + # The expense employee is able to a create an expense sheet. + + expense_sheet = self.env['hr.expense.sheet'].with_user(self.expense_user_employee).create({ + 'name': 'First Expense for employee', + 'employee_id': self.expense_employee.id, + 'journal_id': self.company_data['default_journal_purchase'].id, + 'accounting_date': '2017-01-01', + 'expense_line_ids': [ + (0, 0, { + # Expense without foreign currency but analytic account. + 'name': 'expense_1', + 'date': '2016-01-01', + 'product_id': self.product_a.id, + 'unit_amount': 1000.0, + 'employee_id': self.expense_employee.id, + }), + ], + }) + self.assertRecordValues(expense_sheet, [{'state': 'draft'}]) + + # The expense employee is able to submit the expense sheet. + + expense_sheet.with_user(self.expense_user_employee).action_submit_sheet() + self.assertRecordValues(expense_sheet, [{'state': 'submit'}]) + + # The expense employee is not able to approve itself the expense sheet. + + with self.assertRaises(UserError): + expense_sheet.with_user(self.expense_user_employee).approve_expense_sheets() + self.assertRecordValues(expense_sheet, [{'state': 'submit'}]) + + # An expense manager is required for this step. + + expense_sheet.with_user(self.expense_user_manager).approve_expense_sheets() + self.assertRecordValues(expense_sheet, [{'state': 'approve'}]) + + # An expense manager is not able to create the journal entry. + + with self.assertRaises(UserError): + expense_sheet.with_user(self.expense_user_manager).action_sheet_move_create() + self.assertRecordValues(expense_sheet, [{'state': 'approve'}]) + + # An expense manager having accounting access rights is able to create the journal entry. + + expense_sheet.with_user(self.env.user).action_sheet_move_create() + self.assertRecordValues(expense_sheet, [{'state': 'post'}]) + + def test_expense_sheet_access_rights_refuse(self): + + # The expense employee is able to a create an expense sheet. + + expense_sheet = self.env['hr.expense.sheet'].with_user(self.expense_user_employee).create({ + 'name': 'First Expense for employee', + 'employee_id': self.expense_employee.id, + 'journal_id': self.company_data['default_journal_purchase'].id, + 'accounting_date': '2017-01-01', + 'expense_line_ids': [ + (0, 0, { + # Expense without foreign currency but analytic account. + 'name': 'expense_1', + 'date': '2016-01-01', + 'product_id': self.product_a.id, + 'unit_amount': 1000.0, + 'employee_id': self.expense_employee.id, + }), + ], + }) + self.assertRecordValues(expense_sheet, [{'state': 'draft'}]) + + # The expense employee is able to submit the expense sheet. + + expense_sheet.with_user(self.expense_user_employee).action_submit_sheet() + self.assertRecordValues(expense_sheet, [{'state': 'submit'}]) + + # The expense employee is not able to refuse itself the expense sheet. + + with self.assertRaises(UserError): + expense_sheet.with_user(self.expense_user_employee).refuse_sheet('') + self.assertRecordValues(expense_sheet, [{'state': 'submit'}]) + + # An expense manager is required for this step. + + expense_sheet.with_user(self.expense_user_manager).refuse_sheet('') + self.assertRecordValues(expense_sheet, [{'state': 'cancel'}]) diff --git a/addons/hr_expense/tests/test_expenses_mail_import.py b/addons/hr_expense/tests/test_expenses_mail_import.py new file mode 100644 index 00000000..9f6db49a --- /dev/null +++ b/addons/hr_expense/tests/test_expenses_mail_import.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.addons.hr_expense.tests.common import TestExpenseCommon +from odoo.tests import tagged + + +@tagged('-at_install', 'post_install') +class TestExpensesMailImport(TestExpenseCommon): + + @classmethod + def setUpClass(cls, chart_template_ref=None): + super().setUpClass(chart_template_ref=chart_template_ref) + + cls.product_a.default_code = 'product_a' + cls.product_b.default_code = 'product_b' + + def test_import_expense_from_email(self): + message_parsed = { + 'message_id': "the-world-is-a-ghetto", + 'subject': '%s %s' % (self.product_a.default_code, self.product_a.standard_price), + 'email_from': self.expense_user_employee.email, + 'to': 'catchall@yourcompany.com', + 'body': "Don't you know, that for me, and for you", + 'attachments': [], + } + + expense = self.env['hr.expense'].message_new(message_parsed) + + self.assertRecordValues(expense, [{ + 'product_id': self.product_a.id, + 'total_amount': 920.0, + 'employee_id': self.expense_employee.id, + }]) + + def test_import_expense_from_email_no_product(self): + message_parsed = { + 'message_id': "the-world-is-a-ghetto", + 'subject': 'no product code 800', + 'email_from': self.expense_user_employee.email, + 'to': 'catchall@yourcompany.com', + 'body': "Don't you know, that for me, and for you", + 'attachments': [], + } + + expense = self.env['hr.expense'].message_new(message_parsed) + + self.assertRecordValues(expense, [{ + 'product_id': False, + 'total_amount': 800.0, + 'employee_id': self.expense_employee.id, + }]) + + def test_import_expense_from_mail_parsing_subjects(self): + + def assertParsedValues(subject, currencies, exp_description, exp_amount, exp_product): + product, amount, currency_id, description = self.env['hr.expense']\ + .with_user(self.expense_user_employee)\ + ._parse_expense_subject(subject, currencies) + + self.assertEqual(product, exp_product) + self.assertAlmostEqual(amount, exp_amount) + self.assertEqual(description, exp_description) + + # Without Multi currency access + assertParsedValues( + "product_a bar $1205.91 electro wizard", + self.company_data['currency'], + "bar electro wizard", + 1205.91, + self.product_a, + ) + + # subject having other currency then company currency, it should ignore other currency then company currency + assertParsedValues( + "foo bar %s1406.91 royal giant" % self.currency_data['currency'].symbol, + self.company_data['currency'], + "foo bar %s royal giant" % self.currency_data['currency'].symbol, + 1406.91, + self.env['product.product'], + ) + + # With Multi currency access + self.expense_user_employee.groups_id |= self.env.ref('base.group_multi_currency') + + assertParsedValues( + "product_a foo bar $2205.92 elite barbarians", + self.company_data['currency'], + "foo bar elite barbarians", + 2205.92, + self.product_a, + ) + + # subject having other currency then company currency, it should accept other currency because multi currency is activated + assertParsedValues( + "product_a %s2510.90 chhota bheem" % self.currency_data['currency'].symbol, + self.company_data['currency'] + self.currency_data['currency'], + "chhota bheem", + 2510.90, + self.product_a, + ) + + # subject without product and currency, should take company currency and default product + assertParsedValues( + "foo bar 109.96 spear goblins", + self.company_data['currency'] + self.currency_data['currency'], + "foo bar spear goblins", + 109.96, + self.env['product.product'], + ) + + # subject with currency symbol at end + assertParsedValues( + "product_a foo bar 2910.94$ inferno dragon", + self.company_data['currency'] + self.currency_data['currency'], + "foo bar inferno dragon", + 2910.94, + self.product_a, + ) + + # subject with no amount and product + assertParsedValues( + "foo bar mega knight", + self.company_data['currency'] + self.currency_data['currency'], + "foo bar mega knight", + 0.0, + self.env['product.product'], + ) + + # price with a comma + assertParsedValues( + "foo bar 291,56$ mega knight", + self.company_data['currency'] + self.currency_data['currency'], + "foo bar mega knight", + 291.56, + self.env['product.product'], + ) + + # price without decimals + assertParsedValues( + "foo bar 291$ mega knight", + self.company_data['currency'] + self.currency_data['currency'], + "foo bar mega knight", + 291.0, + self.env['product.product'], + ) + + assertParsedValues( + "product_a foo bar 291.5$ mega knight", + self.company_data['currency'] + self.currency_data['currency'], + "foo bar mega knight", + 291.5, + self.product_a, + ) diff --git a/addons/hr_expense/tests/test_expenses_multi_company.py b/addons/hr_expense/tests/test_expenses_multi_company.py new file mode 100644 index 00000000..9ad54908 --- /dev/null +++ b/addons/hr_expense/tests/test_expenses_multi_company.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.addons.hr_expense.tests.common import TestExpenseCommon +from odoo.tests import tagged +from odoo.exceptions import UserError + + +@tagged('post_install', '-at_install') +class TestExpenseMultiCompany(TestExpenseCommon): + + def test_expense_sheet_multi_company_approve(self): + self.expense_employee.company_id = self.company_data_2['company'] + + # The expense employee is able to a create an expense sheet for company_2. + + expense_sheet = self.env['hr.expense.sheet']\ + .with_user(self.expense_user_employee)\ + .with_context(allowed_company_ids=self.company_data_2['company'].ids)\ + .create({ + 'name': 'First Expense for employee', + 'employee_id': self.expense_employee.id, + 'journal_id': self.company_data_2['default_journal_purchase'].id, + 'accounting_date': '2017-01-01', + 'expense_line_ids': [ + (0, 0, { + # Expense without foreign currency but analytic account. + 'name': 'expense_1', + 'date': '2016-01-01', + 'product_id': self.product_a.id, + 'unit_amount': 1000.0, + 'employee_id': self.expense_employee.id, + }), + ], + }) + self.assertRecordValues(expense_sheet, [{'company_id': self.company_data_2['company'].id}]) + + # The expense employee is able to submit the expense sheet. + + expense_sheet.with_user(self.expense_user_employee).action_submit_sheet() + + # An expense manager is not able to approve without access to company_2. + + with self.assertRaises(UserError): + expense_sheet\ + .with_user(self.expense_user_manager)\ + .with_context(allowed_company_ids=self.company_data['company'].ids)\ + .approve_expense_sheets() + + # An expense manager is able to approve with access to company_2. + + expense_sheet\ + .with_user(self.expense_user_manager)\ + .with_context(allowed_company_ids=self.company_data_2['company'].ids)\ + .approve_expense_sheets() + + # An expense manager having accounting access rights is not able to create the journal entry without access + # to company_2. + + with self.assertRaises(UserError): + expense_sheet\ + .with_user(self.env.user)\ + .with_context(allowed_company_ids=self.company_data['company'].ids)\ + .action_sheet_move_create() + + # An expense manager having accounting access rights is able to create the journal entry with access to + # company_2. + + expense_sheet\ + .with_user(self.env.user)\ + .with_context(allowed_company_ids=self.company_data_2['company'].ids)\ + .action_sheet_move_create() + + def test_expense_sheet_multi_company_refuse(self): + self.expense_employee.company_id = self.company_data_2['company'] + + # The expense employee is able to a create an expense sheet for company_2. + + expense_sheet = self.env['hr.expense.sheet']\ + .with_user(self.expense_user_employee)\ + .with_context(allowed_company_ids=self.company_data_2['company'].ids)\ + .create({ + 'name': 'First Expense for employee', + 'employee_id': self.expense_employee.id, + 'journal_id': self.company_data_2['default_journal_purchase'].id, + 'accounting_date': '2017-01-01', + 'expense_line_ids': [ + (0, 0, { + # Expense without foreign currency but analytic account. + 'name': 'expense_1', + 'date': '2016-01-01', + 'product_id': self.product_a.id, + 'unit_amount': 1000.0, + 'employee_id': self.expense_employee.id, + }), + ], + }) + self.assertRecordValues(expense_sheet, [{'company_id': self.company_data_2['company'].id}]) + + # The expense employee is able to submit the expense sheet. + + expense_sheet.with_user(self.expense_user_employee).action_submit_sheet() + + # An expense manager is not able to approve without access to company_2. + + with self.assertRaises(UserError): + expense_sheet\ + .with_user(self.expense_user_manager)\ + .with_context(allowed_company_ids=self.company_data['company'].ids)\ + .refuse_sheet('') + + # An expense manager is able to approve with access to company_2. + + expense_sheet\ + .with_user(self.expense_user_manager)\ + .with_context(allowed_company_ids=self.company_data_2['company'].ids)\ + .refuse_sheet('') |
