Files
enterprise-addons/approvals/tests/test_approvals.py
T

496 lines
21 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import Command, fields
from odoo.tests import common, Form, new_test_user
from odoo.exceptions import AccessError, UserError
class TestRequest(common.TransactionCase):
def test_compute_request_status(self):
category_test = self.env.ref('approvals.approval_category_data_business_trip')
requester_user = self.env.ref('base.user_admin')
record = self.env['approval.request'].create({
'name': 'test request',
'request_owner_id': requester_user.id,
'category_id': category_test.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
record.write({'approver_ids': [(5, 0, 0)]})
first_approver = self.env['approval.approver'].create({
'user_id': 1,
'request_id': record.id,
'status': 'new'})
second_approver = self.env['approval.approver'].create({
'user_id': 2,
'request_id': record.id,
'status': 'new'})
record.approver_ids = (first_approver | second_approver)
def assert_record_request_status_equals(expected_request_status):
"""
This helper function will be used to test 2 things:
1. The real record's expected request_status value
2. A virtual record's expected request_status, as it would be
computed in an `onchange` request with a fresh environment
"""
self.assertEqual(record.request_status, expected_request_status)
# Because we are simulating the virtual record behavior as it
# exists in the context of an `onchange` request, we should make
# sure that our environment represents that, i.e. we need a clean
# cache.
self.env.invalidate_all()
self.assertEqual(
record.new(origin=record).request_status,
expected_request_status)
assert_record_request_status_equals('new')
record.action_confirm()
# Test case 1: Min approval = 1
assert_record_request_status_equals('pending')
record.action_approve(first_approver)
assert_record_request_status_equals('approved')
record.action_approve(second_approver)
assert_record_request_status_equals('approved')
record.action_withdraw(first_approver)
assert_record_request_status_equals('approved')
record.action_refuse(first_approver)
assert_record_request_status_equals('refused')
# Test case 2: Min approval = 1
category_test.approval_minimum = 2
record.action_withdraw(first_approver)
record.action_withdraw(second_approver)
assert_record_request_status_equals('pending')
record.action_approve(first_approver)
assert_record_request_status_equals('pending')
record.action_approve(second_approver)
assert_record_request_status_equals('approved')
record.action_withdraw(second_approver)
assert_record_request_status_equals('pending')
record.action_refuse(second_approver)
assert_record_request_status_equals('refused')
# Test case 3: Check that cancel is erasing the old validations
record.action_cancel()
self.assertEqual(first_approver.status, 'cancel')
self.assertEqual(second_approver.status, 'cancel')
assert_record_request_status_equals('cancel')
# Test case 4: Set the approval request to draft
record.action_draft()
self.assertEqual(first_approver.status, 'new')
self.assertEqual(second_approver.status, 'new')
assert_record_request_status_equals('new')
# Test case 5: Set min approval to an impossible value to reach
category_test.approval_minimum = 3
with self.assertRaises(UserError):
record.action_confirm()
assert_record_request_status_equals('new')
def test_compute_request_status_with_required(self):
category_test = self.env.ref('approvals.approval_category_data_business_trip')
requester_user = self.env.ref('base.user_admin')
record = self.env['approval.request'].create({
'name': 'test request',
'request_owner_id': requester_user.id,
'category_id': category_test.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
record.write({'approver_ids': [(5, 0, 0)]})
first_approver = self.env['approval.approver'].create({
'user_id': 1,
'request_id': record.id,
'status': 'new',
'required': True})
second_approver = self.env['approval.approver'].create({
'user_id': 2,
'request_id': record.id,
'status': 'new'})
record.approver_ids = (first_approver | second_approver)
self.assertEqual(record.request_status, 'new')
record.action_confirm()
# Min approval = 1 but first approver IS required
self.assertEqual(record.request_status, 'pending')
record.action_approve(second_approver)
# Min approval is met but required approvals are not
self.assertEqual(record.request_status, 'pending')
record.action_approve(first_approver)
self.assertEqual(record.request_status, 'approved')
# Min approval = 2
category_test.approval_minimum = 2
record.action_withdraw(first_approver)
record.action_withdraw(second_approver)
self.assertEqual(record.request_status, 'pending')
record.action_approve(first_approver)
# All required approvals are met but not the minimal approval count
self.assertEqual(record.request_status, 'pending')
record.action_approve(second_approver)
self.assertEqual(record.request_status, 'approved')
def test_product_line_compute_uom(self):
category_test = self.env.ref('approvals.approval_category_data_business_trip')
uom = self.env.ref('uom.product_uom_dozen')
product = self.env['product.product'].create({
'name': 'foo',
'uom_id': uom.id,
})
approval = self.env['approval.request'].create({
'category_id': category_test.id,
'product_line_ids': [
Command.create({'product_id': product.id})
],
})
self.assertEqual(approval.product_line_ids.description, 'foo')
self.assertEqual(approval.product_line_ids.product_uom_id, uom)
def test_unlink_approval(self):
"""
There is no error when unlinking a draft request with a document attached
or a binary field filled.
"""
approval = self.env['approval.request'].create({
'name': 'test request',
'category_id': self.env.ref('approvals.approval_category_data_business_trip').id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
self.env['ir.attachment'].create({
'name': 'test.file',
'res_id': approval.id,
'res_model': 'approval.request',
})
self.env['ir.model.fields'].create({
'name': 'x_test_field',
'model_id': self.env.ref('approvals.model_approval_request').id,
'ttype': 'binary',
})
approval.x_test_field = 'test'
approval.unlink()
def test_unlink_multiple_approvals_with_product_line(self):
"""
There is no error when unlinking a multiple approval requests with a
product line.
"""
approvals = self.env['approval.request'].create([{
'name': 'Approval Request 1',
'category_id': self.env.ref('approvals.approval_category_data_borrow_items').id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland',
}, {
'name': 'Approval Request 1',
'category_id': self.env.ref('approvals.approval_category_data_borrow_items').id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testitems',
}])
product_line = self.env['approval.product.line'].create({
'approval_request_id': approvals[0].id,
'description': "Description",
})
approvals.unlink()
self.assertFalse(product_line.exists())
self.assertFalse(approvals.exists())
def test_request_with_automated_sequence(self):
approval_category = self.env['approval.category'].create({
'name': 'Test Category',
'automated_sequence': True,
'sequence_code': '1234',
})
request_form = Form(self.env['approval.request'])
request_form.category_id = approval_category
approval_request = request_form.save()
self.assertEqual( approval_request.name, '123400001')
def test_approval_request_change_category(self):
user1 = new_test_user(self.env, login='user1')
user2 = new_test_user(self.env, login='user2')
category1 = self.env['approval.category'].create({
'name': 'Test category 1',
'approver_ids': [
Command.create({'user_id': user1.id}),
Command.create({'user_id': user2.id}),
]
})
category2 = self.env['approval.category'].create({
'name': 'Test category 2',
'approver_ids': [
Command.create({'user_id': user1.id})
]
})
approval = self.env['approval.request'].create({
'name': 'Test request',
'category_id': category1.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
self.assertEqual(approval.approver_ids.user_id, (user1 + user2))
approval.write({
'category_id': category2.id
})
self.assertEqual(approval.approver_ids.user_id, user1)
def test_approval_request_write_approved(self):
user_1 = new_test_user(self.env, login="user 1", groups="base.group_user")
user_2 = new_test_user(self.env, login="user 2", groups="base.group_user")
category_test = self.env.ref('approvals.approval_category_data_business_trip')
record = self.env['approval.request'].create({
'name': 'test request',
'request_owner_id': user_1.id,
'category_id': category_test.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
first_approver = self.env['approval.approver'].create({
'user_id': user_2.id,
'request_id': record.id,
'status': 'new'
})
record.approver_ids = first_approver
# approval owner can write on his approval
record.with_user(user_1).write({'amount': 10})
record.action_confirm()
self.assertEqual(record.request_status, 'pending')
record.action_approve(first_approver)
self.assertEqual(record.request_status, 'approved')
# approval owner cannot write on approved approval
with self.assertRaises(AccessError):
record.with_user(user_1).write({'amount': 20})
record.with_user(user_2).write({'amount': 20})
# approval owner can cancel
record.with_user(user_1).write({'request_status': 'cancel'})
self.assertEqual(record.request_status, 'cancel')
record.action_draft()
self.assertEqual(record.request_status, 'new')
# approval owner cannot approved his own approval
with self.assertRaises(AccessError):
record.with_user(user_1).write({'request_status': 'approved'})
def test_approval_approvers_access(self):
user1 = new_test_user(self.env, login='user1')
user2 = new_test_user(self.env, login='user2')
user3 = new_test_user(self.env, login='user3', groups='approvals.group_approval_user')
category1 = self.env['approval.category'].create({
'name': 'Test category 1',
'company_id': user1.company_id.id,
'approver_ids': [
Command.create({'user_id': user2.id}),
]
})
approval = self.env['approval.request'].with_user(user1).create({
'name': 'Test request',
'request_owner_id': user1.id,
'category_id': category1.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
# Only an officer can edit an approver
with self.assertRaises(AccessError):
approval.approver_ids.with_user(user1).write({'required': True})
approval.approver_ids.with_user(user3).write({'required': True})
self.assertTrue(approval.approver_ids.required)
# Only an officer can add an approver to the request
with self.assertRaises(AccessError):
self.env['approval.approver'].with_user(user1).create({'user_id': user3.id, 'request_id': approval.id})
self.env['approval.approver'].with_user(user3).create({'user_id': user3.id, 'request_id': approval.id})
self.assertEqual(len(approval.approver_ids), 2)
approver2 = approval.approver_ids.filtered(lambda a: a.user_id.id == user2.id)
approver3 = approval.approver_ids.filtered(lambda a: a.user_id.id == user3.id)
# user1 cannot approve the user 2 approver, but user 2 can
with self.assertRaises(AccessError):
approver2.with_user(user1).action_approve()
approver2.with_user(user2).action_approve()
self.assertEqual(approver2.status, 'approved')
# Officer can access, and user2 can access because they are the approver
approver2.with_user(user2).read()
approver2.with_user(user3).read()
# Only officer can read the approvers
with self.assertRaises(AccessError):
approver3.with_user(user2).read()
approver3.with_user(user3).read()
# Only officer can unlink an approver
with self.assertRaises(AccessError):
approver3.with_user(user1).unlink()
approver3.with_user(user3).unlink()
self.assertEqual(approval.approver_ids.user_id.id, user2.id)
def test_consistency_between_request_and_approver(self):
user = new_test_user(self.env, login='user1', groups='base.group_user')
admin = new_test_user(self.env, login='admin1', groups='approvals.group_approval_manager')
admin_env = self.env(user=admin)
category1 = self.env['approval.category'].create({
'name': 'Test category 1',
'approver_ids': [
Command.create({'user_id': admin.id}),
]
})
private_approval = admin_env['approval.request'].create({
'name': 'Test request (admin)',
'request_owner_id': admin.id,
'category_id': category1.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
approval = admin_env['approval.request'].create({
'name': 'Test request',
'request_owner_id': admin.id,
'category_id': category1.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
user_approver = admin_env['approval.approver'].create({
'user_id': user.id,
'request_id': approval.id,
})
with self.assertRaises(AccessError):
user_approver.with_user(user).request_id = private_approval
# As admin, create an approver for your own approval with user
user_approver_for_admin = admin_env['approval.approver'].create({
'user_id': user.id,
'request_id': private_approval.id
})
user_approval = admin_env['approval.request'].create({
'name': 'Test request',
'request_owner_id': user.id,
'category_id': category1.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
# As user, try to move your own approver on your own request
with self.assertRaises(AccessError):
user_approver_for_admin.with_user(user).request_id = user_approval
# As user, move your own approver on the same request
user_approver_for_admin.with_user(user).request_id = private_approval.id
# Create an approver without request
user_approver = self.env['approval.approver'].create({
'user_id': user.id,
})
# Move it to a request
user_approver.request_id = approval.id
def test_employee_in_user_company(self):
'''Ensure that the correct manager is added as an approver.
'''
user = new_test_user(self.env, login='user1', groups='base.group_user')
manager1 = new_test_user(self.env, login='manager1', groups='approvals.group_approval_manager')
manager2 = new_test_user(self.env, login='manager2', groups='approvals.group_approval_manager')
admin = new_test_user(self.env, login='admin1', groups='approvals.group_approval_manager')
admin_env = self.env(user=admin)
company2 = self.env['res.company'].create({'name': 'Wrong Company'})
# When incorrect employee is added first, it is selected first.
employee_manager1 = self.env['hr.employee'].create({
'user_id': manager1.id,
})
employee_manager2 = self.env['hr.employee'].create({
'user_id': manager2.id,
})
employee_user_wrong_company = self.env['hr.employee'].create({
'user_id': user.id,
'parent_id': employee_manager2.id,
'company_id': company2.id,
})
employee_user_correct_company = self.env['hr.employee'].create({
'user_id': user.id,
'parent_id': employee_manager1.id,
'company_id': user.company_id.id,
})
category1 = self.env['approval.category'].create({
'name': 'Test category 1',
'approver_ids': [
Command.create({'user_id': admin.id}),
],
'manager_approval': 'approver',
})
approval = admin_env['approval.request'].create({
'name': 'Test request',
'request_owner_id': user.id,
'category_id': category1.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland'
})
self.assertTrue(employee_user_correct_company.parent_id.user_id in approval.approver_ids.user_id)
self.assertTrue(employee_user_wrong_company.parent_id.user_id not in approval.approver_ids.user_id)
def test_cancel_approver_status_as_non_privileged_user(self):
"""
Ensure action_cancel does not raise an AccessError when called by a
non-privileged user. Previously, writing 'cancel' on approver_ids without
sudo caused an AccessError.
"""
user_1 = new_test_user(self.env, login='user1', groups='base.group_user')
user_2 = new_test_user(self.env, login='admin1', groups='approvals.group_approval_manager')
category_test = self.env.ref('approvals.approval_category_data_business_trip')
record = self.env['approval.request'].create({
'name': 'test cancel request',
'request_owner_id': user_1.id,
'category_id': category_test.id,
'date_start': fields.Datetime.now(),
'date_end': fields.Datetime.now(),
'location': 'testland',
})
first_approver = self.env['approval.approver'].create({
'user_id': user_2.id,
'request_id': record.id,
'status': 'new',
})
record.approver_ids = first_approver
record.action_confirm()
self.assertEqual(record.request_status, 'pending')
# The approval owner (a plain internal user) cancels the request.
# Before the fix this raised AccessError because writing on approver_ids
# was done without sudo. The fix uses sudo() so this must not raise.
record.with_user(user_1).action_cancel()
# Approver status must be 'cancel' after the sudo write
self.assertEqual(first_approver.status, 'cancel')
self.assertEqual(record.request_status, 'cancel')