diff --git a/hr_timesheet_sheet/models/hr_timesheet_sheet.py b/hr_timesheet_sheet/models/hr_timesheet_sheet.py
index aa748a2..9b34f75 100644
--- a/hr_timesheet_sheet/models/hr_timesheet_sheet.py
+++ b/hr_timesheet_sheet/models/hr_timesheet_sheet.py
@@ -149,6 +149,14 @@ def _default_department_id(self):
compute="_compute_available_task_ids",
)
total_time = fields.Float(compute="_compute_total_time", store=True)
+ approver_id = fields.Many2one(
+ comodel_name="res.users",
+ string="Approver",
+ compute="_compute_approver_id",
+ help="User able to review this sheet, in addition to the users allowed "
+ "by the review policy. It is read from the employee field configured "
+ "as the approver field on the company.",
+ )
can_review = fields.Boolean(
compute="_compute_can_review", search="_search_can_review"
)
@@ -183,7 +191,18 @@ def _compute_total_time(self):
for sheet in self:
sheet.total_time = sum(sheet.mapped("timesheet_ids.unit_amount"))
- @api.depends("review_policy")
+ @api.depends("employee_id", "company_id.timesheet_sheet_approver_field_id")
+ def _compute_approver_id(self):
+ for sheet in self:
+ company = sheet.company_id or self.env.company
+ field = company.sudo().timesheet_sheet_approver_field_id
+ approver = self.env["res.users"]
+ employee = sheet.employee_id
+ if field and employee and field.name in employee._fields:
+ approver = employee[field.name]
+ sheet.approver_id = approver
+
+ @api.depends("review_policy", "approver_id")
def _compute_can_review(self):
for sheet in self:
sheet.can_review = self.env.user in sheet._get_possible_reviewers()
@@ -329,6 +348,8 @@ def _get_possible_reviewers(self):
res |= self.env.ref("hr.group_hr_manager").users
elif self.review_policy == "timesheet_manager":
res |= self.env.ref("hr_timesheet.group_hr_timesheet_approver").users
+ if self.approver_id:
+ res |= self.approver_id
return res
def _get_timesheet_sheet_company(self):
diff --git a/hr_timesheet_sheet/models/res_company.py b/hr_timesheet_sheet/models/res_company.py
index b6582fb..51715a6 100644
--- a/hr_timesheet_sheet/models/res_company.py
+++ b/hr_timesheet_sheet/models/res_company.py
@@ -37,3 +37,13 @@ class ResCompany(models.Model):
default="hr",
help="How Timesheet Sheets review is performed.",
)
+ timesheet_sheet_approver_field_id = fields.Many2one(
+ comodel_name="ir.model.fields",
+ string="Timesheet Approver Field",
+ domain="[('model', '=', 'hr.employee'), ('relation', '=', 'res.users'), "
+ "('ttype', '=', 'many2one')]",
+ ondelete="set null",
+ help="Employee field pointing to a user (res.users). The user found in "
+ "this field on the employee can review the employee's timesheet sheets, "
+ "in addition to the review policy.",
+ )
diff --git a/hr_timesheet_sheet/models/res_config.py b/hr_timesheet_sheet/models/res_config.py
index 1e932b6..120290c 100644
--- a/hr_timesheet_sheet/models/res_config.py
+++ b/hr_timesheet_sheet/models/res_config.py
@@ -25,3 +25,10 @@ class ResConfig(models.TransientModel):
timesheet_sheet_review_policy = fields.Selection(
related="company_id.timesheet_sheet_review_policy", readonly=False
)
+
+ timesheet_sheet_approver_field_id = fields.Many2one(
+ related="company_id.timesheet_sheet_approver_field_id",
+ readonly=False,
+ domain="[('model', '=', 'hr.employee'), ('relation', '=', 'res.users'), "
+ "('ttype', '=', 'many2one')]",
+ )
diff --git a/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py b/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py
index d0cb7ca..7ac7f3d 100644
--- a/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py
+++ b/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py
@@ -1003,6 +1003,21 @@ def test_review_policy_default(self):
sheet.unlink()
self.assertFalse(sheet.exists())
+ @mute_logger("odoo.models.unlink")
+ def test_approver_from_configured_field(self):
+ sheet = Form(self.sheet_model.with_user(self.user)).save()
+ # No approver field configured yet, so there is no approver.
+ self.assertFalse(sheet.approver_id)
+ # Configure which employee field designates the approver. The user set
+ # in that field on the employee becomes the approver of the sheet and
+ # can review it.
+ self.company.timesheet_sheet_approver_field_id = self.env[
+ "ir.model.fields"
+ ]._get("hr.employee", "user_id")
+ sheet.invalidate_recordset(["approver_id"])
+ self.assertEqual(sheet.approver_id, self.employee.user_id)
+ self.assertIn(self.employee.user_id, sheet._get_possible_reviewers())
+
def test_same_week_different_years(self):
sheet_form = Form(self.sheet_model.with_user(self.user))
sheet_form.date_start = date(2019, 12, 30)
diff --git a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml
index 4030f6d..47f45d9 100644
--- a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml
+++ b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml
@@ -108,6 +108,7 @@
+
diff --git a/hr_timesheet_sheet/views/res_config_settings_views.xml b/hr_timesheet_sheet/views/res_config_settings_views.xml
index 3dcaeb4..98dcdf7 100644
--- a/hr_timesheet_sheet/views/res_config_settings_views.xml
+++ b/hr_timesheet_sheet/views/res_config_settings_views.xml
@@ -38,6 +38,12 @@
required="1"
/>
+
+
+