diff --git a/addons/hr/data/hr_data.xml b/addons/hr/data/hr_data.xml index ab7165fee25..8c70cef3e68 100644 --- a/addons/hr/data/hr_data.xml +++ b/addons/hr/data/hr_data.xml @@ -99,5 +99,10 @@ + + hr.hr_presence_control_login + True + + diff --git a/addons/hr/models/__init__.py b/addons/hr/models/__init__.py index efe3c1d702c..43857d3d83e 100644 --- a/addons/hr/models/__init__.py +++ b/addons/hr/models/__init__.py @@ -13,3 +13,4 @@ from . import mail_channel from . import res_config_settings from . import res_partner from . import res_users +from . import res_company diff --git a/addons/hr/models/hr_employee_base.py b/addons/hr/models/hr_employee_base.py index fec003ccfc6..191a5cb926d 100644 --- a/addons/hr/models/hr_employee_base.py +++ b/addons/hr/models/hr_employee_base.py @@ -23,3 +23,31 @@ class HrEmployeeBase(models.AbstractModel): user_id = fields.Many2one('res.users') resource_id = fields.Many2one('resource.resource') resource_calendar_id = fields.Many2one('resource.calendar') + hr_presence_state = fields.Selection([ + ('present', 'Present'), + ('absent', 'Absent'), + ('to_define', 'To Define')], compute='_compute_presence_state', default='to_define') + last_activity = fields.Date(compute="_compute_last_activity") + + def _compute_presence_state(self): + """ + This method is overritten in several other modules which add additional + presence criterions. e.g. hr_attendance, hr_holidays + """ + # Check on login + check_login = self.env['ir.config_parameter'].sudo().get_param('hr.hr_presence_control_login') + for employee in self: + state = 'to_define' + if check_login: + if employee.user_id.im_status == 'online': + state = 'present' + elif employee.user_id.im_status == 'offline': + state = 'absent' + employee.hr_presence_state = state + + def _compute_last_activity(self): + employees = self.filtered(lambda e: e.user_id) + presences = self.env['bus.presence'].search([('user_id', 'in', employees.mapped('user_id.id'))]) + + for presence in presences: + presence.user_id.employee_ids.last_activity = presence.last_presence.date() diff --git a/addons/hr/models/res_company.py b/addons/hr/models/res_company.py new file mode 100644 index 00000000000..cd1937d639e --- /dev/null +++ b/addons/hr/models/res_company.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class Company(models.Model): + _inherit = 'res.company' + + hr_presence_control_email_amount = fields.Integer(string="# emails to send") + hr_presence_control_ip_list = fields.Char(string="Valid IP addresses") diff --git a/addons/hr/models/res_config_settings.py b/addons/hr/models/res_config_settings.py index 14494a6318e..a75564bc122 100644 --- a/addons/hr/models/res_config_settings.py +++ b/addons/hr/models/res_config_settings.py @@ -10,9 +10,12 @@ class ResConfigSettings(models.TransientModel): 'resource.calendar', 'Company Working Hours', related='company_id.resource_calendar_id', readonly=False) module_hr_org_chart = fields.Boolean(string="Show Organizational Chart") - module_hr_presence = fields.Boolean(string="Control presence of employees") + module_hr_presence = fields.Boolean(string="Advanced control presence of employees") module_hr_skills = fields.Boolean(string="Employee Skills and Resumé") hr_presence_control_login = fields.Boolean(string="According to the system login (User status on chat)", config_parameter='hr.hr_presence_control_login') - hr_presence_control_email = fields.Boolean(string="According to the amount of sent emails", config_parameter='hr.hr_presence_control_email') - hr_presence_control_ip = fields.Boolean(string="According to the IP address", config_parameter='hr.hr_presence_control_ip') + hr_presence_control_email = fields.Boolean(string="According to the amount of sent emails", config_parameter='hr_presence.hr_presence_control_email') + hr_presence_control_ip = fields.Boolean(string="According to the IP address", config_parameter='hr_presence.hr_presence_control_ip') + module_hr_attendance = fields.Boolean(string="According to the Attendance module.") + hr_presence_control_email_amount = fields.Integer(related="company_id.hr_presence_control_email_amount", readonly=False) + hr_presence_control_ip_list = fields.Char(related="company_id.hr_presence_control_ip_list", readonly=False) hr_employee_self_edit = fields.Boolean(string="Employee Edition", config_parameter='hr.hr_employee_self_edit') diff --git a/addons/hr/models/res_users.py b/addons/hr/models/res_users.py index 0e663a8d62b..c64f678070a 100644 --- a/addons/hr/models/res_users.py +++ b/addons/hr/models/res_users.py @@ -52,6 +52,8 @@ class User(models.Model): study_field = fields.Char(related='employee_id.study_field', readonly=False, related_sudo=False) study_school = fields.Char(related='employee_id.study_school', readonly=False, related_sudo=False) employee_count = fields.Integer(compute='_compute_employee_count') + hr_presence_state = fields.Selection(related='employee_id.hr_presence_state') + last_activity = fields.Date(related='employee_id.last_activity') @api.depends('employee_ids') def _compute_employee_count(self): @@ -69,6 +71,8 @@ class User(models.Model): 'employee_id', 'employee_ids', 'employee_parent_id', + 'hr_presence_state', + 'last_activity', ] hr_writable_fields = [ diff --git a/addons/hr/views/hr_employee_public_views.xml b/addons/hr/views/hr_employee_public_views.xml index fa8582f3015..95b277b30f0 100644 --- a/addons/hr/views/hr_employee_public_views.xml +++ b/addons/hr/views/hr_employee_public_views.xml @@ -95,6 +95,7 @@ +
@@ -107,6 +108,15 @@
+
+ +
+
+ +
+
+ +
diff --git a/addons/hr/views/hr_employee_views.xml b/addons/hr/views/hr_employee_views.xml index d7e52389246..56a96215194 100644 --- a/addons/hr/views/hr_employee_views.xml +++ b/addons/hr/views/hr_employee_views.xml @@ -40,14 +40,37 @@
+
- -
- + +
+ +
+
+
+ +
+ Control presence of employees +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+

Work Organization

diff --git a/addons/hr/views/res_users.xml b/addons/hr/views/res_users.xml index d417b93341b..1eb980c20f3 100644 --- a/addons/hr/views/res_users.xml +++ b/addons/hr/views/res_users.xml @@ -36,9 +36,31 @@ +
+
diff --git a/addons/hr_attendance/models/hr_employee.py b/addons/hr_attendance/models/hr_employee.py index 62b7def6d2c..fa5d788c210 100644 --- a/addons/hr_attendance/models/hr_employee.py +++ b/addons/hr_attendance/models/hr_employee.py @@ -17,6 +17,20 @@ class HrEmployeeBase(models.AbstractModel): hours_last_month = fields.Float(compute='_compute_hours_last_month') hours_today = fields.Float(compute='_compute_hours_today') + def _compute_presence_state(self): + """ + Override to include checkin/checkout in the presence state + Attendance has the second highest priority after login + """ + super()._compute_presence_state() + employees = self.filtered(lambda employee: employee.hr_presence_state != 'present') + for employee in employees: + if employee.attendance_state == 'checked_out' and employee.hr_presence_state == 'to_define': + employee.hr_presence_state = 'absent' + for employee in employees: + if employee.attendance_state == 'checked_in': + employee.hr_presence_state = 'present' + def _compute_hours_last_month(self): for employee in self: now = datetime.now() diff --git a/addons/hr_attendance/views/hr_employee_view.xml b/addons/hr_attendance/views/hr_employee_view.xml index f03fddc1730..ad1d073dd60 100644 --- a/addons/hr_attendance/views/hr_employee_view.xml +++ b/addons/hr_attendance/views/hr_employee_view.xml @@ -4,14 +4,24 @@ hr.employee hr.employee - 10 + 20 -
+ + + {'invisible': ['|', '|', ('user_id', '=', False), ('hr_presence_state', '=', 'absent'), ('attendance_state', '=', 'checked_in')]} + + + -
+
@@ -43,11 +53,17 @@ res.users + + + {'invisible': ['|', '|', ('hr_presence_state', '=', 'absent'), ('attendance_state', '=', 'checked_in')]} + + -
-
- - hr.employee.view.kanban hr.employee @@ -54,7 +23,7 @@
- + @@ -64,31 +33,4 @@ - - hr.employee - hr.employee - - 1 - - - - - -
-
- -
-
- -
-
- -
- - - -
-
-
-
diff --git a/addons/hr_presence/views/res_config_settings_views.xml b/addons/hr_presence/views/res_config_settings_views.xml deleted file mode 100644 index 9f447753925..00000000000 --- a/addons/hr_presence/views/res_config_settings_views.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - res.config.settings.view.form.inherit.hr - res.config.settings - - - - -
-
- -
-
-
-
-
-
-
-