[UPD] exp_hr_appraisal: add feature employee reject appraisals

This commit is contained in:
Samir Ladoui 2025-02-25 16:15:58 +01:00
parent 5a030f29f6
commit 6e6c7b89e4
6 changed files with 115 additions and 14 deletions

View File

@ -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

View File

@ -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')

View File

@ -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

View File

@ -37,6 +37,7 @@
<field name="appraisal_plan_id" string="Appraisal plan"
attrs="{'readonly':[('state','!=','draft')]}" required="1"/>
<field name="appraisal_type" attrs="{'readonly':[('state','!=','draft')]}" required="1" string="Appraisal Type"/>
<field name="employee_protest" groups="exp_hr_appraisal.group_appraisal_manager" />
</group>
<group>

View File

@ -7,12 +7,14 @@
<field name="arch" type="xml">
<form>
<header>
<button name="draft" string="Re-draft" class="oe_highlight" type="object" states="state_done"
<button name="draft" string="Re-draft" class="oe_highlight" type="object" states="state_done,employee_rejection"
groups="hr.group_hr_manager, hr_base.group_division_manager"/>
<button name="action_employee_approve" string="Approve" type="object" states="employee_confirmation" class="oe_highlight"/>
<button name="action_employee_reject" string="Reject" type="object" states="employee_confirmation"/>
<button name="set_state_done" string="Done" type="object" states="draft" class="oe_highlight"/>
<!--button name="closed" string="Closed" type="object" states="state_done" class="oe_highlight"
groups="hr.group_hr_manager, hr_base.group_division_manager"/-->
<field name="state" widget="statusbar" statusbar_colors="{'KEY_IS_STATE':'VALUE_IS_COLOR'}"/>
<field name="state" widget="statusbar" statusbar_visible="draft,state_done,closed" statusbar_colors="{'KEY_IS_STATE':'VALUE_IS_COLOR'}"/>
</header>
<sheet>
<group>
@ -28,7 +30,7 @@
<field name="appraisal_plan_id" string="Appraisal plan"
attrs="{'readonly':[('state','!=','draft')]}" required="1"/>
<field name="appraisal_type" attrs="{'readonly':[('state','!=','draft')]}" required="1" string="Appraisal Type"/>
<field name="employee_protest" groups="exp_hr_appraisal.group_appraisal_manager" />
</group>
<group>
<field name="date_from" string="Date From"
@ -47,6 +49,10 @@
<tree editable="bottom">
<field name="question" string="Question" readonly="1" force_save="1"/>
<field name="greed" string="Greed" required="1" force_save="1" store="1" />
<field name="accrued_greed" attrs="{
'invisible': [('parent.employee_protest', '!=', True)],
'column_invisible': [('parent.employee_protest', '!=', True)]
}"/>
<field name="great_level" string="Great Level" readonly="1" force_save="1"/>
</tree>
</field>

View File

@ -28,10 +28,15 @@
<field name="name" string="Appraisal name" required="1"/>
</group>
</group>
<field name="has_employee_protest" invisible="1" />
<field name="customize_appraisal_id">
<tree editable="bottom">
<field name="question" string="Question" required="1" force_save="1"/>
<field name="degree_id" string="Degree level" required="1" force_save="1"/>
<field name="accrued_degree_id" attrs="{
'invisible': [('parent.has_employee_protest', '!=', True)],
'column_invisible': [('parent.has_employee_protest', '!=', True)]
}"/>
<field name="greed" string="Degree" readonly="1" force_save="1"/>
<field name="great_degree_level" string="Great level" readonly="1" force_save="1"/>
</tree>