diff --git a/addons/hr/models/hr_employee_public.py b/addons/hr/models/hr_employee_public.py index fc4a3142036..3e434733cd1 100644 --- a/addons/hr/models/hr_employee_public.py +++ b/addons/hr/models/hr_employee_public.py @@ -32,6 +32,9 @@ class HrEmployeePublic(models.Model): tz = fields.Selection(readonly=True) color = fields.Integer(readonly=True) + # Manager-only fields + is_manager = fields.Boolean(compute='_compute_is_manager') + employee_id = fields.Many2one('hr.employee', 'Employee', compute="_compute_employee_id", search="_search_employee_id", compute_sudo=True) # hr.employee.public specific fields child_ids = fields.One2many('hr.employee.public', 'parent_id', string='Direct subordinates', readonly=True) @@ -49,6 +52,28 @@ class HrEmployeePublic(models.Model): coach_id = fields.Many2one('hr.employee.public', 'Coach', readonly=True) user_partner_id = fields.Many2one(related='user_id.partner_id', related_sudo=False, string="User's partner") + @api.depends_context('uid') + @api.depends('parent_id') + def _compute_is_manager(self): + all_reports = self.env['hr.employee.public'].search([('id', 'child_of', self.env.user.employee_id.id)]).ids + for employee in self: + employee.is_manager = employee.id in all_reports + + def _get_manager_only_fields(self): + return [] + + @api.depends_context('uid') + def _compute_manager_only_fields(self): + manager_fields = self._get_manager_only_fields() + for employee in self: + if employee.is_manager: + employee_sudo = employee.employee_id.sudo() + for f in manager_fields: + employee[f] = employee_sudo[f] + else: + for f in manager_fields: + employee[f] = False + def _search_employee_id(self, operator, value): return [('id', operator, value)] diff --git a/addons/hr_contract/models/hr_employee.py b/addons/hr_contract/models/hr_employee.py index dfed6e942c8..bf025f557c3 100644 --- a/addons/hr_contract/models/hr_employee.py +++ b/addons/hr_contract/models/hr_employee.py @@ -7,6 +7,18 @@ from datetime import date, datetime, time from odoo import api, fields, models from odoo.osv import expression +class EmployeePublic(models.Model): + _inherit = 'hr.employee.public' + + first_contract_date = fields.Date(compute='_compute_manager_only_fields', search='_search_first_contract_date') + + def _get_manager_only_fields(self): + return super()._get_manager_only_fields() + ['first_contract_date'] + + def _search_first_contract_date(self, operator, value): + employees = self.env['hr.employee'].sudo().search([('id', 'child_of', self.env.user.employee_id.ids), ('first_contract_date', operator, value)]) + return [('id', 'in', employees.ids)] + class Employee(models.Model): _inherit = "hr.employee" diff --git a/addons/hr_contract/tests/__init__.py b/addons/hr_contract/tests/__init__.py index 6f1137322aa..353b82263a3 100644 --- a/addons/hr_contract/tests/__init__.py +++ b/addons/hr_contract/tests/__init__.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import test_access from . import test_auto_status from . import test_contract from . import test_calendar_sync diff --git a/addons/hr_contract/tests/test_access.py b/addons/hr_contract/tests/test_access.py new file mode 100644 index 00000000000..15f91b93bd2 --- /dev/null +++ b/addons/hr_contract/tests/test_access.py @@ -0,0 +1,92 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.tests.common import TransactionCase + +from odoo.addons.mail.tests.common import mail_new_test_user + +class TestContractPublicAccess(TransactionCase): + + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.company = cls.env['res.company'].create({'name': 'mami rock'}) + cls.manager_user = mail_new_test_user( + cls.env, + name='manager_user', + login='manager_user', + email='manager_user@example.com', + notification_type='email', + groups='base.group_user', + company_id=cls.company.id, + ) + + cls.manager = cls.env['hr.employee'].create({ + 'name': 'Johnny', + 'user_id': cls.manager_user.id, + 'company_id': cls.company.id, + }) + + cls.employee_a, cls.employee_b = cls.env['hr.employee'].create([{ + 'name': 'David', + 'parent_id': cls.manager.id, + 'company_id': cls.company.id, + }, { + 'name': 'Laura', + 'company_id': cls.company.id, + }]) + cls.employee_c = cls.env['hr.employee'].create({ + 'name': 'Jade', + 'parent_id': cls.employee_a.id, + 'company_id': cls.company.id, + }) + + cls.contract_a, cls.contract_b, cls.contract_c = cls.env['hr.contract'].create([{ + 'name': 'contract johnny', + 'employee_id': cls.employee_a.id, + 'state': 'open', + 'wage': 1, + 'date_start': '2017-12-05', + 'company_id': cls.company.id, + }, { + 'name': 'contract laura', + 'employee_id': cls.employee_b.id, + 'state': 'open', + 'wage': 1, + 'date_start': '2018-12-05', + 'company_id': cls.company.id, + }, { + 'name': 'contract jade', + 'employee_id': cls.employee_c.id, + 'state': 'open', + 'wage': 1, + 'date_start': '2019-12-05', + 'company_id': cls.company.id, + }]) + + def test_manager(self): + with self.with_user(self.manager_user.login): + david, laura, jade = self.env['hr.employee.public'].browse((self.employee_a | self.employee_b | self.employee_c).ids) + + self.assertTrue(david.is_manager) + self.assertFalse(laura.is_manager) + self.assertTrue(jade.is_manager) + + def test_manager_access_read(self): + with self.with_user(self.manager_user.login): + david, laura, jade = self.env['hr.employee.public'].browse((self.employee_a | self.employee_b | self.employee_c).ids) + + # Should be able to read direct reports and indirect reports first_contract_date + self.assertEqual(str(david.first_contract_date), '2017-12-05') + self.assertEqual(str(jade.first_contract_date), '2019-12-05') + + # Cannot read on an employee the user is not manager of + self.assertFalse(laura.first_contract_date) + + def test_manager_access_search(self): + with self.with_user(self.manager_user.login): + employees = self.env['hr.employee.public'].search([('first_contract_date', '>=', '2017-12-05')]) + + # Should not find Laura as the user is not her manager + self.assertEqual(len(employees), 2) + self.assertTrue('Laura' not in employees.mapped('name')) diff --git a/addons/hr_contract/views/hr_employee_views.xml b/addons/hr_contract/views/hr_employee_views.xml index 3688e440ec3..5be383ed5b4 100644 --- a/addons/hr_contract/views/hr_employee_views.xml +++ b/addons/hr_contract/views/hr_employee_views.xml @@ -34,4 +34,15 @@ + + + hr.employee.public + + + + + + + +