diff --git a/odex25_hr/exp_hr_appraisal/i18n/ar_001.po b/odex25_hr/exp_hr_appraisal/i18n/ar_001.po
index dac66f02d..61e984c90 100644
--- a/odex25_hr/exp_hr_appraisal/i18n/ar_001.po
+++ b/odex25_hr/exp_hr_appraisal/i18n/ar_001.po
@@ -15,6 +15,16 @@ msgstr ""
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
+#. module: exp_hr_appraisal
+#: model:ir.model.fields,field_description:exp_hr_appraisal.field_customize_complete_appraisal__accrued_degree_id
+msgid "Accrued Degree"
+msgstr "الدرجة المستحقة"
+
+#. module: exp_hr_appraisal
+#: model:ir.model.fields,field_description:exp_hr_appraisal.field_standard_appraisal_line__accrued_greed
+msgid "Accrued Greed"
+msgstr "الدرجة المستحقة"
+
#. module: exp_hr_appraisal
#: model:ir.model.fields,field_description:exp_hr_appraisal.field_appraisal_degree__message_needaction
#: model:ir.model.fields,field_description:exp_hr_appraisal.field_appraisal_plan__message_needaction
@@ -188,6 +198,11 @@ msgstr "خطة التقييم"
msgid "Appraisal result"
msgstr "نتيجة التقييم"
+#. module: exp_hr_appraisal
+#: model_terms:ir.ui.view,arch_db:exp_hr_appraisal.hr_appraisal_form_view
+msgid "Approve"
+msgstr "إعتماد"
+
#. module: exp_hr_appraisal
#: model:ir.model.fields,field_description:exp_hr_appraisal.field_appraisal_degree__message_attachment_count
#: model:ir.model.fields,field_description:exp_hr_appraisal.field_appraisal_plan__message_attachment_count
@@ -396,11 +411,23 @@ msgstr "الموظف"
msgid "Employee Appraisal"
msgstr "تقيمات الموظف"
+#. module: exp_hr_appraisal
+#: model:ir.model.fields.selection,name:exp_hr_appraisal.selection__hr_employee_appraisal__state__employee_confirmation
+msgid "Employee Confirmation"
+msgstr "موافقة الموظف"
+
#. module: exp_hr_appraisal
#: model:ir.model,name:exp_hr_appraisal.model_hr_contract
msgid "Employee Contract"
msgstr "عقد الموظف"
+#. module: exp_hr_appraisal
+#: model:ir.model.fields,field_description:exp_hr_appraisal.field_hr_employee_appraisal__employee_protest
+#: model:ir.model.fields,field_description:exp_hr_appraisal.field_hr_group_employee_appraisal__employee_protest
+#: model:ir.model.fields,field_description:exp_hr_appraisal.field_manager_appraisal_complete_line__has_employee_protest
+msgid "Employee Protest"
+msgstr "السماح للموظف بالإعتراض"
+
#. module: exp_hr_appraisal
#: model_terms:ir.ui.view,arch_db:exp_hr_appraisal.employee_appraisal_form_view
#: model_terms:ir.ui.view,arch_db:exp_hr_appraisal.hr_appraisal_form_view
@@ -875,6 +902,18 @@ msgstr ""
msgid "Number of unread messages"
msgstr ""
+#. module: exp_hr_appraisal
+#: code:addons/exp_hr_appraisal/models/appraisal.py:0
+#, python-format
+msgid "Only %s should approve this appraisal!"
+msgstr "فقط %s من يجب أن يوافق على هذا!"
+
+#. module: exp_hr_appraisal
+#: code:addons/exp_hr_appraisal/models/appraisal.py:0
+#, python-format
+msgid "Only %s should reject this appraisal!"
+msgstr "فقط %s من يجب أن يرفض هذا!"
+
#. module: exp_hr_appraisal
#: model:ir.model.fields.selection,name:exp_hr_appraisal.selection__appraisal_setting__appraisal_type__other
#: model:ir.model.fields.selection,name:exp_hr_appraisal.selection__hr_employee_appraisal__appraisal_type__other
@@ -946,6 +985,16 @@ msgstr "اعادة حساب التقييم"
msgid "Re-draft"
msgstr "إرجاع لمبدئي"
+#. module: exp_hr_appraisal
+#: model_terms:ir.ui.view,arch_db:exp_hr_appraisal.hr_appraisal_form_view
+msgid "Reject"
+msgstr "رفض"
+
+#. module: exp_hr_appraisal
+#: model:ir.model.fields.selection,name:exp_hr_appraisal.selection__hr_employee_appraisal__state__employee_rejection
+msgid "Rejected by the Employee"
+msgstr "مرفوض من الموظف"
+
#. module: exp_hr_appraisal
#: model:ir.model.fields,field_description:exp_hr_appraisal.field_appraisal_degree__activity_user_id
#: model:ir.model.fields,field_description:exp_hr_appraisal.field_appraisal_plan__activity_user_id
diff --git a/odex25_hr/exp_hr_appraisal/models/appraisal.py b/odex25_hr/exp_hr_appraisal/models/appraisal.py
index 8e65c3f9d..e5a927bd8 100644
--- a/odex25_hr/exp_hr_appraisal/models/appraisal.py
+++ b/odex25_hr/exp_hr_appraisal/models/appraisal.py
@@ -17,7 +17,11 @@ class Appraisal(models.Model):
appraisal_date = fields.Date()
is_manager = fields.Boolean(related='appraisal_plan_id.is_manager')
state = fields.Selection([
- ("draft", _("Draft")), ("state_done", _("Done")), ("closed", _("Closed"))
+ ("draft", "Draft"),
+ ('employee_confirmation', 'Employee Confirmation'),
+ ('employee_rejection', 'Rejected by the Employee'),
+ ("state_done", "Done"),
+ ("closed", "Closed")
], default='draft', tracking=True)
start_compute = fields.Char(
compute='fill_employee_or_manager_appraisal') # Invisible filed to call compute function
@@ -38,6 +42,12 @@ class Appraisal(models.Model):
('general', 'General'),
('other', 'Other')], string='Appraisal Type')
company_id = fields.Many2one('res.company', string='Company',default=lambda self: self.env.company)
+ employee_protest = fields.Boolean(
+ groups="exp_hr_appraisal.group_appraisal_manager",
+ readonly=True,
+ states={'draft': [('readonly', False)]}
+ )
+
@api.onchange('appraisal_plan_id')
def onchange_applicants(self):
@@ -191,6 +201,20 @@ class Appraisal(models.Model):
else:
self.onchange_manager_appraisal_line_id()
+ def action_employee_approve(self):
+ if self.employee_id.user_id.id != self.env.user.id:
+ raise exceptions.AccessError(
+ _('Only %s should approve this appraisal!') % self.employee_id.user_id.name
+ )
+ self.state = 'state_done'
+
+ def action_employee_reject(self):
+ if self.employee_id.user_id.id != self.env.user.id:
+ raise exceptions.AccessError(
+ _('Only %s should reject this appraisal!') % self.employee_id.user_id.name
+ )
+ self.state = 'employee_rejection'
+
def draft(self):
for item in self:
if item.employee_appraisal:
@@ -204,15 +228,17 @@ class Appraisal(models.Model):
def set_state_done(self):
for item in self:
-
- # Update appraisal result in contract
- if item.employee_id.contract_id:
- if item.appraisal_result:
- item.employee_id.contract_id.appraisal_result_id = item.appraisal_result
+ if item.employee_protest and item.state == 'draft':
+ item.state = 'employee_confirmation'
else:
- raise exceptions.Warning(
- _('There is no contract for employee "%s" to update appraisal result ') % item.employee_id.name)
- item.state = 'state_done'
+ # Update appraisal result in contract
+ if item.employee_id.contract_id:
+ if item.appraisal_result:
+ item.employee_id.contract_id.appraisal_result_id = item.appraisal_result
+ else:
+ raise exceptions.Warning(
+ _('There is no contract for employee "%s" to update appraisal result ') % item.employee_id.name)
+ item.state = 'state_done'
def closed(self):
self.state = 'closed'
@@ -232,6 +258,7 @@ class StandardAppraisalLines(models.Model):
_description = 'Standard Appraisal line'
greed = fields.Float()
+ accrued_greed = fields.Float()
question = fields.Char()
great_level = fields.Float()
@@ -266,6 +293,7 @@ class ManagerAppraisalLines(models.Model):
action['views'] = [(self.env.ref('exp_hr_appraisal.manager_appraisal_complete_line_form_view').id, 'form')]
action['res_id'] = item.question_complete_id.id
action['target'] = 'new'
+ action['context'] = {"default_has_employee_protest": item.manager_appraisal_line_for_employee.employee_protest}
return action
@@ -278,6 +306,10 @@ class ManagerAppraisalCompleteLines(models.Model):
# Relational fields
customize_appraisal_id = fields.One2many('customize.complete.appraisal', 'customize_appraisal_line_id')
+ # FIXME this relation (related_manager_appraisal_complete, question_complete_id) is reversed: the parent should have one2many and here many2one
+ related_manager_appraisal_complete = fields.One2many('manager.appraisal.complete', 'question_complete_id')
+ has_employee_protest = fields.Boolean(related="related_manager_appraisal_complete.manager_appraisal_line_for_employee.employee_protest")
+
@api.onchange('customize_appraisal_id')
def compute_total_and_greate_level(self):
@@ -303,3 +335,4 @@ class CustomizeAppraisal(models.Model):
# Relational fields
customize_appraisal_line_id = fields.Many2one('manager.appraisal.complete.line') # Inverse Field
degree_id = fields.Many2one('appraisal.degree')
+ accrued_degree_id = fields.Many2one('appraisal.degree')
diff --git a/odex25_hr/exp_hr_appraisal/models/employees_appraisal.py b/odex25_hr/exp_hr_appraisal/models/employees_appraisal.py
index 0c8954c53..a40135cd7 100644
--- a/odex25_hr/exp_hr_appraisal/models/employees_appraisal.py
+++ b/odex25_hr/exp_hr_appraisal/models/employees_appraisal.py
@@ -39,9 +39,14 @@ class EmployeesAppraisal(models.Model):
('mission', 'Mission'),
('general', 'General'),
('other', 'Other')], string='Appraisal Type')
+ employee_protest = fields.Boolean(
+ groups="exp_hr_appraisal.group_appraisal_manager",
+ readonly=True,
+ states={'draft': [('readonly', False)]}
+ )
+
# Dynamic domain for manager_id
-
@api.onchange('department_id')
def manager_domain(self):
for item in self:
@@ -132,7 +137,9 @@ class EmployeesAppraisal(models.Model):
'appraisal_plan_id': item.appraisal_plan_id.id,
'appraisal_type': item.appraisal_type,
'standard_appraisal_employee_line_ids': [(0, 0, value) for value in standard_appraisal_list],
- 'manager_appraisal_line_id': [(0, 0, value) for value in manager_appraisal_list]}
+ 'manager_appraisal_line_id': [(0, 0, value) for value in manager_appraisal_list],
+ 'employee_protest': item.employee_protest
+ }
line_id = self.env['hr.employee.appraisal'].create(appraisal_line)
# Initialize
diff --git a/odex25_hr/exp_hr_appraisal/views/appraisal_for_employees_view.xml b/odex25_hr/exp_hr_appraisal/views/appraisal_for_employees_view.xml
index c077b1189..a7546d802 100644
--- a/odex25_hr/exp_hr_appraisal/views/appraisal_for_employees_view.xml
+++ b/odex25_hr/exp_hr_appraisal/views/appraisal_for_employees_view.xml
@@ -37,6 +37,7 @@
+
diff --git a/odex25_hr/exp_hr_appraisal/views/employee_appraisal_view.xml b/odex25_hr/exp_hr_appraisal/views/employee_appraisal_view.xml
index bbdd0f334..58085c86a 100644
--- a/odex25_hr/exp_hr_appraisal/views/employee_appraisal_view.xml
+++ b/odex25_hr/exp_hr_appraisal/views/employee_appraisal_view.xml
@@ -7,12 +7,14 @@
+
+