summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
Diffstat (limited to 'addons')
-rw-r--r--addons/hr/data/hr_data.xml5
-rw-r--r--addons/hr/models/__init__.py1
-rw-r--r--addons/hr/models/hr_employee_base.py28
-rw-r--r--addons/hr/models/res_company.py11
-rw-r--r--addons/hr/models/res_config_settings.py9
-rw-r--r--addons/hr/models/res_users.py4
-rw-r--r--addons/hr/views/hr_employee_public_views.xml10
-rw-r--r--addons/hr/views/hr_employee_views.xml41
-rw-r--r--addons/hr/views/res_config_settings_views.xml44
-rw-r--r--addons/hr/views/res_users.xml22
-rw-r--r--addons/hr_attendance/models/hr_employee.py14
-rw-r--r--addons/hr_attendance/views/hr_employee_view.xml51
-rw-r--r--addons/hr_attendance_presence/__init__.py1
-rw-r--r--addons/hr_attendance_presence/__manifest__.py19
-rw-r--r--addons/hr_attendance_presence/models/__init__.py2
-rw-r--r--addons/hr_attendance_presence/models/hr_employee.py32
-rw-r--r--addons/hr_attendance_presence/models/res_config_settings.py9
-rw-r--r--addons/hr_attendance_presence/views/hr_employee.xml21
-rw-r--r--addons/hr_attendance_presence/views/res_config_settings_views.xml17
-rw-r--r--addons/hr_holidays/models/hr_employee.py5
-rw-r--r--addons/hr_holidays/models/hr_leave.py1
-rw-r--r--addons/hr_holidays/views/hr_views.xml17
-rw-r--r--addons/hr_holidays_attendance/__init__.py0
-rw-r--r--addons/hr_holidays_attendance/__manifest__.py15
-rw-r--r--addons/hr_holidays_attendance/views/hr_employee_views.xml64
-rw-r--r--addons/hr_presence/__manifest__.py1
-rw-r--r--addons/hr_presence/models/__init__.py1
-rw-r--r--addons/hr_presence/models/hr_employee.py77
-rw-r--r--addons/hr_presence/models/res_company.py3
-rw-r--r--addons/hr_presence/models/res_config_settings.py13
-rw-r--r--addons/hr_presence/views/hr_employee_views.xml62
-rw-r--r--addons/hr_presence/views/res_config_settings_views.xml44
32 files changed, 341 insertions, 303 deletions
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 @@
<field name="user_signature" eval="False"/>
</record>
+ <record model="ir.config_parameter" id="hr_presence_control_login" forcecreate="False">
+ <field name="key">hr.hr_presence_control_login</field>
+ <field name="value">True</field>
+ </record>
+
</data>
</odoo>
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 @@
<field name="arch" type="xml">
<kanban class="o_hr_employee_kanban">
<field name="id"/>
+ <field name="hr_presence_state"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click o_kanban_record_has_image_fill o_hr_kanban_record">
@@ -107,6 +108,15 @@
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
+ <div class="float-right" t-if="record.hr_presence_state.raw_value == 'present'">
+ <span class="fa fa-circle text-success" role="img" aria-label="Present" title="Present" name="presence_present"></span>
+ </div>
+ <div class="float-right" t-if="record.hr_presence_state.raw_value == 'absent'">
+ <span class="fa fa-circle text-danger" role="img" aria-label="Absent" title="Absent" name="presence_absent"></span>
+ </div>
+ <div class="float-right" t-if="record.hr_presence_state.raw_value == 'to_define'">
+ <span class="fa fa-circle text-warning" role="img" aria-label="To define" title="To define" name="presence_to_define"></span>
+ </div>
<field name="name"/>
</strong>
<span t-if="record.job_id.raw_value" class="o_kanban_record_subtitle"><field name="job_id"/></span>
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 @@
<form string="Employee" js_class="hr_employee_form">
<field name="active" invisible="1"/>
<field name="user_partner_id" invisible="1"/>
+ <field name="hr_presence_state" invisible="1"/>
<header>
<button string="Chat" class="btn btn-primary o_employee_chat_btn" attrs="{'invisible': [('user_id','=', False)]}"/>
<button name="%(plan_wizard_action)d" string="Launch Plan" type="action" groups="hr.group_hr_manager"/>
</header>
<sheet>
- <widget name="web_ribbon" text="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
- <div name="button_box" class="oe_button_box"/>
- <field name="image" widget='image' class="oe_avatar" options='{"zoom": true, "preview_image":"image_medium"}'/>
+ <widget name="web_ribbon" text="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
+ <div name="button_box" class="oe_button_box">
+ <button
+ id="hr_presence_button"
+ class="oe_stat_button"
+ disabled="1"
+ attrs="{'invisible': ['|', ('last_activity', '=', False), ('user_id', '=', False)]}">
+ <div role="img" class="fa fa-fw fa-circle text-success o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'present')]}" aria-label="Available" title="Available"/>
+ <div role="img" class="fa fa-fw fa-circle text-warning o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'to_define')]}" aria-label="Away" title="Away"/>
+ <div role="img" class="fa fa-fw fa-circle text-danger o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'absent')]}" aria-label="Not available" title="Not available"/>
+
+ <div class="o_stat_info" attrs="{'invisible': [('hr_presence_state', '=', 'present')]}">
+ <span class="o_stat_value">
+ <field name="last_activity"/>
+ </span>
+ <span class="o_stat_text">
+ Last Activity
+ </span>
+ </div>
+ <div class="o_stat_info" attrs="{'invisible': [('hr_presence_state', '!=', 'present')]}">
+ <span class="o_stat_text">Connected</span>
+ </div>
+ </button>
+ </div>
+ <field name="image" widget='image' class="oe_avatar" options='{"zoom": true, "preview_image":"image_medium"}'/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1>
@@ -204,6 +227,7 @@
<field name="arch" type="xml">
<kanban class="o_hr_employee_kanban">
<field name="id"/>
+ <field name="hr_presence_state"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click o_kanban_record_has_image_fill o_hr_kanban_record">
@@ -216,7 +240,16 @@
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
- <field name="name"/>
+ <div class="float-right" t-if="record.hr_presence_state.raw_value == 'present'">
+ <span class="fa fa-circle text-success" role="img" aria-label="Present" title="Present" name="presence_present"></span>
+ </div>
+ <div class="float-right" t-if="record.hr_presence_state.raw_value == 'absent'">
+ <span class="fa fa-circle text-danger" role="img" aria-label="Absent" title="Absent" name="presence_absent"></span>
+ </div>
+ <div class="float-right" t-if="record.hr_presence_state.raw_value == 'to_define'">
+ <span class="fa fa-circle text-warning" role="img" aria-label="To define" title="To define" name="presence_to_define"></span>
+ </div>
+ <field name="name" placeholder="Employee's Name"/>
</strong>
<span t-if="record.job_id.raw_value" class="o_kanban_record_subtitle"><field name="job_id"/></span>
</div>
diff --git a/addons/hr/views/res_config_settings_views.xml b/addons/hr/views/res_config_settings_views.xml
index 5cdcf6f679a..62d4f4179f6 100644
--- a/addons/hr/views/res_config_settings_views.xml
+++ b/addons/hr/views/res_config_settings_views.xml
@@ -20,6 +20,50 @@
</div>
</div>
</div>
+ <div class="col-12 col-lg-6 o_setting_box" title="Presence of employees">
+
+ <div class="o_setting_right_pane">
+ <span class="o_form_label">Control presence of employees</span>
+ <div class="content-group" name="hr_presence_options">
+ <div class="row">
+ <field name="module_hr_attendance" class="col-lg-1 ml16"/>
+ <label for="module_hr_attendance" class="col-lg-10 o_light_label"/>
+ </div>
+ <div class="row">
+ <field name="hr_presence_control_login" class="col-lg-1 ml16"/>
+ <label for="hr_presence_control_login" class="col-lg-10 o_light_label"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="col-12 col-lg-6 o_setting_box" title="Advanced presence of employees">
+ <div class="o_setting_left_pane">
+ <field name="module_hr_presence"/>
+ </div>
+ <div class="o_setting_right_pane">
+ <label for="module_hr_presence"/>
+ <div class="text-muted" name="hr_presence_options_advanced">
+ Presence reporting screen, email and IP address control.
+ </div>
+ <div class="row mt-1" attrs="{'invisible': [('module_hr_presence', '=', False)]}">
+ <field name="hr_presence_control_email" class="col-lg-1 ml16"/>
+ <label for="hr_presence_control_email" class="col-lg-10 o_light_label"/>
+ </div>
+ <div class="row ml-4" attrs="{'invisible': ['|', ('module_hr_presence', '=', False), ('hr_presence_control_email', '=', False)]}">
+ <span class="mr-2">At least </span>
+ <field name="hr_presence_control_email_amount"/>
+ <span> sent emails</span>
+ </div>
+ <div class="row" attrs="{'invisible': [('module_hr_presence', '=', False)]}">
+ <field name="hr_presence_control_ip" class="col-lg-1 ml16"/>
+ <label for="hr_presence_control_ip" class="col-lg-10 o_light_label"/>
+ </div>
+ <div class="row ml-4" attrs="{'invisible': ['|', ('module_hr_presence', '=', False), ('hr_presence_control_ip', '=', False)]}">
+ <span class="mr-2">IP List (comma separated):</span>
+ <field name="hr_presence_control_ip_list"/>
+ </div>
+ </div>
+ </div>
</div>
<h2>Work Organization</h2>
<div class="row mt16 o_settings_container">
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 @@
<field name="arch" type="xml">
<form position="replace">
<form>
+ <field name="hr_presence_state" invisible="1"/>
<header></header> <!-- Used by other modules to add buttons -->
<sheet>
<div class="oe_button_box" name="button_box">
+ <button
+ id="hr_presence_button"
+ class="oe_stat_button"
+ disabled="1"
+ attrs="{'invisible': [('hr_presence_state', '=', 'absent')]}">
+ <div role="img" class="fa fa-fw fa-circle text-success o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'present')]}" aria-label="Available" title="Available"/>
+ <div role="img" class="fa fa-fw fa-circle text-warning o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'to_define')]}" aria-label="Away" title="Away"/>
+ <div role="img" class="fa fa-fw fa-circle text-danger o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'absent')]}" aria-label="Not available" title="Not available"/>
+
+ <div class="o_stat_info" attrs="{'invisible': [('hr_presence_state', '=', 'present')]}">
+ <span class="o_stat_value">
+ <field name="last_activity"/>
+ </span>
+ <span class="o_stat_text">
+ Last Activity
+ </span>
+ </div>
+ <div class="o_stat_info" attrs="{'invisible': [('hr_presence_state', '!=', 'present')]}">
+ <span class="o_stat_text">Connected</span>
+ </div>
+ </button>
</div>
<field name="image" widget='image' class="oe_avatar" options='{"zoom": true, "preview_image":"image_medium"}'/>
<div class="oe_title">
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 @@
<field name="name">hr.employee</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_form"/>
- <field name="priority">10</field>
+ <field name="priority">20</field>
<field name="groups_id" eval="[(4,ref('hr_attendance.group_hr_attendance_user'))]"/>
<field name="arch" type="xml">
- <div name="button_box" position="inside">
+ <xpath expr="//button[@id='hr_presence_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', '|', ('user_id', '=', False), ('hr_presence_state', '=', 'absent'), ('attendance_state', '=', 'checked_in')]}
+ </attribute>
+ </xpath>
+ <xpath expr="//div[@name='button_box']" position="inside">
<field name="attendance_state" invisible="1"/>
<button name="%(hr_attendance_action_employee)d"
+ id="hr_attendance_button"
class="oe_stat_button"
- type="action" attrs="{'invisible': [('attendance_state', '=', False)]}">
+ type="action" attrs="{'invisible': [
+ '|', ('attendance_state', '=', False),
+ '&amp;',
+ ('hr_presence_state', '=', 'present'),
+ ('attendance_state', '=', 'checked_out')]}">
<div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_green" attrs="{'invisible': [('attendance_state', '=', 'checked_out')]}" aria-label="Available" title="Available"/>
<div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_red" attrs="{'invisible': [('attendance_state', '=', 'checked_in')]}" aria-label="Not available" title="Not available"/>
<div class="o_stat_info">
@@ -34,7 +44,7 @@
</span>
</div>
</button>
- </div>
+ </xpath>
</field>
</record>
@@ -43,11 +53,17 @@
<field name="model">res.users</field>
<field name="inherit_id" ref="hr.res_users_view_form_profile"/>
<field name="arch" type="xml">
+ <xpath expr="//button[@id='hr_presence_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', '|', ('hr_presence_state', '=', 'absent'), ('attendance_state', '=', 'checked_in')]}
+ </attribute>
+ </xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<field name="attendance_state" invisible="1"/>
<button name="%(hr_attendance_action_my_attendances)d"
+ id="hr_attendance_button"
class="oe_stat_button"
- type="action" attrs="{'invisible': [('attendance_state', '=', False)]}">
+ type="action" attrs="{'invisible': ['|', ('attendance_state', '=', False), '&amp;', ('hr_presence_state', '=', 'present'), ('attendance_state', '=', 'checked_out')]}">
<div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_green" attrs="{'invisible': [('attendance_state', '=', 'checked_out')]}" aria-label="Available" title="Available"/>
<div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_red" attrs="{'invisible': [('attendance_state', '=', 'checked_in')]}" aria-label="Not available" title="Not available"/>
<div class="o_stat_info">
@@ -131,31 +147,6 @@
</field>
</record>
- <record id="view_employee_kanban_inherit_hr_attendance" model="ir.ui.view">
- <field name="name">hr.employee</field>
- <field name="model">hr.employee</field>
- <field name="inherit_id" ref="hr.hr_kanban_view_employees"/>
- <field name="priority">1</field>
- <field name="arch" type="xml">
- <templates position="before">
- <field name="attendance_state"/>
- </templates>
- <field name="name" position="replace">
- <div>
- <div class="float-right" t-if="record.attendance_state.raw_value == 'checked_in'">
- <span id="oe_hr_attendance_status" class="fa fa-circle oe_hr_attendance_status_green" role="img" aria-label="Available" title="Available"></span>
- </div>
- <div class="float-right" t-if="record.attendance_state.raw_value == 'checked_out'">
- <span id="oe_hr_attendance_status" class="fa fa-circle oe_hr_attendance_status_red" role="img" aria-label="Not available" title="Not available"></span>
- </div>
- <strong>
- <field name="name" placeholder="Employee's Name"/>
- </strong>
- </div>
- </field>
- </field>
- </record>
-
<record id="hr_employee_attendance_action_kanban" model="ir.actions.act_window">
<field name="name">Employees</field>
<field name="res_model">hr.employee</field>
diff --git a/addons/hr_attendance_presence/__init__.py b/addons/hr_attendance_presence/__init__.py
deleted file mode 100644
index 0650744f6bc..00000000000
--- a/addons/hr_attendance_presence/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from . import models
diff --git a/addons/hr_attendance_presence/__manifest__.py b/addons/hr_attendance_presence/__manifest__.py
deleted file mode 100644
index da31006ddb7..00000000000
--- a/addons/hr_attendance_presence/__manifest__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-{
- 'name': 'Attendance Presence',
- 'version': '1.0',
- 'category': 'Human Resources',
- 'sequence': 85,
- 'summary': 'Bridge Attendance module and Presence module',
- 'description': "",
- 'website': 'https://www.odoo.com/page/employees',
- 'depends': ['hr_attendance', 'hr_presence'],
- 'installable': True,
- 'auto_install': True,
- 'data': [
- 'views/res_config_settings_views.xml',
- 'views/hr_employee.xml',
- ],
-}
diff --git a/addons/hr_attendance_presence/models/__init__.py b/addons/hr_attendance_presence/models/__init__.py
deleted file mode 100644
index 5d68338dfc7..00000000000
--- a/addons/hr_attendance_presence/models/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from . import hr_employee
-from . import res_config_settings
diff --git a/addons/hr_attendance_presence/models/hr_employee.py b/addons/hr_attendance_presence/models/hr_employee.py
deleted file mode 100644
index c1dc644cac7..00000000000
--- a/addons/hr_attendance_presence/models/hr_employee.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import logging
-
-from odoo import models
-
-_logger = logging.getLogger(__name__)
-
-
-class Employee(models.Model):
- _inherit = 'hr.employee'
-
- def _action_open_presence_view(self):
- action = super(Employee, self)._action_open_presence_view()
-
- if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_attendance'):
- company = self.env.company
- employees = self.env['hr.employee'].search([
- ('department_id.company_id', '=', company.id),
- ('user_id', '!=', False),
- ])
-
- employees.filtered(
- lambda e: e.attendance_state == 'checked_in'
- ).write({'hr_presence_state': 'present'})
-
- employees.filtered(
- lambda e: e.attendance_state == 'checked_out'
- ).write({'hr_presence_state': 'absent'})
-
- return action
diff --git a/addons/hr_attendance_presence/models/res_config_settings.py b/addons/hr_attendance_presence/models/res_config_settings.py
deleted file mode 100644
index a9bbd8f64b3..00000000000
--- a/addons/hr_attendance_presence/models/res_config_settings.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import fields, models
-
-
-class ResConfigSettings(models.TransientModel):
- _inherit = 'res.config.settings'
-
- hr_presence_control_attendance = fields.Boolean(string="According to the Attendance module", config_parameter='hr_presence.hr_presence_control_attendance')
diff --git a/addons/hr_attendance_presence/views/hr_employee.xml b/addons/hr_attendance_presence/views/hr_employee.xml
deleted file mode 100644
index a645e594b20..00000000000
--- a/addons/hr_attendance_presence/views/hr_employee.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<odoo>
-
- <record id="hr_employee_view_kanban" model="ir.ui.view">
- <field name="name">hr.employee</field>
- <field name="model">hr.employee</field>
- <field name="inherit_id" ref="hr_presence.hr_employee_view_kanban_inherit"/>
- <field name="priority">20</field>
- <field name="arch" type="xml">
- <xpath expr="//span[@name='presence_absent']" position="attributes">
- <attribute name="invisible">1</attribute>
- </xpath>
- <xpath expr="//span[@name='presence_present']" position="attributes">
- <attribute name="invisible">1</attribute>
- </xpath>
- <xpath expr="//span[@name='presence_to_define']" position="attributes">
- <attribute name="invisible">1</attribute>
- </xpath>
- </field>
- </record>
-</odoo>
diff --git a/addons/hr_attendance_presence/views/res_config_settings_views.xml b/addons/hr_attendance_presence/views/res_config_settings_views.xml
deleted file mode 100644
index ef6ab9142e6..00000000000
--- a/addons/hr_attendance_presence/views/res_config_settings_views.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<odoo>
- <record id="res_config_settings_view_form" model="ir.ui.view">
- <field name="name">res.config.settings.view.form.inherit.presence.hr</field>
- <field name="model">res.config.settings</field>
- <field name="priority" eval="70"/>
- <field name="inherit_id" ref="hr.res_config_settings_view_form"/>
- <field name="arch" type="xml">
- <xpath expr="//div[@name='hr_presence_options']" position="inside">
- <div class="row">
- <field name="hr_presence_control_attendance" class="col-lg-1 ml16"/>
- <label for="hr_presence_control_attendance" class="col-lg-10 o_light_label"/>
- </div>
- </xpath>
- </field>
- </record>
-</odoo>
diff --git a/addons/hr_holidays/models/hr_employee.py b/addons/hr_holidays/models/hr_employee.py
index c0a47809e04..a79ad7eb307 100644
--- a/addons/hr_holidays/models/hr_employee.py
+++ b/addons/hr_holidays/models/hr_employee.py
@@ -93,6 +93,11 @@ class HrEmployeeBase(models.AbstractModel):
for employee in self:
employee.allocation_used_count = employee.allocation_count - employee.remaining_leaves
+ def _compute_presence_state(self):
+ super()._compute_presence_state()
+ employees = self.filtered(lambda employee: employee.hr_presence_state != 'present' and employee.is_absent)
+ employees.update({'hr_presence_state': 'absent'})
+
@api.multi
def _compute_leave_status(self):
# Used SUPERUSER_ID to forcefully get status of other user's leave, to bypass record rule
diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py
index 4685e543a0c..8deda82c3f4 100644
--- a/addons/hr_holidays/models/hr_leave.py
+++ b/addons/hr_holidays/models/hr_leave.py
@@ -793,7 +793,6 @@ class HolidaysRequest(models.Model):
# FIXME RLi: This does not make sense, only the parent should be in validation_type both
if leaves and leaves[0].validation_type == 'both':
leaves.action_validate()
-
employee_requests = self.filtered(lambda hol: hol.holiday_type == 'employee')
employee_requests._validate_leave_request()
if not self.env.context.get('leave_fast_create'):
diff --git a/addons/hr_holidays/views/hr_views.xml b/addons/hr_holidays/views/hr_views.xml
index c7da3c7eea1..48f28f883b8 100644
--- a/addons/hr_holidays/views/hr_views.xml
+++ b/addons/hr_holidays/views/hr_views.xml
@@ -135,6 +135,11 @@
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_form"/>
<field name="arch" type="xml">
+ <xpath expr="//button[@id='hr_presence_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', '|', '|', ('last_activity', '=', False), ('is_absent', '=', True), ('user_id', '=', False), ('id', '=', False)]}
+ </attribute>
+ </xpath>
<xpath expr="//group[@name='managers']" position="inside">
<field name="leave_manager_id"/>
</xpath>
@@ -142,10 +147,11 @@
<field name="current_leave_id" invisible="1"/>
<field name="show_leaves" invisible="1"/>
<field name="is_absent" invisible="1"/>
- <button name="%(hr_leave_action_new_request)d" type="action"
+ <button disabled="1"
class="oe_stat_button"
+ context="{'search_default_employee_id': active_id}"
attrs="{'invisible': [('is_absent', '=', False)]}">
- <div role="img" class="fa fa-fw fa-circle o_button_icon text-danger" aria-label="Absent Until" title="Absent Until"/>
+ <div role="img" class="fa fa-fw fa-plane o_button_icon text-danger" aria-label="Absent Until" title="Absent Until"/>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="leave_date_to"/>
@@ -160,6 +166,7 @@
class="oe_stat_button"
icon="fa-calendar"
attrs="{'invisible': [('show_leaves','=', False)]}"
+ context="{'search_default_employee_id': active_id}"
groups="base.group_user"
help="Remaining leaves">
<div class="o_field_widget o_stat_info">
@@ -188,10 +195,10 @@
<field name="current_leave_id" invisible="1"/>
<field name="show_leaves" invisible="1"/>
<field name="is_absent" invisible="1"/>
- <button name="%(hr_leave_action_new_request)d" type="action"
+ <button disabled="1"
class="oe_stat_button"
attrs="{'invisible': [('is_absent', '=', False)]}">
- <div role="img" class="fa fa-fw fa-circle o_button_icon text-danger" aria-label="Absent Until" title="Absent Until"/>
+ <div role="img" class="fa fa-fw fa-plane o_button_icon text-danger" aria-label="Absent Until" title="Absent Until"/>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="leave_date_to"/>
@@ -232,7 +239,7 @@
<button name="%(hr_leave_action_new_request)d" type="action"
class="oe_stat_button"
attrs="{'invisible': [('is_absent', '=', False)]}">
- <div role="img" class="fa fa-fw fa-circle o_button_icon text-danger" aria-label="Absent Until" title="Absent Until"/>
+ <div role="img" class="fa fa-fw fa-plane o_button_icon text-danger" aria-label="Absent Until" title="Absent Until"/>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="leave_date_to"/>
diff --git a/addons/hr_holidays_attendance/__init__.py b/addons/hr_holidays_attendance/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/addons/hr_holidays_attendance/__init__.py
diff --git a/addons/hr_holidays_attendance/__manifest__.py b/addons/hr_holidays_attendance/__manifest__.py
new file mode 100644
index 00000000000..b20f356c401
--- /dev/null
+++ b/addons/hr_holidays_attendance/__manifest__.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': "HR Attendance Holidays",
+ 'summary': """""",
+ 'category': 'HR',
+ 'description': """
+ Hides attendance presence stat button when an employee is on leave.
+ """,
+ 'version': '1.0',
+ 'depends': ['hr_attendance', 'hr_holidays'],
+ 'auto_install': True,
+ 'data': [
+ 'views/hr_employee_views.xml',
+ ],
+}
diff --git a/addons/hr_holidays_attendance/views/hr_employee_views.xml b/addons/hr_holidays_attendance/views/hr_employee_views.xml
new file mode 100644
index 00000000000..53cc6d53e90
--- /dev/null
+++ b/addons/hr_holidays_attendance/views/hr_employee_views.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<odoo>
+
+ <record id="hr_user_view_form" model="ir.ui.view">
+ <field name="name">hr.user.preferences.view.form.attendance.inherit</field>
+ <field name="model">res.users</field>
+ <field name="inherit_id" ref="hr_attendance.hr_user_view_form"/>
+ <field name="arch" type="xml">
+ <!-- Hide Attendance button -->
+ <xpath expr="//button[@id='hr_attendance_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', '|', '&amp;',
+ ('hr_presence_state', '=', 'present'),
+ ('attendance_state', '=', 'checked_out'),
+ ('is_absent', '=', True),
+ ('id', '=', False),
+ ]}
+ </attribute>
+ </xpath>
+ <!-- Merge invisible attr of both module -->
+ <xpath expr="//button[@id='hr_presence_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', '|', '|',
+ ('is_absent', '=', True),
+ ('hr_presence_state', '=', 'absent'),
+ ('attendance_state', '=', 'checked_in'),
+ ('id', '=', False),
+ ]}
+ </attribute>
+ </xpath>
+ </field>
+ </record>
+
+ <record id="hr_employee_view_form" model="ir.ui.view">
+ <field name="name">hr.employee.holidays.attendance.inherit</field>
+ <field name="model">hr.employee</field>
+ <field name="inherit_id" ref="hr_attendance.view_employee_form_inherit_hr_attendance"/>
+ <field name="arch" type="xml">
+ <!-- Hide Attendance button -->
+ <xpath expr="//button[@id='hr_attendance_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', '|', '&amp;',
+ ('hr_presence_state', '=', 'present'),
+ ('attendance_state', '=', 'checked_out'),
+ ('is_absent', '=', True),
+ ('id', '=', False),
+ ]}
+ </attribute>
+ </xpath>
+ <!-- Merge invisible attr of both module -->
+ <xpath expr="//button[@id='hr_presence_button']" position="attributes">
+ <attribute name="attrs">
+ {'invisible': ['|', '|', '|',
+ ('is_absent', '=', True),
+ ('hr_presence_state', '=', 'absent'),
+ ('attendance_state', '=', 'checked_in'),
+ ('id', '=', False),
+ ]}
+ </attribute>
+ </xpath>
+ </field>
+ </record>
+
+</odoo>
diff --git a/addons/hr_presence/__manifest__.py b/addons/hr_presence/__manifest__.py
index d0fdba48fff..05b27fca5ca 100644
--- a/addons/hr_presence/__manifest__.py
+++ b/addons/hr_presence/__manifest__.py
@@ -18,7 +18,6 @@ Allows to contact directly the employee in case of unjustified absence.
""",
'depends': ['hr', 'hr_holidays', 'sms'],
'data': [
- 'views/res_config_settings_views.xml',
'data/ir_actions_server.xml',
'views/hr_employee_views.xml',
'data/sms_data.xml',
diff --git a/addons/hr_presence/models/__init__.py b/addons/hr_presence/models/__init__.py
index 996b19c0a45..76aa02054b2 100644
--- a/addons/hr_presence/models/__init__.py
+++ b/addons/hr_presence/models/__init__.py
@@ -3,5 +3,4 @@
from . import hr_employee
from . import res_company
-from . import res_config_settings
from . import res_users_log
diff --git a/addons/hr_presence/models/hr_employee.py b/addons/hr_presence/models/hr_employee.py
index 2f0c55a9571..9860fa0ec1b 100644
--- a/addons/hr_presence/models/hr_employee.py
+++ b/addons/hr_presence/models/hr_employee.py
@@ -10,21 +10,28 @@ from odoo.fields import Datetime
_logger = logging.getLogger(__name__)
-class ResCompany(models.Model):
- _inherit = 'hr.employee'
+class Employee(models.AbstractModel):
+ _inherit = 'hr.employee.base'
- hr_presence_state = fields.Selection([
+ email_sent = fields.Boolean(default=False)
+ ip_connected = fields.Boolean(default=False)
+ manually_set_present = fields.Boolean(default=False)
+
+ # Stored field used in the presence kanban reporting view
+ # to allow group by state.
+ hr_presence_state_display = fields.Selection([
('present', 'Present'),
('absent', 'Absent'),
- ('to_define', 'To Define')], groups="hr.group_hr_user", default='to_define')
- last_activity = fields.Date(compute="_compute_last_activity")
-
- 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'))])
+ ('to_define', 'To Define')])
- for presence in presences:
- presence.user_id.employee_ids.last_activity = presence.last_presence.date()
+ def _compute_presence_state(self):
+ super()._compute_presence_state()
+ employees = self.filtered(lambda employee: employee.hr_presence_state != 'present' and not employee.is_absent)
+ company = self.env.company
+ for employee in employees:
+ if not employee.is_absent and company.hr_presence_last_compute_date and company.hr_presence_last_compute_date.day == Datetime.now().day and \
+ (employee.email_sent or employee.ip_connected or employee.manually_set_present):
+ employee.hr_presence_state = 'present'
@api.model
def _check_presence(self):
@@ -32,28 +39,16 @@ class ResCompany(models.Model):
if not company.hr_presence_last_compute_date or \
company.hr_presence_last_compute_date.day != Datetime.now().day:
self.env['hr.employee'].search([
- ('department_id.company_id', '=', company.id)
- ]).write({'hr_presence_state': 'to_define'})
-
- employees = self.env['hr.employee'].search([
- ('department_id.company_id', '=', company.id),
- ('user_id', '!=', False),
- ('hr_presence_state', '=', 'to_define')])
-
- # Remove employees on holidays
- leaves = self.env['hr.leave'].search([
- ('state', '=', 'validate'),
- ('date_from', '<=', Datetime.to_string(Datetime.now())),
- ('date_to', '>=', Datetime.to_string(Datetime.now()))])
- employees_on_holiday = leaves.mapped('employee_id')
- employees_on_holiday.write({'hr_presence_state': 'absent'})
- employees = employees - employees_on_holiday
-
- # Check on system login
- if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_login'):
- online_employees = employees.filtered(lambda employee: employee.user_id.im_status in ['away', 'online'])
- online_employees.write({'hr_presence_state': 'present'})
- employees = employees - online_employees
+ ('company_id', '=', company.id)
+ ]).write({
+ 'email_sent': False,
+ 'ip_connected': False,
+ 'manually_set_present': False
+ })
+
+ employees = self.env['hr.employee'].search([('company_id', '=', company.id)])
+ all_employees = employees
+
# Check on IP
if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_ip'):
@@ -68,7 +63,7 @@ class ResCompany(models.Model):
).mapped('ip')
if any([ip in ip_list for ip in employee_ips]):
ip_employees |= employee
- ip_employees.write({'hr_presence_state': 'present'})
+ ip_employees.write({'ip_connected': True})
employees = employees - ip_employees
# Check on sent emails
@@ -82,10 +77,13 @@ class ResCompany(models.Model):
('date', '<=', Datetime.to_string(Datetime.now()))])
if sent_emails >= threshold:
email_employees |= employee
- email_employees.write({'hr_presence_state': 'present'})
+ email_employees.write({'email_sent': True})
employees = employees - email_employees
- company.hr_presence_last_compute_date = Datetime.now()
+ company.sudo().hr_presence_last_compute_date = Datetime.now()
+
+ for employee in all_employees:
+ employee.hr_presence_state_display = employee.hr_presence_state
@api.model
def _action_open_presence_view(self):
@@ -110,7 +108,12 @@ class ResCompany(models.Model):
def action_set_present(self):
if not self.env.user.has_group('hr.group_hr_manager'):
raise UserError(_("You don't have the right to do this. Please contact an Administrator."))
- self.write({'hr_presence_state': 'present'})
+ self.write({'manually_set_present': True})
+
+ def write(self, vals):
+ if vals.get('hr_presence_state_display') == 'present':
+ vals['manually_set_present'] = True
+ return super().write(vals)
def action_open_leave_request(self):
self.ensure_one()
diff --git a/addons/hr_presence/models/res_company.py b/addons/hr_presence/models/res_company.py
index 7de70604a92..834fd26cf21 100644
--- a/addons/hr_presence/models/res_company.py
+++ b/addons/hr_presence/models/res_company.py
@@ -7,7 +7,4 @@ from odoo import fields, models
class ResCompany(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")
hr_presence_last_compute_date = fields.Datetime()
diff --git a/addons/hr_presence/models/res_config_settings.py b/addons/hr_presence/models/res_config_settings.py
deleted file mode 100644
index e831d7506bb..00000000000
--- a/addons/hr_presence/models/res_config_settings.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from odoo import fields, models
-
-
-class ResConfigSettings(models.TransientModel):
- _inherit = 'res.config.settings'
-
- hr_presence_control_login = fields.Boolean(string="According to the system login (User status on chat)", config_parameter='hr_presence.hr_presence_control_login')
- 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')
- 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)
diff --git a/addons/hr_presence/views/hr_employee_views.xml b/addons/hr_presence/views/hr_employee_views.xml
index 6f226b3dc71..61cb26184f8 100644
--- a/addons/hr_presence/views/hr_employee_views.xml
+++ b/addons/hr_presence/views/hr_employee_views.xml
@@ -7,42 +7,11 @@
<field name="groups_id" eval="[(4, ref('hr.group_hr_manager'))]"/>
<field name="arch" type="xml">
<filter name="group_manager" position="after">
- <filter name="group_hr_presence_state" string="Presence" domain="[]" context="{'group_by':'hr_presence_state'}"/>
+ <filter name="group_hr_presence_state" string="Presence" domain="[]" context="{'group_by':'hr_presence_state_display'}"/>
</filter>
</field>
</record>
- <record id="hr_employee_view_form" model="ir.ui.view">
- <field name="name">hr.employee.presence.form.inherit</field>
- <field name="model">hr.employee</field>
- <field name="inherit_id" ref="hr.view_employee_form"/>
- <field name="groups_id" eval="[(4, ref('hr.group_hr_manager'))]"/>
- <field name="arch" type="xml">
- <div name="button_box" position="inside">
- <field name="hr_presence_state" invisible="1"/>
- <button name="%(ir_actions_server_action_open_presence_view)d"
- class="oe_stat_button"
- type="action"
- attrs="{'invisible': ['|', ('hr_presence_state', '=', 'absent'), ('user_id', '=', False)]}">
- <div role="img" class="fa fa-fw fa-circle text-success o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'present')]}" aria-label="Available" title="Available"/>
- <div role="img" class="fa fa-fw fa-circle text-warning o_button_icon" attrs="{'invisible': [('hr_presence_state', '!=', 'to_define')]}" aria-label="Not available" title="Not available"/>
-
- <div class="o_stat_info" attrs="{'invisible': [('hr_presence_state', '!=', 'to_define')]}">
- <span class="o_stat_value">
- <field name="last_activity"/>
- </span>
- <span class="o_stat_text">
- Last Activity
- </span>
- </div>
- <div class="o_stat_info" attrs="{'invisible': [('hr_presence_state', '!=', 'present')]}">
- <span class="o_stat_text">Connected</span>
- </div>
- </button>
- </div>
- </field>
- </record>
-
<record id="hr_employee_view_kanban" model="ir.ui.view">
<field name="name">hr.employee.view.kanban</field>
<field name="model">hr.employee</field>
@@ -54,7 +23,7 @@
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<field name="hr_presence_state" invisible="1"/>
- <button name="action_set_present" type="object" class="btn btn-primary btn-sm mt8 fa fa-check" title="Set as present" attrs="{'invisible': [('hr_presence_state', '!=', 'to_define')]}"> </button>
+ <button name="action_set_present" type="object" class="btn btn-primary btn-sm mt8 fa fa-check" title="Set as present" attrs="{'invisible': [('hr_presence_state', '=', 'present')]}"> </button>
<button name="action_open_leave_request" type="object" class="btn btn-primary btn-sm mt8">Time Off</button>
<button name="action_send_sms" type="object" class="btn btn-primary btn-sm mt8">SMS</button>
<button name="action_send_mail" type="object" class="btn btn-primary btn-sm mt8">Mail</button>
@@ -64,31 +33,4 @@
</field>
</record>
- <record id="hr_employee_view_kanban_inherit" model="ir.ui.view">
- <field name="name">hr.employee</field>
- <field name="model">hr.employee</field>
- <field name="inherit_id" ref="hr.hr_kanban_view_employees"/>
- <field name="priority">1</field>
- <field name="arch" type="xml">
- <templates position="before">
- <field name="hr_presence_state"/>
- </templates>
- <field name="name" position="replace">
- <div>
- <div class="float-right" t-if="record.hr_presence_state.raw_value == 'present'">
- <span class="fa fa-circle text-success" role="img" aria-label="Present" title="Present" name="presence_present"></span>
- </div>
- <div class="float-right" t-if="record.hr_presence_state.raw_value == 'absent'">
- <span class="fa fa-circle text-danger" role="img" aria-label="Absent" title="Absent" name="presence_absent"></span>
- </div>
- <div class="float-right" t-if="record.hr_presence_state.raw_value == 'to_define'">
- <span class="fa fa-circle text-warning" role="img" aria-label="To define" title="To define" name="presence_to_define"></span>
- </div>
- <strong>
- <field name="name" placeholder="Employee's Name"/>
- </strong>
- </div>
- </field>
- </field>
- </record>
</odoo>
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 @@
-<?xml version="1.0" encoding="utf-8"?>
-<odoo>
- <record id="res_config_settings_view_form" model="ir.ui.view">
- <field name="name">res.config.settings.view.form.inherit.hr</field>
- <field name="model">res.config.settings</field>
- <field name="priority" eval="70"/>
- <field name="inherit_id" ref="hr.res_config_settings_view_form"/>
- <field name="arch" type="xml">
- <xpath expr="//div[@data-key='hr']//div[hasclass('o_settings_container')]" position="inside">
- <div class="col-12 col-lg-6 o_setting_box" title="Control presence of employees">
- <div class="o_setting_left_pane">
- <field name="module_hr_presence"/>
- </div>
- <div class="o_setting_right_pane">
- <label for="module_hr_presence"/>
- <div class="content-group" name="hr_presence_options">
- <div class="row">
- <field name="hr_presence_control_login" class="col-lg-1 ml16"/>
- <label for="hr_presence_control_login" class="col-lg-10 o_light_label"/>
- </div>
- <div class="row">
- <field name="hr_presence_control_email" class="col-lg-1 ml16"/>
- <label for="hr_presence_control_email" class="col-lg-10 o_light_label"/>
- </div>
- <div attrs="{'invisible': [('hr_presence_control_email', '=', False)]}">
- <span>At least </span>
- <field name="hr_presence_control_email_amount"/>
- <span> sent emails</span>
- </div>
- <div class="row">
- <field name="hr_presence_control_ip" class="col-lg-1 ml16"/>
- <label for="hr_presence_control_ip" class="col-lg-10 o_light_label"/>
- </div>
- <div attrs="{'invisible': [('hr_presence_control_ip', '=', False)]}">
- <span>IP List (comma separated):</span>
- <field name="hr_presence_control_ip_list"/>
- </div>
- </div>
- </div>
- </div>
- </xpath>
- </field>
- </record>
-</odoo>